From ffee1948daeaebc486ffc01dc030efbb1b266c8c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 19 Jan 2015 12:25:26 +0100 Subject: [PATCH 0001/1256] ShopConnector: Improved xml product data export --- .../Extensions/ConversionExtensions.cs | 20 + .../ExportImport/ExportManager.cs | 637 ++++++++++-------- .../ExportImport/IExportManager.cs | 21 +- .../ExportImport/ExportManagerTests.cs | 5 +- 4 files changed, 387 insertions(+), 296 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs index 2ee0fe32fc..20ff82f9a2 100644 --- a/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs @@ -432,6 +432,26 @@ public static bool ToBool(this string value, bool defaultValue = false) return defaultValue; } + /// + /// Parse ISO-8601 UTC timestamp including milliseconds. + /// + /// + /// Dublicate can be found in HmacAuthentication class. + /// + public static DateTime? ToDateTimeIso8601(this string value) + { + if (value.HasValue()) + { + DateTime dt; + if (DateTime.TryParseExact(value, "o", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out dt)) + return dt; + + if (DateTime.TryParseExact(value, "yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out dt)) + return dt; + } + return null; + } + public static Guid ToGuid(this string value) { if ((!String.IsNullOrEmpty(value)) && (value.Trim().Length == 22)) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 823a4cc0bb..b8aef5b1d8 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -10,7 +11,9 @@ using SmartStore.Core; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Logging; using SmartStore.Services.Catalog; using SmartStore.Services.Common; using SmartStore.Services.Customers; @@ -34,6 +37,7 @@ public partial class ExportManager : IExportManager private readonly IPictureService _pictureService; private readonly INewsLetterSubscriptionService _newsLetterSubscriptionService; private readonly ILanguageService _languageService; + private readonly MediaSettings _mediaSettings; #endregion @@ -44,7 +48,8 @@ public ExportManager(ICategoryService categoryService, IProductService productService, IPictureService pictureService, INewsLetterSubscriptionService newsLetterSubscriptionService, - ILanguageService languageService) + ILanguageService languageService, + MediaSettings mediaSettings) { this._categoryService = categoryService; this._manufacturerService = manufacturerService; @@ -52,8 +57,13 @@ public ExportManager(ICategoryService categoryService, this._pictureService = pictureService; this._newsLetterSubscriptionService = newsLetterSubscriptionService; this._languageService = languageService; + this._mediaSettings = mediaSettings; + + Logger = NullLogger.Instance; } + public ILogger Logger { get; set; } + #endregion #region Utilities @@ -203,313 +213,354 @@ public virtual string ExportCategoriesToXml() return stringWriter.ToString(); } + /// + /// Writes a single product + /// + /// The XML text writer + /// The product + /// Used culture + public virtual void WriteProductToXml(XmlTextWriter writer, Product product, CultureInfo culture = null) + { + if (culture == null) + culture = CultureInfo.InvariantCulture; + + writer.WriteElementString("ProductId", null, product.Id.ToString()); + writer.WriteElementString("ProductTypeId", null, product.ProductTypeId.ToString()); + writer.WriteElementString("ParentGroupedProductId", null, product.ParentGroupedProductId.ToString()); + writer.WriteElementString("VisibleIndividually", null, product.VisibleIndividually.ToString()); + writer.WriteElementString("Name", null, product.Name.RemoveInvalidXmlChars()); + + writer.WriteStartElement("ShortDescription"); + writer.WriteCData(product.ShortDescription.RemoveInvalidXmlChars()); + writer.WriteEndElement(); + + writer.WriteStartElement("FullDescription"); + writer.WriteCData(product.FullDescription.RemoveInvalidXmlChars()); + writer.WriteEndElement(); + + writer.WriteElementString("AdminComment", null, product.AdminComment.RemoveInvalidXmlChars()); + writer.WriteElementString("ProductTemplateId", null, product.ProductTemplateId.ToString()); + writer.WriteElementString("ShowOnHomePage", null, product.ShowOnHomePage.ToString()); + writer.WriteElementString("MetaKeywords", null, product.MetaKeywords.RemoveInvalidXmlChars()); + writer.WriteElementString("MetaDescription", null, product.MetaDescription.RemoveInvalidXmlChars()); + writer.WriteElementString("MetaTitle", null, product.MetaTitle.RemoveInvalidXmlChars()); + writer.WriteElementString("SEName", null, product.GetSeName(0)); + writer.WriteElementString("AllowCustomerReviews", null, product.AllowCustomerReviews.ToString()); + writer.WriteElementString("SKU", null, product.Sku); + writer.WriteElementString("ManufacturerPartNumber", null, product.ManufacturerPartNumber); + writer.WriteElementString("Gtin", null, product.Gtin); + writer.WriteElementString("IsGiftCard", null, product.IsGiftCard.ToString()); + writer.WriteElementString("GiftCardType", null, product.GiftCardType.ToString()); + writer.WriteElementString("RequireOtherProducts", null, product.RequireOtherProducts.ToString()); + writer.WriteElementString("RequiredProductIds", null, product.RequiredProductIds); + writer.WriteElementString("AutomaticallyAddRequiredProducts", null, product.AutomaticallyAddRequiredProducts.ToString()); + writer.WriteElementString("IsDownload", null, product.IsDownload.ToString()); + writer.WriteElementString("DownloadId", null, product.DownloadId.ToString()); + writer.WriteElementString("UnlimitedDownloads", null, product.UnlimitedDownloads.ToString()); + writer.WriteElementString("MaxNumberOfDownloads", null, product.MaxNumberOfDownloads.ToString()); + writer.WriteElementString("DownloadExpirationDays", null, product.DownloadExpirationDays.HasValue ? product.DownloadExpirationDays.ToString() : ""); + writer.WriteElementString("DownloadActivationType", null, product.DownloadActivationType.ToString()); + writer.WriteElementString("HasSampleDownload", null, product.HasSampleDownload.ToString()); + writer.WriteElementString("SampleDownloadId", null, product.SampleDownloadId.ToString()); + writer.WriteElementString("HasUserAgreement", null, product.HasUserAgreement.ToString()); + writer.WriteElementString("UserAgreementText", null, product.UserAgreementText.RemoveInvalidXmlChars()); + writer.WriteElementString("IsRecurring", null, product.IsRecurring.ToString()); + writer.WriteElementString("RecurringCycleLength", null, product.RecurringCycleLength.ToString()); + writer.WriteElementString("RecurringCyclePeriodId", null, product.RecurringCyclePeriodId.ToString()); + writer.WriteElementString("RecurringTotalCycles", null, product.RecurringTotalCycles.ToString()); + writer.WriteElementString("IsShipEnabled", null, product.IsShipEnabled.ToString()); + writer.WriteElementString("IsFreeShipping", null, product.IsFreeShipping.ToString()); + writer.WriteElementString("AdditionalShippingCharge", null, product.AdditionalShippingCharge.ToString(culture)); + writer.WriteElementString("IsEsd", null, product.IsEsd.ToString()); + writer.WriteElementString("IsTaxExempt", null, product.IsTaxExempt.ToString()); + writer.WriteElementString("TaxCategoryId", null, product.TaxCategoryId.ToString()); + writer.WriteElementString("ManageInventoryMethodId", null, product.ManageInventoryMethodId.ToString()); + writer.WriteElementString("StockQuantity", null, product.StockQuantity.ToString()); + writer.WriteElementString("DisplayStockAvailability", null, product.DisplayStockAvailability.ToString()); + writer.WriteElementString("DisplayStockQuantity", null, product.DisplayStockQuantity.ToString()); + writer.WriteElementString("MinStockQuantity", null, product.MinStockQuantity.ToString()); + writer.WriteElementString("LowStockActivityId", null, product.LowStockActivityId.ToString()); + writer.WriteElementString("NotifyAdminForQuantityBelow", null, product.NotifyAdminForQuantityBelow.ToString()); + writer.WriteElementString("BackorderModeId", null, product.BackorderModeId.ToString()); + writer.WriteElementString("AllowBackInStockSubscriptions", null, product.AllowBackInStockSubscriptions.ToString()); + writer.WriteElementString("OrderMinimumQuantity", null, product.OrderMinimumQuantity.ToString()); + writer.WriteElementString("OrderMaximumQuantity", null, product.OrderMaximumQuantity.ToString()); + writer.WriteElementString("AllowedQuantities", null, product.AllowedQuantities); + writer.WriteElementString("DisableBuyButton", null, product.DisableBuyButton.ToString()); + writer.WriteElementString("DisableWishlistButton", null, product.DisableWishlistButton.ToString()); + writer.WriteElementString("AvailableForPreOrder", null, product.AvailableForPreOrder.ToString()); + writer.WriteElementString("CallForPrice", null, product.CallForPrice.ToString()); + writer.WriteElementString("Price", null, product.Price.ToString(culture)); + writer.WriteElementString("OldPrice", null, product.OldPrice.ToString(culture)); + writer.WriteElementString("ProductCost", null, product.ProductCost.ToString(culture)); + writer.WriteElementString("SpecialPrice", null, product.SpecialPrice.HasValue ? product.SpecialPrice.Value.ToString(culture) : ""); + writer.WriteElementString("SpecialPriceStartDateTimeUtc", null, product.SpecialPriceStartDateTimeUtc.HasValue ? product.SpecialPriceStartDateTimeUtc.Value.ToString(culture) : ""); + writer.WriteElementString("SpecialPriceEndDateTimeUtc", null, product.SpecialPriceEndDateTimeUtc.HasValue ? product.SpecialPriceEndDateTimeUtc.Value.ToString(culture) : ""); + writer.WriteElementString("CustomerEntersPrice", null, product.CustomerEntersPrice.ToString()); + writer.WriteElementString("MinimumCustomerEnteredPrice", null, product.MinimumCustomerEnteredPrice.ToString(culture)); + writer.WriteElementString("MaximumCustomerEnteredPrice", null, product.MaximumCustomerEnteredPrice.ToString(culture)); + writer.WriteElementString("LowestAttributeCombinationPrice", null, product.LowestAttributeCombinationPrice.HasValue ? product.LowestAttributeCombinationPrice.Value.ToString(culture) : ""); + writer.WriteElementString("Weight", null, product.Weight.ToString(culture)); + writer.WriteElementString("Length", null, product.Length.ToString(culture)); + writer.WriteElementString("Width", null, product.Width.ToString(culture)); + writer.WriteElementString("Height", null, product.Height.ToString(culture)); + writer.WriteElementString("Published", null, product.Published.ToString()); + writer.WriteElementString("CreatedOnUtc", null, product.CreatedOnUtc.ToString(culture)); + writer.WriteElementString("UpdatedOnUtc", null, product.UpdatedOnUtc.ToString(culture)); + + if (product.DeliveryTimeId.HasValue) + writer.WriteElementString("DeliveryTimeId", null, product.DeliveryTimeId.Value.ToString()); + + writer.WriteElementString("BasePriceEnabled", null, product.BasePriceEnabled.ToString()); + writer.WriteElementString("BasePriceMeasureUnit", null, product.BasePriceMeasureUnit); + + if (product.BasePriceAmount.HasValue) + writer.WriteElementString("BasePriceAmount", null, product.BasePriceAmount.Value.ToString(culture)); + + if (product.BasePriceBaseAmount.HasValue) + writer.WriteElementString("BasePriceBaseAmount", null, product.BasePriceBaseAmount.Value.ToString()); + + writer.WriteElementString("BundleTitleText", null, product.BundleTitleText.RemoveInvalidXmlChars()); + writer.WriteElementString("BundlePerItemShipping", null, product.BundlePerItemShipping.ToString()); + writer.WriteElementString("BundlePerItemPricing", null, product.BundlePerItemPricing.ToString()); + writer.WriteElementString("BundlePerItemShoppingCart", null, product.BundlePerItemShoppingCart.ToString()); + + writer.WriteStartElement("ProductDiscounts"); + foreach (var discount in product.AppliedDiscounts) + { + writer.WriteStartElement("ProductDiscount"); + writer.WriteElementString("DiscountId", null, discount.Id.ToString()); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.WriteStartElement("TierPrices"); + foreach (var tierPrice in product.TierPrices) + { + writer.WriteStartElement("TierPrice"); + writer.WriteElementString("TierPriceId", null, tierPrice.Id.ToString()); + writer.WriteElementString("StoreId", null, tierPrice.StoreId.ToString()); + writer.WriteElementString("CustomerRoleId", null, tierPrice.CustomerRoleId.HasValue ? tierPrice.CustomerRoleId.ToString() : "0"); + writer.WriteElementString("Quantity", null, tierPrice.Quantity.ToString()); + writer.WriteElementString("Price", null, tierPrice.Price.ToString(culture)); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.WriteStartElement("ProductAttributes"); + foreach (var attribute in product.ProductVariantAttributes) + { + writer.WriteStartElement("ProductVariantAttribute"); + writer.WriteElementString("ProductVariantAttributeId", null, attribute.Id.ToString()); + writer.WriteElementString("ProductAttributeId", null, attribute.ProductAttributeId.ToString()); + writer.WriteElementString("TextPrompt", null, attribute.TextPrompt.RemoveInvalidXmlChars()); + writer.WriteElementString("IsRequired", null, attribute.IsRequired.ToString()); + writer.WriteElementString("AttributeControlTypeId", null, attribute.AttributeControlTypeId.ToString()); + writer.WriteElementString("DisplayOrder", null, attribute.DisplayOrder.ToString()); + writer.WriteStartElement("ProductVariantAttributeValues"); + + foreach (var attributeValue in attribute.ProductVariantAttributeValues) + { + writer.WriteStartElement("ProductVariantAttributeValue"); + writer.WriteElementString("ProductVariantAttributeValueId", null, attributeValue.Id.ToString()); + writer.WriteElementString("Name", null, attributeValue.Name.RemoveInvalidXmlChars()); + writer.WriteElementString("PriceAdjustment", null, attributeValue.PriceAdjustment.ToString(culture)); + writer.WriteElementString("WeightAdjustment", null, attributeValue.WeightAdjustment.ToString(culture)); + writer.WriteElementString("IsPreSelected", null, attributeValue.IsPreSelected.ToString()); + writer.WriteElementString("DisplayOrder", null, attributeValue.DisplayOrder.ToString()); + writer.WriteElementString("ValueTypeId", null, attributeValue.ValueTypeId.ToString()); + writer.WriteElementString("LinkedProductId", null, attributeValue.LinkedProductId.ToString()); + writer.WriteElementString("Quantity", null, attributeValue.Quantity.ToString()); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.WriteEndElement(); + } + writer.WriteEndElement(); // ProductAttributes + + writer.WriteStartElement("ProductVariantAttributeCombinations"); + foreach (var combination in product.ProductVariantAttributeCombinations) + { + writer.WriteStartElement("ProductVariantAttributeCombination"); + + writer.WriteElementString("ProductVariantAttributeCombinationId", null, combination.Id.ToString()); + writer.WriteElementString("AllowOutOfStockOrders", null, combination.AllowOutOfStockOrders.ToString()); + writer.WriteElementString("StockQuantity", null, combination.StockQuantity.ToString()); + writer.WriteElementString("AssignedPictureIds", null, combination.AssignedPictureIds); + + writer.WriteStartElement("AttributesXml"); + writer.WriteCData(combination.AttributesXml); + writer.WriteEndElement(); // AttributesXml + + writer.WriteElementString("IsActive", null, combination.IsActive.ToString()); + //xmlWriter.WriteElementString("IsDefaultCombination", null, combination.IsDefaultCombination.ToString()); + if (combination.BasePriceAmount.HasValue) + writer.WriteElementString("BasePriceAmount", null, combination.BasePriceAmount.Value.ToString(culture)); + if (combination.BasePriceBaseAmount.HasValue) + writer.WriteElementString("BasePriceBaseAmount", null, combination.BasePriceBaseAmount.Value.ToString()); + if (combination.DeliveryTimeId.HasValue) + writer.WriteElementString("DeliveryTimeId", null, combination.DeliveryTimeId.Value.ToString()); + if (combination.Length.HasValue) + writer.WriteElementString("Length", null, combination.Length.Value.ToString(culture)); + if (combination.Width.HasValue) + writer.WriteElementString("Width", null, combination.Width.Value.ToString(culture)); + if (combination.Height.HasValue) + writer.WriteElementString("Height", null, combination.Height.Value.ToString(culture)); + if (combination.Height.HasValue) + writer.WriteElementString("Height", null, combination.Height.Value.ToString(culture)); + if (combination.Gtin.HasValue()) + writer.WriteElementString("Gtin", null, combination.Gtin); + if (combination.Sku.HasValue()) + writer.WriteElementString("Sku", null, combination.Sku); + if (combination.ManufacturerPartNumber.HasValue()) + writer.WriteElementString("ManufacturerPartNumber", null, combination.ManufacturerPartNumber); + if (combination.Price.HasValue) + writer.WriteElementString("Price", null, combination.Price.Value.ToString(culture)); + + writer.WriteEndElement(); // ProductVariantAttributeCombination + } + writer.WriteEndElement(); // ProductVariantAttributeCombinations + + writer.WriteStartElement("ProductPictures"); + foreach (var productPicture in product.ProductPictures) + { + writer.WriteStartElement("ProductPicture"); + writer.WriteElementString("ProductPictureId", null, productPicture.Id.ToString()); + writer.WriteElementString("PictureId", null, productPicture.PictureId.ToString()); + writer.WriteElementString("DisplayOrder", null, productPicture.DisplayOrder.ToString()); + writer.WriteElementString("ThumbImageUrl", null, _pictureService.GetPictureUrl(productPicture.Picture, _mediaSettings.ProductThumbPictureSize, false)); + writer.WriteElementString("ImageUrl", null, _pictureService.GetPictureUrl(productPicture.Picture, _mediaSettings.ProductDetailsPictureSize, false)); + writer.WriteElementString("FullSizeImageUrl", null, _pictureService.GetPictureUrl(productPicture.Picture, 0, false)); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.WriteStartElement("ProductCategories"); + var productCategories = _categoryService.GetProductCategoriesByProductId(product.Id); + if (productCategories != null) + { + foreach (var productCategory in productCategories) + { + writer.WriteStartElement("ProductCategory"); + writer.WriteElementString("ProductCategoryId", null, productCategory.Id.ToString()); + writer.WriteElementString("CategoryId", null, productCategory.CategoryId.ToString()); + writer.WriteElementString("IsFeaturedProduct", null, productCategory.IsFeaturedProduct.ToString()); + writer.WriteElementString("DisplayOrder", null, productCategory.DisplayOrder.ToString()); + writer.WriteEndElement(); + } + } + writer.WriteEndElement(); + + writer.WriteStartElement("ProductManufacturers"); + var productManufacturers = _manufacturerService.GetProductManufacturersByProductId(product.Id); + if (productManufacturers != null) + { + foreach (var productManufacturer in productManufacturers) + { + writer.WriteStartElement("ProductManufacturer"); + writer.WriteElementString("ProductManufacturerId", null, productManufacturer.Id.ToString()); + writer.WriteElementString("ManufacturerId", null, productManufacturer.ManufacturerId.ToString()); + writer.WriteElementString("IsFeaturedProduct", null, productManufacturer.IsFeaturedProduct.ToString()); + writer.WriteElementString("DisplayOrder", null, productManufacturer.DisplayOrder.ToString()); + writer.WriteEndElement(); + } + } + writer.WriteEndElement(); + + writer.WriteStartElement("ProductSpecificationAttributes"); + foreach (var productSpecificationAttribute in product.ProductSpecificationAttributes) + { + writer.WriteStartElement("ProductSpecificationAttribute"); + writer.WriteElementString("ProductSpecificationAttributeId", null, productSpecificationAttribute.Id.ToString()); + writer.WriteElementString("SpecificationAttributeOptionId", null, productSpecificationAttribute.SpecificationAttributeOptionId.ToString()); + writer.WriteElementString("AllowFiltering", null, productSpecificationAttribute.AllowFiltering.ToString()); + writer.WriteElementString("ShowOnProductPage", null, productSpecificationAttribute.ShowOnProductPage.ToString()); + writer.WriteElementString("DisplayOrder", null, productSpecificationAttribute.DisplayOrder.ToString()); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.WriteStartElement("ProductBundleItems"); + var bundleItems = _productService.GetBundleItems(product.Id, true); + foreach (var bundleItem in bundleItems.Select(x => x.Item)) + { + writer.WriteStartElement("ProductBundleItem"); + + writer.WriteElementString("ProductId", null, bundleItem.ProductId.ToString()); + writer.WriteElementString("BundleProductId", null, bundleItem.BundleProductId.ToString()); + writer.WriteElementString("Quantity", null, bundleItem.Quantity.ToString()); + if (bundleItem.Discount.HasValue) + writer.WriteElementString("Discount", null, bundleItem.Discount.Value.ToString(culture)); + writer.WriteElementString("DiscountPercentage", null, bundleItem.DiscountPercentage.ToString()); + writer.WriteElementString("Name", null, bundleItem.GetLocalizedName()); + writer.WriteElementString("ShortDescription", null, bundleItem.ShortDescription.RemoveInvalidXmlChars()); + writer.WriteElementString("FilterAttributes", null, bundleItem.FilterAttributes.ToString()); + writer.WriteElementString("HideThumbnail", null, bundleItem.HideThumbnail.ToString()); + writer.WriteElementString("Visible", null, bundleItem.Visible.ToString()); + writer.WriteElementString("Published", null, bundleItem.Published.ToString()); + writer.WriteElementString("DisplayOrder", null, bundleItem.DisplayOrder.ToString()); + writer.WriteElementString("CreatedOnUtc", null, bundleItem.CreatedOnUtc.ToString(culture)); + writer.WriteElementString("UpdatedOnUtc", null, bundleItem.UpdatedOnUtc.ToString(culture)); + + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + /// - /// Export product list to xml + /// Export product list to XML /// /// Products /// Result in XML format public virtual string ExportProductsToXml(IList products) { - var sb = new StringBuilder(); - var stringWriter = new StringWriter(sb); - var xmlWriter = new XmlTextWriter(stringWriter); - xmlWriter.WriteStartDocument(); - xmlWriter.WriteStartElement("Products"); - xmlWriter.WriteAttributeString("Version", SmartStoreVersion.CurrentVersion); - - foreach (var product in products) - { - xmlWriter.WriteStartElement("Product"); - - xmlWriter.WriteElementString("ProductId", null, product.Id.ToString()); - xmlWriter.WriteElementString("ProductTypeId", null, product.ProductTypeId.ToString()); - xmlWriter.WriteElementString("ParentGroupedProductId", null, product.ParentGroupedProductId.ToString()); - xmlWriter.WriteElementString("VisibleIndividually", null, product.VisibleIndividually.ToString()); - xmlWriter.WriteElementString("Name", null, product.Name); - xmlWriter.WriteElementString("ShortDescription", null, product.ShortDescription); - xmlWriter.WriteElementString("FullDescription", null, product.FullDescription.RemoveInvalidXmlChars()); - xmlWriter.WriteElementString("AdminComment", null, product.AdminComment); - xmlWriter.WriteElementString("ProductTemplateId", null, product.ProductTemplateId.ToString()); - xmlWriter.WriteElementString("ShowOnHomePage", null, product.ShowOnHomePage.ToString()); - xmlWriter.WriteElementString("MetaKeywords", null, product.MetaKeywords); - xmlWriter.WriteElementString("MetaDescription", null, product.MetaDescription); - xmlWriter.WriteElementString("MetaTitle", null, product.MetaTitle); - xmlWriter.WriteElementString("SEName", null, product.GetSeName(0)); - xmlWriter.WriteElementString("AllowCustomerReviews", null, product.AllowCustomerReviews.ToString()); - xmlWriter.WriteElementString("SKU", null, product.Sku); - xmlWriter.WriteElementString("ManufacturerPartNumber", null, product.ManufacturerPartNumber); - xmlWriter.WriteElementString("Gtin", null, product.Gtin); - xmlWriter.WriteElementString("IsGiftCard", null, product.IsGiftCard.ToString()); - xmlWriter.WriteElementString("GiftCardType", null, product.GiftCardType.ToString()); - xmlWriter.WriteElementString("RequireOtherProducts", null, product.RequireOtherProducts.ToString()); - xmlWriter.WriteElementString("RequiredProductIds", null, product.RequiredProductIds); - xmlWriter.WriteElementString("AutomaticallyAddRequiredProducts", null, product.AutomaticallyAddRequiredProducts.ToString()); - xmlWriter.WriteElementString("IsDownload", null, product.IsDownload.ToString()); - xmlWriter.WriteElementString("DownloadId", null, product.DownloadId.ToString()); - xmlWriter.WriteElementString("UnlimitedDownloads", null, product.UnlimitedDownloads.ToString()); - xmlWriter.WriteElementString("MaxNumberOfDownloads", null, product.MaxNumberOfDownloads.ToString()); - if (product.DownloadExpirationDays.HasValue) - xmlWriter.WriteElementString("DownloadExpirationDays", null, product.DownloadExpirationDays.ToString()); - else - xmlWriter.WriteElementString("DownloadExpirationDays", null, string.Empty); - xmlWriter.WriteElementString("DownloadActivationType", null, product.DownloadActivationType.ToString()); - xmlWriter.WriteElementString("HasSampleDownload", null, product.HasSampleDownload.ToString()); - xmlWriter.WriteElementString("SampleDownloadId", null, product.SampleDownloadId.ToString()); - xmlWriter.WriteElementString("HasUserAgreement", null, product.HasUserAgreement.ToString()); - xmlWriter.WriteElementString("UserAgreementText", null, product.UserAgreementText); - xmlWriter.WriteElementString("IsRecurring", null, product.IsRecurring.ToString()); - xmlWriter.WriteElementString("RecurringCycleLength", null, product.RecurringCycleLength.ToString()); - xmlWriter.WriteElementString("RecurringCyclePeriodId", null, product.RecurringCyclePeriodId.ToString()); - xmlWriter.WriteElementString("RecurringTotalCycles", null, product.RecurringTotalCycles.ToString()); - xmlWriter.WriteElementString("IsShipEnabled", null, product.IsShipEnabled.ToString()); - xmlWriter.WriteElementString("IsFreeShipping", null, product.IsFreeShipping.ToString()); - xmlWriter.WriteElementString("AdditionalShippingCharge", null, product.AdditionalShippingCharge.ToString()); - xmlWriter.WriteElementString("IsEsd", null, product.IsEsd.ToString()); - xmlWriter.WriteElementString("IsTaxExempt", null, product.IsTaxExempt.ToString()); - xmlWriter.WriteElementString("TaxCategoryId", null, product.TaxCategoryId.ToString()); - xmlWriter.WriteElementString("ManageInventoryMethodId", null, product.ManageInventoryMethodId.ToString()); - xmlWriter.WriteElementString("StockQuantity", null, product.StockQuantity.ToString()); - xmlWriter.WriteElementString("DisplayStockAvailability", null, product.DisplayStockAvailability.ToString()); - xmlWriter.WriteElementString("DisplayStockQuantity", null, product.DisplayStockQuantity.ToString()); - xmlWriter.WriteElementString("MinStockQuantity", null, product.MinStockQuantity.ToString()); - xmlWriter.WriteElementString("LowStockActivityId", null, product.LowStockActivityId.ToString()); - xmlWriter.WriteElementString("NotifyAdminForQuantityBelow", null, product.NotifyAdminForQuantityBelow.ToString()); - xmlWriter.WriteElementString("BackorderModeId", null, product.BackorderModeId.ToString()); - xmlWriter.WriteElementString("AllowBackInStockSubscriptions", null, product.AllowBackInStockSubscriptions.ToString()); - xmlWriter.WriteElementString("OrderMinimumQuantity", null, product.OrderMinimumQuantity.ToString()); - xmlWriter.WriteElementString("OrderMaximumQuantity", null, product.OrderMaximumQuantity.ToString()); - xmlWriter.WriteElementString("AllowedQuantities", null, product.AllowedQuantities); - xmlWriter.WriteElementString("DisableBuyButton", null, product.DisableBuyButton.ToString()); - xmlWriter.WriteElementString("DisableWishlistButton", null, product.DisableWishlistButton.ToString()); - xmlWriter.WriteElementString("AvailableForPreOrder", null, product.AvailableForPreOrder.ToString()); - xmlWriter.WriteElementString("CallForPrice", null, product.CallForPrice.ToString()); - xmlWriter.WriteElementString("Price", null, product.Price.ToString()); - xmlWriter.WriteElementString("OldPrice", null, product.OldPrice.ToString()); - xmlWriter.WriteElementString("ProductCost", null, product.ProductCost.ToString()); - xmlWriter.WriteElementString("SpecialPrice", null, product.SpecialPrice.HasValue ? product.SpecialPrice.ToString() : ""); - xmlWriter.WriteElementString("SpecialPriceStartDateTimeUtc", null, product.SpecialPriceStartDateTimeUtc.HasValue ? product.SpecialPriceStartDateTimeUtc.ToString() : ""); - xmlWriter.WriteElementString("SpecialPriceEndDateTimeUtc", null, product.SpecialPriceEndDateTimeUtc.HasValue ? product.SpecialPriceEndDateTimeUtc.ToString() : ""); - xmlWriter.WriteElementString("CustomerEntersPrice", null, product.CustomerEntersPrice.ToString()); - xmlWriter.WriteElementString("MinimumCustomerEnteredPrice", null, product.MinimumCustomerEnteredPrice.ToString()); - xmlWriter.WriteElementString("MaximumCustomerEnteredPrice", null, product.MaximumCustomerEnteredPrice.ToString()); - xmlWriter.WriteElementString("LowestAttributeCombinationPrice", null, product.LowestAttributeCombinationPrice.HasValue ? product.LowestAttributeCombinationPrice.ToString() : ""); - xmlWriter.WriteElementString("Weight", null, product.Weight.ToString()); - xmlWriter.WriteElementString("Length", null, product.Length.ToString()); - xmlWriter.WriteElementString("Width", null, product.Width.ToString()); - xmlWriter.WriteElementString("Height", null, product.Height.ToString()); - xmlWriter.WriteElementString("Published", null, product.Published.ToString()); - xmlWriter.WriteElementString("CreatedOnUtc", null, product.CreatedOnUtc.ToString()); - xmlWriter.WriteElementString("UpdatedOnUtc", null, product.UpdatedOnUtc.ToString()); - - if (product.DeliveryTimeId.HasValue) - xmlWriter.WriteElementString("DeliveryTimeId", null, product.DeliveryTimeId.Value.ToString()); - xmlWriter.WriteElementString("BasePriceEnabled", null, product.BasePriceEnabled.ToString()); - xmlWriter.WriteElementString("BasePriceMeasureUnit", null, product.BasePriceMeasureUnit); - if (product.BasePriceAmount.HasValue) - xmlWriter.WriteElementString("BasePriceAmount", null, product.BasePriceAmount.Value.ToString()); - if (product.BasePriceBaseAmount.HasValue) - xmlWriter.WriteElementString("BasePriceBaseAmount", null, product.BasePriceBaseAmount.Value.ToString()); - - xmlWriter.WriteElementString("BundleTitleText", null, product.BundleTitleText); - xmlWriter.WriteElementString("BundlePerItemShipping", null, product.BundlePerItemShipping.ToString()); - xmlWriter.WriteElementString("BundlePerItemPricing", null, product.BundlePerItemPricing.ToString()); - xmlWriter.WriteElementString("BundlePerItemShoppingCart", null, product.BundlePerItemShoppingCart.ToString()); - - xmlWriter.WriteStartElement("ProductDiscounts"); - var discounts = product.AppliedDiscounts; - foreach (var discount in discounts) - { - xmlWriter.WriteStartElement("ProductDiscount"); - xmlWriter.WriteElementString("DiscountId", null, discount.Id.ToString()); - xmlWriter.WriteEndElement(); - } - xmlWriter.WriteEndElement(); - - - xmlWriter.WriteStartElement("TierPrices"); - var tierPrices = product.TierPrices; - foreach (var tierPrice in tierPrices) + string result = ExportProductsToXml(writer => + { + foreach (var product in products) { - xmlWriter.WriteStartElement("TierPrice"); - xmlWriter.WriteElementString("TierPriceId", null, tierPrice.Id.ToString()); - xmlWriter.WriteElementString("StoreId", null, tierPrice.StoreId.ToString()); - xmlWriter.WriteElementString("CustomerRoleId", null, tierPrice.CustomerRoleId.HasValue ? tierPrice.CustomerRoleId.ToString() : "0"); - xmlWriter.WriteElementString("Quantity", null, tierPrice.Quantity.ToString()); - xmlWriter.WriteElementString("Price", null, tierPrice.Price.ToString()); - xmlWriter.WriteEndElement(); - } - xmlWriter.WriteEndElement(); + writer.WriteStartElement("Product"); - xmlWriter.WriteStartElement("ProductAttributes"); - var productVariantAttributes = product.ProductVariantAttributes; - foreach (var productVariantAttribute in productVariantAttributes) - { - xmlWriter.WriteStartElement("ProductVariantAttribute"); - xmlWriter.WriteElementString("ProductVariantAttributeId", null, productVariantAttribute.Id.ToString()); - xmlWriter.WriteElementString("ProductAttributeId", null, productVariantAttribute.ProductAttributeId.ToString()); - xmlWriter.WriteElementString("TextPrompt", null, productVariantAttribute.TextPrompt); - xmlWriter.WriteElementString("IsRequired", null, productVariantAttribute.IsRequired.ToString()); - xmlWriter.WriteElementString("AttributeControlTypeId", null, productVariantAttribute.AttributeControlTypeId.ToString()); - xmlWriter.WriteElementString("DisplayOrder", null, productVariantAttribute.DisplayOrder.ToString()); - - xmlWriter.WriteStartElement("ProductVariantAttributeValues"); - var productVariantAttributeValues = productVariantAttribute.ProductVariantAttributeValues; - foreach (var productVariantAttributeValue in productVariantAttributeValues) + try { - xmlWriter.WriteStartElement("ProductVariantAttributeValue"); - xmlWriter.WriteElementString("ProductVariantAttributeValueId", null, productVariantAttributeValue.Id.ToString()); - xmlWriter.WriteElementString("Name", null, productVariantAttributeValue.Name); - xmlWriter.WriteElementString("PriceAdjustment", null, productVariantAttributeValue.PriceAdjustment.ToString()); - xmlWriter.WriteElementString("WeightAdjustment", null, productVariantAttributeValue.WeightAdjustment.ToString()); - xmlWriter.WriteElementString("IsPreSelected", null, productVariantAttributeValue.IsPreSelected.ToString()); - xmlWriter.WriteElementString("DisplayOrder", null, productVariantAttributeValue.DisplayOrder.ToString()); - xmlWriter.WriteElementString("ValueTypeId", null, productVariantAttributeValue.ValueTypeId.ToString()); - xmlWriter.WriteElementString("LinkedProductId", null, productVariantAttributeValue.LinkedProductId.ToString()); - xmlWriter.WriteElementString("Quantity", null, productVariantAttributeValue.Quantity.ToString()); - xmlWriter.WriteEndElement(); + WriteProductToXml(writer, product); + } + catch (Exception exc) + { + Logger.Error("{0} (Product.Id {1})".FormatWith(exc.Message, product.Id), exc); } - xmlWriter.WriteEndElement(); - - xmlWriter.WriteEndElement(); - } - xmlWriter.WriteEndElement(); // ProductAttributes - - xmlWriter.WriteStartElement("ProductVariantAttributeCombinations"); - var combinations = product.ProductVariantAttributeCombinations; - foreach (var combination in combinations) - { - xmlWriter.WriteStartElement("ProductVariantAttributeCombination"); - xmlWriter.WriteElementString("ProductVariantAttributeCombinationId", null, combination.Id.ToString()); - xmlWriter.WriteElementString("AllowOutOfStockOrders", null, combination.AllowOutOfStockOrders.ToString()); - xmlWriter.WriteElementString("StockQuantity", null, combination.StockQuantity.ToString()); - xmlWriter.WriteElementString("AssignedPictureIds", null, combination.AssignedPictureIds); - xmlWriter.WriteStartElement("AttributesXml"); - xmlWriter.WriteCData(combination.AttributesXml); - xmlWriter.WriteEndElement(); // AttributesXml - xmlWriter.WriteElementString("IsActive", null, combination.IsActive.ToString()); - //xmlWriter.WriteElementString("IsDefaultCombination", null, combination.IsDefaultCombination.ToString()); - if (combination.BasePriceAmount.HasValue) - xmlWriter.WriteElementString("BasePriceAmount", null, combination.BasePriceAmount.Value.ToString()); - if (combination.BasePriceBaseAmount.HasValue) - xmlWriter.WriteElementString("BasePriceBaseAmount", null, combination.BasePriceBaseAmount.Value.ToString()); - if (combination.DeliveryTimeId.HasValue) - xmlWriter.WriteElementString("DeliveryTimeId", null, combination.DeliveryTimeId.Value.ToString()); - if (combination.Length.HasValue) - xmlWriter.WriteElementString("Length", null, combination.Length.Value.ToString()); - if (combination.Width.HasValue) - xmlWriter.WriteElementString("Width", null, combination.Width.Value.ToString()); - if (combination.Height.HasValue) - xmlWriter.WriteElementString("Height", null, combination.Height.Value.ToString()); - if (combination.Height.HasValue) - xmlWriter.WriteElementString("Height", null, combination.Height.Value.ToString()); - if (combination.Gtin.HasValue()) - xmlWriter.WriteElementString("Gtin", null, combination.Gtin); - if (combination.Sku.HasValue()) - xmlWriter.WriteElementString("Sku", null, combination.Sku); - if (combination.ManufacturerPartNumber.HasValue()) - xmlWriter.WriteElementString("ManufacturerPartNumber", null, combination.ManufacturerPartNumber); - if (combination.Price.HasValue) - xmlWriter.WriteElementString("Price", null, combination.Price.Value.ToString()); - - xmlWriter.WriteEndElement(); // ProductVariantAttributeCombination - } - xmlWriter.WriteEndElement(); // ProductVariantAttributeCombinations - - xmlWriter.WriteStartElement("ProductPictures"); - var productPictures = product.ProductPictures; - foreach (var productPicture in productPictures) - { - xmlWriter.WriteStartElement("ProductPicture"); - xmlWriter.WriteElementString("ProductPictureId", null, productPicture.Id.ToString()); - xmlWriter.WriteElementString("PictureId", null, productPicture.PictureId.ToString()); - xmlWriter.WriteElementString("DisplayOrder", null, productPicture.DisplayOrder.ToString()); - xmlWriter.WriteEndElement(); - } - xmlWriter.WriteEndElement(); - - xmlWriter.WriteStartElement("ProductCategories"); - var productCategories = _categoryService.GetProductCategoriesByProductId(product.Id); - if (productCategories != null) - { - foreach (var productCategory in productCategories) - { - xmlWriter.WriteStartElement("ProductCategory"); - xmlWriter.WriteElementString("ProductCategoryId", null, productCategory.Id.ToString()); - xmlWriter.WriteElementString("CategoryId", null, productCategory.CategoryId.ToString()); - xmlWriter.WriteElementString("IsFeaturedProduct", null, productCategory.IsFeaturedProduct.ToString()); - xmlWriter.WriteElementString("DisplayOrder", null, productCategory.DisplayOrder.ToString()); - xmlWriter.WriteEndElement(); - } - } - xmlWriter.WriteEndElement(); - - xmlWriter.WriteStartElement("ProductManufacturers"); - var productManufacturers = _manufacturerService.GetProductManufacturersByProductId(product.Id); - if (productManufacturers != null) - { - foreach (var productManufacturer in productManufacturers) - { - xmlWriter.WriteStartElement("ProductManufacturer"); - xmlWriter.WriteElementString("ProductManufacturerId", null, productManufacturer.Id.ToString()); - xmlWriter.WriteElementString("ManufacturerId", null, productManufacturer.ManufacturerId.ToString()); - xmlWriter.WriteElementString("IsFeaturedProduct", null, productManufacturer.IsFeaturedProduct.ToString()); - xmlWriter.WriteElementString("DisplayOrder", null, productManufacturer.DisplayOrder.ToString()); - xmlWriter.WriteEndElement(); - } - } - xmlWriter.WriteEndElement(); - - xmlWriter.WriteStartElement("ProductSpecificationAttributes"); - var productSpecificationAttributes = product.ProductSpecificationAttributes; - foreach (var productSpecificationAttribute in productSpecificationAttributes) - { - xmlWriter.WriteStartElement("ProductSpecificationAttribute"); - xmlWriter.WriteElementString("ProductSpecificationAttributeId", null, productSpecificationAttribute.Id.ToString()); - xmlWriter.WriteElementString("SpecificationAttributeOptionId", null, productSpecificationAttribute.SpecificationAttributeOptionId.ToString()); - xmlWriter.WriteElementString("AllowFiltering", null, productSpecificationAttribute.AllowFiltering.ToString()); - xmlWriter.WriteElementString("ShowOnProductPage", null, productSpecificationAttribute.ShowOnProductPage.ToString()); - xmlWriter.WriteElementString("DisplayOrder", null, productSpecificationAttribute.DisplayOrder.ToString()); - xmlWriter.WriteEndElement(); - } - xmlWriter.WriteEndElement(); - xmlWriter.WriteStartElement("ProductBundleItems"); - var bundleItems = _productService.GetBundleItems(product.Id, true); - foreach (var bundleItem in bundleItems.Select(x => x.Item)) - { - xmlWriter.WriteStartElement("ProductBundleItem"); - - xmlWriter.WriteElementString("ProductId", null, bundleItem.ProductId.ToString()); - xmlWriter.WriteElementString("BundleProductId", null, bundleItem.BundleProductId.ToString()); - xmlWriter.WriteElementString("Quantity", null, bundleItem.Quantity.ToString()); - if (bundleItem.Discount.HasValue) - xmlWriter.WriteElementString("Discount", null, bundleItem.Discount.Value.ToString()); - xmlWriter.WriteElementString("DiscountPercentage", null, bundleItem.DiscountPercentage.ToString()); - xmlWriter.WriteElementString("Name", null, bundleItem.GetLocalizedName()); - xmlWriter.WriteElementString("ShortDescription", null, bundleItem.ShortDescription); - xmlWriter.WriteElementString("FilterAttributes", null, bundleItem.FilterAttributes.ToString()); - xmlWriter.WriteElementString("HideThumbnail", null, bundleItem.HideThumbnail.ToString()); - xmlWriter.WriteElementString("Visible", null, bundleItem.Visible.ToString()); - xmlWriter.WriteElementString("Published", null, bundleItem.Published.ToString()); - xmlWriter.WriteElementString("DisplayOrder", null, bundleItem.DisplayOrder.ToString()); - xmlWriter.WriteElementString("CreatedOnUtc", null, bundleItem.CreatedOnUtc.ToString()); - xmlWriter.WriteElementString("UpdatedOnUtc", null, bundleItem.UpdatedOnUtc.ToString()); - - xmlWriter.WriteEndElement(); + writer.WriteEndElement(); // Product } - xmlWriter.WriteEndElement(); - - + }); - xmlWriter.WriteEndElement(); - } - - xmlWriter.WriteEndElement(); - xmlWriter.WriteEndDocument(); - xmlWriter.Close(); - return stringWriter.ToString(); + return result; } + /// + /// Export product(s) to XML + /// + /// Action to export product entities + /// Result in XML format + public virtual string ExportProductsToXml(Action writeProducts) + { + var sb = new StringBuilder(); + var stringWriter = new StringWriter(sb); + var xmlWriter = new XmlTextWriter(stringWriter); + + xmlWriter.WriteStartDocument(); + xmlWriter.WriteStartElement("Products"); + xmlWriter.WriteAttributeString("Version", SmartStoreVersion.CurrentVersion); + + writeProducts(xmlWriter); + + xmlWriter.WriteEndElement(); + xmlWriter.WriteEndDocument(); + xmlWriter.Close(); + + return stringWriter.ToString(); + } + /// /// Export products to XLSX /// diff --git a/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs index 5f05271673..a73de4dc2c 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs @@ -1,8 +1,10 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Globalization; using System.IO; +using System.Xml; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Customers; -using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Orders; namespace SmartStore.Services.ExportImport @@ -25,6 +27,14 @@ public interface IExportManager /// Result in XML format string ExportCategoriesToXml(); + /// + /// Writes a single product + /// + /// The XML text writer + /// The product + /// Used culture + void WriteProductToXml(XmlTextWriter writer, Product product, CultureInfo culture = null); + /// /// Export product list to xml /// @@ -32,6 +42,13 @@ public interface IExportManager /// Result in XML format string ExportProductsToXml(IList products); + /// + /// Export product(s) to XML + /// + /// Action to export product entities + /// Result in XML format + string ExportProductsToXml(Action writeProducts); + /// /// Export products to XLSX /// diff --git a/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs b/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs index 79e4d2c5a1..2207fc3357 100644 --- a/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs +++ b/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs @@ -18,6 +18,7 @@ using SmartStore.Tests; using NUnit.Framework; using Rhino.Mocks; +using SmartStore.Core.Domain.Media; namespace SmartStore.Services.Tests.ExportImport { @@ -31,6 +32,7 @@ public class ExportManagerTests : ServiceTest INewsLetterSubscriptionService _newsLetterSubscriptionService; IExportManager _exportManager; ILanguageService _languageService; + MediaSettings _mediaSettings; [SetUp] public new void SetUp() @@ -41,9 +43,10 @@ public class ExportManagerTests : ServiceTest _pictureService = MockRepository.GenerateMock(); _newsLetterSubscriptionService = MockRepository.GenerateMock(); _languageService = MockRepository.GenerateMock(); + _mediaSettings = MockRepository.GenerateMock(); _exportManager = new ExportManager(_categoryService, - _manufacturerService, _productService, _pictureService, _newsLetterSubscriptionService, _languageService); + _manufacturerService, _productService, _pictureService, _newsLetterSubscriptionService, _languageService, _mediaSettings); } //[Test] From a64a6c0c87a4f71fea050d96866036960b1772b7 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 19 Jan 2015 20:52:38 +0100 Subject: [PATCH 0002/1256] ShopConnector: Improved xml product data export (2) --- .../ExportImport/ExportManager.cs | 28 ++++++++++--------- .../ExportImport/IExportManager.cs | 7 +++-- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index b8aef5b1d8..26fe7ae048 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -219,7 +219,7 @@ public virtual string ExportCategoriesToXml() /// The XML text writer /// The product /// Used culture - public virtual void WriteProductToXml(XmlTextWriter writer, Product product, CultureInfo culture = null) + public virtual void WriteProductToXml(XmlWriter writer, Product product, CultureInfo culture = null) { if (culture == null) culture = CultureInfo.InvariantCulture; @@ -541,24 +541,26 @@ public virtual string ExportProductsToXml(IList products) /// Export product(s) to XML /// /// Action to export product entities + /// XML writer settings /// Result in XML format - public virtual string ExportProductsToXml(Action writeProducts) + public virtual string ExportProductsToXml(Action writeProducts, XmlWriterSettings settings = null) { var sb = new StringBuilder(); - var stringWriter = new StringWriter(sb); - var xmlWriter = new XmlTextWriter(stringWriter); - - xmlWriter.WriteStartDocument(); - xmlWriter.WriteStartElement("Products"); - xmlWriter.WriteAttributeString("Version", SmartStoreVersion.CurrentVersion); + using (var stringWriter = new StringWriter(sb)) + using (var xmlWriter = XmlWriter.Create(stringWriter, settings)) + { + xmlWriter.WriteStartDocument(); + xmlWriter.WriteStartElement("Products"); + xmlWriter.WriteAttributeString("Version", SmartStoreVersion.CurrentVersion); - writeProducts(xmlWriter); + writeProducts(xmlWriter); - xmlWriter.WriteEndElement(); - xmlWriter.WriteEndDocument(); - xmlWriter.Close(); + xmlWriter.WriteEndElement(); + xmlWriter.WriteEndDocument(); + xmlWriter.Close(); - return stringWriter.ToString(); + return stringWriter.ToString(); + } } /// diff --git a/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs index a73de4dc2c..e226b54100 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs @@ -30,10 +30,10 @@ public interface IExportManager /// /// Writes a single product /// - /// The XML text writer + /// The XML writer /// The product /// Used culture - void WriteProductToXml(XmlTextWriter writer, Product product, CultureInfo culture = null); + void WriteProductToXml(XmlWriter writer, Product product, CultureInfo culture = null); /// /// Export product list to xml @@ -46,8 +46,9 @@ public interface IExportManager /// Export product(s) to XML /// /// Action to export product entities + /// XML writer settings /// Result in XML format - string ExportProductsToXml(Action writeProducts); + string ExportProductsToXml(Action writeProducts, XmlWriterSettings settings = null); /// /// Export products to XLSX From 11d67d5eebbdd9ee23e54c2ac22838ced4a43b20 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 21 Jan 2015 15:21:44 +0100 Subject: [PATCH 0003/1256] Time picker improvement --- .../Views/Shared/EditorTemplates/DateTime.cshtml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml index 4b8bfbb4b3..1b6638ac94 100644 --- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml @@ -20,6 +20,12 @@ { return ViewData["pickTime"].Convert(); } + else if (ViewData.ContainsKey("pickTimeFieldIds")) + { + var ids = ViewData["pickTimeFieldIds"] as List; + var id = ViewData.TemplateInfo.GetFullHtmlFieldId(string.Empty); + return ids.Contains(id); + } return false; } } From 7b6ff417e5ae801143d8e2324f60414f850eb941 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 26 Jan 2015 12:08:27 +0100 Subject: [PATCH 0004/1256] XPath extensions, more xml product export fields and more app path routines --- .../Extensions/XPathExtensions.cs | 69 +++++++++++++ .../SmartStore.Core/SmartStore.Core.csproj | 1 + .../ExportImport/ExportManager.cs | 5 +- .../SmartStore.Web.Framework/AppPath.cs | 96 ++++++++++++++++++- 4 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs diff --git a/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs new file mode 100644 index 0000000000..a9aefb6fb3 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs @@ -0,0 +1,69 @@ +using System; +using System.ComponentModel; +using System.Xml.XPath; + +namespace SmartStore +{ + public static class XPathExtensions + { + /// + /// Safe way to get the value of a xpath navigator item + /// + /// Type + /// The node + /// Optional xpath + /// Optional default value + /// The value + public static T GetValue(this XPathNavigator node, string xpath = null, T defaultValue = default(T)) + { + try + { + if (node != null) + { + if (xpath.IsNullOrEmpty()) + return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(node.Value); + + var n = node.SelectSingleNode(xpath); + if (n != null) + return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(n.Value); + } + } + catch (Exception exc) + { + exc.Dump(); + } + + return defaultValue; + } + + /// + /// Safe way to get the value of a xpath navigator item + /// + /// Type + /// The node + /// Optional xpath + /// Optional default value + /// The value + public static string GetValue(this XPathNavigator node, string xpath = null, string defaultValue = null) + { + try + { + if (node != null) + { + if (xpath.IsNullOrEmpty()) + return node.Value; + + var n = node.SelectSingleNode(xpath); + if (n != null) + return n.Value; + } + } + catch (Exception exc) + { + exc.Dump(); + } + + return defaultValue; + } + } +} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index e73c321770..1abf6893ce 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -157,6 +157,7 @@ + diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 26fe7ae048..2925e500b1 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -427,8 +427,11 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, Culture { writer.WriteStartElement("ProductPicture"); writer.WriteElementString("ProductPictureId", null, productPicture.Id.ToString()); - writer.WriteElementString("PictureId", null, productPicture.PictureId.ToString()); writer.WriteElementString("DisplayOrder", null, productPicture.DisplayOrder.ToString()); + + writer.WriteElementString("PictureId", null, productPicture.PictureId.ToString()); + writer.WriteElementString("SeoFilename", null, productPicture.Picture.SeoFilename); + writer.WriteElementString("MimeType", null, productPicture.Picture.MimeType); writer.WriteElementString("ThumbImageUrl", null, _pictureService.GetPictureUrl(productPicture.Picture, _mediaSettings.ProductThumbPictureSize, false)); writer.WriteElementString("ImageUrl", null, _pictureService.GetPictureUrl(productPicture.Picture, _mediaSettings.ProductDetailsPictureSize, false)); writer.WriteElementString("FullSizeImageUrl", null, _pictureService.GetPictureUrl(productPicture.Picture, 0, false)); diff --git a/src/Presentation/SmartStore.Web.Framework/AppPath.cs b/src/Presentation/SmartStore.Web.Framework/AppPath.cs index 78fa695db3..fc68e357b4 100644 --- a/src/Presentation/SmartStore.Web.Framework/AppPath.cs +++ b/src/Presentation/SmartStore.Web.Framework/AppPath.cs @@ -1,7 +1,7 @@ using System; -using System.Configuration; -using System.Web.Hosting; using System.IO; +using System.Threading; +using System.Web.Hosting; using SmartStore.Utilities; namespace SmartStore @@ -127,5 +127,97 @@ public static void CopyDirectory(DirectoryInfo source, DirectoryInfo target, boo } } } + + /// + /// Safe way to delete all directory content + /// + /// A directory path + public static void ClearDirectory(string directoryPath, bool selfToo) + { + if (directoryPath.IsNullOrEmpty()) + return; + + try + { + var dir = new DirectoryInfo(directoryPath); + + foreach (var fi in dir.GetFiles()) + { + try + { + fi.IsReadOnly = false; + fi.Delete(); + } + catch (Exception) + { + try + { + Thread.Sleep(0); + fi.Delete(); + } + catch (Exception) { } + } + } + + foreach (var di in dir.GetDirectories()) + { + ClearDirectory(di.FullName, false); + + try + { + di.Delete(); + } + catch (Exception) + { + try + { + Thread.Sleep(0); + di.Delete(); + } + catch (Exception) { } + } + } + } + catch (Exception) { } + + if (selfToo) + { + try + { + Directory.Delete(directoryPath, true); // just deletes the (now empty) directory + } + catch (Exception) { } + } + } + + /// + /// Safe way to count files in a directory + /// + /// A directory path + /// File count + public static int CountFiles(string directoryPath) + { + try + { + return Directory.GetFiles(directoryPath).Length; + } + catch (Exception) { } + + return 0; + } + + /// + /// Safe way to empty a file + /// + /// File path + public static void ClearFile(string path) + { + try + { + if (path.HasValue()) + File.WriteAllText(path, ""); + } + catch (Exception) { } + } } } From 077805a3d3f670ee481125d62d51fca9153afe38 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 28 Jan 2015 16:34:10 +0100 Subject: [PATCH 0005/1256] More enhancements on xml product export --- .../Extensions/XPathExtensions.cs | 13 +- .../Extensions/XmlNodeExtensions.cs | 19 ++- .../ExportImport/ExportManager.cs | 147 +++++++++++------- .../ExportImport/IExportManager.cs | 4 +- .../ExportImport/ImportManager.cs | 38 +---- .../Media/IPictureService.cs | 8 + .../Media/PictureService.cs | 49 ++++-- .../ExportImport/ExportManagerTests.cs | 4 +- 8 files changed, 164 insertions(+), 118 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs index a9aefb6fb3..6860481fd6 100644 --- a/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.Globalization; using System.Xml.XPath; namespace SmartStore @@ -13,19 +14,21 @@ public static class XPathExtensions /// The node /// Optional xpath /// Optional default value + /// If null is passed, CultureInfo.InvariantCulture is used. /// The value - public static T GetValue(this XPathNavigator node, string xpath = null, T defaultValue = default(T)) + public static T GetValue(this XPathNavigator node, string xpath = null, T defaultValue = default(T), CultureInfo culture = null) { try { if (node != null) { - if (xpath.IsNullOrEmpty()) - return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(node.Value); + if (xpath.IsNullOrEmpty() && node.Value.HasValue()) + return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(null, culture == null ? CultureInfo.InvariantCulture : culture, node.Value); var n = node.SelectSingleNode(xpath); - if (n != null) - return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(n.Value); + + if (n != null && n.Value.HasValue()) + return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(null, culture == null ? CultureInfo.InvariantCulture : culture, n.Value); } } catch (Exception exc) diff --git a/src/Libraries/SmartStore.Core/Extensions/XmlNodeExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/XmlNodeExtensions.cs index 0633efa3ef..e33b62a4ab 100644 --- a/src/Libraries/SmartStore.Core/Extensions/XmlNodeExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/XmlNodeExtensions.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.Globalization; using System.Xml; namespace SmartStore @@ -27,6 +28,7 @@ public static class XmlNodeExtensions return defaultValue; } + /// Safe way to get inner text of an attribute. public static string GetAttributeText(this XmlNode node, string attributeName) { @@ -34,18 +36,19 @@ public static string GetAttributeText(this XmlNode node, string attributeName) } /// Safe way to get inner text of a node. - public static T GetText(this XmlNode node, string xpath = null, T defaultValue = default(T)) + public static T GetText(this XmlNode node, string xpath = null, T defaultValue = default(T), CultureInfo culture = null) { try { if (node != null) { - if (xpath.IsNullOrEmpty()) - return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(node.InnerText); + if (xpath.IsNullOrEmpty() && node.InnerText.HasValue()) + return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(null, culture == null ? CultureInfo.InvariantCulture : culture, node.InnerText); + + var n = node.SelectSingleNode(xpath); - XmlNode n = node.SelectSingleNode(xpath); - if (n != null) - return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(n.InnerText); + if (n != null && n.InnerText.HasValue()) + return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(null, culture == null ? CultureInfo.InvariantCulture : culture, n.InnerText); } } catch (Exception exc) @@ -55,11 +58,11 @@ public static string GetAttributeText(this XmlNode node, string attributeName) return defaultValue; } + /// Safe way to get inner text of a node. public static string GetText(this XmlNode node, string xpath = null, string defaultValue = default(string)) { return node.GetText(xpath, defaultValue); } - - } // class + } } diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 2925e500b1..0c05387a7f 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -11,6 +11,7 @@ using SmartStore.Core; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Logging; @@ -34,6 +35,7 @@ public partial class ExportManager : IExportManager private readonly ICategoryService _categoryService; private readonly IManufacturerService _manufacturerService; private readonly IProductService _productService; + private readonly IProductTemplateService _productTemplateService; private readonly IPictureService _pictureService; private readonly INewsLetterSubscriptionService _newsLetterSubscriptionService; private readonly ILanguageService _languageService; @@ -46,6 +48,7 @@ public partial class ExportManager : IExportManager public ExportManager(ICategoryService categoryService, IManufacturerService manufacturerService, IProductService productService, + IProductTemplateService productTemplateService, IPictureService pictureService, INewsLetterSubscriptionService newsLetterSubscriptionService, ILanguageService languageService, @@ -54,6 +57,7 @@ public ExportManager(ICategoryService categoryService, this._categoryService = categoryService; this._manufacturerService = manufacturerService; this._productService = productService; + this._productTemplateService = productTemplateService; this._pictureService = pictureService; this._newsLetterSubscriptionService = newsLetterSubscriptionService; this._languageService = languageService; @@ -216,19 +220,17 @@ public virtual string ExportCategoriesToXml() /// /// Writes a single product /// - /// The XML text writer + /// The XML writer /// The product - /// Used culture - public virtual void WriteProductToXml(XmlWriter writer, Product product, CultureInfo culture = null) + /// Context objects + public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExportContext context) { - if (culture == null) - culture = CultureInfo.InvariantCulture; + var culture = CultureInfo.InvariantCulture; + var productTemplate = context.ProductTemplates.FirstOrDefault(x => x.Id == product.ProductTemplateId); - writer.WriteElementString("ProductId", null, product.Id.ToString()); - writer.WriteElementString("ProductTypeId", null, product.ProductTypeId.ToString()); - writer.WriteElementString("ParentGroupedProductId", null, product.ParentGroupedProductId.ToString()); - writer.WriteElementString("VisibleIndividually", null, product.VisibleIndividually.ToString()); + writer.WriteElementString("Id", null, product.Id.ToString()); writer.WriteElementString("Name", null, product.Name.RemoveInvalidXmlChars()); + writer.WriteElementString("SEName", null, product.GetSeName(0, true, false)); writer.WriteStartElement("ShortDescription"); writer.WriteCData(product.ShortDescription.RemoveInvalidXmlChars()); @@ -240,17 +242,28 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, Culture writer.WriteElementString("AdminComment", null, product.AdminComment.RemoveInvalidXmlChars()); writer.WriteElementString("ProductTemplateId", null, product.ProductTemplateId.ToString()); + writer.WriteElementString("ProductTemplateViewPath", null, productTemplate == null ? "" : productTemplate.ViewPath); writer.WriteElementString("ShowOnHomePage", null, product.ShowOnHomePage.ToString()); writer.WriteElementString("MetaKeywords", null, product.MetaKeywords.RemoveInvalidXmlChars()); writer.WriteElementString("MetaDescription", null, product.MetaDescription.RemoveInvalidXmlChars()); writer.WriteElementString("MetaTitle", null, product.MetaTitle.RemoveInvalidXmlChars()); - writer.WriteElementString("SEName", null, product.GetSeName(0)); writer.WriteElementString("AllowCustomerReviews", null, product.AllowCustomerReviews.ToString()); - writer.WriteElementString("SKU", null, product.Sku); + writer.WriteElementString("ApprovedRatingSum", null, product.ApprovedRatingSum.ToString()); + writer.WriteElementString("NotApprovedRatingSum", null, product.NotApprovedRatingSum.ToString()); + writer.WriteElementString("ApprovedTotalReviews", null, product.ApprovedTotalReviews.ToString()); + writer.WriteElementString("NotApprovedTotalReviews", null, product.NotApprovedTotalReviews.ToString()); + writer.WriteElementString("Published", null, product.Published.ToString()); + writer.WriteElementString("CreatedOnUtc", null, product.CreatedOnUtc.ToString(culture)); + writer.WriteElementString("UpdatedOnUtc", null, product.UpdatedOnUtc.ToString(culture)); + writer.WriteElementString("SubjectToAcl", null, product.SubjectToAcl.ToString()); + writer.WriteElementString("LimitedToStores", null, product.LimitedToStores.ToString()); + writer.WriteElementString("ProductTypeId", null, product.ProductTypeId.ToString()); + writer.WriteElementString("ParentGroupedProductId", null, product.ParentGroupedProductId.ToString()); + writer.WriteElementString("Sku", null, product.Sku); writer.WriteElementString("ManufacturerPartNumber", null, product.ManufacturerPartNumber); writer.WriteElementString("Gtin", null, product.Gtin); writer.WriteElementString("IsGiftCard", null, product.IsGiftCard.ToString()); - writer.WriteElementString("GiftCardType", null, product.GiftCardType.ToString()); + writer.WriteElementString("GiftCardTypeId", null, product.GiftCardTypeId.ToString()); writer.WriteElementString("RequireOtherProducts", null, product.RequireOtherProducts.ToString()); writer.WriteElementString("RequiredProductIds", null, product.RequiredProductIds); writer.WriteElementString("AutomaticallyAddRequiredProducts", null, product.AutomaticallyAddRequiredProducts.ToString()); @@ -271,7 +284,6 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, Culture writer.WriteElementString("IsShipEnabled", null, product.IsShipEnabled.ToString()); writer.WriteElementString("IsFreeShipping", null, product.IsFreeShipping.ToString()); writer.WriteElementString("AdditionalShippingCharge", null, product.AdditionalShippingCharge.ToString(culture)); - writer.WriteElementString("IsEsd", null, product.IsEsd.ToString()); writer.WriteElementString("IsTaxExempt", null, product.IsTaxExempt.ToString()); writer.WriteElementString("TaxCategoryId", null, product.TaxCategoryId.ToString()); writer.WriteElementString("ManageInventoryMethodId", null, product.ManageInventoryMethodId.ToString()); @@ -299,31 +311,27 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, Culture writer.WriteElementString("CustomerEntersPrice", null, product.CustomerEntersPrice.ToString()); writer.WriteElementString("MinimumCustomerEnteredPrice", null, product.MinimumCustomerEnteredPrice.ToString(culture)); writer.WriteElementString("MaximumCustomerEnteredPrice", null, product.MaximumCustomerEnteredPrice.ToString(culture)); - writer.WriteElementString("LowestAttributeCombinationPrice", null, product.LowestAttributeCombinationPrice.HasValue ? product.LowestAttributeCombinationPrice.Value.ToString(culture) : ""); + writer.WriteElementString("HasTierPrices", null, product.HasTierPrices.ToString()); + writer.WriteElementString("HasDiscountsApplied", null, product.HasDiscountsApplied.ToString()); writer.WriteElementString("Weight", null, product.Weight.ToString(culture)); writer.WriteElementString("Length", null, product.Length.ToString(culture)); writer.WriteElementString("Width", null, product.Width.ToString(culture)); writer.WriteElementString("Height", null, product.Height.ToString(culture)); - writer.WriteElementString("Published", null, product.Published.ToString()); - writer.WriteElementString("CreatedOnUtc", null, product.CreatedOnUtc.ToString(culture)); - writer.WriteElementString("UpdatedOnUtc", null, product.UpdatedOnUtc.ToString(culture)); - - if (product.DeliveryTimeId.HasValue) - writer.WriteElementString("DeliveryTimeId", null, product.DeliveryTimeId.Value.ToString()); - + writer.WriteElementString("AvailableStartDateTimeUtc", null, product.AvailableStartDateTimeUtc.HasValue ? product.AvailableStartDateTimeUtc.Value.ToString(culture) : ""); + writer.WriteElementString("AvailableEndDateTimeUtc", null, product.AvailableEndDateTimeUtc.HasValue ? product.AvailableEndDateTimeUtc.Value.ToString(culture) : ""); + writer.WriteElementString("DeliveryTimeId", null, product.DeliveryTimeId.HasValue ? product.DeliveryTimeId.Value.ToString() : ""); writer.WriteElementString("BasePriceEnabled", null, product.BasePriceEnabled.ToString()); writer.WriteElementString("BasePriceMeasureUnit", null, product.BasePriceMeasureUnit); - - if (product.BasePriceAmount.HasValue) - writer.WriteElementString("BasePriceAmount", null, product.BasePriceAmount.Value.ToString(culture)); - - if (product.BasePriceBaseAmount.HasValue) - writer.WriteElementString("BasePriceBaseAmount", null, product.BasePriceBaseAmount.Value.ToString()); - + writer.WriteElementString("BasePriceAmount", null, product.BasePriceAmount.HasValue ? product.BasePriceAmount.Value.ToString(culture) : ""); + writer.WriteElementString("BasePriceBaseAmount", null, product.BasePriceBaseAmount.HasValue ? product.BasePriceBaseAmount.Value.ToString() : ""); + writer.WriteElementString("VisibleIndividually", null, product.VisibleIndividually.ToString()); + writer.WriteElementString("DisplayOrder", null, product.DisplayOrder.ToString()); writer.WriteElementString("BundleTitleText", null, product.BundleTitleText.RemoveInvalidXmlChars()); - writer.WriteElementString("BundlePerItemShipping", null, product.BundlePerItemShipping.ToString()); writer.WriteElementString("BundlePerItemPricing", null, product.BundlePerItemPricing.ToString()); + writer.WriteElementString("BundlePerItemShipping", null, product.BundlePerItemShipping.ToString()); writer.WriteElementString("BundlePerItemShoppingCart", null, product.BundlePerItemShoppingCart.ToString()); + writer.WriteElementString("LowestAttributeCombinationPrice", null, product.LowestAttributeCombinationPrice.HasValue ? product.LowestAttributeCombinationPrice.Value.ToString(culture) : ""); + writer.WriteElementString("IsEsd", null, product.IsEsd.ToString()); writer.WriteStartElement("ProductDiscounts"); foreach (var discount in product.AppliedDiscounts) @@ -395,28 +403,17 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, Culture writer.WriteElementString("IsActive", null, combination.IsActive.ToString()); //xmlWriter.WriteElementString("IsDefaultCombination", null, combination.IsDefaultCombination.ToString()); - if (combination.BasePriceAmount.HasValue) - writer.WriteElementString("BasePriceAmount", null, combination.BasePriceAmount.Value.ToString(culture)); - if (combination.BasePriceBaseAmount.HasValue) - writer.WriteElementString("BasePriceBaseAmount", null, combination.BasePriceBaseAmount.Value.ToString()); - if (combination.DeliveryTimeId.HasValue) - writer.WriteElementString("DeliveryTimeId", null, combination.DeliveryTimeId.Value.ToString()); - if (combination.Length.HasValue) - writer.WriteElementString("Length", null, combination.Length.Value.ToString(culture)); - if (combination.Width.HasValue) - writer.WriteElementString("Width", null, combination.Width.Value.ToString(culture)); - if (combination.Height.HasValue) - writer.WriteElementString("Height", null, combination.Height.Value.ToString(culture)); - if (combination.Height.HasValue) - writer.WriteElementString("Height", null, combination.Height.Value.ToString(culture)); - if (combination.Gtin.HasValue()) - writer.WriteElementString("Gtin", null, combination.Gtin); - if (combination.Sku.HasValue()) - writer.WriteElementString("Sku", null, combination.Sku); - if (combination.ManufacturerPartNumber.HasValue()) - writer.WriteElementString("ManufacturerPartNumber", null, combination.ManufacturerPartNumber); - if (combination.Price.HasValue) - writer.WriteElementString("Price", null, combination.Price.Value.ToString(culture)); + writer.WriteElementString("BasePriceAmount", null, combination.BasePriceAmount.HasValue ? combination.BasePriceAmount.Value.ToString(culture) : ""); + writer.WriteElementString("BasePriceBaseAmount", null, combination.BasePriceBaseAmount.HasValue ? combination.BasePriceBaseAmount.Value.ToString() : ""); + writer.WriteElementString("DeliveryTimeId", null, combination.DeliveryTimeId.HasValue ? combination.DeliveryTimeId.Value.ToString() : ""); + writer.WriteElementString("Length", null, combination.Length.HasValue ? combination.Length.Value.ToString(culture) : ""); + writer.WriteElementString("Width", null, combination.Width.HasValue ? combination.Width.Value.ToString(culture) : ""); + writer.WriteElementString("Height", null, combination.Height.HasValue ? combination.Height.Value.ToString(culture) : ""); + writer.WriteElementString("Height", null, combination.Height.HasValue ? combination.Height.Value.ToString(culture) : ""); + writer.WriteElementString("Gtin", null, combination.Gtin); + writer.WriteElementString("Sku", null, combination.Sku); + writer.WriteElementString("ManufacturerPartNumber", null, combination.ManufacturerPartNumber); + writer.WriteElementString("Price", null, combination.Price.HasValue ? combination.Price.Value.ToString(culture) : ""); writer.WriteEndElement(); // ProductVariantAttributeCombination } @@ -489,12 +486,10 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, Culture foreach (var bundleItem in bundleItems.Select(x => x.Item)) { writer.WriteStartElement("ProductBundleItem"); - writer.WriteElementString("ProductId", null, bundleItem.ProductId.ToString()); writer.WriteElementString("BundleProductId", null, bundleItem.BundleProductId.ToString()); writer.WriteElementString("Quantity", null, bundleItem.Quantity.ToString()); - if (bundleItem.Discount.HasValue) - writer.WriteElementString("Discount", null, bundleItem.Discount.Value.ToString(culture)); + writer.WriteElementString("Discount", null, bundleItem.Discount.HasValue ? bundleItem.Discount.Value.ToString(culture) : ""); writer.WriteElementString("DiscountPercentage", null, bundleItem.DiscountPercentage.ToString()); writer.WriteElementString("Name", null, bundleItem.GetLocalizedName()); writer.WriteElementString("ShortDescription", null, bundleItem.ShortDescription.RemoveInvalidXmlChars()); @@ -505,10 +500,37 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, Culture writer.WriteElementString("DisplayOrder", null, bundleItem.DisplayOrder.ToString()); writer.WriteElementString("CreatedOnUtc", null, bundleItem.CreatedOnUtc.ToString(culture)); writer.WriteElementString("UpdatedOnUtc", null, bundleItem.UpdatedOnUtc.ToString(culture)); - writer.WriteEndElement(); } writer.WriteEndElement(); + + writer.WriteStartElement("Localizations"); + foreach (var language in context.Languages) + { + writer.WriteStartElement("Localization"); + + writer.WriteStartElement("Language"); + writer.WriteElementString("Id", null, language.Id.ToString()); + writer.WriteElementString("Name", null, language.Name); + writer.WriteElementString("LanguageCulture", null, language.LanguageCulture); + writer.WriteElementString("UniqueSeoCode", null, language.UniqueSeoCode); + writer.WriteElementString("Published", null, language.Published.ToString()); + writer.WriteEndElement(); + + writer.WriteStartElement("Product"); + writer.WriteElementString("Name", null, product.GetLocalized(x => x.Name, language.Id, false, false)); + writer.WriteElementString("ShortDescription", null, product.GetLocalized(x => x.ShortDescription, language.Id, false, false)); + writer.WriteElementString("FullDescription", null, product.GetLocalized(x => x.FullDescription, language.Id, false, false)); + writer.WriteElementString("MetaKeywords", null, product.GetLocalized(x => x.MetaKeywords, language.Id, false, false)); + writer.WriteElementString("MetaDescription", null, product.GetLocalized(x => x.MetaDescription, language.Id, false, false)); + writer.WriteElementString("MetaTitle", null, product.GetLocalized(x => x.MetaTitle, language.Id, false, false)); + writer.WriteElementString("SEName", null, product.GetSeName(language.Id, false, false)); + writer.WriteElementString("BundleTitleText", null, product.GetLocalized(x => x.BundleTitleText, language.Id, false, false)); + writer.WriteEndElement(); + + writer.WriteEndElement(); // Localization + } + writer.WriteEndElement(); // Localizations } /// @@ -520,13 +542,19 @@ public virtual string ExportProductsToXml(IList products) { string result = ExportProductsToXml(writer => { + var context = new XmlExportContext() + { + ProductTemplates = _productTemplateService.GetAllProductTemplates(), + Languages = _languageService.GetAllLanguages(true) + }; + foreach (var product in products) { writer.WriteStartElement("Product"); try { - WriteProductToXml(writer, product); + WriteProductToXml(writer, product, context); } catch (Exception exc) { @@ -1760,4 +1788,11 @@ public virtual string ExportCustomersToXml(IList customers) #endregion } + + + public class XmlExportContext + { + public IList ProductTemplates { get; set; } + public IList Languages { get; set; } + } } diff --git a/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs index e226b54100..d440b30489 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs @@ -32,8 +32,8 @@ public interface IExportManager /// /// The XML writer /// The product - /// Used culture - void WriteProductToXml(XmlWriter writer, Product product, CultureInfo culture = null); + /// Context objects + void WriteProductToXml(XmlWriter writer, Product product, XmlExportContext context); /// /// Export product list to xml diff --git a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs index 0719dce8c7..b759b01b41 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs @@ -695,7 +695,7 @@ private void ProcessProductPictures(ICollection> batch, Impor continue; var currentPictures = _rsProductPicture.Expand(_rsProductPicture.TableUntracked, x => x.Picture).Where(x => x.ProductId == row.Entity.Id).Select(x => x.Picture).ToList(); - var pictureBinary = FindEqualPicture(picture, currentPictures); + var pictureBinary = _pictureService.FindEqualPicture(picture, currentPictures); if (pictureBinary != null && pictureBinary.Length > 0) { @@ -753,41 +753,5 @@ private void ProcessProductPictures(ICollection> batch, Impor return (int?)null; } - - /// - /// Finds an equal picture by comparing the binary buffer - /// - /// The picture to find a duplicate for - /// The sequence of product pictures to seek within for duplicates - /// The picture binary for path when no picture equals in the sequence, null otherwise. - private byte[] FindEqualPicture(string path, IEnumerable productPictures) - { - try - { - var myBuffer = File.ReadAllBytes(path); - - foreach (var picture in productPictures) - { - var otherBuffer = _pictureService.LoadPictureBinary(picture); - using (var myStream = new MemoryStream(myBuffer)) - { - using (var otherStream = new MemoryStream(otherBuffer)) - { - var equals = myStream.ContentsEqual(otherStream); - if (equals) - { - return null; - } - } - } - } - - return myBuffer; - } - catch - { - return null; - } - } } } diff --git a/src/Libraries/SmartStore.Services/Media/IPictureService.cs b/src/Libraries/SmartStore.Services/Media/IPictureService.cs index 74b2aba0da..0c89008b4d 100644 --- a/src/Libraries/SmartStore.Services/Media/IPictureService.cs +++ b/src/Libraries/SmartStore.Services/Media/IPictureService.cs @@ -17,6 +17,14 @@ public partial interface IPictureService /// MIME type /// Picture binary or throws an exception byte[] ValidatePicture(byte[] pictureBinary); + + /// + /// Finds an equal picture by comparing the binary buffer + /// + /// The picture to find a duplicate for + /// The sequence of product pictures to seek within for duplicates + /// The picture binary for path when no picture equals in the sequence, null otherwise. + byte[] FindEqualPicture(string path, IEnumerable productPictures); /// /// Gets the loaded picture binary depending on picture storage settings diff --git a/src/Libraries/SmartStore.Services/Media/PictureService.cs b/src/Libraries/SmartStore.Services/Media/PictureService.cs index 9f8259a95b..3cfa809d54 100644 --- a/src/Libraries/SmartStore.Services/Media/PictureService.cs +++ b/src/Libraries/SmartStore.Services/Media/PictureService.cs @@ -1,23 +1,18 @@ using System; using System.Collections.Generic; using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; using System.IO; using System.Linq; +using System.Text; +using ImageResizer; using SmartStore.Core; -using SmartStore.Core.IO; using SmartStore.Core.Data; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Media; -using SmartStore.Services.Configuration; using SmartStore.Core.Events; +using SmartStore.Core.IO; using SmartStore.Core.Logging; -using SmartStore.Services.Seo; -using ImageResizer; -using ImageResizer.Configuration; -using System.Threading; -using System.Text; +using SmartStore.Services.Configuration; using SmartStore.Utilities; namespace SmartStore.Services.Media @@ -140,6 +135,42 @@ public virtual byte[] ValidatePicture(byte[] pictureBinary) } } + /// + /// Finds an equal picture by comparing the binary buffer + /// + /// The picture to find a duplicate for + /// The sequence of product pictures to seek within for duplicates + /// The picture binary for path when no picture equals in the sequence, null otherwise. + public byte[] FindEqualPicture(string path, IEnumerable productPictures) + { + try + { + var myBuffer = File.ReadAllBytes(path); + + foreach (var picture in productPictures) + { + var otherBuffer = LoadPictureBinary(picture); + using (var myStream = new MemoryStream(myBuffer)) + { + using (var otherStream = new MemoryStream(otherBuffer)) + { + var equals = myStream.ContentsEqual(otherStream); + if (equals) + { + return null; + } + } + } + } + + return myBuffer; + } + catch + { + return null; + } + } + private string GetDefaultImageFileName(PictureType defaultPictureType = PictureType.Entity) { string defaultImageFileName; diff --git a/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs b/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs index 2207fc3357..9b643109d6 100644 --- a/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs +++ b/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs @@ -28,6 +28,7 @@ public class ExportManagerTests : ServiceTest ICategoryService _categoryService; IManufacturerService _manufacturerService; IProductService _productService; + IProductTemplateService _productTemplateService; IPictureService _pictureService; INewsLetterSubscriptionService _newsLetterSubscriptionService; IExportManager _exportManager; @@ -40,13 +41,14 @@ public class ExportManagerTests : ServiceTest _categoryService = MockRepository.GenerateMock(); _manufacturerService = MockRepository.GenerateMock(); _productService = MockRepository.GenerateMock(); + _productTemplateService = MockRepository.GenerateMock(); _pictureService = MockRepository.GenerateMock(); _newsLetterSubscriptionService = MockRepository.GenerateMock(); _languageService = MockRepository.GenerateMock(); _mediaSettings = MockRepository.GenerateMock(); _exportManager = new ExportManager(_categoryService, - _manufacturerService, _productService, _pictureService, _newsLetterSubscriptionService, _languageService, _mediaSettings); + _manufacturerService, _productService, _productTemplateService, _pictureService, _newsLetterSubscriptionService, _languageService, _mediaSettings); } //[Test] From a1df53ac62c4912f302786af161747fce436440c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 29 Jan 2015 13:28:20 +0100 Subject: [PATCH 0006/1256] More enhancements on xml product export --- .../ExportImport/ExportManager.cs | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 0c05387a7f..ce14a234c3 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -230,7 +230,7 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.WriteElementString("Id", null, product.Id.ToString()); writer.WriteElementString("Name", null, product.Name.RemoveInvalidXmlChars()); - writer.WriteElementString("SEName", null, product.GetSeName(0, true, false)); + writer.WriteElementString("SeName", null, product.GetSeName(0, true, false)); writer.WriteStartElement("ShortDescription"); writer.WriteCData(product.ShortDescription.RemoveInvalidXmlChars()); @@ -459,10 +459,21 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo foreach (var productManufacturer in productManufacturers) { writer.WriteStartElement("ProductManufacturer"); + writer.WriteElementString("ProductManufacturerId", null, productManufacturer.Id.ToString()); writer.WriteElementString("ManufacturerId", null, productManufacturer.ManufacturerId.ToString()); writer.WriteElementString("IsFeaturedProduct", null, productManufacturer.IsFeaturedProduct.ToString()); writer.WriteElementString("DisplayOrder", null, productManufacturer.DisplayOrder.ToString()); + + writer.WriteStartElement("Manufacturer"); + writer.WriteElementString("Name", null, productManufacturer.Manufacturer.Name); + writer.WriteElementString("SeName", null, productManufacturer.Manufacturer.GetSeName(0, true, false)); + writer.WriteElementString("Description", null, productManufacturer.Manufacturer.Description.RemoveInvalidXmlChars()); + writer.WriteElementString("MetaKeywords", null, productManufacturer.Manufacturer.MetaKeywords.RemoveInvalidXmlChars()); + writer.WriteElementString("MetaDescription", null, productManufacturer.Manufacturer.MetaDescription.RemoveInvalidXmlChars()); + writer.WriteElementString("MetaTitle", null, productManufacturer.Manufacturer.MetaTitle.RemoveInvalidXmlChars()); + writer.WriteEndElement(); + writer.WriteEndElement(); } } @@ -504,20 +515,11 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo } writer.WriteEndElement(); - writer.WriteStartElement("Localizations"); + writer.WriteStartElement("LocalizedProperties"); foreach (var language in context.Languages) { - writer.WriteStartElement("Localization"); - - writer.WriteStartElement("Language"); - writer.WriteElementString("Id", null, language.Id.ToString()); - writer.WriteElementString("Name", null, language.Name); - writer.WriteElementString("LanguageCulture", null, language.LanguageCulture); - writer.WriteElementString("UniqueSeoCode", null, language.UniqueSeoCode); - writer.WriteElementString("Published", null, language.Published.ToString()); - writer.WriteEndElement(); + writer.WriteStartElement("LocalizedProperty"); - writer.WriteStartElement("Product"); writer.WriteElementString("Name", null, product.GetLocalized(x => x.Name, language.Id, false, false)); writer.WriteElementString("ShortDescription", null, product.GetLocalized(x => x.ShortDescription, language.Id, false, false)); writer.WriteElementString("FullDescription", null, product.GetLocalized(x => x.FullDescription, language.Id, false, false)); @@ -526,11 +528,18 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.WriteElementString("MetaTitle", null, product.GetLocalized(x => x.MetaTitle, language.Id, false, false)); writer.WriteElementString("SEName", null, product.GetSeName(language.Id, false, false)); writer.WriteElementString("BundleTitleText", null, product.GetLocalized(x => x.BundleTitleText, language.Id, false, false)); + + writer.WriteStartElement("Language"); + writer.WriteElementString("Id", null, language.Id.ToString()); + writer.WriteElementString("Name", null, language.Name); + writer.WriteElementString("LanguageCulture", null, language.LanguageCulture); + writer.WriteElementString("UniqueSeoCode", null, language.UniqueSeoCode); + writer.WriteElementString("Published", null, language.Published.ToString()); writer.WriteEndElement(); - writer.WriteEndElement(); // Localization + writer.WriteEndElement(); // LocalizedProperty } - writer.WriteEndElement(); // Localizations + writer.WriteEndElement(); // LocalizedProperties } /// From e3debe98b6faaa5bb5c4010b5ee09588f3bc1857 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 2 Feb 2015 10:46:57 +0100 Subject: [PATCH 0007/1256] Compression filter attribute, better handling of localized values in xml export --- .../Extensions/XPathExtensions.cs | 38 +- .../Extensions/XmlWriterExtensions.cs | 30 +- .../ExportImport/ExportManager.cs | 423 +++++++++--------- .../Mvc/CompressAttribute.cs | 34 ++ .../SmartStore.Web.Framework.csproj | 1 + 5 files changed, 308 insertions(+), 218 deletions(-) create mode 100644 src/Presentation/SmartStore.Web.Framework/Mvc/CompressAttribute.cs diff --git a/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs index 6860481fd6..b8c8f63d86 100644 --- a/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/XPathExtensions.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Globalization; using System.Xml.XPath; +using SmartStore.Core.Domain.Localization; namespace SmartStore { @@ -14,16 +15,25 @@ public static class XPathExtensions /// The node /// Optional xpath /// Optional default value + /// For localized values. Xpath scheme: Localized/xpath[@culture = 'language.LanguageCulture'] /// If null is passed, CultureInfo.InvariantCulture is used. /// The value - public static T GetValue(this XPathNavigator node, string xpath = null, T defaultValue = default(T), CultureInfo culture = null) + public static T GetValue(this XPathNavigator node, string xpath = null, T defaultValue = default(T), Language language = null, CultureInfo culture = null) { try { if (node != null) { - if (xpath.IsNullOrEmpty() && node.Value.HasValue()) - return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(null, culture == null ? CultureInfo.InvariantCulture : culture, node.Value); + if (xpath.IsNullOrEmpty()) + { + if (node.Value.HasValue()) + return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(null, culture == null ? CultureInfo.InvariantCulture : culture, node.Value); + + return defaultValue; + } + + if (language != null) + xpath = "Localized/{0}[@culture = '{1}']".FormatWith(xpath, language.LanguageCulture.EmptyNull().ToLower()); var n = node.SelectSingleNode(xpath); @@ -40,15 +50,15 @@ public static class XPathExtensions } /// - /// Safe way to get the value of a xpath navigator item + /// Safe way to get a string value of a xpath navigator item /// - /// Type /// The node /// Optional xpath /// Optional default value /// The value - public static string GetValue(this XPathNavigator node, string xpath = null, string defaultValue = null) + public static string GetString(this XPathNavigator node, string xpath = null, string defaultValue = null) { + // note: better not merge GetString(...) and GetValue(...) try { if (node != null) @@ -57,6 +67,7 @@ public static string GetValue(this XPathNavigator node, string xpath = null, str return node.Value; var n = node.SelectSingleNode(xpath); + if (n != null) return n.Value; } @@ -68,5 +79,20 @@ public static string GetValue(this XPathNavigator node, string xpath = null, str return defaultValue; } + + /// + /// Safe way to get a localized string value of a xpath navigator item + /// + /// The node + /// For localized values. Xpath scheme: Localized/xpath[@culture = 'language.LanguageCulture'] + /// Optional xpath + /// Optional default value + /// The value + public static string GetString(this XPathNavigator node, Language language, string xpath, string defaultValue = null) + { + return node.GetString( + "Localized/{0}[@culture = '{1}']".FormatWith(xpath.EmptyNull(), language.LanguageCulture.EmptyNull().ToLower()), + defaultValue); + } } } diff --git a/src/Libraries/SmartStore.Core/Extensions/XmlWriterExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/XmlWriterExtensions.cs index 000994fb77..32796d6dbe 100644 --- a/src/Libraries/SmartStore.Core/Extensions/XmlWriterExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/XmlWriterExtensions.cs @@ -1,10 +1,10 @@ using System; using System.ComponentModel; using System.Xml; +using SmartStore.Core.Domain.Localization; namespace SmartStore { - /// codehint: sm-add public static class XmlWriterExtensions { public static void WriteCData(this XmlWriter writer, string name, string value, string prefix = null, string ns = null) @@ -19,6 +19,7 @@ public static void WriteCData(this XmlWriter writer, string name, string value, writer.WriteEndElement(); } } + public static void WriteNode(this XmlWriter writer, string name, Action content) { if (name.HasValue() && content != null) @@ -29,5 +30,30 @@ public static void WriteNode(this XmlWriter writer, string name, Action content) } } - } // class + /// + /// Created a simple or CData node element + /// + /// The writer + /// Node name + /// Node value + /// The language. Its culture is always converted to lowercase! + /// Whether to create simple or CData node + public static void Write(this XmlWriter writer, string name, string value, Language language = null, bool asCData = false) + { + if (name.HasValue() && value != null) + { + writer.WriteStartElement(name); + + if (language != null) + writer.WriteAttributeString("culture", language.LanguageCulture.EmptyNull().ToLower()); + + if (asCData) + writer.WriteCData(value); + else + writer.WriteString(value); + + writer.WriteEndElement(); + } + } + } } diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index ce14a234c3..2d2bd4bac5 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -127,6 +127,16 @@ protected virtual void WriteCategories(XmlWriter xmlWriter, int parentCategoryId } } + protected Action> WriteLocalized = (writer, context, content) => + { + writer.WriteStartElement("Localized"); + foreach (var language in context.Languages) + { + content(language); + } + writer.WriteEndElement(); + }; + #endregion #region Methods @@ -228,116 +238,123 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo var culture = CultureInfo.InvariantCulture; var productTemplate = context.ProductTemplates.FirstOrDefault(x => x.Id == product.ProductTemplateId); - writer.WriteElementString("Id", null, product.Id.ToString()); - writer.WriteElementString("Name", null, product.Name.RemoveInvalidXmlChars()); - writer.WriteElementString("SeName", null, product.GetSeName(0, true, false)); - - writer.WriteStartElement("ShortDescription"); - writer.WriteCData(product.ShortDescription.RemoveInvalidXmlChars()); - writer.WriteEndElement(); - - writer.WriteStartElement("FullDescription"); - writer.WriteCData(product.FullDescription.RemoveInvalidXmlChars()); - writer.WriteEndElement(); - - writer.WriteElementString("AdminComment", null, product.AdminComment.RemoveInvalidXmlChars()); - writer.WriteElementString("ProductTemplateId", null, product.ProductTemplateId.ToString()); - writer.WriteElementString("ProductTemplateViewPath", null, productTemplate == null ? "" : productTemplate.ViewPath); - writer.WriteElementString("ShowOnHomePage", null, product.ShowOnHomePage.ToString()); - writer.WriteElementString("MetaKeywords", null, product.MetaKeywords.RemoveInvalidXmlChars()); - writer.WriteElementString("MetaDescription", null, product.MetaDescription.RemoveInvalidXmlChars()); - writer.WriteElementString("MetaTitle", null, product.MetaTitle.RemoveInvalidXmlChars()); - writer.WriteElementString("AllowCustomerReviews", null, product.AllowCustomerReviews.ToString()); - writer.WriteElementString("ApprovedRatingSum", null, product.ApprovedRatingSum.ToString()); - writer.WriteElementString("NotApprovedRatingSum", null, product.NotApprovedRatingSum.ToString()); - writer.WriteElementString("ApprovedTotalReviews", null, product.ApprovedTotalReviews.ToString()); - writer.WriteElementString("NotApprovedTotalReviews", null, product.NotApprovedTotalReviews.ToString()); - writer.WriteElementString("Published", null, product.Published.ToString()); - writer.WriteElementString("CreatedOnUtc", null, product.CreatedOnUtc.ToString(culture)); - writer.WriteElementString("UpdatedOnUtc", null, product.UpdatedOnUtc.ToString(culture)); - writer.WriteElementString("SubjectToAcl", null, product.SubjectToAcl.ToString()); - writer.WriteElementString("LimitedToStores", null, product.LimitedToStores.ToString()); - writer.WriteElementString("ProductTypeId", null, product.ProductTypeId.ToString()); - writer.WriteElementString("ParentGroupedProductId", null, product.ParentGroupedProductId.ToString()); - writer.WriteElementString("Sku", null, product.Sku); - writer.WriteElementString("ManufacturerPartNumber", null, product.ManufacturerPartNumber); - writer.WriteElementString("Gtin", null, product.Gtin); - writer.WriteElementString("IsGiftCard", null, product.IsGiftCard.ToString()); - writer.WriteElementString("GiftCardTypeId", null, product.GiftCardTypeId.ToString()); - writer.WriteElementString("RequireOtherProducts", null, product.RequireOtherProducts.ToString()); - writer.WriteElementString("RequiredProductIds", null, product.RequiredProductIds); - writer.WriteElementString("AutomaticallyAddRequiredProducts", null, product.AutomaticallyAddRequiredProducts.ToString()); - writer.WriteElementString("IsDownload", null, product.IsDownload.ToString()); - writer.WriteElementString("DownloadId", null, product.DownloadId.ToString()); - writer.WriteElementString("UnlimitedDownloads", null, product.UnlimitedDownloads.ToString()); - writer.WriteElementString("MaxNumberOfDownloads", null, product.MaxNumberOfDownloads.ToString()); - writer.WriteElementString("DownloadExpirationDays", null, product.DownloadExpirationDays.HasValue ? product.DownloadExpirationDays.ToString() : ""); - writer.WriteElementString("DownloadActivationType", null, product.DownloadActivationType.ToString()); - writer.WriteElementString("HasSampleDownload", null, product.HasSampleDownload.ToString()); - writer.WriteElementString("SampleDownloadId", null, product.SampleDownloadId.ToString()); - writer.WriteElementString("HasUserAgreement", null, product.HasUserAgreement.ToString()); - writer.WriteElementString("UserAgreementText", null, product.UserAgreementText.RemoveInvalidXmlChars()); - writer.WriteElementString("IsRecurring", null, product.IsRecurring.ToString()); - writer.WriteElementString("RecurringCycleLength", null, product.RecurringCycleLength.ToString()); - writer.WriteElementString("RecurringCyclePeriodId", null, product.RecurringCyclePeriodId.ToString()); - writer.WriteElementString("RecurringTotalCycles", null, product.RecurringTotalCycles.ToString()); - writer.WriteElementString("IsShipEnabled", null, product.IsShipEnabled.ToString()); - writer.WriteElementString("IsFreeShipping", null, product.IsFreeShipping.ToString()); - writer.WriteElementString("AdditionalShippingCharge", null, product.AdditionalShippingCharge.ToString(culture)); - writer.WriteElementString("IsTaxExempt", null, product.IsTaxExempt.ToString()); - writer.WriteElementString("TaxCategoryId", null, product.TaxCategoryId.ToString()); - writer.WriteElementString("ManageInventoryMethodId", null, product.ManageInventoryMethodId.ToString()); - writer.WriteElementString("StockQuantity", null, product.StockQuantity.ToString()); - writer.WriteElementString("DisplayStockAvailability", null, product.DisplayStockAvailability.ToString()); - writer.WriteElementString("DisplayStockQuantity", null, product.DisplayStockQuantity.ToString()); - writer.WriteElementString("MinStockQuantity", null, product.MinStockQuantity.ToString()); - writer.WriteElementString("LowStockActivityId", null, product.LowStockActivityId.ToString()); - writer.WriteElementString("NotifyAdminForQuantityBelow", null, product.NotifyAdminForQuantityBelow.ToString()); - writer.WriteElementString("BackorderModeId", null, product.BackorderModeId.ToString()); - writer.WriteElementString("AllowBackInStockSubscriptions", null, product.AllowBackInStockSubscriptions.ToString()); - writer.WriteElementString("OrderMinimumQuantity", null, product.OrderMinimumQuantity.ToString()); - writer.WriteElementString("OrderMaximumQuantity", null, product.OrderMaximumQuantity.ToString()); - writer.WriteElementString("AllowedQuantities", null, product.AllowedQuantities); - writer.WriteElementString("DisableBuyButton", null, product.DisableBuyButton.ToString()); - writer.WriteElementString("DisableWishlistButton", null, product.DisableWishlistButton.ToString()); - writer.WriteElementString("AvailableForPreOrder", null, product.AvailableForPreOrder.ToString()); - writer.WriteElementString("CallForPrice", null, product.CallForPrice.ToString()); - writer.WriteElementString("Price", null, product.Price.ToString(culture)); - writer.WriteElementString("OldPrice", null, product.OldPrice.ToString(culture)); - writer.WriteElementString("ProductCost", null, product.ProductCost.ToString(culture)); - writer.WriteElementString("SpecialPrice", null, product.SpecialPrice.HasValue ? product.SpecialPrice.Value.ToString(culture) : ""); - writer.WriteElementString("SpecialPriceStartDateTimeUtc", null, product.SpecialPriceStartDateTimeUtc.HasValue ? product.SpecialPriceStartDateTimeUtc.Value.ToString(culture) : ""); - writer.WriteElementString("SpecialPriceEndDateTimeUtc", null, product.SpecialPriceEndDateTimeUtc.HasValue ? product.SpecialPriceEndDateTimeUtc.Value.ToString(culture) : ""); - writer.WriteElementString("CustomerEntersPrice", null, product.CustomerEntersPrice.ToString()); - writer.WriteElementString("MinimumCustomerEnteredPrice", null, product.MinimumCustomerEnteredPrice.ToString(culture)); - writer.WriteElementString("MaximumCustomerEnteredPrice", null, product.MaximumCustomerEnteredPrice.ToString(culture)); - writer.WriteElementString("HasTierPrices", null, product.HasTierPrices.ToString()); - writer.WriteElementString("HasDiscountsApplied", null, product.HasDiscountsApplied.ToString()); - writer.WriteElementString("Weight", null, product.Weight.ToString(culture)); - writer.WriteElementString("Length", null, product.Length.ToString(culture)); - writer.WriteElementString("Width", null, product.Width.ToString(culture)); - writer.WriteElementString("Height", null, product.Height.ToString(culture)); - writer.WriteElementString("AvailableStartDateTimeUtc", null, product.AvailableStartDateTimeUtc.HasValue ? product.AvailableStartDateTimeUtc.Value.ToString(culture) : ""); - writer.WriteElementString("AvailableEndDateTimeUtc", null, product.AvailableEndDateTimeUtc.HasValue ? product.AvailableEndDateTimeUtc.Value.ToString(culture) : ""); - writer.WriteElementString("DeliveryTimeId", null, product.DeliveryTimeId.HasValue ? product.DeliveryTimeId.Value.ToString() : ""); - writer.WriteElementString("BasePriceEnabled", null, product.BasePriceEnabled.ToString()); - writer.WriteElementString("BasePriceMeasureUnit", null, product.BasePriceMeasureUnit); - writer.WriteElementString("BasePriceAmount", null, product.BasePriceAmount.HasValue ? product.BasePriceAmount.Value.ToString(culture) : ""); - writer.WriteElementString("BasePriceBaseAmount", null, product.BasePriceBaseAmount.HasValue ? product.BasePriceBaseAmount.Value.ToString() : ""); - writer.WriteElementString("VisibleIndividually", null, product.VisibleIndividually.ToString()); - writer.WriteElementString("DisplayOrder", null, product.DisplayOrder.ToString()); - writer.WriteElementString("BundleTitleText", null, product.BundleTitleText.RemoveInvalidXmlChars()); - writer.WriteElementString("BundlePerItemPricing", null, product.BundlePerItemPricing.ToString()); - writer.WriteElementString("BundlePerItemShipping", null, product.BundlePerItemShipping.ToString()); - writer.WriteElementString("BundlePerItemShoppingCart", null, product.BundlePerItemShoppingCart.ToString()); - writer.WriteElementString("LowestAttributeCombinationPrice", null, product.LowestAttributeCombinationPrice.HasValue ? product.LowestAttributeCombinationPrice.Value.ToString(culture) : ""); - writer.WriteElementString("IsEsd", null, product.IsEsd.ToString()); + writer.Write("Id", product.Id.ToString()); + writer.Write("Name", product.Name.RemoveInvalidXmlChars()); + writer.Write("SeName", product.GetSeName(0, true, false)); + + writer.Write("ShortDescription", product.ShortDescription.RemoveInvalidXmlChars(), null, true); + writer.Write("FullDescription", product.FullDescription.RemoveInvalidXmlChars(), null, true); + + writer.Write("AdminComment", product.AdminComment.RemoveInvalidXmlChars()); + writer.Write("ProductTemplateId", product.ProductTemplateId.ToString()); + writer.Write("ProductTemplateViewPath", productTemplate == null ? "" : productTemplate.ViewPath); + writer.Write("ShowOnHomePage", product.ShowOnHomePage.ToString()); + writer.Write("MetaKeywords", product.MetaKeywords.RemoveInvalidXmlChars()); + writer.Write("MetaDescription", product.MetaDescription.RemoveInvalidXmlChars()); + writer.Write("MetaTitle", product.MetaTitle.RemoveInvalidXmlChars()); + 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.RemoveInvalidXmlChars()); + 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("DeliveryTimeId", product.DeliveryTimeId.HasValue ? product.DeliveryTimeId.Value.ToString() : ""); + 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.RemoveInvalidXmlChars()); + 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).RemoveInvalidXmlChars(), lang, true); + writer.Write("FullDescription", product.GetLocalized(x => x.FullDescription, lang.Id, false, false).RemoveInvalidXmlChars(), lang, true); + writer.Write("MetaKeywords", product.GetLocalized(x => x.MetaKeywords, lang.Id, false, false).RemoveInvalidXmlChars(), lang); + writer.Write("MetaDescription", product.GetLocalized(x => x.MetaDescription, lang.Id, false, false).RemoveInvalidXmlChars(), lang); + writer.Write("MetaTitle", product.GetLocalized(x => x.MetaTitle, lang.Id, false, false).RemoveInvalidXmlChars(), lang); + writer.Write("BundleTitleText", product.GetLocalized(x => x.BundleTitleText, lang.Id, false, false), lang); + }); writer.WriteStartElement("ProductDiscounts"); foreach (var discount in product.AppliedDiscounts) { writer.WriteStartElement("ProductDiscount"); - writer.WriteElementString("DiscountId", null, discount.Id.ToString()); + writer.Write("DiscountId", discount.Id.ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); @@ -346,11 +363,11 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo foreach (var tierPrice in product.TierPrices) { writer.WriteStartElement("TierPrice"); - writer.WriteElementString("TierPriceId", null, tierPrice.Id.ToString()); - writer.WriteElementString("StoreId", null, tierPrice.StoreId.ToString()); - writer.WriteElementString("CustomerRoleId", null, tierPrice.CustomerRoleId.HasValue ? tierPrice.CustomerRoleId.ToString() : "0"); - writer.WriteElementString("Quantity", null, tierPrice.Quantity.ToString()); - writer.WriteElementString("Price", null, tierPrice.Price.ToString(culture)); + writer.Write("TierPriceId", 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(); @@ -359,26 +376,26 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo foreach (var attribute in product.ProductVariantAttributes) { writer.WriteStartElement("ProductVariantAttribute"); - writer.WriteElementString("ProductVariantAttributeId", null, attribute.Id.ToString()); - writer.WriteElementString("ProductAttributeId", null, attribute.ProductAttributeId.ToString()); - writer.WriteElementString("TextPrompt", null, attribute.TextPrompt.RemoveInvalidXmlChars()); - writer.WriteElementString("IsRequired", null, attribute.IsRequired.ToString()); - writer.WriteElementString("AttributeControlTypeId", null, attribute.AttributeControlTypeId.ToString()); - writer.WriteElementString("DisplayOrder", null, attribute.DisplayOrder.ToString()); + writer.Write("ProductVariantAttributeId", attribute.Id.ToString()); + writer.Write("ProductAttributeId", attribute.ProductAttributeId.ToString()); + writer.Write("TextPrompt", attribute.TextPrompt.RemoveInvalidXmlChars()); + writer.Write("IsRequired", attribute.IsRequired.ToString()); + writer.Write("AttributeControlTypeId", attribute.AttributeControlTypeId.ToString()); + writer.Write("DisplayOrder", attribute.DisplayOrder.ToString()); writer.WriteStartElement("ProductVariantAttributeValues"); foreach (var attributeValue in attribute.ProductVariantAttributeValues) { writer.WriteStartElement("ProductVariantAttributeValue"); - writer.WriteElementString("ProductVariantAttributeValueId", null, attributeValue.Id.ToString()); - writer.WriteElementString("Name", null, attributeValue.Name.RemoveInvalidXmlChars()); - writer.WriteElementString("PriceAdjustment", null, attributeValue.PriceAdjustment.ToString(culture)); - writer.WriteElementString("WeightAdjustment", null, attributeValue.WeightAdjustment.ToString(culture)); - writer.WriteElementString("IsPreSelected", null, attributeValue.IsPreSelected.ToString()); - writer.WriteElementString("DisplayOrder", null, attributeValue.DisplayOrder.ToString()); - writer.WriteElementString("ValueTypeId", null, attributeValue.ValueTypeId.ToString()); - writer.WriteElementString("LinkedProductId", null, attributeValue.LinkedProductId.ToString()); - writer.WriteElementString("Quantity", null, attributeValue.Quantity.ToString()); + writer.Write("ProductVariantAttributeValueId", attributeValue.Id.ToString()); + writer.Write("Name", attributeValue.Name.RemoveInvalidXmlChars()); + writer.Write("PriceAdjustment", attributeValue.PriceAdjustment.ToString(culture)); + writer.Write("WeightAdjustment", attributeValue.WeightAdjustment.ToString(culture)); + writer.Write("IsPreSelected", attributeValue.IsPreSelected.ToString()); + writer.Write("DisplayOrder", attributeValue.DisplayOrder.ToString()); + writer.Write("ValueTypeId", attributeValue.ValueTypeId.ToString()); + writer.Write("LinkedProductId", attributeValue.LinkedProductId.ToString()); + writer.Write("Quantity", attributeValue.Quantity.ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); @@ -392,28 +409,28 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo { writer.WriteStartElement("ProductVariantAttributeCombination"); - writer.WriteElementString("ProductVariantAttributeCombinationId", null, combination.Id.ToString()); - writer.WriteElementString("AllowOutOfStockOrders", null, combination.AllowOutOfStockOrders.ToString()); - writer.WriteElementString("StockQuantity", null, combination.StockQuantity.ToString()); - writer.WriteElementString("AssignedPictureIds", null, combination.AssignedPictureIds); + writer.Write("ProductVariantAttributeCombinationId", combination.Id.ToString()); + writer.Write("AllowOutOfStockOrders", combination.AllowOutOfStockOrders.ToString()); + writer.Write("StockQuantity", combination.StockQuantity.ToString()); + writer.Write("AssignedPictureIds", combination.AssignedPictureIds); writer.WriteStartElement("AttributesXml"); writer.WriteCData(combination.AttributesXml); writer.WriteEndElement(); // AttributesXml - writer.WriteElementString("IsActive", null, combination.IsActive.ToString()); - //xmlWriter.WriteElementString("IsDefaultCombination", null, combination.IsDefaultCombination.ToString()); - writer.WriteElementString("BasePriceAmount", null, combination.BasePriceAmount.HasValue ? combination.BasePriceAmount.Value.ToString(culture) : ""); - writer.WriteElementString("BasePriceBaseAmount", null, combination.BasePriceBaseAmount.HasValue ? combination.BasePriceBaseAmount.Value.ToString() : ""); - writer.WriteElementString("DeliveryTimeId", null, combination.DeliveryTimeId.HasValue ? combination.DeliveryTimeId.Value.ToString() : ""); - writer.WriteElementString("Length", null, combination.Length.HasValue ? combination.Length.Value.ToString(culture) : ""); - writer.WriteElementString("Width", null, combination.Width.HasValue ? combination.Width.Value.ToString(culture) : ""); - writer.WriteElementString("Height", null, combination.Height.HasValue ? combination.Height.Value.ToString(culture) : ""); - writer.WriteElementString("Height", null, combination.Height.HasValue ? combination.Height.Value.ToString(culture) : ""); - writer.WriteElementString("Gtin", null, combination.Gtin); - writer.WriteElementString("Sku", null, combination.Sku); - writer.WriteElementString("ManufacturerPartNumber", null, combination.ManufacturerPartNumber); - writer.WriteElementString("Price", null, combination.Price.HasValue ? combination.Price.Value.ToString(culture) : ""); + writer.Write("IsActive", combination.IsActive.ToString()); + //xmlWriter.Write("IsDefaultCombination", combination.IsDefaultCombination.ToString()); + 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("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("Height", combination.Height.HasValue ? combination.Height.Value.ToString(culture) : ""); + writer.Write("Gtin", combination.Gtin); + writer.Write("Sku", combination.Sku); + writer.Write("ManufacturerPartNumber", combination.ManufacturerPartNumber); + writer.Write("Price", combination.Price.HasValue ? combination.Price.Value.ToString(culture) : ""); writer.WriteEndElement(); // ProductVariantAttributeCombination } @@ -423,15 +440,15 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo foreach (var productPicture in product.ProductPictures) { writer.WriteStartElement("ProductPicture"); - writer.WriteElementString("ProductPictureId", null, productPicture.Id.ToString()); - writer.WriteElementString("DisplayOrder", null, productPicture.DisplayOrder.ToString()); - - writer.WriteElementString("PictureId", null, productPicture.PictureId.ToString()); - writer.WriteElementString("SeoFilename", null, productPicture.Picture.SeoFilename); - writer.WriteElementString("MimeType", null, productPicture.Picture.MimeType); - writer.WriteElementString("ThumbImageUrl", null, _pictureService.GetPictureUrl(productPicture.Picture, _mediaSettings.ProductThumbPictureSize, false)); - writer.WriteElementString("ImageUrl", null, _pictureService.GetPictureUrl(productPicture.Picture, _mediaSettings.ProductDetailsPictureSize, false)); - writer.WriteElementString("FullSizeImageUrl", null, _pictureService.GetPictureUrl(productPicture.Picture, 0, false)); + writer.Write("ProductPictureId", productPicture.Id.ToString()); + writer.Write("DisplayOrder", productPicture.DisplayOrder.ToString()); + + writer.Write("PictureId", productPicture.PictureId.ToString()); + writer.Write("SeoFilename", productPicture.Picture.SeoFilename); + writer.Write("MimeType", productPicture.Picture.MimeType); + writer.Write("ThumbImageUrl", _pictureService.GetPictureUrl(productPicture.Picture, _mediaSettings.ProductThumbPictureSize, false)); + writer.Write("ImageUrl", _pictureService.GetPictureUrl(productPicture.Picture, _mediaSettings.ProductDetailsPictureSize, false)); + writer.Write("FullSizeImageUrl", _pictureService.GetPictureUrl(productPicture.Picture, 0, false)); writer.WriteEndElement(); } writer.WriteEndElement(); @@ -443,10 +460,10 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo foreach (var productCategory in productCategories) { writer.WriteStartElement("ProductCategory"); - writer.WriteElementString("ProductCategoryId", null, productCategory.Id.ToString()); - writer.WriteElementString("CategoryId", null, productCategory.CategoryId.ToString()); - writer.WriteElementString("IsFeaturedProduct", null, productCategory.IsFeaturedProduct.ToString()); - writer.WriteElementString("DisplayOrder", null, productCategory.DisplayOrder.ToString()); + writer.Write("ProductCategoryId", productCategory.Id.ToString()); + writer.Write("CategoryId", productCategory.CategoryId.ToString()); + writer.Write("IsFeaturedProduct", productCategory.IsFeaturedProduct.ToString()); + writer.Write("DisplayOrder", productCategory.DisplayOrder.ToString()); writer.WriteEndElement(); } } @@ -458,20 +475,32 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo { foreach (var productManufacturer in productManufacturers) { + var manu = productManufacturer.Manufacturer; writer.WriteStartElement("ProductManufacturer"); - writer.WriteElementString("ProductManufacturerId", null, productManufacturer.Id.ToString()); - writer.WriteElementString("ManufacturerId", null, productManufacturer.ManufacturerId.ToString()); - writer.WriteElementString("IsFeaturedProduct", null, productManufacturer.IsFeaturedProduct.ToString()); - writer.WriteElementString("DisplayOrder", null, productManufacturer.DisplayOrder.ToString()); + writer.Write("ProductManufacturerId", productManufacturer.Id.ToString()); + writer.Write("ManufacturerId", productManufacturer.ManufacturerId.ToString()); + writer.Write("IsFeaturedProduct", productManufacturer.IsFeaturedProduct.ToString()); + writer.Write("DisplayOrder", productManufacturer.DisplayOrder.ToString()); writer.WriteStartElement("Manufacturer"); - writer.WriteElementString("Name", null, productManufacturer.Manufacturer.Name); - writer.WriteElementString("SeName", null, productManufacturer.Manufacturer.GetSeName(0, true, false)); - writer.WriteElementString("Description", null, productManufacturer.Manufacturer.Description.RemoveInvalidXmlChars()); - writer.WriteElementString("MetaKeywords", null, productManufacturer.Manufacturer.MetaKeywords.RemoveInvalidXmlChars()); - writer.WriteElementString("MetaDescription", null, productManufacturer.Manufacturer.MetaDescription.RemoveInvalidXmlChars()); - writer.WriteElementString("MetaTitle", null, productManufacturer.Manufacturer.MetaTitle.RemoveInvalidXmlChars()); + writer.Write("Name", manu.Name); + writer.Write("SeName", manu.GetSeName(0, true, false)); + writer.Write("Description", manu.Description.RemoveInvalidXmlChars()); + writer.Write("MetaKeywords", manu.MetaKeywords.RemoveInvalidXmlChars()); + writer.Write("MetaDescription", manu.MetaDescription.RemoveInvalidXmlChars()); + writer.Write("MetaTitle", manu.MetaTitle.RemoveInvalidXmlChars()); + + 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.RemoveInvalidXmlChars(), lang.Id, false, false), lang); + writer.Write("MetaKeywords", manu.GetLocalized(x => x.MetaKeywords.RemoveInvalidXmlChars(), lang.Id, false, false), lang); + writer.Write("MetaDescription", manu.GetLocalized(x => x.MetaDescription.RemoveInvalidXmlChars(), lang.Id, false, false), lang); + writer.Write("MetaTitle", manu.GetLocalized(x => x.MetaTitle.RemoveInvalidXmlChars(), lang.Id, false, false), lang); + }); + writer.WriteEndElement(); writer.WriteEndElement(); @@ -483,11 +512,11 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo foreach (var productSpecificationAttribute in product.ProductSpecificationAttributes) { writer.WriteStartElement("ProductSpecificationAttribute"); - writer.WriteElementString("ProductSpecificationAttributeId", null, productSpecificationAttribute.Id.ToString()); - writer.WriteElementString("SpecificationAttributeOptionId", null, productSpecificationAttribute.SpecificationAttributeOptionId.ToString()); - writer.WriteElementString("AllowFiltering", null, productSpecificationAttribute.AllowFiltering.ToString()); - writer.WriteElementString("ShowOnProductPage", null, productSpecificationAttribute.ShowOnProductPage.ToString()); - writer.WriteElementString("DisplayOrder", null, productSpecificationAttribute.DisplayOrder.ToString()); + writer.Write("ProductSpecificationAttributeId", productSpecificationAttribute.Id.ToString()); + writer.Write("SpecificationAttributeOptionId", productSpecificationAttribute.SpecificationAttributeOptionId.ToString()); + writer.Write("AllowFiltering", productSpecificationAttribute.AllowFiltering.ToString()); + writer.Write("ShowOnProductPage", productSpecificationAttribute.ShowOnProductPage.ToString()); + writer.Write("DisplayOrder", productSpecificationAttribute.DisplayOrder.ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); @@ -497,49 +526,23 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo foreach (var bundleItem in bundleItems.Select(x => x.Item)) { writer.WriteStartElement("ProductBundleItem"); - writer.WriteElementString("ProductId", null, bundleItem.ProductId.ToString()); - writer.WriteElementString("BundleProductId", null, bundleItem.BundleProductId.ToString()); - writer.WriteElementString("Quantity", null, bundleItem.Quantity.ToString()); - writer.WriteElementString("Discount", null, bundleItem.Discount.HasValue ? bundleItem.Discount.Value.ToString(culture) : ""); - writer.WriteElementString("DiscountPercentage", null, bundleItem.DiscountPercentage.ToString()); - writer.WriteElementString("Name", null, bundleItem.GetLocalizedName()); - writer.WriteElementString("ShortDescription", null, bundleItem.ShortDescription.RemoveInvalidXmlChars()); - writer.WriteElementString("FilterAttributes", null, bundleItem.FilterAttributes.ToString()); - writer.WriteElementString("HideThumbnail", null, bundleItem.HideThumbnail.ToString()); - writer.WriteElementString("Visible", null, bundleItem.Visible.ToString()); - writer.WriteElementString("Published", null, bundleItem.Published.ToString()); - writer.WriteElementString("DisplayOrder", null, bundleItem.DisplayOrder.ToString()); - writer.WriteElementString("CreatedOnUtc", null, bundleItem.CreatedOnUtc.ToString(culture)); - writer.WriteElementString("UpdatedOnUtc", null, bundleItem.UpdatedOnUtc.ToString(culture)); + 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.RemoveInvalidXmlChars()); + 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(); - - writer.WriteStartElement("LocalizedProperties"); - foreach (var language in context.Languages) - { - writer.WriteStartElement("LocalizedProperty"); - - writer.WriteElementString("Name", null, product.GetLocalized(x => x.Name, language.Id, false, false)); - writer.WriteElementString("ShortDescription", null, product.GetLocalized(x => x.ShortDescription, language.Id, false, false)); - writer.WriteElementString("FullDescription", null, product.GetLocalized(x => x.FullDescription, language.Id, false, false)); - writer.WriteElementString("MetaKeywords", null, product.GetLocalized(x => x.MetaKeywords, language.Id, false, false)); - writer.WriteElementString("MetaDescription", null, product.GetLocalized(x => x.MetaDescription, language.Id, false, false)); - writer.WriteElementString("MetaTitle", null, product.GetLocalized(x => x.MetaTitle, language.Id, false, false)); - writer.WriteElementString("SEName", null, product.GetSeName(language.Id, false, false)); - writer.WriteElementString("BundleTitleText", null, product.GetLocalized(x => x.BundleTitleText, language.Id, false, false)); - - writer.WriteStartElement("Language"); - writer.WriteElementString("Id", null, language.Id.ToString()); - writer.WriteElementString("Name", null, language.Name); - writer.WriteElementString("LanguageCulture", null, language.LanguageCulture); - writer.WriteElementString("UniqueSeoCode", null, language.UniqueSeoCode); - writer.WriteElementString("Published", null, language.Published.ToString()); - writer.WriteEndElement(); - - writer.WriteEndElement(); // LocalizedProperty - } - writer.WriteEndElement(); // LocalizedProperties } /// diff --git a/src/Presentation/SmartStore.Web.Framework/Mvc/CompressAttribute.cs b/src/Presentation/SmartStore.Web.Framework/Mvc/CompressAttribute.cs new file mode 100644 index 0000000000..76a4b6cb85 --- /dev/null +++ b/src/Presentation/SmartStore.Web.Framework/Mvc/CompressAttribute.cs @@ -0,0 +1,34 @@ +using System.IO.Compression; +using System.Web; +using System.Web.Mvc; + +namespace SmartStore.Web.Framework.Mvc +{ + public class CompressAttribute : ActionFilterAttribute + { + public bool PreferDeflate { get; set; } + + public override void OnActionExecuting(ActionExecutingContext filterContext) + { + var response = HttpContext.Current.Response; + string acceptEncoding = HttpContext.Current.Request.Headers["Accept-Encoding"].EmptyNull().ToLower(); + + if (acceptEncoding.Contains("gzip") && !(PreferDeflate && acceptEncoding.Contains("deflate"))) + { + response.Filter = new GZipStream(response.Filter, CompressionMode.Compress); + + response.Headers.Remove("Content-Encoding"); + response.AppendHeader("Content-Encoding", "gzip"); + } + else if (acceptEncoding.Contains("deflate")) + { + response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress); + + response.Headers.Remove("Content-Encoding"); + response.AppendHeader("Content-Encoding", "deflate"); + } + + //response.AppendHeader("Vary", "Content-Encoding"); + } + } +} diff --git a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj index e973b2f0a8..45a65602b7 100644 --- a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj +++ b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj @@ -245,6 +245,7 @@ + From 4282b6fbfdc8c82bdb477097678de974a9c58609 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 3 Feb 2015 15:33:12 +0100 Subject: [PATCH 0008/1256] More product data exported in xml export --- .../Extensions/XmlWriterExtensions.cs | 7 +- .../ExportImport/ExportManager.cs | 243 +++++++++++------- .../ExportImport/ImportManager.cs | 3 +- .../Media/IPictureService.cs | 3 +- .../Media/PictureService.cs | 15 +- 5 files changed, 172 insertions(+), 99 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Extensions/XmlWriterExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/XmlWriterExtensions.cs index 32796d6dbe..ef4241d821 100644 --- a/src/Libraries/SmartStore.Core/Extensions/XmlWriterExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/XmlWriterExtensions.cs @@ -1,5 +1,4 @@ using System; -using System.ComponentModel; using System.Xml; using SmartStore.Core.Domain.Localization; @@ -15,7 +14,9 @@ public static void WriteCData(this XmlWriter writer, string name, string value, writer.WriteStartElement(name); else writer.WriteStartElement(prefix, name, ns); + writer.WriteCData(value.RemoveInvalidXmlChars()); + writer.WriteEndElement(); } } @@ -48,9 +49,9 @@ public static void Write(this XmlWriter writer, string name, string value, Langu writer.WriteAttributeString("culture", language.LanguageCulture.EmptyNull().ToLower()); if (asCData) - writer.WriteCData(value); + writer.WriteCData(value.RemoveInvalidXmlChars()); else - writer.WriteString(value); + writer.WriteString(value.RemoveInvalidXmlChars()); writer.WriteEndElement(); } diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 2d2bd4bac5..61761dcd1b 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -137,6 +137,21 @@ protected virtual void WriteCategories(XmlWriter xmlWriter, int parentCategoryId writer.WriteEndElement(); }; + protected void WritePicture(XmlWriter writer, Picture picture) + { + if (picture != null) + { + writer.WriteStartElement("Picture"); + writer.Write("Id", picture.Id.ToString()); + writer.Write("SeoFileName", picture.SeoFilename); + writer.Write("MimeType", picture.MimeType); + writer.Write("ThumbImageUrl", _pictureService.GetPictureUrl(picture, _mediaSettings.ProductThumbPictureSize, false)); + writer.Write("ImageUrl", _pictureService.GetPictureUrl(picture, _mediaSettings.ProductDetailsPictureSize, false)); + writer.Write("FullSizeImageUrl", _pictureService.GetPictureUrl(picture, 0, false)); + writer.WriteEndElement(); + } + } + #endregion #region Methods @@ -239,19 +254,19 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo var productTemplate = context.ProductTemplates.FirstOrDefault(x => x.Id == product.ProductTemplateId); writer.Write("Id", product.Id.ToString()); - writer.Write("Name", product.Name.RemoveInvalidXmlChars()); + writer.Write("Name", product.Name); writer.Write("SeName", product.GetSeName(0, true, false)); - writer.Write("ShortDescription", product.ShortDescription.RemoveInvalidXmlChars(), null, true); - writer.Write("FullDescription", product.FullDescription.RemoveInvalidXmlChars(), null, true); + writer.Write("ShortDescription", product.ShortDescription, null, true); + writer.Write("FullDescription", product.FullDescription, null, true); - writer.Write("AdminComment", product.AdminComment.RemoveInvalidXmlChars()); + 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("MetaKeywords", product.MetaKeywords.RemoveInvalidXmlChars()); - writer.Write("MetaDescription", product.MetaDescription.RemoveInvalidXmlChars()); - writer.Write("MetaTitle", product.MetaTitle.RemoveInvalidXmlChars()); + 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()); @@ -281,7 +296,7 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.Write("HasSampleDownload", product.HasSampleDownload.ToString()); writer.Write("SampleDownloadId", product.SampleDownloadId.ToString()); writer.Write("HasUserAgreement", product.HasUserAgreement.ToString()); - writer.Write("UserAgreementText", product.UserAgreementText.RemoveInvalidXmlChars()); + writer.Write("UserAgreementText", product.UserAgreementText); writer.Write("IsRecurring", product.IsRecurring.ToString()); writer.Write("RecurringCycleLength", product.RecurringCycleLength.ToString()); writer.Write("RecurringCyclePeriodId", product.RecurringCyclePeriodId.ToString()); @@ -331,7 +346,7 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo 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.RemoveInvalidXmlChars()); + writer.Write("BundleTitleText", product.BundleTitleText); writer.Write("BundlePerItemPricing", product.BundlePerItemPricing.ToString()); writer.Write("BundlePerItemShipping", product.BundlePerItemShipping.ToString()); writer.Write("BundlePerItemShoppingCart", product.BundlePerItemShoppingCart.ToString()); @@ -342,14 +357,30 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo { 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).RemoveInvalidXmlChars(), lang, true); - writer.Write("FullDescription", product.GetLocalized(x => x.FullDescription, lang.Id, false, false).RemoveInvalidXmlChars(), lang, true); - writer.Write("MetaKeywords", product.GetLocalized(x => x.MetaKeywords, lang.Id, false, false).RemoveInvalidXmlChars(), lang); - writer.Write("MetaDescription", product.GetLocalized(x => x.MetaDescription, lang.Id, false, false).RemoveInvalidXmlChars(), lang); - writer.Write("MetaTitle", product.GetLocalized(x => x.MetaTitle, lang.Id, false, false).RemoveInvalidXmlChars(), 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); }); + 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) { @@ -363,7 +394,7 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo foreach (var tierPrice in product.TierPrices) { writer.WriteStartElement("TierPrice"); - writer.Write("TierPriceId", tierPrice.Id.ToString()); + 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()); @@ -373,82 +404,96 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.WriteEndElement(); writer.WriteStartElement("ProductAttributes"); - foreach (var attribute in product.ProductVariantAttributes) + foreach (var pva in product.ProductVariantAttributes) { - writer.WriteStartElement("ProductVariantAttribute"); - writer.Write("ProductVariantAttributeId", attribute.Id.ToString()); - writer.Write("ProductAttributeId", attribute.ProductAttributeId.ToString()); - writer.Write("TextPrompt", attribute.TextPrompt.RemoveInvalidXmlChars()); - writer.Write("IsRequired", attribute.IsRequired.ToString()); - writer.Write("AttributeControlTypeId", attribute.AttributeControlTypeId.ToString()); - writer.Write("DisplayOrder", attribute.DisplayOrder.ToString()); - writer.WriteStartElement("ProductVariantAttributeValues"); - - foreach (var attributeValue in attribute.ProductVariantAttributeValues) + 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.WriteStartElement("ProductVariantAttributeValue"); - writer.Write("ProductVariantAttributeValueId", attributeValue.Id.ToString()); - writer.Write("Name", attributeValue.Name.RemoveInvalidXmlChars()); - writer.Write("PriceAdjustment", attributeValue.PriceAdjustment.ToString(culture)); - writer.Write("WeightAdjustment", attributeValue.WeightAdjustment.ToString(culture)); - writer.Write("IsPreSelected", attributeValue.IsPreSelected.ToString()); - writer.Write("DisplayOrder", attributeValue.DisplayOrder.ToString()); - writer.Write("ValueTypeId", attributeValue.ValueTypeId.ToString()); - writer.Write("LinkedProductId", attributeValue.LinkedProductId.ToString()); - writer.Write("Quantity", attributeValue.Quantity.ToString()); - writer.WriteEndElement(); + 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) + { + 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(); + writer.WriteEndElement(); // AttributeValues - writer.WriteEndElement(); + writer.WriteEndElement(); // ProductAttribute } writer.WriteEndElement(); // ProductAttributes - writer.WriteStartElement("ProductVariantAttributeCombinations"); + writer.WriteStartElement("ProductAttributeCombinations"); foreach (var combination in product.ProductVariantAttributeCombinations) { - writer.WriteStartElement("ProductVariantAttributeCombination"); + writer.WriteStartElement("ProductAttributeCombination"); - writer.Write("ProductVariantAttributeCombinationId", combination.Id.ToString()); - writer.Write("AllowOutOfStockOrders", combination.AllowOutOfStockOrders.ToString()); + writer.Write("Id", combination.Id.ToString()); writer.Write("StockQuantity", combination.StockQuantity.ToString()); - writer.Write("AssignedPictureIds", combination.AssignedPictureIds); - - writer.WriteStartElement("AttributesXml"); - writer.WriteCData(combination.AttributesXml); - writer.WriteEndElement(); // AttributesXml - - writer.Write("IsActive", combination.IsActive.ToString()); - //xmlWriter.Write("IsDefaultCombination", combination.IsDefaultCombination.ToString()); - 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("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("Height", combination.Height.HasValue ? combination.Height.Value.ToString(culture) : ""); - writer.Write("Gtin", combination.Gtin); + 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()); - writer.WriteEndElement(); // ProductVariantAttributeCombination + writer.WriteStartElement("Pictures"); + foreach (int pictureId in combination.GetAssignedPictureIds()) + { + WritePicture(writer, _pictureService.GetPictureById(pictureId)); + } + writer.WriteEndElement(); // Pictures + + writer.WriteEndElement(); // ProductAttributeCombination } - writer.WriteEndElement(); // ProductVariantAttributeCombinations + writer.WriteEndElement(); // ProductAttributeCombinations writer.WriteStartElement("ProductPictures"); foreach (var productPicture in product.ProductPictures) { writer.WriteStartElement("ProductPicture"); - writer.Write("ProductPictureId", productPicture.Id.ToString()); + writer.Write("Id", productPicture.Id.ToString()); writer.Write("DisplayOrder", productPicture.DisplayOrder.ToString()); - writer.Write("PictureId", productPicture.PictureId.ToString()); - writer.Write("SeoFilename", productPicture.Picture.SeoFilename); - writer.Write("MimeType", productPicture.Picture.MimeType); - writer.Write("ThumbImageUrl", _pictureService.GetPictureUrl(productPicture.Picture, _mediaSettings.ProductThumbPictureSize, false)); - writer.Write("ImageUrl", _pictureService.GetPictureUrl(productPicture.Picture, _mediaSettings.ProductDetailsPictureSize, false)); - writer.Write("FullSizeImageUrl", _pictureService.GetPictureUrl(productPicture.Picture, 0, false)); + WritePicture(writer, productPicture.Picture); + writer.WriteEndElement(); } writer.WriteEndElement(); @@ -460,10 +505,13 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo foreach (var productCategory in productCategories) { writer.WriteStartElement("ProductCategory"); - writer.Write("ProductCategoryId", productCategory.Id.ToString()); - writer.Write("CategoryId", productCategory.CategoryId.ToString()); writer.Write("IsFeaturedProduct", productCategory.IsFeaturedProduct.ToString()); writer.Write("DisplayOrder", productCategory.DisplayOrder.ToString()); + + writer.WriteStartElement("Category"); + writer.Write("Id", productCategory.Category.Id.ToString()); + writer.WriteEndElement(); + writer.WriteEndElement(); } } @@ -479,26 +527,26 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.WriteStartElement("ProductManufacturer"); writer.Write("ProductManufacturerId", productManufacturer.Id.ToString()); - writer.Write("ManufacturerId", productManufacturer.ManufacturerId.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.RemoveInvalidXmlChars()); - writer.Write("MetaKeywords", manu.MetaKeywords.RemoveInvalidXmlChars()); - writer.Write("MetaDescription", manu.MetaDescription.RemoveInvalidXmlChars()); - writer.Write("MetaTitle", manu.MetaTitle.RemoveInvalidXmlChars()); + writer.Write("Description", manu.Description); + writer.Write("MetaKeywords", manu.MetaKeywords); + writer.Write("MetaDescription", manu.MetaDescription); + writer.Write("MetaTitle", manu.MetaTitle); 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.RemoveInvalidXmlChars(), lang.Id, false, false), lang); - writer.Write("MetaKeywords", manu.GetLocalized(x => x.MetaKeywords.RemoveInvalidXmlChars(), lang.Id, false, false), lang); - writer.Write("MetaDescription", manu.GetLocalized(x => x.MetaDescription.RemoveInvalidXmlChars(), lang.Id, false, false), lang); - writer.Write("MetaTitle", manu.GetLocalized(x => x.MetaTitle.RemoveInvalidXmlChars(), 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(); @@ -509,15 +557,36 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.WriteEndElement(); writer.WriteStartElement("ProductSpecificationAttributes"); - foreach (var productSpecificationAttribute in product.ProductSpecificationAttributes) + foreach (var pca in product.ProductSpecificationAttributes) { writer.WriteStartElement("ProductSpecificationAttribute"); - writer.Write("ProductSpecificationAttributeId", productSpecificationAttribute.Id.ToString()); - writer.Write("SpecificationAttributeOptionId", productSpecificationAttribute.SpecificationAttributeOptionId.ToString()); - writer.Write("AllowFiltering", productSpecificationAttribute.AllowFiltering.ToString()); - writer.Write("ShowOnProductPage", productSpecificationAttribute.ShowOnProductPage.ToString()); - writer.Write("DisplayOrder", productSpecificationAttribute.DisplayOrder.ToString()); - writer.WriteEndElement(); + 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(); @@ -532,7 +601,7 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo 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.RemoveInvalidXmlChars()); + writer.Write("ShortDescription", bundleItem.ShortDescription); writer.Write("FilterAttributes", bundleItem.FilterAttributes.ToString()); writer.Write("HideThumbnail", bundleItem.HideThumbnail.ToString()); writer.Write("Visible", bundleItem.Visible.ToString()); diff --git a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs index b759b01b41..414cb5cf68 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs @@ -674,6 +674,7 @@ private void ProcessProductPictures(ICollection> batch, Impor _rsProductPicture.AutoCommitEnabled = true; ProductPicture lastInserted = null; + int equalPictureId = 0; foreach (var row in batch) { @@ -695,7 +696,7 @@ private void ProcessProductPictures(ICollection> batch, Impor continue; var currentPictures = _rsProductPicture.Expand(_rsProductPicture.TableUntracked, x => x.Picture).Where(x => x.ProductId == row.Entity.Id).Select(x => x.Picture).ToList(); - var pictureBinary = _pictureService.FindEqualPicture(picture, currentPictures); + var pictureBinary = _pictureService.FindEqualPicture(picture, currentPictures, out equalPictureId); if (pictureBinary != null && pictureBinary.Length > 0) { diff --git a/src/Libraries/SmartStore.Services/Media/IPictureService.cs b/src/Libraries/SmartStore.Services/Media/IPictureService.cs index 0c89008b4d..2f7bda0d13 100644 --- a/src/Libraries/SmartStore.Services/Media/IPictureService.cs +++ b/src/Libraries/SmartStore.Services/Media/IPictureService.cs @@ -23,8 +23,9 @@ public partial interface IPictureService /// /// The picture to find a duplicate for /// The sequence of product pictures to seek within for duplicates + /// Id of equal picture if any /// The picture binary for path when no picture equals in the sequence, null otherwise. - byte[] FindEqualPicture(string path, IEnumerable productPictures); + byte[] FindEqualPicture(string path, IEnumerable productPictures, out int equalPictureId); /// /// Gets the loaded picture binary depending on picture storage settings diff --git a/src/Libraries/SmartStore.Services/Media/PictureService.cs b/src/Libraries/SmartStore.Services/Media/PictureService.cs index 3cfa809d54..3ef4aaf84b 100644 --- a/src/Libraries/SmartStore.Services/Media/PictureService.cs +++ b/src/Libraries/SmartStore.Services/Media/PictureService.cs @@ -140,9 +140,11 @@ public virtual byte[] ValidatePicture(byte[] pictureBinary) /// /// The picture to find a duplicate for /// The sequence of product pictures to seek within for duplicates + /// Id of equal picture if any /// The picture binary for path when no picture equals in the sequence, null otherwise. - public byte[] FindEqualPicture(string path, IEnumerable productPictures) + public byte[] FindEqualPicture(string path, IEnumerable productPictures, out int equalPictureId) { + equalPictureId = 0; try { var myBuffer = File.ReadAllBytes(path); @@ -150,15 +152,14 @@ public byte[] FindEqualPicture(string path, IEnumerable productPictures foreach (var picture in productPictures) { var otherBuffer = LoadPictureBinary(picture); + using (var myStream = new MemoryStream(myBuffer)) + using (var otherStream = new MemoryStream(otherBuffer)) { - using (var otherStream = new MemoryStream(otherBuffer)) + if (myStream.ContentsEqual(otherStream)) { - var equals = myStream.ContentsEqual(otherStream); - if (equals) - { - return null; - } + equalPictureId = picture.Id; + return null; } } } From a2400e7f0c410269658c107775858391cd8970cf Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 23 Mar 2015 20:38:01 +0100 Subject: [PATCH 0009/1256] Updated gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ce0460f432..601e434200 100644 --- a/.gitignore +++ b/.gitignore @@ -202,6 +202,7 @@ Kopie von* /src/Presentation/SmartStore.Web/App_Data/_temp/ /src/Presentation/SmartStore.Web/App_Data/Settings.txt /src/Presentation/SmartStore.Web/App_Data/InstalledPlugins.txt +/src/Presentation/SmartStore.Web/App_Data/Licensing.key /src/Presentation/SmartStore.Web/Media # Import/Export From 5134ff3eb2e4b31b4b232f151a5715454d842597 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 31 Mar 2015 12:05:21 +0200 Subject: [PATCH 0010/1256] ShopConnector: Fixed some post merging issues --- .../SmartStore.Licensing.dll | Bin 167936 -> 168448 bytes .../Extensions/XPathExtensions.cs | 4 +-- .../ExportImport/ExportManager.cs | 34 ++++++++++++++++-- .../Media/PictureService.cs | 1 + .../SmartStore.Web.Framework/AppPath.cs | 2 +- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/lib/SmartStore.Licensing/SmartStore.Licensing.dll b/lib/SmartStore.Licensing/SmartStore.Licensing.dll index dff31a3c267b614d1af0ccb5c8fa54470956436f..47363c168976240c24eb0ef28ed996d8644fc66f 100644 GIT binary patch literal 168448 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

ALnI|5tD7+yr9$nLr2>Z!LqHl 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

-&Z&Mi|9iqvvA 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%0A&JyiP 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 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(); + } + + if (product.QuantityUnit != null) + { + writer.WriteStartElement("QuantityUnit"); + writer.Write("Id", product.QuantityUnit.Id.ToString()); + writer.Write("Name", product.QuantityUnit.Name); + writer.Write("Description", product.QuantityUnit.Description); + writer.Write("DisplayLocale", product.QuantityUnit.DisplayLocale); + writer.Write("DisplayOrder", product.QuantityUnit.DisplayOrder.ToString()); + writer.Write("IsDefault", product.QuantityUnit.IsDefault.ToString()); + WriteLocalized(writer, context, lang => + { + writer.Write("Name", product.QuantityUnit.GetLocalized(x => x.Name, lang.Id, false, false), lang); + writer.Write("Description", product.QuantityUnit.GetLocalized(x => x.Description, lang.Id, false, false), lang); + }); + writer.WriteEndElement(); + } + writer.WriteStartElement("ProductTags"); foreach (var tag in product.ProductTags) { @@ -1959,7 +1990,6 @@ public virtual string ExportCustomersToXml(IList customers) return stringWriter.ToString(); } - #endregion } diff --git a/src/Libraries/SmartStore.Services/Media/PictureService.cs b/src/Libraries/SmartStore.Services/Media/PictureService.cs index 3c53fa4e12..662a74a8fe 100644 --- a/src/Libraries/SmartStore.Services/Media/PictureService.cs +++ b/src/Libraries/SmartStore.Services/Media/PictureService.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; +using System.Threading.Tasks; using ImageResizer; using SmartStore.Core; using SmartStore.Core.Data; diff --git a/src/Presentation/SmartStore.Web.Framework/AppPath.cs b/src/Presentation/SmartStore.Web.Framework/AppPath.cs index 38fd384ce4..d7468f8cb9 100644 --- a/src/Presentation/SmartStore.Web.Framework/AppPath.cs +++ b/src/Presentation/SmartStore.Web.Framework/AppPath.cs @@ -134,7 +134,7 @@ public static void CopyDirectory(DirectoryInfo source, DirectoryInfo target, boo /// A directory path public static void ClearDirectory(string directoryPath, bool selfToo) { - if (directoryPath.IsNullOrEmpty()) + if (directoryPath.IsEmpty()) return; try From 2f1ee705084f88907fa224081b31971cad36963a Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 1 Apr 2015 21:16:11 +0200 Subject: [PATCH 0011/1256] ShopConnector: Testing import, make product grid filterable via URL --- .../ExportImport/ExportManager.cs | 22 +++++++++------ .../Controllers/ProductController.cs | 27 ++----------------- .../Administration/Views/Product/List.cshtml | 4 +-- .../ExportImport/ExportManagerTests.cs | 6 +++-- 4 files changed, 22 insertions(+), 37 deletions(-) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index abc2a688a2..9fed9462af 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -14,6 +14,7 @@ using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Domain.Stores; using SmartStore.Core.Logging; using SmartStore.Services.Catalog; using SmartStore.Services.Common; @@ -40,6 +41,7 @@ public partial class ExportManager : IExportManager private readonly INewsLetterSubscriptionService _newsLetterSubscriptionService; private readonly ILanguageService _languageService; private readonly MediaSettings _mediaSettings; + private readonly ICommonServices _commonServices; #endregion @@ -52,7 +54,8 @@ public ExportManager(ICategoryService categoryService, IPictureService pictureService, INewsLetterSubscriptionService newsLetterSubscriptionService, ILanguageService languageService, - MediaSettings mediaSettings) + MediaSettings mediaSettings, + ICommonServices commonServices) { this._categoryService = categoryService; this._manufacturerService = manufacturerService; @@ -62,6 +65,7 @@ public ExportManager(ICategoryService categoryService, this._newsLetterSubscriptionService = newsLetterSubscriptionService; this._languageService = languageService; this._mediaSettings = mediaSettings; + this._commonServices = commonServices; Logger = NullLogger.Instance; } @@ -137,7 +141,7 @@ protected virtual void WriteCategories(XmlWriter xmlWriter, int parentCategoryId writer.WriteEndElement(); }; - protected void WritePicture(XmlWriter writer, Picture picture) + protected void WritePicture(XmlWriter writer, XmlExportContext context, Picture picture) { if (picture != null) { @@ -145,9 +149,9 @@ protected void WritePicture(XmlWriter writer, Picture picture) writer.Write("Id", picture.Id.ToString()); writer.Write("SeoFileName", picture.SeoFilename); writer.Write("MimeType", picture.MimeType); - writer.Write("ThumbImageUrl", _pictureService.GetPictureUrl(picture, _mediaSettings.ProductThumbPictureSize, false)); - writer.Write("ImageUrl", _pictureService.GetPictureUrl(picture, _mediaSettings.ProductDetailsPictureSize, false)); - writer.Write("FullSizeImageUrl", _pictureService.GetPictureUrl(picture, 0, false)); + writer.Write("ThumbImageUrl", _pictureService.GetPictureUrl(picture, _mediaSettings.ProductThumbPictureSize, false, storeLocation: context.Store.Url)); + writer.Write("ImageUrl", _pictureService.GetPictureUrl(picture, _mediaSettings.ProductDetailsPictureSize, false, storeLocation: context.Store.Url)); + writer.Write("FullSizeImageUrl", _pictureService.GetPictureUrl(picture, 0, false, storeLocation: context.Store.Url)); writer.WriteEndElement(); } } @@ -508,7 +512,7 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.WriteStartElement("Pictures"); foreach (int pictureId in combination.GetAssignedPictureIds()) { - WritePicture(writer, _pictureService.GetPictureById(pictureId)); + WritePicture(writer, context, _pictureService.GetPictureById(pictureId)); } writer.WriteEndElement(); // Pictures @@ -523,7 +527,7 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.Write("Id", productPicture.Id.ToString()); writer.Write("DisplayOrder", productPicture.DisplayOrder.ToString()); - WritePicture(writer, productPicture.Picture); + WritePicture(writer, context, productPicture.Picture); writer.WriteEndElement(); } @@ -657,7 +661,8 @@ public virtual string ExportProductsToXml(IList products) var context = new XmlExportContext() { ProductTemplates = _productTemplateService.GetAllProductTemplates(), - Languages = _languageService.GetAllLanguages(true) + Languages = _languageService.GetAllLanguages(true), + Store = _commonServices.StoreContext.CurrentStore }; foreach (var product in products) @@ -1998,5 +2003,6 @@ public class XmlExportContext { public IList ProductTemplates { get; set; } public IList Languages { get; set; } + public Store Store { get; set; } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index faa2829d0d..6ad9380536 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -878,38 +878,15 @@ public ActionResult Index() return RedirectToAction("List"); } - public ActionResult List() + public ActionResult List(ProductListModel model) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); - var ctx = new ProductSearchContext(); - ctx.LanguageId = _workContext.WorkingLanguage.Id; - ctx.OrderBy = ProductSortingEnum.Position; - ctx.PageSize = _adminAreaSettings.GridPageSize; - ctx.ShowHidden = true; - - var products = _productService.SearchProducts(ctx); - - var model = new ProductListModel(); model.DisplayProductPictures = _adminAreaSettings.DisplayProductPictures; model.DisplayPdfExport = _pdfSettings.Enabled; model.GridPageSize = _adminAreaSettings.GridPageSize; - model.Products = new GridModel - { - Data = products.Select(x => - { - var productModel = x.ToModel(); - PrepareProductPictureThumbnailModel(productModel, x); - - productModel.ProductTypeName = x.GetProductTypeLabel(_localizationService); - - return productModel; - }), - Total = products.TotalCount - }; - //categories var allCategories = _categoryService.GetAllCategories(showHidden: true); var mappedCategories = allCategories.ToDictionary(x => x.Id); @@ -990,7 +967,7 @@ public ActionResult GoToSku(ProductListModel model) return RedirectToAction("Edit", "Product", new { id = product.Id }); //not found - return List(); + return List(model); } //create product diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml index 165c2f333b..78c68219b4 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml @@ -159,7 +159,7 @@ diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/Navbar.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/Navbar.cshtml index e0834c2570..065d85f61b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/Navbar.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/Navbar.cshtml @@ -1,16 +1,17 @@ -@using SmartStore.Services.Customers; +@using SmartStore.Core.Domain.Stores; +@using SmartStore.Services.Customers; @using SmartStore.Services.Stores; @{ var currentCustomer = this.WorkContext.CurrentCustomer; var currentLanguage = this.WorkContext.WorkingLanguage; - var usernamesEnabled = EngineContext.Current.Resolve().UsernamesEnabled; - var userName = usernamesEnabled ? currentCustomer.Username : currentCustomer.Email; - var stores = EngineContext.Current.Resolve().GetAllStores(); + var userName = (string)ViewBag.UserName; + var stores = (IList)ViewBag.Stores; string currentLanguageCode = currentLanguage.UniqueSeoCode.EmptyNull().ToLower(); string communityUrl = (currentLanguageCode == "de" ? "http://community.smartstore.com" : "http://community.smartstore.com/index.php?/&k=880ea6a14ea49e853634fbdc5015a024&setlanguage=1&cal_id=&langid=1"); + var checkUpdateResult = (CheckUpdateResult)ViewBag.CheckUpdateResult; } } -
+
- @(Html.Telerik().Grid(Model.Products.Data) + @(Html.Telerik().Grid() .Name("products-grid") .Columns(columns => { @@ -204,7 +204,7 @@ .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") .Title(T("Admin.Common.Edit").Text); }) - .Pageable(settings => settings.Total(Model.Products.Total).PageSize(Model.GridPageSize).Position(GridPagerPosition.Both)) + .Pageable(settings => settings.PageSize(Model.GridPageSize).Position(GridPagerPosition.Both)) .DataBinding(dataBinding => dataBinding.Ajax().Select("ProductList", "Product")) .ClientEvents(events => events.OnDataBinding("productsGrid_onDataBinding").OnDataBound("productsGrid_onDataBound")) .EnableCustomBinding(true) diff --git a/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs b/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs index 06ac5332ee..d11de81706 100644 --- a/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs +++ b/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs @@ -34,6 +34,7 @@ public class ExportManagerTests : ServiceTest IExportManager _exportManager; ILanguageService _languageService; MediaSettings _mediaSettings; + ICommonServices _commonServices; [SetUp] public new void SetUp() @@ -46,9 +47,10 @@ public class ExportManagerTests : ServiceTest _newsLetterSubscriptionService = MockRepository.GenerateMock(); _languageService = MockRepository.GenerateMock(); _mediaSettings = MockRepository.GenerateMock(); + _commonServices = MockRepository.GenerateMock(); - _exportManager = new ExportManager(_categoryService, - _manufacturerService, _productService, _productTemplateService, _pictureService, _newsLetterSubscriptionService, _languageService, _mediaSettings); + _exportManager = new ExportManager(_categoryService, _manufacturerService, _productService, _productTemplateService, _pictureService, + _newsLetterSubscriptionService, _languageService, _mediaSettings, _commonServices); } //[Test] From 53fcc3ffc665476baeb0d6f0c497bd5f3669a870 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 3 Apr 2015 00:35:52 +0200 Subject: [PATCH 0012/1256] Implemented update checker (TODO: Localization) --- .../SmartStore.Core/Async/AsyncRunner.cs | 123 ++++++++- .../SmartStore.Core/Caching/AspNetCache.cs | 3 +- .../SmartStore.Core/Caching/StaticCache.cs | 5 +- .../AppInitScheduledTasksEvent.cs | 2 +- .../Common/GenericAttributeService.cs | 3 +- .../Seo/SitemapGenerator.cs | 2 +- .../SmartStore.Services/Tasks/Job.cs | 2 +- .../SmartStore.Services/Tasks/TaskManager.cs | 9 +- .../SmartStore.Services/Tasks/TaskThread.cs | 2 +- .../Administration/Content/admin.less | 13 +- .../Controllers/CommonController.cs | 236 +++++++++++------- .../Controllers/HomeController.cs | 3 +- .../Controllers/ScheduleTaskController.cs | 8 +- .../Models/Common/CheckUpdateResult.cs | 25 ++ .../Administration/SmartStore.Admin.csproj | 7 + .../Views/Common/CheckUpdate.cshtml | 51 ++++ .../Views/Common/SystemInfo.cshtml | 1 + .../Administration/Views/Shared/Navbar.cshtml | 31 ++- .../Views/Shared/_AdminLayout.cshtml | 12 +- .../Administration/packages.config | 1 + 20 files changed, 402 insertions(+), 137 deletions(-) create mode 100644 src/Presentation/SmartStore.Web/Administration/Models/Common/CheckUpdateResult.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Common/CheckUpdate.cshtml diff --git a/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs b/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs index 06733ed1ed..9b38188671 100644 --- a/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs +++ b/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Autofac; @@ -10,21 +11,68 @@ namespace SmartStore.Core.Async public static class AsyncRunner { - private static readonly TaskFactory _myTaskFactory; - - static AsyncRunner() - { - _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); - } + /// + /// Execute's an async Task method which has a void return value synchronously + /// + /// Task method to execute public static void RunSync(Func func) { - _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult(); + var oldContext = SynchronizationContext.Current; + var synch = new ExclusiveSynchronizationContext(); + SynchronizationContext.SetSynchronizationContext(synch); + synch.Post(async _ => + { + try + { + await func(); + } + catch (Exception e) + { + synch.InnerException = e; + throw; + } + finally + { + synch.EndMessageLoop(); + } + }, null); + synch.BeginMessageLoop(); + + SynchronizationContext.SetSynchronizationContext(oldContext); } + /// + /// Execute's an async Task method which has a T return type synchronously + /// + /// Return Type + /// Task method to execute + /// public static TResult RunSync(Func> func) { - return _myTaskFactory.StartNew>(func).Unwrap().GetAwaiter().GetResult(); + var oldContext = SynchronizationContext.Current; + var synch = new ExclusiveSynchronizationContext(); + SynchronizationContext.SetSynchronizationContext(synch); + TResult ret = default(TResult); + synch.Post(async _ => + { + try + { + ret = await func(); + } + catch (Exception e) + { + synch.InnerException = e; + throw; + } + finally + { + synch.EndMessageLoop(); + } + }, null); + synch.BeginMessageLoop(); + SynchronizationContext.SetSynchronizationContext(oldContext); + return ret; } public static Task Run(Action action) @@ -84,6 +132,65 @@ public static Task Run(Action action, object state, Canc return t; } + private class ExclusiveSynchronizationContext : SynchronizationContext + { + private bool done; + public Exception InnerException { get; set; } + readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false); + readonly Queue> items = new Queue>(); + + public override void Send(SendOrPostCallback d, object state) + { + throw new NotSupportedException("We cannot send to the same thread"); + } + + public override void Post(SendOrPostCallback d, object state) + { + lock (items) + { + items.Enqueue(Tuple.Create(d, state)); + } + workItemsWaiting.Set(); + } + + public void EndMessageLoop() + { + Post(_ => done = true, null); + } + + public void BeginMessageLoop() + { + while (!done) + { + Tuple task = null; + lock (items) + { + if (items.Count > 0) + { + task = items.Dequeue(); + } + } + if (task != null) + { + task.Item1(task.Item2); + if (InnerException != null) // the method threw an exeption + { + throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException); + } + } + else + { + workItemsWaiting.WaitOne(); + } + } + } + + public override SynchronizationContext CreateCopy() + { + return this; + } + } + } } diff --git a/src/Libraries/SmartStore.Core/Caching/AspNetCache.cs b/src/Libraries/SmartStore.Core/Caching/AspNetCache.cs index 94c65017c3..e50f69ed08 100644 --- a/src/Libraries/SmartStore.Core/Caching/AspNetCache.cs +++ b/src/Libraries/SmartStore.Core/Caching/AspNetCache.cs @@ -56,8 +56,9 @@ public void Set(string key, object value, int? cacheTime) key = BuildKey(key); var absoluteExpiration = Cache.NoAbsoluteExpiration; - if (cacheTime.GetValueOrDefault() > 0) + if (cacheTime.HasValue) { + var span = cacheTime.Value == 0 ? TimeSpan.FromMilliseconds(10) : TimeSpan.FromMinutes(cacheTime.Value); absoluteExpiration = DateTime.UtcNow + TimeSpan.FromMinutes(cacheTime.Value); } diff --git a/src/Libraries/SmartStore.Core/Caching/StaticCache.cs b/src/Libraries/SmartStore.Core/Caching/StaticCache.cs index 3e68892de3..c4fc216e76 100644 --- a/src/Libraries/SmartStore.Core/Caching/StaticCache.cs +++ b/src/Libraries/SmartStore.Core/Caching/StaticCache.cs @@ -42,9 +42,10 @@ public void Set(string key, object value, int? cacheTime) { var cacheItem = new CacheItem(key, value); CacheItemPolicy policy = null; - if (cacheTime.GetValueOrDefault() > 0) + if (cacheTime.HasValue) { - policy = new CacheItemPolicy { AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime.Value) }; + var span = cacheTime.Value == 0 ? TimeSpan.FromMilliseconds(10) : TimeSpan.FromMinutes(cacheTime.Value); + policy = new CacheItemPolicy { AbsoluteExpiration = DateTime.Now + span }; } Cache.Add(cacheItem, policy); diff --git a/src/Libraries/SmartStore.Core/Events/CommonMessages/AppInitScheduledTasksEvent.cs b/src/Libraries/SmartStore.Core/Events/CommonMessages/AppInitScheduledTasksEvent.cs index 9f10cd94dc..fb13ce342b 100644 --- a/src/Libraries/SmartStore.Core/Events/CommonMessages/AppInitScheduledTasksEvent.cs +++ b/src/Libraries/SmartStore.Core/Events/CommonMessages/AppInitScheduledTasksEvent.cs @@ -12,6 +12,6 @@ namespace SmartStore.Core.Events /// codehint: sm-add public class AppInitScheduledTasksEvent { - public List ScheduledTasks { get; set; } + public IList ScheduledTasks { get; set; } } } diff --git a/src/Libraries/SmartStore.Services/Common/GenericAttributeService.cs b/src/Libraries/SmartStore.Services/Common/GenericAttributeService.cs index e3d58978bb..f8d0ae9280 100644 --- a/src/Libraries/SmartStore.Services/Common/GenericAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Common/GenericAttributeService.cs @@ -199,8 +199,9 @@ public virtual void SaveAttribute(BaseEntity entity, string key, TPro var props = GetAttributesForEntity(entity.Id, keyGroup) .Where(x => x.StoreId == storeId) .ToList(); + var prop = props.FirstOrDefault(ga => - ga.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase)); //should be culture invariant + ga.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase)); // should be culture invariant string valueStr = value.Convert(); diff --git a/src/Libraries/SmartStore.Services/Seo/SitemapGenerator.cs b/src/Libraries/SmartStore.Services/Seo/SitemapGenerator.cs index f2b404cfdd..776d424311 100644 --- a/src/Libraries/SmartStore.Services/Seo/SitemapGenerator.cs +++ b/src/Libraries/SmartStore.Services/Seo/SitemapGenerator.cs @@ -117,7 +117,7 @@ private void WriteProducts(UrlHelper urlHelper) private void WriteTopics(UrlHelper urlHelper) { - var topics = _topicService.GetAllTopics(_storeContext.CurrentStore.Id).ToList().FindAll(t => t.IncludeInSitemap); + var topics = _topicService.GetAllTopics(_storeContext.CurrentStore.Id).ToList().FindAll(t => t.IncludeInSitemap && !t.RenderAsWidget); var protocol = _securitySettings.ForceSslForAllPages ? "https" : "http"; foreach (var topic in topics) { diff --git a/src/Libraries/SmartStore.Services/Tasks/Job.cs b/src/Libraries/SmartStore.Services/Tasks/Job.cs index 3fd090a0b8..453a3daf86 100644 --- a/src/Libraries/SmartStore.Services/Tasks/Job.cs +++ b/src/Libraries/SmartStore.Services/Tasks/Job.cs @@ -50,7 +50,7 @@ private ITask CreateTask(ILifetimeScope scope) object instance; if (!EngineContext.Current.ContainerManager.TryResolve(type2, scope, out instance)) { - //not resolved + // not resolved instance = EngineContext.Current.ContainerManager.ResolveUnregistered(type2, scope); } task = instance as ITask; diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs b/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs index 9547986a5c..6a8dc82be3 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs @@ -27,10 +27,7 @@ public void Initialize() this._taskThreads.Clear(); var taskService = EngineContext.Current.Resolve(); - var scheduleTasks = taskService - .GetAllTasks() - .OrderBy(x => x.Seconds) - .ToList(); + var scheduleTasks = taskService.GetAllTasks(); var eventPublisher = EngineContext.Current.Resolve(); eventPublisher.Publish(new AppInitScheduledTasksEvent { @@ -52,8 +49,8 @@ public void Initialize() var isActiveModule = PluginManager.IsActivePluginAssembly(taskType.Assembly); if (isActiveModule) { - var task = new Job(scheduleTask); - taskThread.AddJob(task); + var job = new Job(scheduleTask); + taskThread.AddJob(job); } } } diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs b/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs index 511bcba705..b1401d0ebe 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs @@ -38,7 +38,7 @@ private void Run() this._startedUtc = DateTime.UtcNow; this._isRunning = true; - foreach (Job job in this._jobs.Values) + foreach (var job in this._jobs.Values) { job.Execute(); } diff --git a/src/Presentation/SmartStore.Web/Administration/Content/admin.less b/src/Presentation/SmartStore.Web/Administration/Content/admin.less index 7ee65d51ff..eae90aefb8 100644 --- a/src/Presentation/SmartStore.Web/Administration/Content/admin.less +++ b/src/Presentation/SmartStore.Web/Administration/Content/admin.less @@ -254,6 +254,15 @@ header { .opacity(100); } +.reddot { + position: absolute; + width: 10px; + height: 10px; + border-radius: 50%; + background-color: @red; + color: #fff; +} + /* SM additions -------------------------------------------------------------- */ @@ -277,9 +286,7 @@ header { height: 3px; z-index: 20; background-color: #ffab40; - transition: opacity .05s ease-in; - -o-transition: opacity .05s ease-in; - -webkit-transition: opacity .05s ease-in; + .transition(opacity .05s ease-in); } #ajax-busy.busy { opacity: 1; diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs index 56759bbed2..3bf0d9a538 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs @@ -2,15 +2,30 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Reflection; using System.Runtime.InteropServices; using System.Security.Principal; +using System.Threading.Tasks; using System.Web.Mvc; +using Newtonsoft.Json; using SmartStore.Admin.Models.Common; +using SmartStore.Collections; using SmartStore.Core; +using SmartStore.Core.Async; using SmartStore.Core.Caching; +using SmartStore.Core.Data; +using SmartStore.Core.Domain.Common; +using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Directory; +using SmartStore.Core.Domain.Security; using SmartStore.Core.Domain.Seo; +using SmartStore.Core.Infrastructure; +using SmartStore.Core.Logging; using SmartStore.Core.Plugins; +using SmartStore.Services; +using SmartStore.Services.Common; using SmartStore.Services.Customers; using SmartStore.Services.Directory; using SmartStore.Services.Helpers; @@ -20,20 +35,12 @@ using SmartStore.Services.Security; using SmartStore.Services.Seo; using SmartStore.Services.Shipping; +using SmartStore.Utilities; +using SmartStore.Web.Framework; using SmartStore.Web.Framework.Controllers; using SmartStore.Web.Framework.Security; -using SmartStore.Collections; -using SmartStore.Utilities; using SmartStore.Web.Framework.UI; -using SmartStore.Core.Domain.Security; -using SmartStore.Core.Infrastructure; -using SmartStore.Core.Data; using Telerik.Web.Mvc; -using SmartStore.Services.Common; -using SmartStore.Core.Domain.Common; -using System.Reflection; -using Autofac; -using SmartStore.Web.Framework; namespace SmartStore.Admin.Controllers { @@ -48,21 +55,17 @@ public class CommonController : AdminControllerBase private readonly Lazy _measureService; private readonly ICustomerService _customerService; private readonly IUrlRecordService _urlRecordService; - private readonly IWebHelper _webHelper; private readonly Lazy _currencySettings; private readonly Lazy _measureSettings; private readonly Lazy _dateTimeHelper; private readonly ILanguageService _languageService; - private readonly IWorkContext _workContext; - private readonly IStoreContext _storeContext; - private readonly IPermissionService _permissionService; private readonly ILocalizationService _localizationService; private readonly Lazy _imageCache; private readonly Lazy _securitySettings; private readonly Lazy _menuPublisher; private readonly Lazy _pluginFinder; private readonly IGenericAttributeService _genericAttributeService; - private readonly IDbContext _dbContext; + private readonly ICommonServices _services; private readonly Func _cache; private readonly static object _lock = new object(); @@ -78,21 +81,17 @@ public CommonController( Lazy measureService, ICustomerService customerService, IUrlRecordService urlRecordService, - IWebHelper webHelper, Lazy currencySettings, Lazy measureSettings, Lazy dateTimeHelper, ILanguageService languageService, - IWorkContext workContext, - IStoreContext storeContext, - IPermissionService permissionService, ILocalizationService localizationService, Lazy imageCache, Lazy securitySettings, Lazy menuPublisher, Lazy pluginFinder, IGenericAttributeService genericAttributeService, - IDbContext dbContext, + ICommonServices services, Func cache) { this._paymentService = paymentService; @@ -101,21 +100,17 @@ public CommonController( this._measureService = measureService; this._customerService = customerService; this._urlRecordService = urlRecordService; - this._webHelper = webHelper; this._currencySettings = currencySettings; this._measureSettings = measureSettings; this._dateTimeHelper = dateTimeHelper; this._languageService = languageService; - this._workContext = workContext; - this._storeContext = storeContext; - this._permissionService = permissionService; this._localizationService = localizationService; this._imageCache = imageCache; this._securitySettings = securitySettings; this._menuPublisher = menuPublisher; this._pluginFinder = pluginFinder; this._genericAttributeService = genericAttributeService; - this._dbContext = dbContext; + this._services = services; this._cache = cache; } @@ -123,15 +118,27 @@ public CommonController( #region Methods - #region AdminMenu + #region Navbar & Menu + + [ChildActionOnly] + public ActionResult Navbar() + { + var currentCustomer = _services.WorkContext.CurrentCustomer; + + ViewBag.UserName = _services.Settings.LoadSetting().UsernamesEnabled ? currentCustomer.Username : currentCustomer.Email; + ViewBag.Stores = _services.StoreService.GetAllStores(); + ViewBag.CheckUpdateResult = AsyncRunner.RunSync(() => CheckUpdateAsync(false)); + + return PartialView(); + } [ChildActionOnly] public ActionResult Menu() { - var cacheManager = _cache("static"); + var cacheManager = _services.Cache; - var customerRolesIds = _workContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); - string cacheKey = string.Format("smartstore.pres.adminmenu.navigation-{0}-{1}", _workContext.WorkingLanguage.Id, string.Join(",", customerRolesIds)); + var customerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); + string cacheKey = string.Format("smartstore.pres.adminmenu.navigation-{0}-{1}", _services.WorkContext.WorkingLanguage.Id, string.Join(",", customerRolesIds)); var rootNode = cacheManager.Get(cacheKey, () => { @@ -152,31 +159,6 @@ private TreeNode PrepareAdminMenu() _menuPublisher.Value.RegisterMenus(rootNode, "admin"); - //TreeNode pluginNode = null; - - //// "collect" menus from plugins - //var providers = new List(); - //var providerTypes = _typeFinder.FindClassesOfType(ignoreInactivePlugins: true); - - //foreach (var type in providerTypes) - //{ - // try - // { - // var provider = Activator.CreateInstance(type) as IMenuProvider; - // if (provider.MenuName.IsCaseInsensitiveEqual("admin")) - // { - // providers.Add(provider); - // } - // } - // catch { } - //} - - //if (providers.Any()) - //{ - // pluginNode = rootNode.Children.FirstOrDefault(x => x.Value.Id == "plugins"); - // providers.Each(x => x.BuildMenu(pluginNode)); - //} - // hide based on permissions rootNode.TraverseTree(x => { if (!x.IsRoot) @@ -265,7 +247,7 @@ private bool MenuItemAccessPermitted(MenuItem item) if (_securitySettings.Value.HideAdminMenuItemsBasedOnPermissions && item.PermissionNames.HasValue()) { - var permitted = item.PermissionNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Any(x => _permissionService.Authorize(x.Trim())); + var permitted = item.PermissionNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Any(x => _services.Permissions.Authorize(x.Trim())); if (!permitted) { result = false; @@ -275,6 +257,89 @@ private bool MenuItemAccessPermitted(MenuItem item) return result; } + public async Task CheckUpdate(bool enforce = false) + { + var model = await CheckUpdateAsync(enforce); + return View(model); + } + + public ActionResult CheckUpdateSuppress(string myVersion, string newVersion) + { + var suppressKey = "SuppressUpdateMessage.{0}.{1}".FormatInvariant(myVersion, newVersion); + _genericAttributeService.SaveAttribute(_services.WorkContext.CurrentCustomer, suppressKey, true); + _services.Cache.RemoveByPattern("Common.CheckUpdateResult"); + + return RedirectToAction("Index", "Home"); + } + + [NonAction] + private async Task CheckUpdateAsync(bool enforce = false, bool forSuppress = false) + { + var curVersion = SmartStoreVersion.CurrentFullVersion; + var lang = _services.WorkContext.WorkingLanguage.UniqueSeoCode; + var cacheKeyPattern = "Common.CheckUpdateResult"; + var cacheKey = "{0}.{1}".FormatInvariant(cacheKeyPattern, lang); + + if (enforce) + { + _services.Cache.RemoveByPattern(cacheKeyPattern); + } + + var result = await _services.Cache.Get(cacheKey, async () => + { + var noUpdateResult = new CheckUpdateResult { UpdateAvailable = false, LanguageCode = lang, CurrentVersion = curVersion }; + + try + { + string url = "http://dlm.smartstore.com/api/v1/apprelease/CheckUpdate?app=SMNET&version={0}&language={1}".FormatInvariant(curVersion, lang); + + using (var client = new HttpClient()) + { + client.Timeout = TimeSpan.FromMilliseconds(3000); + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + client.DefaultRequestHeaders.UserAgent.ParseAdd("SmartStore.NET {0}".FormatInvariant(curVersion)); + client.DefaultRequestHeaders.Add("Authorization-Key", _services.StoreContext.CurrentStore.Url.TrimEnd('/')); + + HttpResponseMessage response = await client.GetAsync(url); + + if (!response.IsSuccessStatusCode) + { + return noUpdateResult; + } + + var jsonStr = await response.Content.ReadAsStringAsync(); + var model = JsonConvert.DeserializeObject(jsonStr); + model.UpdateAvailable = true; + model.CurrentVersion = curVersion; + model.LanguageCode = lang; + + // don't show message if user decided to suppress it + var suppressKey = "SuppressUpdateMessage.{0}.{1}".FormatInvariant(curVersion, model.Version); + if (enforce) + { + // but ignore user's decision if 'enforce' + _genericAttributeService.SaveAttribute(_services.WorkContext.CurrentCustomer, suppressKey, null); + } + var showMessage = enforce || _services.WorkContext.CurrentCustomer.GetAttribute(suppressKey, _genericAttributeService).GetValueOrDefault() == false; + if (!showMessage) + { + return noUpdateResult; + } + + return model; + } + } + catch (Exception ex) + { + Logger.Error("An error occurred while checking for update", ex); + return noUpdateResult; + } + }, 1440 /* 24h * 60min. */); + + return result; + } + #endregion [HttpPost] @@ -323,12 +388,12 @@ public ActionResult SystemInfo() model.ServerTimeZone = TimeZone.CurrentTimeZone.StandardName; model.ServerLocalTime = DateTime.Now; model.UtcTime = DateTime.UtcNow; - model.HttpHost = _webHelper.ServerVariables("HTTP_HOST"); + model.HttpHost = _services.WebHelper.ServerVariables("HTTP_HOST"); //Environment.GetEnvironmentVariable("USERNAME"); try { - var mbSize = _dbContext.SqlQuery("Select Sum(size)/128.0 From sysfiles").FirstOrDefault(); + var mbSize = _services.DbContext.SqlQuery("Select Sum(size)/128.0 From sysfiles").FirstOrDefault(); model.DatabaseSize = Convert.ToDouble(mbSize); } catch (Exception) { } @@ -368,8 +433,8 @@ public ActionResult Warnings() var model = new List(); //store URL - var currentStoreUrl = _storeContext.CurrentStore.Url.EnsureEndsWith("/"); - if (currentStoreUrl.HasValue() && (currentStoreUrl.IsCaseInsensitiveEqual(_webHelper.GetStoreLocation(false)) || currentStoreUrl.IsCaseInsensitiveEqual(_webHelper.GetStoreLocation(true)))) + var currentStoreUrl = _services.StoreContext.CurrentStore.Url.EnsureEndsWith("/"); + if (currentStoreUrl.HasValue() && (currentStoreUrl.IsCaseInsensitiveEqual(_services.WebHelper.GetStoreLocation(false)) || currentStoreUrl.IsCaseInsensitiveEqual(_services.WebHelper.GetStoreLocation(true)))) model.Add(new SystemWarningModel() { Level = SystemWarningLevel.Pass, @@ -379,7 +444,7 @@ public ActionResult Warnings() model.Add(new SystemWarningModel() { Level = SystemWarningLevel.Warning, - Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.URL.NoMatch"), currentStoreUrl, _webHelper.GetStoreLocation(false)) + Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.URL.NoMatch"), currentStoreUrl, _services.WebHelper.GetStoreLocation(false)) }); @@ -523,7 +588,7 @@ public ActionResult Warnings() //validate write permissions (the same procedure like during installation) var dirPermissionsOk = true; - var dirsToCheck = FilePermissionHelper.GetDirectoriesWrite(_webHelper); + var dirsToCheck = FilePermissionHelper.GetDirectoriesWrite(_services.WebHelper); foreach (string dir in dirsToCheck) if (!FilePermissionHelper.CheckPermissions(dir, false, true, true, false)) { @@ -542,7 +607,7 @@ public ActionResult Warnings() }); var filePermissionsOk = true; - var filesToCheck = FilePermissionHelper.GetFilesWrite(_webHelper); + var filesToCheck = FilePermissionHelper.GetFilesWrite(_services.WebHelper); foreach (string file in filesToCheck) if (!FilePermissionHelper.CheckPermissions(file, false, true, true, true)) { @@ -566,14 +631,14 @@ public ActionResult Warnings() public ActionResult ShrinkDatabase() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); try { if (DataSettings.Current.IsSqlServer) { - _dbContext.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); + _services.DbContext.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); NotifySuccess(_localizationService.GetResource("Common.ShrinkDatabaseSuccessful")); } } @@ -587,7 +652,7 @@ public ActionResult ShrinkDatabase() public ActionResult Maintenance() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); var model = new MaintenanceModel(); @@ -608,7 +673,7 @@ public ActionResult Maintenance() [FormValueRequired("delete-image-cache")] public ActionResult MaintenanceDeleteImageCache() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); _imageCache.Value.DeleteCachedImages(); @@ -620,7 +685,7 @@ public ActionResult MaintenanceDeleteImageCache() [FormValueRequired("delete-guests")] public ActionResult MaintenanceDeleteGuests(MaintenanceModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); DateTime? startDateValue = (model.DeleteGuests.StartDate == null) ? null @@ -638,7 +703,7 @@ public ActionResult MaintenanceDeleteGuests(MaintenanceModel model) [FormValueRequired("delete-exported-files")] public ActionResult MaintenanceDeleteFiles(MaintenanceModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); DateTime? startDateValue = (model.DeleteExportedFiles.StartDate == null) ? null @@ -682,7 +747,7 @@ public ActionResult MaintenanceDeleteFiles(MaintenanceModel model) [FormValueRequired("execute-sql-query")] public ActionResult MaintenanceExecuteSql(MaintenanceModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); if (model.SqlQuery.HasValue()) @@ -703,14 +768,13 @@ public ActionResult MaintenanceExecuteSql(MaintenanceModel model) return View(model); } - //language [ChildActionOnly] public ActionResult LanguageSelector() { var model = new LanguageSelectorModel(); - model.CurrentLanguage = _workContext.WorkingLanguage.ToModel(); + model.CurrentLanguage = _services.WorkContext.WorkingLanguage.ToModel(); model.AvailableLanguages = _languageService - .GetAllLanguages(storeId: _storeContext.CurrentStore.Id) + .GetAllLanguages(storeId: _services.StoreContext.CurrentStore.Id) .Select(x => x.ToModel()) .ToList(); return PartialView(model); @@ -720,14 +784,14 @@ public ActionResult LanguageSelected(int customerlanguage) var language = _languageService.GetLanguageById(customerlanguage); if (language != null) { - _workContext.WorkingLanguage = language; + _services.WorkContext.WorkingLanguage = language; } return Content(_localizationService.GetResource("Admin.Common.DataEditSuccess")); } public ActionResult ClearCache(string previousUrl) { - var cacheManager = _cache("static"); + var cacheManager = _services.Cache; cacheManager.Clear(); cacheManager = _cache("aspnet"); @@ -743,10 +807,10 @@ public ActionResult ClearCache(string previousUrl) public ActionResult RestartApplication(string previousUrl) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); - _webHelper.RestartAppDomain(); + _services.WebHelper.RestartAppDomain(); if (previousUrl.HasValue()) return Redirect(previousUrl); @@ -760,7 +824,7 @@ public ActionResult RestartApplication(string previousUrl) public ActionResult SeNames() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); var model = new UrlRecordListModel(); @@ -770,7 +834,7 @@ public ActionResult SeNames() [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult SeNames(GridCommand command, UrlRecordListModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); var urlRecords = _urlRecordService.GetAllUrlRecords(model.SeName, command.Page - 1, command.PageSize); @@ -809,7 +873,7 @@ public ActionResult SeNames(GridCommand command, UrlRecordListModel model) [HttpPost] public ActionResult DeleteSelectedSeNames(ICollection selectedIds) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); if (selectedIds != null) @@ -844,10 +908,10 @@ public ActionResult GenericAttributes(string entityName, int entityId) [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributesSelect(string entityName, int entityId, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); - var storeId = _storeContext.CurrentStore.Id; + var storeId = _services.StoreContext.CurrentStore.Id; ViewBag.StoreId = storeId; var model = new List(); @@ -882,7 +946,7 @@ public ActionResult GenericAttributesSelect(string entityName, int entityId, Gri [GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributeAdd(GenericAttributeModel model, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); model.Key = model.Key.TrimSafe(); @@ -895,7 +959,7 @@ public ActionResult GenericAttributeAdd(GenericAttributeModel model, GridCommand return Content(modelStateErrorMessages.FirstOrDefault()); } - var storeId = _storeContext.CurrentStore.Id; + var storeId = _services.StoreContext.CurrentStore.Id; var attr = _genericAttributeService.GetAttribute(model.EntityName, model.EntityId, model.Key, storeId); if (attr == null) @@ -921,7 +985,7 @@ public ActionResult GenericAttributeAdd(GenericAttributeModel model, GridCommand [GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributeUpdate(GenericAttributeModel model, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); model.Key = model.Key.TrimSafe(); @@ -934,7 +998,7 @@ public ActionResult GenericAttributeUpdate(GenericAttributeModel model, GridComm return Content(modelStateErrorMessages.FirstOrDefault()); } - var storeId = _storeContext.CurrentStore.Id; + var storeId = _services.StoreContext.CurrentStore.Id; var attr = _genericAttributeService.GetAttributeById(model.Id); // if the key changed, ensure it isn't being used by another attribute @@ -960,7 +1024,7 @@ public ActionResult GenericAttributeUpdate(GenericAttributeModel model, GridComm [GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributeDelete(int id, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); var attr = _genericAttributeService.GetAttributeById(id); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/HomeController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/HomeController.cs index fad8865a38..45bce21219 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/HomeController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/HomeController.cs @@ -92,8 +92,9 @@ public ActionResult MarketplaceFeed() try { string url = "http://community.smartstore.com/index.php?/rss/downloads/"; - var request = WebRequest.Create(url); + var request = (HttpWebRequest)WebRequest.Create(url); request.Timeout = 3000; + request.UserAgent = "SmartStore.NET {0}".FormatInvariant(SmartStoreVersion.CurrentFullVersion); using (WebResponse response = request.GetResponse()) { diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs index 1384933d48..e1a6705984 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs @@ -168,10 +168,10 @@ public ActionResult RunJob(int id, string returnUrl = "") var t = AsyncRunner.Run(c => { + var svc = c.Resolve(); + try { - var svc = c.Resolve(); - var scheduleTask = svc.GetTaskById(id); if (scheduleTask == null) throw new Exception("Schedule task cannot be loaded"); @@ -184,9 +184,9 @@ public ActionResult RunJob(int id, string returnUrl = "") { try { - _scheduleTaskService.EnsureTaskIsNotRunning(id); + svc.EnsureTaskIsNotRunning(id); } - catch (Exception) { } + catch { } } }); diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Common/CheckUpdateResult.cs b/src/Presentation/SmartStore.Web/Administration/Models/Common/CheckUpdateResult.cs new file mode 100644 index 0000000000..453629ffc8 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Models/Common/CheckUpdateResult.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using SmartStore.Web.Framework.Mvc; + +namespace SmartStore.Admin.Models.Common +{ + [Serializable] + public class CheckUpdateResult : ModelBase + { + public bool UpdateAvailable { get; set; } + public string CurrentVersion { get; set; } + public string LanguageCode { get; set; } + + public string Version { get; set; } + public string FullName { get; set; } + public string ReleaseNotes { get; set; } + public string InfoUrl { get; set; } + public string DownloadUrl { get; set; } + public DateTime ReleaseDateUtc { get; set; } + public bool IsStable { get; set; } + public bool AutoUpdatePossible { get; set; } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index 75c255ee8f..0f20b4a962 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -97,6 +97,11 @@ + + + False + ..\..\..\packages\Microsoft.AspNet.WebApi.Client.5.1.2\lib\net45\System.Net.Http.Formatting.dll + @@ -231,6 +236,7 @@ + @@ -485,6 +491,7 @@ + diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Common/CheckUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Common/CheckUpdate.cshtml new file mode 100644 index 0000000000..64165e5f56 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Views/Common/CheckUpdate.cshtml @@ -0,0 +1,51 @@ +@model CheckUpdateResult + +@{ + ViewBag.Title = "Check for Updates"; +} + +
+
+ + Check for Updates +
+
+ +
+ @if (!Model.UpdateAvailable) + { +
+ Your SmartStore.NET version is up-to-date +
+ } + else + { +

Update available!

+
+
Your Version
+
@Model.CurrentVersion
+
Current Version
+
@Model.Version
+
Date
+
@Model.ReleaseDateUtc.ToShortDateString()
+
+ +
+
Release Notes
+
@Html.Raw(Model.ReleaseNotes)
+
+ +
+ More Info + @if (Model.DownloadUrl.HasValue()) + { + + + Download + + } + Don't notify anymore +
+ } +
+ diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Common/SystemInfo.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Common/SystemInfo.cshtml index 7cad69a0a0..07a4235db8 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Common/SystemInfo.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Common/SystemInfo.cshtml @@ -28,6 +28,7 @@
@Html.DisplayFor(model => model.AppVersion) + Check for updates
- @(Html.Telerik().Grid(Model.Data) + @(Html.Telerik().Grid() .Name("campaigns-grid") .Columns(columns => { columns.Bound(x => x.Name) - .Width(500) .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })) .ClientTemplate("\"><#= Name #>"); columns.Bound(x => x.Subject); columns.Bound(x => x.LimitedToStores) - .Width(180) .Template(item => @Html.SymbolForBool(item.LimitedToStores)) .ClientTemplate(@Html.SymbolForBool("LimitedToStores")) + .Hidden((int)ViewData["StoreCount"] <= 1) .Centered(); - columns.Bound(x => x.CreatedOn) - .Width(180); + columns.Bound(x => x.CreatedOn); }) .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "Campaign")) .PreserveGridState() diff --git a/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/Index.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/Index.cshtml index 19f4ad462f..8ee7574be3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/Index.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/Index.cshtml @@ -160,6 +160,7 @@ .Width(100) .Template(x => @Html.SymbolForBool(x.LimitedToStores)) .ClientTemplate(@Html.SymbolForBool("LimitedToStores")) + .Hidden(Model.StoreCount <= 1) .Centered(); columns.Bound(x => x.Published) .Width(100) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Customer/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Customer/List.cshtml index 1cba231bbf..abbc1653cc 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Customer/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Customer/List.cshtml @@ -189,48 +189,32 @@ .Columns(columns => { columns.Bound(x => x.Id) - .Template(x => string.Format("", x.Id)) - .ClientTemplate("") - .Title("") - .Width(50) - .HtmlAttributes(new { style = "text-align:center" }) - .HeaderHtmlAttributes(new { style = "text-align:center" }); - - columns.Bound(x => x.Id) - .Width(50); - //I don't know why but the customer list does not have an 'Edit' column in the grid on some machines (maybe because we are inside Html.BeginForm()). - //That's why the 'Email' column is clickable. + .Template(x => string.Format("", x.Id)) + .ClientTemplate("") + .Title("") + .HtmlAttributes(new { style = "text-align:center" }) + .HeaderHtmlAttributes(new { style = "text-align:center" }); + columns.Bound(x => x.Id); columns.Bound(x => x.Email) .Template(x => Html.ActionLink(x.Email, "Edit", "Customer", new { id = x.Id }, new { })) - .ClientTemplate("\"><#= Email #>") - .Width(150); + .ClientTemplate("\"><#= Email #>"); columns.Bound(x => x.Username) - .Width(150) .Visible(Model.UsernamesEnabled); - columns.Bound(x => x.FullName) - .Width(200); - columns.Bound(x => x.CustomerRoleNames) - .Width(200); + columns.Bound(x => x.FullName); + columns.Bound(x => x.CustomerRoleNames); columns.Bound(x => x.Company) - .Width(150) .Visible(Model.CompanyEnabled); columns.Bound(x => x.Phone) - .Width(100) .Visible(Model.PhoneEnabled); columns.Bound(x => x.ZipPostalCode) - .Width(75) .Visible(Model.ZipPostalCodeEnabled); columns.Bound(x => x.Active) - .Width(100) .Template(item => @Html.SymbolForBool(item.Active)) .ClientTemplate(@Html.SymbolForBool("Active")) .Centered(); - columns.Bound(x => x.CreatedOn) - .Width(100); - columns.Bound(x => x.LastActivityDate) - .Width(100); + columns.Bound(x => x.CreatedOn); + columns.Bound(x => x.LastActivityDate); columns.Bound(x => x.Id) - .Width(50) .Centered() .Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id })) .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml index 78c68219b4..bcf08d04b1 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml @@ -192,6 +192,12 @@ .RightAlign(); columns.Bound(x => x.StockQuantity) .Centered(); + columns.Bound(x => x.LimitedToStores) + .Template(item => @Html.SymbolForBool(item.LimitedToStores)) + .ClientTemplate(@Html.SymbolForBool("LimitedToStores")) + .Hidden(Model.StoreCount <= 1) + .Centered(); + columns.Bound(x => x.UpdatedOn); columns.Bound(x => x.Published) .Width(100) .Template(item => @Html.SymbolForBool(item.Published)) From b705b369ef01788eccf87ce32c30d64341902a28 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Fri, 3 Apr 2015 18:38:00 +0200 Subject: [PATCH 0016/1256] Added deletion of selected specification attributes --- .../Migrations/201503032227054_V22Res.cs | 8 + .../Catalog/ISpecificationAttributeService.cs | 9 +- .../Catalog/SpecificationAttributeService.cs | 21 ++- .../SpecificationAttributeController.cs | 46 +++-- .../Catalog/SpecificationAttributeModel.cs | 3 +- .../Views/SpecificationAttribute/List.cshtml | 160 ++++++++++++++---- 6 files changed, 201 insertions(+), 46 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201503032227054_V22Res.cs b/src/Libraries/SmartStore.Data/Migrations/201503032227054_V22Res.cs index bc2a15f44d..b66b0d7113 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201503032227054_V22Res.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201503032227054_V22Res.cs @@ -99,6 +99,14 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Common.Execution", "Execution", "Ausfhrung"); + + builder.AddOrUpdate("Admin.Catalog.Attributes.SpecificationAttributes.OptionsCount", + "Number options", + "Anzahl Optionen"); + + builder.AddOrUpdate("Admin.Common.DeleteSelected", + "Delete selected", + "Ausgewhlte lschen"); } } } diff --git a/src/Libraries/SmartStore.Services/Catalog/ISpecificationAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/ISpecificationAttributeService.cs index aac243a206..e0d765eb5b 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ISpecificationAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ISpecificationAttributeService.cs @@ -21,9 +21,16 @@ public partial interface ISpecificationAttributeService /// /// Gets specification attributes /// - /// Specification attributes + /// Specification attribute query IQueryable GetSpecificationAttributes(); + /// + /// Gets specification attributes by identifier + /// + /// Identifiers + /// Specification attribute query + IQueryable GetSpecificationAttributesByIds(int[] ids); + /// /// Deletes a specification attribute /// diff --git a/src/Libraries/SmartStore.Services/Catalog/SpecificationAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/SpecificationAttributeService.cs index 5a19971440..bb0bb7d806 100644 --- a/src/Libraries/SmartStore.Services/Catalog/SpecificationAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/SpecificationAttributeService.cs @@ -74,7 +74,7 @@ public virtual SpecificationAttribute GetSpecificationAttributeById(int specific /// /// Gets specification attributes /// - /// Specification attributes + /// Specification attribute query public virtual IQueryable GetSpecificationAttributes() { var query = @@ -85,6 +85,25 @@ from sa in _specificationAttributeRepository.Table return query; } + /// + /// Gets specification attributes by identifier + /// + /// Identifiers + /// Specification attribute query + public virtual IQueryable GetSpecificationAttributesByIds(int[] ids) + { + if (ids == null || ids.Length == 0) + return null; + + var query = + from sa in _specificationAttributeRepository.Table + where ids.Contains(sa.Id) + orderby sa.DisplayOrder, sa.Name + select sa; + + return query; + } + /// /// Deletes a specification attribute /// diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/SpecificationAttributeController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/SpecificationAttributeController.cs index 55301c0f95..06c73475a1 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/SpecificationAttributeController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/SpecificationAttributeController.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Catalog; @@ -120,16 +121,24 @@ public ActionResult List(GridCommand command) if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); + var optionsText = _localizationService.GetResource("Admin.Catalog.Attributes.SpecificationAttributes.Options"); + var data = _specificationAttributeService.GetSpecificationAttributes() .ForCommand(command) - .Select(x => x.ToModel()) + .Select(x => + { + var model = x.ToModel(); + model.OptionCount = x.SpecificationAttributeOptions.Count; + + return model; + }) .ToList(); - var gridModel = new GridModel - { - Data = data.PagedForCommand(command), - Total = data.Count - }; + var gridModel = new GridModel + { + Data = data.PagedForCommand(command), + Total = data.Count + }; return new JsonResult { @@ -180,7 +189,6 @@ public ActionResult Edit(int id) var specificationAttribute = _specificationAttributeService.GetSpecificationAttributeById(id); if (specificationAttribute == null) - //No specification attribute found with the specified id return RedirectToAction("List"); var model = specificationAttribute.ToModel(); @@ -201,7 +209,6 @@ public ActionResult Edit(SpecificationAttributeModel model, bool continueEditing var specificationAttribute = _specificationAttributeService.GetSpecificationAttributeById(model.Id); if (specificationAttribute == null) - //No specification attribute found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) @@ -231,7 +238,6 @@ public ActionResult DeleteConfirmed(int id) var specificationAttribute = _specificationAttributeService.GetSpecificationAttributeById(id); if (specificationAttribute == null) - //No specification attribute found with the specified id return RedirectToAction("List"); _specificationAttributeService.DeleteSpecificationAttribute(specificationAttribute); @@ -243,6 +249,26 @@ public ActionResult DeleteConfirmed(int id) return RedirectToAction("List"); } + [HttpPost] + public ActionResult DeleteSelected(ICollection selectedIds) + { + if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + return AccessDeniedView(); + + if (selectedIds != null && selectedIds.Count > 0) + { + var attributes = _specificationAttributeService.GetSpecificationAttributesByIds(selectedIds.ToArray()).ToList(); + string deletedNames = string.Join(", ", attributes.Select(x => x.Name)); + + foreach (var attribute in attributes) + _specificationAttributeService.DeleteSpecificationAttribute(attribute); + + _customerActivityService.InsertActivity("DeleteSpecAttribute", _localizationService.GetResource("ActivityLog.DeleteSpecAttribute"), deletedNames); + } + + return Json(new { Result = true }); + } + [HttpPost] public ActionResult ProductMappingEdit(int specificationAttributeId, string field, bool value) { @@ -345,7 +371,6 @@ public ActionResult OptionEditPopup(int id) var sao = _specificationAttributeService.GetSpecificationAttributeOptionById(id); if (sao == null) - //No specification attribute option found with the specified id return RedirectToAction("List"); var model = sao.ToModel(); @@ -366,7 +391,6 @@ public ActionResult OptionEditPopup(string btnId, string formId, SpecificationAt var sao = _specificationAttributeService.GetSpecificationAttributeOptionById(model.Id); if (sao == null) - //No specification attribute option found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/SpecificationAttributeModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/SpecificationAttributeModel.cs index b7617cc450..24018dcb55 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/SpecificationAttributeModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/SpecificationAttributeModel.cs @@ -23,9 +23,10 @@ public SpecificationAttributeModel() [SmartResourceDisplayName("Admin.Catalog.Attributes.SpecificationAttributes.Fields.DisplayOrder")] public int DisplayOrder {get;set;} - public IList Locales { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Attributes.SpecificationAttributes.OptionsCount")] + public int OptionCount { get; set; } } public class SpecificationAttributeLocalizedModel : ILocalizedModelLocal diff --git a/src/Presentation/SmartStore.Web/Administration/Views/SpecificationAttribute/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/SpecificationAttribute/List.cshtml index 774d46febd..966cc46457 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/SpecificationAttribute/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/SpecificationAttribute/List.cshtml @@ -3,35 +3,131 @@ ViewBag.Title = T("Admin.Catalog.Attributes.SpecificationAttributes").Text; } -
-
- @T("Admin.Catalog.Attributes.SpecificationAttributes") -
- -
- - - - - -
- @(Html.Telerik().Grid() - .Name("specificationattributes-grid") - .Columns(columns => - { - columns.Bound(x => x.Name) - .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })) - .ClientTemplate("<#= Name #>"); - columns.Bound(x => x.DisplayOrder) - .Width(200) - .Filterable(false) - .Centered(); - }) - .Filterable() - .Pageable(settings => settings.PageSize((int)ViewData["GridPageSize"]).Position(GridPagerPosition.Both)) - .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "SpecificationAttribute")) - .PreserveGridState() - .EnableCustomBinding(true)) -
\ No newline at end of file +@using (Html.BeginForm()) +{ +
+
+ @T("Admin.Catalog.Attributes.SpecificationAttributes") +
+
+  @T("Admin.Common.AddNew") + + +
+
+ + + + + +
+ @(Html.Telerik().Grid() + .Name("specificationattributes-grid") + .ClientEvents(events => events.OnDataBound("onDataBound")) + .Columns(columns => + { + columns.Bound(x => x.Id) + .ClientTemplate("") + .Title("") + .Width(50) + .Filterable(false) + .HtmlAttributes(new { style = "text-align:center" }) + .HeaderHtmlAttributes(new { style = "text-align:center" }); + columns.Bound(x => x.Name) + .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })) + .ClientTemplate("<#= Name #>"); + columns.Bound(x => x.OptionCount) + .Filterable(false) + .Width(200) + .Centered(); + columns.Bound(x => x.DisplayOrder) + .Filterable(false) + .Width(200) + .Centered(); + }) + .Filterable() + .Pageable(settings => settings.PageSize((int)ViewData["GridPageSize"]).Position(GridPagerPosition.Both)) + .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "SpecificationAttribute")) + .PreserveGridState() + .EnableCustomBinding(true)) +
+} + + \ No newline at end of file From 5669ab08a981986f9782920822a3b0f0e716cb8c Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Sat, 4 Apr 2015 02:49:52 +0200 Subject: [PATCH 0017/1256] Minor typo fixes --- src/Libraries/SmartStore.Core/Domain/Media/Download.cs | 6 +++--- .../Extensions/NameValueCollectionExtensions.cs | 2 +- .../SmartStore.Web.Framework/Mvc/UniversalResult.cs | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Domain/Media/Download.cs b/src/Libraries/SmartStore.Core/Domain/Media/Download.cs index 92ebeba670..933790f578 100644 --- a/src/Libraries/SmartStore.Core/Domain/Media/Download.cs +++ b/src/Libraries/SmartStore.Core/Domain/Media/Download.cs @@ -10,19 +10,19 @@ namespace SmartStore.Core.Domain.Media public partial class Download : BaseEntity { /// - /// Gets a sets a GUID + /// Gets or sets a GUID /// [DataMember] public Guid DownloadGuid { get; set; } /// - /// Gets a sets a value indicating whether DownloadUrl property should be used + /// Gets or sets a value indicating whether DownloadUrl property should be used /// [DataMember] public bool UseDownloadUrl { get; set; } /// - /// Gets a sets a download URL + /// Gets or sets a download URL /// [DataMember] public string DownloadUrl { get; set; } diff --git a/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs b/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs index 575c2948c8..99ee1e5744 100644 --- a/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs +++ b/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs @@ -158,7 +158,7 @@ public static string CreateSelectedAttributesXml(this NameValueCollection collec else { //save an uploaded file - var download = new Download() + var download = new Download { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = false, diff --git a/src/Presentation/SmartStore.Web.Framework/Mvc/UniversalResult.cs b/src/Presentation/SmartStore.Web.Framework/Mvc/UniversalResult.cs index 5ac5d40287..e8d3ef8576 100644 --- a/src/Presentation/SmartStore.Web.Framework/Mvc/UniversalResult.cs +++ b/src/Presentation/SmartStore.Web.Framework/Mvc/UniversalResult.cs @@ -11,7 +11,6 @@ namespace SmartStore.Web.Framework.Mvc { /// An action method result wrapper that handles all required action results in a project. - /// codehint: sm-add public class UniversalResult : ActionResult { public UniversalResult() { From a968af0b6b58281164712cf099738ea157ab977b Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 7 Apr 2015 11:41:37 +0200 Subject: [PATCH 0018/1256] More changes on XML export and file download manager --- .../ExportImport/ExportManager.cs | 192 +++++++++++------- .../Utilities/FileDownloadManager.cs | 17 +- 2 files changed, 128 insertions(+), 81 deletions(-) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 9172a4ffe2..18cf57a3bf 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -11,6 +11,7 @@ using SmartStore.Core; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Orders; @@ -76,75 +77,78 @@ public ExportManager(ICategoryService categoryService, #region Utilities - protected virtual void WriteCategories(XmlWriter xmlWriter, int parentCategoryId) + protected Action> WriteLocalized = (writer, context, content) => + { + if (context.Languages.Count > 1) + { + writer.WriteStartElement("Localized"); + foreach (var language in context.Languages) + { + content(language); + } + writer.WriteEndElement(); + } + }; + + protected virtual void WriteCategories(XmlWriter writer, int parentCategoryId) { var categories = _categoryService.GetAllCategoriesByParentCategoryId(parentCategoryId, true); if (categories != null && categories.Count > 0) { foreach (var category in categories) { - xmlWriter.WriteStartElement("Category"); - xmlWriter.WriteElementString("Id", null, category.Id.ToString()); - xmlWriter.WriteElementString("Name", null, category.Name); - xmlWriter.WriteElementString("Description", null, category.Description); - xmlWriter.WriteElementString("CategoryTemplateId", null, category.CategoryTemplateId.ToString()); - xmlWriter.WriteElementString("MetaKeywords", null, category.MetaKeywords); - xmlWriter.WriteElementString("MetaDescription", null, category.MetaDescription); - xmlWriter.WriteElementString("MetaTitle", null, category.MetaTitle); - xmlWriter.WriteElementString("SeName", null, category.GetSeName(0)); - xmlWriter.WriteElementString("ParentCategoryId", null, category.ParentCategoryId.ToString()); - xmlWriter.WriteElementString("PictureId", null, category.PictureId.ToString()); - xmlWriter.WriteElementString("PageSize", null, category.PageSize.ToString()); - xmlWriter.WriteElementString("AllowCustomersToSelectPageSize", null, category.AllowCustomersToSelectPageSize.ToString()); - xmlWriter.WriteElementString("PageSizeOptions", null, category.PageSizeOptions); - xmlWriter.WriteElementString("PriceRanges", null, category.PriceRanges); - xmlWriter.WriteElementString("ShowOnHomePage", null, category.ShowOnHomePage.ToString()); - xmlWriter.WriteElementString("Published", null, category.Published.ToString()); - xmlWriter.WriteElementString("Deleted", null, category.Deleted.ToString()); - xmlWriter.WriteElementString("DisplayOrder", null, category.DisplayOrder.ToString()); - xmlWriter.WriteElementString("CreatedOnUtc", null, category.CreatedOnUtc.ToString()); - xmlWriter.WriteElementString("UpdatedOnUtc", null, category.UpdatedOnUtc.ToString()); - - - xmlWriter.WriteStartElement("Products"); + writer.WriteStartElement("Category"); + writer.Write("Id", category.Id.ToString()); + writer.Write("Name", category.Name); + writer.Write("Description", category.Description); + 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, true, false)); + 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()); + writer.Write("UpdatedOnUtc", category.UpdatedOnUtc.ToString()); + writer.Write("SubjectToAcl", category.SubjectToAcl.ToString()); + writer.Write("LimitedToStores", category.LimitedToStores.ToString()); + writer.Write("Alias", category.Alias); + writer.Write("DefaultViewMode", category.DefaultViewMode); + + writer.WriteStartElement("Products"); var productCategories = _categoryService.GetProductCategoriesByCategoryId(category.Id, 0, int.MaxValue, true); foreach (var productCategory in productCategories) { var product = productCategory.Product; if (product != null && !product.Deleted) { - xmlWriter.WriteStartElement("ProductCategory"); - xmlWriter.WriteElementString("ProductCategoryId", null, productCategory.Id.ToString()); - xmlWriter.WriteElementString("ProductId", null, productCategory.ProductId.ToString()); - xmlWriter.WriteElementString("IsFeaturedProduct", null, productCategory.IsFeaturedProduct.ToString()); - xmlWriter.WriteElementString("DisplayOrder", null, productCategory.DisplayOrder.ToString()); - xmlWriter.WriteEndElement(); + writer.WriteStartElement("ProductCategory"); + writer.Write("ProductCategoryId", productCategory.Id.ToString()); + writer.Write("ProductId", productCategory.ProductId.ToString()); + writer.Write("IsFeaturedProduct", productCategory.IsFeaturedProduct.ToString()); + writer.Write("DisplayOrder", productCategory.DisplayOrder.ToString()); + writer.WriteEndElement(); } } - xmlWriter.WriteEndElement(); + writer.WriteEndElement(); - xmlWriter.WriteStartElement("SubCategories"); - WriteCategories(xmlWriter, category.Id); - xmlWriter.WriteEndElement(); - xmlWriter.WriteEndElement(); + writer.WriteStartElement("SubCategories"); + WriteCategories(writer, category.Id); + writer.WriteEndElement(); + writer.WriteEndElement(); } } } - protected Action> WriteLocalized = (writer, context, content) => - { - if (context.Languages.Count > 1) - { - writer.WriteStartElement("Localized"); - foreach (var language in context.Languages) - { - content(language); - } - writer.WriteEndElement(); - } - }; - - protected void WritePicture(XmlWriter writer, XmlExportContext context, Picture picture) + protected virtual void WritePicture(XmlWriter writer, XmlExportContext context, Picture picture, int thumbSize) { if (picture != null) { @@ -152,13 +156,33 @@ protected void WritePicture(XmlWriter writer, XmlExportContext context, Picture writer.Write("Id", picture.Id.ToString()); writer.Write("SeoFileName", picture.SeoFilename); writer.Write("MimeType", picture.MimeType); - writer.Write("ThumbImageUrl", _pictureService.GetPictureUrl(picture, _mediaSettings.ProductThumbPictureSize, false, storeLocation: context.Store.Url)); - writer.Write("ImageUrl", _pictureService.GetPictureUrl(picture, _mediaSettings.ProductDetailsPictureSize, false, storeLocation: context.Store.Url)); + writer.Write("ThumbImageUrl", _pictureService.GetPictureUrl(picture, thumbSize, false, storeLocation: context.Store.Url)); + writer.Write("ImageUrl", _pictureService.GetPictureUrl(picture, thumbSize, false, storeLocation: context.Store.Url)); writer.Write("FullSizeImageUrl", _pictureService.GetPictureUrl(picture, 0, false, storeLocation: context.Store.Url)); writer.WriteEndElement(); } } + protected virtual void WriteQuantityUnit(XmlWriter writer, XmlExportContext context, QuantityUnit quantityUnit) + { + if (quantityUnit != null) + { + writer.WriteStartElement("QuantityUnit"); + writer.Write("Id", quantityUnit.Id.ToString()); + writer.Write("Name", quantityUnit.Name); + writer.Write("Description", quantityUnit.Description); + writer.Write("DisplayLocale", quantityUnit.DisplayLocale); + writer.Write("DisplayOrder", quantityUnit.DisplayOrder.ToString()); + writer.Write("IsDefault", quantityUnit.IsDefault.ToString()); + WriteLocalized(writer, context, lang => + { + writer.Write("Name", quantityUnit.GetLocalized(x => x.Name, lang.Id, false, false), lang); + writer.Write("Description", quantityUnit.GetLocalized(x => x.Description, lang.Id, false, false), lang); + }); + writer.WriteEndElement(); + } + } + #endregion #region Methods @@ -386,22 +410,7 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.WriteEndElement(); } - if (product.QuantityUnit != null) - { - writer.WriteStartElement("QuantityUnit"); - writer.Write("Id", product.QuantityUnit.Id.ToString()); - writer.Write("Name", product.QuantityUnit.Name); - writer.Write("Description", product.QuantityUnit.Description); - writer.Write("DisplayLocale", product.QuantityUnit.DisplayLocale); - writer.Write("DisplayOrder", product.QuantityUnit.DisplayOrder.ToString()); - writer.Write("IsDefault", product.QuantityUnit.IsDefault.ToString()); - WriteLocalized(writer, context, lang => - { - writer.Write("Name", product.QuantityUnit.GetLocalized(x => x.Name, lang.Id, false, false), lang); - writer.Write("Description", product.QuantityUnit.GetLocalized(x => x.Description, lang.Id, false, false), lang); - }); - writer.WriteEndElement(); - } + WriteQuantityUnit(writer, context, product.QuantityUnit); writer.WriteStartElement("ProductTags"); foreach (var tag in product.ProductTags) @@ -512,10 +521,12 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo 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)); + WritePicture(writer, context, _pictureService.GetPictureById(pictureId), _mediaSettings.ProductThumbPictureSize); } writer.WriteEndElement(); // Pictures @@ -530,7 +541,7 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.Write("Id", productPicture.Id.ToString()); writer.Write("DisplayOrder", productPicture.DisplayOrder.ToString()); - WritePicture(writer, context, productPicture.Picture); + WritePicture(writer, context, productPicture.Picture, _mediaSettings.ProductThumbPictureSize); writer.WriteEndElement(); } @@ -542,12 +553,49 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo { 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", productCategory.Category.Id.ToString()); + writer.Write("Id", category.Id.ToString()); + writer.Write("Name", category.Name); + writer.Write("Description", category.Description); + 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); + + WriteLocalized(writer, context, lang => + { + writer.Write("Name", category.GetLocalized(x => x.Name, lang.Id, false, false), lang); + writer.Write("Description", category.GetLocalized(x => x.Description, 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(); @@ -577,6 +625,8 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.Write("MetaDescription", manu.MetaDescription); writer.Write("MetaTitle", manu.MetaTitle); + WritePicture(writer, context, manu.Picture, _mediaSettings.ManufacturerThumbPictureSize); + WriteLocalized(writer, context, lang => { writer.Write("Name", manu.GetLocalized(x => x.Name, lang.Id, false, false), lang); diff --git a/src/Presentation/SmartStore.Web.Framework/Utilities/FileDownloadManager.cs b/src/Presentation/SmartStore.Web.Framework/Utilities/FileDownloadManager.cs index 9892246299..2770a7d2c9 100644 --- a/src/Presentation/SmartStore.Web.Framework/Utilities/FileDownloadManager.cs +++ b/src/Presentation/SmartStore.Web.Framework/Utilities/FileDownloadManager.cs @@ -33,7 +33,7 @@ private async Task ProcessUrl(FileDownloadManagerContext context, HttpClient cli { dstStream.Write(bytes, 0, count); - if (context.CancellationToken.IsCancellationRequested) + if (context.CancellationToken != null && context.CancellationToken.IsCancellationRequested) canceled = true; } } @@ -54,7 +54,7 @@ private async Task ProcessUrl(FileDownloadManagerContext context, HttpClient cli } } - private async Task DownloadFiles(FileDownloadManagerContext context) + private async Task DownloadFiles(FileDownloadManagerContext context, List items) { var client = new HttpClient(); @@ -66,7 +66,7 @@ private async Task DownloadFiles(FileDownloadManagerContext context) client.Timeout = context.Timeout; IEnumerable downloadTasksQuery = - from item in context.Items + from item in items select ProcessUrl(context, client, item); // now execute the bunch @@ -87,20 +87,17 @@ from item in context.Items /// /// Start asynchronous download of files /// - public async Task Start(FileDownloadManagerContext context) + /// Download context + /// Items to be downloaded + public async Task StartAsynchronous(FileDownloadManagerContext context, List items) { - await DownloadFiles(context); + await DownloadFiles(context, items); } } public class FileDownloadManagerContext { - /// - /// Items to be downloaded - /// - public List Items { get; set; } - /// /// Optional logger to log errors /// From 64a0a363b99d83f983c58d56d6830706e149b5d0 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 7 Apr 2015 13:47:57 +0200 Subject: [PATCH 0019/1256] XML product export now paged --- .../ExportImport/ExportManager.cs | 97 +++++++++---------- .../ExportImport/IExportManager.cs | 21 ++-- .../Controllers/ProductController.cs | 61 ++++++++---- 3 files changed, 95 insertions(+), 84 deletions(-) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 18cf57a3bf..5940062b54 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -702,65 +702,64 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo writer.WriteEndElement(); } - /// - /// Export product list to XML - /// - /// Products - /// Result in XML format - public virtual string ExportProductsToXml(IList products) - { - string result = ExportProductsToXml(writer => + /// + /// Export product list to XML + /// + /// Stream to write + /// Search context + public virtual void ExportProductsToXml(Stream stream, ProductSearchContext searchContext) + { + var settings = new XmlWriterSettings() { - var context = new XmlExportContext() - { - ProductTemplates = _productTemplateService.GetAllProductTemplates(), - Languages = _languageService.GetAllLanguages(true), - Store = _commonServices.StoreContext.CurrentStore - }; + Encoding = new UTF8Encoding(false), + CheckCharacters = false + }; + + var context = new XmlExportContext() + { + ProductTemplates = _productTemplateService.GetAllProductTemplates(), + Languages = _languageService.GetAllLanguages(true), + Store = _commonServices.StoreContext.CurrentStore + }; + + using (var writer = XmlWriter.Create(stream, settings)) + { + writer.WriteStartDocument(); + writer.WriteStartElement("Products"); + writer.WriteAttributeString("Version", SmartStoreVersion.CurrentVersion); - foreach (var product in products) + for (int i = 0; i < 9999999; ++i) { - writer.WriteStartElement("Product"); + searchContext.PageIndex = i; - try - { - WriteProductToXml(writer, product, context); - } - catch (Exception exc) + var products = _productService.SearchProducts(searchContext); + + foreach (var product in products) { - Logger.Error("{0} (Product.Id {1})".FormatWith(exc.Message, product.Id), exc); + writer.WriteStartElement("Product"); + + try + { + WriteProductToXml(writer, product, context); + } + catch (Exception exc) + { + Logger.Error("{0} (Product.Id {1})".FormatWith(exc.Message, product.Id), exc); + } + + writer.WriteEndElement(); // Product } - writer.WriteEndElement(); // Product + if (!products.HasNextPage) + break; } - }); - return result; - } - - /// - /// Export product(s) to XML - /// - /// Action to export product entities - /// XML writer settings - /// Result in XML format - public virtual string ExportProductsToXml(Action writeProducts, XmlWriterSettings settings = null) - { - var sb = new StringBuilder(); - using (var stringWriter = new StringWriter(sb)) - using (var xmlWriter = XmlWriter.Create(stringWriter, settings)) - { - xmlWriter.WriteStartDocument(); - xmlWriter.WriteStartElement("Products"); - xmlWriter.WriteAttributeString("Version", SmartStoreVersion.CurrentVersion); - - writeProducts(xmlWriter); - - xmlWriter.WriteEndElement(); - xmlWriter.WriteEndDocument(); - xmlWriter.Close(); + writer.WriteEndElement(); + writer.WriteEndDocument(); + writer.Flush(); + writer.Close(); - return stringWriter.ToString(); + stream.Seek(0, SeekOrigin.Begin); } } diff --git a/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs index d440b30489..0c8afdbcfd 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/IExportManager.cs @@ -1,11 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Globalization; +using System.Collections.Generic; using System.IO; using System.Xml; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Orders; +using SmartStore.Services.Catalog; namespace SmartStore.Services.ExportImport { @@ -35,20 +34,12 @@ public interface IExportManager /// Context objects void WriteProductToXml(XmlWriter writer, Product product, XmlExportContext context); - /// - /// Export product list to xml - /// - /// Products - /// Result in XML format - string ExportProductsToXml(IList products); - /// - /// Export product(s) to XML + /// Export product list to XML /// - /// Action to export product entities - /// XML writer settings - /// Result in XML format - string ExportProductsToXml(Action writeProducts, XmlWriterSettings settings = null); + /// Stream to write + /// Search context + void ExportProductsToXml(Stream stream, ProductSearchContext searchContext); /// /// Export products to XLSX diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index b7d5a028a3..ffca4580b0 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Mime; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -2709,24 +2710,28 @@ public ActionResult ExportXmlAll() { using (var scope = new DbContextScope(_dbContext, autoDetectChanges: false, forceNoTracking: true)) { - var ctx = new ProductSearchContext(); - ctx.LanguageId = _workContext.WorkingLanguage.Id; - ctx.OrderBy = ProductSortingEnum.Position; - ctx.PageSize = int.MaxValue; - ctx.ShowHidden = true; + var searchContext = new ProductSearchContext + { + LanguageId = _workContext.WorkingLanguage.Id, + OrderBy = ProductSortingEnum.Position, + PageSize = 100, + ShowHidden = true + }; - var products = _productService.SearchProducts(ctx); + var stream = new MemoryStream(); + _exportManager.ExportProductsToXml(stream, searchContext); + + var result = new FileStreamResult(stream, MediaTypeNames.Text.Xml); + result.FileDownloadName = string.Format("products_{0}.xml", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")); - var fileName = string.Format("products_{0}.xml", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")); - var xml = _exportManager.ExportProductsToXml(products); - return new XmlDownloadResult(xml, fileName); + return result; } } catch (Exception exc) { NotifyError(exc); - return RedirectToAction("List"); } + return RedirectToAction("List"); } [HttpPost] @@ -2735,21 +2740,37 @@ public ActionResult ExportXmlSelected(string selectedIds) if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); - using (var scope = new DbContextScope(_dbContext, autoDetectChanges: false, forceNoTracking: true)) - { - var products = new List(); - if (selectedIds != null) + try + { + using (var scope = new DbContextScope(_dbContext, autoDetectChanges: false, forceNoTracking: true)) { - var ids = selectedIds + var searchContext = new ProductSearchContext + { + LanguageId = _workContext.WorkingLanguage.Id, + OrderBy = ProductSortingEnum.Position, + PageSize = 100, + ShowHidden = true + }; + + searchContext.ProductIds = selectedIds .Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => Convert.ToInt32(x)) - .ToArray(); - products.AddRange(_productService.GetProductsByIds(ids)); - } + .ToList(); + + var stream = new MemoryStream(); + _exportManager.ExportProductsToXml(stream, searchContext); - var xml = _exportManager.ExportProductsToXml(products); - return new XmlDownloadResult(xml, "products.xml"); + var result = new FileStreamResult(stream, MediaTypeNames.Text.Xml); + result.FileDownloadName = string.Format("products_{0}.xml", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")); + + return result; + } } + catch (Exception exc) + { + NotifyError(exc); + } + return RedirectToAction("List"); } public ActionResult ExportExcelAll() From 5f923708d8e5e7958c9eea1f8b81db9f656dcef5 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 7 Apr 2015 13:51:43 +0200 Subject: [PATCH 0020/1256] Updated changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 0a799e9133..305e36d186 100644 --- a/changelog.md +++ b/changelog.md @@ -29,6 +29,7 @@ * Minor UI tweaks in checkout process * #666 Export addresses in customer export * New shopping cart setting ShowItemsFromWishlistToCartButton +* XML product export now paged and more data exported ### Bugfixes * Instant search box did not display all results when SQL Fulltext Search was enabled From e73bf35a1faf731f81c8ae06bb094a259569ce3b Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 7 Apr 2015 16:59:19 +0200 Subject: [PATCH 0021/1256] Catalog Settings > Product Detail > Base price for bundle items was without effect --- .../SmartStore.Web/Views/Product/_BundleItems.cshtml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Views/Product/_BundleItems.cshtml b/src/Presentation/SmartStore.Web/Views/Product/_BundleItems.cshtml index fb451a50b9..a61c43934e 100644 --- a/src/Presentation/SmartStore.Web/Views/Product/_BundleItems.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Product/_BundleItems.cshtml @@ -67,9 +67,12 @@ @Html.Raw(item.ProductPrice.PriceWithDiscount) -
- @item.BasePriceInfo -
+ @if(item.ProductPrice.BundleItemShowBasePrice == true) + { +
+ @item.BasePriceInfo +
+ } } From 2879beef2f2fb32346d963167b96250431953c9c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 7 Apr 2015 22:12:31 +0200 Subject: [PATCH 0022/1256] Resolves #670 Move FileDownloadManager to SmartStore.Core.Utilities --- src/Libraries/SmartStore.Core/SmartStore.Core.csproj | 2 ++ .../SmartStore.Core}/Utilities/FileDownloadManager.cs | 2 +- .../SmartStore.Web.Framework/SmartStore.Web.Framework.csproj | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) rename src/{Presentation/SmartStore.Web.Framework => Libraries/SmartStore.Core}/Utilities/FileDownloadManager.cs (99%) diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index c668a31953..21183c082f 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -105,6 +105,7 @@ ..\..\packages\System.Linq.Dynamic.1.0.0\lib\net40\System.Linq.Dynamic.dll + @@ -547,6 +548,7 @@ + diff --git a/src/Presentation/SmartStore.Web.Framework/Utilities/FileDownloadManager.cs b/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs similarity index 99% rename from src/Presentation/SmartStore.Web.Framework/Utilities/FileDownloadManager.cs rename to src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs index 2770a7d2c9..f0ac584ac1 100644 --- a/src/Presentation/SmartStore.Web.Framework/Utilities/FileDownloadManager.cs +++ b/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; using SmartStore.Core.Logging; -namespace SmartStore.Web.Framework.Utilities +namespace SmartStore.Utilities { public class FileDownloadManager { diff --git a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj index 792068e11e..037c1ffd70 100644 --- a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj +++ b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj @@ -333,7 +333,6 @@ - From 5551b74db62bb6e8919404cf6283d25956f28040 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 7 Apr 2015 18:22:54 +0200 Subject: [PATCH 0023/1256] Minor fixes --- .../Extensions/MiscExtensions.cs | 4 + .../Utilities/FileDownloadManager.cs | 79 ++++++++++--------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs index 8fe27314e0..da7f1483e3 100644 --- a/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs @@ -20,6 +20,7 @@ public static void Dump(this Exception exc) } catch { } } + public static string ToAllMessages(this Exception exc) { var sb = new StringBuilder(); @@ -37,6 +38,7 @@ public static string ToElapsedMinutes(this Stopwatch watch) { return "{0:0.0}".FormatWith(TimeSpan.FromMilliseconds(watch.ElapsedMilliseconds).TotalMinutes); } + public static string ToElapsedSeconds(this Stopwatch watch) { return "{0:0.0}".FormatWith(TimeSpan.FromMilliseconds(watch.ElapsedMilliseconds).TotalSeconds); @@ -47,6 +49,7 @@ public static bool HasColumn(this DataView dv, string columnName) dv.RowFilter = "ColumnName='" + columnName + "'"; return dv.Count > 0; } + public static string GetDataType(this DataTable dt, string columnName) { dt.DefaultView.RowFilter = "ColumnName='" + columnName + "'"; @@ -76,6 +79,7 @@ public static object SafeConvert(this TypeConverter converter, string value) } return null; } + public static bool IsEqual(this TypeConverter converter, string value, object compareWith) { object convertedObject = converter.SafeConvert(value); diff --git a/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs b/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs index f0ac584ac1..6b95e181b6 100644 --- a/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs +++ b/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs @@ -15,6 +15,46 @@ public class FileDownloadManager { private const int _bufferSize = 16384; + /// + /// Start asynchronous download of files + /// + /// Download context + /// Items to be downloaded + public async Task DownloadAsync(FileDownloadManagerContext context, IEnumerable items) + { + await DownloadFiles(context, items); + } + + private async Task DownloadFiles(FileDownloadManagerContext context, IEnumerable items) + { + var client = new HttpClient(); + + client.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue(); + client.DefaultRequestHeaders.CacheControl.NoCache = true; + client.DefaultRequestHeaders.Add("Connection", "Keep-alive"); + + if (context.Timeout != null) + client.Timeout = context.Timeout; + + IEnumerable downloadTasksQuery = + from item in items + select ProcessUrl(context, client, item); + + // now execute the bunch + List downloadTasks = downloadTasksQuery.ToList(); + + while (downloadTasks.Count > 0) + { + // identify the first task that completes + Task firstFinishedTask = await Task.WhenAny(downloadTasks); + + // process only once + downloadTasks.Remove(firstFinishedTask); + + await firstFinishedTask; + } + } + private async Task ProcessUrl(FileDownloadManagerContext context, HttpClient client, FileDownloadManagerItem item) { try @@ -54,45 +94,6 @@ private async Task ProcessUrl(FileDownloadManagerContext context, HttpClient cli } } - private async Task DownloadFiles(FileDownloadManagerContext context, List items) - { - var client = new HttpClient(); - - client.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue(); - client.DefaultRequestHeaders.CacheControl.NoCache = true; - client.DefaultRequestHeaders.Add("Connection", "Keep-alive"); - - if (context.Timeout != null) - client.Timeout = context.Timeout; - - IEnumerable downloadTasksQuery = - from item in items - select ProcessUrl(context, client, item); - - // now execute the bunch - List downloadTasks = downloadTasksQuery.ToList(); - - while (downloadTasks.Count > 0) - { - // identify the first task that completes - Task firstFinishedTask = await Task.WhenAny(downloadTasks); - - // process only once - downloadTasks.Remove(firstFinishedTask); - - await firstFinishedTask; - } - } - - /// - /// Start asynchronous download of files - /// - /// Download context - /// Items to be downloaded - public async Task StartAsynchronous(FileDownloadManagerContext context, List items) - { - await DownloadFiles(context, items); - } } From 26504526589731be7a502fe0e21bdb6dced80f97 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 8 Apr 2015 15:41:29 +0200 Subject: [PATCH 0024/1256] Removed unused private method --- .../Controllers/ProductController.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index ffca4580b0..3c5a462c99 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -829,20 +829,6 @@ private void PrepareProductPictureThumbnailModel(ProductModel model, Product pro } } - [NonAction] - private string[] ParseProductTags(string productTags) - { - var result = new List(); - if (!String.IsNullOrWhiteSpace(productTags)) - { - string[] values = productTags.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - foreach (string val1 in values) - if (!String.IsNullOrEmpty(val1.Trim())) - result.Add(val1.Trim()); - } - return result.ToArray(); - } - #endregion Utitilies #region Methods From ea406029a8920ba36524041a25484d9062c48a2b Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 8 Apr 2015 18:06:54 +0200 Subject: [PATCH 0025/1256] Added a fake user-agent to KeepAliveTask --- src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs b/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs index cac76727e4..74a382ccae 100644 --- a/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs +++ b/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs @@ -26,7 +26,8 @@ public void Execute(TaskExecutionContext ctx) { using (var wc = new WebClient()) { - //wc.Headers.Add("SmartStore.NET"); // makes problems + // FAKE a user-agent + wc.Headers.Add("user-agent", @"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"); if (!url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && !url.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { url = "http://" + url; From 84c2566eb073c2578c3467f876d34be1aa1203d4 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 10 Apr 2015 18:20:54 +0200 Subject: [PATCH 0026/1256] global.asax and web.config are not required to be writable anymore --- src/Libraries/SmartStore.Core/WebHelper.cs | 37 +++---------------- .../Security/FilePermissionHelper.cs | 11 +----- 2 files changed, 7 insertions(+), 41 deletions(-) diff --git a/src/Libraries/SmartStore.Core/WebHelper.cs b/src/Libraries/SmartStore.Core/WebHelper.cs index 997e0fa399..0f4d108a91 100644 --- a/src/Libraries/SmartStore.Core/WebHelper.cs +++ b/src/Libraries/SmartStore.Core/WebHelper.cs @@ -2,6 +2,7 @@ using System.Configuration; using System.IO; using System.Text.RegularExpressions; +using System.Threading; using System.Web; using System.Web.Configuration; using SmartStore.Collections; @@ -467,40 +468,12 @@ public virtual T QueryString(string name) /// Redirect URL; empty string if you want to redirect to the current page URL public virtual void RestartAppDomain(bool makeRedirect = false, string redirectUrl = "") { - if (WebHelper.GetTrustLevel() > AspNetHostingPermissionLevel.Medium) - { - //full trust - HttpRuntime.UnloadAppDomain(); - - if (!OptimizedCompilationsEnabled) - { - // not a good idea with optimized compilation! - TryWriteGlobalAsax(); - } - } - else - { - //medium trust - bool success = TryWriteWebConfig(); - if (!success) - { - throw new SmartException("SmartStore.NET needs to be restarted due to a configuration change, but was unable to do so." + Environment.NewLine + - "To prevent this issue in the future, a change to the web server configuration is required:" + Environment.NewLine + - "- run the application in a full trust environment, or" + Environment.NewLine + - "- give the application write access to the 'web.config' file."); - } + HttpRuntime.UnloadAppDomain(); - success = TryWriteGlobalAsax(); - if (!success) - { - throw new SmartException("SmartStore.NET needs to be restarted due to a configuration change, but was unable to do so." + Environment.NewLine + - "To prevent this issue in the future, a change to the web server configuration is required:" + Environment.NewLine + - "- run the application in a full trust environment, or" + Environment.NewLine + - "- give the application write access to the 'Global.asax' file."); - } - } + // without this, MVC may fail resolving controllers for newly installed plugins after IIS restart + Thread.Sleep(250); - // If setting up extensions/modules requires an AppDomain restart, it's very unlikely the + // If setting up plugins requires an AppDomain restart, it's very unlikely the // current request can be processed correctly. So, we redirect to the same URL, so that the // new request will come to the newly started AppDomain. if (_httpContext != null && makeRedirect) diff --git a/src/Presentation/SmartStore.Web.Framework/Security/FilePermissionHelper.cs b/src/Presentation/SmartStore.Web.Framework/Security/FilePermissionHelper.cs index 3070f18b28..e601c80016 100644 --- a/src/Presentation/SmartStore.Web.Framework/Security/FilePermissionHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Security/FilePermissionHelper.cs @@ -154,20 +154,13 @@ public static IEnumerable GetDirectoriesWrite(IWebHelper webHelper) { string rootDir = webHelper.MapPath("~/"); var dirsToCheck = new List(); - //dirsToCheck.Add(rootDir); dirsToCheck.Add(Path.Combine(rootDir, "App_Data")); - //dirsToCheck.Add(Path.Combine(rootDir, "App_Data\\files")); - //dirsToCheck.Add(Path.Combine(rootDir, "App_Data\\files\\exportimport")); dirsToCheck.Add(Path.Combine(rootDir, "bin")); dirsToCheck.Add(Path.Combine(rootDir, "content")); dirsToCheck.Add(Path.Combine(rootDir, "content\\files\\exportimport")); - //dirsToCheck.Add(Path.Combine(rootDir, "content\\images")); - //dirsToCheck.Add(Path.Combine(rootDir, "content\\images\\thumbs")); - //dirsToCheck.Add(Path.Combine(rootDir, "content\\images\\uploaded")); dirsToCheck.Add(Path.Combine(rootDir, "media")); dirsToCheck.Add(Path.Combine(rootDir, "media\\thumbs")); dirsToCheck.Add(Path.Combine(rootDir, "media\\uploaded")); - //dirsToCheck.Add(Path.Combine(rootDir, "media\\exportimport")); dirsToCheck.Add(Path.Combine(rootDir, "plugins")); dirsToCheck.Add(Path.Combine(rootDir, "plugins\\bin")); return dirsToCheck; @@ -182,8 +175,8 @@ public static IEnumerable GetFilesWrite(IWebHelper webHelper) { string rootDir = webHelper.MapPath("~/"); var filesToCheck = new List(); - filesToCheck.Add(Path.Combine(rootDir, "Global.asax")); - filesToCheck.Add(Path.Combine(rootDir, "web.config")); + //filesToCheck.Add(Path.Combine(rootDir, "Global.asax")); + //filesToCheck.Add(Path.Combine(rootDir, "web.config")); filesToCheck.Add(Path.Combine(rootDir, "App_Data\\InstalledPlugins.txt")); filesToCheck.Add(Path.Combine(rootDir, "App_Data\\Settings.txt")); return filesToCheck; From ef8ab588f4e265a9b00ad14142fb2a8e8ca93e58 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 10 Apr 2015 20:22:59 +0200 Subject: [PATCH 0027/1256] Heavily refactored async behoviour throughout the app. Now every background task (TPL or ITask) gets wrapped in AsyncRunner.Run(), which ensures that a single thread-specific lifetime scope is spawned for the unit of work. Increases stability and performance in background tasks condiderably. --- .../SmartStore.Core/Async/AsyncRunner.cs | 193 ++++++++++++- .../Extensions/TypeExtensions.cs | 1 - .../Infrastructure/ContextState.cs | 81 ++++++ .../AutofacLifetimeScopeProvider.cs | 80 ------ .../AutofacRequestLifetimeHttpModule.cs | 6 +- .../DependencyManagement/ContainerManager.cs | 24 +- .../DefaultLifetimeScopeAccessor.cs | 91 ++++++ .../DefaultLifetimeScopeProvider.cs | 35 +++ .../ILifetimeScopeAccessor.cs | 43 +++ .../Infrastructure/MostRecentlyUsedList.cs | 4 + .../ObjectSignatureAttribute.cs | 1 - .../Infrastructure/SmartStoreEngine.cs | 31 +- .../SmartStore.Core/SmartStore.Core.csproj | 5 +- .../Events/EventPublisher.cs | 2 +- .../ExportImport/IImportManager.cs | 18 +- .../ExportImport/ImportManager.cs | 266 +++++++++--------- .../SmartStore.Services/Tasks/Job.cs | 33 ++- .../Tasks/TaskExecutionContext.cs | 2 +- .../SmartStore.Services/Tasks/TaskThread.cs | 18 +- .../Services/AmazonPayService.cs | 5 +- .../Services/GoogleFeedService.cs | 10 +- .../DependencyRegistrar.cs | 4 +- .../Plugins/FeedPluginHelper.cs | 94 ++++--- .../WebApi/WebApiStartupTask.cs | 3 +- .../Controllers/CommonController.cs | 7 +- .../Controllers/ProductController.cs | 10 +- .../Controllers/ScheduleTaskController.cs | 4 +- 27 files changed, 707 insertions(+), 364 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Infrastructure/ContextState.cs delete mode 100644 src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/AutofacLifetimeScopeProvider.cs create mode 100644 src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/DefaultLifetimeScopeAccessor.cs create mode 100644 src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/DefaultLifetimeScopeProvider.cs create mode 100644 src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ILifetimeScopeAccessor.cs diff --git a/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs b/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs index 9b38188671..a0372bfca7 100644 --- a/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs +++ b/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs @@ -2,15 +2,18 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Web.Hosting; using Autofac; using SmartStore.Core.Infrastructure; -using SmartStore.Core.Infrastructure.DependencyManagement; +using SmartStore.Utilities; namespace SmartStore.Core.Async { public static class AsyncRunner { + private static readonly BackgroundWorkHost _host = new BackgroundWorkHost(); + /// /// Execute's an async Task method which has a void return value synchronously @@ -75,59 +78,143 @@ public static TResult RunSync(Func> func) return ret; } - public static Task Run(Action action) + public static Task Run(Action action) { return Run(action, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); } - public static Task Run(Action action, CancellationToken cancellationToken) + public static Task Run(Action action, CancellationToken cancellationToken) { return Run(action, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default); } - public static Task Run(Action action, TaskCreationOptions options) + public static Task Run(Action action, TaskCreationOptions options) { return Run(action, CancellationToken.None, options, TaskScheduler.Default); } - public static Task Run(Action action, CancellationToken cancellationToken, TaskCreationOptions options) + public static Task Run(Action action, CancellationToken cancellationToken, TaskCreationOptions options) { return Run(action, cancellationToken, options, TaskScheduler.Default); } - public static Task Run(Action action, TaskScheduler scheduler) + public static Task Run(Action action, TaskScheduler scheduler) { return Run(action, CancellationToken.None, TaskCreationOptions.None, scheduler); } - - public static Task Run(Action action, CancellationToken cancellationToken, TaskCreationOptions options, TaskScheduler scheduler) + + public static Task Run(Action action, CancellationToken cancellationToken, TaskCreationOptions options, TaskScheduler scheduler) { Guard.ArgumentNotNull(() => action); Guard.ArgumentNotNull(() => scheduler); + var ct = _host.CreateCompositeCancellationTokenSource(cancellationToken).Token; + options |= TaskCreationOptions.LongRunning; // enforce an exclusive thread (not from pool) + var t = Task.Factory.StartNew(() => { - using (var container = EngineContext.Current.ContainerManager.Container.BeginLifetimeScope(AutofacLifetimeScopeProvider.HttpRequestTag)) + var accessor = EngineContext.Current.ContainerManager.ScopeAccessor; + using (var scope = accessor.BeginContextAwareScope()) { - action(container); + action(accessor.GetLifetimeScope(null), ct); } - }, cancellationToken, options, scheduler); + }, ct, options, scheduler); + + _host.Register(t, ct); return t; } - public static Task Run(Action action, object state, CancellationToken cancellationToken, TaskCreationOptions options, TaskScheduler scheduler) + public static Task Run(Action action, object state, CancellationToken cancellationToken, TaskCreationOptions options, TaskScheduler scheduler) { Guard.ArgumentNotNull(() => state); Guard.ArgumentNotNull(() => action); Guard.ArgumentNotNull(() => scheduler); + var ct = _host.CreateCompositeCancellationTokenSource(cancellationToken).Token; + options |= TaskCreationOptions.LongRunning; // enforce an exclusive thread (not from pool) + + var t = Task.Factory.StartNew((o) => + { + var accessor = EngineContext.Current.ContainerManager.ScopeAccessor; + using (var scope = accessor.BeginContextAwareScope()) + { + action(accessor.GetLifetimeScope(null), ct, o); + } + }, state, ct, options, scheduler); + + _host.Register(t, ct); + + return t; + } + + + + public static Task Run(Func function) + { + return Run(function, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); + } + + public static Task Run(Func function, CancellationToken cancellationToken) + { + return Run(function, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default); + } + + public static Task Run(Func function, TaskCreationOptions options) + { + return Run(function, CancellationToken.None, options, TaskScheduler.Default); + } + + public static Task Run(Func function, CancellationToken cancellationToken, TaskCreationOptions options) + { + return Run(function, cancellationToken, options, TaskScheduler.Default); + } + + public static Task Run(Func function, TaskScheduler scheduler) + { + return Run(function, CancellationToken.None, TaskCreationOptions.None, scheduler); + } + + public static Task Run(Func function, CancellationToken cancellationToken, TaskCreationOptions options, TaskScheduler scheduler) + { + Guard.ArgumentNotNull(() => function); + Guard.ArgumentNotNull(() => scheduler); + + var ct = _host.CreateCompositeCancellationTokenSource(cancellationToken).Token; + options |= TaskCreationOptions.LongRunning; // enforce an exclusive thread (not from pool) + + var t = Task.Factory.StartNew(() => + { + var accessor = EngineContext.Current.ContainerManager.ScopeAccessor; + using (var scope = accessor.BeginContextAwareScope()) + { + return function(accessor.GetLifetimeScope(null), ct); + } + }, ct, options, scheduler); + + _host.Register(t, ct); + + return t; + } + + public static Task Run(Func function, object state, CancellationToken cancellationToken, TaskCreationOptions options, TaskScheduler scheduler) + { + Guard.ArgumentNotNull(() => state); + Guard.ArgumentNotNull(() => function); + Guard.ArgumentNotNull(() => scheduler); + + var ct = _host.CreateCompositeCancellationTokenSource(cancellationToken).Token; + options |= TaskCreationOptions.LongRunning; // enforce an exclusive thread (not from pool) + var t = Task.Factory.StartNew((o) => { - using (var container = EngineContext.Current.ContainerManager.Container.BeginLifetimeScope(AutofacLifetimeScopeProvider.HttpRequestTag)) + var accessor = EngineContext.Current.ContainerManager.ScopeAccessor; + using (var scope = accessor.BeginContextAwareScope()) { - action(container, o); + return function(accessor.GetLifetimeScope(null), ct, o); } - }, state, cancellationToken, options, scheduler); + }, state, ct, options, scheduler); + + _host.Register(t, ct); return t; } @@ -193,4 +280,80 @@ public override SynchronizationContext CreateCopy() } + internal class BackgroundWorkHost : IRegisteredObject + { + private CancellationTokenSource _shutdownCancellationTokenSource = new CancellationTokenSource(); + private int _numRunningWorkItems = 0; + + public BackgroundWorkHost() + { + HostingEnvironment.RegisterObject(this); + } + + public void Stop(bool immediate) + { + int num; + lock (this) + { + _shutdownCancellationTokenSource.Cancel(); + num = _numRunningWorkItems; + } + if (num == 0) + { + FinalShutdown(); + } + } + + public CancellationTokenSource CreateCompositeCancellationTokenSource(CancellationToken userCancellationToken) + { + if (userCancellationToken == CancellationToken.None) + { + return _shutdownCancellationTokenSource; + } + return CancellationTokenSource.CreateLinkedTokenSource(_shutdownCancellationTokenSource.Token, userCancellationToken); + } + + public void Register(Task work, CancellationToken cancellationToken) + { + if (!cancellationToken.IsCancellationRequested) + { + lock (this) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + _numRunningWorkItems++; + } + + work.ContinueWith( + WorkItemComplete, + CancellationToken.None, + TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + } + } + + private void WorkItemComplete(Task work) + { + int num; + bool isCancellationRequested; + lock (this) + { + num = --_numRunningWorkItems; + isCancellationRequested = _shutdownCancellationTokenSource.IsCancellationRequested; + } + if (num == 0 && isCancellationRequested) + { + FinalShutdown(); + } + } + + private void FinalShutdown() + { + HostingEnvironment.UnregisterObject(this); + } + + } + } diff --git a/src/Libraries/SmartStore.Core/Extensions/TypeExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/TypeExtensions.cs index 1f651a8ee1..fd92e44f83 100644 --- a/src/Libraries/SmartStore.Core/Extensions/TypeExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/TypeExtensions.cs @@ -544,7 +544,6 @@ public static TAttribute GetAttribute(this ICustomAttributeProvider } return null; - } public static bool HasAttribute(this ICustomAttributeProvider target, bool inherits) where TAttribute : Attribute diff --git a/src/Libraries/SmartStore.Core/Infrastructure/ContextState.cs b/src/Libraries/SmartStore.Core/Infrastructure/ContextState.cs new file mode 100644 index 0000000000..996493f80d --- /dev/null +++ b/src/Libraries/SmartStore.Core/Infrastructure/ContextState.cs @@ -0,0 +1,81 @@ +using System; +using System.Runtime.Remoting.Messaging; +using System.Threading; +using System.Web; + +namespace SmartStore.Core.Infrastructure +{ + /// + /// Holds some state for the current HttpContext or thread + /// + /// The type of data to store + public class ContextState where T : class + { + private readonly string _name; + private readonly Func _defaultValue; + + public ContextState(string name) + { + _name = name; + } + + public ContextState(string name, Func defaultValue) + { + _name = name; + _defaultValue = defaultValue; + } + + public T GetState() + { + if (HttpContext.Current == null) + { + var data = CallContext.GetData(_name); + + if (data == null) + { + if (_defaultValue != null) + { + CallContext.SetData(_name, data = _defaultValue()); + return data as T; + } + } + + return data as T; + } + + if (HttpContext.Current.Items[_name] == null) + { + HttpContext.Current.Items[_name] = _defaultValue == null ? null : _defaultValue(); + } + + return HttpContext.Current.Items[_name] as T; + } + + public void SetState(T state) + { + if (HttpContext.Current == null) + { + CallContext.SetData(_name, state); + } + else + { + HttpContext.Current.Items[_name] = state; + } + } + + public void RemoveState() + { + if (HttpContext.Current == null) + { + CallContext.FreeNamedDataSlot(_name); + } + else + { + if (HttpContext.Current.Items.Contains(_name)) + { + HttpContext.Current.Items.Remove(_name); + } + } + } + } +} diff --git a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/AutofacLifetimeScopeProvider.cs b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/AutofacLifetimeScopeProvider.cs deleted file mode 100644 index b307f82e78..0000000000 --- a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/AutofacLifetimeScopeProvider.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Web; -using Autofac; -using Autofac.Integration.Mvc; - -namespace SmartStore.Core.Infrastructure.DependencyManagement -{ - public class AutofacLifetimeScopeProvider : ILifetimeScopeProvider - { - private readonly ILifetimeScope _container; - internal static readonly object HttpRequestTag = "AutofacWebRequest"; - - public AutofacLifetimeScopeProvider(ILifetimeScope container) - { - Guard.ArgumentNotNull(() => container); - - this._container = container; - AutofacRequestLifetimeHttpModule.SetLifetimeScopeProvider(this); - - } - - public ILifetimeScope ApplicationContainer - { - get { return _container; } - } - - public void EndLifetimeScope() - { - try - { - ILifetimeScope lifetimeScope = LifetimeScope; - if (lifetimeScope != null) - { - lifetimeScope.Dispose(); - HttpContext.Current.Items.Remove(typeof(ILifetimeScope)); - } - } - catch { } - } - - public ILifetimeScope GetLifetimeScope(Action configurationAction) - { - //little hack here to get dependencies when HttpContext is not available - if (HttpContext.Current != null) - { - return LifetimeScope ?? (LifetimeScope = GetLifetimeScopeCore(configurationAction)); - } - else - { - return GetLifetimeScopeCore(configurationAction); - } - } - - protected virtual ILifetimeScope GetLifetimeScopeCore(Action configurationAction) - { - return (configurationAction == null) - ? _container.BeginLifetimeScope(HttpRequestTag) - : _container.BeginLifetimeScope(HttpRequestTag, configurationAction); - } - - private static ILifetimeScope LifetimeScope - { - get - { - return (ILifetimeScope)HttpContext.Current.Items[typeof(ILifetimeScope)]; - } - set - { - HttpContext.Current.Items[typeof(ILifetimeScope)] = value; - } - } - - - } -} diff --git a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/AutofacRequestLifetimeHttpModule.cs b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/AutofacRequestLifetimeHttpModule.cs index 9f84b3d57b..a3fa432497 100644 --- a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/AutofacRequestLifetimeHttpModule.cs +++ b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/AutofacRequestLifetimeHttpModule.cs @@ -1,7 +1,5 @@ using System; -using System.Threading; using System.Web; -using Autofac; using Autofac.Integration.Mvc; namespace SmartStore.Core.Infrastructure.DependencyManagement @@ -12,7 +10,6 @@ namespace SmartStore.Core.Infrastructure.DependencyManagement /// public class AutofacRequestLifetimeHttpModule : IHttpModule { - #region New public void Init(HttpApplication context) { @@ -42,13 +39,12 @@ public static void SetLifetimeScopeProvider(ILifetimeScopeProvider lifetimeScope internal static ILifetimeScopeProvider LifetimeScopeProvider { get; - set; + private set; } public void Dispose() { } - #endregion } } diff --git a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs index b06cf107b0..7bac9acb62 100644 --- a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs +++ b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs @@ -1,12 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Web; -using System.Threading; using Autofac; using Autofac.Builder; -using Autofac.Integration.Mvc; -using SmartStore.Utilities; using SmartStore.Core.Caching; namespace SmartStore.Core.Infrastructure.DependencyManagement @@ -121,21 +117,17 @@ public T InjectUnsetProperties(T instance, ILifetimeScope scope = null) public ILifetimeScope Scope() { - ILifetimeScope scope = null; - try - { - scope = AutofacDependencyResolver.Current.RequestLifetimeScope; - } - catch { } + var scope = _container.Resolve().GetLifetimeScope(null); + return scope ?? _container; + } - if (scope == null) + public ILifetimeScopeAccessor ScopeAccessor + { + get { - // really hackisch. But strange things are going on ?? :-) - scope = _container.BeginLifetimeScope("AutofacWebRequest"); + return _container.Resolve(); } - - return scope ?? _container; - } + } } diff --git a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/DefaultLifetimeScopeAccessor.cs b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/DefaultLifetimeScopeAccessor.cs new file mode 100644 index 0000000000..8cbf076078 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/DefaultLifetimeScopeAccessor.cs @@ -0,0 +1,91 @@ +using System; +using System.Diagnostics; +using System.Web; +using Autofac; +using Autofac.Core.Lifetime; +using SmartStore.Core.Logging; +using SmartStore.Utilities; + +namespace SmartStore.Core.Infrastructure.DependencyManagement +{ + public class DefaultLifetimeScopeAccessor : ILifetimeScopeAccessor + { + private ContextState _state; + private readonly ILifetimeScope _rootContainer; + internal static readonly object ScopeTag = "AutofacWebRequest"; + + public DefaultLifetimeScopeAccessor(ILifetimeScope rootContainer) + { + Guard.ArgumentNotNull(() => rootContainer); + + //rootContainer.ChildLifetimeScopeBeginning += OnScopeBeginning; + + this._rootContainer = rootContainer; + this._state = new ContextState("CustomLifetimeScopeProvider.WorkScope"); + } + + public ILifetimeScope ApplicationContainer + { + get { return _rootContainer; } + } + + public IDisposable BeginContextAwareScope() + { + var disposer = HttpContext.Current != null + ? ActionDisposable.Empty + : new ActionDisposable(() => this.EndLifetimeScope()); + + return disposer; + } + + public void EndLifetimeScope() + { + try + { + var scope = _state.GetState(); + if (scope != null) + { + try + { + scope.Resolve().Flush(); + } + catch { } + scope.Dispose(); + _state.RemoveState(); + } + } + catch { } + } + + public ILifetimeScope GetLifetimeScope(Action configurationAction) + { + var scope = _state.GetState(); + if (scope == null) + { + _state.SetState((scope = BeginLifetimeScope(configurationAction))); + //scope.CurrentScopeEnding += OnScopeEnding; + } + return scope; + } + + private void OnScopeBeginning(object sender, LifetimeScopeBeginningEventArgs args) + { + bool isWeb = System.Web.HttpContext.Current != null; + Debug.WriteLine("Scope Begin, Web: " + isWeb); + } + + private void OnScopeEnding(object sender, LifetimeScopeEndingEventArgs args) + { + bool isWeb = System.Web.HttpContext.Current != null; + Debug.WriteLine("Scope END, Web: " + isWeb); + } + + private ILifetimeScope BeginLifetimeScope(Action configurationAction) + { + return (configurationAction == null) + ? _rootContainer.BeginLifetimeScope(ScopeTag) + : _rootContainer.BeginLifetimeScope(ScopeTag, configurationAction); + } + + } +} diff --git a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/DefaultLifetimeScopeProvider.cs b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/DefaultLifetimeScopeProvider.cs new file mode 100644 index 0000000000..9f01c73248 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/DefaultLifetimeScopeProvider.cs @@ -0,0 +1,35 @@ +using System; +using Autofac; +using Autofac.Integration.Mvc; + +namespace SmartStore.Core.Infrastructure.DependencyManagement +{ + public class DefaultLifetimeScopeProvider : ILifetimeScopeProvider + { + private readonly ILifetimeScopeAccessor _accessor; + + public DefaultLifetimeScopeProvider(ILifetimeScopeAccessor accessor) + { + Guard.ArgumentNotNull(() => accessor); + + this._accessor = accessor; + AutofacRequestLifetimeHttpModule.SetLifetimeScopeProvider(this); + } + + public ILifetimeScope ApplicationContainer + { + get { return _accessor.ApplicationContainer; } + } + + public void EndLifetimeScope() + { + _accessor.EndLifetimeScope(); + } + + public ILifetimeScope GetLifetimeScope(Action configurationAction) + { + return _accessor.GetLifetimeScope(configurationAction); + } + + } +} diff --git a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ILifetimeScopeAccessor.cs b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ILifetimeScopeAccessor.cs new file mode 100644 index 0000000000..03beda80b8 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ILifetimeScopeAccessor.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using Autofac; + +namespace SmartStore.Core.Infrastructure.DependencyManagement +{ + public interface ILifetimeScopeAccessor + { + /// + /// Gets the global, application-wide container. + /// + ILifetimeScope ApplicationContainer { get; } + + /// + /// Ends the current lifetime scope. + /// + void EndLifetimeScope(); + + /// + /// Gets a nested lifetime scope that services can be resolved from + /// + /// A configuration action that will execute during lifetime scope creation. + /// + /// A new or existing nested lifetime scope. + /// + ILifetimeScope GetLifetimeScope(Action configurationAction); + + /// + /// Either creates a new lifetime scope when HttpContext.Current is null, + /// OR returns the current http context scoped lifetime. + /// + /// + /// A disposable object which does nothing when internal lifetime scope is bound to the http context, + /// OR ends the lifetime scope otherwise. + /// + /// + /// This method is intended for usage in background threads or tasks. There may be situations where HttpContext is present, + /// especially when a task was started with TaskScheduler.FromCurrentSynchronizationContext(). In this case it may not be + /// desirable to create a new scope, but use the existing, http context bound scope instead. + /// + IDisposable BeginContextAwareScope(); + } +} diff --git a/src/Libraries/SmartStore.Core/Infrastructure/MostRecentlyUsedList.cs b/src/Libraries/SmartStore.Core/Infrastructure/MostRecentlyUsedList.cs index cc5aacaab8..1029a802bf 100644 --- a/src/Libraries/SmartStore.Core/Infrastructure/MostRecentlyUsedList.cs +++ b/src/Libraries/SmartStore.Core/Infrastructure/MostRecentlyUsedList.cs @@ -14,6 +14,7 @@ public MostRecentlyUsedList(int maxSize) _maxSize = maxSize; _mru = new List(); } + public MostRecentlyUsedList(IEnumerable collection, int maxSize) { _maxSize = maxSize; @@ -21,6 +22,7 @@ public MostRecentlyUsedList(IEnumerable collection, int maxSize) Normalize(); } + public MostRecentlyUsedList(string collection, int maxSize) { _maxSize = maxSize; @@ -28,6 +30,7 @@ public MostRecentlyUsedList(string collection, int maxSize) Normalize(); } + public MostRecentlyUsedList(IEnumerable collection, T newItem, int maxSize) { _maxSize = maxSize; @@ -35,6 +38,7 @@ public MostRecentlyUsedList(IEnumerable collection, T newItem, int maxSize) Add(newItem); } + public MostRecentlyUsedList(string collection, T newItem, int maxSize) { _maxSize = maxSize; diff --git a/src/Libraries/SmartStore.Core/Infrastructure/ObjectSignatureAttribute.cs b/src/Libraries/SmartStore.Core/Infrastructure/ObjectSignatureAttribute.cs index 3095534f82..ec0292c390 100644 --- a/src/Libraries/SmartStore.Core/Infrastructure/ObjectSignatureAttribute.cs +++ b/src/Libraries/SmartStore.Core/Infrastructure/ObjectSignatureAttribute.cs @@ -1,6 +1,5 @@ using System; - namespace SmartStore { diff --git a/src/Libraries/SmartStore.Core/Infrastructure/SmartStoreEngine.cs b/src/Libraries/SmartStore.Core/Infrastructure/SmartStoreEngine.cs index c82c9f17b3..accd095b46 100644 --- a/src/Libraries/SmartStore.Core/Infrastructure/SmartStoreEngine.cs +++ b/src/Libraries/SmartStore.Core/Infrastructure/SmartStoreEngine.cs @@ -1,13 +1,10 @@ using System; using System.Collections.Generic; -using System.Configuration; using System.Linq; -using System.Reflection; using System.Threading.Tasks; using System.Web.Mvc; using Autofac; using Autofac.Integration.Mvc; -using SmartStore.Core.Configuration; using SmartStore.Core.Data; using SmartStore.Core.Infrastructure.DependencyManagement; using SmartStore.Core.Plugins; @@ -46,7 +43,7 @@ protected virtual ITypeFinder CreateTypeFinder() protected virtual object CreateDependencyResolver(IContainer container) { - var scopeProvider = new AutofacLifetimeScopeProvider(container); + var scopeProvider = container.Resolve(); var dependencyResolver = new AutofacDependencyResolver(container, scopeProvider); return dependencyResolver; } @@ -59,8 +56,19 @@ protected virtual ContainerManager RegisterDependencies() // core dependencies builder = new ContainerBuilder(); - builder.RegisterInstance(this).As().SingleInstance(); - builder.RegisterInstance(typeFinder).As().SingleInstance(); + builder.RegisterInstance(this).As(); + builder.RegisterInstance(typeFinder).As(); + + // Autofac + var lifetimeScopeAccessor = new DefaultLifetimeScopeAccessor(container); + var lifetimeScopeProvider = new DefaultLifetimeScopeProvider(lifetimeScopeAccessor); + builder.RegisterInstance(lifetimeScopeAccessor).As(); + builder.RegisterInstance(lifetimeScopeProvider).As(); + + var dependencyResolver = new AutofacDependencyResolver(container, lifetimeScopeProvider); + builder.RegisterInstance(dependencyResolver); + DependencyResolver.SetResolver(dependencyResolver); + builder.Update(container); // register dependencies provided by other assemblies @@ -79,17 +87,6 @@ protected virtual ContainerManager RegisterDependencies() } builder.Update(container); - // AutofacDependencyResolver - var dependencyResolver = CreateDependencyResolver(container); - if (dependencyResolver is IDependencyResolver) - { - DependencyResolver.SetResolver((IDependencyResolver)dependencyResolver); - } - else if (dependencyResolver != null) - { - DependencyResolver.SetResolver(dependencyResolver); - } - return new ContainerManager(container); } diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 21183c082f..bdca89060d 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -162,6 +162,10 @@ + + + + @@ -235,7 +239,6 @@ - diff --git a/src/Libraries/SmartStore.Services/Events/EventPublisher.cs b/src/Libraries/SmartStore.Services/Events/EventPublisher.cs index 88bfc4e8cd..fc8b33df35 100644 --- a/src/Libraries/SmartStore.Services/Events/EventPublisher.cs +++ b/src/Libraries/SmartStore.Services/Events/EventPublisher.cs @@ -43,7 +43,7 @@ public void Publish(T eventMessage) // first fire/forget all async consumers if (consumerFactory.HasAsyncConsumer) { - AsyncRunner.Run(c => + AsyncRunner.Run((c, ct) => { // for wiring up dependencies correctly var newFactory = c.Resolve>(); diff --git a/src/Libraries/SmartStore.Services/ExportImport/IImportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/IImportManager.cs index 52dc196107..fdefe47639 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/IImportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/IImportManager.cs @@ -1,9 +1,7 @@ using System; using System.IO; using System.Threading; -using System.Threading.Tasks; using SmartStore.Core.Data; -using SmartStore.Core.Async; namespace SmartStore.Services.ExportImport { @@ -12,9 +10,9 @@ namespace SmartStore.Services.ExportImport ///
public interface IImportManager { - Task ImportProductsFromExcelAsync( + ImportResult ImportProductsFromExcel( Stream stream, - CancellationToken cancellationToken, + CancellationToken cancellationToken, IProgress progress = null); /// @@ -27,19 +25,9 @@ Task ImportProductsFromExcelAsync( public static class IImportManagerExtensions { - public static Task ImportProductsFromExcelAsync( - this IImportManager importManager, - Stream stream, - IProgress progress = null) - { - return importManager.ImportProductsFromExcelAsync(stream, CancellationToken.None, progress); - } - public static ImportResult ImportProductsFromExcel(this IImportManager importManager, Stream stream) { - //Func> fn = () => importManager.ImportProductsFromExcelAsync(stream); - //return fn.RunSync(); - return AsyncRunner.RunSync(() => importManager.ImportProductsFromExcelAsync(stream)); + return importManager.ImportProductsFromExcel(stream, CancellationToken.None); } } } diff --git a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs index b9999c6a17..ef5b8bce04 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs @@ -132,159 +132,164 @@ public virtual string CreateTextReport(ImportResult result) /// Import products from XLSX file /// /// Stream - public virtual async Task ImportProductsFromExcelAsync( - Stream stream, + public virtual ImportResult ImportProductsFromExcel( + Stream stream, CancellationToken cancellationToken, IProgress progress = null) { Guard.ArgumentNotNull(() => stream); - var t = await Task.Run(async () => { + var result = new ImportResult(); + int saved = 0; - var result = new ImportResult(); - int saved = 0; - - if (progress != null) - progress.Report(new ImportProgressInfo { ElapsedTime = TimeSpan.Zero }); + if (progress != null) + progress.Report(new ImportProgressInfo { ElapsedTime = TimeSpan.Zero }); - using (var scope = new DbContextScope(ctx: _rsProduct.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false)) + using (var scope = new DbContextScope(ctx: _rsProduct.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false)) + { + using (var segmenter = new DataSegmenter(stream)) { - using (var segmenter = new DataSegmenter(stream)) + result.TotalRecords = segmenter.TotalRows; + + while (segmenter.ReadNextBatch() && !cancellationToken.IsCancellationRequested) { - result.TotalRecords = segmenter.TotalRows; - - while (segmenter.ReadNextBatch() && !cancellationToken.IsCancellationRequested) - { - var batch = segmenter.CurrentBatch; + var batch = segmenter.CurrentBatch; - // Perf: detach all entities - _rsProduct.Context.DetachAll(); + // Perf: detach all entities + _rsProduct.Context.DetachAll(); - // Update progress for calling thread - if (progress != null) + // Update progress for calling thread + if (progress != null) + { + progress.Report(new ImportProgressInfo { - progress.Report(new ImportProgressInfo - { - TotalRecords = result.TotalRecords, - TotalProcessed = segmenter.CurrentSegmentFirstRowIndex - 1, - NewRecords = result.NewRecords, - ModifiedRecords = result.ModifiedRecords, - ElapsedTime = DateTime.UtcNow - result.StartDateUtc, - TotalWarnings = result.Messages.Count(x => x.MessageType == ImportMessageType.Warning), - TotalErrors = result.Messages.Count(x => x.MessageType == ImportMessageType.Error), - }); - } + TotalRecords = result.TotalRecords, + TotalProcessed = segmenter.CurrentSegmentFirstRowIndex - 1, + NewRecords = result.NewRecords, + ModifiedRecords = result.ModifiedRecords, + ElapsedTime = DateTime.UtcNow - result.StartDateUtc, + TotalWarnings = result.Messages.Count(x => x.MessageType == ImportMessageType.Warning), + TotalErrors = result.Messages.Count(x => x.MessageType == ImportMessageType.Error), + }); + } - // =========================================================================== - // 1.) Import products - // =========================================================================== + // =========================================================================== + // 1.) Import products + // =========================================================================== + try + { + saved = ProcessProducts(batch, result); + } + catch (Exception ex) + { + result.AddError(ex, segmenter.CurrentSegment, "ProcessProducts"); + } + + // reduce batch to saved (valid) products. + // No need to perform import operations on errored products. + batch = batch.Where(x => x.Entity != null && !x.IsTransient).AsReadOnly(); + + // update result object + result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient); + result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient); + + // =========================================================================== + // 2.) Import SEO Slugs + // IMPORTANT: Unlike with Products AutoCommitEnabled must be TRUE, + // as Slugs are going to be validated against existing ones in DB. + // =========================================================================== + if (batch.Any(x => x.IsNew || (x.ContainsKey("SeName") || x.NameChanged))) + { try { - saved = await ProcessProducts(batch, result); + _rsProduct.Context.AutoDetectChangesEnabled = true; + ProcessSlugs(batch, result); } catch (Exception ex) { - result.AddError(ex, segmenter.CurrentSegment, "ProcessProducts"); + result.AddError(ex, segmenter.CurrentSegment, "ProcessSeoSlugs"); } - - // reduce batch to saved (valid) products. - // No need to perform import operations on errored products. - batch = batch.Where(x => x.Entity != null && !x.IsTransient).AsReadOnly(); - - // update result object - result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient); - result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient); - - // =========================================================================== - // 2.) Import SEO Slugs - // IMPORTANT: Unlike with Products AutoCommitEnabled must be TRUE, - // as Slugs are going to be validated against existing ones in DB. - // =========================================================================== - if (batch.Any(x => x.IsNew || (x.ContainsKey("SeName") || x.NameChanged))) + finally { - _rsProduct.Context.AutoDetectChangesEnabled = true; - await ProcessSlugs(batch, result); _rsProduct.Context.AutoDetectChangesEnabled = false; } + } + + // =========================================================================== + // 3.) Import Localizations + // =========================================================================== + try + { + ProcessLocalizations(batch, result); + } + catch (Exception ex) + { + result.AddError(ex, segmenter.CurrentSegment, "ProcessLocalizations"); + } - // =========================================================================== - // 3.) Import Localizations - // =========================================================================== - try - { - await ProcessLocalizations(batch, result); - } - catch (Exception ex) - { - result.AddError(ex, segmenter.CurrentSegment, "ProcessLocalizations"); - } - - // =========================================================================== - // 4.) Import product category mappings - // =========================================================================== - if (batch.Any(x => x.ContainsKey("CategoryIds"))) + // =========================================================================== + // 4.) Import product category mappings + // =========================================================================== + if (batch.Any(x => x.ContainsKey("CategoryIds"))) + { + try { - try - { - await ProcessProductCategories(batch, result); - } - catch (Exception ex) - { - result.AddError(ex, segmenter.CurrentSegment, "ProcessProductCategories"); - } + ProcessProductCategories(batch, result); } - - // =========================================================================== - // 5.) Import product manufacturer mappings - // =========================================================================== - if (batch.Any(x => x.ContainsKey("ManufacturerIds"))) + catch (Exception ex) { - try - { - await ProcessProductManufacturers(batch, result); - } - catch (Exception ex) - { - result.AddError(ex, segmenter.CurrentSegment, "ProcessProductManufacturers"); - } + result.AddError(ex, segmenter.CurrentSegment, "ProcessProductCategories"); } + } - // =========================================================================== - // 6.) Import product picture mappings - // =========================================================================== - if (batch.Any(x => x.ContainsKey("Picture1") || x.ContainsKey("Picture2") || x.ContainsKey("Picture3"))) + // =========================================================================== + // 5.) Import product manufacturer mappings + // =========================================================================== + if (batch.Any(x => x.ContainsKey("ManufacturerIds"))) + { + try { - try - { - ProcessProductPictures(batch, result); - } - catch (Exception ex) - { - result.AddError(ex, segmenter.CurrentSegment, "ProcessProductPictures"); - } + ProcessProductManufacturers(batch, result); + } + catch (Exception ex) + { + result.AddError(ex, segmenter.CurrentSegment, "ProcessProductManufacturers"); } + } + // =========================================================================== + // 6.) Import product picture mappings + // =========================================================================== + if (batch.Any(x => x.ContainsKey("Picture1") || x.ContainsKey("Picture2") || x.ContainsKey("Picture3"))) + { + try + { + ProcessProductPictures(batch, result); + } + catch (Exception ex) + { + result.AddError(ex, segmenter.CurrentSegment, "ProcessProductPictures"); + } } + } } + } - result.EndDateUtc = DateTime.UtcNow; + result.EndDateUtc = DateTime.UtcNow; - if (cancellationToken.IsCancellationRequested) - { - result.Cancelled = true; - result.AddInfo("Import task was cancelled by user"); - } - - return result; - }); + if (cancellationToken.IsCancellationRequested) + { + result.Cancelled = true; + result.AddInfo("Import task was cancelled by user"); + } - return t; + return result; } - private async Task ProcessProducts(ICollection> batch, ImportResult result) + private int ProcessProducts(ICollection> batch, ImportResult result) { - _rsProduct.AutoCommitEnabled = false; + _rsProduct.AutoCommitEnabled = true; Product lastInserted = null; Product lastUpdated = null; @@ -434,7 +439,7 @@ private async Task ProcessProducts(ICollection> batch, I } // commit whole batch at once - var t = await _rsProduct.Context.SaveChangesAsync(); + var num = _rsProduct.Context.SaveChanges(); // Perf: notify only about LAST insertion and update if (lastInserted != null) @@ -442,16 +447,11 @@ private async Task ProcessProducts(ICollection> batch, I if (lastUpdated != null) _eventPublisher.EntityUpdated(lastUpdated); - //// ensure all products got imported before processing other stuff. - //t.Wait(); - - return t; + return num; } - private async Task ProcessSlugs(ICollection> batch, ImportResult result) + private int ProcessSlugs(ICollection> batch, ImportResult result) { - _rsUrlRecord.AutoCommitEnabled = false; - var slugMap = new Dictionary(100); Func slugLookup = ((s) => { if (slugMap.ContainsKey(s)) @@ -477,7 +477,7 @@ private async Task ProcessSlugs(ICollection> batch, Impo if (row.IsNew) { // dont't bother validating SeName for new entities. - urlRecord = new UrlRecord() + urlRecord = new UrlRecord { EntityId = row.Entity.Id, EntityName = entityName, @@ -506,12 +506,10 @@ private async Task ProcessSlugs(ICollection> batch, Impo } // commit whole batch at once - var t = await _rsUrlRecord.Context.SaveChangesAsync(); - - return t; + return _rsUrlRecord.Context.SaveChanges(); } - private async Task ProcessLocalizations(ICollection> batch, ImportResult result) + private int ProcessLocalizations(ICollection> batch, ImportResult result) { //_rsProductManufacturer.AutoCommitEnabled = false; @@ -556,17 +554,17 @@ private async Task ProcessLocalizations(ICollection> bat } // commit whole batch at once - var t = await _rsProductManufacturer.Context.SaveChangesAsync(); + var num = _rsProductManufacturer.Context.SaveChanges(); // Perf: notify only about LAST insertion and update //if (lastInserted != null) // _eventPublisher.EntityInserted(lastInserted); - return t; + return num; } - private async Task ProcessProductCategories(ICollection> batch, ImportResult result) + private int ProcessProductCategories(ICollection> batch, ImportResult result) { _rsProductCategory.AutoCommitEnabled = false; @@ -608,16 +606,16 @@ private async Task ProcessProductCategories(ICollection> } // commit whole batch at once - var t = await _rsProductCategory.Context.SaveChangesAsync(); + var num = _rsProductCategory.Context.SaveChanges(); // Perf: notify only about LAST insertion and update if (lastInserted != null) _eventPublisher.EntityInserted(lastInserted); - return t; + return num; } - private async Task ProcessProductManufacturers(ICollection> batch, ImportResult result) + private int ProcessProductManufacturers(ICollection> batch, ImportResult result) { _rsProductManufacturer.AutoCommitEnabled = false; @@ -659,13 +657,13 @@ private async Task ProcessProductManufacturers(ICollection> batch, ImportResult result) diff --git a/src/Libraries/SmartStore.Services/Tasks/Job.cs b/src/Libraries/SmartStore.Services/Tasks/Job.cs index 453a3daf86..c38203e95c 100644 --- a/src/Libraries/SmartStore.Services/Tasks/Job.cs +++ b/src/Libraries/SmartStore.Services/Tasks/Job.cs @@ -1,10 +1,9 @@ using System; +using System.Threading; +using Autofac; using SmartStore.Core.Domain.Tasks; using SmartStore.Core.Infrastructure; using SmartStore.Core.Logging; -using Autofac; -using SmartStore.Core.Data; -using System.Threading; namespace SmartStore.Services.Tasks { @@ -59,15 +58,31 @@ private ITask CreateTask(ILifetimeScope scope) return task; } + /// + /// Executes the task + /// + /// + /// The caller is responsible for disposing the lifetime scope + /// + public void Execute(ILifetimeScope scope = null, bool throwOnError = false) + { + Execute(CancellationToken.None, scope, throwOnError); + } + /// /// Executes the task /// - public void Execute(ILifetimeScope scope = null, bool throwOnError = false) + /// + /// The caller is responsible for disposing the lifetime scope + /// + public void Execute( + CancellationToken cancellationToken, + ILifetimeScope scope = null, + bool throwOnError = false) { this.IsRunning = true; - - scope = scope ?? EngineContext.Current.ContainerManager.Scope(); var faulted = false; + scope = scope ?? EngineContext.Current.ContainerManager.Scope(); try { @@ -90,10 +105,12 @@ public void Execute(ILifetimeScope scope = null, bool throwOnError = false) var ctx = new TaskExecutionContext { LifetimeScope = scope, - CancellationToken = new CancellationTokenSource(TimeSpan.FromHours(6.0)) // TODO: make that somewhat configurable (AdminAreaSettings?) + CancellationToken = cancellationToken }; task.Execute(ctx); + + ctx.CancellationToken.ThrowIfCancellationRequested(); this.LastEndUtc = this.LastSuccessUtc = DateTime.UtcNow; this.LastError = null; } @@ -136,8 +153,6 @@ public void Execute(ILifetimeScope scope = null, bool throwOnError = false) scheduleTaskService.UpdateTask(scheduleTask); } - scope.Dispose(); - this.IsRunning = false; } } diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs b/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs index b456b14861..074a7e619a 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs @@ -21,6 +21,6 @@ public class TaskExecutionContext /// A cancellation token for the running task. /// You can use ThrowIfCancellationRequested() for a hard or IsCancellationRequested for a soft break. /// - public CancellationTokenSource CancellationToken { get; internal set; } + public CancellationToken CancellationToken { get; internal set; } } } diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs b/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs index b1401d0ebe..b165daaeec 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs @@ -1,7 +1,10 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Threading; +using System.Threading.Tasks; +using SmartStore.Core.Async; using SmartStore.Core.Domain.Tasks; namespace SmartStore.Services.Tasks @@ -38,10 +41,17 @@ private void Run() this._startedUtc = DateTime.UtcNow; this._isRunning = true; - foreach (var job in this._jobs.Values) - { - job.Execute(); - } + + var jobs = _jobs.Values + .Select(job => AsyncRunner.Run((c, ct) => job.Execute(ct, c))) + .ToArray(); + + try + { + Task.WaitAll(jobs); + } + catch { } + this._isRunning = false; } diff --git a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs index 7056960c98..22ddf54b15 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs @@ -997,10 +997,9 @@ public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest request) state.Errors.AddRange(errors); } - AsyncRunner.Run((container, x) => + AsyncRunner.Run((container, ct, o) => { - var obj = x as AmazonPayActionState; - + var obj = o as AmazonPayActionState; container.Resolve().AddCustomerOrderNoteLoop(obj); }, state, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs b/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs index 785e33f4f2..0415081000 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs @@ -649,6 +649,7 @@ public GridModel GetGridModel(GridCommand command, string se #endregion old code } + private void CreateFeed(FeedFileCreationContext fileCreation, TaskExecutionContext taskContext) { var xmlSettings = new XmlWriterSettings @@ -656,7 +657,7 @@ private void CreateFeed(FeedFileCreationContext fileCreation, TaskExecutionConte Encoding = Encoding.UTF8, CheckCharacters = false }; - + using (var writer = XmlWriter.Create(fileCreation.Stream, xmlSettings)) { try @@ -686,6 +687,9 @@ private void CreateFeed(FeedFileCreationContext fileCreation, TaskExecutionConte for (int i = 0; i < 9999999; ++i) { searchContext.PageIndex = i; + + // Perf + _dbContext.DetachAll(); var products = _productService.SearchProducts(searchContext); @@ -724,7 +728,7 @@ private void CreateFeed(FeedFileCreationContext fileCreation, TaskExecutionConte } } - if (!products.HasNextPage) + if (!products.HasNextPage || taskContext.CancellationToken.IsCancellationRequested) break; } @@ -741,6 +745,7 @@ private void CreateFeed(FeedFileCreationContext fileCreation, TaskExecutionConte } } } + public void CreateFeed(TaskExecutionContext context) { Helper.StartCreatingFeeds(fileCreation => @@ -749,6 +754,7 @@ public void CreateFeed(TaskExecutionContext context) return true; }); } + public void SetupModel(FeedFroogleModel model) { Helper.SetupConfigModel(model, "FeedFroogle"); diff --git a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs index 78edb8741d..9fe14c718e 100644 --- a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs +++ b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs @@ -347,7 +347,7 @@ public class LoggingModule : Module protected override void Load(ContainerBuilder builder) { builder.RegisterType().As().InstancePerRequest(); - builder.RegisterType().As().InstancePerRequest().OnRelease(x => x.Flush()); + builder.RegisterType().As().InstancePerRequest(); builder.RegisterType().As().InstancePerRequest(); } @@ -630,7 +630,7 @@ protected override void Load(ContainerBuilder builder) // register all api controllers builder.RegisterApiControllers(foundAssemblies); - builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As(); } protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs index 77ba29db78..936d8f5124 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs @@ -9,6 +9,7 @@ using Autofac; using SmartStore.Core; using SmartStore.Core.Async; +using SmartStore.Core.Data; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Stores; @@ -315,7 +316,7 @@ public FeedFileData GetFeedFileByStore(Store store, string secondFileName = null if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); - var feedFile = new FeedFileData() + var feedFile = new FeedFileData { StoreId = store.Id, StoreName = store.Name, @@ -363,62 +364,65 @@ public void StartCreatingFeeds(Func createFeed, s { try { - _cachedPathes = null; - _cachedCategories = null; - - var storeService = _ctx.Resolve(); - var stores = new List(); - - if (BaseSettings.StoreId != 0) + using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, forceNoTracking: true)) { - var storeById = storeService.GetStoreById(BaseSettings.StoreId); - if (storeById != null) - stores.Add(storeById); - } + _cachedPathes = null; + _cachedCategories = null; - if (stores.Count == 0) - { - stores.AddRange(storeService.GetAllStores()); - } + var storeService = _ctx.Resolve(); + var stores = new List(); - var context = new FeedFileCreationContext() - { - StoreCount = stores.Count, - Progress = new Progress(x => + if (BaseSettings.StoreId != 0) { - AsyncState.Current.Set(x, SystemName); - }) - }; + var storeById = storeService.GetStoreById(BaseSettings.StoreId); + if (storeById != null) + stores.Add(storeById); + } - foreach (var store in stores) - { - var feedFile = GetFeedFileByStore(store, secondFileName); - if (feedFile != null) + if (stores.Count == 0) { - AppPath.Delete(feedFile.FileTempPath); + stores.AddRange(storeService.GetAllStores()); + } - if (secondFileName.HasValue()) - AppPath.Delete(feedFile.CustomProperties["SecondFileTempPath"] as string); + var context = new FeedFileCreationContext() + { + StoreCount = stores.Count, + Progress = new Progress(x => + { + AsyncState.Current.Set(x, SystemName); + }) + }; - using (var stream = new FileStream(feedFile.FileTempPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) - using (var logger = new TraceLogger(feedFile.LogPath)) + foreach (var store in stores) + { + var feedFile = GetFeedFileByStore(store, secondFileName); + if (feedFile != null) { - context.Stream = stream; - context.Logger = logger; - context.Store = store; - context.FeedFileUrl = feedFile.FileUrl; + AppPath.Delete(feedFile.FileTempPath); if (secondFileName.HasValue()) - context.SecondFilePath = feedFile.CustomProperties["SecondFileTempPath"] as string; + AppPath.Delete(feedFile.CustomProperties["SecondFileTempPath"] as string); - if (!createFeed(context)) - break; - } + using (var stream = new FileStream(feedFile.FileTempPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) + using (var logger = new TraceLogger(feedFile.LogPath)) + { + context.Stream = stream; + context.Logger = logger; + context.Store = store; + context.FeedFileUrl = feedFile.FileUrl; + + if (secondFileName.HasValue()) + context.SecondFilePath = feedFile.CustomProperties["SecondFileTempPath"] as string; + + if (!createFeed(context)) + break; + } - AppPath.Copy(feedFile.FileTempPath, feedFile.FilePath); + AppPath.Copy(feedFile.FileTempPath, feedFile.FilePath); - if (secondFileName.HasValue()) - AppPath.Copy(context.SecondFilePath, feedFile.CustomProperties["SecondFilePath"] as string); + if (secondFileName.HasValue()) + AppPath.Copy(context.SecondFilePath, feedFile.CustomProperties["SecondFilePath"] as string); + } } } } @@ -596,7 +600,7 @@ public bool RunScheduleTask() string scheduleTaskType = ScheduleTaskType; - var task = AsyncRunner.Run(container => + var task = AsyncRunner.Run((container, ct) => { try { @@ -609,7 +613,7 @@ public bool RunScheduleTask() var job = new Job(scheduleTask); job.Enabled = true; - job.Execute(container, false); + job.Execute(ct, container, false); } catch (Exception exc) { diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiStartupTask.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiStartupTask.cs index bcb441c04a..5d9ec60a7a 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiStartupTask.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiStartupTask.cs @@ -42,7 +42,8 @@ public void Execute() config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; - var configPublisher = EngineContext.Current.Resolve(); + //var configPublisher = EngineContext.Current.Resolve(); + var configPublisher = (IWebApiConfigurationPublisher)config.DependencyResolver.GetService(typeof(IWebApiConfigurationPublisher)); configPublisher.Configure(configBroadcaster); //config.Services.Insert(typeof(ModelBinderProvider), 0, diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs index 3bf0d9a538..a834d0259a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; @@ -303,7 +304,7 @@ private async Task CheckUpdateAsync(bool enforce = false, boo HttpResponseMessage response = await client.GetAsync(url); - if (!response.IsSuccessStatusCode) + if (response.StatusCode != HttpStatusCode.OK) { return noUpdateResult; } @@ -611,7 +612,7 @@ public ActionResult Warnings() foreach (string file in filesToCheck) if (!FilePermissionHelper.CheckPermissions(file, false, true, true, true)) { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Warning, Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.FilePermission.Wrong"), WindowsIdentity.GetCurrent().Name, file) @@ -619,7 +620,7 @@ public ActionResult Warnings() filePermissionsOk = false; } if (filePermissionsOk) - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = _localizationService.GetResource("Admin.System.Warnings.FilePermission.OK") diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index 3c5a462c99..a72bb4095e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -3037,7 +3037,7 @@ public ActionResult ImportExcel(FormCollection form) var cts = new CancellationTokenSource(); var scheduler = TaskScheduler.Default; - var task = AsyncRunner.Run(c => + var task = AsyncRunner.Run((c, ct) => { var progress = new Progress(p => { @@ -3048,9 +3048,7 @@ public ActionResult ImportExcel(FormCollection form) { AsyncState.Current.SetCancelTokenSource(cts); var importManager = c.Resolve(); - var t = importManager.ImportProductsFromExcelAsync(stream, cts.Token, progress); - - var result = t.Result; + var result = importManager.ImportProductsFromExcel(stream, ct, progress); // Saving the result enables us to show a report for last import. AsyncState.Current.Set(result, neverExpires: true); @@ -3074,11 +3072,11 @@ public ActionResult ImportExcel(FormCollection form) } else { - NotifyError(_localizationService.GetResource("Admin.Common.UploadFile")); + NotifyError(T("Admin.Common.UploadFile")); return RedirectToAction("List"); } - NotifySuccess(_localizationService.GetResource("Admin.Common.ImportFromExcel.InProgress")); + NotifySuccess(T("Admin.Common.ImportFromExcel.InProgress")); return RedirectToAction("List"); } catch (Exception exc) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs index e1a6705984..d0f05c079a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs @@ -166,7 +166,7 @@ public ActionResult RunJob(int id, string returnUrl = "") returnUrl = returnUrl.NullEmpty() ?? Request.UrlReferrer.ToString(); - var t = AsyncRunner.Run(c => + var t = AsyncRunner.Run((c, ct) => { var svc = c.Resolve(); @@ -178,7 +178,7 @@ public ActionResult RunJob(int id, string returnUrl = "") var job = new Job(scheduleTask); job.Enabled = true; - job.Execute(c, false); + job.Execute(ct, c, false); } catch { From dff7970568ca2baccd55d180e9a4f51f9f6bc669 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 10 Apr 2015 21:27:56 +0200 Subject: [PATCH 0028/1256] Updated to .NET Framework 4.5.1 --- .../SmartStore.Core/SmartStore.Core.csproj | 4 +- .../SmartStore.Data/SmartStore.Data.csproj | 4 +- src/Libraries/SmartStore.Data/app.config | 12 +- .../Properties/Settings.Designer.cs | 4 +- .../SmartStore.Services.csproj | 4 +- .../EuropaCheckVatService/Reference.cs | 16 +- src/Libraries/SmartStore.Services/app.config | 24 +- .../SmartStore.AmazonPay.csproj | 14 +- src/Plugins/SmartStore.AmazonPay/web.config | 132 +++---- .../Clickatell/Reference.cs | 2 +- .../SmartStore.Clickatell.csproj | 13 +- src/Plugins/SmartStore.Clickatell/web.config | 208 +++++------ .../SmartStore.DevTools.csproj | 13 +- src/Plugins/SmartStore.DevTools/Web.config | 128 +++---- .../SmartStore.DiscountRules.csproj | 13 +- .../SmartStore.DiscountRules/web.config | 208 +++++------ .../SmartStore.FacebookAuth.csproj | 13 +- .../SmartStore.FacebookAuth/web.config | 216 ++++++------ .../SmartStore.GoogleAnalytics.csproj | 13 +- .../SmartStore.GoogleAnalytics/web.config | 208 +++++------ .../SmartStore.GoogleMerchantCenter.csproj | 13 +- .../web.config | 208 +++++------ .../SmartStore.OfflinePayment.csproj | 13 +- .../SmartStore.OfflinePayment/web.config | 208 +++++------ .../Properties/Settings.Designer.cs | 2 +- .../SmartStore.PayPal.csproj | 13 +- .../Web References/PayPalSvc/Reference.cs | 237 +++++++------ src/Plugins/SmartStore.PayPal/web.config | 228 ++++++------ .../SmartStore.Shipping.csproj | 13 +- src/Plugins/SmartStore.Shipping/web.config | 208 +++++------ .../SmartStore.ShippingByWeight.csproj | 13 +- .../SmartStore.ShippingByWeight/web.config | 208 +++++------ .../SmartStore.Tax/SmartStore.Tax.csproj | 13 +- src/Plugins/SmartStore.Tax/web.config | 118 +++---- .../SmartStore.WebApi.csproj | 14 +- src/Plugins/SmartStore.WebApi/web.config | 90 ++--- .../SmartStore.Web.Framework.csproj | 4 +- .../SmartStore.Web.Framework/app.config | 52 +-- .../Administration/SmartStore.Admin.csproj | 6 +- .../SmartStore.Web/Administration/Web.config | 124 +++---- .../EditorLocalization.designer.cs | 2 +- .../GridLocalization.designer.cs | 2 +- .../MvcLocalization.Designer.cs | 32 +- .../SmartStore.Web/SmartStore.Web.csproj | 6 +- src/Presentation/SmartStore.Web/Web.config | 326 +++++++++--------- src/Tests/SmartStore.Core.Tests/App.config | 18 +- .../SmartStore.Core.Tests.csproj | 4 +- src/Tests/SmartStore.Data.Tests/App.config | 20 +- .../SmartStore.Data.Tests.csproj | 4 +- .../SmartStore.Services.Tests/App.config | 34 +- .../SmartStore.Services.Tests.csproj | 4 +- .../SmartStore.Tests/SmartStore.Tests.csproj | 4 +- src/Tests/SmartStore.Web.MVC.Tests/App.config | 72 ++-- .../SmartStore.Web.MVC.Tests.csproj | 4 +- src/Tools/SmartStore.Packager/App.config | 20 +- .../Properties/Resources.Designer.cs | 118 +++---- .../Properties/Settings.Designer.cs | 2 +- .../SmartStore.Packager.csproj | 4 +- src/Tools/SmartStore.WebApi.Client/App.config | 26 +- .../Properties/Resources.Designer.cs | 2 +- .../Properties/Settings.Designer.cs | 4 +- .../SmartStore.WebApi.Client.csproj | 5 +- 62 files changed, 1895 insertions(+), 1852 deletions(-) diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index bdca89060d..84f587fbcb 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,7 +10,7 @@ Properties SmartStore.Core SmartStore.Core - v4.5 + v4.5.1 512 diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 067a8e02be..3b73c16870 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,7 +10,7 @@ Properties SmartStore.Data SmartStore.Data - v4.5 + v4.5.1 512 diff --git a/src/Libraries/SmartStore.Data/app.config b/src/Libraries/SmartStore.Data/app.config index 272dfdab56..4f592fbcd8 100644 --- a/src/Libraries/SmartStore.Data/app.config +++ b/src/Libraries/SmartStore.Data/app.config @@ -1,15 +1,15 @@ - + - - + + - - + + - \ No newline at end of file + diff --git a/src/Libraries/SmartStore.Services/Properties/Settings.Designer.cs b/src/Libraries/SmartStore.Services/Properties/Settings.Designer.cs index 55c9eb47fe..0d4d638b36 100644 --- a/src/Libraries/SmartStore.Services/Properties/Settings.Designer.cs +++ b/src/Libraries/SmartStore.Services/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.17929 +// Laufzeitversion:4.0.30319.34209 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. @@ -12,7 +12,7 @@ namespace SmartStore.Services.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index f763c10b90..15e782ea36 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,7 +10,7 @@ Properties SmartStore.Services SmartStore.Services - v4.5 + v4.5.1 512 diff --git a/src/Libraries/SmartStore.Services/Web References/EuropaCheckVatService/Reference.cs b/src/Libraries/SmartStore.Services/Web References/EuropaCheckVatService/Reference.cs index e885835819..dc2b98b1a8 100644 --- a/src/Libraries/SmartStore.Services/Web References/EuropaCheckVatService/Reference.cs +++ b/src/Libraries/SmartStore.Services/Web References/EuropaCheckVatService/Reference.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.17929 +// Laufzeitversion:4.0.30319.34209 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. @@ -9,7 +9,7 @@ //------------------------------------------------------------------------------ // -// Der Quellcode wurde automatisch mit Microsoft.VSDesigner generiert. Version 4.0.30319.17929. +// Der Quellcode wurde automatisch mit Microsoft.VSDesigner generiert. Version 4.0.30319.34209. // #pragma warning disable 1591 @@ -23,7 +23,7 @@ namespace SmartStore.Services.EuropaCheckVatService { /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.17929")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute(Name="checkVatBinding", Namespace="urn:ec.europa.eu:taxud:vies:services:checkVat")] @@ -222,7 +222,7 @@ private bool IsLocalFileSystemWebService(string url) { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.17929")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")] [System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:ec.europa.eu:taxud:vies:services:checkVat:types")] public enum matchCode { @@ -237,11 +237,11 @@ public enum matchCode { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.17929")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void checkVatCompletedEventHandler(object sender, checkVatCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.17929")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class checkVatCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -303,11 +303,11 @@ public string address { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.17929")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void checkVatApproxCompletedEventHandler(object sender, checkVatApproxCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.17929")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class checkVatApproxCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { diff --git a/src/Libraries/SmartStore.Services/app.config b/src/Libraries/SmartStore.Services/app.config index be10f88c49..9419122e87 100644 --- a/src/Libraries/SmartStore.Services/app.config +++ b/src/Libraries/SmartStore.Services/app.config @@ -1,11 +1,11 @@ - + -
+
-
+
@@ -20,23 +20,23 @@ - - + + - - + + - - + + - + - + - \ No newline at end of file + diff --git a/src/Plugins/SmartStore.AmazonPay/SmartStore.AmazonPay.csproj b/src/Plugins/SmartStore.AmazonPay/SmartStore.AmazonPay.csproj index e63b9dd44a..ab7c222b62 100644 --- a/src/Plugins/SmartStore.AmazonPay/SmartStore.AmazonPay.csproj +++ b/src/Plugins/SmartStore.AmazonPay/SmartStore.AmazonPay.csproj @@ -1,5 +1,5 @@  - + @@ -18,7 +18,7 @@ Properties SmartStore.AmazonPay SmartStore.AmazonPay - v4.5 + v4.5.1 512 @@ -35,6 +35,7 @@ + true @@ -92,8 +93,12 @@ - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -118,11 +123,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + diff --git a/src/Plugins/SmartStore.AmazonPay/web.config b/src/Plugins/SmartStore.AmazonPay/web.config index 2b12a6d610..4c9e3769d7 100644 --- a/src/Plugins/SmartStore.AmazonPay/web.config +++ b/src/Plugins/SmartStore.AmazonPay/web.config @@ -1,124 +1,124 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + - + \ No newline at end of file diff --git a/src/Plugins/SmartStore.Clickatell/Service References/Clickatell/Reference.cs b/src/Plugins/SmartStore.Clickatell/Service References/Clickatell/Reference.cs index 8432f85785..fe2b19478f 100644 --- a/src/Plugins/SmartStore.Clickatell/Service References/Clickatell/Reference.cs +++ b/src/Plugins/SmartStore.Clickatell/Service References/Clickatell/Reference.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18444 +// Laufzeitversion:4.0.30319.34209 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. diff --git a/src/Plugins/SmartStore.Clickatell/SmartStore.Clickatell.csproj b/src/Plugins/SmartStore.Clickatell/SmartStore.Clickatell.csproj index 8f48db5b34..f7e9ee7a8e 100644 --- a/src/Plugins/SmartStore.Clickatell/SmartStore.Clickatell.csproj +++ b/src/Plugins/SmartStore.Clickatell/SmartStore.Clickatell.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.Clickatell SmartStore.Clickatell - v4.5 + v4.5.1 512 @@ -86,10 +86,14 @@ - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -114,11 +118,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + diff --git a/src/Plugins/SmartStore.Clickatell/web.config b/src/Plugins/SmartStore.Clickatell/web.config index 87dc044abe..34297838be 100644 --- a/src/Plugins/SmartStore.Clickatell/web.config +++ b/src/Plugins/SmartStore.Clickatell/web.config @@ -1,117 +1,117 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj b/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj index 49e9ea8d27..e1c88f8d2c 100644 --- a/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj +++ b/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.DevTools SmartStore.DevTools - v4.5 + v4.5.1 512 ..\..\ @@ -98,8 +98,12 @@ - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -124,11 +128,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + diff --git a/src/Plugins/SmartStore.DevTools/Web.config b/src/Plugins/SmartStore.DevTools/Web.config index 7ea66da53a..b68f7d42bb 100644 --- a/src/Plugins/SmartStore.DevTools/Web.config +++ b/src/Plugins/SmartStore.DevTools/Web.config @@ -1,131 +1,131 @@ - + -
+
- - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + \ No newline at end of file diff --git a/src/Plugins/SmartStore.DiscountRules/SmartStore.DiscountRules.csproj b/src/Plugins/SmartStore.DiscountRules/SmartStore.DiscountRules.csproj index 986d771ed3..236ce4de62 100644 --- a/src/Plugins/SmartStore.DiscountRules/SmartStore.DiscountRules.csproj +++ b/src/Plugins/SmartStore.DiscountRules/SmartStore.DiscountRules.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.DiscountRules SmartStore.DiscountRules - v4.5 + v4.5.1 512 @@ -88,8 +88,12 @@ ..\..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -114,11 +118,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + diff --git a/src/Plugins/SmartStore.DiscountRules/web.config b/src/Plugins/SmartStore.DiscountRules/web.config index 87dc044abe..34297838be 100644 --- a/src/Plugins/SmartStore.DiscountRules/web.config +++ b/src/Plugins/SmartStore.DiscountRules/web.config @@ -1,117 +1,117 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.FacebookAuth/SmartStore.FacebookAuth.csproj b/src/Plugins/SmartStore.FacebookAuth/SmartStore.FacebookAuth.csproj index 174c750212..9037add387 100644 --- a/src/Plugins/SmartStore.FacebookAuth/SmartStore.FacebookAuth.csproj +++ b/src/Plugins/SmartStore.FacebookAuth/SmartStore.FacebookAuth.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.FacebookAuth SmartStore.FacebookAuth - v4.5 + v4.5.1 512 @@ -125,7 +125,7 @@ - + False @@ -137,6 +137,10 @@ + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -161,11 +165,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + diff --git a/src/Plugins/SmartStore.FacebookAuth/web.config b/src/Plugins/SmartStore.FacebookAuth/web.config index 84c8a14ea7..2178f3c9db 100644 --- a/src/Plugins/SmartStore.FacebookAuth/web.config +++ b/src/Plugins/SmartStore.FacebookAuth/web.config @@ -1,121 +1,121 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.GoogleAnalytics/SmartStore.GoogleAnalytics.csproj b/src/Plugins/SmartStore.GoogleAnalytics/SmartStore.GoogleAnalytics.csproj index 086a8a1c6f..0b26e4d1d5 100644 --- a/src/Plugins/SmartStore.GoogleAnalytics/SmartStore.GoogleAnalytics.csproj +++ b/src/Plugins/SmartStore.GoogleAnalytics/SmartStore.GoogleAnalytics.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.GoogleAnalytics SmartStore.GoogleAnalytics - v4.5 + v4.5.1 512 @@ -85,8 +85,12 @@ ..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -111,11 +115,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + diff --git a/src/Plugins/SmartStore.GoogleAnalytics/web.config b/src/Plugins/SmartStore.GoogleAnalytics/web.config index 3828368835..8ec2a24780 100644 --- a/src/Plugins/SmartStore.GoogleAnalytics/web.config +++ b/src/Plugins/SmartStore.GoogleAnalytics/web.config @@ -1,116 +1,116 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/SmartStore.GoogleMerchantCenter.csproj b/src/Plugins/SmartStore.GoogleMerchantCenter/SmartStore.GoogleMerchantCenter.csproj index ce815846bf..291f5019cd 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/SmartStore.GoogleMerchantCenter.csproj +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/SmartStore.GoogleMerchantCenter.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.GoogleMerchantCenter SmartStore.GoogleMerchantCenter - v4.5 + v4.5.1 512 @@ -106,8 +106,12 @@ - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -132,11 +136,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + False ..\..\..\lib\Telerik\Telerik.Web.Mvc.dll diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/web.config b/src/Plugins/SmartStore.GoogleMerchantCenter/web.config index 87dc044abe..34297838be 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/web.config +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/web.config @@ -1,117 +1,117 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.OfflinePayment/SmartStore.OfflinePayment.csproj b/src/Plugins/SmartStore.OfflinePayment/SmartStore.OfflinePayment.csproj index 5868afdc54..015c3b66c5 100644 --- a/src/Plugins/SmartStore.OfflinePayment/SmartStore.OfflinePayment.csproj +++ b/src/Plugins/SmartStore.OfflinePayment/SmartStore.OfflinePayment.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.OfflinePayment SmartStore.OfflinePayment - v4.5 + v4.5.1 512 @@ -96,8 +96,12 @@ ..\..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -122,11 +126,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + diff --git a/src/Plugins/SmartStore.OfflinePayment/web.config b/src/Plugins/SmartStore.OfflinePayment/web.config index 87dc044abe..34297838be 100644 --- a/src/Plugins/SmartStore.OfflinePayment/web.config +++ b/src/Plugins/SmartStore.OfflinePayment/web.config @@ -1,117 +1,117 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.PayPal/Properties/Settings.Designer.cs b/src/Plugins/SmartStore.PayPal/Properties/Settings.Designer.cs index a04fd43fad..a9236cb586 100644 --- a/src/Plugins/SmartStore.PayPal/Properties/Settings.Designer.cs +++ b/src/Plugins/SmartStore.PayPal/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18444 +// Laufzeitversion:4.0.30319.34209 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. diff --git a/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj b/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj index 8e4e8ae9fb..1efcc29c03 100644 --- a/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj +++ b/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.PayPal SmartStore.PayPal - v4.5 + v4.5.1 512 ..\..\ @@ -68,9 +68,13 @@ ..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -96,11 +100,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + diff --git a/src/Plugins/SmartStore.PayPal/Web References/PayPalSvc/Reference.cs b/src/Plugins/SmartStore.PayPal/Web References/PayPalSvc/Reference.cs index 1e10b576a7..b8c6682313 100644 --- a/src/Plugins/SmartStore.PayPal/Web References/PayPalSvc/Reference.cs +++ b/src/Plugins/SmartStore.PayPal/Web References/PayPalSvc/Reference.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18444 +// Laufzeitversion:4.0.30319.34209 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. @@ -9,7 +9,7 @@ //------------------------------------------------------------------------------ // -// Der Quellcode wurde automatisch mit Microsoft.VSDesigner generiert. Version 4.0.30319.18444. +// Der Quellcode wurde automatisch mit Microsoft.VSDesigner generiert. Version 4.0.30319.34209. // #pragma warning disable 1591 @@ -23,7 +23,7 @@ namespace SmartStore.PayPal.PayPalSvc { /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute(Name="PayPalAPISoapBinding", Namespace="urn:ebay:api:PayPalAPI")] @@ -1000,7 +1000,7 @@ private bool IsLocalFileSystemWebService(string url) { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute(Name="PayPalAPIAASoapBinding", Namespace="urn:ebay:api:PayPalAPI")] @@ -11776,7 +11776,6 @@ public string Build { } /// - //[System.Xml.Serialization.XmlAnyElementAttribute(Order=6)] [System.Xml.Serialization.XmlIgnoreAttribute()] public System.Xml.XmlElement Any { get { @@ -27114,11 +27113,11 @@ public ExternalRememberMeOptOutRequestType ExternalRememberMeOptOutRequest { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void RefundTransactionCompletedEventHandler(object sender, RefundTransactionCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class RefundTransactionCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27140,11 +27139,11 @@ public RefundTransactionResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void InitiateRecoupCompletedEventHandler(object sender, InitiateRecoupCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class InitiateRecoupCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27166,11 +27165,11 @@ public InitiateRecoupResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void CompleteRecoupCompletedEventHandler(object sender, CompleteRecoupCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class CompleteRecoupCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27192,11 +27191,11 @@ public CompleteRecoupResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void CancelRecoupCompletedEventHandler(object sender, CancelRecoupCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class CancelRecoupCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27218,11 +27217,11 @@ public CancelRecoupResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetTransactionDetailsCompletedEventHandler(object sender, GetTransactionDetailsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetTransactionDetailsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27244,11 +27243,11 @@ public GetTransactionDetailsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void BMCreateButtonCompletedEventHandler(object sender, BMCreateButtonCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class BMCreateButtonCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27270,11 +27269,11 @@ public BMCreateButtonResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void BMUpdateButtonCompletedEventHandler(object sender, BMUpdateButtonCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class BMUpdateButtonCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27296,11 +27295,11 @@ public BMUpdateButtonResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void BMManageButtonStatusCompletedEventHandler(object sender, BMManageButtonStatusCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class BMManageButtonStatusCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27322,11 +27321,11 @@ public BMManageButtonStatusResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void BMGetButtonDetailsCompletedEventHandler(object sender, BMGetButtonDetailsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class BMGetButtonDetailsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27348,11 +27347,11 @@ public BMGetButtonDetailsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void BMSetInventoryCompletedEventHandler(object sender, BMSetInventoryCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class BMSetInventoryCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27374,11 +27373,11 @@ public BMSetInventoryResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void BMGetInventoryCompletedEventHandler(object sender, BMGetInventoryCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class BMGetInventoryCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27400,11 +27399,11 @@ public BMGetInventoryResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void BMButtonSearchCompletedEventHandler(object sender, BMButtonSearchCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class BMButtonSearchCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27426,11 +27425,11 @@ public BMButtonSearchResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void BillUserCompletedEventHandler(object sender, BillUserCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class BillUserCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27452,11 +27451,11 @@ public BillUserResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void TransactionSearchCompletedEventHandler(object sender, TransactionSearchCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class TransactionSearchCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27478,11 +27477,11 @@ public TransactionSearchResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void MassPayCompletedEventHandler(object sender, MassPayCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class MassPayCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27504,11 +27503,11 @@ public MassPayResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void BillAgreementUpdateCompletedEventHandler(object sender, BillAgreementUpdateCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class BillAgreementUpdateCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27530,11 +27529,11 @@ public BAUpdateResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void AddressVerifyCompletedEventHandler(object sender, AddressVerifyCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class AddressVerifyCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27556,11 +27555,11 @@ public AddressVerifyResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void EnterBoardingCompletedEventHandler(object sender, EnterBoardingCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class EnterBoardingCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27582,11 +27581,11 @@ public EnterBoardingResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetBoardingDetailsCompletedEventHandler(object sender, GetBoardingDetailsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetBoardingDetailsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27608,11 +27607,11 @@ public GetBoardingDetailsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void CreateMobilePaymentCompletedEventHandler(object sender, CreateMobilePaymentCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class CreateMobilePaymentCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27634,11 +27633,11 @@ public CreateMobilePaymentResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetMobileStatusCompletedEventHandler(object sender, GetMobileStatusCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetMobileStatusCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27660,11 +27659,11 @@ public GetMobileStatusResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void SetMobileCheckoutCompletedEventHandler(object sender, SetMobileCheckoutCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class SetMobileCheckoutCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27686,11 +27685,11 @@ public SetMobileCheckoutResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoMobileCheckoutPaymentCompletedEventHandler(object sender, DoMobileCheckoutPaymentCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoMobileCheckoutPaymentCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27712,11 +27711,11 @@ public DoMobileCheckoutPaymentResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetBalanceCompletedEventHandler(object sender, GetBalanceCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetBalanceCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27738,11 +27737,11 @@ public GetBalanceResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetPalDetailsCompletedEventHandler(object sender, GetPalDetailsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetPalDetailsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27764,11 +27763,11 @@ public GetPalDetailsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoExpressCheckoutPaymentCompletedEventHandler(object sender, DoExpressCheckoutPaymentCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoExpressCheckoutPaymentCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27790,11 +27789,11 @@ public DoExpressCheckoutPaymentResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoUATPExpressCheckoutPaymentCompletedEventHandler(object sender, DoUATPExpressCheckoutPaymentCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoUATPExpressCheckoutPaymentCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27816,11 +27815,11 @@ public DoUATPExpressCheckoutPaymentResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void SetAuthFlowParamCompletedEventHandler(object sender, SetAuthFlowParamCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class SetAuthFlowParamCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27842,11 +27841,11 @@ public SetAuthFlowParamResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetAuthDetailsCompletedEventHandler(object sender, GetAuthDetailsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetAuthDetailsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27868,11 +27867,11 @@ public GetAuthDetailsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void SetAccessPermissionsCompletedEventHandler(object sender, SetAccessPermissionsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class SetAccessPermissionsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27894,11 +27893,11 @@ public SetAccessPermissionsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void UpdateAccessPermissionsCompletedEventHandler(object sender, UpdateAccessPermissionsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class UpdateAccessPermissionsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27920,11 +27919,11 @@ public UpdateAccessPermissionsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetAccessPermissionDetailsCompletedEventHandler(object sender, GetAccessPermissionDetailsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetAccessPermissionDetailsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27946,11 +27945,11 @@ public GetAccessPermissionDetailsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetIncentiveEvaluationCompletedEventHandler(object sender, GetIncentiveEvaluationCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetIncentiveEvaluationCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27972,11 +27971,11 @@ public GetIncentiveEvaluationResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void SetExpressCheckoutCompletedEventHandler(object sender, SetExpressCheckoutCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class SetExpressCheckoutCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -27998,11 +27997,11 @@ public SetExpressCheckoutResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void ExecuteCheckoutOperationsCompletedEventHandler(object sender, ExecuteCheckoutOperationsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class ExecuteCheckoutOperationsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28024,11 +28023,11 @@ public ExecuteCheckoutOperationsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetExpressCheckoutDetailsCompletedEventHandler(object sender, GetExpressCheckoutDetailsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetExpressCheckoutDetailsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28050,11 +28049,11 @@ public GetExpressCheckoutDetailsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoDirectPaymentCompletedEventHandler(object sender, DoDirectPaymentCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoDirectPaymentCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28076,11 +28075,11 @@ public DoDirectPaymentResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void ManagePendingTransactionStatusCompletedEventHandler(object sender, ManagePendingTransactionStatusCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class ManagePendingTransactionStatusCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28102,11 +28101,11 @@ public ManagePendingTransactionStatusResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoCancelCompletedEventHandler(object sender, DoCancelCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoCancelCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28128,11 +28127,11 @@ public DoCancelResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoCaptureCompletedEventHandler(object sender, DoCaptureCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoCaptureCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28154,11 +28153,11 @@ public DoCaptureResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoReauthorizationCompletedEventHandler(object sender, DoReauthorizationCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoReauthorizationCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28180,11 +28179,11 @@ public DoReauthorizationResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoVoidCompletedEventHandler(object sender, DoVoidCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoVoidCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28206,11 +28205,11 @@ public DoVoidResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoAuthorizationCompletedEventHandler(object sender, DoAuthorizationCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoAuthorizationCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28232,11 +28231,11 @@ public DoAuthorizationResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void UpdateAuthorizationCompletedEventHandler(object sender, UpdateAuthorizationCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class UpdateAuthorizationCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28258,11 +28257,11 @@ public UpdateAuthorizationResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void SetCustomerBillingAgreementCompletedEventHandler(object sender, SetCustomerBillingAgreementCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class SetCustomerBillingAgreementCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28284,11 +28283,11 @@ public SetCustomerBillingAgreementResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetBillingAgreementCustomerDetailsCompletedEventHandler(object sender, GetBillingAgreementCustomerDetailsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetBillingAgreementCustomerDetailsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28310,11 +28309,11 @@ public GetBillingAgreementCustomerDetailsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void CreateBillingAgreementCompletedEventHandler(object sender, CreateBillingAgreementCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class CreateBillingAgreementCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28336,11 +28335,11 @@ public CreateBillingAgreementResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoReferenceTransactionCompletedEventHandler(object sender, DoReferenceTransactionCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoReferenceTransactionCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28362,11 +28361,11 @@ public DoReferenceTransactionResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoNonReferencedCreditCompletedEventHandler(object sender, DoNonReferencedCreditCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoNonReferencedCreditCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28388,11 +28387,11 @@ public DoNonReferencedCreditResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void DoUATPAuthorizationCompletedEventHandler(object sender, DoUATPAuthorizationCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class DoUATPAuthorizationCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28414,11 +28413,11 @@ public DoUATPAuthorizationResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void CreateRecurringPaymentsProfileCompletedEventHandler(object sender, CreateRecurringPaymentsProfileCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class CreateRecurringPaymentsProfileCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28440,11 +28439,11 @@ public CreateRecurringPaymentsProfileResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void GetRecurringPaymentsProfileDetailsCompletedEventHandler(object sender, GetRecurringPaymentsProfileDetailsCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class GetRecurringPaymentsProfileDetailsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28466,11 +28465,11 @@ public GetRecurringPaymentsProfileDetailsResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void ManageRecurringPaymentsProfileStatusCompletedEventHandler(object sender, ManageRecurringPaymentsProfileStatusCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class ManageRecurringPaymentsProfileStatusCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28492,11 +28491,11 @@ public ManageRecurringPaymentsProfileStatusResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void BillOutstandingAmountCompletedEventHandler(object sender, BillOutstandingAmountCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class BillOutstandingAmountCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28518,11 +28517,11 @@ public BillOutstandingAmountResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void UpdateRecurringPaymentsProfileCompletedEventHandler(object sender, UpdateRecurringPaymentsProfileCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class UpdateRecurringPaymentsProfileCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28544,11 +28543,11 @@ public UpdateRecurringPaymentsProfileResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void ReverseTransactionCompletedEventHandler(object sender, ReverseTransactionCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class ReverseTransactionCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -28570,11 +28569,11 @@ public ReverseTransactionResponseType Result { } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] public delegate void ExternalRememberMeOptOutCompletedEventHandler(object sender, ExternalRememberMeOptOutCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class ExternalRememberMeOptOutCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { diff --git a/src/Plugins/SmartStore.PayPal/web.config b/src/Plugins/SmartStore.PayPal/web.config index 23e1793c45..79e1718372 100644 --- a/src/Plugins/SmartStore.PayPal/web.config +++ b/src/Plugins/SmartStore.PayPal/web.config @@ -1,11 +1,11 @@ - + -
+
- + @@ -14,124 +14,124 @@ - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.Shipping/SmartStore.Shipping.csproj b/src/Plugins/SmartStore.Shipping/SmartStore.Shipping.csproj index f4152c7b66..59f1bdcdf0 100644 --- a/src/Plugins/SmartStore.Shipping/SmartStore.Shipping.csproj +++ b/src/Plugins/SmartStore.Shipping/SmartStore.Shipping.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.Shipping SmartStore.Shipping - v4.5 + v4.5.1 512 @@ -100,8 +100,12 @@ - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -126,11 +130,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + ..\..\..\lib\Telerik\Telerik.Web.Mvc.dll diff --git a/src/Plugins/SmartStore.Shipping/web.config b/src/Plugins/SmartStore.Shipping/web.config index 3828368835..8ec2a24780 100644 --- a/src/Plugins/SmartStore.Shipping/web.config +++ b/src/Plugins/SmartStore.Shipping/web.config @@ -1,116 +1,116 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj b/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj index b2428733b5..561149e08f 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj +++ b/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.ShippingByWeight SmartStore.ShippingByWeight - v4.5 + v4.5.1 512 @@ -104,8 +104,12 @@ - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -130,11 +134,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + False ..\..\..\lib\Telerik\Telerik.Web.Mvc.dll diff --git a/src/Plugins/SmartStore.ShippingByWeight/web.config b/src/Plugins/SmartStore.ShippingByWeight/web.config index 3828368835..8ec2a24780 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/web.config +++ b/src/Plugins/SmartStore.ShippingByWeight/web.config @@ -1,116 +1,116 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.Tax/SmartStore.Tax.csproj b/src/Plugins/SmartStore.Tax/SmartStore.Tax.csproj index 2ce459c85d..4c9be02213 100644 --- a/src/Plugins/SmartStore.Tax/SmartStore.Tax.csproj +++ b/src/Plugins/SmartStore.Tax/SmartStore.Tax.csproj @@ -1,5 +1,5 @@  - + @@ -20,7 +20,7 @@ Properties SmartStore.Tax SmartStore.Tax - v4.5 + v4.5.1 512 @@ -101,8 +101,12 @@ - + + + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -127,11 +131,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + False ..\..\..\lib\Telerik\Telerik.Web.Mvc.dll diff --git a/src/Plugins/SmartStore.Tax/web.config b/src/Plugins/SmartStore.Tax/web.config index 8c445486aa..34297838be 100644 --- a/src/Plugins/SmartStore.Tax/web.config +++ b/src/Plugins/SmartStore.Tax/web.config @@ -1,116 +1,116 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj b/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj index c6ba01e79a..e6ed2e4a5d 100644 --- a/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj +++ b/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj @@ -1,5 +1,5 @@  - + @@ -27,7 +27,7 @@ Properties SmartStore.WebApi SmartStore.WebApi - v4.5 + v4.5.1 512 @@ -48,6 +48,7 @@ + true @@ -106,7 +107,7 @@ ..\..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll - + False @@ -121,9 +122,13 @@ + ..\..\packages\Microsoft.AspNet.Cors.5.1.2\lib\net45\System.Web.Cors.dll + + + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll @@ -159,11 +164,10 @@ False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - + ..\..\..\lib\Telerik\Telerik.Web.Mvc.dll diff --git a/src/Plugins/SmartStore.WebApi/web.config b/src/Plugins/SmartStore.WebApi/web.config index f72dbd837d..bddef732e2 100644 --- a/src/Plugins/SmartStore.WebApi/web.config +++ b/src/Plugins/SmartStore.WebApi/web.config @@ -1,88 +1,88 @@ - + - - + + - + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj index 037c1ffd70..6df8b31d91 100644 --- a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj +++ b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,7 +10,7 @@ Properties SmartStore.Web.Framework SmartStore.Web.Framework - v4.5 + v4.5.1 512 diff --git a/src/Presentation/SmartStore.Web.Framework/app.config b/src/Presentation/SmartStore.Web.Framework/app.config index 02b2d0326a..b9b662f2f0 100644 --- a/src/Presentation/SmartStore.Web.Framework/app.config +++ b/src/Presentation/SmartStore.Web.Framework/app.config @@ -1,55 +1,55 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - \ No newline at end of file + diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index 0f20b4a962..a44a9e9db6 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -1,5 +1,5 @@  - + Debug @@ -13,7 +13,7 @@ Properties SmartStore.Admin SmartStore.Admin - v4.5 + v4.5.1 false true @@ -103,7 +103,6 @@ ..\..\..\packages\Microsoft.AspNet.WebApi.Client.5.1.2\lib\net45\System.Net.Http.Formatting.dll - @@ -114,6 +113,7 @@ + False ..\..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll diff --git a/src/Presentation/SmartStore.Web/Administration/Web.config b/src/Presentation/SmartStore.Web/Administration/Web.config index 876c996719..b242a817ea 100644 --- a/src/Presentation/SmartStore.Web/Administration/Web.config +++ b/src/Presentation/SmartStore.Web/Administration/Web.config @@ -1,111 +1,111 @@ - + - - - - - + + + + + - + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + - + \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/App_GlobalResources/EditorLocalization.designer.cs b/src/Presentation/SmartStore.Web/App_GlobalResources/EditorLocalization.designer.cs index 8c5b956c13..1002132cd1 100644 --- a/src/Presentation/SmartStore.Web/App_GlobalResources/EditorLocalization.designer.cs +++ b/src/Presentation/SmartStore.Web/App_GlobalResources/EditorLocalization.designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18444 +// Laufzeitversion:4.0.30319.34209 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. diff --git a/src/Presentation/SmartStore.Web/App_GlobalResources/GridLocalization.designer.cs b/src/Presentation/SmartStore.Web/App_GlobalResources/GridLocalization.designer.cs index 9153314c68..4ad683bdb0 100644 --- a/src/Presentation/SmartStore.Web/App_GlobalResources/GridLocalization.designer.cs +++ b/src/Presentation/SmartStore.Web/App_GlobalResources/GridLocalization.designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18444 +// Laufzeitversion:4.0.30319.34209 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. diff --git a/src/Presentation/SmartStore.Web/App_GlobalResources/MvcLocalization.Designer.cs b/src/Presentation/SmartStore.Web/App_GlobalResources/MvcLocalization.Designer.cs index 7aedfffcc9..07cb03a819 100644 --- a/src/Presentation/SmartStore.Web/App_GlobalResources/MvcLocalization.Designer.cs +++ b/src/Presentation/SmartStore.Web/App_GlobalResources/MvcLocalization.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.34209 +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.34209 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. // //------------------------------------------------------------------------------ @@ -13,12 +13,12 @@ namespace Resources { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option or rebuild the Visual Studio project. + // Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse + // über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen das Visual Studio-Projekt neu. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Web.Application.StronglyTypedResourceProxyBuilder", "12.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -33,7 +33,7 @@ internal MvcLocalization() { } /// - /// Returns the cached ResourceManager instance used by this class. + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ internal MvcLocalization() { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ internal MvcLocalization() { } /// - /// Looks up a localized string similar to The field {0} must be a date.. + /// Sucht eine lokalisierte Zeichenfolge, die The field {0} must be a date. ähnelt. /// internal static string FieldMustBeDate { get { @@ -70,7 +70,7 @@ internal static string FieldMustBeDate { } /// - /// Looks up a localized string similar to The field {0} must be a number.. + /// Sucht eine lokalisierte Zeichenfolge, die The field {0} must be a number. ähnelt. /// internal static string FieldMustBeNumeric { get { @@ -79,7 +79,7 @@ internal static string FieldMustBeNumeric { } /// - /// Looks up a localized string similar to The value '{0}' is not valid for {1}.. + /// Sucht eine lokalisierte Zeichenfolge, die The value '{0}' is not valid for {1}. ähnelt. /// internal static string PropertyValueInvalid { get { @@ -88,7 +88,7 @@ internal static string PropertyValueInvalid { } /// - /// Looks up a localized string similar to A value is required.. + /// Sucht eine lokalisierte Zeichenfolge, die A value is required. ähnelt. /// internal static string PropertyValueRequired { get { diff --git a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj index a5f776c0f5..a2b7ba3a8e 100644 --- a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj +++ b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj @@ -1,5 +1,5 @@  - + Debug @@ -13,7 +13,7 @@ Properties SmartStore.Web SmartStore.Web - v4.5 + v4.5.1 false true @@ -151,7 +151,6 @@ - @@ -161,6 +160,7 @@ + False ..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config index ea72e0831d..4ca49af32f 100644 --- a/src/Presentation/SmartStore.Web/Web.config +++ b/src/Presentation/SmartStore.Web/Web.config @@ -1,308 +1,316 @@ - + -
+
-
-
-
+
+
+
-
-
+
+
- - + + - - + + - - + + - + - + - - + + - + - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - + - - - - - - - + + + + + + + + - - - + + + - - - - - - + + + + + + - + - - - - - - - + + + + + + + - - + + - - - - + + + + - - - - - - - + + + + + + + - + - - - + + + - + - + - + - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/src/Tests/SmartStore.Core.Tests/App.config b/src/Tests/SmartStore.Core.Tests/App.config index 159321b301..a4934a8730 100644 --- a/src/Tests/SmartStore.Core.Tests/App.config +++ b/src/Tests/SmartStore.Core.Tests/App.config @@ -1,22 +1,22 @@ - + -
+
- - + + - + - - + + - - + + diff --git a/src/Tests/SmartStore.Core.Tests/SmartStore.Core.Tests.csproj b/src/Tests/SmartStore.Core.Tests/SmartStore.Core.Tests.csproj index a7d34436e1..3c9e2534bb 100644 --- a/src/Tests/SmartStore.Core.Tests/SmartStore.Core.Tests.csproj +++ b/src/Tests/SmartStore.Core.Tests/SmartStore.Core.Tests.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,7 +10,7 @@ Properties SmartStore.Core.Tests SmartStore.Core.Tests - v4.5 + v4.5.1 512 diff --git a/src/Tests/SmartStore.Data.Tests/App.config b/src/Tests/SmartStore.Data.Tests/App.config index 1230ac0bd5..3930abaf6a 100644 --- a/src/Tests/SmartStore.Data.Tests/App.config +++ b/src/Tests/SmartStore.Data.Tests/App.config @@ -1,34 +1,34 @@ - + -
+
- + - - + + - - + + - - + + - \ No newline at end of file + diff --git a/src/Tests/SmartStore.Data.Tests/SmartStore.Data.Tests.csproj b/src/Tests/SmartStore.Data.Tests/SmartStore.Data.Tests.csproj index 879074ca14..894a358733 100644 --- a/src/Tests/SmartStore.Data.Tests/SmartStore.Data.Tests.csproj +++ b/src/Tests/SmartStore.Data.Tests/SmartStore.Data.Tests.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,7 +10,7 @@ Properties SmartStore.Data.Tests SmartStore.Data.Tests - v4.5 + v4.5.1 512 diff --git a/src/Tests/SmartStore.Services.Tests/App.config b/src/Tests/SmartStore.Services.Tests/App.config index 96e0a659b1..39d7a48483 100644 --- a/src/Tests/SmartStore.Services.Tests/App.config +++ b/src/Tests/SmartStore.Services.Tests/App.config @@ -1,33 +1,33 @@ - + -
+
- - + + - - - + + + - - - - - + + + + + - + - - + + - - + + diff --git a/src/Tests/SmartStore.Services.Tests/SmartStore.Services.Tests.csproj b/src/Tests/SmartStore.Services.Tests/SmartStore.Services.Tests.csproj index 61a2f9dcb6..a264eb3938 100644 --- a/src/Tests/SmartStore.Services.Tests/SmartStore.Services.Tests.csproj +++ b/src/Tests/SmartStore.Services.Tests/SmartStore.Services.Tests.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,7 +10,7 @@ Properties SmartStore.Services.Tests SmartStore.Services.Tests - v4.5 + v4.5.1 512 diff --git a/src/Tests/SmartStore.Tests/SmartStore.Tests.csproj b/src/Tests/SmartStore.Tests/SmartStore.Tests.csproj index 6d0fd9ed1f..84a1971ddb 100644 --- a/src/Tests/SmartStore.Tests/SmartStore.Tests.csproj +++ b/src/Tests/SmartStore.Tests/SmartStore.Tests.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,7 +10,7 @@ Properties SmartStore.Tests SmartStore.Tests - v4.5 + v4.5.1 512 diff --git a/src/Tests/SmartStore.Web.MVC.Tests/App.config b/src/Tests/SmartStore.Web.MVC.Tests/App.config index 5939dae289..04668c3c98 100644 --- a/src/Tests/SmartStore.Web.MVC.Tests/App.config +++ b/src/Tests/SmartStore.Web.MVC.Tests/App.config @@ -1,80 +1,80 @@ - + -
-
+
+
- - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Tests/SmartStore.Web.MVC.Tests/SmartStore.Web.MVC.Tests.csproj b/src/Tests/SmartStore.Web.MVC.Tests/SmartStore.Web.MVC.Tests.csproj index ccba2a4204..802605a430 100644 --- a/src/Tests/SmartStore.Web.MVC.Tests/SmartStore.Web.MVC.Tests.csproj +++ b/src/Tests/SmartStore.Web.MVC.Tests/SmartStore.Web.MVC.Tests.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,7 +10,7 @@ Properties SmartStore.Web.MVC.Tests SmartStore.Web.MVC.Tests - v4.5 + v4.5.1 512 diff --git a/src/Tools/SmartStore.Packager/App.config b/src/Tools/SmartStore.Packager/App.config index 9fcf2099fc..30622f85af 100644 --- a/src/Tools/SmartStore.Packager/App.config +++ b/src/Tools/SmartStore.Packager/App.config @@ -1,33 +1,33 @@ - + -
+
- + - + - + - - + + - - + + - \ No newline at end of file + diff --git a/src/Tools/SmartStore.Packager/Properties/Resources.Designer.cs b/src/Tools/SmartStore.Packager/Properties/Resources.Designer.cs index 04b3a4f37f..b864eb9989 100644 --- a/src/Tools/SmartStore.Packager/Properties/Resources.Designer.cs +++ b/src/Tools/SmartStore.Packager/Properties/Resources.Designer.cs @@ -1,71 +1,63 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18444 +// Laufzeitversion:4.0.30319.34209 // -// Änderungen an dieser Datei können fehlerhaftes Verhalten verursachen und gehen verloren, wenn -// der Code neu generiert wird. +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. // //------------------------------------------------------------------------------ -namespace SmartStore.Packager.Properties -{ - - - /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. - /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse - // über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der Option /str erneut aus, oder erstellen Sie Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources - { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() - { - } - - /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager - { - get - { - if ((resourceMan == null)) - { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SmartStore.Packager.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture - { - get - { - return resourceCulture; - } - set - { - resourceCulture = value; - } - } - } +namespace SmartStore.Packager.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SmartStore.Packager.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } } diff --git a/src/Tools/SmartStore.Packager/Properties/Settings.Designer.cs b/src/Tools/SmartStore.Packager/Properties/Settings.Designer.cs index aa69af3189..b5f2c5cff2 100644 --- a/src/Tools/SmartStore.Packager/Properties/Settings.Designer.cs +++ b/src/Tools/SmartStore.Packager/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18444 +// Laufzeitversion:4.0.30319.34209 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. diff --git a/src/Tools/SmartStore.Packager/SmartStore.Packager.csproj b/src/Tools/SmartStore.Packager/SmartStore.Packager.csproj index 0a979065fb..44e4d6faa7 100644 --- a/src/Tools/SmartStore.Packager/SmartStore.Packager.csproj +++ b/src/Tools/SmartStore.Packager/SmartStore.Packager.csproj @@ -9,8 +9,9 @@ Properties SmartStore.Packager SmartStore.Packager - v4.5 + v4.5.1 512 + AnyCPU @@ -82,6 +83,7 @@ True Resources.resx + True SettingsSingleFileGenerator diff --git a/src/Tools/SmartStore.WebApi.Client/App.config b/src/Tools/SmartStore.WebApi.Client/App.config index 7a187ca6aa..951540450e 100644 --- a/src/Tools/SmartStore.WebApi.Client/App.config +++ b/src/Tools/SmartStore.WebApi.Client/App.config @@ -1,39 +1,39 @@ - + - -
+ +
- + - + - + - + - + - + - + - + - + - \ No newline at end of file + diff --git a/src/Tools/SmartStore.WebApi.Client/Properties/Resources.Designer.cs b/src/Tools/SmartStore.WebApi.Client/Properties/Resources.Designer.cs index e1c2ae8e6e..296212580e 100644 --- a/src/Tools/SmartStore.WebApi.Client/Properties/Resources.Designer.cs +++ b/src/Tools/SmartStore.WebApi.Client/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18052 +// Laufzeitversion:4.0.30319.34209 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. diff --git a/src/Tools/SmartStore.WebApi.Client/Properties/Settings.Designer.cs b/src/Tools/SmartStore.WebApi.Client/Properties/Settings.Designer.cs index 3f3617a2f0..b4d629771b 100644 --- a/src/Tools/SmartStore.WebApi.Client/Properties/Settings.Designer.cs +++ b/src/Tools/SmartStore.WebApi.Client/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18408 +// Laufzeitversion:4.0.30319.34209 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. @@ -12,7 +12,7 @@ namespace SmartStoreNetWebApiClient.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/src/Tools/SmartStore.WebApi.Client/SmartStore.WebApi.Client.csproj b/src/Tools/SmartStore.WebApi.Client/SmartStore.WebApi.Client.csproj index d941229df0..74d52a1717 100644 --- a/src/Tools/SmartStore.WebApi.Client/SmartStore.WebApi.Client.csproj +++ b/src/Tools/SmartStore.WebApi.Client/SmartStore.WebApi.Client.csproj @@ -1,5 +1,5 @@  - + Debug @@ -9,7 +9,7 @@ Properties SmartStoreNetWebApiClient SmartStoreNetWebApiClient - v4.5 + v4.5.1 512 false veröffentlichen\ @@ -28,6 +28,7 @@ true ..\..\ true + AnyCPU From ea75d63aae8e8f415400cf97317c5d66260a9a25 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 10 Apr 2015 21:51:30 +0200 Subject: [PATCH 0029/1256] Update dependency --- .../SmartStore.Licensing.dll | Bin 168448 -> 168960 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/SmartStore.Licensing/SmartStore.Licensing.dll b/lib/SmartStore.Licensing/SmartStore.Licensing.dll index 47363c168976240c24eb0ef28ed996d8644fc66f..84192f84b2b52286b8037955a18ef90a716794da 100644 GIT binary patch literal 168960 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 U-9-BQSyRb~`TyhR4~PT*4M{R+-T(jq literal 168448 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

ALnI|5tD7+yr9$nLr2>Z!LqHl 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

@@ -431,5 +432,10 @@ public CatalogSettings() /// Gets or sets how many items to display maximally in the most recently used category list /// public int MostRecentlyUsedCategoriesMaxSize { get; set; } + + /// + /// Gets or sets how many items to display maximally in the most recently used manufacturer list + /// + public int MostRecentlyUsedManufacturersMaxSize { get; set; } } } \ No newline at end of file diff --git a/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerAttributeNames.cs b/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerAttributeNames.cs index f830bf8631..ea0bb24d01 100644 --- a/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerAttributeNames.cs +++ b/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerAttributeNames.cs @@ -34,6 +34,7 @@ public static partial class SystemCustomerAttributeNames public static string ImpersonatedCustomerId { get { return "ImpersonatedCustomerId"; } } public static string AdminAreaStoreScopeConfiguration { get { return "AdminAreaStoreScopeConfiguration"; } } public static string MostRecentlyUsedCategories { get { return "MostRecentlyUsedCategories"; } } + public static string MostRecentlyUsedManufacturers { get { return "MostRecentlyUsedManufacturers"; } } //depends on store public static string CurrencyId { get { return "CurrencyId"; } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs index 12817a0890..178d046379 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs @@ -5,8 +5,11 @@ using SmartStore.Core; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Common; +using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Infrastructure; using SmartStore.Core.Logging; using SmartStore.Services.Catalog; +using SmartStore.Services.Common; using SmartStore.Services.ExportImport; using SmartStore.Services.Helpers; using SmartStore.Services.Localization; @@ -182,6 +185,7 @@ private void PrepareManufacturerModel(ManufacturerModel model, Manufacturer manu public ActionResult AllManufacturers(string label, int selectedId) { var manufacturers = _manufacturerService.GetAllManufacturers(true); + if (label.HasValue()) { manufacturers.Insert(0, new Manufacturer { Name = label, Id = 0 }); @@ -195,7 +199,39 @@ public ActionResult AllManufacturers(string label, int selectedId) selected = m.Id == selectedId }; - return new JsonResult { Data = list.ToList(), JsonRequestBehavior = JsonRequestBehavior.AllowGet }; + var data = list.ToList(); + + var mru = new MostRecentlyUsedList(_workContext.CurrentCustomer.GetAttribute(SystemCustomerAttributeNames.MostRecentlyUsedManufacturers), + _catalogSettings.MostRecentlyUsedManufacturersMaxSize); + + // TODO: insert disabled option separator (select2 v.3.4.2 or higher required) + //if (mru.Count > 0) + //{ + // data.Insert(0, new + // { + // id = "", + // text = "----------------------", + // selected = false, + // disabled = true + // }); + //} + + for (int i = mru.Count - 1; i >= 0; --i) + { + string id = mru[i]; + var item = manufacturers.FirstOrDefault(x => x.Id.ToString() == id); + if (item != null) + { + data.Insert(0, new + { + id = id, + text = item.Name, + selected = false + }); + } + } + + return new JsonResult { Data = data, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } public ActionResult Index() diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index a72bb4095e..9911f3f69f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -1419,6 +1419,11 @@ public ActionResult ProductManufacturerInsert(GridCommand command, ProductModel. }; _manufacturerService.InsertProductManufacturer(productManufacturer); + var mru = new MostRecentlyUsedList(_workContext.CurrentCustomer.GetAttribute(SystemCustomerAttributeNames.MostRecentlyUsedManufacturers), + model.Manufacturer, _catalogSettings.MostRecentlyUsedManufacturersMaxSize); + + _genericAttributeService.SaveAttribute(_workContext.CurrentCustomer, SystemCustomerAttributeNames.MostRecentlyUsedManufacturers, mru.ToString()); + return ProductManufacturerList(command, model.ProductId); } @@ -1432,12 +1437,22 @@ public ActionResult ProductManufacturerUpdate(GridCommand command, ProductModel. if (productManufacturer == null) throw new ArgumentException("No product manufacturer mapping found with the specified id"); + bool manufacturerChanged = (Int32.Parse(model.Manufacturer) != productManufacturer.ManufacturerId); + //use Manufacturer property (not ManufacturerId) because appropriate property is stored in it productManufacturer.ManufacturerId = Int32.Parse(model.Manufacturer); productManufacturer.IsFeaturedProduct = model.IsFeaturedProduct; productManufacturer.DisplayOrder = model.DisplayOrder; _manufacturerService.UpdateProductManufacturer(productManufacturer); + if (manufacturerChanged) + { + var mru = new MostRecentlyUsedList(_workContext.CurrentCustomer.GetAttribute(SystemCustomerAttributeNames.MostRecentlyUsedManufacturers), + model.Manufacturer, _catalogSettings.MostRecentlyUsedManufacturersMaxSize); + + _genericAttributeService.SaveAttribute(_workContext.CurrentCustomer, SystemCustomerAttributeNames.MostRecentlyUsedManufacturers, mru.ToString()); + } + return ProductManufacturerList(command, productManufacturer.ProductId); } diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index c597ea62cd..9a945b6017 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -598,7 +598,8 @@ public void Execute() .ForMember(dest => dest.ShowProductImagesInSearchAutoComplete, mo => mo.Ignore()) .ForMember(dest => dest.ProductSearchPageSize, mo => mo.Ignore()) .ForMember(dest => dest.ManufacturersBlockItemsToDisplay, mo => mo.Ignore()) - .ForMember(dest => dest.MostRecentlyUsedCategoriesMaxSize, mo => mo.Ignore()); + .ForMember(dest => dest.MostRecentlyUsedCategoriesMaxSize, mo => mo.Ignore()) + .ForMember(dest => dest.MostRecentlyUsedManufacturersMaxSize, mo => mo.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.PrimaryStoreCurrencyCode, mo => mo.Ignore()) .ForMember(dest => dest.PointsForPurchases_OverrideForStore, mo => mo.Ignore()); diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Manufacturers.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Manufacturers.cshtml index e37fa56afe..e06230c752 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Manufacturers.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Manufacturers.cshtml @@ -9,7 +9,11 @@ @(Html.Telerik().Grid() @@ -47,7 +51,11 @@ .Width(180); }) .ToolBar(commands => commands.Insert()) - .ClientEvents(events => events.OnEdit("onProductManufacturerEdit")) + .ClientEvents(events => + { + events.OnEdit("onProductManufacturerEdit"); + events.OnDataBound("onProductManufacturerDataBound"); + }) .EnableCustomBinding(true)) } else From 3e3b6759ab6483b0fec810b4ddacdc9e182c82bf Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Sat, 11 Apr 2015 22:43:17 +0200 Subject: [PATCH 0034/1256] Minor localization fix --- .../SmartStore.Web.Framework/Extensions/Extensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web.Framework/Extensions/Extensions.cs b/src/Presentation/SmartStore.Web.Framework/Extensions/Extensions.cs index cc7a948a2e..f846489c7c 100644 --- a/src/Presentation/SmartStore.Web.Framework/Extensions/Extensions.cs +++ b/src/Presentation/SmartStore.Web.Framework/Extensions/Extensions.cs @@ -325,7 +325,7 @@ public static string RelativeFormat(this DateTime source, { if (delta < 60) // 60 (seconds) { - result = ts.Seconds == 1 ? localizer.GetResource("Time.OneSecondAgo") : String.Format(localizer.GetResource("Time.OneSecondAgo"), ts.Seconds); + result = ts.Seconds == 1 ? localizer.GetResource("Time.OneSecondAgo") : String.Format(localizer.GetResource("Time.SecondsAgo"), ts.Seconds); } else if (delta < 120) //2 (minutes) * 60 (seconds) { From 13bccd1caebef6a6fdca2ff51a38cfeca3d1df98 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 13 Apr 2015 11:19:06 +0200 Subject: [PATCH 0035/1256] Resolves #560 Return requests: Add fields for last update, last update of requested action and general notes Resolves #588 Alternative localized category name used as title for category pages Resolves #589 Backend product list: Add filter for products with "no category mapping" and "no manufacturer mapping" Resolves #592 Add a second category description displayed beyond products on category page Resolves #626 Add IsActive flag for checkout attributes --- changelog.md | 5 + .../Domain/Catalog/Category.cs | 13 +- .../Domain/Orders/CheckoutAttribute.cs | 10 + .../Domain/Orders/ReturnRequest.cs | 12 + .../Mapping/Catalog/CategoryMap.cs | 2 + .../Mapping/Orders/ReturnRequestMap.cs | 1 + ...11815146_NewCategoryProperties.Designer.cs | 29 + .../201504111815146_NewCategoryProperties.cs | 89 +++ ...201504111815146_NewCategoryProperties.resx | 126 ++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 + .../Sql/LatestProductLoadAllPaged.sql | 605 ++++++++++++++++++ .../Catalog/CategoryExtensions.cs | 21 +- .../Catalog/CategoryService.cs | 6 +- .../Catalog/ProductSearchContext.cs | 10 + .../Catalog/ProductService.cs | 32 +- .../ExportImport/ExportManager.cs | 6 + .../Orders/CheckoutAttributeService.cs | 18 +- .../Orders/ICheckoutAttributeService.cs | 2 +- .../Controllers/CategoryController.cs | 47 +- .../CheckoutAttributeController.cs | 17 +- .../Controllers/ProductController.cs | 4 +- .../Controllers/ReturnRequestController.cs | 25 +- .../Models/Catalog/CategoryListModel.cs | 3 +- .../Models/Catalog/CategoryModel.cs | 18 +- .../Models/Catalog/ProductListModel.cs | 7 + .../Models/Orders/CheckoutAttributeModel.cs | 6 +- .../Models/Orders/ReturnRequestModel.cs | 9 + .../Administration/Views/Category/List.cshtml | 24 +- .../Views/Category/_CreateOrUpdate.cshtml | 54 +- .../Views/CheckoutAttribute/List.cshtml | 71 +- .../CheckoutAttribute/_CreateOrUpdate.cshtml | 9 + .../Administration/Views/Product/List.cshtml | 149 +++-- .../ReturnRequest/_CreateOrUpdate.cshtml | 28 + .../Extensions/MappingExtensions.cs | 4 +- .../Models/Catalog/CategoryModel.cs | 2 + ...mplate.ProductsInGridOrLines.Mobile.cshtml | 9 +- ...egoryTemplate.ProductsInGridOrLines.cshtml | 18 +- 37 files changed, 1300 insertions(+), 201 deletions(-) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.resx create mode 100644 src/Libraries/SmartStore.Data/Sql/LatestProductLoadAllPaged.sql diff --git a/changelog.md b/changelog.md index 305e36d186..b8f50f61cf 100644 --- a/changelog.md +++ b/changelog.md @@ -14,6 +14,8 @@ * #459 New field to determine tag for page titles on widget level * Added _shrink database_ to backend UI * (Developer) Added `BeginTransaction()` and `UseTransaction()` methods to `IDbContext` +* #588 Alternative localized category name used as title for category pages +* #592 Add a second category description displayed beyond products on category page ### Improvements * Perf: product list rendering up to 10x (!) faster now (depends on page size and view mode) @@ -30,6 +32,9 @@ * #666 Export addresses in customer export * New shopping cart setting ShowItemsFromWishlistToCartButton * XML product export now paged and more data exported +* #560 Return requests: Add fields for last update, last update of requested action and general notes +* #589 Backend product list: Add filter for products with "no category mapping" and "no manufacturer mapping" +* #626 Add IsActive flag for checkout attributes ### Bugfixes * Instant search box did not display all results when SQL Fulltext Search was enabled diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/Category.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/Category.cs index 98755be4d1..b4deb2cf4b 100644 --- a/src/Libraries/SmartStore.Core/Domain/Catalog/Category.cs +++ b/src/Libraries/SmartStore.Core/Domain/Catalog/Category.cs @@ -26,17 +26,28 @@ public partial class Category : BaseEntity, ISoftDeletable, ILocalizedEntity, IS [DataMember] public string Name { get; set; } + /// + /// Gets or sets the full name (category page title) + /// + [DataMember] + public string FullName { get; set; } + /// /// Gets or sets the description /// [DataMember] public string Description { get; set; } + /// + /// Gets or sets a description displayed at the bottom of the category page + /// + [DataMember] + public string BottomDescription { get; set; } + /// /// Gets or sets the category alias /// (an optional key for advanced customization) /// - /// codehint: sm-add [DataMember] public string Alias { get; set; } diff --git a/src/Libraries/SmartStore.Core/Domain/Orders/CheckoutAttribute.cs b/src/Libraries/SmartStore.Core/Domain/Orders/CheckoutAttribute.cs index e1685f9937..a317879baa 100644 --- a/src/Libraries/SmartStore.Core/Domain/Orders/CheckoutAttribute.cs +++ b/src/Libraries/SmartStore.Core/Domain/Orders/CheckoutAttribute.cs @@ -11,6 +11,11 @@ public partial class CheckoutAttribute : BaseEntity, ILocalizedEntity { private ICollection _checkoutAttributeValues; + public CheckoutAttribute() + { + this.IsActive = true; + } + /// /// Gets or sets the name /// @@ -50,6 +55,11 @@ public partial class CheckoutAttribute : BaseEntity, ILocalizedEntity /// Gets or sets the display order /// public int DisplayOrder { get; set; } + + /// + /// Gets or sets whether the checkout attribute is active + /// + public bool IsActive { get; set; } /// /// Gets the attribute control type diff --git a/src/Libraries/SmartStore.Core/Domain/Orders/ReturnRequest.cs b/src/Libraries/SmartStore.Core/Domain/Orders/ReturnRequest.cs index 4135b6b042..ba269bdf4c 100644 --- a/src/Libraries/SmartStore.Core/Domain/Orders/ReturnRequest.cs +++ b/src/Libraries/SmartStore.Core/Domain/Orders/ReturnRequest.cs @@ -46,6 +46,12 @@ public partial class ReturnRequest : BaseEntity [DataMember] public string RequestedAction { get; set; } + /// + /// Gets or sets the date and time when requested action was last updated + /// + [DataMember] + public DateTime? RequestedActionUpdatedOnUtc { get; set; } + /// /// Gets or sets the customer comments /// @@ -58,6 +64,12 @@ public partial class ReturnRequest : BaseEntity [DataMember] public string StaffNotes { get; set; } + /// + /// Gets or sets the admin comment + /// + [DataMember] + public string AdminComment { get; set; } + /// /// Gets or sets the return status identifier /// diff --git a/src/Libraries/SmartStore.Data/Mapping/Catalog/CategoryMap.cs b/src/Libraries/SmartStore.Data/Mapping/Catalog/CategoryMap.cs index a3331fcfa3..ab3339358e 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Catalog/CategoryMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Catalog/CategoryMap.cs @@ -10,6 +10,8 @@ public CategoryMap() this.ToTable("Category"); this.HasKey(c => c.Id); this.Property(c => c.Name).IsRequired().HasMaxLength(400); + this.Property(c => c.FullName).HasMaxLength(400); + this.Property(c => c.BottomDescription).IsMaxLength(); this.Property(c => c.Description).IsMaxLength(); this.Property(c => c.MetaKeywords).HasMaxLength(400); this.Property(c => c.MetaTitle).HasMaxLength(400); diff --git a/src/Libraries/SmartStore.Data/Mapping/Orders/ReturnRequestMap.cs b/src/Libraries/SmartStore.Data/Mapping/Orders/ReturnRequestMap.cs index 9b9a5639b3..5f963c41b0 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Orders/ReturnRequestMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Orders/ReturnRequestMap.cs @@ -11,6 +11,7 @@ public ReturnRequestMap() this.HasKey(rr => rr.Id); this.Property(rr => rr.ReasonForReturn).IsRequired(); this.Property(rr => rr.RequestedAction).IsRequired(); + this.Property(rr => rr.AdminComment).HasMaxLength(4000); this.Ignore(rr => rr.ReturnRequestStatus); diff --git a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.Designer.cs new file mode 100644 index 0000000000..1cf913c0e4 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class NewCategoryProperties : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(NewCategoryProperties)); + + string IMigrationMetadata.Id + { + get { return "201504111815146_NewCategoryProperties"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs b/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs new file mode 100644 index 0000000000..43ed260971 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs @@ -0,0 +1,89 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + using System.Web.Hosting; + using SmartStore.Core.Data; + using SmartStore.Data.Setup; + + public partial class NewCategoryProperties : DbMigration, ILocaleResourcesProvider, IDataSeeder + { + public override void Up() + { + AddColumn("dbo.Category", "FullName", c => c.String(maxLength: 400)); + AddColumn("dbo.Category", "BottomDescription", c => c.String()); + + AddColumn("dbo.CheckoutAttribute", "IsActive", c => c.Boolean(nullable: false, defaultValue: true)); + + AddColumn("dbo.ReturnRequest", "AdminComment", c => c.String(maxLength: 4000)); + AddColumn("dbo.ReturnRequest", "RequestedActionUpdatedOnUtc", c => c.DateTime()); + + if (HostingEnvironment.IsHosted && DataSettings.Current.IsSqlServer) + { + this.SqlFile("LatestProductLoadAllPaged.sql"); + } + } + + public override void Down() + { + // inverse of LatestProductLoadAllPaged.sql does not make sense to me + + DropColumn("dbo.ReturnRequest", "RequestedActionUpdatedOnUtc"); + DropColumn("dbo.ReturnRequest", "AdminComment"); + + DropColumn("dbo.CheckoutAttribute", "IsActive"); + + DropColumn("dbo.Category", "BottomDescription"); + DropColumn("dbo.Category", "FullName"); + } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Admin.Catalog.Categories.Fields.FullName", + "Complete name", + "Vollstndiger Name", + "Complete name displayed as title on the category page.", + "Vollstndiger Name, der als Titel auf der Warengruppenseite angezeigt wird."); + + builder.AddOrUpdate("Admin.Catalog.Categories.Fields.BottomDescription", + "Bottom description", + "Untere Beschreibung", + "Optional second description displayed below products on the category page.", + "Optionale zweite Beschreibung, die auf der Warengruppenseite unterhalb der Produkte angezeigt wird."); + + builder.AddOrUpdate("Admin.Catalog.Products.List.SearchWithoutCategories", + "Without category mapping", + "Ohne Warengruppenzuordnung", + "Filters for products without category mapping.", + "Filtert nach Produkten ohne Warengruppenzuordnung."); + + builder.AddOrUpdate("Admin.Catalog.Products.List.SearchWithoutManufacturers", + "Without manufacturer mapping", + "Ohne Herstellerzuordnung", + "Filters for products without manufacturer mapping.", + "Filtert nach Produkten ohne Herstellerzuordnung."); + + builder.AddOrUpdate("Admin.Common.AdminComment", + "Admin comment", + "Admin-Kommentar", + "Admin comment for internal use. Won't be published.", + "Kommentar fr internen Gebrauch. Wird nicht verffentlicht."); + + builder.AddOrUpdate("Admin.ReturnRequests.Fields.RequestedActionUpdatedOnUtc", + "Last update of requested action", + "Letzte Aktualisierung der angeforderten Aktion", + "Date when the requested action was updated the last time.", + "Datum, an dem die angeforderte Aktion zuletzt gendert wurde."); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.resx b/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.resx new file mode 100644 index 0000000000..2592f8a19e --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 3b73c16870..ec387362a7 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -240,6 +240,10 @@ 201502120858030_Licensing.cs + + + 201504111815146_NewCategoryProperties.cs + @@ -474,6 +478,9 @@ 201502120858030_Licensing.cs + + 201504111815146_NewCategoryProperties.cs + @@ -489,6 +496,9 @@ + + + diff --git a/src/Libraries/SmartStore.Data/Sql/LatestProductLoadAllPaged.sql b/src/Libraries/SmartStore.Data/Sql/LatestProductLoadAllPaged.sql new file mode 100644 index 0000000000..f5b367a08b --- /dev/null +++ b/src/Libraries/SmartStore.Data/Sql/LatestProductLoadAllPaged.sql @@ -0,0 +1,605 @@ +ALTER PROCEDURE [dbo].[ProductLoadAllPaged] +( + @CategoryIds nvarchar(MAX) = null, --a list of category IDs (comma-separated list). e.g. 1,2,3 + @ManufacturerId int = 0, + @StoreId int = 0, + @ParentGroupedProductId int = 0, + @ProductTypeId int = null, --product type identifier, null - load all products + @VisibleIndividuallyOnly bit = 0, --0 - load all products , 1 - "visible indivially" only + @ProductTagId int = 0, + @FeaturedProducts bit = null, --0 featured only , 1 not featured only, null - load all products + @PriceMin decimal(18, 4) = null, + @PriceMax decimal(18, 4) = null, + @Keywords nvarchar(4000) = null, + @SearchDescriptions bit = 0, --a value indicating whether to search by a specified "keyword" in product descriptions + @SearchSku bit = 0, --a value indicating whether to search by a specified "keyword" in product SKU + @SearchProductTags bit = 0, --a value indicating whether to search by a specified "keyword" in product tags + @UseFullTextSearch bit = 0, + @FullTextMode int = 0, --0 - using CONTAINS with , 5 - using CONTAINS and OR with , 10 - using CONTAINS and AND with + @FilteredSpecs nvarchar(MAX) = null, --filter by attributes (comma-separated list). e.g. 14,15,16 + @LanguageId int = 0, + @OrderBy int = 0, --0 - position, 5 - Name: A to Z, 6 - Name: Z to A, 10 - Price: Low to High, 11 - Price: High to Low, 15 - creation date + @AllowedCustomerRoleIds nvarchar(MAX) = null, --a list of customer role IDs (comma-separated list) for which a product should be shown (if a subjet to ACL) + @PageIndex int = 0, + @PageSize int = 2147483644, + @ShowHidden bit = 0, + @LoadFilterableSpecificationAttributeOptionIds bit = 0, --a value indicating whether we should load the specification attribute option identifiers applied to loaded products (all pages) + @WithoutCategories bit = 0, + @WithoutManufacturers bit = 0, + @FilterableSpecificationAttributeOptionIds nvarchar(MAX) = null OUTPUT, --the specification attribute option identifiers applied to loaded products (all pages). returned as a comma separated list of identifiers + @TotalRecords int = null OUTPUT +) +AS +BEGIN + + /* Products that filtered by keywords */ + CREATE TABLE #KeywordProducts + ( + [ProductId] int NOT NULL + ) + + DECLARE + @SearchKeywords bit, + @sql nvarchar(max), + @sql_orderby nvarchar(max) + + SET NOCOUNT ON + + --filter by keywords + SET @Keywords = isnull(@Keywords, '') + SET @Keywords = rtrim(ltrim(@Keywords)) + IF ISNULL(@Keywords, '') != '' + BEGIN + SET @SearchKeywords = 1 + + IF @UseFullTextSearch = 1 + BEGIN + --remove wrong chars (' ") + SET @Keywords = REPLACE(@Keywords, '''', '') + SET @Keywords = REPLACE(@Keywords, '"', '') + + --full-text search + IF @FullTextMode = 0 + BEGIN + --0 - using CONTAINS with + SET @Keywords = ' "' + @Keywords + '*" ' + END + ELSE + BEGIN + --5 - using CONTAINS and OR with + --10 - using CONTAINS and AND with + + --clean multiple spaces + WHILE CHARINDEX(' ', @Keywords) > 0 + SET @Keywords = REPLACE(@Keywords, ' ', ' ') + + DECLARE @concat_term nvarchar(100) + IF @FullTextMode = 5 --5 - using CONTAINS and OR with + BEGIN + SET @concat_term = 'OR' + END + IF @FullTextMode = 10 --10 - using CONTAINS and AND with + BEGIN + SET @concat_term = 'AND' + END + + --now let's build search string + declare @fulltext_keywords nvarchar(4000) + set @fulltext_keywords = N'' + declare @index int + + set @index = CHARINDEX(' ', @Keywords, 0) + + -- if index = 0, then only one field was passed + IF(@index = 0) + set @fulltext_keywords = ' "' + @Keywords + '*" ' + ELSE + BEGIN + DECLARE @first BIT + SET @first = 1 + WHILE @index > 0 + BEGIN + IF (@first = 0) + SET @fulltext_keywords = @fulltext_keywords + ' ' + @concat_term + ' ' + ELSE + SET @first = 0 + + SET @fulltext_keywords = @fulltext_keywords + '"' + SUBSTRING(@Keywords, 1, @index - 1) + '*"' + SET @Keywords = SUBSTRING(@Keywords, @index + 1, LEN(@Keywords) - @index) + SET @index = CHARINDEX(' ', @Keywords, 0) + end + + -- add the last field + IF LEN(@fulltext_keywords) > 0 + SET @fulltext_keywords = @fulltext_keywords + ' ' + @concat_term + ' ' + '"' + SUBSTRING(@Keywords, 1, LEN(@Keywords)) + '*"' + END + SET @Keywords = @fulltext_keywords + END + END + ELSE + BEGIN + --usual search by PATINDEX + SET @Keywords = '%' + @Keywords + '%' + END + --PRINT @Keywords + + --product name + SET @sql = ' + INSERT INTO #KeywordProducts ([ProductId]) + SELECT p.Id + FROM Product p with (NOLOCK) + WHERE ' + IF @UseFullTextSearch = 1 + SET @sql = @sql + 'CONTAINS(p.[Name], @Keywords) ' + ELSE + SET @sql = @sql + 'PATINDEX(@Keywords, p.[Name]) > 0 ' + + + --localized product name + SET @sql = @sql + ' + UNION + SELECT lp.EntityId + FROM LocalizedProperty lp with (NOLOCK) + WHERE + lp.LocaleKeyGroup = N''Product'' + AND lp.LanguageId = ' + ISNULL(CAST(@LanguageId AS nvarchar(max)), '0') + ' + AND lp.LocaleKey = N''Name''' + IF @UseFullTextSearch = 1 + SET @sql = @sql + ' AND CONTAINS(lp.[LocaleValue], @Keywords) ' + ELSE + SET @sql = @sql + ' AND PATINDEX(@Keywords, lp.[LocaleValue]) > 0 ' + + + IF @SearchDescriptions = 1 + BEGIN + --product short description + SET @sql = @sql + ' + UNION + SELECT p.Id + FROM Product p with (NOLOCK) + WHERE ' + IF @UseFullTextSearch = 1 + SET @sql = @sql + 'CONTAINS(p.[ShortDescription], @Keywords) ' + ELSE + SET @sql = @sql + 'PATINDEX(@Keywords, p.[ShortDescription]) > 0 ' + + + --product full description + SET @sql = @sql + ' + UNION + SELECT p.Id + FROM Product p with (NOLOCK) + WHERE ' + IF @UseFullTextSearch = 1 + SET @sql = @sql + 'CONTAINS(p.[FullDescription], @Keywords) ' + ELSE + SET @sql = @sql + 'PATINDEX(@Keywords, p.[FullDescription]) > 0 ' + + + + --localized product short description + SET @sql = @sql + ' + UNION + SELECT lp.EntityId + FROM LocalizedProperty lp with (NOLOCK) + WHERE + lp.LocaleKeyGroup = N''Product'' + AND lp.LanguageId = ' + ISNULL(CAST(@LanguageId AS nvarchar(max)), '0') + ' + AND lp.LocaleKey = N''ShortDescription''' + IF @UseFullTextSearch = 1 + SET @sql = @sql + ' AND CONTAINS(lp.[LocaleValue], @Keywords) ' + ELSE + SET @sql = @sql + ' AND PATINDEX(@Keywords, lp.[LocaleValue]) > 0 ' + + + --localized product full description + SET @sql = @sql + ' + UNION + SELECT lp.EntityId + FROM LocalizedProperty lp with (NOLOCK) + WHERE + lp.LocaleKeyGroup = N''Product'' + AND lp.LanguageId = ' + ISNULL(CAST(@LanguageId AS nvarchar(max)), '0') + ' + AND lp.LocaleKey = N''FullDescription''' + IF @UseFullTextSearch = 1 + SET @sql = @sql + ' AND CONTAINS(lp.[LocaleValue], @Keywords) ' + ELSE + SET @sql = @sql + ' AND PATINDEX(@Keywords, lp.[LocaleValue]) > 0 ' + END + + --SKU + IF @SearchSku = 1 + BEGIN + SET @sql = @sql + ' + UNION + SELECT p.Id + FROM Product p with (NOLOCK) + LEFT OUTER JOIN ProductVariantAttributeCombination pvac with(NOLOCK) ON pvac.ProductId = p.Id + WHERE ' + IF @UseFullTextSearch = 1 + SET @sql = @sql + '(CONTAINS(pvac.[Sku], @Keywords) OR CONTAINS(p.[Sku], @Keywords)) ' + ELSE + SET @sql = @sql + 'PATINDEX(@Keywords, pvac.[Sku]) > 0 OR PATINDEX(@Keywords, p.[Sku]) > 0 ' + END + + IF @SearchProductTags = 1 + BEGIN + --product tag + SET @sql = @sql + ' + UNION + SELECT pptm.Product_Id + FROM Product_ProductTag_Mapping pptm with(NOLOCK) INNER JOIN ProductTag pt with(NOLOCK) ON pt.Id = pptm.ProductTag_Id + WHERE ' + IF @UseFullTextSearch = 1 + SET @sql = @sql + 'CONTAINS(pt.[Name], @Keywords) ' + ELSE + SET @sql = @sql + 'PATINDEX(@Keywords, pt.[Name]) > 0 ' + + --localized product tag + SET @sql = @sql + ' + UNION + SELECT pptm.Product_Id + FROM LocalizedProperty lp with (NOLOCK) INNER JOIN Product_ProductTag_Mapping pptm with(NOLOCK) ON lp.EntityId = pptm.ProductTag_Id + WHERE + lp.LocaleKeyGroup = N''ProductTag'' + AND lp.LanguageId = ' + ISNULL(CAST(@LanguageId AS nvarchar(max)), '0') + ' + AND lp.LocaleKey = N''Name''' + IF @UseFullTextSearch = 1 + SET @sql = @sql + ' AND CONTAINS(lp.[LocaleValue], @Keywords) ' + ELSE + SET @sql = @sql + ' AND PATINDEX(@Keywords, lp.[LocaleValue]) > 0 ' + END + + --PRINT (@sql) + EXEC sp_executesql @sql, N'@Keywords nvarchar(4000)', @Keywords + + END + ELSE + BEGIN + SET @SearchKeywords = 0 + END + + --filter by category IDs + SET @CategoryIds = isnull(@CategoryIds, '') + CREATE TABLE #FilteredCategoryIds + ( + CategoryId int not null + ) + INSERT INTO #FilteredCategoryIds (CategoryId) + SELECT CAST(data as int) FROM [sm_splitstring_to_table](@CategoryIds, ',') + DECLARE @CategoryIdsCount int + SET @CategoryIdsCount = (SELECT COUNT(1) FROM #FilteredCategoryIds) + + --filter by attributes + SET @FilteredSpecs = isnull(@FilteredSpecs, '') + CREATE TABLE #FilteredSpecs + ( + SpecificationAttributeOptionId int not null + ) + INSERT INTO #FilteredSpecs (SpecificationAttributeOptionId) + SELECT CAST(data as int) FROM [sm_splitstring_to_table](@FilteredSpecs, ',') + DECLARE @SpecAttributesCount int + SET @SpecAttributesCount = (SELECT COUNT(1) FROM #FilteredSpecs) + + --filter by customer role IDs (access control list) + SET @AllowedCustomerRoleIds = isnull(@AllowedCustomerRoleIds, '') + CREATE TABLE #FilteredCustomerRoleIds + ( + CustomerRoleId int not null + ) + INSERT INTO #FilteredCustomerRoleIds (CustomerRoleId) + SELECT CAST(data as int) FROM [sm_splitstring_to_table](@AllowedCustomerRoleIds, ',') + + --paging + DECLARE @PageLowerBound int + DECLARE @PageUpperBound int + DECLARE @RowsToReturn int + SET @RowsToReturn = @PageSize * (@PageIndex + 1) + SET @PageLowerBound = @PageSize * @PageIndex + SET @PageUpperBound = @PageLowerBound + @PageSize + 1 + + CREATE TABLE #DisplayOrderTmp + ( + [Id] int IDENTITY (1, 1) NOT NULL, + [ProductId] int NOT NULL + ) + + SET @sql = ' + INSERT INTO #DisplayOrderTmp ([ProductId]) + SELECT p.Id + FROM + Product p with (NOLOCK)' + + IF @CategoryIdsCount > 0 + BEGIN + SET @sql = @sql + ' + LEFT JOIN Product_Category_Mapping pcm with (NOLOCK) + ON p.Id = pcm.ProductId' + END + + IF @ManufacturerId > 0 + BEGIN + SET @sql = @sql + ' + LEFT JOIN Product_Manufacturer_Mapping pmm with (NOLOCK) + ON p.Id = pmm.ProductId' + END + + IF ISNULL(@ProductTagId, 0) != 0 + BEGIN + SET @sql = @sql + ' + LEFT JOIN Product_ProductTag_Mapping pptm with (NOLOCK) + ON p.Id = pptm.Product_Id' + END + + --searching by keywords + IF @SearchKeywords = 1 + BEGIN + SET @sql = @sql + ' + JOIN #KeywordProducts kp + ON p.Id = kp.ProductId' + END + + SET @sql = @sql + ' + WHERE + p.Deleted = 0' + + --filter by category + IF @CategoryIdsCount > 0 + BEGIN + SET @sql = @sql + ' + AND pcm.CategoryId IN (SELECT CategoryId FROM #FilteredCategoryIds)' + + IF @FeaturedProducts IS NOT NULL + BEGIN + SET @sql = @sql + ' + AND pcm.IsFeaturedProduct = ' + CAST(@FeaturedProducts AS nvarchar(max)) + END + END + + --filter by manufacturer + IF @ManufacturerId > 0 + BEGIN + SET @sql = @sql + ' + AND pmm.ManufacturerId = ' + CAST(@ManufacturerId AS nvarchar(max)) + + IF @FeaturedProducts IS NOT NULL + BEGIN + SET @sql = @sql + ' + AND pmm.IsFeaturedProduct = ' + CAST(@FeaturedProducts AS nvarchar(max)) + END + END + + --filter by parent grouped product identifer + IF @ParentGroupedProductId > 0 + BEGIN + SET @sql = @sql + ' + AND p.ParentGroupedProductId = ' + CAST(@ParentGroupedProductId AS nvarchar(max)) + END + + --filter by product type + IF @ProductTypeId is not null + BEGIN + SET @sql = @sql + ' + AND p.ProductTypeId = ' + CAST(@ProductTypeId AS nvarchar(max)) + END + + --filter by visible individually + IF @VisibleIndividuallyOnly = 1 + BEGIN + SET @sql = @sql + ' + AND p.VisibleIndividually = 1' + END + + --filter by product tag + IF ISNULL(@ProductTagId, 0) != 0 + BEGIN + SET @sql = @sql + ' + AND pptm.ProductTag_Id = ' + CAST(@ProductTagId AS nvarchar(max)) + END + + --show hidden + IF @ShowHidden = 0 + BEGIN + SET @sql = @sql + ' + AND p.Published = 1 + AND p.Deleted = 0 + AND (getutcdate() BETWEEN ISNULL(p.AvailableStartDateTimeUtc, ''1/1/1900'') and ISNULL(p.AvailableEndDateTimeUtc, ''1/1/2999''))' + END + + --min price + IF @PriceMin > 0 + BEGIN + SET @sql = @sql + ' + AND ( + ( + --special price (specified price and valid date range) + (p.SpecialPrice IS NOT NULL AND (getutcdate() BETWEEN isnull(p.SpecialPriceStartDateTimeUtc, ''1/1/1900'') AND isnull(p.SpecialPriceEndDateTimeUtc, ''1/1/2999''))) + AND + (p.SpecialPrice >= ' + CAST(@PriceMin AS nvarchar(max)) + ') + ) + OR + ( + --regular price (price isnt specified or date range isnt valid) + (p.SpecialPrice IS NULL OR (getutcdate() NOT BETWEEN isnull(p.SpecialPriceStartDateTimeUtc, ''1/1/1900'') AND isnull(p.SpecialPriceEndDateTimeUtc, ''1/1/2999''))) + AND + (p.Price >= ' + CAST(@PriceMin AS nvarchar(max)) + ') + ) + )' + END + + --max price + IF @PriceMax > 0 + BEGIN + SET @sql = @sql + ' + AND ( + ( + --special price (specified price and valid date range) + (p.SpecialPrice IS NOT NULL AND (getutcdate() BETWEEN isnull(p.SpecialPriceStartDateTimeUtc, ''1/1/1900'') AND isnull(p.SpecialPriceEndDateTimeUtc, ''1/1/2999''))) + AND + (p.SpecialPrice <= ' + CAST(@PriceMax AS nvarchar(max)) + ') + ) + OR + ( + --regular price (price isnt specified or date range isnt valid) + (p.SpecialPrice IS NULL OR (getutcdate() NOT BETWEEN isnull(p.SpecialPriceStartDateTimeUtc, ''1/1/1900'') AND isnull(p.SpecialPriceEndDateTimeUtc, ''1/1/2999''))) + AND + (p.Price <= ' + CAST(@PriceMax AS nvarchar(max)) + ') + ) + )' + END + + --show hidden and ACL + IF @ShowHidden = 0 + BEGIN + SET @sql = @sql + ' + AND (p.SubjectToAcl = 0 OR EXISTS ( + SELECT 1 FROM #FilteredCustomerRoleIds [fcr] + WHERE + [fcr].CustomerRoleId IN ( + SELECT [acl].CustomerRoleId + FROM [AclRecord] acl with (NOLOCK) + WHERE [acl].EntityId = p.Id AND [acl].EntityName = ''Product'' + ) + ))' + END + + --show hidden and filter by store + IF @StoreId > 0 + BEGIN + SET @sql = @sql + ' + AND (p.LimitedToStores = 0 OR EXISTS ( + SELECT 1 FROM [StoreMapping] sm with (NOLOCK) + WHERE [sm].EntityId = p.Id AND [sm].EntityName = ''Product'' and [sm].StoreId=' + CAST(@StoreId AS nvarchar(max)) + ' + ))' + END + + --filter by specs + IF @SpecAttributesCount > 0 + BEGIN + SET @sql = @sql + ' + AND NOT EXISTS ( + SELECT 1 FROM #FilteredSpecs [fs] + WHERE + [fs].SpecificationAttributeOptionId NOT IN ( + SELECT psam.SpecificationAttributeOptionId + FROM Product_SpecificationAttribute_Mapping psam with (NOLOCK) + WHERE psam.AllowFiltering = 1 AND psam.ProductId = p.Id + ) + )' + END + + IF @WithoutCategories = 1 + BEGIN + SET @sql = @sql + ' + AND NOT EXISTS ( + SELECT 1 FROM [Product_Category_Mapping] pcm with (NOLOCK) + WHERE [pcm].[ProductId] = p.Id + )' + END + + IF @WithoutManufacturers = 1 + BEGIN + SET @sql = @sql + ' + AND NOT EXISTS ( + SELECT 1 FROM [Product_Manufacturer_Mapping] pmm with (NOLOCK) + WHERE [pmm].[ProductId] = p.Id + )' + END + + --sorting + SET @sql_orderby = '' + IF @OrderBy = 5 /* Name: A to Z */ + SET @sql_orderby = ' p.[Name] ASC' + ELSE IF @OrderBy = 6 /* Name: Z to A */ + SET @sql_orderby = ' p.[Name] DESC' + ELSE IF @OrderBy = 10 /* Price: Low to High */ + SET @sql_orderby = ' p.[Price] ASC' + ELSE IF @OrderBy = 11 /* Price: High to Low */ + SET @sql_orderby = ' p.[Price] DESC' + ELSE IF @OrderBy = 15 /* creation date */ + SET @sql_orderby = ' p.[CreatedOnUtc] DESC' + ELSE /* default sorting, 0 (position) */ + BEGIN + --category position (display order) + IF @CategoryIdsCount > 0 SET @sql_orderby = ' pcm.DisplayOrder ASC' + + --manufacturer position (display order) + IF @ManufacturerId > 0 + BEGIN + IF LEN(@sql_orderby) > 0 SET @sql_orderby = @sql_orderby + ', ' + SET @sql_orderby = @sql_orderby + ' pmm.DisplayOrder ASC' + END + + --parent grouped product specified (sort associated products) + IF @ParentGroupedProductId > 0 + BEGIN + IF LEN(@sql_orderby) > 0 SET @sql_orderby = @sql_orderby + ', ' + SET @sql_orderby = @sql_orderby + ' p.[DisplayOrder] ASC' + END + + --name + IF LEN(@sql_orderby) > 0 SET @sql_orderby = @sql_orderby + ', ' + SET @sql_orderby = @sql_orderby + ' p.[Name] ASC' + END + + SET @sql = @sql + ' + ORDER BY' + @sql_orderby + + --PRINT (@sql) + EXEC sp_executesql @sql + + DROP TABLE #FilteredCategoryIds + DROP TABLE #FilteredSpecs + DROP TABLE #FilteredCustomerRoleIds + DROP TABLE #KeywordProducts + + CREATE TABLE #PageIndex + ( + [IndexId] int IDENTITY (1, 1) NOT NULL, + [ProductId] int NOT NULL + ) + INSERT INTO #PageIndex ([ProductId]) + SELECT ProductId + FROM #DisplayOrderTmp + GROUP BY ProductId + ORDER BY min([Id]) + + --total records + SET @TotalRecords = @@rowcount + + DROP TABLE #DisplayOrderTmp + + --prepare filterable specification attribute option identifier (if requested) + IF @LoadFilterableSpecificationAttributeOptionIds = 1 + BEGIN + CREATE TABLE #FilterableSpecs + ( + [SpecificationAttributeOptionId] int NOT NULL + ) + INSERT INTO #FilterableSpecs ([SpecificationAttributeOptionId]) + SELECT DISTINCT [psam].SpecificationAttributeOptionId + FROM [Product_SpecificationAttribute_Mapping] [psam] with (NOLOCK) + WHERE [psam].[AllowFiltering] = 1 + AND [psam].[ProductId] IN (SELECT [pi].ProductId FROM #PageIndex [pi]) + + --build comma separated list of filterable identifiers + SELECT @FilterableSpecificationAttributeOptionIds = COALESCE(@FilterableSpecificationAttributeOptionIds + ',' , '') + CAST(SpecificationAttributeOptionId as nvarchar(4000)) + FROM #FilterableSpecs + + DROP TABLE #FilterableSpecs + END + + --return products + SELECT TOP (@RowsToReturn) + p.* + FROM + #PageIndex [pi] + INNER JOIN Product p with (NOLOCK) on p.Id = [pi].[ProductId] + WHERE + [pi].IndexId > @PageLowerBound AND + [pi].IndexId < @PageUpperBound + ORDER BY + [pi].IndexId + + DROP TABLE #PageIndex +END diff --git a/src/Libraries/SmartStore.Services/Catalog/CategoryExtensions.cs b/src/Libraries/SmartStore.Services/Catalog/CategoryExtensions.cs index 939501292a..39825192a6 100644 --- a/src/Libraries/SmartStore.Services/Catalog/CategoryExtensions.cs +++ b/src/Libraries/SmartStore.Services/Catalog/CategoryExtensions.cs @@ -47,17 +47,17 @@ public static IList SortCategoriesForTree(this IList source, /// Product identifier /// Category identifier /// A ProductCategory that has the specified values; otherwise null - public static ProductCategory FindProductCategory(this IList source, - int productId, int categoryId) + public static ProductCategory FindProductCategory(this IList source, int productId, int categoryId) { - foreach (var productCategory in source) - if (productCategory.ProductId == productId && productCategory.CategoryId == categoryId) - return productCategory; - + foreach (var productCategory in source) + { + if (productCategory.ProductId == productId && productCategory.CategoryId == categoryId) + return productCategory; + } return null; } - public static string GetFullCategoryName(this Category category) + public static string GetCategoryNameWithAlias(this Category category) { if (category != null) { @@ -77,7 +77,7 @@ public static string GetCategoryNameWithPrefix(this Category category, ICategory { if (String.IsNullOrEmpty(result)) { - result = category.GetFullCategoryName(); + result = category.GetCategoryNameWithAlias(); } else { @@ -103,14 +103,13 @@ public static string GetCategoryBreadCrumb(this Category category, ICategoryServ while (category != null && !category.Deleted) { - // codehint: sm-edit if (String.IsNullOrEmpty(result)) { - result = category.GetFullCategoryName(); + result = category.GetCategoryNameWithAlias(); } else { - result = category.GetFullCategoryName() + " >> " + result; + result = category.GetCategoryNameWithAlias() + " >> " + result; } int parentId = category.ParentCategoryId; diff --git a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs index 0b16a2a4a0..0733a9fa98 100644 --- a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs @@ -148,12 +148,16 @@ public virtual IPagedList GetAllCategories(string categoryName = "", i bool applyNavigationFilters = true, bool ignoreCategoriesWithoutExistingParent = true) { var query = _categoryRepository.Table; + if (!showHidden) query = query.Where(c => c.Published); + if (!String.IsNullOrWhiteSpace(categoryName)) - query = query.Where(c => c.Name.Contains(categoryName)); + query = query.Where(c => c.Name.Contains(categoryName) || c.FullName.Contains(categoryName)); + if (!String.IsNullOrWhiteSpace(alias)) query = query.Where(c => c.Alias.Contains(alias)); + query = query.Where(c => !c.Deleted); query = query.OrderBy(c => c.ParentCategoryId).ThenBy(c => c.DisplayOrder); diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductSearchContext.cs b/src/Libraries/SmartStore.Services/Catalog/ProductSearchContext.cs index 2f9f92362e..3e8fd2d1f0 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductSearchContext.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductSearchContext.cs @@ -37,11 +37,21 @@ public ProductSearchContext() /// Only works in LINQ mode at the moment public bool MatchAllcategories { get; set; } + /// + /// A value indicating whether to load products without any catgory mapping + /// + public bool WithoutCategories { get; set; } + /// /// Manufacturer identifier; 0 to load all records /// public int ManufacturerId { get; set; } + /// + /// A value indicating whether to load products without any manufacturer mapping + /// + public bool WithoutManufacturers { get; set; } + /// /// A value indicating whether loaded products are marked as featured (relates only to categories and manufacturers). 0 to load featured products only, 1 to load not featured products only, null to load all products /// diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs index 7546dc5b37..46c783293f 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs @@ -42,7 +42,7 @@ public partial class ProductService : IProductService private readonly IRepository _storeMappingRepository; private readonly IRepository _productPictureRepository; private readonly IRepository _productSpecificationAttributeRepository; - private readonly IRepository _productVariantAttributeCombinationRepository; // codehint: sm-add + private readonly IRepository _productVariantAttributeCombinationRepository; private readonly IRepository _productBundleItemRepository; private readonly IProductAttributeService _productAttributeService; private readonly IProductAttributeParser _productAttributeParser; @@ -272,7 +272,6 @@ public virtual int CountProducts(ProductSearchContext ctx) public virtual IPagedList SearchProducts(ProductSearchContext ctx) { - // codehint: sm-edit (turn off nc filtering, we have our own) ctx.LoadFilterableSpecificationAttributeOptionIds = false; ctx.FilterableSpecificationAttributeOptionIds = new List(); @@ -312,7 +311,7 @@ public virtual IPagedList SearchProducts(ProductSearchContext ctx) //pass categry identifiers as comma-delimited string string commaSeparatedCategoryIds = ""; - if (ctx.CategoryIds != null) + if (ctx.CategoryIds != null && !ctx.WithoutCategories) { for (int i = 0; i < ctx.CategoryIds.Count; i++) { @@ -362,7 +361,7 @@ public virtual IPagedList SearchProducts(ProductSearchContext ctx) var pManufacturerId = _dataProvider.GetParameter(); pManufacturerId.ParameterName = "ManufacturerId"; - pManufacturerId.Value = ctx.ManufacturerId; + pManufacturerId.Value = (ctx.WithoutManufacturers ? 0 : ctx.ManufacturerId); pManufacturerId.DbType = DbType.Int32; var pStoreId = _dataProvider.GetParameter(); @@ -475,6 +474,16 @@ public virtual IPagedList SearchProducts(ProductSearchContext ctx) pLoadFilterableSpecificationAttributeOptionIds.Value = ctx.LoadFilterableSpecificationAttributeOptionIds; pLoadFilterableSpecificationAttributeOptionIds.DbType = DbType.Boolean; + var pWithoutCategories = _dataProvider.GetParameter(); + pWithoutCategories.ParameterName = "WithoutCategories"; + pWithoutCategories.Value = ctx.WithoutCategories; + pWithoutCategories.DbType = DbType.Boolean; + + var pWithoutManufacturers = _dataProvider.GetParameter(); + pWithoutManufacturers.ParameterName = "WithoutManufacturers"; + pWithoutManufacturers.Value = ctx.WithoutManufacturers; + pWithoutManufacturers.DbType = DbType.Boolean; + var pFilterableSpecificationAttributeOptionIds = _dataProvider.GetParameter(); pFilterableSpecificationAttributeOptionIds.ParameterName = "FilterableSpecificationAttributeOptionIds"; pFilterableSpecificationAttributeOptionIds.Direction = ParameterDirection.Output; @@ -513,6 +522,8 @@ public virtual IPagedList SearchProducts(ProductSearchContext ctx) pPageSize, pShowHidden, pLoadFilterableSpecificationAttributeOptionIds, + pWithoutCategories, + pWithoutManufacturers, pFilterableSpecificationAttributeOptionIds, pTotalRecords); @@ -785,7 +796,11 @@ from p in query } // category filtering - if (ctx.CategoryIds != null && ctx.CategoryIds.Count > 0) + if (ctx.WithoutCategories) + { + query = query.Where(x => x.ProductCategories.Count == 0); + } + else if (ctx.CategoryIds != null && ctx.CategoryIds.Count > 0) { //search in subcategories if (ctx.MatchAllcategories) @@ -806,7 +821,11 @@ from pc in p.ProductCategories.Where(pc => ctx.CategoryIds.Contains(pc.CategoryI } // manufacturer filtering - if (ctx.ManufacturerId > 0) + if (ctx.WithoutManufacturers) + { + query = query.Where(x => x.ProductManufacturers.Count == 0); + } + else if (ctx.ManufacturerId > 0) { query = from p in query from pm in p.ProductManufacturers.Where(pm => pm.ManufacturerId == ctx.ManufacturerId) @@ -1446,7 +1465,6 @@ public virtual void DeleteProductPicture(ProductPicture productPicture) if (productPicture == null) throw new ArgumentNullException("productPicture"); - // codehint: sm-add UnassignDeletedPictureFromVariantCombinations(productPicture); _productPictureRepository.Delete(productPicture); diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 5940062b54..d33dbf7dee 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -100,7 +100,9 @@ protected virtual void WriteCategories(XmlWriter writer, int parentCategoryId) 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); @@ -561,7 +563,9 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo 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); @@ -589,7 +593,9 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo 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); diff --git a/src/Libraries/SmartStore.Services/Orders/CheckoutAttributeService.cs b/src/Libraries/SmartStore.Services/Orders/CheckoutAttributeService.cs index 981f4f879a..d9a340c451 100644 --- a/src/Libraries/SmartStore.Services/Orders/CheckoutAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Orders/CheckoutAttributeService.cs @@ -14,12 +14,14 @@ namespace SmartStore.Services.Orders public partial class CheckoutAttributeService : ICheckoutAttributeService { #region Constants + private const string CHECKOUTATTRIBUTES_ALL_KEY = "SmartStore.checkoutattribute.all-{0}"; private const string CHECKOUTATTRIBUTEVALUES_ALL_KEY = "SmartStore.checkoutattributevalue.all-{0}"; private const string CHECKOUTATTRIBUTES_PATTERN_KEY = "SmartStore.checkoutattribute."; private const string CHECKOUTATTRIBUTEVALUES_PATTERN_KEY = "SmartStore.checkoutattributevalue."; private const string CHECKOUTATTRIBUTES_BY_ID_KEY = "SmartStore.checkoutattribute.id-{0}"; private const string CHECKOUTATTRIBUTEVALUES_BY_ID_KEY = "SmartStore.checkoutattributevalue.id-{0}"; + #endregion #region Fields @@ -79,13 +81,19 @@ public virtual void DeleteCheckoutAttribute(CheckoutAttribute checkoutAttribute) /// Gets all checkout attributes /// /// Checkout attribute collection - public virtual IList GetAllCheckoutAttributes() + public virtual IList GetAllCheckoutAttributes(bool showHidden = false) { - return _cacheManager.Get(CHECKOUTATTRIBUTES_ALL_KEY, () => + string key = CHECKOUTATTRIBUTES_ALL_KEY.FormatInvariant(showHidden); + + return _cacheManager.Get(key, () => { - var query = from ca in _checkoutAttributeRepository.Table - orderby ca.DisplayOrder - select ca; + var query = _checkoutAttributeRepository.Table; + + if (!showHidden) + query = query.Where(x => x.IsActive); + + query = query.OrderBy(x => x.DisplayOrder); + var checkoutAttributes = query.ToList(); return checkoutAttributes; }); diff --git a/src/Libraries/SmartStore.Services/Orders/ICheckoutAttributeService.cs b/src/Libraries/SmartStore.Services/Orders/ICheckoutAttributeService.cs index cb34e948c4..2ceb9c3396 100644 --- a/src/Libraries/SmartStore.Services/Orders/ICheckoutAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Orders/ICheckoutAttributeService.cs @@ -20,7 +20,7 @@ public partial interface ICheckoutAttributeService /// Gets all checkout attributes /// /// Checkout attribute collection - IList GetAllCheckoutAttributes(); + IList GetAllCheckoutAttributes(bool showHidden = false); /// /// Gets a checkout attribute diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs index e9fc74a00c..c66181d69a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Catalog; @@ -109,30 +108,19 @@ protected void UpdateLocales(Category category, CategoryModel model) { foreach (var localized in model.Locales) { - _localizedEntityService.SaveLocalizedValue(category, - x => x.Name, - localized.Name, - localized.LanguageId); - - _localizedEntityService.SaveLocalizedValue(category, - x => x.Description, - localized.Description, - localized.LanguageId); - - _localizedEntityService.SaveLocalizedValue(category, - x => x.MetaKeywords, - localized.MetaKeywords, - localized.LanguageId); - - _localizedEntityService.SaveLocalizedValue(category, - x => x.MetaDescription, - localized.MetaDescription, - localized.LanguageId); - - _localizedEntityService.SaveLocalizedValue(category, - x => x.MetaTitle, - localized.MetaTitle, - localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(category, x => x.Name, localized.Name, localized.LanguageId); + + _localizedEntityService.SaveLocalizedValue(category, x => x.FullName, localized.FullName, localized.LanguageId); + + _localizedEntityService.SaveLocalizedValue(category, x => x.Description, localized.Description, localized.LanguageId); + + _localizedEntityService.SaveLocalizedValue(category, x => x.BottomDescription, localized.BottomDescription, localized.LanguageId); + + _localizedEntityService.SaveLocalizedValue(category, x => x.MetaKeywords, localized.MetaKeywords, localized.LanguageId); + + _localizedEntityService.SaveLocalizedValue(category, x => x.MetaDescription, localized.MetaDescription, localized.LanguageId); + + _localizedEntityService.SaveLocalizedValue(category, x => x.MetaTitle, localized.MetaTitle, localized.LanguageId); //search engine name var seName = category.ValidateSeName(localized.SeName, localized.Name, false, localized.LanguageId); @@ -276,9 +264,14 @@ public ActionResult List() if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); - var model = new CategoryListModel(); + var model = new CategoryListModel + { + GridPageSize = _adminAreaSettings.GridPageSize + }; + var categories = _categoryService.GetAllCategories(null, 0, _adminAreaSettings.GridPageSize, true); var mappedCategories = categories.ToDictionary(x => x.Id); + model.Categories = new GridModel { Data = categories.Select(x => @@ -591,7 +584,9 @@ public ActionResult Edit(int id) AddLocales(_languageService, model.Locales, (locale, languageId) => { locale.Name = category.GetLocalized(x => x.Name, languageId, false, false); + locale.FullName = category.GetLocalized(x => x.FullName, languageId, false, false); locale.Description = category.GetLocalized(x => x.Description, languageId, false, false); + locale.BottomDescription = category.GetLocalized(x => x.BottomDescription, languageId, false, false); locale.MetaKeywords = category.GetLocalized(x => x.MetaKeywords, languageId, false, false); locale.MetaDescription = category.GetLocalized(x => x.MetaDescription, languageId, false, false); locale.MetaTitle = category.GetLocalized(x => x.MetaTitle, languageId, false, false); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CheckoutAttributeController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CheckoutAttributeController.cs index b0d2d559d6..11009f3784 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CheckoutAttributeController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CheckoutAttributeController.cs @@ -120,18 +120,7 @@ public ActionResult List() if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); - var checkoutAttributes = _checkoutAttributeService.GetAllCheckoutAttributes(); - var gridModel = new GridModel - { - Data = checkoutAttributes.Select(x => - { - var caModel = x.ToModel(); - caModel.AttributeControlTypeName = x.AttributeControlType.GetLocalizedEnum(_localizationService, _workContext); - return caModel; - }), - Total = checkoutAttributes.Count() - }; - return View(gridModel); + return View(); } [HttpPost, GridAction(EnableCustomBinding = true)] @@ -140,7 +129,7 @@ public ActionResult List(GridCommand command) if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); - var checkoutAttributes = _checkoutAttributeService.GetAllCheckoutAttributes(); + var checkoutAttributes = _checkoutAttributeService.GetAllCheckoutAttributes(true); var gridModel = new GridModel { Data = checkoutAttributes.Select(x => @@ -164,6 +153,8 @@ public ActionResult Create() return AccessDeniedView(); var model = new CheckoutAttributeModel(); + model.IsActive = true; + //locales AddLocales(_languageService, model.Locales); PrepareCheckoutAttributeModel(model, null, true); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index 9911f3f69f..3afa1197d6 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -923,7 +923,9 @@ public ActionResult ProductList(GridCommand command, ProductListModel model) PageIndex = command.Page - 1, PageSize = command.PageSize, ShowHidden = true, - ProductType = model.SearchProductTypeId > 0 ? (ProductType?)model.SearchProductTypeId : null + ProductType = model.SearchProductTypeId > 0 ? (ProductType?)model.SearchProductTypeId : null, + WithoutCategories = model.SearchWithoutCategories, + WithoutManufacturers = model.SearchWithoutManufacturers }; if (model.SearchCategoryId > 0) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ReturnRequestController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ReturnRequestController.cs index e6c75f0b05..e87838859c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ReturnRequestController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ReturnRequestController.cs @@ -1,24 +1,24 @@ using System; -using System.Linq; using System.Collections.Generic; +using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Orders; using SmartStore.Core; +using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Logging; +using SmartStore.Services.Catalog; using SmartStore.Services.Customers; using SmartStore.Services.Helpers; using SmartStore.Services.Localization; -using SmartStore.Core.Logging; using SmartStore.Services.Messages; using SmartStore.Services.Orders; using SmartStore.Services.Security; -using SmartStore.Services.Catalog; +using SmartStore.Services.Stores; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Controllers; using Telerik.Web.Mvc; -using SmartStore.Core.Domain.Common; -using SmartStore.Services.Stores; namespace SmartStore.Admin.Controllers { @@ -116,13 +116,19 @@ private bool PrepareReturnRequestModel(ReturnRequestModel model, ReturnRequest r model.Quantity = returnRequest.Quantity; model.ReturnRequestStatusStr = returnRequest.ReturnRequestStatus.GetLocalizedEnum(_localizationService, _workContext); model.CreatedOn = _dateTimeHelper.ConvertToUserTime(returnRequest.CreatedOnUtc, DateTimeKind.Utc); + model.UpdatedOn = _dateTimeHelper.ConvertToUserTime(returnRequest.UpdatedOnUtc, DateTimeKind.Utc); if (!excludeProperties) { model.ReasonForReturn = returnRequest.ReasonForReturn; model.RequestedAction = returnRequest.RequestedAction; + + if (returnRequest.RequestedActionUpdatedOnUtc.HasValue) + model.RequestedActionUpdated = _dateTimeHelper.ConvertToUserTime(returnRequest.RequestedActionUpdatedOnUtc.Value, DateTimeKind.Utc); + model.CustomerComments = returnRequest.CustomerComments; model.StaffNotes = returnRequest.StaffNotes; + model.AdminComment = returnRequest.AdminComment; model.ReturnRequestStatusId = returnRequest.ReturnRequestStatusId; } @@ -238,13 +244,19 @@ public ActionResult Edit(ReturnRequestModel model, bool continueEditing) if (ModelState.IsValid) { + var utcNow = DateTime.UtcNow; + + if (returnRequest.RequestedAction != model.RequestedAction) + returnRequest.RequestedActionUpdatedOnUtc = utcNow; + returnRequest.Quantity = model.Quantity; returnRequest.ReasonForReturn = model.ReasonForReturn; returnRequest.RequestedAction = model.RequestedAction; returnRequest.CustomerComments = model.CustomerComments; returnRequest.StaffNotes = model.StaffNotes; + returnRequest.AdminComment = model.AdminComment; returnRequest.ReturnRequestStatusId = model.ReturnRequestStatusId; - returnRequest.UpdatedOnUtc = DateTime.UtcNow; + returnRequest.UpdatedOnUtc = utcNow; if (returnRequest.ReasonForReturn == null) returnRequest.ReasonForReturn = ""; @@ -261,7 +273,6 @@ public ActionResult Edit(ReturnRequestModel model, bool continueEditing) return continueEditing ? RedirectToAction("Edit", returnRequest.Id) : RedirectToAction("List"); } - //If we got this far, something failed, redisplay form PrepareReturnRequestModel(model, returnRequest, true); return View(model); diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryListModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryListModel.cs index 5778691c57..3c7e910efb 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryListModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryListModel.cs @@ -11,10 +11,11 @@ public class CategoryListModel : ModelBase [AllowHtml] public string SearchCategoryName { get; set; } - /// codehint: sm-add [SmartResourceDisplayName("Admin.Catalog.Categories.List.SearchAlias")] public string SearchAlias { get; set; } public GridModel Categories { get; set; } + + public int GridPageSize { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryModel.cs index 48c683a880..4cf603ec78 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryModel.cs @@ -11,7 +11,6 @@ using SmartStore.Web.Framework.Localization; using SmartStore.Web.Framework.Mvc; using Telerik.Web.Mvc; -using Telerik.Web.Mvc.UI; namespace SmartStore.Admin.Models.Catalog { @@ -33,10 +32,17 @@ public CategoryModel() [AllowHtml] public string Name { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Categories.Fields.FullName")] + public string FullName { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Categories.Fields.Description")] [AllowHtml] public string Description { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Categories.Fields.BottomDescription")] + [AllowHtml] + public string BottomDescription { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Categories.Fields.Alias")] public string Alias { get; set; } @@ -62,7 +68,6 @@ public CategoryModel() public string SeName { get; set; } [SmartResourceDisplayName("Admin.Catalog.Categories.Fields.Parent")] - // codehint: sm-edit public int? ParentCategoryId { get; set; } [UIHint("Picture")] @@ -199,9 +204,16 @@ public class CategoryLocalizedModel : ILocalizedModelLocal [AllowHtml] public string Name { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Categories.Fields.FullName")] + public string FullName { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Categories.Fields.Description")] [AllowHtml] - public string Description {get;set;} + public string Description { get;set; } + + [SmartResourceDisplayName("Admin.Catalog.Categories.Fields.BottomDescription")] + [AllowHtml] + public string BottomDescription { get; set; } [SmartResourceDisplayName("Admin.Catalog.Categories.Fields.MetaKeywords")] [AllowHtml] diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductListModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductListModel.cs index 0e50f935d1..bfb62f2d0d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductListModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductListModel.cs @@ -15,6 +15,7 @@ public ProductListModel() AvailableStores = new List(); AvailableProductTypes = new List(); } + public GridModel Products { get; set; } [SmartResourceDisplayName("Admin.Catalog.Products.List.SearchProductName")] @@ -24,9 +25,15 @@ public ProductListModel() [SmartResourceDisplayName("Admin.Catalog.Products.List.SearchCategory")] public int SearchCategoryId { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Products.List.SearchWithoutCategories")] + public bool SearchWithoutCategories { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Products.List.SearchManufacturer")] public int SearchManufacturerId { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Products.List.SearchWithoutManufacturers")] + public bool SearchWithoutManufacturers { get; set; } + [SmartResourceDisplayName("Admin.Common.Store.SearchFor")] public int SearchStoreId { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Orders/CheckoutAttributeModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Orders/CheckoutAttributeModel.cs index 45c1b635b8..5c371f8f85 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Orders/CheckoutAttributeModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Orders/CheckoutAttributeModel.cs @@ -17,6 +17,9 @@ public CheckoutAttributeModel() AvailableTaxCategories = new List(); } + [SmartResourceDisplayName("Common.IsActive")] + public bool IsActive { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Attributes.CheckoutAttributes.Fields.Name")] [AllowHtml] public string Name { get; set; } @@ -47,9 +50,7 @@ public CheckoutAttributeModel() [SmartResourceDisplayName("Admin.Catalog.Attributes.CheckoutAttributes.Fields.DisplayOrder")] public int DisplayOrder { get; set; } - public IList Locales { get; set; } - } public class CheckoutAttributeLocalizedModel : ILocalizedModelLocal @@ -63,6 +64,5 @@ public class CheckoutAttributeLocalizedModel : ILocalizedModelLocal [SmartResourceDisplayName("Admin.Catalog.Attributes.CheckoutAttributes.Fields.TextPrompt")] [AllowHtml] public string TextPrompt { get; set; } - } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Orders/ReturnRequestModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Orders/ReturnRequestModel.cs index 418088b13e..61f6abda9c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Orders/ReturnRequestModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Orders/ReturnRequestModel.cs @@ -55,6 +55,9 @@ public ReturnRequestModel() public string RequestedAction { get; set; } public IList AvailableRequestedAction { get; set; } + [SmartResourceDisplayName("Admin.ReturnRequests.Fields.RequestedActionUpdatedOnUtc")] + public DateTime? RequestedActionUpdated { get; set; } + [AllowHtml] [SmartResourceDisplayName("Admin.ReturnRequests.Fields.CustomerComments")] public string CustomerComments { get; set; } @@ -63,6 +66,9 @@ public ReturnRequestModel() [SmartResourceDisplayName("Admin.ReturnRequests.Fields.StaffNotes")] public string StaffNotes { get; set; } + [SmartResourceDisplayName("Admin.Common.AdminComment")] + public string AdminComment { get; set; } + [SmartResourceDisplayName("Admin.ReturnRequests.Fields.Status")] public int ReturnRequestStatusId { get; set; } [SmartResourceDisplayName("Admin.ReturnRequests.Fields.Status")] @@ -71,6 +77,9 @@ public ReturnRequestModel() [SmartResourceDisplayName("Admin.ReturnRequests.Fields.CreatedOn")] public DateTime CreatedOn { get; set; } + [SmartResourceDisplayName("Common.UpdatedOn")] + public DateTime UpdatedOn { get; set; } + public bool CanAccept { get diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Category/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Category/List.cshtml index cf51334e8e..f724f75928 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Category/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Category/List.cshtml @@ -1,9 +1,6 @@ @model CategoryListModel @using Telerik.Web.Mvc.UI -@{ - var gridPageSize = EngineContext.Current.Resolve().GridPageSize; - - //page title +@{ ViewBag.Title = T("Admin.Catalog.Categories.Manage").Text; } - +
+ + + + + + + + + + + + + + + +
@Html.SmartLabelFor(model => model.SearchCategoryName) @@ -53,10 +50,11 @@ .OnDataBinding("onDataBinding")) .Columns(columns => { - columns.Bound(x => x.Breadcrumb).Title(T("Admin.Catalog.Categories.Fields.Name").Text) - - .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })) - .ClientTemplate("\"><#= Name #>"); + columns.Bound(x => x.Breadcrumb) + .Title(T("Admin.Catalog.Products.Categories.Fields.Category").Text) + .Template(x => Html.ActionLink(x.Breadcrumb, "Edit", new { id = x.Id })) + .ClientTemplate("\"><#= Breadcrumb #>"); + columns.Bound(x => x.FullName); columns.Bound(x => x.Alias); columns.Bound(x => x.Published) .Width(100) @@ -66,14 +64,8 @@ columns.Bound(x => x.DisplayOrder) .Width(100) .Centered(); - columns.Bound(x => x.Id) - .Width(50) - .Centered() - .Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id })) - .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") - .Title(T("Admin.Common.Edit").Text); }) - .Pageable(settings => settings.Total(Model.Categories.Total).PageSize(gridPageSize).Position(GridPagerPosition.Both)) + .Pageable(settings => settings.Total(Model.Categories.Total).PageSize(Model.GridPageSize).Position(GridPagerPosition.Both)) .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "Category")) .PreserveGridState() .EnableCustomBinding(true)) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml index c82000e585..dc94281687 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml @@ -27,6 +27,15 @@ @Html.ValidationMessageFor(model => model.Locales[item].Name)
+ @Html.SmartLabelFor(model => model.Locales[item].FullName) + + @Html.EditorFor(model => Model.Locales[item].FullName) + @Html.ValidationMessageFor(model => model.Locales[item].FullName) +
@Html.SmartLabelFor(model => model.Locales[item].Description) @@ -36,6 +45,15 @@ @Html.ValidationMessageFor(model => model.Locales[item].Description)
+ @Html.SmartLabelFor(model => model.Locales[item].BottomDescription) + + @Html.EditorFor(model => model.Locales[item].BottomDescription, Html.RichEditorFlavor()) + @Html.ValidationMessageFor(model => model.Locales[item].BottomDescription) +
@Html.HiddenFor(model => model.Locales[item].LanguageId) @@ -53,6 +71,15 @@ @Html.ValidationMessageFor(model => model.Name)
+ @Html.SmartLabelFor(model => model.FullName) + + @Html.EditorFor(model => model.FullName) + @Html.ValidationMessageFor(model => model.FullName) +
@Html.SmartLabelFor(model => model.Description) @@ -62,6 +89,15 @@ @Html.ValidationMessageFor(model => model.Description)
+ @Html.SmartLabelFor(model => model.BottomDescription) + + @Html.EditorFor(x => x.BottomDescription, Html.RichEditorFlavor()) + @Html.ValidationMessageFor(model => model.BottomDescription) +
)) @@ -106,15 +142,15 @@ @Html.SmartLabelFor(model => model.ParentCategoryId) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/List.cshtml index aa8dfae18f..d80b3f8bfb 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/List.cshtml @@ -1,8 +1,6 @@ -@model Telerik.Web.Mvc.GridModel -@using Telerik.Web.Mvc.UI +@using Telerik.Web.Mvc.UI @{ - //page title ViewBag.Title = T("Admin.Catalog.Attributes.CheckoutAttributes").Text; }
@@ -13,36 +11,49 @@  @T("Admin.Common.AddNew")
+
- @* codehint: sm-edit *@ - @(Html.HiddenFor(x => x.ParentCategoryId, new { - style = "min-width: 700px", - placeholder = "[" + T("Common.Unspecified") + "]", - data_select = true, - data_select_lazy = true, - data_select_init_text = Model.ParentCategoryBreadcrumb, - data_select_url = Url.Action("Allcategories", "Category") - })) + @(Html.HiddenFor(x => x.ParentCategoryId, new + { + style = "min-width: 700px", + placeholder = "[" + T("Common.Unspecified") + "]", + data_select = true, + data_select_lazy = true, + data_select_init_text = Model.ParentCategoryBreadcrumb, + data_select_url = Url.Action("Allcategories", "Category") + })) @Html.ValidationMessageFor(model => model.ParentCategoryId)
- @(Html.Telerik().Grid(Model.Data) - .Name("checkoutattributes-grid") - .Columns(columns => - { - columns.Bound(x => x.Name) - .Width(300) - .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })) - .ClientTemplate("<#= Name #>"); - columns.Bound(x => x.AttributeControlTypeName) - .Width(150); - columns.Bound(x => x.IsRequired) - .Width(100) - .Template(item => @Html.SymbolForBool(item.IsRequired)) - .ClientTemplate(@Html.SymbolForBool("IsRequired")) - .Centered(); - columns.Bound(x => x.DisplayOrder) - .Width(100) - .Centered(); - columns.Bound(x => x.Id) - .Width(50) - .Centered() - .Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id })) - .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") - .Title(T("Admin.Common.Edit").Text); - }) - .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "CheckoutAttribute")) - .EnableCustomBinding(true)) + @(Html.Telerik().Grid() + .Name("checkoutattributes-grid") + .Columns(columns => + { + columns.Bound(x => x.Name) + .Width(300) + .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })) + .ClientTemplate("<#= Name #>"); + columns.Bound(x => x.AttributeControlTypeName) + .Width(150); + columns.Bound(x => x.IsActive) + .Width(100) + .Template(item => @Html.SymbolForBool(item.IsActive)) + .ClientTemplate(@Html.SymbolForBool("IsActive")) + .Centered(); + columns.Bound(x => x.IsRequired) + .Width(100) + .Template(item => @Html.SymbolForBool(item.IsRequired)) + .ClientTemplate(@Html.SymbolForBool("IsRequired")) + .Centered(); + columns.Bound(x => x.DisplayOrder) + .Width(100) + .Centered(); + columns.Bound(x => x.Id) + .Width(50) + .Centered() + .Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id })) + .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") + .Title(T("Admin.Common.Edit").Text); + }) + .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "CheckoutAttribute")) + .ClientEvents(events => events.OnRowDataBound("checkoutAttributesGrid_onRowDataBound")) + .EnableCustomBinding(true))
\ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/_CreateOrUpdate.cshtml index b1b9c7c421..33499f2b73 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/_CreateOrUpdate.cshtml @@ -83,6 +83,15 @@

-&Z&Mi|9iqvvA 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 Date: Fri, 10 Apr 2015 23:42:14 +0200 Subject: [PATCH 0030/1256] Several installation fixes --- .../SmartStore.Core/Async/AsyncRunner.cs | 1 + .../DefaultLifetimeScopeAccessor.cs | 5 +- .../DependencyRegistrar.cs | 5 +- .../Controllers/InstallController.cs | 62 +++++++++---------- 4 files changed, 38 insertions(+), 35 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs b/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs index a0372bfca7..0186e041c1 100644 --- a/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs +++ b/src/Libraries/SmartStore.Core/Async/AsyncRunner.cs @@ -219,6 +219,7 @@ public static Task Run(Func().Flush(); + if (DataSettings.DatabaseIsInstalled()) + scope.Resolve().Flush(); } catch { } + scope.Dispose(); _state.RemoveState(); } diff --git a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs index 9fe14c718e..839a8fd01e 100644 --- a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs +++ b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs @@ -579,7 +579,10 @@ protected override void Load(ContainerBuilder builder) builder.RegisterFilterProvider(); // global exception handling - builder.RegisterType().AsActionFilterFor(); + if (DataSettings.DatabaseIsInstalled()) + { + builder.RegisterType().AsActionFilterFor(); + } } static HttpContextBase HttpContextBaseFactory(IComponentContext ctx) diff --git a/src/Presentation/SmartStore.Web/Controllers/InstallController.cs b/src/Presentation/SmartStore.Web/Controllers/InstallController.cs index fa3a1499a0..10b8491c6c 100644 --- a/src/Presentation/SmartStore.Web/Controllers/InstallController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/InstallController.cs @@ -1,4 +1,5 @@ -using System; +using Autofac; +using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; @@ -235,18 +236,20 @@ public JsonResult Progress() [HttpPost] public async Task Install(InstallModel model) { - var result = await InstallCore(model); - return Json(result); + var t = AsyncRunner.Run( + (c, ct, state) => InstallCore(c, (InstallModel)state), + model, + CancellationToken.None, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return Json(await t); } [NonAction] - protected virtual Task InstallCore(InstallModel model) + protected virtual InstallationResult InstallCore(ILifetimeScope scope, InstallModel model) { - var tcs = new TaskCompletionSource(); - var t = tcs.Task; - var scope = EngineContext.Current.ContainerManager.Scope(); - UpdateResult(x => { x.ProgressMessage = _locService.GetResource("Progress.CheckingRequirements"); @@ -255,12 +258,11 @@ protected virtual Task InstallCore(InstallModel model) if (DataSettings.DatabaseIsInstalled()) { - tcs.SetResult(UpdateResult(x => + return UpdateResult(x => { x.Success = true; x.RedirectUrl = Url.Action("Index", "Home"); - })); - return t; + }); } //set page timeout to 5 minutes @@ -329,7 +331,7 @@ protected virtual Task InstallCore(InstallModel model) //and the configured application pool identity on IIS 7.5) that is used if the application is not impersonating. //If the application is impersonating via , //the identity will be the anonymous user (typically IUSR_MACHINENAME) or the authenticated request user. - var webHelper = EngineContext.Current.ContainerManager.Resolve(scope: scope); + var webHelper = scope.Resolve(); //validate permissions var dirsToCheck = FilePermissionHelper.GetDirectoriesWrite(webHelper); foreach (string dir in dirsToCheck) @@ -351,13 +353,12 @@ protected virtual Task InstallCore(InstallModel model) if (GetInstallResult().HasErrors) { - tcs.SetResult(UpdateResult(x => + return UpdateResult(x => { x.Completed = true; x.Success = false; x.RedirectUrl = null; - })); - return t; + }); } else { @@ -399,14 +400,13 @@ protected virtual Task InstallCore(InstallModel model) var errorCreatingDatabase = CreateDatabase(connectionString, collation); if (errorCreatingDatabase.HasValue()) { - tcs.SetResult(UpdateResult(x => + return UpdateResult(x => { x.Errors.Add(errorCreatingDatabase); x.Completed = true; x.Success = false; x.RedirectUrl = null; - })); - return t; + }); } else { @@ -423,14 +423,13 @@ protected virtual Task InstallCore(InstallModel model) //check whether database exists if (!SqlServerDatabaseExists(connectionString)) { - tcs.SetResult(UpdateResult(x => + return UpdateResult(x => { x.Errors.Add(_locService.GetResource("DatabaseNotExists")); x.Completed = true; x.Success = false; x.RedirectUrl = null; - })); - return t; + }); } } } @@ -460,7 +459,7 @@ protected virtual Task InstallCore(InstallModel model) settings.Save(); // init data provider - var dataProviderInstance = EngineContext.Current.ContainerManager.Resolve(scope: scope); + var dataProviderInstance = scope.Resolve(); // Although obsolete we have no other chance than using this here. // Delegating this to DbConfiguration is not possible during installation. @@ -472,14 +471,13 @@ protected virtual Task InstallCore(InstallModel model) var lazyLanguage = _locService.GetAppLanguage(model.PrimaryLanguage); if (lazyLanguage == null) { - tcs.SetResult(UpdateResult(x => + return UpdateResult(x => { x.Errors.Add(string.Format("The install language '{0}' is not registered", model.PrimaryLanguage)); x.Completed = true; x.Success = false; x.RedirectUrl = null; - })); - return t; + }); } // create the DataContext @@ -517,7 +515,7 @@ protected virtual Task InstallCore(InstallModel model) // install plugins PluginManager.MarkAllPluginsAsUninstalled(); - var pluginFinder = EngineContext.Current.ContainerManager.Resolve(scope: scope); + var pluginFinder = scope.Resolve(); var plugins = pluginFinder.GetPlugins(false) //.ToList() .OrderBy(x => x.PluginDescriptor.Group) @@ -568,17 +566,16 @@ protected virtual Task InstallCore(InstallModel model) foreach (var providerType in permissionProviders) { dynamic provider = Activator.CreateInstance(providerType); - EngineContext.Current.ContainerManager.Resolve(scope: scope).InstallPermissions(provider); + scope.Resolve().InstallPermissions(provider); } // SUCCESS: Redirect to home page - tcs.SetResult(UpdateResult(x => + return UpdateResult(x => { x.Completed = true; x.Success = true; x.RedirectUrl = Url.Action("Index", "Home"); - })); - return t; + }); } catch (Exception exception) { @@ -607,14 +604,13 @@ protected virtual Task InstallCore(InstallModel model) msg += " (" + realException.Message + ")"; } - tcs.SetResult(UpdateResult(x => + return UpdateResult(x => { x.Errors.Add(string.Format(_locService.GetResource("SetupFailed"), msg)); x.Success = false; x.Completed = true; x.RedirectUrl = null; - })); - return t; + }); } finally { From 63af07739f0fd983c4613aa3bee8eed3c563bbf9 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Sat, 11 Apr 2015 00:03:21 +0200 Subject: [PATCH 0031/1256] Minor fixes --- .../Administration/Infrastructure/AutoMapperStartupTask.cs | 4 +++- .../Public/Infrastructure/RoutesTests.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index c783737588..c597ea62cd 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -102,6 +102,7 @@ public void Execute() .ForMember(dest => dest.PhoneRequired, mo => mo.Ignore()) .ForMember(dest => dest.FaxEnabled, mo => mo.Ignore()) .ForMember(dest => dest.FaxRequired, mo => mo.Ignore()) + .ForMember(dest => dest.EmailMatch, mo => mo.Ignore()) .ForMember(dest => dest.CountryName, mo => mo.MapFrom(src => src.Country != null ? src.Country.Name : null)) .ForMember(dest => dest.StateProvinceName, mo => mo.MapFrom(src => src.StateProvince != null ? src.StateProvince.Name : null)); Mapper.CreateMap() @@ -171,7 +172,8 @@ public void Execute() .ForMember(dest => dest.Locales, mo => mo.Ignore()) .ForMember(dest => dest.AvailableStores, mo => mo.Ignore()) .ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore()) - .ForMember(dest => dest.AvailableWidgetZones, mo => mo.Ignore()); + .ForMember(dest => dest.AvailableWidgetZones, mo => mo.Ignore()) + .ForMember(dest => dest.AvailableTitleTags, mo => mo.Ignore()); Mapper.CreateMap(); //category diff --git a/src/Tests/SmartStore.Web.MVC.Tests/Public/Infrastructure/RoutesTests.cs b/src/Tests/SmartStore.Web.MVC.Tests/Public/Infrastructure/RoutesTests.cs index 2e48cb64b0..b275d3afec 100644 --- a/src/Tests/SmartStore.Web.MVC.Tests/Public/Infrastructure/RoutesTests.cs +++ b/src/Tests/SmartStore.Web.MVC.Tests/Public/Infrastructure/RoutesTests.cs @@ -154,7 +154,7 @@ public void Order_routes() [Test] public void ReturnRequest_routes() { - "~/returnrequest/2".ShouldMapTo(c => c.ReturnRequest(2)); + "~/returnrequest/returnrequest/2".ShouldMapTo(c => c.ReturnRequest(2)); } [Test] From 0bde7cda1d09abe828af065be276d546938ec560 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 11 Apr 2015 12:37:53 +0200 Subject: [PATCH 0032/1256] Updated licensing assembly --- .../SmartStore.Licensing.dll | Bin 168960 -> 185856 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/SmartStore.Licensing/SmartStore.Licensing.dll b/lib/SmartStore.Licensing/SmartStore.Licensing.dll index 84192f84b2b52286b8037955a18ef90a716794da..5647e23948b1c037b1ceb739a92fad76475d4d36 100644 GIT binary patch literal 185856 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 O(Yve5cY;w0@ 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 U-9-BQSyRb~`TyhR4~PT*4M{R+-T(jq From 5e81e60b26c8a72d0408af2fb4e542d40413e534 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 11 Apr 2015 16:27:19 +0200 Subject: [PATCH 0033/1256] Resolves #673 Manufacturer list: Prepend history list of previous selected manufacturers --- .../Domain/Catalog/CatalogSettings.cs | 6 +++ .../Customers/SystemCustomerAttributeNames.cs | 1 + .../Controllers/ManufacturerController.cs | 38 ++++++++++++++++++- .../Controllers/ProductController.cs | 15 ++++++++ .../Infrastructure/AutoMapperStartupTask.cs | 3 +- .../_CreateOrUpdate.Manufacturers.cshtml | 12 +++++- 6 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs index 4ca01100fe..1002413e23 100644 --- a/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs @@ -53,6 +53,7 @@ public CatalogSettings() ShowProductReviewsInProductDetail = true; HtmlTextCollapsedHeight = 260; MostRecentlyUsedCategoriesMaxSize = 6; + MostRecentlyUsedManufacturersMaxSize = 4; } ///

)) + + + + @@ -105,9 +118,3 @@
+ @Html.SmartLabelFor(model => model.IsActive) + + @Html.EditorFor(model => model.IsActive) + @Html.ValidationMessageFor(model => model.IsActive) +
@Html.SmartLabelFor(model => model.IsRequired) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml index bcf08d04b1..7e39510f8b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml @@ -93,69 +93,86 @@ - - - - - - - - - - - - - - - - - - - - - - - - + +
- @Html.SmartLabelFor(model => model.SearchProductName) - - @Html.EditorFor(model => Model.SearchProductName) -
- @Html.SmartLabelFor(model => model.SearchCategoryId) - - @Html.DropDownList("SearchCategoryId", Model.AvailableCategories, T("Admin.Common.All").Text) -
- @Html.SmartLabelFor(model => model.SearchManufacturerId) - - @Html.DropDownList("SearchManufacturerId", Model.AvailableManufacturers, T("Admin.Common.All").Text) -
- @Html.SmartLabelFor(model => model.SearchStoreId) - - @Html.DropDownList("SearchStoreId", Model.AvailableStores) -
- @Html.SmartLabelFor(model => model.SearchProductTypeId) - - @Html.DropDownList("SearchProductTypeId", Model.AvailableProductTypes) -
- @Html.SmartLabelFor(model => model.GoDirectlyToSku) - - @Html.EditorFor(model => Model.GoDirectlyToSku) - + +
+ +

+ + @if(Model.RequestedActionUpdated.HasValue) + { + + + + + } + + + + + + + +
@@ -245,6 +262,7 @@ return false; } }); + $("#@Html.FieldIdFor(model => model.GoDirectlyToSku)").keydown(function (event) { if (event.keyCode == 13) { $("#go-to-product-by-sku").click(); @@ -252,6 +270,16 @@ } }); + // show/hide category filter + $('#SearchWithoutCategories').change(function () { + $('#SearchCategoryIdContainer').toggle(!$(this).is(':checked')); + }).trigger('change'); + + // show/hide manufacturer filter + $('#SearchWithoutManufacturers').change(function () { + $('#SearchManufacturerIdContainer').toggle(!$(this).is(':checked')); + }).trigger('change'); + // export selected to pdf, xml, xls... $('a.export-form-post').click(function (e) { e.preventDefault(); @@ -303,7 +331,9 @@ SearchCategoryId: $('#SearchCategoryId').val(), SearchManufacturerId: $('#SearchManufacturerId').val(), SearchStoreId: $('#SearchStoreId').val(), - SearchProductTypeId: $('#SearchProductTypeId').val() + SearchProductTypeId: $('#SearchProductTypeId').val(), + SearchWithoutCategories: $('#SearchWithoutCategories').is(':checked'), + SearchWithoutManufacturers: $('#SearchWithoutManufacturers').is(':checked') }; e.data = searchModel; } @@ -486,6 +516,5 @@ $(".export-catalog a").click(function (e) { displayNotification("@T("Admin.Common.Export.Wait")", 'danger'); }); - }); diff --git a/src/Presentation/SmartStore.Web/Administration/Views/ReturnRequest/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/ReturnRequest/_CreateOrUpdate.cshtml index 2421cf7076..518acee762 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/ReturnRequest/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/ReturnRequest/_CreateOrUpdate.cshtml @@ -90,6 +90,17 @@ @Html.ValidationMessageFor(model => model.RequestedAction)
+ @Html.SmartLabelFor(model => model.RequestedActionUpdated) + + @Html.DisplayFor(model => model.RequestedActionUpdated) +
@Html.SmartLabelFor(model => model.CustomerComments) @@ -108,6 +119,15 @@ @Html.ValidationMessageFor(model => model.StaffNotes)
+ @Html.SmartLabelFor(model => model.AdminComment) + + @Html.TextAreaFor(model => model.AdminComment, new { style = "min-width: 500px; min-height: 100px;" }) + @Html.ValidationMessageFor(model => model.AdminComment) +
@Html.SmartLabelFor(model => model.CreatedOn) @@ -116,4 +136,12 @@ @Html.DisplayFor(model => model.CreatedOn)
+ @Html.SmartLabelFor(model => model.UpdatedOn) + + @Html.DisplayFor(model => model.UpdatedOn) +
diff --git a/src/Presentation/SmartStore.Web/Extensions/MappingExtensions.cs b/src/Presentation/SmartStore.Web/Extensions/MappingExtensions.cs index 7198e82d35..fcd098d40b 100644 --- a/src/Presentation/SmartStore.Web/Extensions/MappingExtensions.cs +++ b/src/Presentation/SmartStore.Web/Extensions/MappingExtensions.cs @@ -21,11 +21,13 @@ public static CategoryModel ToModel(this Category entity) if (entity == null) return null; - var model = new CategoryModel() + var model = new CategoryModel { Id = entity.Id, Name = entity.GetLocalized(x => x.Name), + FullName = entity.GetLocalized(x => x.FullName), Description = entity.GetLocalized(x => x.Description), + BottomDescription = entity.GetLocalized(x => x.BottomDescription), MetaKeywords = entity.GetLocalized(x => x.MetaKeywords), MetaDescription = entity.GetLocalized(x => x.MetaDescription), MetaTitle = entity.GetLocalized(x => x.MetaTitle), diff --git a/src/Presentation/SmartStore.Web/Models/Catalog/CategoryModel.cs b/src/Presentation/SmartStore.Web/Models/Catalog/CategoryModel.cs index e078502a7a..395a5ad46e 100644 --- a/src/Presentation/SmartStore.Web/Models/Catalog/CategoryModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Catalog/CategoryModel.cs @@ -18,7 +18,9 @@ public CategoryModel() } public string Name { get; set; } + public string FullName { get; set; } public string Description { get; set; } + public string BottomDescription { get; set; } public string MetaKeywords { get; set; } public string MetaDescription { get; set; } public string MetaTitle { get; set; } diff --git a/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.Mobile.cshtml b/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.Mobile.cshtml index b197142d0a..01adaed1c6 100644 --- a/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.Mobile.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.Mobile.cshtml @@ -13,7 +13,7 @@ @Html.Action("SearchBox", "Catalog")
-

@Model.Name

+

@(Model.FullName.HasValue() ? Model.FullName : Model.Name)

@Html.Widget("mobile_categorydetails_top") @@ -76,6 +76,13 @@ @(Html.SmartStore().Pager(Model.PagingFilteringContext).WithRenderer().Name("pagination-bottom").QueryParam("pagenumber")) + @if (Model.BottomDescription.HasValue()) + { +
+ @Html.Raw(Html.CollapsedText(Model.BottomDescription)) +
+ } + @Html.Widget("mobile_categorydetails_bottom")
diff --git a/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.cshtml b/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.cshtml index f49561fa37..e1e40c6b0f 100644 --- a/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.cshtml @@ -22,8 +22,10 @@ @using SmartStore.Web.Models.Catalog; @using SmartStore.Web.Framework.UI; -@functions{ - private bool ShowListOptions() { +@functions +{ + private bool ShowListOptions() + { return Model.Products.Count > 0 && (Model.PagingFilteringContext.AllowProductViewModeChanging || Model.PagingFilteringContext.AllowProductSorting || @@ -57,7 +59,7 @@ }
-

@Model.Name

+

@(Model.FullName.HasValue() ? Model.FullName : Model.Name)

@Html.Widget("categorydetails_top") @@ -150,11 +152,19 @@ @Html.SmartStore().Pager(Model.PagingFilteringContext).Name("pagination-bottom").QueryParam("pagenumber")
+ @if (Model.BottomDescription.HasValue()) + { +
+ @Html.Raw(Html.CollapsedText(Model.BottomDescription)) +
+ } + @Html.Widget("categorydetails_bottom") -@section right_top { +@section right_top +{ @Html.Widget("categorydetails_before_filters") @*filtering*@ From cd3427ff06ac4bee18b62df7cb15b912af87310e Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 13 Apr 2015 14:44:33 +0200 Subject: [PATCH 0036/1256] Resolves #672 Option to automatically create mutual associations for cross sell products and related products --- changelog.md | 1 + .../201504111815146_NewCategoryProperties.cs | 12 ++ .../Catalog/IProductService.cs | 14 ++ .../Catalog/ProductService.cs | 128 ++++++++++++++++-- .../Controllers/ProductController.cs | 60 ++++++++ .../Product/_CreateOrUpdate.Promotion.cshtml | 26 +++- 6 files changed, 231 insertions(+), 10 deletions(-) diff --git a/changelog.md b/changelog.md index b8f50f61cf..5ba3b0a719 100644 --- a/changelog.md +++ b/changelog.md @@ -16,6 +16,7 @@ * (Developer) Added `BeginTransaction()` and `UseTransaction()` methods to `IDbContext` * #588 Alternative localized category name used as title for category pages * #592 Add a second category description displayed beyond products on category page +* Resolves #672 Option to automatically create mutual associations for cross sell products and related products ### Improvements * Perf: product list rendering up to 10x (!) faster now (depends on page size and view mode) diff --git a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs b/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs index 43ed260971..67b8536692 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs @@ -84,6 +84,18 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Letzte Aktualisierung der angeforderten Aktion", "Date when the requested action was updated the last time.", "Datum, an dem die angeforderte Aktion zuletzt gendert wurde."); + + builder.AddOrUpdate("Admin.Common.CreateMutuallyAssociations", + "Create all mutual associations", + "Alle gegenseitigen Zuordnungen erstellen"); + + builder.AddOrUpdate("Admin.Common.AskCreateMutuallyAssociations", + "Do you want to create all mutual associations?", + "Mchten Sie alle gegenseitigen Zuordnungen erstellen?"); + + builder.AddOrUpdate("Admin.Common.CreateMutuallyAssociationsResult", + "There were {0} mutual association(s) created.", + "Es wurden {0} gegenseitige Zuordnung(en) erstellt."); } } } diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductService.cs b/src/Libraries/SmartStore.Services/Catalog/IProductService.cs index 732da540ab..116f996a1c 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductService.cs @@ -188,6 +188,13 @@ public partial interface IProductService /// Related product void UpdateRelatedProduct(RelatedProduct relatedProduct); + /// + /// Ensure existence of all mutually related products + /// + /// First product identifier + /// Number of inserted related products + int EnsureMutuallyRelatedProducts(int productId1); + #endregion #region Cross-sell products @@ -233,6 +240,13 @@ public partial interface IProductService /// Cross-sells IList GetCrosssellProductsByShoppingCart(IList cart, int numberOfProducts); + /// + /// Ensure existence of all mutually cross selling products + /// + /// First product identifier + /// Number of inserted cross selling products + int EnsureMutuallyCrossSellProducts(int productId1); + #endregion #region Tier prices diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs index 46c783293f..cd3cdd8636 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs @@ -137,12 +137,91 @@ public ProductService(ICacheManager cacheManager, public DbQuerySettings QuerySettings { get; set; } #endregion - - #region Methods - #region Products + #region Utilities - /// + protected virtual int EnsureMutuallyRelatedProducts(List productIds) + { + int count = 0; + + foreach (int id1 in productIds) + { + var mutualAssociations = ( + from rp in _relatedProductRepository.Table + join p in _productRepository.Table on rp.ProductId2 equals p.Id + where !p.Deleted && rp.ProductId2 == id1 + select rp).ToList(); + + foreach (int id2 in productIds) + { + if (id1 == id2) + continue; + + if (!mutualAssociations.Any(x => x.ProductId1 == id2)) + { + int maxDisplayOrder = _relatedProductRepository.TableUntracked + .Where(x => x.ProductId1 == id2) + .OrderByDescending(x => x.DisplayOrder) + .Select(x => x.DisplayOrder) + .FirstOrDefault(); + + var newRelatedProduct = new RelatedProduct + { + ProductId1 = id2, + ProductId2 = id1, + DisplayOrder = maxDisplayOrder + 1 + }; + + InsertRelatedProduct(newRelatedProduct); + ++count; + } + } + } + + return count; + } + + protected virtual int EnsureMutuallyCrossSellProducts(List productIds) + { + int count = 0; + + foreach (int id1 in productIds) + { + var mutualAssociations = ( + from rp in _crossSellProductRepository.Table + join p in _productRepository.Table on rp.ProductId2 equals p.Id + where !p.Deleted && rp.ProductId2 == id1 + select rp).ToList(); + + foreach (int id2 in productIds) + { + if (id1 == id2) + continue; + + if (!mutualAssociations.Any(x => x.ProductId1 == id2)) + { + var newCrossSellProduct = new CrossSellProduct + { + ProductId1 = id2, + ProductId2 = id1 + }; + + InsertCrossSellProduct(newCrossSellProduct); + ++count; + } + } + } + + return count; + } + + #endregion + + #region Methods + + #region Products + + /// /// Delete a product /// /// Product @@ -1199,13 +1278,11 @@ public virtual IList GetRelatedProductsByProductId1(int productI { var query = from rp in _relatedProductRepository.Table join p in _productRepository.Table on rp.ProductId2 equals p.Id - where rp.ProductId1 == productId1 && - !p.Deleted && - (showHidden || p.Published) + where rp.ProductId1 == productId1 && !p.Deleted && (showHidden || p.Published) orderby rp.DisplayOrder select rp; - var relatedProducts = query.ToList(); + var relatedProducts = query.ToList(); return relatedProducts; } @@ -1253,6 +1330,23 @@ public virtual void UpdateRelatedProduct(RelatedProduct relatedProduct) _eventPublisher.EntityUpdated(relatedProduct); } + /// + /// Ensure existence of all mutually related products + /// + /// First product identifier + /// Number of inserted related products + public virtual int EnsureMutuallyRelatedProducts(int productId1) + { + var relatedProducts = GetRelatedProductsByProductId1(productId1, true); + var productIds = relatedProducts.Select(x => x.ProductId2).ToList(); + + if (productIds.Count > 0 && !productIds.Any(x => x == productId1)) + productIds.Add(productId1); + + int count = EnsureMutuallyRelatedProducts(productIds); + return count; + } + #endregion #region Cross-sell products @@ -1383,6 +1477,24 @@ public virtual IList GetCrosssellProductsByShoppingCart(IList + /// Ensure existence of all mutually cross selling products + /// + /// First product identifier + /// Number of inserted cross selling products + public virtual int EnsureMutuallyCrossSellProducts(int productId1) + { + var crossSellProducts = GetCrossSellProductsByProductId1(productId1, true); + var productIds = crossSellProducts.Select(x => x.ProductId2).ToList(); + + if (productIds.Count > 0 && !productIds.Any(x => x == productId1)) + productIds.Add(productId1); + + int count = EnsureMutuallyCrossSellProducts(productIds); + return count; + } + #endregion #region Tier prices diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index 3afa1197d6..1faaf81100 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -1674,6 +1674,36 @@ public ActionResult RelatedProductAddPopup(string btnId, string formId, ProductM model.Products = new GridModel(); return View(model); } + + [HttpPost] + [ValidateInput(false)] + public ActionResult CreateAllMutuallyRelatedProducts(int productId) + { + string message = null; + + if (_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + { + var product = _productService.GetProductById(productId); + if (product != null) + { + int count = _productService.EnsureMutuallyRelatedProducts(productId); + message = T("Admin.Common.CreateMutuallyAssociationsResult", count); + } + else + { + message = "No product found with the specified id"; + } + } + else + { + message = T("Admin.AccessDenied.Title"); + } + + return new JsonResult + { + Data = new { Message = message } + }; + } #endregion @@ -1859,6 +1889,36 @@ public ActionResult CrossSellProductAddPopup(string btnId, string formId, Produc return View(model); } + [HttpPost] + [ValidateInput(false)] + public ActionResult CreateAllMutuallyCrossSellProducts(int productId) + { + string message = null; + + if (_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + { + var product = _productService.GetProductById(productId); + if (product != null) + { + int count = _productService.EnsureMutuallyCrossSellProducts(productId); + message = T("Admin.Common.CreateMutuallyAssociationsResult", count); + } + else + { + message = "No product found with the specified id"; + } + } + else + { + message = T("Admin.AccessDenied.Title"); + } + + return new JsonResult + { + Data = new { Message = message } + }; + } + #endregion #region Associated products diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Promotion.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Promotion.cshtml index af38a44a21..f47318846b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Promotion.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Promotion.cshtml @@ -52,11 +52,16 @@
- + \ No newline at end of file From 7c09d3c26336a580c9fc86ccae10ed9ce5545708 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 13 Apr 2015 16:21:37 +0200 Subject: [PATCH 0037/1256] Last migration makes trouble --- ...201504111815146_NewCategoryProperties.resx | 126 ------------------ ...1412183_NewCategoryProperties.Designer.cs} | 2 +- ... 201504131412183_NewCategoryProperties.cs} | 22 ++- ...201504131412183_NewCategoryProperties.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- 5 files changed, 141 insertions(+), 145 deletions(-) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.resx rename src/Libraries/SmartStore.Data/Migrations/{201504111815146_NewCategoryProperties.Designer.cs => 201504131412183_NewCategoryProperties.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201504111815146_NewCategoryProperties.cs => 201504131412183_NewCategoryProperties.cs} (82%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.resx diff --git a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.resx b/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.resx deleted file mode 100644 index 2592f8a19e..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - H4sIAAAAAAAEAOy923LcOtIueD8R8w4OX+29o7e97O6O6H/FWrNDkiVb8cu2WiXbf/eNgmJBJbRYZC0edOgd82RzMY80rzAAeMKZOJGsKteNXSKAD0AikUgkEon/7//5f3/7X8/r5NUjyAuYpb+/fvfml9evQBpnS5iufn9dlXf/82+v/9f/9X/+H7+dLtfPr763+f6M86GSafH76/uy3Pz69m0R34N1VLxZwzjPiuyufBNn67fRMnv7/pdf/uPtu3dvAYJ4jbBevfrtqkpLuAbkD/TnSZbGYFNWUfI5W4KkaL6jlAVBffUlWoNiE8Xg99eLdZSXizLLwZsPURm9fnWUwAg1YwGSu9evojTNyqhEjfz1WwEWZZ6lq8UGfYiS65cNQPnuoqQATeN/7bOb9uOX97gfb/uCLVRcFWW2tgR89+eGMG/54k7kfd0RDpHuFJG4fMG9JuT7/fXfq4h8+pbC8vUrvsJfT5IcZ2YofELIjLLB9M0HmIMYfX15QwP96RWX/U8dl7x/g9jpzS9/enVSJWWVg99TUJV5lPzp1WV1m8D4P8HLdfYA0t/TKknopqPGozTmA/p0mWcbkJcvV+Cu6dD58vWrt2y5t3zBrhhVpu7meVr++f3rV19Q5dFtAjrOoEhCevURpCCPSrC8jMoS5CnGAKT/Qu1cXfjftjbEimhKvX71OXq+AOmqvP/99V/RHDqDz2DZfmgagMiKJiAqU+YVkDRQX+kHUMQ53NQ85Fv3QFWw2CTRy0UWR0mAjhpV9jVfgnxoCPVI58UHcBchnmxhjrMsAVE6APTb235GaecZqm5ZxeVxlS4TcF6C9VGJaHJbleAMJiVuvfXcO0GSLslWb4agD7NRXVdPtOFa9Ugd0YMBfY+SyhvtvLjMAVoGkZQGSzveRmBfoke4IoRW0u31qyuQkCzFPdzUS+4gS97Q5c/ybH2VJQaThCp2s8iqPMYCJrMvex3lK1CGmskhp+5hrqrraojlOyNqYgcCa7UePxS0jMUZ0n5blA8ghusoef0Kzd0YNlr4316/WuA19ffXfzHFuwRoiqRltALWM99Oa/nLLyFW88V9lpdmqgr6GaDCWjJ0gqLwpdInuATX99X6No1g4gv2HQ38beI9ckQ4FPcOwn80XeskB1gAfE2/lXHH8ujLNVzbq7bfNksPMOUCx60exVzLXLtUuSxz7RJpt6g3NZh1+IYro+kkm3V4/ebyy9ZsXWfsumHUAfOm6xptq2j4qxcHpUIjHmsS4ep8dYHLKEd1fsyzaoMaEka/aBaB83QJH+GyipLkZUuWcstap1/bUfumrO9ouYbpSbZeg16PG62ylmvBGi3J/ltONDhPX9NP2RpcBtAVP4MyQlP8KcuXxeg6I65symHG9V3DUmvaCtOzoyTJnk6I6Af5FXiE4MlbQT3abPLsESyvkOxMV4tq7cc3X7IyMGILd43Ee8J12ruN4UAX1e2/AJp/2VHsredfwDUscePISuY9xIuHavxJF6XVXRRjhSFHq175BW15+k3BaNV+RCw2eiXnxUd4V55EufeGqcUJoVtcgT8qmIOv5T2ieC38vTmlwexVFZ20fvdLGKFWYU22hDHWZI6WS64N3n06Lz5kT2mSRf7b3QbHd+S+pUk9wVtA7z6iUakn3Nc7AdPR/tTAnD5vYE7U6g/RC49pBnEUl/CRQIRg+09RsYiQjgNCjSqLJjRvsDXfCpAfrXIAaDXPtTEM2DV4Hl9vPC+uQFzlNbqv9GiATl7iBNSN8pVxNOIlyGHmPfs6TLL2E2DPuXJeLO7h5jTFRbzZ8bw4Q8OPATcBhgTJU4hnXpS0iCf32ABhbla2bv519Hz6jHYh3nPhvDgtvMmJWnOCtkOrLH/xZRyk4qCt0Hn6iKYmgkNq/70/NyINL34IdmSArbEE8egxgqgsTChUTyuvtKXOCxZMA/b8Inuqe41XGoTmOyhogwDvXsj2/SzL2zYeA7T78jxoiuKHDFvLsf+S96kw3g1ixPOalmgH0m16vTUKYtNHowTX1TrMINWI0XM4REIAsGzAIJhAWUVzATfwuHo5rsqyNy54zC2c+wcs7hNYlGFAm8mfAMS8SK4zxzOumCdIOydwMPY/f6JBgq9AX5PluBU0G5OTrLA4nbVdFjYIJ0osO2KOuSjRHr09E5Mek5ljnaZLD6TWnHWa4jO1IPzViC0GGYzMFI1gm7ROtPm4hqCek94CH62hoCi7o8OTbH0L0+YULSAToja3rgjF0WaTQH+N+QeAq/vxpiK7jwkO/wMuR0T/NC5tupXGV550QH7CJJxDQjgfCZAAFz+77XWQEDsIH0H+ggtbWk9oB3HLosdRAZrVJ8i2u8P7DKKiykHt/D6uq3JX59E6pKtXB4t/sNBmpCVOC+REa8ACFca83jh1gBz7SYQyfDCgmBqhMRf3WW1PQYIvnBNtsyR2S6TUV6VNvWlyX2e9rbx3VlHnEjyINFltHYZoaaBztLlhMwo+Nky6yr2GzeToDtT76Bh6dLk7OA16bikcoix71Bi8yIZY3aHWLKZxdOKzqDog5HNsOH2IqG07nVHTflk2VR+keR37cQkJjrYLTR5N67kcqobz2Rzb3B2Cq5tcZ9G0mM2gajCXy7G9ZAd6B2OShfbXVbdfXkTTH30BVf8GSjn29zpaaTt3w+QT5SmVrBSndB5Hafo9yiFS6mT7SG3zNeU0A2RQSjVKJkUdh4qHtuq4RW9tu+jcL/ZGqIYH2YwiE9LpSi5kMtmyIX82rGksn1VsLptD2WAum22TaRuOpLldsowzhESBF8QcstE39kDu76U4XAxulNru18ELWV3XgE/u+3F8ctuRCeGp8a3Ae6VAt43U95eCG7Xaqmx35dYnv43JzMHO1VjJHEo23lXFSVZtsvQEcYq3ZUpAkh+/hTl9IyND/CPJLPPl0R4JE8/WD2RoG3+dDWzFxI03XUC3l+/zCcuSNrPt4iQxMYxhkRjug2C8MLZINFAN52PHqoFOyEtI+iHLqO6KNLfXdaB23+1xH6iFOCzF6roGluKRrsdcZOkqUM0DLlLZZsrrEpPewMExf0Zflto5FOruzeG2TJCe1ZfvQnn/NWY2y2MqfHlqAf8N/Opm7v0U11kdvIPHdnbHaXC+sp5jHpsOA/efqyhdaR22gsUPCHiNbQTnhS2+NrRtR+B7GW1AIBWJOPUdgqfP+h2VozQOffLosF8ZPn2UbG6MTbC1mJa2vj+majP1LebTBDVeyOB3kb9tgbXi/hksYfSmKX/Q2jXiqybRMUyjvPdXb/4ymUhDToZrgDG1S9go1+ZBdgYTkOq3Bn8OdPPxC3iylttBj0fFqSrPMXg8ys1rt2nLYPqH4ThM46lCfKnU9+l0EKcly3k2KM6qVJPGcgaHdWwYamuIyDkS41uQIywK7zCLtfOGkCvA/OPJflUlYPFSlGA9YC0LY79YbMDoR0PHMEmwayGuxN9y0d38DAN3BQpE25hsNLtYJGjeWlpGephOwuvMAWEGj6o0esHMU1/inLLidjSGrS2ha27sApbjdPqMBFUdQX2yvWjvZDDeMY1yF6o91HFbexhXV4+A6jTQYbVR1zWwEIwTUP0kS7L8E3gmMZonr30nYqzb7rMCnG9ySIdZo64r0E4r1IHLeXEGIjwQrYIwo/1YuVL1HGrgaN9nVnvadz8UmyIx4whbOJerAUPtDbKLuxR99f1lA412kA+jywea3D+FjGC51fBSC1tIf7OF+UMxD9UFRpAfPtdzTNofRJYEEiIH6bHNTlSTerZQnHBwBdouV6CD884OOu8c/Fl2z5/F6ZSLXdzFMy5ZuqAoSDOF2G3U91X99xk1TjAd4RUO79DUT7xbGhFzkqUlPt2aQpcfkt6hTNiYcJNEQ61jlvsR5RNINndV8g9QkAijQcC+ZC5YPjq87WVvhd6uuBJu2dAapaFFCooCzdWh+AZCmRtuPit6pCyhv8+uLuZ1dtDOahfx0+oc3a/D/kRdV0ujjxXsaq1/O4RwHnDOChSM8nRNvSk2XjWXUVHgDcjowret6CzL15G/x0+DtoiS8deNSZ96CRhj+ejuDiYwwEaVhN713s0E0qzPi9oh5Chm3lB09tGfzrvkIirK883Rcon2O+P7BgTdN+CmX2QrmDreTMbl2wDOSgj3G7k1SRUqQyv8b6hslG+4kCp6h4tZbFWdxumnG3tdM/m8krayWdQN5vLZtprfdeia3eS56XUasd18HkHpUma0vSlA+y4NkJvLKqE2k0NNbDabLa1Pn7FKEyVHVXmPlZo6wtAViGvroKQHuhLSYTAqIIyJWSnbAUJqQLW+zArFXZQuWdoRMVVotSSLUxOvsw2MNW0k6epGssnyVnJ5bJtJTEzyFpIkaePYFKFdXLJtk64A2mWk2McKqAaYySJtojyH0FRFNvsmP0X58jKDaVl8gkWpOvaX5FO0Xp1P0gdNZtuetD6IRmuNkFki/rg8agHIZ7QO70RF3VSHbORzScmvzCTQXp3Ta2vfEdR+Z482Gln6pgE47OrVdZ3BvCgn09wnqWho1x9oa5CtN1H6MkE9cqf0gR0Z4g4cJfURprHtqd4J9e7IiPYAMjXfTVXR+9Er+ifcYF0pSgYiPQUyBd1nKRh8QzLQs8Dt43lbvt9W72TqOSRdCtuFtsvTL4BckrBo8+nWazU9SbWN43KKTWQyKBvK5vKLrNSSy8Nbv8E4LM/qugYWTNPwPC4eGUVj+PC2oBKwUGHrr5+yC4CJeF5kA4L2fYjQT/c5AKYV/jlAhUjQghzGXGWeLy5/j7xNvOF8Q0ZwIBUvj3XX1qSbHzrPTV+4lkdcpI7h3JLt0GAR6w0pLbkV3WKEu2Q5k2YQGy/N5bWPY+nhsGS0ANzQHRYOjRzZe2/ScN5h56sU0bp+99Xeic5AKlGCZQp5xKt/FiLMbX6z2qmHRsggHaa3uq5AV9VnUi9vb3PwCKMBMREm9uRWKy66janjei5Mfu2q7+Vy1R1pBvC8arAOc14z5xtSed8JM3CfCOMLf46DQCLW26vX/QbPy8Mf8atOi5S+AE7T+jjJVp2HlvWUxqWLNxTGdvhxN42ZxDcadx6bgK0nqNrlpUGUshRF65s+Y89OsnSBlaSZvNmobooHD2GAw1qgrusiSldVtPL2Sgx1P8E2flO2DHHE5HTRrGZ278tS7crW4J1IXhG1VcazMjxo/drZyIJvnpdaDlc/t/ES4UhHeNQ6JbeiOK2GvPFTu2SaNrWVzcpmEtQ+F9tGJlG6XLM5vNbqvhHWazUJpAT/TTK/aXEOS7a6rnlsLe3INFTXbvnGqB+V/qMCCzDFYd1ZEq3O16izOPzzALmDhPm6Kvf3SYIRrF117LV6MK5AQUSbXJjLckolpjajIN71ub3OuGTQ3lJVgnmQsMOyLkAAV0LrAREy0guTbe1DYRJH2iSdF3h2XSbVCqaCEBm8dpdVsUz4BFGdAgkFXqUyEyFOQuFScf85VKgECnI7rG1M63yn4Y+oaDoY7kz2kr3hPuXleO39/+E79U4M+AU8Fe4mXVz6DQWxHTzWWnQniawxpfkYUxrfnghnPm4RpYxODexNn7Fna1m6wMTSTN4sWzfFnV9x+YOipK5rx63Hi/ssDzEdLas9I6Jr6lqD7ejmMdL+jDb3rbKoHozmQXrmtmXplkTZNkVIlK6ubA7bKybU+iy3tDhpAbxdRasquO2csiT5npVkSxaT0DrW2gCGKN7wQNuhw+JWHaXFk4Mzj3pr02HK9zUcIW7o/NRmRp1N3MFo8vrtm6mmeYx7DXFQBPV8OLIP6UhqUX0h8esd4r9+hd2iJ+syLCIU07CZInUedupRSdLpRqdbhwrkpqsiOKC/nBDCABrIFGc54SUhDrJBXVeoTeI88qEOSdZouuPfxg62SQv6HDvZfH0kAWSuMywpZzwV3IrdqO/OzG0XQKS1bAfAJEjlvbvm38tYtZw3XIhk8ly2UHldJsDQQW4SYKCDXFfXNXSq+de/jmI8ywEIdgc8VHBPBNRINIzDDcGAaA0SzrONw1kzv+fSYRKE03R0jaUMyNewKAai7PG51PEC9TlFSaTP7qdcctgu95ZBXOUIVSDAQT45y6dR9cV5ZGP/7N3oNXsE+ww2iQU9x2zOO01iXeBNL21DB3yY3RpeD3SJcZogb+0o1727gxOEwGqrbBSTCWv+inmZcN80VR3FMSiKaSq8xBeg0aZ1zEjlbhdDR4pAzAtZu7jFTrK2CxfsIFhJ2aIPWXwQoeq6SKxj70eIA8nhQJ5Rtvumy+Er7GHCR+z8xXPrKOC85NAECjdtYB+ie6CJdEZZI6lY3+pmUpn85VnTGC+BRjAOEk1dF6HS1kg0PFoYwBeoCb+n80UxvIVkfzbavArg0/zvEDx5QuCQz04BERQ4oYa4xavlrt0Rwn4sCHZPLkhlreJZBqs1YaiBTSZp68hPXdPqDP5LgKf0Pwh+dV2EQB/zrNqMfMo80l2tKZ0bv/QPqXgRKsjigCVokH3IPi4RP9e7xf0cVkvzGzoTJ82pNLk0pzP4S/OmEV4inWAc5LpGyOy9NP4J57jmBS/T+S19u0smAJzmdzMY1lO7fv2r/u8wq9V1EQJN9BIIqcv7qWHS4W0xLLAPSXpbF9iHwizf+CHkxaFhq2ANCYN2Gb3gayRBweq41xM+UtvdBanyHKTxyyQvArWVXUW9n+cHEMN1lLx+dZmjX0SKvX73t9evFjjkwe+v/+Y8F1jPKd9x+h6VU4qVRXVbIpGYnKdxco1hjYj1F+tuMZWdPk9T2TWuDI0Nedh5qh4ylU7T00bqTNPDprJJe4YqspjK9pUxwhGtIhCrCFFyBsDYNFXXPDaB1TWPTe0Gf/xYnISHRmfSdq6PWwsRK6NVgRTvKl2C5dF61J7QD9P+ADlAbBcgHvo9iB+yqjwqER/dViWYcu8rVF7813qCBzcb1SPUvaSjuzuYQDQng+0PNqPTgFzowZsa/NhuDpD8OkG8xepOziyFkGg3+PEGEjd5EjVcoM14kQei4gEsVUMyag9PHh/Hf9wUV3T6vIE5MSR8ztLyfuI6/wGi8elJz6/6VaIP4BZ63zOhoI5ism5+ypLlBPwhVjwRY1IVH0fpwyQbYK7OSUQMXef5yZTVdQ8CTVfl+W00gXLRrKZEAexi14097yu0IcibuKvXeZQWUYx/9qrB5FVPMmVUlV+BokrGJ/tJtMGG9GkJLlY6UW8X1W2no0/b5csqj++jAkxpwL+MoOstbf690LHHpakO78+RwNlU9WnJ5FbjDyAB5V49laXZCV8BfPRGXQaWH1uo34NgDlOkJ5OE22/4jP3ppCxd8ECQZrL1ddP649U1yFzx2BRF05wd8FoTzrcCbaY/waLMFA8RyjLeNGetfWPVuYRTX01W27c2PsI7st8a7IQs4823Aix/wPJe6MxwbqFTBkVsO0dK4VhqGv4modaE9nNJQmP5dKeWfalDL6lahpMVLeuT5C2j0m1bdgWWAKzBkpY1p8o3Nulcg0wxmFnozHAJ63fAUdvVwfzaVJHsbIr0xXIq2aVVGyNpLOTkpR2XQSH0+FxebmFyQejwinENU0gF5sGvRF1Xd1rpaYitpZqvNXec96v6AxPTFbYvMbDIth+FuaLPbasvNDJlDAXBqOGs5HKa6XJtwdVfTIZ2mObqulp6+c5QZgUNAca8tBL8/G8kgdJS01zb7UsMKLrtR2Fe6nPbChRO0ZpCaTfqkFyn8xI4/kLmIFjUdbXmLUoqyJ7RMJNOIfzZRvYoOC/axpIoZFEAo1ELeJJVm4lsz1eIGBuIRngS41pX2zSBYxYgxfvYKXpWVzVNtz6jzRYVl3S0es6LnjsyEv5mZrPoSAYo+yXZyOwkLOCmvZFLUm1/blRlxB4psipXZVV+ryWZaqHXRZHDG0Mmm3FEJO9LHEH0/Mv6UTVfmL9XUdN7r01HCsvLHMaje9p2FY3uWDtFbybpydiOwK1to9YRxyYZW9vYtJvFG3VaL9QP2VOaZNEywDNR50ULFkyNv0ATJC1Ai2u5BcLS+geAq3uLrcvAlbcqXSYAqVnR+P4GtYA/IfHnQvG3UlE6Koosxs7Dy1ZZkZ96BNSSVJrfkFblb9+1OGiUHtdIDiKNFdJ6VAea1eWSNaxJ1DStzeGvV34hbyx46ZUY4qBXqusKog1+od7CmC5qYXtjMuudPbZyTzsgCcwO9qXTTXLw7zTZJAfrXtGcJXiHOajhu0A34muCh8A4jpIojYHntqwY/TLYVAa0kSSD1pFN5u0ic2vT5RPEhjZz+BOnwA5BJr0JeNzUuvG4PFXReNR0PkQH+aeuK4gOcp1H8QOi+ET+2OQubdjdHeEZ4Orl/QEk8BHkL47FJ9d9jJ3r+Emv8L2zdflTO4LSOW56GSA2kMmgdAJkc3lFZKIhQwilg9F9eEYSOgXxpJMdok9jLx+cDCHngWq+ymeL434FsWN6Bf7AbzG6GwgYmMM80MyDEHG/gk2CUNulMIdPVyAqsvQsy2tumt4M0vAvIGbvIAcEjuPR3C4dPybLoozu7r5kU4R/YUREmChqW3ShzHVjStFEsSWV5ZBs36TZPPdsGdFxTpAs93NL4JEOC4RuRgZYIC6jvFETLA/a6mMxh4L0EIdwVAxmyAvjXTFPQCE0JUGOeAh7F4xm+Auzdu+CKO6ZW6Gks1Lqhs5Pq+rKbBKFXZ036FVdoSLZWqLMNNxuZ8Om7phUqEVyWqrKM9zkIGenDchig+baXfM0XScLXA52ojJKstUbLe5heRxdnssJ/3XDhr1wXCtwqKYzmKCOBXhSHPH109e06fYldULjHvLJOT680yzXsrpsyhsVEN/qNSplbeLU8IlDb/VwpiTQoVjSRQvlt3vQdtVZcOpgD3LTVuCN/LbRuN4qY0gwOZkUz47PPdX5Y5IAUsNPLsq1PG29ChxKAbQvLuqGDhgjCL/gYu8g8H4G0aTjXsWx6/RTTjiy9Zi2Pju162jlvy1DIIep5Ty1/hLoDa2htVq7Kt/0Q1lIlls6WbWOMnlC8Ob3KIdR2gcnP8nWtzCNPDXiYfADL6vrWjxUAVh54Ap7CXVniWEq+Ryl1V0U40HML9FoDzpvhanW0jY9cEmINCQU2g+4DAf2Kezto6gAhHK2Tr2GsPgHC210iHNUFHCVolkECR+dL3Wnwu9+CcJArbMdtu1bnjm1Jxf4LqnthbKC3GzzNqbt5PESEpnxQ5hjH2Lr/FqVX+8IaH3ea01UdWwyijl0q71m8bthMQRNwLSoyrBmXD7kyYlB3WrDqkEpl866mljpWezaWRbDqsd0UZduM+VDnDXxlYVXDQ/64OgCvYEJZmi9Bs8l+rTejB8MHke4+aOCuf+db2q+pGWeJSH8QmY6veKnkIV4tZWpzoKU5zmX/kjtQaZlbHuoN7YadJUHJuEStWYBaYkbpeQdpIG2vMqwYAcSwvIQcDE5rCIGq8hRAqOBvVMAST2TiXu0CCq+mlITLTW0ukRgD9yurktBN38/mh2aRAPekVmS5Ys/qigHxdXqdvRO1bal5b/QTKBfqQruO1rf2pygovMCIaGFHMQBYhF56JAcEhENIdTaC5g+YEffOUPB2Wpb26NnGeqdZsqa04rUxrVyWH0+gyWM3rQAh3VGM28bGnnHbfzWByL7life4kSEGj3I2zFMo/6JxfYvk+qGFqq0RIOBYUfvyxlMQDrF6nv6jPpUhNdXZcvUF/Bkx0/GIuYagrw5bXPWcDuMg5hR1xVoFQ5ykau9d4HXNcfTMV9DZtC7R4O3W3BHpYpFx7o3bNZedZDnEJQDRbaQxzN9FRIzoZCoaaHOFGjujIgZ0SXGBf5S1P8d5IW6roncoXgdRqttjFTpokhOU5zfew+2ADHilTCdGPDcyArtRfpAfgwX2Srr/CZmO+Pg+16uk+Ns+TLF48W15tgeeX8B5VOWPwQeXTuZ9zkiNwI9RV+DcpCA6rpq8vuyfY0yjzR1UNbMFfd7sAbE3HCbuKzDpHzxhoE5cKO6LkKo0ZeVQHxqYF/U1PI+zNo1JvcfR/HDeUq8w+hn5j02sQrEw5QIOsCj7YtDRfaYI5CsgvWk0RaG8grbvsECIbeoqsokG9aBrMb9CLKZpd3cr8Ea6cleTg0yuIMgUdc1j3b2HYIn1NT76Wt23YoZ8zNiRLDK8pcAvMxDHfj4wMeT8XEj3AOwMYd04OIDF0/GxWQoYOzlLpmt11n6hkc6sLG6rjDmI9Sjj3lWbaZnS1TzDLNwwDQwkvfnmKaCozi5AnHm9Cg5OU9AcG86kMOMG3vGzWmw1R6MWzsXni+Trg+B3Ta+5T5Mnb3pyh/4eZ/5eZFUq+lrDXUN+iJKV1W0GmthWMT3YFkl4DoqHlwOUFCx4g0NcphL6rrmuVWC1u8sXXq+uBbIbdFabITxiCizzdf0NM8z79cXLyISYT8vHV4vwmVP06VjyUUVx6AoXOulOx/KVcNc/by7gwl0M150ZYv+50HIqOs6Wi5zxCfenjIgAQEuhDguguo3mOveSQ9eOva46XL1Ry1ConC4IubwO04BUYH4r319zZrvP8AcxPixwDcM0oH11XUNrK+mF8BsV5eXogRrRIcnshWZuvorTDpDN+K/bZ9dsGHuD2gday4S+M+UDuwwWQ6TZZ8my0mV5yCNXd697idJC3KYHM6T468jGd7qgTlBELrKR5oYYOx5cZFhAH+ympgvz7J8jQadeiVirPou4BoiFrvOas9mX4WZTLDifpuuYm/RA0R8H4lsQ3tqNLLBLyIYS2XEa9Xa0wOTYBRvBKiDkFbXRdPJ++JyKN9JMoLeMcmyDYx30YtT4F+p/6Y6l7Ap12T1jAgIHxEtPqNtPnn4x3XCsjiH2aqZrSEcpTEPhZqp11koJMSf/wKxLn7gX8bRGHHswumt8jiMYeStn5wXjYnx+OWoKu/9TfMU4BXSWzeQiprjijmSDKXZWBHrhRYrN2x+OqSLMpskcos6r637ez91TFpP51a2vc801HIqp9cSQEzT6NNF5nKPEZVaofn2hkI5SH91XRSZcJVbc9Olfg18ehk6kmDhyCw/Junz3Aj5qQMTdTbx6ESTN+hjrHRFMqEiS9e2NrgoqckYQpzg/AeRoq5rZlPygInw/Ti1OnlEWFyZWW8iuHIxYDSrc/GmxTiwrjPvjOUINLhNGaliHCdj15bYkFZe4/l3iqZSchTH9fMy7nOQxjnMQ3VdhE46If7XUQ5bGtP80ApiWLm+LhyjZ/oeXmY5/z6S7TlBgUYyDIFs2x4VxYBKMVLN9eK+KLzjZuIonOAuQrMaCUEyF1CpkWRWI3Q8rid2YouDOkgudV3zaJ/HcVwvLbWDHNCduZk2wVdnCRRkLJCOMs2lAHp994+PPYVm8wU8FRcAM7nnQWknLOSIB5mhkRlSinmfnM6kRIWZSUE3CWPe4Px7BSqwbGjtPmsomMNUUdd1mcMs947wi+2SWvejURZpXOug/1qIJfM6m75z19kkXbsCm+QlSP+M6pmkTycno1eB9MPR69gvjTDs+oPfF8gh8Lzrh2EUDRpRLVUeCLFGMcmhELWm3bCZ+4MhVR7hcEiZ0euA6OQexA9Z5fVaXP0C8BsB6rCOq+saEKwj3f3eySdFF2hCbXD+yzpKVCjc8+I6ej59BhQ1XKEQUBuJLdiz4Fv+gKow2zUPccrz3khkTy8XTcsID24aF/R6ZFNeS0DheXiBcEhB4SnmO0vmEcmHZ/tml1zTyyxet7MWdk4y6wrHy8J8fRm9YBb4BAt8785daCkAD1JLXRdPMl+hRUZiSy9k8H2VzjMFD92Ihft5ZlpGmGfGBYPOs3AT7DCzNEz8EiegXpo9ZwMGugQ5zJb+NznKKCF4vpYPHNkHT8kQ1phQh32BIrGcpxC7AWyzJKObaCTFbtgSatHFZByUV2xuWwdm5fo/tVjmt2zW8txJLJNb3vDf5MllQhYnb2iCQTK/EQAP4lldV5hwjW5BByU45Mb/fOGDu/rnqnqqUMJKYdSOpFT6CDPrps/eyxt1LkGQarJ6qnoJmQ3tCyrOEfBZoIMgUdd12T5J9M5PBHQ47+cxrpqbGvOsKNC0SPy5jIc68Nm28pmFVuNzSfRwOXRgrVxdgEeQeN/Dv8/ysgvpMPV9kzOUPVzlA5u5TRficmQHXOVN2yEn+tXAE8RhCIGYHOQ5yKeoa8I4SEMeXuCPqo4D57WLr98V/hQV+gdnXEjndr1Xda1Xe5033DXeBWgihjk8TZPewVWV1zvWBucg8tV1zXN/YQ9fdqF8Ipzi9z+/oRAOHOvMsbv6LhcJNebCObhcUf93YBvN3CdRCgaYJ5BSmMZJtQTn6QKiKqPO3ubuudVehUQJZRBHA4O7lWFocQ1LbajRMLVM4iL8GZRRE+VCp+6Hq+wDoC5oTVDfNGMVOE7rFUiRSD4qfsBlfcjihVaj/DNLx6dDXdWPPNo0+r/QdpPyaKv9xIybX8+PM7zABZAvQe7tkI5dR7rQwS5joVqTj4oiiyFZbVhj1iUkz2ffNP9zy+NpunzVBkiTZe83SnUn6shsdE7UI7Qqww1ah1Gzfn/9PwTCDNbRnTFSdcjB373mF/OvaX20/Qqfk2OHuJOoiKOlODyIbkv2C9n21/faERcXSKOAaSkqCzCN4SZKjLrAlTZUNnDrunr4lA9gg6VEWhqNk0kDmiLydnTVcdQbItZvbykOtGPMxlRuyjT8s/ZjMGZTh4wxW8P+tjMm24UZGJMdJyPGbM3vMzFmu4MdlJV8Rhkz9htqczYUcM0l4y9v3rwTkJ0YSdWICVhIRdddkGpok13f8TraoEHBOmLTG3yVTjXgukIypmrz2zCVtg4JgxkyrhdpmpluQ5i2yHhk6WowF/sBaNL+aK5KYd8pA7LIStlQJuh6Zdo+CV0l+YYH0UmsGZFuAhlnRCKTdrTl59bjbhDfwEeQv5BTpwENi8ms0eEclDcWWsZrdDtHWz51rZlOC5PS2YirqHJzc1anDnRL0gALCAU0HOainymrsVhGt2anoOzFdFyqHC+TJtC3eLeCSw03snz+kXl0h/eyqj7MwKA7uJv9HKXVXUQ2RfngjlaWWcaYdD4brpTiz7G71TVkAr7S0XkXdrkNUzPdYHhiQCwpC2qkoCvPDVYp4T9dXVsjFwd7NJ2AHBxPk6bQ5baKsw1XdFmZifh5h1d3XT9mYuAdXOVJxB2Yrj6D8j5b3lwBhAaxl8UJtg1ojY/DRWVMzJay4V+D+mT7KJIY0Bq5KJFSh4btETEKuGnhlY2W5ZbShc5oRRZpDeaUmH9Ca3swwVTWjpHRVrIuMtskbvzwB5mRyydjw86l35wBeVRz1gunlivaMAHzKGi6S2zDip6hYWZnS1gWYrEljKSVkuHZSdqeCZlKSmuT+pmC8x2Itzci+lj9Kg4Qs0oPxbt7GRaH4iKyhLHMmNal78cwSZDW0lYw2Ew2f3AqcPDmpBBnlwM1Gne//oLNUHv5Ajp6dL6E9mQRqpEtYgqyz69ADfViAok1NF5G6yF1zW8WeVXHS6g9LdH2grS8D0eg4iFtKRm/ygrYMK2+Qgnn9hEVto1zjboyAfsajaFJO+ioJbPw8HGSrS6zohzmWyGnjFfbTDb8KQLvFE8qmz8BHyrHZGd4r3nN+KZjHB2X8JlVHNg9kWzHhAK8hA9VDL4dfKjqwUSsqBofk+rbMnNb5K/AIwRPn0CyuauSFOu8TMKQcX6guMZOL5R0MNYP1a622ze92zqutuvYdIZ8w3G2sOnXBWdjf/zS1nkJ1sOKgJBTxtRtJhsmFoF3ShFQNn8CrlSOyU4oArj17drRMY6OS/jMKg50UASk8BI+VDH4dvChqgcTsaJqfEyqb8vMpwhkSTIsBZlc0mUdZbBawhnAnZJ80qZPsRbLxmAnJB5u+VFaPGEvgEyIIsEyBZVPxWd1Fltuo4FlmqGEgbeD1yQNn4jbJGNhpOKh/LPy2vesJKaqOMuXNxTH6NhDUUbFg3R2W05UVaXgSjm7bwdvDnRlIj4dGDtTnq1Lzce5IF/DAgflaXrSmvxxR9VnY/piUv7lSljxr742zckQzjDCCaIZkeTZg58fzkSM02cc8ihKjqryHvNiTBK5AVLSxqi0jFS6gjbkM2vATh06WnVpAilpNcYm7Zn9OPIsy6s1MbsOMriYVcbNXS4b1pVAW/FpEIccdSMm4Cw1cXeHjUiMPEM+YvMqGamJ2mfJSRz4TKwkb8VUvCQn8O4w0w35t35PQzvYVEYlG1lzEA0qYR+qbVu3ZqraPxXjScbDpOq+1DYIsZprDIRM3eUxxFeNrGK+LeU7SdOnFXjMeBjz3RaoXxS/DGtJVIfDq2AUuIr7pHy9JSyo6MOkOpw4PibVkwKzsWL9CJyhJ7Ess4wVm3jO5mwoBTZ3IA6kv+laMQEj6ahrUj1bcmaOGtwPsNkCctFu2jzkbZ+M63Zyx9DGmfqGH6Vpn3vs4oqpuERbShepjC7gEs9NXqEm9Nj2calRVyZgWqMxNGnH7KHKpD2pJZ8VP3FPv47MvezTsUMye0v5lunEXEzLjJtJI7oXjudb3Imbjp5HuXzK5d3W74/H3R0WVLR8qhVeHItdYrahcCdCzhEYbhcDmihbPynb7WDwko/wrjyJsEMEavJ9VIDlD1je9xykYpeBcjK2bIvYcOVQNSqxKOP+cHfbDVs1Ae8ZDoMRJ0oRZmdMRonoWGiIX6SldEzpqjXqK5Swp2oWzC9DjboyIU9rx9CkHW2Z7eLhb/QUs2Nkpuhk3MzWujuKqHln5mJq6XiaNIYpOK/a+iUrgckeqc+nVFlxFmuVlcLdHdZUtHwqZVUci+3fI12BJzR9LjMEULTzZ9D2riskY0NJfhuG1Fa3U1Z6k55MwK0m47cTFnxZR8wUgcGSxmJPuv+xqchtwngFPcIBK8mtOT2R2GyqmJm21x451N1ZXuQNn2C+ysdh+xeXtt31nrlllSG+YHLrmM7WFievQBbLT8HV28OC0i5MyInSMTKpvwOY172gjdhr5rHC5Q7obMAj+wS989KaVS2ZSndW0diUpzZb4LlyBcoqT/GrV8DkZoQ8u1wdoHLaac7SKnZMZ9b1YRJtWTdOO6En9402lHuqAsEv7YUUgFaaSUaqPYnyei07rtJlArRnM5oyci2FzW6nqairUp8fUn0YbbEwaNkkasjgUJi0oi81o4rM9WRw2VCWGJ0Jd3P9GOzGHPy6k6uI0IshtwpVgdE5dRd9LYY6MQeb7qDnBRsbb4hDpbkHIyc6h0vcScbU9mACrtSO0Q6x5GIDYnjX3P4/Kssc3lYlMGVRfWkNy8oLOrDwQAt2kKXNejQdi5uN8S6wvLwnXzf4zxsFRypXd3ssqYKhgbFSNhyaI7MxG03L+aeKR3en0FjcecPIsihF2NKFRMvgbrJdT97Zlhxts4znmnzqzz/j/Ps++4plwjfu86/GmXsWtsvydbTSxIcT82rmjcMMYZDVKhhKDhfxrMH8HuUwSstuWE6y9S1MScYbNGPgI8hfruFaE9fWDkdDOA2EA02NGyS7e0l3fDQrrGNDp5MLtmNq0jK63NyTX9c/ww2dAcRWcPwO7+8surUdU2MHd3oGvfp7hVIQZ3xLodesoHG2YmowDZLMD6bjcy4GsoZuB8fLxtSkZXS5beN91xXAQewHYOh9EvDbI9X3SJS3XRm21JkCzMPgWnOc0MddY/k5rG+2420xCbbG2MZ37nuUVF0PBW61ZE0tmMUsITgBpoq+PeppMzRrt3b2GHV4vplkxB8Ws4qHmHtyWW0NTPV/FyvaVmnyM6vre6GT3yyi9SYBH7KnNMkidWQDefbA3MWBy8yGbTtH5y15WybkLjmljU4DmJKzcdg1BDnqdQyYF0eUHCbPLuOwLqcNjyngLZ8/IXw29xqt78oELKofKpMG0OW2gEGHDBFCzhHYchfNC8rWT8qEu2tCoNzx65+GFjFVOc16rL70YLAyK+vbJWY17Mt0S/zQKJq0hCm4Rexsz8jTsbAL84bULdVNmYX39kF8djv1M5iUOLr78DU1CwwjnuSKe7Gopiku19q2UPYO93COuTDMAuYyedbrcsdR/HCeLsosflhUt0Wcw9qnbPDW3FBB2VRQlLGZAYPV7tRVOtPeTMDipuNps2nbOq4eUjYGyk3M07uoOxv2ZUaG3kEt5ujuDiboC7gZCjMg5JSxbJfJhklF5MmfA1I2YQJuUhLWpO6546iQd7Dslnd1EeVTZ67iT1PVTE+Gzr0WDxN/J1Zh1N9HNGM+I9aPVuDmLM/Wg3ynKSPfXNHZ7bZS6oqmZzuD1kyyzRkkvkkr6HLbwnzXmS3r9SVGZTyqmtnZTmzL9Ewnkt2kDX2p+ZQ0pGA/osG5yFY31G88mGp1TV1Gqrj1WaxUN00tMiWOa/zW7TEM+jOFRjg8dka6IVt0K9h3UFTKMo/EsLtp2NH1YGLe3EnV8e8VqMDydB3B5Ib8exTrH5FUFZBxJZXXhiuVVUg4k2nz1nHnUE8m4NCh8TJpAl1uvkiQ9yB+yCrexVT4rI4MaQggjRQpLWsVN9K0dpn4Ffq4dZxu270JON92vI3kNV94xpC9cZUjUqwuoxcSyvo8hRh36PEATSl5AF+2gF0MX11l5tHzg+zAjBozAVcajYBRO6hyW8OF7TsRAtuY8ogKwIQ3nR5oMaxewq1DU2N+oWzbuxnYf2i8TZrEl51tNlxkcZTAf4Nl28abiyhdVdhupWJAdREZxwu5bXhdU5WEu7uWbx1XD/djAj4eHjeTRrRlZuRYAyPEkPHB0ujgamzYCk//mewMO2JfOCW3qFCZEpUAeXv7ZR3l5dfbf4G4xEngGY13TBoWpWlWEpRfvxXgJMkxGxS/vy7zShSZGHoBSsmVreL1qzpZee9NYEYWbMjtTFbBsLuhbaVGtZjCasAGIT7Aguz1ZRht2iDISVSCVZZDIENpEl+GewPjssqlGE2SKUF0SEwOY/LghzVgDrDKoaMUlW0YmooUJcVkgnSZdVw7EGweg/Go83+O0uouIuTSTQ462yD0EKYVWCv4pMzXLTADII07iZRwnQfOUEMwC6hmAUkbJnr71MhnUN5nSxkSm2MYEAldfEXhES0/0pYxGYyJTaS7fDJwWQYhj5NsdZkVUqw2bRCkVa9kIL1+OwSCNT2wKPEG4woUZO2VAkryDYJ/AU+FSvS3acNzMkuSo7R4UkzFLtUISAVhzARYYdFxQH2Jc6glIF/DokCKAdrcZbmU5/k8g6Cnz2hZTqPkqCrvsXZTB+dUV6DLP1gZcS1ScXCXaAZznW1grMQhqSZAkQrBrBUf86zaKFtBUgeBiLVKhtGY/gxXXurRbLlklWQcFrOSJ7nl6PJX1Q3RdYBm9FMJjC7RDAY/+qyEqZ/eHoARH3uV00v6KKzBmqfSrPpXLg1BVBRj3+Mc7C31mpq8m8xjd4NtY58skbePf1rGTD2TRx/WKGqquNdDfdBEOZb2RxvO2qky82pMiUfCIispReIRmwFpogdqKtAGgXSr2KI20ypMsK1BpUGELBrfHMoOLSJNGA7putFFMxkA6e66y1CouAODingm35KSBLPinyMiI5QoTfpwl+7RHpWQ9FauwTEZhjV4+bUQqUKvutpjsWO8ButNEsn5UZbP1H7xogPm8xiLGA0ml2VYrwApQLymnZB8nuGdb5yo9eIucRDmW66B6RKH2Ty+B8sqAddR8SBlcyp9uGvtBRNp1/obO0O8B6IC8dMPAFf3Um2AyWAK9wEidaRQTBM+j8GWLM9BGiuMD3XisCYmXJJQ7gGsJi/rjiyfCazr9yDPdr54cq6lXCTNoYhFWg9XO+8OipP1JoIrKfHatOEdLOWIJd2xMt5wgyxH6KoVnGwWI3PGBSjRtnmIX+Q5ByugvNnkRn/K4XBoQHhXHunIiJ5XtrBKJUblUza4DZGdoKs2XgoPCcs6TLDNDGnUkam8yZIj7sHGYt5cas492BzDQ5hnRYEKJhpIPo9B76VSyUQaoV+lSsGrk4Z1u+hZewzQpw/TW2mNkhuiqKNC1ZnMTXfyQmWWns10OfmzTCF0B1egO7fueiM5GBJOSAdR2+NrGlUBxxyaopwOVGpZbZhKsuv32v5w9+4DUYm7Vy+ihqBSy7g6LhLyqPvAZ5XRhJ5LGnIIUOOyS2v0vDnabBIIltcZ3U6RKNr86l7pismIRZ0ma2ilRZXQTT0EQSjX86cJ3brcNv1rC4WkWYc57pTrKpYfhWtIJi1g0ENZuQCEk8JKaCfvZygBzz46phbvmsfJZGJY/gaZAUcMg8lIxLouhKJNJ0N7/URJHzHvYLeEIho6GUp9JfLYUoyveFhfELKa92pYY3Ak1zRKA20S1CkO0nzqzsiyy0jE+bpoyCNFnETtZGpmnW+UDKUuM8gAyqIaFjMn42AlEpJq0QPRdXiOSrPbdXR4rvoRcpopy/o43VyBoswR04Ml5WIlUtGglLqzw4VlNBXctTTkNKhBtmz0PfYnK+3qddO5pEkoKc2o6Zosv5RenDeajlxSzJEp1Aai0tCGz6LuAZdTRg/K7VBDCh5oIiJwnoFqUrAZh/vBDq03WVg4CXH0XOdih2j986mGSiwRYi6NAUHILLVG9L6uOmOEiCWhipLIPgQ5hkmCZFznMquhCpfVoDtsiQD04QAnIlLjGNvfxtFQScg73Cu+iI5OvRuvAbkEYJkcUg2AA71kbrb9NTsJ0fQF1B3UlpORT+EorKGhvgoJISmHZm9Ctl7UWuKJmdS9EfLKiET5dWsII0JNQIyTbE1unvbu5XJ6CPn0/eCze888KaiEPkpSu29drsAjBE+fQLK5q5IUS0cmQbOLGSo5uOEYAPCmqmE1GummqsaB3K3rv3ZuipnUvRPyyuhFXUbQEEqEGnlu4gpbfu/vRMjpIeTT94PP7s1FUlAJfZSkdpmbWZJoGYXNoJkCdD6psaC+H6KbRQzEyIzR32y5qW+oyLtOZ9G3nMqp6n53z2aACDSUzCwio6QjCb5nJdEfsCvdDX3bR04OVXZ9fxSl/MWuBltBN8UQuFCPu0F0w91hkhBQX0LTT21BKbeJV6B0dNTja5atpq/hdnuDRFTkNNiaDRLNcqs3OZF0V8q0Wz+zguouG5WXUXTg0pyGymZVjrxd7G7aaakryaXul5hZRjf6/p+GSBKwKShCXLWGScJlG+gGm1tJlNZ/bIgqHNwUZLmhrzIqaELnGegBlVVBjWiYDDSIhAbM1cyQzNHcDNVyRp3HaBzrvoThiRpLTgyBol5Cg75gqxMbVD6TuU71JYTooOBUHCInsANt6jh1wxZdaT51Z2TZZbRpLxBr6CKFGtmKW9epk6dcjqHm66SoMQ2mkp2y29Y3faAYtTuYvIC6W9pyOncw/kq3gW+YvA6Nb9holGzuxhuSURIAdLh/bPzPEQjIxvwcZGbXKUjsLUp68VkG5k+fUzkLh81lPNI0JNC4lYiZTBqvcSGxJsQ07iJtTIWbS9Ti+6gAyx+wvKdiJIikGSqi7txASRnZqHgQGqoNAavYKZRxURbq4qYPV6GmobzAcEel5XT0s5BM+jokpFSOUShKfqMH1JicbCnL/jKFxyQsW9Hocg9HLBkQ/VSWATnV51RKvCZ8ypDEo5DGJIEkxIpWHdXmV3dJV0xGKUWEGA3RtDWMrMfK6h6cocOF7DrrOG0scV3HytFvkxyIKUnI5VD3i82o8r2U3s7Q4Yw5MekQQzd94CI1EdiMw31g8utIMqyiySFlvnMqKjtvnVs/2EGLAp9xaA/M5ffaT/NYIxsVmHhSA9JcmlMnIGQF5FKBjXqllTpS0JGFdt/4YRZS5jU4KzJgJMvTp4nZiQ8mdkMHFZbJI3V2nQhRlpLLJiEImlY+qcHVm0kmwHJ4KurmpTqzRSd1s9OTflPNUaFijX1CmdeiXxprhSfFprFdsD5nw3eEuIwaNwFZ/rC+c9OSSB7qz4BkAwUHO6svr7lqpQxjOEzggTpHvn6lid14o4q4KJneDjCa+WmPJhUK+jiWOgHh0ACZQm3GFMHniT4gp+3k0aK5creewhNOM21DjMdUwVQewQOYsKXKIWOyDZKAzu0dOYDGUsuouv2hqKKJomoabcEYYpACpkgaSutjyQ4PgnETpovsoGvS8PptUtqLKsMr+ZhjMqkSpWsI+46O03AwEF5UoZFmGhimCZLR4d4lGmuIHGaI+7RwmAtOdJ6X69vateqrcVnnzmsV1TGorVVM+Twj0r9+nleRaDEWehxrMmnhLMaojQNqP1D6FqgHbZBLPJROw2XBUvabCngzvXMmUX2ziNabBPSh5NXU4XIOd4kt4E0hDk6m+/XB8r3p04XFZ+5dyOijyKnukLyAjD504H4NhRSAE1wR6WvWLPFiJpOuaJZxa7JMulRTdv7657D2oywyOCtUJTWzTXPEYFXD1MS0IqMLAcck3UxE4575HDhFsylu0Xk1ihGpxedNbSivqXyqUzjFiyHaw7jBMmoSDBWVRrpQvn+ii+0wVNHIB3Wq+jWCYqiIfWc1QiMoUacRIN2TIjcaxwQxk7o7Ql5psCzqlRNdtCwBa2QnBOGdkOFLiLaTVV1IednKnJc04CNPTfY1lJuzPFvrSKfLrpP1ylLyhYV7w0W7jKihpyXddWZBOCqzcd/6MoGJRgGPTDLqeZsb4akbifzSZNdIH3UpqUxjHvjRSTUNrky+Ca/9BCWfjtmk+cw6pmMxJ0pNxVrUIz037INFIn2UedVdUhWR0Yl9TkhDJyWohFbcI03+Do7Sd4JuJE8TSRweTctq3BUNIaReRKrHkHTukab1ydhU8qZTADdc9qGjm/MUljBKNDcCdAXUPdeWk/vmCs80ad1zdfDjXk6RPkN1Iz4hNUxMZVnzjqsgTEhseonFsEYJ1QcH1TVoJv2o1nDETHludZfVhZSxMvm3wDQE1aCPHGRsaAU3XLmHVuzBlXqMFfq3tzUAdvKMYAryLu23t/hNzXXUfPjtLcoSg01ZRcnnbAmSok1oH5/tSzZfXi02UYzF+f9cvH71vE7S4vfX92W5+fXt24JAF2/WMM6zIrsr38TZ+m20zN6+/+WX/3j77t3bdY3xNmb2wb9xre1qQnMLjTaXisNfL8EZzIvyQ1RGt1GBKH6yXAvZFusoL7/e/gvEJfF2feZkyW8dldsKWz2GPj4SRw6nYX2yLYV/N66UuEbcavAGN+2N7pCsp+gZ6iQWCKS/QHGOJRZHAAs0eaK8nTpN88+XiBxZUq3T/m+e/9Sl8b9s+fqLOcIHQD37SAMxCRZ4sNgk0UsdU5dDZJOsMZuVXgLZpJgjnhcfwF1UJSVH/P6ziPXbW44DeF57KzAbJwF4Djbi72GrsQ/PD6E7zAN7yHHmRt8AHodNMUfsOsIDMgkOeES3VoJ2qTb8fZkDtDAC/IYFz+NM0vbyeWDGDsHJU7FuUzEPQn22nQYKRCHRHLdd7ljA/quVeG8sD5xolz6gbIJ0CZBihzSLlbgCCelTLraL+ywvlSuumGqOXItWesNNI4up5sif4BJc31fr25Q850zDcknmmN9hAW959aD7aDFPqtsEFve8iKM+z6lknOQAv3f8Nf1Wxiwim2KO+G2zVCCyKdsm1IOIcncBPrHYxj1RiO42yQIzylHPSGTJ7ulsAVyRx3pCnqdL+AiXaHuZvEgnJ5thT0RnlSRKYCHRQrtbrmHaRKHnNDsmxZ6/wHqDX1JX8RiVbEXfp6/pp2wNLoVlk08zR/0Myug/wctTHaWYxmRT7BCVoyUk2uFew5JflKjPFiOfJNlT55BIruNyvZfnsKhhs8mzR7C8inDM9gWOEMvAi8kWczUrB+DlOexbf52VUSKnjzSHUx/UlSgzWcyaihisrrOjmNON2BRzxAu4hiVuEFnLuBYLiRYtfai4BuIPFvODemkSrTflF6T28YqSKo95LR8RN7GY9RebnW8fFo/d9vbfLdrTlJEt6XyaOWrzfPXX8h678bYuTjS2PId1Db0yIMdn0i3mb4XkVoRDySM14Gi55ND4uTyY28pu1/nzc4a77ruFyt+U4UeW/m6hnKdJPT0pZ31GRZek28y/53o6fb1T4Mtz2FPj9HkDc3JM8SF6KeSU4fPY10JcHgiCbG6pc1lsXKOCvwLCbF7FZAtpypTkWy+mWrX6W4H26qscAFFzFFMt+JMueI3PV1j2FJNt5mV3XspPTCrBRn41hU5e4gRcgHRV3vMSTJbDtYZLkMNMGEdVHodaiIJBYARJLMthQ3kcv+o0jdDuTBCKTJIN5hnigzYuFg/Kptnsh5YQz+QoaUuf3OMDVH5vpMpl0/7r6Pn0Ge2DhPMdKsEG77QQaEs+mWOgik/QpmyV5S88m3FJVjoZ2o+dp49oxqLC9ePVPLoyk4W0wz7bcnsvl2RtbiPljx4jmES3MBHg1bncapJ3Qp7DYhxgqkEXUy12A9lT3ffGQZAfXFm61S4J3r0Qa8RZlrftOwZobyrslNQZLY4iovghw1ZU7LwgHEXwiZb7bfWdBGHjbX59QV0nsQajoYXrai0fd3kO2xqi56Ea+ByWdAPLpijklyZJstWsw+vOcfVyXJWl4FwgpFoj/4DFfQKLUgPPZ7GgTC1rEoDY/RLtw8RDAXkOi8MBtBsiRWHMrYBsio11UICyxviaLCUw/VdrW+UJecFXYqWsEyzWIBzGKUokrWNT3BAXZZRj/ySAg+sIhyv6nG41nqZLo/r4fBYc1pgXT1PsJSJjNFkGq1UPCx4GBcjYR5vRagdsWJ8uo9VOjL6OzW3DdDe11ZhovQaFNKKNpB+Dma360r2Pc7TZJJDfK0gzmOP/AHB1z0309psFdST7PPud3Q+45EGaTxb0kvTnk3V/ujVCL1402Rzq0gkWZaY5j8mDHuKDBAgeT93H3Ty61/S1iwcn2M+4NHu3HuzFyqPyaTaafwGa5UxiqBBTHZA/g6ioclBHwpGiMzkcajhai15KQqIDLv6hxaYz2Dp+kcNL0donJFo7lNWPG8mNRIosjnVgGuir6HI496KPL63tCZ1ta5xs+pfvfLxsVO/+GbjZqIuO42eD//X0em9aLD174NKsLOwqz0MuaVtcGtvSMvHDp9nYCxs9RtzZMCnmiI2+IuDR361PR4uTrNpkKb6fIj0dZdItdAcFqhtaOwrk6J8o/yp+ZXNYehzUZ2x1ZFnB44BO3Bqp15jMofTJenOx11reHcSeuui2ir2LLF2JKP1Xi+OMbKP0wuLTbFTasJeRjhIYCUZN8snGUFePssrrTpZ+cJDTY9UOq6rzMDHVAhkS9yMBsv9s08oVWMB/8zbV7qujQ2BxndXXb+T4Q3nt2/9VdhAiJFoamq+idMUvFkzC3K6nY5u8dsf1bxsNLPt920JNPXK79DsET58F/VBI3BpVq5Genrc4ahCXWxyqkuOoWU11xzCN8hfpMtIm2ZyVrEEdtIk9GGm/WogdkJ3BBKSCFsck2Pi2fAHcaX/zaXvYrz4xDMOFDJb7laKpeTLghdCQKpK7GJ/ZVtZs8evILiHMZhSghwVNizIOa7VVq8wKbmhUR66qBCxeihKsxa2nQXar43W5JYtJsDARwyTB1l5cTtyliKk2Gm/j2iiHliTbGLeKEunhRFekg6KLzq3qfC61XSqvGshyONVQR2KqPRjVtXC5XGpqB0C6c9JkcxslIgx0w9NlsDCYPpd5hAUUZy/tP2+PSGbetfKSxZrnwEyEsLb4ttr0UNks/wSeSZQQ3uLMJFkv61sSxGdetTOQnZlFczE3DyJsv+qpsvi52frOizO0sa/6q2TCTQU+ef+5lb6CGYRhaUB3ptWjbD/j0u2XXLBg0g4M7MTA4TjXk2Xn4FV/NSD00RlNBdXRlyrP4fhLj3U4pNq9Q6rD4cy+HM7M5a/SzBYS3NbX6tgoBHXEEne1TFV++xUyiSi2FsN170XfWPq7BRqJhMMhNd9sLh4km7sq+QcoyH1w/gYCl2iN+yVTw3Zp4afMAHefF/j317v/JjhnsXPmv7s4abEQU/F6W62w06W+W2wUNt2jVUyT+s82m4426BG/2+i//5yC3VIGHyfZqg3iZs+X2tIj8WRdnSjwmASL8xHUhcusEIPKUt9nHyVmpWskXSp52c120dRCjbp+1vUrVtE+0Rz3R1Q0vWEh6e+zj+MX8FS4zzZt6XFnm6iosCnzzV9MFFl4dPr77ON+mSXJ9wyrUVcgznLhdW6TeTsIMdJ8RfUepcWTqAWwKVu3RfH0qFc8w2KhrE2tpX2soEJPq1OsrgDlqWDM679anOCuhXjbzScb40pRYAsab1Vpv9ojnWX5OpIEIOZT7ZEXEf8aB5tiYcgKHng3dECp7r1X4c0HOsECD4f/4U10zbfpzUfnRe2/0z0oyFKMS7TwmlE4Ebl5C11ESEOV76u4pDl3Q7gpF9kKptLrb2KqHXIbNkoJLmTYmrWqfw3ZZ61SPPNssFQpS46zUpEHtETWpz7bjbwI1X+ddo1C4ngTpS+CRlt/tMGR+tK5+eeViN/Rt0eYxoKMFhIt2iiE8DqxDdlVs907fl1rv1ojvZcivbdB+ifc4O1+lIh3XrkkC63gPkuBLMY0k2Axf9rguNz86T9PIeXn0uvJHPC+KVvPJBe1XlVyWw/TyfFm0Xj4Sk4++yRbTHm8DD7N4hzkKbsAZYk2kkUmTj8x1QL5PgdAhy1JtxijCm2uYCxF5tMc7uR9j3gXcCZlpuPZXXPJaRmy9aX2kR4sloMQGQLYVlky0gObIR/DXKWI1HWYZf6EiU3aHs6kdTBPxqShXPhSX34s43I4ZTfAcnl7m4PH+mljbmFjUg5i14i52/MzP75uURzPJuVFx+Hm9qFwIbo19X1a15DjbMlt1Oovtt50talR+vhTl2SB2RzQN2VPROuaPIeFLOifRFJXosxkMUbRiiNK/cVqi77VMaZ+Ts/Wsbwkd27L3YouPxneojjIcHXRbVWU2xafVAm5Wi9dCrpEiyO5FP5RgQWQ7DS5JAtzUhKtzteoPTjkgsQsKyZbOBKWnEmVfJh/Dv7UOll933FR5sSLoMiq3HffIUN0medGMLugt7WtF6cTm2KPKLkayyVZ3dnKs/VlUq34lwrZFKvD5ayKhXlFfd6aWdB6Bvlxfovi6MclL7oLHB5iZ0JeOuYU3vqTxepVJdwSU3+ZZy3Ydk3+sJPT1bN9Gv/PuSOb69p558noeaGpw3F08FQVHmddwDXKnDqn3jO1D75+z0p+7nFJe6ybY8L7c58j3+2mJuLPebXTXSM1Zf54XdJMWsUoQWXJgv+xAkWJtHM8syT6AJs858HetmtWvrrDzG7yOFpaGFd5jOThLi8vvq12PvXbwq4vCyucs51cs1GhZrqJ8Vr5tKkdtFvfaTLeUq/qOmVsl+q51nmQr2FRIGW6vsfjueZzaC7r/yDEts7BsK70XUgydp/Wfd0aDjp9LvFFnOSoKu9RpTAmjgkhuEmH7MBZdnDjcFnYK+whXMVbqpwvMU3uIK8nydLt0RsRP1SJJJt5XV/xwF5nD4AzGtDfLdGO4hgUhQqTSbXQyLFfE9I6VfJClr41s/0sy6u1vyNNB+MwjzVlx5m019kGxjxE93GuyS9eWba9q3x+KY+AcbkVt7R2LhgR4UvCFgHmBsFxnRyKwuPMDlIjD9F9nG12YBLIXiJkEqy94KUO8JbGxVp68nbF5qs5En7ThINpPtkYwIpSFm2E/m6PphpJWbo9OokkLcWtUw4yy05mRf7CylVOTSqiPuZZtZHKqS5ll68wfOnWHl6ytJ/nEFJ4akrVJybhILAMeeYQQ3IktY2IgABqG8FxFYeKwttq79r+S1gH7n5NaObH2DXZ7XlaUW4cdiaVyW6jMwmWeGIII+qzzZGh5C0ah/dnwu6QmuvWzV5fiDcopNocE9fHTQpoSbLluODrgZWAyyXZt1cOK6ZamPrqd5PkwEKiNW59bVdpR1Rlsue4kyrPQRq/SB5gl+awqaEudxXx5/5sin2b2YNF1ZwRc1nswKNSJnGoz7Z8Xd2WOFzweRonqGEy9uZzONZw+jxUQ5fDvgYS8rh76k7XF3lOzxq1fZPntK2xEQmavvE5HGvQ9IXP4VgDKivOPXkOR/mE5DzEumCUnAEgJZlB9hB1S4lpkD1E3VIyG2S3crLARYQroO1XS/6Qc50Lp7WzTQLXJ9m2Toy4Tn+3uc5yV6VLsJQ9ccmn2aA+RfnyMoNpWfwAOUBjyzvgKbJYrHP3IH7IqvKoLHN4W5VAuR/T5/SosfivdTJQVZ3FfvVWuWbK0i1chgLHiOw0741CI99YO0LifQESumiDisTBCWIRmYqhz2njZJIvRZes/qsdkqiC9l8tkSR9duvh56h4AEs9NVV57Np88vj4Xmxx/dUO6fR5A3PinPI5S8t7EVTI4Ir/DxBJqMynu3HwB5iDuPwAbiF/C0eVycZU1BVrYp5+yhKJ2UiVy6cmGQepcznVdBylD+JWS5rBGV+crNIMbvjnJ2ponOaE2ka8UyF36U7o57cRb8bkE+3XBaKTSKMmy3NYzLQK6Yw5/DeZptd5lBZRjH8KC5smn39tIpPqc/rXeAWKio9pPZTXRjpucCQEDT3lOXxqkPVIncvKY6HT8jQd0mSzuWSSx/dRAZRWWGkGm30VlN+RYBLsLX5N3Dupva9Ns0fFGy4cbLcq6zVaa6UzLmRzMBMm5vg2HZ+Y7LSuwDqCqXADQpFla45o2k3wtwLtZz7BovR/GFsC6RJj1gxmnAOdzirI8zH13dJoID0wsBTfuxYz6SO8I3uagMwlgXRhLjOYcZirrZtHob9bSLUCLH/A8l7KZEKiHa4kzAr1+Sdg3DC86sGfk11/b1Qkilsk70ipc9lzv+xcjE+z0NglFlR7y+l50baAXOWLBD1GmsG+72izuJHtX2TpNtpIDDcQcZOo53FJDpiS2z58moWuClKsiYvqKPXdFk3SQCbBwmoHikK4Yd59tOGmnuwZuVEkcJMkwx5L1U5iBHAJcgw3pSk7omsQrlDhztMnTa9PXgZ8vvnvVUSozEL1Xy0UjxSW5El36WmtmOqALD2LFVNtKKlqr2tb1e10baP0ENjhqLfdA9XLq7TTiiyudUjJoMhioTIMHl36Hllqjiqdjyg/ZE9pkkVLSewvLslmoWqLKtUeSQYLX3TEsGkBWgzB0V1Mtmg7kp8/AFzd86/SUd8t3BKrdJkAvMpwDonUd2v5eoJvi8okbJ2wXcvzFxJcynt5xjCuy7O87JjLs/9S+kWIHPTFLVjQddY9mSrzQqeT91hTpK2mYexGIqKL2cgIZRxODet/XXeBk0rNN1uUY5SCX0qRgHVJdnYn2W6e/j79Xm7nZhA+2amDmPrMmhbF8XWnKV9nDyXJr/MofkAdkx0k8mkWqNg1UKanMAmWp31AfizJp1md3cFHkMtfjxUSf4LZ42+soJE8ZtGUJouuTsnZdPvdwQAin5vW9mN7Q8NsOkxZ5ekV+INEj/RUXigoJ7VFW34kNgp08Sw0A4VVpMLZva5AVGTpWZbXo8Xb2rlEG1wy7IDs3XkTh5DocD1LGkhdTLXhnOju7osYAJn+btN/ivnll+EUWXbTWWW2JTMjf54g0RVi2WTRnJbOIYjtlnuXUd4s/OLdTTrF1rolQ2RTbFSFnsayA11Z+mxb3oCnHWNYdtteIRYGOVgSM7+832yOOdaqg7xr+WaxATG8a8J59mPvF8hWB+0S1dYObyQPk4DTT96Trxupi/FAXsv7JWcwQZNPcPPk06xE6NPXtCGDKrI9k2xtU96dhx90g+WpUGiQXZQLK7iRFA1pG8z4f/JwPfvBiWPwYDDu26HgTbvGDY38JU8aB1jZEY77Mi4tPPdIzzsu36McIiW2mwkn2foWppH/qjGM7z6OVqAjrSAPFbdY4A8W/qwl/2Rm/cXifC5Kq7soxvfNcrStld5vVeWxdKaSeFFZObGAdMVfh26/maP8gEsepPlkjvFJcoz0yd7VJSoAIYLssFVIdMDFP7TYdAYLLbwo4CpFu19IOOKcf/pPlm5/AoaDYwqXf7g0+403djHkUfk0G7ct2SM0/df9MY0gCRo/yK0XXJLlbu5rVX69IxBNqEJxUydm2fbVb5QlL9w6t4sGh6aQcpMlS7dwDgDPJfokPndFfbe7dvBHBXPZbYP2u8N0PsnSMs8SmZVXlWf/NwRh51yAyTb5LDtKYCSITfJp0g2lYzTg7RLc5F7lKNK7vrEZTIQr4EaV43wbFCJYlm3XuBmVzfLFH1WUg+JqdcsdsPCJltugo+W/qqIUY8IIiRabGrL5UAGLqTZr2WUOFiABseROApM0xVqjQiTTQbYwMgk29yXSB3y8J9VfhMQ9dJ1qr4J4xqFoUFxiTyiLjiPj2vrES4JsipUbdVv0W87tw/g0+3YKkJ54xzCNhOBaXJqN/ExLNKqS2IJ0gjneGUxAKkj1/qs5En5qMC0ELYX6bCMbv4AnXiaST1szj68hyMm64jeROxiHmawpu/3bztCx+/FjwipnmjZtDncSG/vsXOeB9ZvlXsd/+KfLaZ+83NxHPsqVR1hu7NaERZGcptFtwit89HcLNBBXORDaRH22MLyLz1J9sn6TKltlnWma0+zYpDk12k/lOjnOli98E+nv1utxaz//AsqnLH+QLs1Cnu0SAM2nAHKgyeYqDpTFx5EKdfU8Rv/VFkmUMvT38RbIufSge7AGxDKBxJenLkRDuehD+vLjsA+plLNt15+mXJgk0cysI5ntCMMdR/HDeUpOregQq36spwB1YEJjpHHYMZiHfkBVP6yv+85duKR9PK7BGiktvmcqMkQHVjWD2VZdHL/JfBnxHif91z0+oTtBA7XK8pcw3MSjOXDSMMSBi7aOi1qfyyBMxIF5uIAeWGh3WOgjSEEO40CuAjyaS2zZQYht30T+J3ipnytmkPqvVkgCyGFPIeXjozi5AnHmGxS5g3HgXE3ZbWfZsHaPcQz658X5MhHcSetvW8OG3/IgbNjBOLChpuzPxYaLpOLuQdZf5vBhVr3Zp3+rby5jcnwPllUCrqPiwdOYTCG5GJO1xbdVm1yg2Zfyjv/dRwu7pOAhYOsaID2pcjmmKrPN1/Q0z7Nc0AP6BJvZQAKZ5KVgAGJT7BBP06UUr/1u2b4qjkFRyFtIpVm2UaQh9XlrJED35qenNtXCuGhT6rLjTPyj5TJHgyq4j/efrS7qBHlmSrb8qBefuayjICqqHNSelJ5mURrKxR6qL7+1KwZ5ywxt7p6w2sZKWDbJHPMK39VksZpPe2zNaMb/A1zXHmtBuLFDc2dIDcSBJ/ecJ0+qPAdp7BsiuoFxiQutLrqtzNe2WHyEiE2xYj3+1SH7lyUwe11kKFF4HphJsrWUnGX5OipLyIftEVNtvPTXECkb11njGsh56XOJFqfK1W0Ci3tet6E+z+kZtk2Rv5S9zvA7m2hTQly1OKdyJmlrRBhiwWodzlVDgHOQaQYY4wg3uk7xQoSYOpeTBSEQD9V9tLBCZBsY8zjdxz12+rjMyVsyTTh+37NVGsvpaFUPMBKvB3JFOsuztYq7+TQbzlRhsilWc/tfIC6FKV1/tGgZeJZclrezPF+BSHJFPrI8MmlsDscv9UPwPKCQ7ITdvROohKdy7LHEIJYZlHCRefpgU0BO55Ca0iPZzvoqpSEYxOTZfA/riN+8e//a9u7vLjMnRg7GoORMwotJ5QgjrWgjWDX8t7u25zSzOS2uNxFceWr/LYqTk6Kq6LYaMkJpFPhaEwtSf5lza+xrYpiJi8mLy0cxeZ7Tj5NpJAdu1hcfh6Ml71Bbv0DdGGfEycEk2F1cFO8tWhmlspyPF0K+WJh5CpCnQof6rxZtiYpCXFz6r7arwqLgx6v/bNW/D+AuqpISzfYl4kYYJYXQWVmWrZm3zd430P0LFszpZGcAYVuXpOM4riVPfbDNC25J8i4ud+Fct2gxLTi5cWl7v3h+AU/FBShLkIczB8sxHaakKdBIM1Nau2gi1uWbdiG38y6ZTrHcEZfzv1egAktCdb8JQAE5cL229DisfpnDLId8bJX+q51lWLQH2yKIi2L/1caezFuR7UqLrWi/WRxTg03ywjek+2iNIzaJSbCY5Cfc1D6xVDkEJWM31YoRhB2a09fkAXHOX7j7bIclaRr1eSq1Zy4L1T2IH7IqVORbAc7FZjWMsa07hW2O/EyekcYb4cv60qkcW53Lpt3X0fPpMxDIwCRYUDV6bi9bC+eWbJKFJneIg20kDgLEMJZjhhAMk8YtFmoXjtdkGaaUPod4wDs5565w7Dr8zOBl9IJr/QQLxPi+3q9yVBdnWGOkceYdXz2PJks3R68fHecgu497fLrNky0stwVgs8nk+kucANlrUEyCJd4lQFv7pbBCsEk2W+UySkhpbtPDJNjYi9DwoYED4s6HSZnDehzqJth5CvGBjHSC82l7PM+Jiz38Nwkxjzviu67weC4rigHGSIe5wS7eu11PV6KRexDyMCh8mgOqAtAeSxIehUnYGq6/AviIsX1WwXdto7GcVjY9wFgm5yZs4Tt+I9B/d0B7r0B7v9c6+kmeFQXajSRBOIpHc9kLD0LsL1fNtpJ6Oim7OSdP6JSMqroAjyARFjXqu43BMcvL9v4FZ2SkUyxOrqokkQIyCRYq4qbx2eCI1n+ey+n6EvVECHLffbTZPN+BPAe5gMUk7Nd1wbMc/FGR27vcAWf32cb5nYSx/xQV/OaQTtgaEYU+lNA7nn0N4hJ9SFVyW89rfqJwf/1Jie8OkDpzcQlYryu9rXyyc/oquW7qOcwYwmWA5eXGGdr6Coo4wPR3G5NRnFRLcJ4uICodcRtxMdXqoKPxZ0YJpfy4Q8wwhw/1NSz5YA3Npym9Rj6DMmouFnHKGZtih6h8VlZItMOV0Iz6PJ2Lq1oLTJF4Oip+wOUKlLwiyKZZHAuSEv/MUq7r9HdbtB95tGlUKxkok2yLjXYdT5KREhJtcY8zLPz5Cc2nzeErSDp0Ha0k05l8nX65OiqKLIY4glEqvhIKC+IfdXO02SQQczqlsOjeBdWW45enNrdKCUFr5FJc/ZUV3CyyKpe+ZGi02nXQsmUPE7Nri2czr6McT2/HZrbEsmzmb2+l4+3DEp39zYoh+lIqdlCY0YzI3KJvNS90jfTjhAZmakYgbmnoT7Ss3mfLmytQlDnEStIJ7uWQhDApLexlmTJ1RhNhMVyXJ5twFQRgFoMme4qPmnpTM01reruhbmbpwsWJucW4cHWe1j44TFsR1XP4O8AAAy9pnN9ANzizDfQxTBL0uTPfGow2X0Q15DZjzWJ60pQDCznsHLQfY1o3DCnyS4jH89V58aVKkt9f30VJASx77808lyBfwwKHGq0fAbihH1zQ8tBQSSEkFZefzm7AXvrqPEdPAA/AZwMN9lxTKKzZ5I0xq6hKqKSNJWvI4bdxpdkXFrgCT1G+vMxgWhaNQ+zNtwIsf8DyvjEG6zxKBguLPiRCEQO+GKzIcwRYrAB8MtzgbVykhsgQTuC0qrqNhiOUCaHicKCefMSjhZQ4PPY2MtBw//3VnGbj3vx/Ha30uo0suxhjkyT2eUy0GBHYV3VxMkkYNy6IvQQhBV+hWlsrNohHMAU5n6Uz5jZfur+L9gMe0GgFPmdLkBR9OfyK0DoiPSo2UUx28EtwBvMCu4ZHt1EB6iyvX6G2P0Ik9dojt8bg8kdyktTRK9sMn6MU3oGivM4eQPr76/e/vHv/+tVRAqMC+w0kd69fPa+TtPg1JvM2StOsJF3//fV9WW5+ffu2IDUWb9YwzrMiuyvfxNn6bbTM3iKsP7999+4tWK7f8sUbWCOUX/6jRSmKJRMagDo4bcb571VEPn1LIccbv/0nEDitHeErcPdKJUd+e8sX/E3CW7gJv7+GmLJkNpLHH4l3aYQDZKQ4FyAte/0Kixt8lbMTOW+18PVpaV1B+hjl8X2EFJHP0XN9B+L313/9xRqTOVQzhi5z0QVDQGYjyI+BTelxDckte4/juZL4UC3ILRwCoQ9YtAzYCJbjKl0m4BzNvO7a4RlMSn4x31mm7PvHVcRP9F/P0yV4/v31/yYFf311/l83dNk/vSKj+eurX17939aNYG50urMDe2/VD4u7Hjk+e+0JP122nsW2zNQV9OKkmp7OjeCKezWlXcF8uLA9ZmoxliCG6yjBqz76VZDl+93f0ChiIf376784COL6dA4g/RBpOStgzuoOC9xffrFeKogrs2aV+2/r6Pm/24LWEpwKyeHR6U9I+bq+r9a3KYl15Q70HY3nbeI1ANSbJ+4goRZn1mG54V/0pYSYSyzBWF9lKzBbkbxfgriNqeE+jpdRjppALsd1d6z8EBtOR+IXoq1LFSXJy5Rixwh0HLmDcofGPFquYdqFiw8A2DJOE0bUb6ix29fX9FO2Bpeeiwvrlxh2kRHcEwOQkXJQDNvYoyTJnjrTPHiE4MlrATvabPLsESzxu3fpalGtfcb7S1YGxWvByD18rrOe7QsF2UR9u86OYq/1X/A/dYdaPFTBp0iUVndRXFY5yNGKUH5BGk+vH4Sq5SNimdCY58VHeFeeRLmXVtRi+K+nTcSvr+U9yC8Zbzu3lrURxLqlWS8e3/3iIHIqvHEqYYyX6qPlkqvSq/nnxYfsKU2yyE9pbTD8huZbmtSTsIXz6hkiej1Lvt4JeE6bwQbk9HkDc7KD/RC9qBCNdn8NIIkhQgD9uftTVCwipDmAEKPKItlv5/nyqv28CbFQx3Dw/aNVDgCta7n0iwGqH+IKoHHgsIVNiB8/edKAMPF5fOQdjXfZRecJgMhE5/Gx9eHzwe51Gx9ZdoYGtT1s9FLKlvWhZpS0aCf3+JzMxRBk2HQqdKQPBU4LLxJyASfdBxUpLDhMTPqIphgCq31vPTczZRY/BDLrYRMLwTt6jCAqCxMK08NsI22j0+oF02D9vcie6r42T2z5DQPS4eHdC9n3nmV5275jgLZFPrDHUfxAbhPh01rPgwi8RcN45zUN2ZcJPAaFLF9oZOC6WocYmBoveg6FRzoOlg0UBOFVUcTmOPNx9XJclWW/V3ecMjj3D1jcJ7Ao/QGbuZwAxJdIMDMmVBe8E6RvEygY+9mFaYDgS8fXZDluBc0244S8wTRSHYsNwokS544YnWVQdXRxAK/hGgwYtW2xT9NlQOTW1HSaliAvvHmxkV4MKhiZgRoJN2mdaL9wDUE9d71kPlo8QVFSsbLXtzAlO55RmRW1vz0dLJpLbj69qKMYj0ZtdpsSHP4HXI6I/mlc2nSrUmiZ0wGHFTihDiDDnIa2gVE9VvEtOQiVdg4+gvwFD5y9dYUt7WNboZ397NvBlvZpx3FUgGYF9bYFdFifQVRUOSCOjGHd6LoqjtZjOol01eAfbFUORsfaxaaOkSCxfPla+xsPHpBjn6oQlhgGEJMhJN7iPquNO1E+hg9j5z60Hy4Ngwf97x0O+lsa+Zu+vxUgjB+V2isruG7QVuUuQQwtZ3TUcz/1oFE2AiA1x1jFSVZtshS74Hst8wKKyujh6qVHTojJKujHqD0OXrotTOfGgkce/GV/BY+Lh9FFlq5sgU245TrbhPZlCe6zhK+lhJ4lLc+FcVw6uBsx7n9hzmQuIXEgcXAObwv6aPfYA20B/w18esA4XxXXWX1DgEd2stE2GF/ZUwITPcfMqw8p8FdRuhqwybu5aAfy8Qtsc9pCz6xtsUnsm5O3jEjkZth3CJ4+S3QyAyFr7jheS6c9UXaa3hzDNMq7w0BEtVvywW1xQgOIcQYkj/0EB9kZTEA6pEX92cVr8At4Mp9htpcM9oxl5r30NZ5aMaIstTbiNLtV8em2nWWbtmcOpueupO/I8aS9qhJAB7cOoJovNmB0A0sTxqsJBOh7Z6PxOAsB1gc7vM7oeEJKVDPDTQt6qXR6dhoqCrh+JLF2GwsN3lJYoet7ojd6qheFT5/LPMKhJsbUm+gDpD0RaYMGHYcYDydZkuWfwHPzckZY8O0L82CrSu2ZrXFmXUph6DGovy/p1YDz4gxtKav+dsn021xbDqTvRh24MAQX0hS1bwNb+qfhxj1kw1EOXoKb3im6Hw4fwh4+HA4MBlu3ewcGB3u6Emdb7OnmJ/1tQOXm1aD9WHfoR0UtteCupJ/esWEi0Iab1udFG/9gH1xardl0z/jzYwW7iqoU/lEBSCDvIBZD9v5r+eBRisudrdM1FRorGGr/+F4ADaYFO8vydeQZ3qjFWkR9YMrtCvET6LLv0d0dTKC3tktuhXqpQgEW8POitvofxUzAPSe3g7DHBxdRUSqXAyfEoNIbN+8iW8E0kFMmxmvvCRtA2pyO0NG/7VZ1AcBnWyELRm7XHBHBvD3GS6b0DaadXTFJcO2gczIYmHR5dJvY2XoTpS+BsGSnfyYacFvQa44geByH9RGmscP2nyvu05IT6kq85ypO5tO7kGDvg4D9E24uswKHUnFzlJKoQPdZCuQhwtwCJ7ahlOZe/8w3HLIHDXdWeg7aYd852GGJaaxollYvPZQAhbjsdf2UXQBMrPMiG7zJ8d7aM/8+B8Ac/8+2+GiKgBzGHLZXTMPvkZcqPGNAYuOZyr7O+bNM2G04OAn2DMQqRdSrA2RZWJPNOYTWJvaEQcZT72ZcUG5vc/AIo8HXUBxuF+2CJDtOshVW5PaERS+idFXhGG7WPNqX9GJS6ZGmIOnMLBDZcngXYXGgWBsDg8R9brBONPf6zaZ0H1o5FGT/iJqvC+5W3j8+HPOHPxCeYm/Xipc9kbOjrMUtjU6qhFx00R9j2p9VkcOuBRhhl3aWRKvzNWo6vlo0SBt7r9ircr8uI46r09SOyYsSh/u9AoXkIcudnXez6zctPQeZ3CWuSgsu9Vp3U31weOVsfZlUK6gK02l4+plVsZrtPc5MvoCnYo8ec5udQwNq4ORBnzBQ+BmfMEhBJPB2Krc/0z5lO/TXwwajhTW+v5ElyVFaPO2NXxjukIOzNCkV3J7nJhLbJ1O+Z6Xfqw5j3/1BRNsTrpl9mQ/HPbXvVSPzwhxlB1mig4XIIcvqxwoUJdJi8RzZBq/17dRAnFdla69ifKF9T2TB8F7wr3+1V5gDvYoTxGsVgTR8jzEUbG+k4Xr7rbZOp4R/RvE41Q2dj+IE8jUscNyKKxBjSbu/zO+zDo0ymbr77n7AxmN9+oypGiVHVXmP6RoTZWCvxn326z7hXEDb0Tqn7oEEhG0kZ2D0r5i3rrMHEGYbSeCO4hgURThQ4v+BBtjLu9940p1lebXeo7P862wDY/vp1RTzi2gx9+Q2euDRTF+4NLkV6BI7d9fu85H5QbhjTyYI6ZA9izbFdnyC4HHENXvGLaudVvW2Q4cQSV9qSexljPru+8o4vnGCW+EZ+b1BUQy5IxqJ3+W5Wd9NCbRPwudjnlUbRwnUlB3XJdTpdY/AJxRfmlXHay6HECh47smUqoNYGcXCuZviiUzLPZFROyEeflp2q3u8H5xG+hLwuiHBCxqpQx/fdTeUfvZKve+VfM/GcBfqvW/k+105JiXxpaOKb4ljt0JgNQGRA0LVF+4CR8vo4lFVeQ7S+CXYleYW8Crqz1wHwnj/zXlWsmdUftT+HpWhhRnaaZdoLiTnaZygphqS4y9ukrit7PR5msqucWVdgPmJeshUOk1PG9kwTQ+byibtGarIYrLaV8aIMST4IV4bouQMgLFpqq55bAKrax6b2g1+mPtghE9GZ8Tu+dVRayGiY7QqkKZeIW1nOfL7FVfgKcqXlxla4IofIAeItTwjFN6D+CGryqOyzOFtVYLQWz2hguK/1oGi+DRKgMItz9ZhLEyQtk7r3wTpI3Fjw9sY/M5IDpAcOUHjz+opTsOOUGi3Hr+BwE0KppgK/fMMOl08gKWKdN4tPXl8DBNbCIOdPm9gTnZOn7O0vB8B9x8gCtN3mi8/QCTcyg/gtn+43c3JsoNpggt+ypJloLESwQMyAgV+HKUPwbZSHG6wKUbjnp+EhmwjOgWGPb+NAi1IjYQmSkHIaKHYmwZNiH/XL0bnUVpEMfsI9SjwwdhNVcEVKKpAEVpPog2+5RyeOCJwwFajfWenE4Vv+mWFyxYgtDn1MoKhPMS50E9BaNpA4r0KDsdY1SbDUWxdAcLebstBg35HcAXWEUwp5/FBb23r1xW/FUjT/gSRCN2boH2zP69IitrX3hTz82maIAzIR3hHVO89ZJ22a/aD15f0Gr9vBVj+gOW9Iwtxxb2bwgQxCG78mJJZ94RBW+WCGmW0sjpcfVXg+BzftaT2P7oZ2eh2XrRNJVeZIk9dogVDG6VNQPX9CnV2AxGfBNObOsRw1y4WIMVabqgW1nDhmvcZFAV18dTz8Yh+RDLiwDCXBmrnnbJHcVm6/gT1KplRXbuc97nJv1dRMxDusvpbCkvyZtrYh39dRaOf9U3Rm0l6MvbZZLtfqtfrsUnG1jY27UY7QAt/cPYhe0qTLFp6x/M5L1qoIIrRBWLxtAAtptfD7Fjq/wBwde+kFprUcFylywQ4vv2uFO0n+C5jGB61W/a/4BgZ+7Tsz7JAf6EijfjdYWz92rLuSb4tVx5pQ+R+WXlm9wGuierlSkoQjqMkwqH5fdS3YnQfl5CbsLB2e9r+4fAcGV9+hMfI8LHKen/el51Rkl/nUfwA01XAEznigTauUkKO1UCoc78PIIGPIDd5X3Bb3pNqJ8AeWTG6LjndtqhLBjifEu3Go1sPLHSPssrTK/AHDvi2L8Puf3kp0MDNrv+EsDtdgajI0rMsr3kljJLecBwg+1+D/b4VufmgwL4ve9zdfclCOYYzEy7EXadtcbCwWGgy4sByEuV7tdj4S53LKG8WYC8LTm1fcTuupMv6PUHcD7L/MeXscnTm44PxrgCg2QlyxP7YSD7avjTEKrRzYq4Z+cUG0fCuiWnYjeOeyLyZp4Wctl83rI+psc6vRfObv9jp/wwmiNyeAWrrOM8N+XxDPY/97qmGoHsyAeRdDMV7WxP0fBZG2RMW2ZlRaITKdbTaY8pbPlFsS7zvUQ6RrtPxMNqJ3sI02ieJ91DZ0NTInbGE+td0XR6PidLqLorx1ZYcbasUl9Z8a3FWm41eFyDtGgv9B1yOB/5pXP+BqACE8u7HaVbV4B9sVS6x/IsCrlI0AyFhyvOB95Le/WLPje2hAw5r53Algynts/dvt3vYj8y+HWxpn3acF/4PKOzdxh+tB/FDiA052dN8rcqvdwSSdHKMJ1AUK+ueLKe+/NX+39Hl5nNEDG89A97QemPHje/crWAe+xwRwTvwOfpEvdfi7Xj+RwVzP2c8SvlLyzxL/M2fSsV/Aj55PzgstjN536bwUQKj4PHyA+4avbxqfcV0fa9tPwZa0UVnKSillSoxpByfj2ONjiayJMsXf1RRDoqr1W3odtY7h+W/0DDRASyCH3rU7koTVHReIKQFSEDs6UUeYJkJwtLDS47YdlKR/0p7AdMHfBomU8q2x2mn9fPfE7nadifoXbNv/XWIb3niNS1EmCCXSI5hGvXRfhDiLfngKDPTEpEKQwVp4xlMQBpKoOOnvdIi1K2e8+ILeBphn3mNuKy25+3HrJr7bDZcBHH8eKW750ddOoQ9y8u1J6CDhfm5Gh6DPWHnAIc5kkVCFOnemIsiOU1xfi9dbAHiKgeW7TMyzdPvwgQzPV9kq6yzbI9i6rDE+VSuk+Ns+RIqSlq9vrY28i+gfMryB7+xsZvGjblmT2Zz3Uc/VqkxRpEL1ouXuZZxD9aAbIRu9+ZFb9Kn0HLKdlxNMJkgS6onfqxRx2OW4yh+OE/J8QodSXFP2CaEw/S8Ou7sbslT3AujPSmuwRqtzntjuR9l7cAPcaKmCUGovYFHdv9qX30/jPH+jnEj9g5DvL9DTOgK4307ZA2xYUBdqN+rDD2kCDg8/8l0VbcT4PEU1KM4uQJxtjdBP7d8W6oxiFqfGZ4vEwvHOGOO+JYfOGJKQ0VSrYKDhvCbdHlayNwgFt+DZZWA66h42BM+C+fvs0DTL116xTwyOkY0ZH1/S3iZbb6mp3meeQXywm9+L8ooLwOEY8FYp+kyENKiimNQFKHaRRPK0b5vvv63T3/tySx0fp03zCPBAZ7bsJXc5mYgEBVVDpogTPsx3INL8juXJZk8wYJ69oS1oNDoV5gDDc+R7V8HHnlv2vDQByTaan+QAxsd2MjBUtk8lP2zsM9fXXaK6sfJWWwX1jF1ZHHmnIsMA1gQxTzkyVmWr9GQUWEYAsFfwDVE/HCdEf6wuAklOdaqbhNY3I/kzTvdGZMIFvQBrw8ZfrQLKeJoMH1dWoyFD+Kfar2Pp7FUl4I64s5+SEpGzM+Cc51tYDxbmDaL4x0SSr4NA7wnjOnvJnCWZ2t3NmRL+91XzNybQZf188ytbv8FYuHGJGs2dNA58GXMMFYjfA8z8lr8zotmL338Uj/OGgise5jIB28KUUDsAOjTRbYvLoNUj3AtDjYaHmDHfX8MH2DeRpYkBub9YMtx9+mDe8P3DqDWRnkLH6L1JoKrfdGJAx7KyNdcNzDs1z77tA+4ATZmL/Jc4VFM3qbaExaTvsDIzvC/2ttomr3/sPRgsU3vjwRv72WWq2IrmV72zFPLzpo1LCqKQcHuAlzL4EXhdTMV33EFd1GVlGgiEw5EpUY5+yEbyp/NbdBlbT2O41pK1QeCYtB4XQ1Gtw0Mdm8uN7iMFpWpom7Rgt73Qv/Yi9IX8FRcAMyMe2gVlHcuqH1QsQIabKRw4xKhcTcE8KYxG7FxUjyFtj9jB1W4ZJax0GQLGP7p7xWowLIe7v2YHZc5zHLPi+HYujhwEmW/CmFQg2NF60XiOgve1OtsjIZegU3yYtdaC9gxWnxyEhoRqSKhIbde+QgrX3FElRwCL19KDDLYHKMoKmqdyEDos6UtDI/mtp97ED9k1d6F9xuc7C4u1lsZuJI8gYjzX9bXxEJgnhfX0fPpM6B66gKDQNr7iX77gQmDc440rfYpoqLQOYfTFBEi+KMZ3tP9EHNwptlzhcPo4Dd3LqMXTJD9el6b75397BERArx3uvV+Mnyv94QdTl7iBLCvRjiNAIa5BGhvu/T1miqjhKD5adD41o7BQ8qT3W0LcE3jPIXYWO/4SjdbeusjiBBvXvhvEleV1L0n8016N9Rg+AR63JygnQDamS29ojorrlyGadBfXBpEvLjVt+7DtOzPnGHXRT/rWjpWI98Ha6RzXACL1TEh86PeBO7JXL1sAz6981mKOpT327xjzLOiQLp5chjBMCNosdDti7Ml6skFeASJnwK4uM/ysvVGD+KwdIaymwIaGc42zUF96GP6Md1DjV45QBQKFbAccSrIc5CHwpvlRpFR1PMc/FGRm4U+26c6VOynqBiKHRXoRtIC1NfZ9kPyjOKVsxPBlCgb988yllsYP41c9doT+te+6bJRcFss0zipluA8XUAEG3U7Ordzoda1EiWU3mZklZ+mUz+vYSlePnZCCnau/RmUUXPHQFBVnAH9XgaTY4ajXcD71FcAaVn5UfEDLlfA6xyyRvhnlobpYw33I482jdagaJs5FlK5n5gxcO/lcYZFrOe8DOAhRbqDXyW3p7j5i0qwIK4RPgtwi3EjrgTS/G1dkvzDKwdTmd0GgyrqZzqm22+5x+mLjuGK0vbQwwBiO5hNVbs6lnTz7VrQlxxjJIlLCtrcoKXlPlue4K66TU4WyHiK1hU6jaqkRjvKCgCe10X7rlhO1q7kKG5jjbmjtcM4jG0LYTqqTVVOo8rU5WbY8R1Juvl2LehLjjGSlyBfwwI7l9QRYOlotS7DyuMZT1qqXqcxllZsKRVFiCC3zbs+ubFeU3zMeew76raT2Xu0t2BGb//oNqt88x9Wxl0mtFJH0mVHlbnN4mlVGmUD2vY7taEuPOKIXoFHCJ4+gWRzVyWp4wIcwPRl4vUSZDjqDjsPSFvcqyk/oqKh+Aj3EY+TbNXGBtnXsWz6ZxRxyMhOh2h2mRUODpR9yTEmKb6q97OMZTDDYWjmwINwXgI+hJzhTcu65CgSPEuS7xk++pv1xYUJJDfq6FFaPLmcptNlR19G93cE5n1nL5xsqMcpmGjAYZT7QLJO79TWesA/QEG8pQNAfckskVS8flQUWQzJyHK7gPqh35vmf47rT9PlK7wTQdmb9KYlC5Dcvem+fa6SEm4SGKOaf3/97jU/U76mtZv1K+yvje+rnERFHC1FKqDWL5UtYBrMNoRLYtvzP4RqiBNMHWLlJEuLMo8QZcXpDdMYbqKEowCXz1AQ4M51iHzKB7DBp1ppKe+qSY3Ug81ixR0+R+0hOvz2luIbO3aSWuuFwZSN4s/CTjIKbQ879YvELOzUHSoFlEu/vHnzThi7Hqk7LqSh+o+7LlPkp6Gq4Z9ZmnRHYUcbRHLsONA0H4LiZpFVeazmiLYsM479x0mEi3AELWvLyLzVdXkC5tIfuSvq1B/Lzs5m11GOHUyCiIs9ZjOrIZ+DzTSuGbOxWbO87pQsk6lsQtreSDIb9WwbBVnHYQNibH5FfH7+mlAVd2Ev7VHbpNzV/miCyWDLLH/GtJ2yi2qwtDlM+t7IMLpXNnJsbiPCDRp5+Ajyl2t870c5tnQmZlCZBKs9oIU0DMUXyq6OwxtW6xrVtrl5otPiFF6926WYc42W8dMeqeV8j2y08q3hq52xWM7IVNPbLO2sVjMbLT9HaXUXEctZPqHhkq6WgWMTdt2AyfRmF4yYDTsyXKHuhO+Ajit0lE2Spo/CatbjH0YCWVdLF9gq3tuZFW4LmG36lc5evM282nFXWq4AQoP47m99x8TgpIZFYEaaT5qE/eQXlNTN6nKMwoIcCSbgRIMLWoqKTW5kbQlPDh3rSEZdMc4/BRfacMFs7Ke+2jcV35Von4La9Yi6Cm6kTd8uHqPby/IWm7LzPMV0x4KXZmOl9l5fQCYa2D9yUbMIUvdt1xlAehV1y4dew7T+c3jrmMF+ik7IEkzj5vOGa+8mdi/RDanWbQlWPHQfJ1lk+NvgsqaMLGfaDk/AVdq774oq9fdjZ+KsAQXZQkDsLV/ZjPEMbKWOiTA1Vx3DJEEavTwehBNPDTnx2si93eUGo7pY4s/PDU1YrBt5J7Z08eJieTFN6dL2ZvFqe2SzeM3GV3UM9UWZk1uTBVGIbtrA+Urm6jLQI9p/nIS5ZC1n2yPNMAqbyQk2DptJu2VSL/0cwiy81l4N3w3+alvLtKH/uPN81HVlJ3invTm+G7zTtpZpQ/9x53mn68pO8A6+8r4bfINbyh7Wkg87zy+kGzvDK/9/e1fW4zaOhP/KYv5AMO+9C3TODZBr0p2ZR0Fts91CbKshyzn2169EXTyqiiWZpKROXoK0WWQd/EgWKbKqCY+Q2EKP7amAKGlktCTofg7zPZ/bix7Q0irC4VaTz4cXM66dGnvMecJo1tb70yqMgy4qaiEln04YBoGmSWKgkR3FEcMnK2zjAsDq+qqPAYHq+F8QpKMBMjdAHREjY593jppBF3XM5RogEcEX9cBrKuAWB7YVzYBLBF2sGe9i4M070736UaexSffX5/KhbnEjC40ledEzHqWBJhdNuPoZkFRvDCBnw+LrvDgf5KGsb+Dh3xd7nlpLyq+rx8Wgy3pAIPN8xUZBk1zMgkH789PAAZBAbdFASOS/TYpqsvO0LNZD57U/R1mIJENbhEDQwQwTEDwsRoNcS5hCALnH91hIvMww6fD7Mu6MI8kX4HxgYl/SdSEhFN17GdmvUf0XKdZsIJJhlANckqN8Fy3Xqmyk/WXtd+MaNTiMdIPP3Pur2DTHBU1MN5ePmtk93C4805dTuhP/zSppip8JHFdqoWG4VMlBeXSCJxOIS1OLw3f2SFwg1oCxMn6O+AUgxp9T5sKXlHDehU/eiFsyonopbQkCXoWLhp1BkTUBZvkxTOaBTcR4JeOAM3eUkjfZffkiLbbJp3OdGuYktv9k5QOiw/RudDxL6qTQGht+DDeTsPvpQlD0urAwAXbF7BDRfB1YoaldGmiugSQH5Yng9IxCgCe0jfZ7uorLwtoXdSgs1BtaEtSi+UiTcab16Lxu04e8FMv3s2spbQmaX9eNoUGR5fvZn8X3Cu2f8qqBUzc5reJ8EhBcEwcsX/3ZJaTVKk4yIZx5XQQd7vhy4BJtGpqKFa1b5g3sV+cxWPRK1glpBesLmFciGoB6PZa/jHWiyhMjWO6pvRYYOdaBg14QLM4ou2M9gYh9LNFXmPcjbReaMl4gm9+f6f8wjD6jt1Kei2OdTEcEuGscyB9WRDZcG63kCfjAqj6r8H77BzzxZ5Xf4bHQ6WVO3zaXgrxIi8ZleX4+bveC/DzRflZRKIEvXmrpKJiYEhkuiVkY8osWZoswALJ04/AcRFwOhFaxSi0BZjHXqknomn25srC1/G/wSwBWxC/yk3A194f5lv/No9hk9+3rw+uyLLK7cylWgDFSfkgujHLt6KPVWwMUYdE/PtZ/Jhy91KnHjQceEEJNjYSuDCk7wjAnUdMhdOkMSinL2kyADSx0cuVrGxo4v+TcfDHYZp+wKQ3mxnznOtymO3cMs6V4EYPMkCxq6RPxFhSVRngIM4YfA8DliLhD9ynQmb8CxLgdPifKKvLZgfZ3WmTpsezn1hf54S47SsIETxmvvodRibR3MFrBqGNBt2wQtEjyME+8UAMFRRulKEcKVewl4281e/PFAzX+unspRufeqjPg+de5Kql66csxwzGqEalY0Aue5PSIG2jR0FPFXhr+1jsnciD5ZGe/NU95HeTcR5IWIdDlsY8hF4vGqMeOHmC5mLNGU4m/0/25BymtYRhcxEWuVJcjZksYEsOT8BQGyo22I/BsNjA3rGd3Jzkuw7odw9V5f8lNenjci5f59+M+T/Enwj2Bdv7S/7hwNMDqzY8E3fizYeE2E0Wl30Zocdid960kETf+usREkFWsl16TRfn1SQRbH/ThMFOlWwCslr+lnAdEEbeN4/CzkI3icB21vUi8fCBZko+7zbw+YNkqcZhq3bkgmHkFmNMF+o0Smuni8NHv5V5n+7KOdxv8eUOsacrQjBbSIn46zyacuvJnt1mfUTxPN1/fHm/KfPP15nx32hRZcwd0Fa8pEOH1HNAYzerfVmCajXH8F4e75XtuywNdxPX5EszNvUpf399n++oXkUSKO98z1Bsafl3749NBFQ6zuR+1yzQJQRc5HAoWbzsdxRNbnWydVrEuVfp9qwD9vgJquhPJ6yI/xEOJztxY4/Si1ePDUIjDUe2MpQDkNv8Nj4XAY+iK+VyMyq/8Vpn8Xb5LlP/XHYU7Gwad5iuYZVE8XIUrJk0o34WyWRigqUqxvBhdxEVAbRWb9flQFXPeGgun2aesv87iLLavDmm2T+S/1xs6u45GpGUP1gqiYEoR3riDovweBFO4qcLgStWIw06Vb76wTw9i8zU/mzfkrJ/xecui1CYwuzROMndQLVq0kHfgHPYMA0hEQ9acZ1adMc7d5lxUGu8+pT9lrNW3x6xu11PIVdyVNxkbAevMwnXHUbX0YfFUemIx+OgiN9Ma+ernYJESQaVI0cKGhJ4GEL+gHBMh2qw7Gz7f5Zt0n/1PbDsZk3fpcXe2dsxK7/cEancPP0ZBoCW2LoxdGgR1sKnCoM3WicO0k3BGfPneXIa732nuK5/GfnI1+8j2695n8S0T3/8r9o/35/2xDjJad8nQuDxR7zFV/V7WbtdtnmD1nbBr2wDR15eNvnJlywF8cQaIGDfcL8Jcp1GUI1hOj4ziPScOtYI/UVhpZHinzwYpv3cGWmWWjiat8nx3Vvb57kV+kBtF5qymVIk9kamstbsp6u9PaLpCTT2KXWQY1f//lJ9KfD7qKKw+bH6Mc+VpPJQ8TVO9ogsEUCfbbED6IL6fRs5HSpXY85HKWm1S+/0JzUeoqUexiwyj+v/1fWR8PuoorD6MeCt9ApQ8zUe9ogsEUCfbfK53vt//nZfZcfdZbPJiy976GfWib/lM/ppfbhU+oTmKtvwonnPgq/7h+nj6LgpiP9fTWN3a/RznJc0lIPO16RuUXiq4BhGXcYIw6fhq1jMr/pnFuqcuTwcY0QHV/uU8gZr/cfJYPK3vOct4EMV9xPJKBoCpR1VVQxTdWX++Fa+z4lS+TMv0Lj3ZH/vqWjeiBALJ/PGvphQN2HOzeRCH9N9/bO/yqufTOzvWjzUN6dzcr0AtCdxVIKnctcZKyhGNKQuXOc6SZORs/mV2ai/iWe0PRRCDodTB4UVaip28E2BxGIogDkOpy0TZpjwXAjJRVwKaqCvk9QDBxSAg+iNpiZL3qcxLxO6fOo1jVohmy4p2lUZF9ZpG6BJBC4tt89aKQaYaBc/aBGosCsreHRXb4G3F9+nxfJ/KviJmIp2KkkOlZMviEMLNXadwDVTTsbTHq0kBDluTiMmW4EczcnLon2RaDPoSqP2+0KVAPaDg+a0rAcXvCh3Nd8k434vyId8CXEwCiJlJ4+JZVsOmgu63yj+CxrxRDnLUSRwMhw8VFq+hCGIzlDo4DFeXLA5DEcRhKHVxqO/uiJuykDvZU5NfBeAGkoGcQUqHFMMRq8V5KIK41aXu2VE5DrEnRaUQnAuVcgYfhAPeNnuqaQLKodNNU0xNOQ2FSwdRHLLTqXLVu8MaWx+LBNTNonJwfvWjcmuP6f76XD7U24kmGxEqBU0OSUTXcEgnX/wig10pg/jK4lPCGvCS9jZ/zDYYn7aQYNRScDhhTMj2WwpO+2+K/PyIMWkLCU4thYNTez/dYtL+DrXfFjHd2C/1K83+kjDqx+pklCOrUzqkeJPdV25jsXVIAZNBUsCUTCkIzjQ3Xjcii4BShnYna2MqKT/kJTSTKmUok6bYweSz+F4p/CnPjuUJ7zCQCmIMEjL8L2TbNRRhPhdrg9URIj2mF1OcWP32WVTbgWO9ARTgFGyUw2bUSJzqmVmFARVNElhNk4q3l8NSGGK7Ooye2t8h+SS5Oz06M6RtL5IctB1ZY5J0bLnGSMTtU5mODetAWUj0lizn8SFz0GD8yUqEXGS9afLyhXScWxk5FcaepzAE4kkyGilIlgGuWVryEb3W1nB5RH2wc9sL6otAz6cvdXBQog1bLJQyiIdS7DwpyMEz0fZ3+GQgZ5y6SqoeZHD7fTHKhovS26q+kB15B24NjXLQZjqJ68ADi/xmn39glOBxCEY84qTxVhwe9yk4UmEy18njQMn8VEBIYJNQnw7YnLuFAWdsUVDrC5ftG3EU1TCjJkebBNwaWFSuM9HNHj0PUMrAc9Gh2MHkS4EzUcogJkqxa6Koam/Pe3Gbnr5CE4VWDE4UGoXLbkNUPttuQxlot6HYNRpFeqoGzj8i2z1ALrpRDo4/nYTH8GVW7SJO8DRkkxBsFSrnkVxRiOMGPD3vi+CjuK6Uc3rimGMBGuIsZdTMakbcAiYWnYA69zJInWNciZgDjHKlFB7nCgGfVROAimLXUDhYNkTOBePwmGY7qEuHIniB6EpdR6lasBr76FQrBo9KNQrnOJQ9S63AJgU8Cg0ixjeDd6IsReEYJxgh9j0BonXIooXksQTQSuErKAqBCz12XBgbRjYNiCebbCxzbF+CEbLE4O1F0CgOwOEQQgkfEyHEI8VhyMETgPcJTw8pYLEGaNCPdzqZU+16sG7xCz8mAayyTuNCYZGfTlXje5yrTQIiz6JymhpalNDFiLMIVf8rkd1iVwL6f12ha4+Y/iBupWil4P5QJXCxQj5bEV+seJ+qus8mhCI2CfX9Jbl+fNxnYnubt/SZcH9F7irjoLMoeDK05G4J9PsQ+A0OhM59xeKzOFVTsLxby7hB0n5Wxi+qWBTU1+mWiNER5pdlxwdympzz6TqpSdlnh/1VIt53e/73ey0x3dijTM4JNPMgOhnoxkoBBADAhAFICZkAasblnf45nX1+pZZiV3h6AoanirPSSjGflMvKfmtj29ciwa6m6FRjetjVrYy+tBgqt8ixa65Jf5tVIQbvu/aU5jV35Z2AfnW24onevoXeF4DVjSLz1YKu4gT1u4XHrT78DAF6qGHLvxj1+3uyRL9bNP573PRLZEXUbRqvJuW2JDftDTtbc041XCnzjr1UCrs/D9YEzWIXhjXPbVrsBDgiONU89fnCzNM5nKOwY1YKiRxo7rHKQhpmDGrMSv6n1JnMAjy7OJEmASuExAnwvkRrhHowMnmxTfSXIehSq9MRygAvVRotiBcoU3E1Xe1+HR2mJlR1mzbERIo8ulHV9ziNmqq5fS2LNJizFckE2nMgwuUC6fy7XdBDI1mZfEA0ueeNx1AqCxQCeB3PakGoQBsCy4OYyT1IQPJgAyWySfTTtaQ7XhPtmRztvvMr42rDz7CkxvTjKqIV49wRaAx7JBbEgLirxq9MrE6Asoh6SzGZ+oQt6dsFzAMSBjAF9CyvMQH52m686u0RMqW0SeJfXeM4XNbDHmVOV9EwHa6oTui9lyKq3h+D918KiMkTJyZ63HjT23Q58l4XrAkZwCoLYQh8EsSJvfTjEszwPNvvq4m0b5kwgkEazgQsDF2gdBecaWga19qiDTkEjHf4WgPY4/rxZoAeGQ/ZIQBb0BVwtcwH2FIf7HG1XpN4WN20wnkoPd403dty0hw2UQgTmO/jZU307ft4Vbun4aSqNlEIVc0H7LLm8OPlm6t8vyfV1AlCqKi+bm/2TNDr9WmqNQ/sk6ZFWDmV5EIhrRp6cIC+HvLsf4KK5oUC9Us+5cbwKhLKIa/5GxUdL/TJlqDbDWCrZPQB76bEHSFeRfcCZylMKbhIE4L3SVjO9Ej0efAmXEaPYxqGex0dTXOZiIqiQbqjvIoh0MSJLCJbGxUhZLzp+jghpJ0AqhBGsQKayKrKr37UlTc83foaZMEU1u6oDhrD91Anqpyo0U0QfVUah8haDJVBZDA2il3brui3Z9smyW5taC4WdJ7elCNRbZYasQqdR9Ejj1sZ6IRxqgLS+T9S0cL7yFpw9J6pilJzk0ERYloKpx4UbSgZ7lfgFzngCsQNhosvckCxjbRWyFhFnkzT2p1pFzDB8Ph+XYQ5+vhJuA1MEr+KW7GfhnqeDlAG+Ylv0jaR/y/R4VXtIm4ln6r92UN6Ett/svJB4WAr7qriTR2trhlTTFZF44VNN4Q2bof2cTPAFTwpAtZERzwrWJsn03xR+51tH72W33lhLvP0sd4cE6JCEmBCVOPUDfXAEHTjVQSiypGuEEkfwjEioujJRjhh8fyYxTku3JX8omMe03QB+/AxYVD4VdoMaXjT3aLxdL1XjUeYDO3iWuqEngQHa1rrKxk7cepGqLuR5NzymYRr2vNpUSAdEx5IGWaqA6JbtiOZClp5wQE3o7NRWv/9HfrahBmEM1FzmUAjHCd37gjsjCvq3gBPomKMfDj8aDv6HSFFPRiIGhk4cYjBMbspiA0jSut/3xjbDGRYWcbFbkdF/wZixc1VW2PGcp2AICJsLRJzFwTXhGYI/LjtwjMIo1U9BDDRNhLK1zdaaeZjIUy2FtlUCx0BdqQI8pYLTh1smrDjYagtqKVBjEHcU8GpnUoh2gBqLMMkROho7itLdhPEqbuvB5iMsNuqRccEzg5iYvcizqkdbIiuzZx6IslJNtWawA0E5byUpqByWa7VxBNgGh+bHGuFNxHpTrLrOpUnteb5jYs0o4w7maBs2Sal24liFE67WuxOqnE4Hud0R4g5UUafDcMGUEhu0sPjXgyZEHDFDUrCdTHyMTRuC5JrIaLKfSoG7V4spDJC6T5Imn5z1koxIavj2SMuUZ9Yu2wi/6tVeFWtY832rNS9aKNVgi3aU09mvZhllEGetCmMTOaOs/gx1eOczbskopt25XGf8OIPTp9CHuE764Q4yXekj5ENcXPB+DMTMTBdVfwPz3lN1Cf7SIjPgjaR/++BVsKSpiaai2Ti3W72cCGoQwwUNPvHTX/X23PP60k6ktdFfqDsQZGHMAicj6QdVWR6kYtNcZuPMIRCvHYzKFlNEivDCTArEOTEOIczsDSjnU6rgrWDteHZJBQoQLoQeIijtpKdJNETw9iqo7S4ElCyGqkFlYTGOACwsq+0+388rcqEqzNgmpIESKICXKXh1iVQguV9aeDiSuVCt2UfBTGTsky5gKWnN0neHrMyS/fE5UqqAq7ktIuVcBKXm+YuliMxy+XG6C6P2qzcdkHrBlKXbAm+lcrLrDMxHIyatsYdCwamxhW8MBAMlJ6nacKZcWeKOej1Kfi6ZK5Hftahdv9kpXpIavfgRX48lUWaVfND7Y32+nXBj27zBKtPnDr45+U294QIStDWE021oe5F3WkzPHaTVvDnKKsbVZnK4xov2oBKahEu3LRsJMA5xmUthscskIylOeogsqxcZtguDBWIQ5iQFp8d6GoGxZUMMtz+15LO2Ba6sMXwiAJy7sg2qGQ6lxm2i/YFIgompMVnxxObQXEzPRB7XbTSCgGrgK+2I6y1SLqlZolwpVDyYPYhTBm8oFL0tFqjYqLNaxR1KZ7koDl9kWmtRvb1+O7OxUZu/3I7cQNlsE+ZHpW/etY0Upu+6mdR9GVXz5qEZe0P1Z/V1rXa+b3Pt2J/kr9ePft8rmofRPPXS3HKdkMTV1WbRyFTKw6NdjRvj/d5t/8zJOpIuuI+53KZbtMyvS7KrA5YXxVvKu9TpuKTJzX18dmd2L49fjyXj+eyUlkc7vba7vLqGc3/6pkl81VzC/3kQ4VKzKxSQXw8Pj9n+20v9+t0fzJ21FgTLyrrvxHV701fVoOzFLuffUsf8iOzodZ8L8WjOG6rQdcloT59PN6k38QU2b6cxDuxSzc/P9Whs+XBE9aIuyN0s1+9zNJdkR5ObRtD/erPCsPbw4///B8qxosOQPAHAA== - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.Designer.cs index 1cf913c0e4..cf72dff95e 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class NewCategoryProperties : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201504111815146_NewCategoryProperties"; } + get { return "201504131412183_NewCategoryProperties"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs b/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.cs similarity index 82% rename from src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs rename to src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.cs index 67b8536692..10ffae4c76 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201504111815146_NewCategoryProperties.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.cs @@ -11,12 +11,10 @@ public partial class NewCategoryProperties : DbMigration, ILocaleResourcesProvid public override void Up() { AddColumn("dbo.Category", "FullName", c => c.String(maxLength: 400)); - AddColumn("dbo.Category", "BottomDescription", c => c.String()); - - AddColumn("dbo.CheckoutAttribute", "IsActive", c => c.Boolean(nullable: false, defaultValue: true)); - - AddColumn("dbo.ReturnRequest", "AdminComment", c => c.String(maxLength: 4000)); - AddColumn("dbo.ReturnRequest", "RequestedActionUpdatedOnUtc", c => c.DateTime()); + AddColumn("dbo.Category", "BottomDescription", c => c.String()); + AddColumn("dbo.ReturnRequest", "RequestedActionUpdatedOnUtc", c => c.DateTime()); + AddColumn("dbo.ReturnRequest", "AdminComment", c => c.String(maxLength: 4000)); + AddColumn("dbo.CheckoutAttribute", "IsActive", c => c.Boolean(nullable: false)); if (HostingEnvironment.IsHosted && DataSettings.Current.IsSqlServer) { @@ -28,13 +26,11 @@ public override void Down() { // inverse of LatestProductLoadAllPaged.sql does not make sense to me - DropColumn("dbo.ReturnRequest", "RequestedActionUpdatedOnUtc"); - DropColumn("dbo.ReturnRequest", "AdminComment"); - - DropColumn("dbo.CheckoutAttribute", "IsActive"); - - DropColumn("dbo.Category", "BottomDescription"); - DropColumn("dbo.Category", "FullName"); + DropColumn("dbo.CheckoutAttribute", "IsActive"); + DropColumn("dbo.ReturnRequest", "AdminComment"); + DropColumn("dbo.ReturnRequest", "RequestedActionUpdatedOnUtc"); + DropColumn("dbo.Category", "BottomDescription"); + DropColumn("dbo.Category", "FullName"); } public bool RollbackOnFailure diff --git a/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.resx b/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.resx new file mode 100644 index 0000000000..8ebb7814c7 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index ec387362a7..769d9178be 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -240,9 +240,9 @@ 201502120858030_Licensing.cs - - - 201504111815146_NewCategoryProperties.cs + + + 201504131412183_NewCategoryProperties.cs @@ -478,8 +478,8 @@ 201502120858030_Licensing.cs - - 201504111815146_NewCategoryProperties.cs + + 201504131412183_NewCategoryProperties.cs From 47db95a75cbb5ee86e6d4ae3cfb1636416b4b68b Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 14 Apr 2015 21:36:06 +0200 Subject: [PATCH 0038/1256] Promotion feeds now exports the preselected price (including price adjustments and overrides) --- changelog.md | 3 +- .../Catalog/IPriceCalculationService.cs | 7 + .../Catalog/PriceCalculationService.cs | 184 +++++++++++++++--- .../Controllers/OData/ProductsController.cs | 2 +- .../Plugins/FeedPluginHelper.cs | 2 +- .../Catalog/PriceCalculationServiceTests.cs | 19 +- .../Orders/OrderProcessingServiceTests.cs | 13 +- .../OrderTotalCalculationServiceTests.cs | 15 +- 8 files changed, 209 insertions(+), 36 deletions(-) diff --git a/changelog.md b/changelog.md index 5ba3b0a719..76001045a7 100644 --- a/changelog.md +++ b/changelog.md @@ -16,7 +16,8 @@ * (Developer) Added `BeginTransaction()` and `UseTransaction()` methods to `IDbContext` * #588 Alternative localized category name used as title for category pages * #592 Add a second category description displayed beyond products on category page -* Resolves #672 Option to automatically create mutual associations for cross sell products and related products +* #672 Option to automatically create mutual associations for cross sell products and related products +* Promotion feeds now exports the preselected price (including price adjustments and overrides) ### Improvements * Perf: product list rendering up to 10x (!) faster now (depends on page size and view mode) diff --git a/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs index 9777824f0a..703033f375 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs @@ -98,6 +98,13 @@ decimal GetFinalPrice(Product product, IList bundleItems, /// The lowest price. decimal? GetLowestPrice(Product product, IEnumerable associatedProducts, out Product lowestPriceProduct); + /// + /// Get the initial price including preselected attributes + /// + /// Product + /// Preselected price + decimal GetPreselectedPrice(Product product); + /// /// Gets the product cost /// diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index 55f36117ce..b55750ac4f 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -1,12 +1,15 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.Linq; -using SmartStore.Core; +using System.Web; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Discounts; using SmartStore.Core.Domain.Orders; using SmartStore.Services.Discounts; +using SmartStore.Services.Media; +using SmartStore.Services.Tax; namespace SmartStore.Services.Catalog { @@ -15,8 +18,6 @@ namespace SmartStore.Services.Catalog /// public partial class PriceCalculationService : IPriceCalculationService { - private readonly IWorkContext _workContext; - private readonly IStoreContext _storeContext; private readonly IDiscountService _discountService; private readonly ICategoryService _categoryService; private readonly IProductAttributeParser _productAttributeParser; @@ -24,19 +25,24 @@ public partial class PriceCalculationService : IPriceCalculationService private readonly ShoppingCartSettings _shoppingCartSettings; private readonly CatalogSettings _catalogSettings; private readonly IProductAttributeService _productAttributeService; + private readonly IDownloadService _downloadService; + private readonly ICommonServices _commonServices; + private readonly HttpRequestBase _httpRequestBase; + private readonly ITaxService _taxService; - public PriceCalculationService(IWorkContext workContext, - IStoreContext storeContext, + public PriceCalculationService( IDiscountService discountService, ICategoryService categoryService, IProductAttributeParser productAttributeParser, IProductService productService, ShoppingCartSettings shoppingCartSettings, CatalogSettings catalogSettings, - IProductAttributeService productAttributeService) + IProductAttributeService productAttributeService, + IDownloadService downloadService, + ICommonServices commonServices, + HttpRequestBase httpRequestBase, + ITaxService taxService) { - this._workContext = workContext; - this._storeContext = storeContext; this._discountService = discountService; this._categoryService = categoryService; this._productAttributeParser = productAttributeParser; @@ -44,6 +50,10 @@ public PriceCalculationService(IWorkContext workContext, this._shoppingCartSettings = shoppingCartSettings; this._catalogSettings = catalogSettings; this._productAttributeService = productAttributeService; + this._downloadService = downloadService; + this._commonServices = commonServices; + this._httpRequestBase = httpRequestBase; + this._taxService = taxService; } #region Utilities @@ -54,8 +64,7 @@ public PriceCalculationService(IWorkContext workContext, /// Product /// Customer /// Discounts - protected virtual IList GetAllowedDiscounts(Product product, - Customer customer) + protected virtual IList GetAllowedDiscounts(Product product, Customer customer) { var allowedDiscounts = new List(); if (_catalogSettings.IgnoreDiscounts) @@ -66,10 +75,12 @@ protected virtual IList GetAllowedDiscounts(Product product, //we use this property ("HasDiscountsApplied") for performance optimziation to avoid unnecessary database calls foreach (var discount in product.AppliedDiscounts) { - if (_discountService.IsDiscountValid(discount, customer) && - discount.DiscountType == DiscountType.AssignedToSkus && - !allowedDiscounts.ContainsDiscount(discount)) - allowedDiscounts.Add(discount); + if (_discountService.IsDiscountValid(discount, customer) && + discount.DiscountType == DiscountType.AssignedToSkus && + !allowedDiscounts.ContainsDiscount(discount)) + { + allowedDiscounts.Add(discount); + } } } @@ -90,10 +101,12 @@ protected virtual IList GetAllowedDiscounts(Product product, var categoryDiscounts = category.AppliedDiscounts; foreach (var discount in categoryDiscounts) { - if (_discountService.IsDiscountValid(discount, customer) && - discount.DiscountType == DiscountType.AssignedToCategories && - !allowedDiscounts.ContainsDiscount(discount)) - allowedDiscounts.Add(discount); + if (_discountService.IsDiscountValid(discount, customer) && + discount.DiscountType == DiscountType.AssignedToCategories && + !allowedDiscounts.ContainsDiscount(discount)) + { + allowedDiscounts.Add(discount); + } } } } @@ -116,7 +129,7 @@ protected virtual IList GetAllowedDiscounts(Product product, var tierPrices = product.TierPrices .OrderBy(tp => tp.Quantity) - .FilterByStore(_storeContext.CurrentStore.Id) + .FilterByStore(_commonServices.StoreContext.CurrentStore.Id) .FilterForCustomer(customer) .ToList() .RemoveDuplicatedQuantities(); @@ -139,6 +152,100 @@ protected virtual IList GetAllowedDiscounts(Product product, return previousPrice; } + protected virtual decimal GetPreselectedPrice(Product product, ProductBundleItemData bundleItem, IList bundleItems) + { + var taxRate = decimal.Zero; + var attributesTotalPriceBase = decimal.Zero; + var preSelectedPriceAdjustmentBase = decimal.Zero; + var isBundle = (product.ProductType == ProductType.BundledProduct); + var isBundleItemPricing = (bundleItem != null && bundleItem.Item.BundleProduct.BundlePerItemPricing); + var isBundlePricing = (bundleItem != null && !bundleItem.Item.BundleProduct.BundlePerItemPricing); + var bundleItemId = (bundleItem == null ? 0 : bundleItem.Item.Id); + var attributes = (isBundle ? new List() : _productAttributeService.GetProductVariantAttributesByProductId(product.Id)); + var selectedAttributes = new NameValueCollection(); + List selectedAttributeValues = null; + + foreach (var attribute in attributes) + { + int preSelectedValueId = 0; + ProductVariantAttributeValue defaultValue = null; + + if (attribute.ShouldHaveValues()) + { + var pvaValues = _productAttributeService.GetProductVariantAttributeValues(attribute.Id); + if (pvaValues.Count == 0) + continue; + + foreach (var pvaValue in pvaValues) + { + ProductBundleItemAttributeFilter attributeFilter = null; + + if (bundleItem.FilterOut(pvaValue, out attributeFilter)) + continue; + + if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) + preSelectedValueId = attributeFilter.AttributeValueId; + + if (!isBundlePricing && pvaValue.IsPreSelected) + { + decimal attributeValuePriceAdjustment = GetProductVariantAttributeValuePriceAdjustment(pvaValue); + decimal priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, out taxRate); + + preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); + } + } + + // value pre-selected by a bundle item filter discards the default pre-selection + if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) + defaultValue.IsPreSelected = true; + + if (defaultValue == null) + defaultValue = pvaValues.FirstOrDefault(x => x.IsPreSelected); + + if (defaultValue == null && attribute.IsRequired) + defaultValue = pvaValues.First(); + + if (defaultValue != null) + selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); + } + } + + if (!isBundle && selectedAttributes.Count > 0) + { + string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _commonServices.Localization, + _downloadService, _catalogSettings, _httpRequestBase, new List(), true, bundleItemId); + + selectedAttributeValues = _productAttributeParser.ParseProductVariantAttributeValues(attributeXml).ToList(); + + var combinations = _productAttributeService.GetAllProductVariantAttributeCombinations(product.Id); + + var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml)); + + if (selectedCombination != null && selectedCombination.IsActive) + product.MergeWithCombination(selectedCombination); + } + + if (_catalogSettings.EnableDynamicPriceUpdate && !isBundlePricing) + { + if (selectedAttributeValues != null) + { + selectedAttributeValues.Each(x => attributesTotalPriceBase += GetProductVariantAttributeValuePriceAdjustment(x)); + } + else + { + attributesTotalPriceBase = preSelectedPriceAdjustmentBase; + } + } + + if (bundleItem != null) + { + bundleItem.AdditionalCharge = attributesTotalPriceBase; + } + + var result = GetFinalPrice(product, bundleItems, _commonServices.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem); + return result; + } + #endregion #region Methods @@ -183,7 +290,7 @@ protected virtual IList GetAllowedDiscounts(Product product, public virtual decimal GetFinalPrice(Product product, bool includeDiscounts) { - var customer = _workContext.CurrentCustomer; + var customer = _commonServices.WorkContext.CurrentCustomer; return GetFinalPrice(product, customer, includeDiscounts); } @@ -342,7 +449,7 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa } } - decimal lowestPrice = GetFinalPrice(product, bundleItems, _workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); + decimal lowestPrice = GetFinalPrice(product, bundleItems, _commonServices.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); if (product.LowestAttributeCombinationPrice.HasValue && product.LowestAttributeCombinationPrice.Value < lowestPrice) { @@ -388,7 +495,7 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa foreach (var associatedProduct in associatedProducts) { - var tmpPrice = GetFinalPrice(associatedProduct, _workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); + var tmpPrice = GetFinalPrice(associatedProduct, _commonServices.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); if (associatedProduct.LowestAttributeCombinationPrice.HasValue && associatedProduct.LowestAttributeCombinationPrice.Value < tmpPrice) { @@ -404,6 +511,37 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa return lowestPrice; } + /// + /// Get the initial price including preselected attributes + /// + /// Product + /// Preselected price + public virtual decimal GetPreselectedPrice(Product product) + { + if (product == null) + throw new ArgumentNullException("product"); + + var result = decimal.Zero; + + if (product.ProductType == ProductType.BundledProduct) + { + var bundleItems = _productService.GetBundleItems(product.Id); + + foreach (var bundleItem in bundleItems.Where(x => x.Item.Product.CanBeBundleItem())) + { + // fetch bundleItems.AdditionalCharge for all bundle items + var unused = GetPreselectedPrice(bundleItem.Item.Product, bundleItem, bundleItems); + } + + result = GetPreselectedPrice(product, null, bundleItems); + } + else + { + result = GetPreselectedPrice(product, null, null); + } + return result; + } + /// /// Gets the product cost /// @@ -438,7 +576,7 @@ public virtual decimal GetProductCost(Product product, string attributesXml) /// Discount amount public virtual decimal GetDiscountAmount(Product product) { - var customer = _workContext.CurrentCustomer; + var customer = _commonServices.WorkContext.CurrentCustomer; return GetDiscountAmount(product, customer, decimal.Zero); } diff --git a/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs b/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs index 02caa63ae3..e0a6d49da2 100644 --- a/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs +++ b/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs @@ -209,7 +209,7 @@ public IQueryable GetProductBundleItems(int key) } else { - result = _priceCalculationService.Value.GetFinalPrice(entity, null, _workContext.Value.CurrentCustomer, decimal.Zero, true, 1); + result = _priceCalculationService.Value.GetPreselectedPrice(entity); } return null; }); diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs index 936d8f5124..938337a7f4 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs @@ -264,7 +264,7 @@ public string GetProductDetailUrl(Store store, Product product) public decimal GetProductPrice(Product product, Currency currency) { - decimal priceBase = PriceCalculationService.GetFinalPrice(product, null, WorkContext.CurrentCustomer, decimal.Zero, true, 1); + decimal priceBase = PriceCalculationService.GetPreselectedPrice(product); if (BaseSettings.ConvertNetToGrossPrices) { diff --git a/src/Tests/SmartStore.Services.Tests/Catalog/PriceCalculationServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Catalog/PriceCalculationServiceTests.cs index 8c693c5b20..e6771c6599 100644 --- a/src/Tests/SmartStore.Services.Tests/Catalog/PriceCalculationServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Catalog/PriceCalculationServiceTests.cs @@ -11,13 +11,15 @@ using Rhino.Mocks; using System.Collections.Generic; using SmartStore.Core.Domain.Stores; +using SmartStore.Services.Media; +using System.Web; +using SmartStore.Services.Tax; namespace SmartStore.Services.Tests.Catalog { [TestFixture] public class PriceCalculationServiceTests : ServiceTest { - IWorkContext _workContext; IStoreContext _storeContext; IDiscountService _discountService; ICategoryService _categoryService; @@ -25,6 +27,10 @@ public class PriceCalculationServiceTests : ServiceTest IProductService _productService; IProductAttributeService _productAttributeService; IPriceCalculationService _priceCalcService; + IDownloadService _downloadService; + ICommonServices _commonServices; + HttpRequestBase _httpRequestBase; + ITaxService _taxService; ShoppingCartSettings _shoppingCartSettings; CatalogSettings _catalogSettings; @@ -33,8 +39,6 @@ public class PriceCalculationServiceTests : ServiceTest [SetUp] public new void SetUp() { - _workContext = null; - _store = new Store() { Id = 1 }; _storeContext = MockRepository.GenerateMock(); _storeContext.Expect(x => x.CurrentStore).Return(_store); @@ -47,11 +51,16 @@ public class PriceCalculationServiceTests : ServiceTest _productService = MockRepository.GenerateMock(); _productAttributeService = MockRepository.GenerateMock(); + _downloadService = MockRepository.GenerateMock(); + _commonServices = MockRepository.GenerateMock(); + _httpRequestBase = MockRepository.GenerateMock(); + _taxService = MockRepository.GenerateMock(); + _shoppingCartSettings = new ShoppingCartSettings(); _catalogSettings = new CatalogSettings(); - _priceCalcService = new PriceCalculationService(_workContext, _storeContext, _discountService, - _categoryService, _productAttributeParser, _productService, _shoppingCartSettings, _catalogSettings, _productAttributeService); + _priceCalcService = new PriceCalculationService(_discountService, _categoryService, _productAttributeParser, _productService, _shoppingCartSettings, _catalogSettings, + _productAttributeService, _downloadService, _commonServices, _httpRequestBase, _taxService); } [Test] diff --git a/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs index 1455c6d179..ca52c5a295 100644 --- a/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs @@ -34,6 +34,8 @@ using Rhino.Mocks; using SmartStore.Core.Domain.Stores; using SmartStore.Services.Configuration; +using SmartStore.Services.Media; +using System.Web; namespace SmartStore.Services.Tests.Orders { @@ -85,6 +87,9 @@ public class OrderProcessingServiceTests : ServiceTest CurrencySettings _currencySettings; IAffiliateService _affiliateService; ISettingService _settingService; + IDownloadService _downloadService; + ICommonServices _commonServices; + HttpRequestBase _httpRequestBase; IGeoCountryLookup _geoCountryLookup; Store _store; @@ -109,8 +114,6 @@ public class OrderProcessingServiceTests : ServiceTest _categoryService = MockRepository.GenerateMock(); _productAttributeParser = MockRepository.GenerateMock(); _productAttributeService = MockRepository.GenerateMock(); - _priceCalcService = new PriceCalculationService(_workContext, _storeContext, - _discountService, _categoryService, _productAttributeParser, _productService, _shoppingCartSettings, _catalogSettings, _productAttributeService); _eventPublisher = MockRepository.GenerateMock(); _eventPublisher.Expect(x => x.Publish(Arg.Is.Anything)); @@ -151,12 +154,18 @@ public class OrderProcessingServiceTests : ServiceTest _addressService = MockRepository.GenerateMock(); _addressService.Expect(x => x.GetAddressById(_taxSettings.DefaultTaxAddressId)).Return(new Address() { Id = _taxSettings.DefaultTaxAddressId }); + _downloadService = MockRepository.GenerateMock(); + _commonServices = MockRepository.GenerateMock(); + _httpRequestBase = MockRepository.GenerateMock(); _geoCountryLookup = MockRepository.GenerateMock(); _taxService = new TaxService(_addressService, _workContext, _taxSettings, _shoppingCartSettings, pluginFinder, _settingService, _geoCountryLookup, this.ProviderManager); _rewardPointsSettings = new RewardPointsSettings(); + _priceCalcService = new PriceCalculationService(_discountService, _categoryService, _productAttributeParser, _productService, _shoppingCartSettings, _catalogSettings, + _productAttributeService, _downloadService, _commonServices, _httpRequestBase, _taxService); + _orderTotalCalcService = new OrderTotalCalculationService(_workContext, _storeContext, _priceCalcService, _taxService, _shippingService, _paymentService, _checkoutAttributeParser, _discountService, _giftCardService, diff --git a/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs index 74ff5517ec..711e6763b9 100644 --- a/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs @@ -26,6 +26,8 @@ using SmartStore.Core.Domain.Stores; using SmartStore.Services.Configuration; using SmartStore.Services.Directory; +using SmartStore.Services.Media; +using System.Web; namespace SmartStore.Services.Tests.Orders { @@ -58,6 +60,9 @@ public class OrderTotalCalculationServiceTests : ServiceTest CatalogSettings _catalogSettings; IEventPublisher _eventPublisher; ISettingService _settingService; + IDownloadService _downloadService; + ICommonServices _commonServices; + HttpRequestBase _httpRequestBase; IGeoCountryLookup _geoCountryLookup; Store _store; @@ -81,12 +86,13 @@ public class OrderTotalCalculationServiceTests : ServiceTest _productAttributeService = MockRepository.GenerateMock(); _settingService = MockRepository.GenerateMock(); + _downloadService = MockRepository.GenerateMock(); + _commonServices = MockRepository.GenerateMock(); + _httpRequestBase = MockRepository.GenerateMock(); + _shoppingCartSettings = new ShoppingCartSettings(); _catalogSettings = new CatalogSettings(); - _priceCalcService = new PriceCalculationService(_workContext, _storeContext, - _discountService, _categoryService, _productAttributeParser, _productService, _shoppingCartSettings, _catalogSettings, _productAttributeService); - _eventPublisher = MockRepository.GenerateMock(); _eventPublisher.Expect(x => x.Publish(Arg.Is.Anything)); @@ -134,6 +140,9 @@ public class OrderTotalCalculationServiceTests : ServiceTest _rewardPointsSettings = new RewardPointsSettings(); + _priceCalcService = new PriceCalculationService(_discountService, _categoryService, _productAttributeParser, _productService, _shoppingCartSettings, _catalogSettings, + _productAttributeService, _downloadService, _commonServices, _httpRequestBase, _taxService); + _orderTotalCalcService = new OrderTotalCalculationService(_workContext, _storeContext, _priceCalcService, _taxService, _shippingService, _paymentService, _checkoutAttributeParser, _discountService, _giftCardService, _genericAttributeService, From 93b01e484250fc518d205eea272586ace9d8bb6b Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 15 Apr 2015 13:12:50 +0200 Subject: [PATCH 0039/1256] Web API: minor changes and improvements --- .../Controllers/WebApiController.cs | 25 ++- .../Services/WebApiPluginService.cs | 30 +-- .../Views/WebApi/Configure.cshtml | 77 ++++--- src/Plugins/SmartStore.WebApi/WebApiPlugin.cs | 12 +- .../SmartStore.Web.Framework.csproj | 3 +- .../Caching/WebApiCachingControllingData.cs | 69 ++++++ .../WebApi/Caching/WebApiCachingUserData.cs | 165 ++++++++++++++ .../Security/WebApiAuthenticateAttribute.cs | 21 +- .../WebApi/WebApiCaching.cs | 210 ------------------ 9 files changed, 323 insertions(+), 289 deletions(-) create mode 100644 src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingControllingData.cs create mode 100644 src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingUserData.cs delete mode 100644 src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCaching.cs diff --git a/src/Plugins/SmartStore.WebApi/Controllers/WebApiController.cs b/src/Plugins/SmartStore.WebApi/Controllers/WebApiController.cs index e5b8fcaad1..30c9c98295 100644 --- a/src/Plugins/SmartStore.WebApi/Controllers/WebApiController.cs +++ b/src/Plugins/SmartStore.WebApi/Controllers/WebApiController.cs @@ -5,6 +5,7 @@ using SmartStore.Services; using SmartStore.Web.Framework.Controllers; using SmartStore.Web.Framework.WebApi; +using SmartStore.Web.Framework.WebApi.Caching; using SmartStore.WebApi.Models; using SmartStore.WebApi.Security; using SmartStore.WebApi.Services; @@ -18,36 +19,36 @@ public class WebApiController : PluginControllerBase private readonly WebApiSettings _webApiSettings; private readonly IWebApiPluginService _webApiPluginService; private readonly AdminAreaSettings _adminAreaSettings; - private readonly ICommonServices _services; + private readonly ICommonServices _commonServices; public WebApiController( WebApiSettings settings, IWebApiPluginService webApiPluginService, AdminAreaSettings adminAreaSettings, - ICommonServices services) + ICommonServices commonServices) { _webApiSettings = settings; _webApiPluginService = webApiPluginService; _adminAreaSettings = adminAreaSettings; - _services = services; + _commonServices = commonServices; } private bool HasPermission(bool notify = true) { - bool hasPermission = _services.Permissions.Authorize(WebApiPermissionProvider.ManageWebApi); + bool hasPermission = _commonServices.Permissions.Authorize(WebApiPermissionProvider.ManageWebApi); if (notify && !hasPermission) - NotifyError(_services.Localization.GetResource("Admin.AccessDenied.Description")); + NotifyError(_commonServices.Localization.GetResource("Admin.AccessDenied.Description")); return hasPermission; } private void AddButtonText() { - ViewData["ButtonTextEnable"] = _services.Localization.GetResource("Plugins.Api.WebApi.Activate"); - ViewData["ButtonTextDisable"] = _services.Localization.GetResource("Plugins.Api.WebApi.Deactivate"); - ViewData["ButtonTextRemoveKeys"] = _services.Localization.GetResource("Plugins.Api.WebApi.RemoveKeys"); - ViewData["ButtonTextCreateKeys"] = _services.Localization.GetResource("Plugins.Api.WebApi.CreateKeys"); + ViewData["ButtonTextEnable"] = _commonServices.Localization.GetResource("Plugins.Api.WebApi.Activate"); + ViewData["ButtonTextDisable"] = _commonServices.Localization.GetResource("Plugins.Api.WebApi.Deactivate"); + ViewData["ButtonTextRemoveKeys"] = _commonServices.Localization.GetResource("Plugins.Api.WebApi.RemoveKeys"); + ViewData["ButtonTextCreateKeys"] = _commonServices.Localization.GetResource("Plugins.Api.WebApi.CreateKeys"); } public ActionResult Configure() @@ -83,9 +84,9 @@ public ActionResult SaveGeneralSettings(WebApiConfigModel model) return AccessDeniedPartialView(); model.Copy(_webApiSettings, false); - _services.Settings.SaveSetting(_webApiSettings); + _commonServices.Settings.SaveSetting(_webApiSettings); - WebApiCaching.Remove(WebApiControllingCacheData.Key); + WebApiCachingControllingData.Remove(); return Configure(); } @@ -94,7 +95,7 @@ public ActionResult SaveGeneralSettings(WebApiConfigModel model) public ActionResult GridUserData(GridCommand command) { if (!HasPermission()) - return new JsonResult { Data = new GridModel() { Data = new List() }}; + return new JsonResult { Data = new GridModel { Data = new List() }}; var model = _webApiPluginService.GetGridModel(command.Page - 1, command.PageSize); diff --git a/src/Plugins/SmartStore.WebApi/Services/WebApiPluginService.cs b/src/Plugins/SmartStore.WebApi/Services/WebApiPluginService.cs index a1b51c1bf7..8fb2385a8a 100644 --- a/src/Plugins/SmartStore.WebApi/Services/WebApiPluginService.cs +++ b/src/Plugins/SmartStore.WebApi/Services/WebApiPluginService.cs @@ -1,13 +1,13 @@ -using SmartStore.Core; +using System.Linq; +using SmartStore.Core; using SmartStore.Core.Data; using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Customers; -using SmartStore.WebApi.Models; using SmartStore.Services.Common; using SmartStore.Services.Customers; -using SmartStore.Web.Framework.WebApi; +using SmartStore.Web.Framework.WebApi.Caching; using SmartStore.Web.Framework.WebApi.Security; -using System.Linq; +using SmartStore.WebApi.Models; using Telerik.Web.Mvc; namespace SmartStore.WebApi.Services @@ -40,7 +40,7 @@ from c in _customers.Table join a in ( from a in _genericAttributes.Table - where a.KeyGroup == "Customer" && a.Key == WebApiUserCacheData.Key + where a.KeyGroup == "Customer" && a.Key == WebApiCachingUserData.Key select a ) on c.Id equals a.EntityId into ga @@ -57,7 +57,7 @@ orderby a.Value descending var lst = new PagedList(query, pageIndex, pageSize); - var cacheData = WebApiCaching.UserData(); + var cacheData = WebApiCachingUserData.Data(); foreach (var itm in lst) { @@ -80,7 +80,7 @@ public GridModel GetGridModel(int pageIndex, int pageSize) { var apiUsers = GetUsers(pageIndex, pageSize); - var model = new GridModel() + var model = new GridModel { Data = apiUsers, Total = apiUsers.TotalCount @@ -94,14 +94,14 @@ public bool CreateKeys(int customerId) if (customerId != 0) { var hmac = new HmacAuthentication(); - var userData = WebApiCaching.UserData(); + var userData = WebApiCachingUserData.Data(); string key1, key2; for (int i = 0; i < 9999; ++i) { if (hmac.CreateKeys(out key1, out key2) && !userData.Exists(x => x.PublicKey.IsCaseInsensitiveEqual(key1))) { - var apiUser = new WebApiUserCacheData() + var apiUser = new WebApiUserCacheData { CustomerId = customerId, PublicKey = key1, @@ -111,17 +111,17 @@ public bool CreateKeys(int customerId) RemoveKeys(customerId); - var attribute = new GenericAttribute() + var attribute = new GenericAttribute { EntityId = customerId, KeyGroup = "Customer", - Key = WebApiUserCacheData.Key, + Key = WebApiCachingUserData.Key, Value = apiUser.ToString() }; _genericAttributeService.InsertAttribute(attribute); - WebApiCaching.Remove(WebApiUserCacheData.Key); + WebApiCachingUserData.Remove(); return true; } } @@ -134,7 +134,7 @@ public void RemoveKeys(int customerId) { var data = ( from a in _genericAttributes.Table - where a.EntityId == customerId && a.KeyGroup == "Customer" && a.Key == WebApiUserCacheData.Key + where a.EntityId == customerId && a.KeyGroup == "Customer" && a.Key == WebApiCachingUserData.Key select a).ToList(); if (data.Count > 0) @@ -142,7 +142,7 @@ from a in _genericAttributes.Table foreach (var itm in data) _genericAttributeService.DeleteAttribute(itm); - WebApiCaching.Remove(WebApiUserCacheData.Key); + WebApiCachingUserData.Remove(); } } } @@ -150,7 +150,7 @@ public void EnableOrDisableUser(int customerId, bool enable) { if (customerId != 0) { - var cacheData = WebApiCaching.UserData(); + var cacheData = WebApiCachingUserData.Data(); var apiUser = cacheData.FirstOrDefault(x => x.CustomerId == customerId); if (apiUser != null) diff --git a/src/Plugins/SmartStore.WebApi/Views/WebApi/Configure.cshtml b/src/Plugins/SmartStore.WebApi/Views/WebApi/Configure.cshtml index e5f3224848..67256c2851 100644 --- a/src/Plugins/SmartStore.WebApi/Views/WebApi/Configure.cshtml +++ b/src/Plugins/SmartStore.WebApi/Views/WebApi/Configure.cshtml @@ -14,6 +14,18 @@ Html.AddScriptParts(true, Url.Content("~/Plugins/SmartStore.WebApi/Scripts/smartstore.web.api.js")); } + +
@Html.Raw(@T("Plugins.Api.WebApi.AdminInstruction"))
@@ -22,35 +34,36 @@
- @(Html.Telerik().Grid() - .Name("apiuser-grid") - .DataKeys(keys => keys.Add(x => x.Id).RouteKey("Id")) - .Columns(c => - { - c.Bound(x => x.Id).Width(50); - c.Bound(x => x.Username); - c.Bound(x => x.Email) - .Template(x => Html.ActionLink(x.Email, "Edit", "Customer", new { id = x.Id, area = "admin" }, new { })) - .ClientTemplate("\"><#= Email #>"); - c.Bound(x => x.AdminComment); - c.Bound(x => x.PublicKey); - c.Bound(x => x.SecretKey); - c.Bound(x => x.Enabled).Width(110).Centered() - .Template(x => @Html.SymbolForBool(x.Enabled)) - .ClientTemplate(@Html.SymbolForBool("Enabled")); - c.Bound(x => x.LastRequest); - c.Template(x => @Html.ApiGridButtons()) - .Width(330) - .ClientTemplate(@Html.ApiGridButtons()); - }) - .DataBinding(dataBinding => - { - dataBinding.Ajax().Select("GridUserData", "WebApi", new RouteValueDictionary() { { "Namespaces", "SmartStore.WebApi.Controllers" }, { "area", WebApiGlobal.PluginSystemName } }); - }) - .Pageable(settings => settings.PageSize(Model.GridPageSize).Position(GridPagerPosition.Both)) - .PreserveGridState() - .EnableCustomBinding(true) - ) + @(Html.Telerik().Grid() + .Name("apiuser-grid") + .DataKeys(keys => keys.Add(x => x.Id).RouteKey("Id")) + .Columns(c => + { + c.Bound(x => x.Id).Width(50); + c.Bound(x => x.Username); + c.Bound(x => x.Email) + .Template(x => Html.ActionLink(x.Email, "Edit", "Customer", new { id = x.Id, area = "admin" }, new { })) + .ClientTemplate("\"><#= Email #>"); + c.Bound(x => x.AdminComment); + c.Bound(x => x.PublicKey); + c.Bound(x => x.SecretKey); + c.Bound(x => x.Enabled).Width(110).Centered() + .Template(x => @Html.SymbolForBool(x.Enabled)) + .ClientTemplate(@Html.SymbolForBool("Enabled")); + c.Bound(x => x.LastRequest); + c.Template(x => @Html.ApiGridButtons()) + .Width(330) + .ClientTemplate(@Html.ApiGridButtons()); + }) + .DataBinding(dataBinding => + { + dataBinding.Ajax().Select("GridUserData", "WebApi", new { Namespaces = "SmartStore.WebApi.Controllers", area = WebApiGlobal.PluginSystemName }); + }) + .Pageable(settings => settings.PageSize(Model.GridPageSize).Position(GridPagerPosition.Both)) + .ClientEvents(events => events.OnRowDataBound("onRowDataBound_ApiUser")) + .PreserveGridState() + .EnableCustomBinding(true) + )
} - - diff --git a/src/Plugins/SmartStore.WebApi/WebApiPlugin.cs b/src/Plugins/SmartStore.WebApi/WebApiPlugin.cs index 34974f6652..c85f063e18 100644 --- a/src/Plugins/SmartStore.WebApi/WebApiPlugin.cs +++ b/src/Plugins/SmartStore.WebApi/WebApiPlugin.cs @@ -1,10 +1,10 @@ using System.Web.Routing; using SmartStore.Core.Plugins; -using SmartStore.Services.Common; +using SmartStore.Services.Configuration; using SmartStore.Services.Localization; using SmartStore.Services.Security; -using SmartStore.Services.Configuration; using SmartStore.Web.Framework.WebApi; +using SmartStore.Web.Framework.WebApi.Caching; using SmartStore.WebApi.Security; namespace SmartStore.WebApi @@ -46,14 +46,14 @@ public override void Install() base.Install(); - WebApiCaching.Remove(WebApiControllingCacheData.Key); - WebApiCaching.Remove(WebApiUserCacheData.Key); + WebApiCachingControllingData.Remove(); + WebApiCachingUserData.Remove(); } public override void Uninstall() { - WebApiCaching.Remove(WebApiControllingCacheData.Key); - WebApiCaching.Remove(WebApiUserCacheData.Key); + WebApiCachingControllingData.Remove(); + WebApiCachingUserData.Remove(); _settingService.DeleteSetting(); diff --git a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj index 6df8b31d91..4c750356f4 100644 --- a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj +++ b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj @@ -398,7 +398,8 @@ - + + diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingControllingData.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingControllingData.cs new file mode 100644 index 0000000000..0514ba29e0 --- /dev/null +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingControllingData.cs @@ -0,0 +1,69 @@ +using System.Web; +using System.Web.Caching; +using SmartStore.Core.Infrastructure; +using SmartStore.Core.Plugins; + +namespace SmartStore.Web.Framework.WebApi.Caching +{ + public static class WebApiCachingControllingData + { + private static object _lock = new object(); + + public static string Key { get { return "WebApiControllingData"; } } + + public static void Remove() + { + try + { + HttpRuntime.Cache.Remove(Key); + } + catch { } + } + + public static WebApiControllingCacheData Data() + { + var data = HttpRuntime.Cache[Key] as WebApiControllingCacheData; + if (data == null) + { + lock (_lock) + { + data = HttpRuntime.Cache[Key] as WebApiControllingCacheData; + + if (data == null) + { + var engine = EngineContext.Current; + var plugin = engine.Resolve().GetPluginDescriptorBySystemName(WebApiGlobal.PluginSystemName); + var settings = engine.Resolve(); + + data = new WebApiControllingCacheData + { + ValidMinutePeriod = settings.ValidMinutePeriod, + LogUnauthorized = settings.LogUnauthorized, + ApiUnavailable = (plugin == null || !plugin.Installed), + PluginVersion = (plugin == null ? "1.0" : plugin.Version.ToString()) + }; + + HttpRuntime.Cache.Add(Key, data, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); + } + } + } + return data; + } + } + + public partial class WebApiControllingCacheData + { + public bool ApiUnavailable { get; set; } + public int ValidMinutePeriod { get; set; } + public bool LogUnauthorized { get; set; } + public string PluginVersion { get; set; } + + public string Version + { + get + { + return "{0} {1}".FormatWith(WebApiGlobal.MaxApiVersion, PluginVersion); + } + } + } +} diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingUserData.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingUserData.cs new file mode 100644 index 0000000000..6f0a2a5c31 --- /dev/null +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingUserData.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web; +using System.Web.Caching; +using SmartStore.Core.Data; +using SmartStore.Core.Domain.Common; +using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Infrastructure; +using SmartStore.Data; + +namespace SmartStore.Web.Framework.WebApi.Caching +{ + public static class WebApiCachingUserData + { + private static object _lock = new object(); + + /// + /// Lazy storing... fired on app shut down. Note that items with CacheItemPriority.NotRemovable are not removed when the cache is emptied. + /// We're beyond infrastructure and cannot use IOC objects here. It would lead to ComponentNotRegisteredException from autofac. + /// + private static void OnDataRemoved(string key, object value, CacheItemRemovedReason reason) + { + try + { + if (key == Key) + { + var cacheData = value as List; + + if (cacheData != null) + { + var dataToStore = cacheData.Where(x => x.LastRequest.HasValue && x.IsValid); + + if (dataToStore.Count() > 0) + { + if (DataSettings.Current.IsValid()) + { + var dbContext = new SmartObjectContext(DataSettings.Current.DataConnectionString); + + foreach (var user in dataToStore) + { + try + { + dbContext.Execute("Update GenericAttribute Set Value = {1} Where Id = {0}", user.GenericAttributeId, user.ToString()); + } + catch (Exception exc) + { + exc.Dump(); + } + } + } + } + } + } + } + catch (Exception exc) + { + exc.Dump(); + } + } + + public static string Key { get { return "WebApiUserData"; } } + + public static void Remove() + { + try + { + HttpRuntime.Cache.Remove(Key); + } + catch { } + } + + public static List Data() + { + var data = HttpRuntime.Cache[Key] as List; + if (data == null) + { + lock (_lock) + { + data = HttpRuntime.Cache[Key] as List; + + if (data == null) + { + var engine = EngineContext.Current; + var genericAttributes = engine.Resolve>(); + var customers = engine.Resolve>(); + + var attributes = ( + from a in genericAttributes.Table + join c in customers.Table on a.EntityId equals c.Id + where !c.Deleted && c.Active && a.KeyGroup == "Customer" && a.Key == Key + select new + { + a.Id, + a.EntityId, + a.Value + }).ToList(); + + data = new List(); + + foreach (var attribute in attributes) + { + if (!string.IsNullOrWhiteSpace(attribute.Value) && !data.Exists(x => x.CustomerId == attribute.EntityId)) + { + string[] arr = attribute.Value.SplitSafe("¶"); + + if (arr.Length > 2) + { + var apiUser = new WebApiUserCacheData + { + GenericAttributeId = attribute.Id, + CustomerId = attribute.EntityId, + Enabled = bool.Parse(arr[0]), + PublicKey = arr[1], + SecretKey = arr[2] + }; + + if (arr.Length > 3) + apiUser.LastRequest = DateTime.ParseExact(arr[3], "o", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal); + + if (apiUser.IsValid) + data.Add(apiUser); + } + } + } + + HttpRuntime.Cache.Add(Key, data, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, + new CacheItemRemovedCallback(OnDataRemoved)); + } + } + } + return data; + } + } + + public partial class WebApiUserCacheData + { + public int GenericAttributeId { get; set; } + public int CustomerId { get; set; } + public bool Enabled { get; set; } + public string PublicKey { get; set; } + public string SecretKey { get; set; } + public DateTime? LastRequest { get; set; } + + public bool IsValid + { + get + { + return GenericAttributeId != 0 && CustomerId != 0 && !string.IsNullOrWhiteSpace(PublicKey) && !string.IsNullOrWhiteSpace(SecretKey); + } + } + public override string ToString() + { + if (!string.IsNullOrWhiteSpace(PublicKey) && !string.IsNullOrWhiteSpace(SecretKey)) + { + if (!LastRequest.HasValue) + return string.Join("¶", Enabled, PublicKey, SecretKey); + + return string.Join("¶", Enabled, PublicKey, SecretKey, LastRequest.Value.ToString("o")); + } + return ""; + } + } +} diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs index d43cbfcef6..ba40cda5b7 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs @@ -1,11 +1,4 @@ -using SmartStore.Core; -using SmartStore.Core.Domain.Customers; -using SmartStore.Core.Domain.Logging; -using SmartStore.Core.Infrastructure; -using SmartStore.Services.Localization; -using SmartStore.Core.Logging; -using SmartStore.Services.Security; -using System; +using System; using System.Linq; using System.Net; using System.Net.Http; @@ -13,7 +6,15 @@ using System.Web; using System.Web.Http; using System.Web.Http.Controllers; +using SmartStore.Core; +using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Domain.Logging; +using SmartStore.Core.Infrastructure; +using SmartStore.Core.Logging; using SmartStore.Services.Customers; +using SmartStore.Services.Localization; +using SmartStore.Services.Security; +using SmartStore.Web.Framework.WebApi.Caching; namespace SmartStore.Web.Framework.WebApi.Security { @@ -136,7 +137,7 @@ protected virtual HmacResult IsAuthenticated(HttpActionContext actionContext, Da if (Math.Abs((headDateTime - now).TotalMinutes) > maxMinutes) return HmacResult.TimestampOutOfPeriod; - var cacheUserData = WebApiCaching.UserData(); + var cacheUserData = WebApiCachingUserData.Data(); var apiUser = cacheUserData.FirstOrDefault(x => x.PublicKey == headPublicKey); if (apiUser == null) @@ -190,7 +191,7 @@ protected virtual HmacResult IsAuthenticated(HttpActionContext actionContext, Da public override void OnAuthorization(HttpActionContext actionContext) { var result = HmacResult.FailedForUnknownReason; - var cacheControllingData = WebApiCaching.ControllingData(); + var cacheControllingData = WebApiCachingControllingData.Data(); var now = DateTime.UtcNow; Customer customer = null; diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCaching.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCaching.cs deleted file mode 100644 index 1acfcf0297..0000000000 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCaching.cs +++ /dev/null @@ -1,210 +0,0 @@ -using SmartStore.Core.Data; -using SmartStore.Core.Domain.Common; -using SmartStore.Core.Domain.Customers; -using SmartStore.Core.Infrastructure; -using SmartStore.Core.Plugins; -using SmartStore.Data; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Web; -using System.Web.Caching; - -namespace SmartStore.Web.Framework.WebApi -{ - public static class WebApiCaching - { - private static object _lock = new object(); - - private static T _get(string key, Action fetch) - { - if (HttpRuntime.Cache[key] == null) - { - lock (_lock) - { - if (HttpRuntime.Cache[key] == null) - { - fetch(); - } - } - } - return (T)HttpRuntime.Cache[key]; - } - - /// - /// Lazy storing... fired on app shut down. Note that items with CacheItemPriority.NotRemovable are not removed when the cache is emptied. - /// We're beyond infrastructure and cannot use IOC objects here. It would lead to ComponentNotRegisteredException from autofac. - /// - private static void OnDataRemoved(string key, object value, CacheItemRemovedReason reason) - { - try - { - if (key == WebApiUserCacheData.Key) - { - var cacheData = value as List; - - if (cacheData != null) - { - var dataToStore = cacheData.Where(x => x.LastRequest.HasValue && x.IsValid); - - if (dataToStore.Count() > 0) - { - if (DataSettings.Current.IsValid()) - { - var dbContext = new SmartObjectContext(DataSettings.Current.DataConnectionString); - - foreach (var user in dataToStore) - { - try - { - dbContext.Execute("Update GenericAttribute Set Value = {1} Where Id = {0}", user.GenericAttributeId, user.ToString()); - } - catch (Exception exc) - { - exc.Dump(); - } - } - } - } - } - } - } - catch (Exception exc) - { - exc.Dump(); - } - } - - public static void Remove(string key) - { - try - { - if (HttpRuntime.Cache[key] != null) - HttpRuntime.Cache.Remove(key); - } - catch (Exception) { } - } - public static List UserData() - { - return _get>(WebApiUserCacheData.Key, () => - { - var engine = EngineContext.Current; - var genericAttributes = engine.Resolve>(); - var customers = engine.Resolve>(); - - var attributes = ( - from a in genericAttributes.Table - join c in customers.Table on a.EntityId equals c.Id - where !c.Deleted && c.Active && a.KeyGroup == "Customer" && a.Key == WebApiUserCacheData.Key - select new - { - a.Id, - a.EntityId, - a.Value - }).ToList(); - - var data = new List(); - - foreach (var attribute in attributes) - { - if (!string.IsNullOrWhiteSpace(attribute.Value) && !data.Exists(x => x.CustomerId == attribute.EntityId)) - { - string[] arr = attribute.Value.SplitSafe("¶"); - - if (arr.Length > 2) - { - var apiUser = new WebApiUserCacheData() - { - GenericAttributeId = attribute.Id, - CustomerId = attribute.EntityId, - Enabled = bool.Parse(arr[0]), - PublicKey = arr[1], - SecretKey = arr[2] - }; - - if (arr.Length > 3) - apiUser.LastRequest = DateTime.ParseExact(arr[3], "o", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal); - - if (apiUser.IsValid) - data.Add(apiUser); - } - } - } - - HttpRuntime.Cache.Add(WebApiUserCacheData.Key, data, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, - new CacheItemRemovedCallback(OnDataRemoved)); - }); - } - public static WebApiControllingCacheData ControllingData() - { - return _get(WebApiControllingCacheData.Key, () => - { - var engine = EngineContext.Current; - var plugin = engine.Resolve().GetPluginDescriptorBySystemName(WebApiGlobal.PluginSystemName); - var settings = engine.Resolve(); - - var data = new WebApiControllingCacheData() - { - ValidMinutePeriod = settings.ValidMinutePeriod, - LogUnauthorized = settings.LogUnauthorized, - ApiUnavailable = (plugin == null || !plugin.Installed), - PluginVersion = (plugin == null ? "1.0" : plugin.Version.ToString()) - }; - - HttpRuntime.Cache.Add(WebApiControllingCacheData.Key, data, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); - }); - } - } - - - public partial class WebApiUserCacheData - { - public int GenericAttributeId { get; set; } - public int CustomerId { get; set; } - public bool Enabled { get; set; } - public string PublicKey { get; set; } - public string SecretKey { get; set; } - public DateTime? LastRequest { get; set; } - - public static string Key { get { return "WebApiUserData"; } } - - public bool IsValid - { - get - { - return GenericAttributeId != 0 && CustomerId != 0 && !string.IsNullOrWhiteSpace(PublicKey) && !string.IsNullOrWhiteSpace(SecretKey); - } - } - public override string ToString() - { - if (!string.IsNullOrWhiteSpace(PublicKey) && !string.IsNullOrWhiteSpace(SecretKey)) - { - if (!LastRequest.HasValue) - return string.Join("¶", Enabled, PublicKey, SecretKey); - - return string.Join("¶", Enabled, PublicKey, SecretKey, LastRequest.Value.ToString("o")); - } - return ""; - } - } - - - public partial class WebApiControllingCacheData - { - public bool ApiUnavailable { get; set; } - public int ValidMinutePeriod { get; set; } - public bool LogUnauthorized { get; set; } - public string PluginVersion { get; set; } - - public static string Key { get { return "WebApiControllingData"; } } - - public string Version - { - get - { - return "{0} {1}".FormatWith(WebApiGlobal.MaxApiVersion, PluginVersion); - } - } - } -} From 3c88a72de9da8676aacdedb2296c3cf904cc5d8b Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 15 Apr 2015 17:43:02 +0200 Subject: [PATCH 0040/1256] CSS for large modal dialog --- .../SmartStore.Web/Administration/Content/admin.less | 6 ++++++ .../Administration/Views/Plugin/LicensePlugin.cshtml | 2 +- .../SmartStore.Web/Administration/Views/Plugin/List.cshtml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Content/admin.less b/src/Presentation/SmartStore.Web/Administration/Content/admin.less index eae90aefb8..85c7ebd084 100644 --- a/src/Presentation/SmartStore.Web/Administration/Content/admin.less +++ b/src/Presentation/SmartStore.Web/Administration/Content/admin.less @@ -501,6 +501,12 @@ body .t-content.t-state-active { padding: 5px; } +.modal-large { + width: 800px !important; + margin: -250px 0 0 -400px !important; +} + + /* HTML editor (tiny mce) -------------------------------------------------------------- */ diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml index 9533495bfc..d8e2188426 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml @@ -28,7 +28,7 @@ @Html.HiddenFor(model => model.Licenses[i].StoreId) @Html.HiddenFor(model => model.Licenses[i].StoreUrl) - @Html.TextAreaFor(model => model.Licenses[i].LicenseKey, new { rows = 2 }) + @Html.TextBoxFor(model => model.Licenses[i].LicenseKey, new { @class = "input-large" }) } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml index 3e89a384a4..3e9ba8a631 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml @@ -208,7 +208,7 @@ }

-
bool IsSingleStoreMode(); + + /// + /// True if the store data is valid. Otherwise False. + /// + /// Store entity + bool IsStoreDataValid(Store store); } } \ No newline at end of file diff --git a/src/Libraries/SmartStore.Services/Stores/StoreService.cs b/src/Libraries/SmartStore.Services/Stores/StoreService.cs index 41bea638a3..cd0565d3c0 100644 --- a/src/Libraries/SmartStore.Services/Stores/StoreService.cs +++ b/src/Libraries/SmartStore.Services/Stores/StoreService.cs @@ -155,6 +155,41 @@ public virtual bool IsSingleStoreMode() return _isSingleStoreMode.Value; } + /// + /// True if the store data is valid. Otherwise False. + /// + /// Store entity + public virtual bool IsStoreDataValid(Store store) + { + if (store == null) + throw new ArgumentNullException("store"); + + if (store.Url.IsEmpty()) + return false; + + try + { + var uri = new Uri(store.Url); + var domain = uri.DnsSafeHost.EmptyNull().ToLower(); + + switch (domain) + { + case "www.yourstore.com": + case "yourstore.com": + case "www.mein-shop.de": + case "mein-shop.de": + return false; + default: + return store.Url.IsWebUrl(); + } + } + catch (Exception exc) + { + var message = "{0} ({1})".FormatInvariant(exc.Message.NaIfEmpty(), store.Url); + throw new Exception(message, exc); + } + } + #endregion } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs index cb1f67f261..dc1f576bc7 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs @@ -353,6 +353,16 @@ public ActionResult LicensePlugin(string systemName, string licenseKey) Licenses = new List() }; + // validate store url + foreach (var store in stores) + { + if (!_commonService.StoreService.IsStoreDataValid(store)) + { + model.InvalidDataStoreId = store.Id; + return View(model); + } + } + if (singleLicenseForAllStores) { var licenseModel = new LicensePluginModel.LicenseModel(); @@ -400,26 +410,29 @@ public ActionResult LicensePlugin(string systemName, LicensePluginModel model) if (!isLicensable) return HttpNotFound(); - foreach (var item in model.Licenses) + if (model.Licenses != null) { - var result = LicenseChecker.Activate(item.LicenseKey, descriptor.SystemName, item.StoreUrl); - - if (result == null) - { - // do nothing, skiped - } - else if (result.Success) - { - NotifySuccess(T("Admin.Configuration.Plugins.LicenseActivated")); - } - else + foreach (var item in model.Licenses) { - if (result.IsFailureWarning) - NotifyWarning(result.ToString()); + var result = LicenseChecker.Activate(item.LicenseKey, descriptor.SystemName, item.StoreUrl); + + if (result == null) + { + // do nothing, skiped + } + else if (result.Success) + { + NotifySuccess(T("Admin.Configuration.Plugins.LicenseActivated")); + } else - NotifyError(result.ToString()); + { + if (result.IsFailureWarning) + NotifyWarning(result.ToString()); + else + NotifyError(result.ToString()); - return RedirectToAction("List"); + return RedirectToAction("List"); + } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Plugins/LicensePluginModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Plugins/LicensePluginModel.cs index 8c432289ab..60624309e0 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Plugins/LicensePluginModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Plugins/LicensePluginModel.cs @@ -7,6 +7,7 @@ namespace SmartStore.Admin.Models.Plugins public class LicensePluginModel : ModelBase { public string SystemName { get; set; } + public int InvalidDataStoreId { get; set; } public List Licenses { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml index 066941d3d5..19288ebf7a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml @@ -5,29 +5,48 @@ }
+ data-resetcheckurl="@Url.Action("LicenseResetStatusCheck", "Plugin", new { systemName = Model.SystemName })"> - - @for (int i = 0; i < Model.Licenses.Count; ++i) - { - - - - - - + + } +
-
-
@Model.Licenses[i].StoreName (@Model.Licenses[i].StoreUrl)
-
-
- @Html.SmartLabelFor(model => model.Licenses[i].LicenseKey) - - @Html.HiddenFor(model => model.Licenses[i].StoreId) - @Html.HiddenFor(model => model.Licenses[i].StoreUrl) + @if (Model.InvalidDataStoreId == 0) + { + + @for (int i = 0; i < Model.Licenses.Count; ++i) + { + + + + + + - - } -
+
+
+ @Model.Licenses[i].StoreUrl (@Model.Licenses[i].StoreName) + - + @T("Admin.Common.Change") + +
+
+
+ @Html.SmartLabelFor(model => model.Licenses[i].LicenseKey) + + @Html.HiddenFor(model => model.Licenses[i].StoreId) + @Html.HiddenFor(model => model.Licenses[i].StoreUrl) - @Html.TextBoxFor(model => model.Licenses[i].LicenseKey, new { @class = "input-large" }) -
+ @Html.TextBoxFor(model => model.Licenses[i].LicenseKey, new { @class = "input-large" }) +
+ } + else + { +
+ }
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml index 3e9ba8a631..44d5d1e924 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml @@ -234,196 +234,196 @@ diff --git a/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml index 3800e46a27..82c2317d34 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml @@ -87,6 +87,15 @@ @Html.ValidationMessageFor(model => model.IsActive) + + + @Html.SmartLabelFor(model => model.SendManually) + + + @Html.EditorFor(model => model.SendManually) + @Html.ValidationMessageFor(model => model.SendManually) + + @(Html.LocalizedEditor("messagetemplate-localized", @ diff --git a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/Edit.cshtml index 8f6237a9c2..b6638c1736 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/Edit.cshtml @@ -1,6 +1,5 @@ @model QueuedEmailModel @{ - //page title ViewBag.Title = T("Admin.System.QueuedEmails.EditQueuedEmailDetails").Text; } @using (Html.BeginForm()) @@ -13,6 +12,12 @@ + @if (Model.SendManually) + { + + } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml index 39df4dcf74..6da45a0a2a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml @@ -2,7 +2,6 @@ @using Telerik.Web.Mvc.UI @{ var gridPageSize = EngineContext.Current.Resolve().GridPageSize; - //page title ViewBag.Title = T("Admin.System.QueuedEmails").Text; } @using (Html.BeginForm()) @@ -58,6 +57,19 @@ @Html.EditorFor(model => Model.SearchLoadNotSent) + + + +
+ @Html.SmartLabelFor(model => model.SearchSendManually) + + @Html.DropDownList("SearchSendManually", new List + { + new SelectListItem { Text = T("Common.Unspecified"), Value = "", Selected = !Model.SearchSendManually.HasValue }, + new SelectListItem { Text = T("Admin.Common.Yes"), Value = "true", Selected = Model.SearchSendManually ?? false }, + new SelectListItem { Text = T("Admin.Common.No"), Value = "false", Selected = !Model.SearchSendManually ?? false } + }) +
@Html.SmartLabelFor(model => model.SearchMaxSentTries) @@ -92,41 +104,36 @@
@(Html.Telerik().Grid() - .Name("queuedEmails-grid") - .ClientEvents(events => events.OnDataBinding("onDataBinding").OnDataBound("onDataBound")) - .Columns(columns => - { - columns.Bound(x => x.Id) - .ClientTemplate("") - .Title("") - .Width(50) - .HtmlAttributes(new { style = "text-align:center" }) - .HeaderHtmlAttributes(new { style = "text-align:center" }); - - columns.Bound(x => x.Id).Width(50); - columns.Bound(x => x.Subject).Width(500); - columns.Bound(x => x.Priority) - .Centered() - .Width(50); - columns.Bound(x => x.From); - columns.Bound(x => x.FromName); - columns.Bound(x => x.SentTries) - .Centered() - .Width(50); - columns.Bound(x => x.SentOn); - columns.Bound(x => x.CreatedOn); - columns.Bound(x => x.Id) - .Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id })) - .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") - .Width(50) - .Centered() - .HeaderTemplate(T("Admin.Common.Edit").Text) - .Filterable(false); - }) - .Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both)) - .DataBinding(dataBinding => dataBinding.Ajax().Select("QueuedEmailList", "QueuedEmail")) - .PreserveGridState() - .EnableCustomBinding(true)) + .Name("queuedEmails-grid") + .Columns(columns => + { + columns.Bound(x => x.Id) + .ClientTemplate("") + .Title("") + .HtmlAttributes(new { style = "text-align:center" }) + .HeaderHtmlAttributes(new { style = "text-align:center" }); + columns.Bound(x => x.Id) + .Template(x => Html.ActionLink(x.Id.ToString(), "Edit", new { id = x.Id })) + .ClientTemplate("\"><#= Id #>"); + columns.Bound(x => x.Subject); + columns.Bound(x => x.Priority) + .Centered(); + columns.Bound(x => x.From); + columns.Bound(x => x.FromName); + columns.Bound(x => x.SendManually) + .Template(item => @Html.SymbolForBool(item.SendManually)) + .ClientTemplate(@Html.SymbolForBool("SendManually")) + .Centered(); + columns.Bound(x => x.SentTries) + .Centered(); + columns.Bound(x => x.SentOn); + columns.Bound(x => x.CreatedOn); + }) + .Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both)) + .DataBinding(dataBinding => dataBinding.Ajax().Select("QueuedEmailList", "QueuedEmail")) + .ClientEvents(events => events.OnDataBinding("onDataBinding").OnDataBound("onDataBound").OnRowDataBound("onRowDataBound")) + .PreserveGridState() + .EnableCustomBinding(true))
@@ -207,18 +214,18 @@ function onDataBinding(e) { var searchModel = { - SearchStartDate: $('#@Html.FieldIdFor(model => model.SearchStartDate)').val(), - SearchEndDate: $('#@Html.FieldIdFor(model => model.SearchEndDate)').val(), - SearchFromEmail: $('#@Html.FieldIdFor(model => model.SearchFromEmail)').val(), - SearchToEmail: $('#@Html.FieldIdFor(model => model.SearchToEmail)').val(), - SearchLoadNotSent: $('#@Html.FieldIdFor(model => model.SearchLoadNotSent)').is(':checked'), - SearchMaxSentTries: $('#@Html.FieldIdFor(model => model.SearchMaxSentTries)').val() - }; + SearchStartDate: $('#@Html.FieldIdFor(model => model.SearchStartDate)').val(), + SearchEndDate: $('#@Html.FieldIdFor(model => model.SearchEndDate)').val(), + SearchFromEmail: $('#@Html.FieldIdFor(model => model.SearchFromEmail)').val(), + SearchToEmail: $('#@Html.FieldIdFor(model => model.SearchToEmail)').val(), + SearchLoadNotSent: $('#@Html.FieldIdFor(model => model.SearchLoadNotSent)').is(':checked'), + SearchSendManually: $('#@Html.FieldIdFor(model => model.SearchSendManually)').val(), + SearchMaxSentTries: $('#@Html.FieldIdFor(model => model.SearchMaxSentTries)').val() + }; e.data = searchModel; } function onDataBound(e) { - $('#queuedEmails-grid input[type=checkbox][id!=mastercheckbox]').each(function () { var currentId = $(this).val(); var checked = jQuery.inArray(currentId, selectedIds); @@ -228,12 +235,16 @@ updateMasterCheckbox(); } + + function onRowDataBound(e) { + if (e.dataItem.SentOn) + $(e.row).find('td').wrapInner(''); + } function updateMasterCheckbox() { var numChkBoxes = $('#queuedEmails-grid input[type=checkbox][id!=mastercheckbox]').length; var numChkBoxesChecked = $('#queuedEmails-grid input[type=checkbox][checked][id!=mastercheckbox]').length; $('#mastercheckbox').attr('checked', numChkBoxes == numChkBoxesChecked && numChkBoxes > 0); } - - + } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/_CreateOrUpdate.cshtml index c2945f7dd3..f297897a7a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/_CreateOrUpdate.cshtml @@ -75,7 +75,7 @@ @Html.SmartLabelFor(model => model.Subject) - @Html.EditorFor(model => model.Subject) + @Html.TextBoxFor(model => model.Subject, new { @class = "input-large" }) @Html.ValidationMessageFor(model => model.Subject) @@ -88,6 +88,15 @@ @Html.ValidationMessageFor(model => model.Body) + + + @Html.SmartLabelFor(model => model.SendManually) + + + @Html.EditorFor(model => model.SendManually) + @Html.ValidationMessageFor(model => model.SendManually) + + @Html.SmartLabelFor(model => model.SentTries) From 6756b151d8f7da2ec74d9ae1501c5e0c2122233c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 28 Apr 2015 20:06:16 +0200 Subject: [PATCH 0084/1256] Category filtering by store for backend category tree and list. Resolves #105. --- changelog.md | 1 + .../Catalog/CategoryService.cs | 46 ++++++--- .../Catalog/ICategoryService.cs | 3 +- .../Controllers/CategoryController.cs | 72 ++++++++------ .../Models/Catalog/CategoryListModel.cs | 13 ++- .../Models/Catalog/CategoryTreeModel.cs | 19 ++++ .../Administration/SmartStore.Admin.csproj | 1 + .../Administration/Views/Category/List.cshtml | 15 ++- .../Administration/Views/Category/Tree.cshtml | 94 +++++++++++++------ .../Administration/Views/Store/List.cshtml | 9 -- 10 files changed, 189 insertions(+), 84 deletions(-) create mode 100644 src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryTreeModel.cs diff --git a/changelog.md b/changelog.md index d72bab674c..5b0e3141c9 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,7 @@ * #652 Web API: Support for file upload and multipart mime * New option to display product thumbnails in instant search (NOTE: the feature can be enabled via _Configuration > Settings > Catalog Settings > Search_) * #594 Option to prevent a message from being automatically sent +* Category filtering by store for backend category tree and list ## SmartStore.NET 2.2.0 diff --git a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs index 0733a9fa98..05f2190515 100644 --- a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs @@ -143,9 +143,10 @@ public virtual void DeleteCategory(Category category, bool deleteChilds = false) /// Alias to be filtered /// Whether to apply instances to the actual categories query. Never applied when is true /// A value indicating whether categories without parent category in provided category list (source) should be ignored + /// Store identifier; 0 to load all records /// Categories public virtual IPagedList GetAllCategories(string categoryName = "", int pageIndex = 0, int pageSize = int.MaxValue, bool showHidden = false, string alias = null, - bool applyNavigationFilters = true, bool ignoreCategoriesWithoutExistingParent = true) + bool applyNavigationFilters = true, bool ignoreCategoriesWithoutExistingParent = true, int storeId = 0) { var query = _categoryRepository.Table; @@ -160,10 +161,27 @@ public virtual IPagedList GetAllCategories(string categoryName = "", i query = query.Where(c => !c.Deleted); query = query.OrderBy(c => c.ParentCategoryId).ThenBy(c => c.DisplayOrder); - - if (!showHidden) + + if (showHidden) + { + if (!QuerySettings.IgnoreMultiStore && storeId > 0) + { + query = from c in query + join sm in _storeMappingRepository.Table + on new { c1 = c.Id, c2 = "Category" } equals new { c1 = sm.EntityId, c2 = sm.EntityName } into c_sm + from sm in c_sm.DefaultIfEmpty() + where !c.LimitedToStores || storeId == sm.StoreId + select c; + + query = from c in query + group c by c.Id into cGroup + orderby cGroup.Key + select cGroup.FirstOrDefault(); + } + } + else { - query = ApplyHiddenCategoriesFilter(query, applyNavigationFilters); + query = ApplyHiddenCategoriesFilter(query, applyNavigationFilters, _storeContext.CurrentStore.Id); query = query.OrderBy(c => c.ParentCategoryId).ThenBy(c => c.DisplayOrder); } @@ -184,7 +202,8 @@ public virtual IPagedList GetAllCategories(string categoryName = "", i /// Category collection public IList GetAllCategoriesByParentCategoryId(int parentCategoryId, bool showHidden = false) { - string key = string.Format(CATEGORIES_BY_PARENT_CATEGORY_ID_KEY, parentCategoryId, showHidden, _workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id); + int storeId = _storeContext.CurrentStore.Id; + string key = string.Format(CATEGORIES_BY_PARENT_CATEGORY_ID_KEY, parentCategoryId, showHidden, _workContext.CurrentCustomer.Id, storeId); return _cacheManager.Get(key, () => { var query = _categoryRepository.Table; @@ -196,7 +215,7 @@ public IList GetAllCategoriesByParentCategoryId(int parentCategoryId, if (!showHidden) { - query = ApplyHiddenCategoriesFilter(query, false); + query = ApplyHiddenCategoriesFilter(query, false, storeId); query = query.OrderBy(c => c.DisplayOrder); } @@ -206,13 +225,13 @@ public IList GetAllCategoriesByParentCategoryId(int parentCategoryId, } - protected virtual IQueryable ApplyHiddenCategoriesFilter(IQueryable query, bool applyNavigationFilters) + protected virtual IQueryable ApplyHiddenCategoriesFilter(IQueryable query, bool applyNavigationFilters, int storeId = 0) { // ACL (access control list) - var allowedCustomerRolesIds = _workContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); - if (!QuerySettings.IgnoreAcl) { + var allowedCustomerRolesIds = _workContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); + query = from c in query join acl in _aclRepository.Table on new { c1 = c.Id, c2 = "Category" } equals new { c1 = acl.EntityId, c2 = acl.EntityName } into c_acl @@ -221,19 +240,18 @@ from acl in c_acl.DefaultIfEmpty() select c; } - if (!QuerySettings.IgnoreMultiStore) + // Store mapping + if (!QuerySettings.IgnoreMultiStore && storeId > 0) { - //Store mapping - var currentStoreId = _storeContext.CurrentStore.Id; query = from c in query join sm in _storeMappingRepository.Table on new { c1 = c.Id, c2 = "Category" } equals new { c1 = sm.EntityId, c2 = sm.EntityName } into c_sm from sm in c_sm.DefaultIfEmpty() - where !c.LimitedToStores || currentStoreId == sm.StoreId + where !c.LimitedToStores || storeId == sm.StoreId select c; } - //only distinct categories (group by ID) + // only distinct categories (group by ID) query = from c in query group c by c.Id into cGroup orderby cGroup.Key diff --git a/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs index 876a4d93af..6b7650d69b 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs @@ -27,9 +27,10 @@ public partial interface ICategoryService /// Alias to be filtered /// Whether to apply instances to the actual categories query. Never applied when is true /// A value indicating whether categories without parent category in provided category list (source) should be ignored + /// Store identifier; 0 to load all records /// Categories IPagedList GetAllCategories(string categoryName = "", int pageIndex = 0, int pageSize = int.MaxValue, bool showHidden = false, string alias = null, - bool applyNavigationFilters = true, bool ignoreCategoriesWithoutExistingParent = true); + bool applyNavigationFilters = true, bool ignoreCategoriesWithoutExistingParent = true, int storeId = 0); /// /// Gets all categories filtered by parent category identifier diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs index c66181d69a..ceda143ff6 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs @@ -264,24 +264,18 @@ public ActionResult List() if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); + var allStores = _storeService.GetAllStores(); var model = new CategoryListModel { GridPageSize = _adminAreaSettings.GridPageSize }; - var categories = _categoryService.GetAllCategories(null, 0, _adminAreaSettings.GridPageSize, true); - var mappedCategories = categories.ToDictionary(x => x.Id); + model.AvailableStores.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" }); + foreach (var store in allStores) + { + model.AvailableStores.Add(new SelectListItem { Text = store.Name, Value = store.Id.ToString() }); + } - model.Categories = new GridModel - { - Data = categories.Select(x => - { - var categoryModel = x.ToModel(); - categoryModel.Breadcrumb = x.GetCategoryBreadCrumb(_categoryService, mappedCategories); - return categoryModel; - }), - Total = categories.TotalCount - }; return View(model); } @@ -291,7 +285,7 @@ public ActionResult List(GridCommand command, CategoryListModel model) if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); - var categories = _categoryService.GetAllCategories(model.SearchCategoryName, command.Page - 1, command.PageSize, true, model.SearchAlias, true, false); + var categories = _categoryService.GetAllCategories(model.SearchCategoryName, command.Page - 1, command.PageSize, true, model.SearchAlias, true, false, model.SearchStoreId); var mappedCategories = categories.ToDictionary(x => x.Id); var gridModel = new GridModel @@ -304,6 +298,7 @@ public ActionResult List(GridCommand command, CategoryListModel model) }), Total = categories.TotalCount }; + return new JsonResult { Data = gridModel @@ -369,32 +364,55 @@ public ActionResult Tree() if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); - var rootCategories = _categoryService.GetAllCategoriesByParentCategoryId(0, true); - return View(rootCategories); + var allStores = _storeService.GetAllStores(); + var model = new CategoryTreeModel(); + + model.AvailableStores.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" }); + foreach (var store in allStores) + { + model.AvailableStores.Add(new SelectListItem { Text = store.Name, Value = store.Id.ToString() }); + } + + return View(model); } //ajax [AcceptVerbs(HttpVerbs.Post)] - public ActionResult TreeLoadChildren(TreeViewItem node) + public ActionResult TreeLoadChildren(TreeViewItem node, CategoryTreeModel model) { var parentId = !string.IsNullOrEmpty(node.Value) ? Convert.ToInt32(node.Value) : 0; var urlHelper = new UrlHelper(this.ControllerContext.RequestContext); - var children = _categoryService.GetAllCategoriesByParentCategoryId(parentId, true).Select(x => + var parentCategories = _categoryService.GetAllCategoriesByParentCategoryId(parentId, true); + + if (parentId == 0 && model.SearchStoreId != 0) + { + for (int i = parentCategories.Count - 1; i >= 0; --i) + { + var category = parentCategories[i]; + if (!category.LimitedToStores || (category.LimitedToStores && !_storeMappingService.GetStoresIdsWithAccess(category).Contains(model.SearchStoreId))) + { + parentCategories.Remove(category); + } + } + } + + var children = parentCategories.Select(x => { var childCount = _categoryService.GetAllCategoriesByParentCategoryId(x.Id, true).Count; - string text = (childCount > 0 ? "{0} ({1})".FormatWith(x.Name, childCount) : x.Name); + string text = (childCount > 0 ? "{0} ({1})".FormatInvariant(x.Name, childCount) : x.Name); - var item = new TreeViewItem - { - Text = x.Alias.HasValue() ? "{0} {1}".FormatCurrent(text, x.Alias) : text, - Encoded = x.Alias.IsEmpty(), - Value = x.Id.ToString(), - LoadOnDemand = (childCount > 0), - Enabled = true, - ImageUrl = Url.Content(x.Published ? "~/Administration/Content/images/ico-content.png" : "~/Administration/Content/images/ico-content-o60.png"), + var item = new TreeViewItem + { + Text = x.Alias.HasValue() ? "{0} {1}".FormatCurrent(text, x.Alias) : text, + Encoded = x.Alias.IsEmpty(), + Value = x.Id.ToString(), + LoadOnDemand = (childCount > 0), + Enabled = true, + ImageUrl = Url.Content(x.Published ? "~/Administration/Content/images/ico-content.png" : "~/Administration/Content/images/ico-content-o60.png"), Url = urlHelper.Action("Edit", "Category", new { id = x.Id }) - }; + }; + return item; }); diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryListModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryListModel.cs index 3c7e910efb..5b20108889 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryListModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryListModel.cs @@ -1,12 +1,17 @@ -using System.Web.Mvc; +using System.Collections.Generic; +using System.Web.Mvc; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Mvc; -using Telerik.Web.Mvc; namespace SmartStore.Admin.Models.Catalog { public class CategoryListModel : ModelBase { + public CategoryListModel() + { + AvailableStores = new List(); + } + [SmartResourceDisplayName("Admin.Catalog.Categories.List.SearchCategoryName")] [AllowHtml] public string SearchCategoryName { get; set; } @@ -14,7 +19,9 @@ public class CategoryListModel : ModelBase [SmartResourceDisplayName("Admin.Catalog.Categories.List.SearchAlias")] public string SearchAlias { get; set; } - public GridModel Categories { get; set; } + [SmartResourceDisplayName("Admin.Common.Store.SearchFor")] + public int SearchStoreId { get; set; } + public IList AvailableStores { get; set; } public int GridPageSize { get; set; } } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryTreeModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryTreeModel.cs new file mode 100644 index 0000000000..ee98f503d6 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/CategoryTreeModel.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Web.Mvc; +using SmartStore.Web.Framework; +using SmartStore.Web.Framework.Mvc; + +namespace SmartStore.Admin.Models.Catalog +{ + public class CategoryTreeModel : ModelBase + { + public CategoryTreeModel() + { + AvailableStores = new List(); + } + + [SmartResourceDisplayName("Admin.Common.Store.SearchFor")] + public int SearchStoreId { get; set; } + public IList AvailableStores { get; set; } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index a44a9e9db6..fd2aa999ac 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -224,6 +224,7 @@ + diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Category/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Category/List.cshtml index f724f75928..9a3b2abd9f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Category/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Category/List.cshtml @@ -31,6 +31,14 @@ @Html.EditorFor(model => Model.SearchAlias) + + + @Html.SmartLabelFor(model => model.SearchStoreId) + + + @Html.DropDownList("SearchStoreId", Model.AvailableStores) + +   @@ -44,7 +52,7 @@ diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs index 113106e980..191bdc64fc 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs @@ -171,6 +171,7 @@ public ActionResult Category(int categoryId, CatalogPagingFilteringModel command var selectedPriceRange = model.PagingFilteringContext.PriceRangeFilter.GetSelectedPriceRange(_services.WebHelper, category.PriceRanges); decimal? minPriceConverted = null; decimal? maxPriceConverted = null; + if (selectedPriceRange != null) { if (selectedPriceRange.From.HasValue) @@ -180,8 +181,6 @@ public ActionResult Category(int categoryId, CatalogPagingFilteringModel command maxPriceConverted = _currencyService.ConvertToPrimaryStoreCurrency(selectedPriceRange.To.Value, _services.WorkContext.WorkingCurrency); } - - //category breadcrumb model.DisplayCategoryBreadcrumb = _catalogSettings.CategoryBreadcrumbEnabled; if (model.DisplayCategoryBreadcrumb) @@ -190,11 +189,10 @@ public ActionResult Category(int categoryId, CatalogPagingFilteringModel command } model.DisplayFilter = _catalogSettings.FilterEnabled; - model.ShowSubcategoriesAboveProductLists = _catalogSettings.ShowSubcategoriesAboveProductLists; + model.SubCategoryDisplayType = _catalogSettings.SubCategoryDisplayType; var customerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); - //subcategories model.SubCategories = _categoryService .GetAllCategoriesByParentCategoryId(categoryId) @@ -230,8 +228,6 @@ public ActionResult Category(int categoryId, CatalogPagingFilteringModel command .ToList(); - - // Featured products if (!_catalogSettings.IgnoreFeaturedProducts) { diff --git a/src/Presentation/SmartStore.Web/Models/Catalog/CategoryModel.cs b/src/Presentation/SmartStore.Web/Models/Catalog/CategoryModel.cs index 395a5ad46e..52be36ea9b 100644 --- a/src/Presentation/SmartStore.Web/Models/Catalog/CategoryModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Catalog/CategoryModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using SmartStore.Core.Domain.Catalog; using SmartStore.Web.Framework.Mvc; using SmartStore.Web.Framework.UI; using SmartStore.Web.Models.Media; @@ -34,7 +35,7 @@ public CategoryModel() public IList CategoryBreadcrumb { get; set; } public bool DisplayFilter { get; set; } - public bool ShowSubcategoriesAboveProductLists { get; set; } + public SubCategoryDisplayType SubCategoryDisplayType { get; set; } public IList SubCategories { get; set; } diff --git a/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.cshtml b/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.cshtml index e1e40c6b0f..f96a1c71c6 100644 --- a/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Catalog/CategoryTemplate.ProductsInGridOrLines.cshtml @@ -15,6 +15,7 @@ } @using SmartStore.Core; +@using SmartStore.Core.Domain.Catalog; @using SmartStore.Core.Domain.Common; @using SmartStore.Core.Domain.Seo; @using SmartStore.Core.Infrastructure; @@ -33,6 +34,26 @@ } } +@helper SubCategoryList() +{ +
+ @(Html.DataList(Model.SubCategories, 3, + @ + )) +
+} +
@if (Model.DisplayCategoryBreadcrumb) {
} + @*subcategories*@ + @if (Model.SubCategories.Count > 0 && Model.SubCategoryDisplayType == SubCategoryDisplayType.Bottom) + { + @Html.Widget("categorydetails_before_subcategories") + @SubCategoryList() + } + @Html.Widget("categorydetails_bottom") From e85ffeddde7e698d28808aeddff53b80b83a5623 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Mon, 4 May 2015 20:12:42 +0200 Subject: [PATCH 0091/1256] Changed PDF generator tool path to 'App_Data/temp' to prevent annoying app restarts after deployment --- src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs | 2 +- src/Libraries/SmartStore.Services/Pdf/WkHtmlToPdfConverter.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs b/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs index ab455d13c8..2f512f0c81 100644 --- a/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs +++ b/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs @@ -14,7 +14,7 @@ public static class FileSystemHelper public static string TempDir(string subDirectory = null) { string path = CommonHelper.GetAppSetting("sm:TempDirectory", "~/App_Data/_temp"); - path = HostingEnvironment.MapPath(path); + path = CommonHelper.MapPath(path); if (!Directory.Exists(path)) Directory.CreateDirectory(path); diff --git a/src/Libraries/SmartStore.Services/Pdf/WkHtmlToPdfConverter.cs b/src/Libraries/SmartStore.Services/Pdf/WkHtmlToPdfConverter.cs index ca7dc05776..22dfb32589 100644 --- a/src/Libraries/SmartStore.Services/Pdf/WkHtmlToPdfConverter.cs +++ b/src/Libraries/SmartStore.Services/Pdf/WkHtmlToPdfConverter.cs @@ -6,6 +6,7 @@ using System.Web; using NReco.PdfGenerator; using SmartStore.Core.Logging; +using SmartStore.Utilities; namespace SmartStore.Services.Pdf { @@ -76,6 +77,7 @@ internal HtmlToPdfConverter CreateWkConverter(PdfConvertSettings settings) PageHeight = settings.PageHeight, PageWidth = settings.PageWidth, Size = (PageSize)(int)settings.Size, + PdfToolPath = FileSystemHelper.TempDir("wkhtmltopdf") }; if (settings.Margins != null) From 1a48a071fbbd23ff01c9276923322e7edd4eef2f Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Mon, 4 May 2015 20:39:47 +0200 Subject: [PATCH 0092/1256] Updated internal PDF generator to version 1.1.5 --- .../SmartStore.Services.csproj | 4 +- src/Libraries/SmartStore.Services/app.config | 24 +- .../SmartStore.Services/packages.config | 2 +- src/Plugins/SmartStore.AmazonPay/web.config | 124 +++---- src/Plugins/SmartStore.Clickatell/web.config | 116 +++---- src/Plugins/SmartStore.DevTools/Web.config | 126 +++---- .../SmartStore.DiscountRules/web.config | 116 +++---- .../SmartStore.FacebookAuth/web.config | 120 +++---- .../SmartStore.GoogleAnalytics/web.config | 116 +++---- .../web.config | 116 +++---- .../SmartStore.OfflinePayment/web.config | 116 +++---- src/Plugins/SmartStore.PayPal/web.config | 128 +++---- src/Plugins/SmartStore.Shipping/web.config | 116 +++---- .../SmartStore.ShippingByWeight/web.config | 116 +++---- src/Plugins/SmartStore.Tax/web.config | 116 +++---- src/Plugins/SmartStore.WebApi/web.config | 88 ++--- .../SmartStore.Web.Framework/app.config | 52 +-- .../SmartStore.Web/Administration/Web.config | 112 +++--- src/Presentation/SmartStore.Web/Web.config | 320 +++++++++--------- .../SmartStore.Services.Tests/App.config | 34 +- src/Tests/SmartStore.Web.MVC.Tests/App.config | 72 ++-- 21 files changed, 1067 insertions(+), 1067 deletions(-) diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index 840c2efdcc..5d5e01f9a6 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -100,9 +100,9 @@ False ..\..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll - + False - ..\..\packages\NReco.PdfGenerator.1.1.3.0\lib\net20\NReco.PdfGenerator.dll + ..\..\packages\NReco.PdfGenerator.1.1.5.0\lib\net20\NReco.PdfGenerator.dll diff --git a/src/Libraries/SmartStore.Services/app.config b/src/Libraries/SmartStore.Services/app.config index 9419122e87..a376174d13 100644 --- a/src/Libraries/SmartStore.Services/app.config +++ b/src/Libraries/SmartStore.Services/app.config @@ -1,11 +1,11 @@ - + -
+
-
+
@@ -20,23 +20,23 @@ - - + + - - + + - - + + - + - + - + diff --git a/src/Libraries/SmartStore.Services/packages.config b/src/Libraries/SmartStore.Services/packages.config index e16316f498..1d9b39f80e 100644 --- a/src/Libraries/SmartStore.Services/packages.config +++ b/src/Libraries/SmartStore.Services/packages.config @@ -12,7 +12,7 @@ - + \ No newline at end of file diff --git a/src/Plugins/SmartStore.AmazonPay/web.config b/src/Plugins/SmartStore.AmazonPay/web.config index 4c9e3769d7..1e50c947f6 100644 --- a/src/Plugins/SmartStore.AmazonPay/web.config +++ b/src/Plugins/SmartStore.AmazonPay/web.config @@ -1,123 +1,123 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.Clickatell/web.config b/src/Plugins/SmartStore.Clickatell/web.config index 34297838be..46b8ba77d4 100644 --- a/src/Plugins/SmartStore.Clickatell/web.config +++ b/src/Plugins/SmartStore.Clickatell/web.config @@ -1,116 +1,116 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.DevTools/Web.config b/src/Plugins/SmartStore.DevTools/Web.config index b68f7d42bb..4f2a281983 100644 --- a/src/Plugins/SmartStore.DevTools/Web.config +++ b/src/Plugins/SmartStore.DevTools/Web.config @@ -1,131 +1,131 @@ - + -
+
- - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + \ No newline at end of file diff --git a/src/Plugins/SmartStore.DiscountRules/web.config b/src/Plugins/SmartStore.DiscountRules/web.config index 34297838be..46b8ba77d4 100644 --- a/src/Plugins/SmartStore.DiscountRules/web.config +++ b/src/Plugins/SmartStore.DiscountRules/web.config @@ -1,116 +1,116 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.FacebookAuth/web.config b/src/Plugins/SmartStore.FacebookAuth/web.config index 2178f3c9db..10ad5c862a 100644 --- a/src/Plugins/SmartStore.FacebookAuth/web.config +++ b/src/Plugins/SmartStore.FacebookAuth/web.config @@ -1,120 +1,120 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.GoogleAnalytics/web.config b/src/Plugins/SmartStore.GoogleAnalytics/web.config index 8ec2a24780..ad003b3e26 100644 --- a/src/Plugins/SmartStore.GoogleAnalytics/web.config +++ b/src/Plugins/SmartStore.GoogleAnalytics/web.config @@ -1,115 +1,115 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/web.config b/src/Plugins/SmartStore.GoogleMerchantCenter/web.config index 34297838be..46b8ba77d4 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/web.config +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/web.config @@ -1,116 +1,116 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.OfflinePayment/web.config b/src/Plugins/SmartStore.OfflinePayment/web.config index 34297838be..46b8ba77d4 100644 --- a/src/Plugins/SmartStore.OfflinePayment/web.config +++ b/src/Plugins/SmartStore.OfflinePayment/web.config @@ -1,116 +1,116 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.PayPal/web.config b/src/Plugins/SmartStore.PayPal/web.config index 79e1718372..009e149619 100644 --- a/src/Plugins/SmartStore.PayPal/web.config +++ b/src/Plugins/SmartStore.PayPal/web.config @@ -1,11 +1,11 @@ - + -
+
- + @@ -14,123 +14,123 @@ - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.Shipping/web.config b/src/Plugins/SmartStore.Shipping/web.config index 8ec2a24780..ad003b3e26 100644 --- a/src/Plugins/SmartStore.Shipping/web.config +++ b/src/Plugins/SmartStore.Shipping/web.config @@ -1,115 +1,115 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.ShippingByWeight/web.config b/src/Plugins/SmartStore.ShippingByWeight/web.config index 8ec2a24780..ad003b3e26 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/web.config +++ b/src/Plugins/SmartStore.ShippingByWeight/web.config @@ -1,115 +1,115 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.Tax/web.config b/src/Plugins/SmartStore.Tax/web.config index 34297838be..46b8ba77d4 100644 --- a/src/Plugins/SmartStore.Tax/web.config +++ b/src/Plugins/SmartStore.Tax/web.config @@ -1,116 +1,116 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Plugins/SmartStore.WebApi/web.config b/src/Plugins/SmartStore.WebApi/web.config index bddef732e2..0219bc2ade 100644 --- a/src/Plugins/SmartStore.WebApi/web.config +++ b/src/Plugins/SmartStore.WebApi/web.config @@ -1,88 +1,88 @@ - + - - + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Presentation/SmartStore.Web.Framework/app.config b/src/Presentation/SmartStore.Web.Framework/app.config index b9b662f2f0..3bd64c962b 100644 --- a/src/Presentation/SmartStore.Web.Framework/app.config +++ b/src/Presentation/SmartStore.Web.Framework/app.config @@ -1,55 +1,55 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + diff --git a/src/Presentation/SmartStore.Web/Administration/Web.config b/src/Presentation/SmartStore.Web/Administration/Web.config index b242a817ea..7d3a217dd0 100644 --- a/src/Presentation/SmartStore.Web/Administration/Web.config +++ b/src/Presentation/SmartStore.Web/Administration/Web.config @@ -1,110 +1,110 @@ - + - - - - - + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config index d830099b28..993c42a148 100644 --- a/src/Presentation/SmartStore.Web/Web.config +++ b/src/Presentation/SmartStore.Web/Web.config @@ -1,86 +1,86 @@ - + -
+
-
-
-
+
+
+
-
-
+
+
- - + + - - + + - - + + - + - + - - + + - + - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - + - - - - - - - + + + + + + + - - - + + + - - - - - - + + + + + + - + - - - - - - - + + + + + + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - - + + + - + - + - + - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/src/Tests/SmartStore.Services.Tests/App.config b/src/Tests/SmartStore.Services.Tests/App.config index 39d7a48483..28d743eb22 100644 --- a/src/Tests/SmartStore.Services.Tests/App.config +++ b/src/Tests/SmartStore.Services.Tests/App.config @@ -1,33 +1,33 @@ - + -
+
- - + + - - - + + + - - - - - + + + + + - + - - + + - - + + diff --git a/src/Tests/SmartStore.Web.MVC.Tests/App.config b/src/Tests/SmartStore.Web.MVC.Tests/App.config index 04668c3c98..10b4b64ed8 100644 --- a/src/Tests/SmartStore.Web.MVC.Tests/App.config +++ b/src/Tests/SmartStore.Web.MVC.Tests/App.config @@ -1,80 +1,80 @@ - + -
-
+
+
- - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + From 87d661bc32f8c953b6f1c8d8c2571ce2e86ecf14 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Mon, 4 May 2015 21:22:23 +0200 Subject: [PATCH 0093/1256] LESS CSS validation in backend throws exception when store is hosted as sub-application --- .../Administration/Controllers/ThemeController.cs | 7 ++++--- src/Presentation/SmartStore.Web/Web.config | 8 -------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs index f4c88744bf..7d376c349f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs @@ -9,6 +9,7 @@ using System.Web.Mvc; using SmartStore.Admin.Models.Themes; using SmartStore.Collections; +using SmartStore.Core; using SmartStore.Core.Domain.Themes; using SmartStore.Core.Localization; using SmartStore.Core.Packaging; @@ -301,13 +302,13 @@ private string ValidateLess(ThemeManifest manifest, int storeId) virtualPath = file.ResultVirtualPath; } - var url = "{0}{1}?storeId={2}&theme={3}".FormatInvariant( - _services.WebHelper.GetStoreLocation().EnsureEndsWith("/"), - VirtualPathUtility.ToAbsolute(virtualPath).TrimStart('/'), + var url = "{0}?storeId={1}&theme={2}".FormatInvariant( + WebHelper.GetAbsoluteUrl(virtualPath, this.Request), storeId, manifest.ThemeName); HttpWebRequest request = WebRequest.CreateHttp(url); + request.UserAgent = "SmartStore.NET {0}".FormatInvariant(SmartStoreVersion.CurrentFullVersion); WebResponse response = null; try diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config index 993c42a148..2c83f69c00 100644 --- a/src/Presentation/SmartStore.Web/Web.config +++ b/src/Presentation/SmartStore.Web/Web.config @@ -82,14 +82,6 @@ - From c31d6255d6c9ba05e647cfbbad99deb84199795b Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 5 May 2015 17:18:50 +0200 Subject: [PATCH 0094/1256] Updated changelog --- changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index b59d48de47..26723c3a9f 100644 --- a/changelog.md +++ b/changelog.md @@ -9,9 +9,11 @@ * #594 Option to prevent a message from being automatically sent * Category filtering by store for backend category tree and list * #554 Flag to indicate that a new payment notification (IPN) arrived for an order since last opening\editing of the order +* Setting whether and how to display sub-categories on a category page (hide, above products, bottom of page) +* Debitoor: Extend option "Book invoice if paid" to also (optionally) mail the invoice as a PDF ### Bugfixes -Fixed System.NullReferenceException at admin/order/pdfpackagingslips +* Fixed System.NullReferenceException at admin/order/pdfpackagingslips ## SmartStore.NET 2.2.0 From 080d71de9d91672d6c6e60d86d5e8172ff767efe Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 5 May 2015 21:12:47 +0200 Subject: [PATCH 0095/1256] Refactoring: Replaced obsolete AppPath by FileSystemHelper --- .../Utilities/FileSystemHelper.cs | 1 - .../Controllers/Api/UploadsController.cs | 3 +- .../SmartStore.Web.Framework/AppPath.cs | 224 ------------------ .../Plugins/FeedPluginHelper.cs | 21 +- .../SmartStore.Web.Framework.csproj | 1 - .../WebApi/WebApiExtension.cs | 3 +- 6 files changed, 15 insertions(+), 238 deletions(-) delete mode 100644 src/Presentation/SmartStore.Web.Framework/AppPath.cs diff --git a/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs b/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs index 2f512f0c81..bac48f33cd 100644 --- a/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs +++ b/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Threading; -using System.Web.Hosting; namespace SmartStore.Utilities { diff --git a/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs b/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs index db18f02946..232860f3c8 100644 --- a/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs +++ b/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs @@ -10,6 +10,7 @@ using SmartStore.Core.Domain.Media; using SmartStore.Services.Catalog; using SmartStore.Services.Media; +using SmartStore.Utilities; using SmartStore.Web.Framework.WebApi; using SmartStore.Web.Framework.WebApi.OData; using SmartStore.Web.Framework.WebApi.Security; @@ -48,7 +49,7 @@ public async Task> PostProductImages() Product entity = null; string identifier = null; - string tempDir = AppPath.TempDir(); + string tempDir = FileSystemHelper.TempDir(); var provider = new MultipartFormDataStreamProvider(tempDir); try diff --git a/src/Presentation/SmartStore.Web.Framework/AppPath.cs b/src/Presentation/SmartStore.Web.Framework/AppPath.cs deleted file mode 100644 index 8752f45f19..0000000000 --- a/src/Presentation/SmartStore.Web.Framework/AppPath.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.IO; -using System.Threading; -using System.Web.Hosting; -using SmartStore.Utilities; - -namespace SmartStore -{ - [Obsolete("Use Core.Utilities.FileSystemHelper instead.")] - public static class AppPath - { - /// Returns physical path to temp directory - /// Name of a sub directory to be created and returned (optional) - public static string TempDir(string subDirectory = null) - { - string path = CommonHelper.GetAppSetting("sm:TempDirectory", "~/App_Data/_temp"); - path = HostingEnvironment.MapPath(path); - - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); - - if (subDirectory.HasValue()) - { - path = Path.Combine(path, subDirectory); - - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); - } - - return path; - } - - /// Safe way to cleanup the temp directory. Should be called via scheduled task. - public static void TempCleanup() - { - try - { - string dir = AppPath.TempDir(); - - if (!Directory.Exists(dir)) - return; - - FileInfo fi; - DateTime dtOld = DateTime.Now.Subtract(new TimeSpan(0, 5, 0, 0)); - var files = Directory.EnumerateFiles(dir); - - foreach (string file in files) - { - fi = new FileInfo(file); - - if (fi != null && fi.LastWriteTime < dtOld) - AppPath.Delete(file); - } - } - catch (Exception exc) - { - exc.Dump(); - } - } - - /// Safe way to delete a file. - public static bool Delete(string path) - { - if (path.IsEmpty()) - return true; - - bool result = true; - try - { - if (Directory.Exists(path)) - { - throw new MemberAccessException("Deleting folders cause of security reasons not possible: {0}".FormatWith(path)); - } - - System.IO.File.Delete(path); // no exception, if file doesn't exists - } - catch (Exception exc) - { - result = false; - exc.Dump(); - } - return result; - } - - /// Safe way to copy a file. - public static bool Copy(string sourcePath, string destinationPath, bool overwrite = true, bool deleteSource = false) - { - bool result = true; - try - { - System.IO.File.Copy(sourcePath, destinationPath, overwrite); - - if (deleteSource) - Delete(sourcePath); - } - catch (Exception exc) - { - result = false; - exc.Dump(); - } - return result; - } - - public static void CopyDirectory(DirectoryInfo source, DirectoryInfo target, bool overwrite = true) - { - foreach (FileInfo fi in source.GetFiles()) - { - try - { - fi.CopyTo(Path.Combine(target.ToString(), fi.Name), overwrite); - } - catch (Exception exc) - { - exc.Dump(); - } - } - - foreach (DirectoryInfo sourceSubDir in source.GetDirectories()) - { - try - { - DirectoryInfo targetSubDir = target.CreateSubdirectory(sourceSubDir.Name); - CopyDirectory(sourceSubDir, targetSubDir, overwrite); - } - catch (Exception exc) - { - exc.Dump(); - } - } - } - - /// - /// Safe way to delete all directory content - /// - /// A directory path - public static void ClearDirectory(string directoryPath, bool selfToo) - { - if (directoryPath.IsEmpty()) - return; - - try - { - var dir = new DirectoryInfo(directoryPath); - - foreach (var fi in dir.GetFiles()) - { - try - { - fi.IsReadOnly = false; - fi.Delete(); - } - catch (Exception) - { - try - { - Thread.Sleep(0); - fi.Delete(); - } - catch (Exception) { } - } - } - - foreach (var di in dir.GetDirectories()) - { - ClearDirectory(di.FullName, false); - - try - { - di.Delete(); - } - catch (Exception) - { - try - { - Thread.Sleep(0); - di.Delete(); - } - catch (Exception) { } - } - } - } - catch (Exception) { } - - if (selfToo) - { - try - { - Directory.Delete(directoryPath, true); // just deletes the (now empty) directory - } - catch (Exception) { } - } - } - - /// - /// Safe way to count files in a directory - /// - /// A directory path - /// File count - public static int CountFiles(string directoryPath) - { - try - { - return Directory.GetFiles(directoryPath).Length; - } - catch (Exception) { } - - return 0; - } - - /// - /// Safe way to empty a file - /// - /// File path - public static void ClearFile(string path) - { - try - { - if (path.HasValue()) - File.WriteAllText(path, ""); - } - catch (Exception) { } - } - } -} diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs index f78be083d9..633c273f42 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs @@ -23,6 +23,7 @@ using SmartStore.Services.Stores; using SmartStore.Services.Tasks; using SmartStore.Services.Tax; +using SmartStore.Utilities; namespace SmartStore.Web.Framework.Plugins { @@ -302,7 +303,7 @@ public FeedFileData GetFeedFileByStore(Store store, string secondFileName = null if (store == null) return null; - string dirTemp = AppPath.TempDir(); + string dirTemp = FileSystemHelper.TempDir(); string ext = extension ?? BaseSettings.ExportFormat; string dir = Path.Combine(HttpRuntime.AppDomainAppPath, "Content\\files\\exportimport"); string fileName = "{0}_{1}".FormatWith(store.Id, BaseSettings.StaticFileName); @@ -401,10 +402,10 @@ public void StartCreatingFeeds(Func createFeed, s var feedFile = GetFeedFileByStore(store, secondFileName); if (feedFile != null) { - AppPath.Delete(feedFile.FileTempPath); + FileSystemHelper.Delete(feedFile.FileTempPath); if (secondFileName.HasValue()) - AppPath.Delete(feedFile.CustomProperties["SecondFileTempPath"] as string); + FileSystemHelper.Delete(feedFile.CustomProperties["SecondFileTempPath"] as string); using (var stream = new FileStream(feedFile.FileTempPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) using (var logger = new TraceLogger(feedFile.LogPath)) @@ -421,10 +422,10 @@ public void StartCreatingFeeds(Func createFeed, s break; } - AppPath.Copy(feedFile.FileTempPath, feedFile.FilePath); + FileSystemHelper.Copy(feedFile.FileTempPath, feedFile.FilePath); if (secondFileName.HasValue()) - AppPath.Copy(context.SecondFilePath, feedFile.CustomProperties["SecondFilePath"] as string); + FileSystemHelper.Copy(context.SecondFilePath, feedFile.CustomProperties["SecondFilePath"] as string); } } } @@ -454,14 +455,14 @@ public void DeleteFeedFiles(string secondFileName = null) var feedFile = GetFeedFileByStore(store, secondFileName, ext); if (feedFile != null) { - AppPath.Delete(feedFile.FileTempPath); - AppPath.Delete(feedFile.FilePath); - AppPath.Delete(feedFile.LogPath); + FileSystemHelper.Delete(feedFile.FileTempPath); + FileSystemHelper.Delete(feedFile.FilePath); + FileSystemHelper.Delete(feedFile.LogPath); if (secondFileName.HasValue()) { - AppPath.Delete(feedFile.CustomProperties["SecondFilePath"] as string); - AppPath.Delete(feedFile.CustomProperties["SecondFileTempPath"] as string); + FileSystemHelper.Delete(feedFile.CustomProperties["SecondFilePath"] as string); + FileSystemHelper.Delete(feedFile.CustomProperties["SecondFileTempPath"] as string); } } } diff --git a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj index 9b7093b9ec..cd2f03fa0d 100644 --- a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj +++ b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj @@ -223,7 +223,6 @@ Properties\AssemblyVersionInfo.cs - diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiExtension.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiExtension.cs index 706ea47196..28f430b974 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiExtension.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiExtension.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Web.Http; using System.Web.Http.OData.Routing; +using SmartStore.Utilities; namespace SmartStore.Web.Framework.WebApi { @@ -102,7 +103,7 @@ public static void DeleteLocalFiles(this MultipartFormDataStreamProvider provide try { foreach (var file in provider.FileData) - AppPath.Delete(file.LocalFileName); + FileSystemHelper.Delete(file.LocalFileName); } catch { } } From 9d17f608f3ff3d818101ac052eac503a5c9ac92f Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 5 May 2015 19:33:38 +0200 Subject: [PATCH 0096/1256] Added missing file: Themes/web.config --- src/Presentation/SmartStore.Web/SmartStore.Web.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj index db6c846f95..e4db2c4359 100644 --- a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj +++ b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj @@ -1863,6 +1863,7 @@ + From d63962cbf75ba692d05d1663ecf6101a90f6aeb0 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 5 May 2015 22:32:40 +0200 Subject: [PATCH 0097/1256] PDF converter: fixed 'QFont::setPixelSize' bug --- changelog.md | 4 + ...5052021483_PdfConverterRoleFix.Designer.cs | 29 ++++ .../201505052021483_PdfConverterRoleFix.cs | 47 +++++++ .../201505052021483_PdfConverterRoleFix.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 7 + .../Installation/InstallDataSeeder.cs | 2 +- 6 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.resx diff --git a/changelog.md b/changelog.md index 26723c3a9f..1382f2738f 100644 --- a/changelog.md +++ b/changelog.md @@ -12,7 +12,11 @@ * Setting whether and how to display sub-categories on a category page (hide, above products, bottom of page) * Debitoor: Extend option "Book invoice if paid" to also (optionally) mail the invoice as a PDF +### Improvements +* PDF converter: first init is much faster now + ### Bugfixes +* PDF converter: fixed _QFont::setPixelSize_ bug * Fixed System.NullReferenceException at admin/order/pdfpackagingslips ## SmartStore.NET 2.2.0 diff --git a/src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.Designer.cs new file mode 100644 index 0000000000..c10a58454d --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class PdfConverterRoleFix : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(PdfConverterRoleFix)); + + string IMigrationMetadata.Id + { + get { return "201505052021483_PdfConverterRoleFix"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.cs b/src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.cs new file mode 100644 index 0000000000..1bd58e0760 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.cs @@ -0,0 +1,47 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Linq; + using System.Data.Entity; + using System.Data.Entity.Migrations; + using SmartStore.Core.Domain.Customers; + using SmartStore.Data.Setup; + + public partial class PdfConverterRoleFix : DbMigration, IDataSeeder + { + public override void Up() + { + } + + public override void Down() + { + } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + var pdfUser = context.Set().Include(x => x.CustomerRoles).FirstOrDefault(x => x.SystemName == SystemCustomerNames.PdfConverter); + + if (pdfUser == null) + return; + + if (!pdfUser.CustomerRoles.Any()) + { + var guestRole = pdfUser.CustomerRoles.FirstOrDefault(x => x.SystemName == SystemCustomerRoleNames.Guests); + if (guestRole == null) + { + guestRole = context.Set().FirstOrDefault(x => x.SystemName == SystemCustomerRoleNames.Guests); + if (guestRole != null) + { + pdfUser.CustomerRoles.Add(guestRole); + context.SaveChanges(); + } + } + } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.resx b/src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.resx new file mode 100644 index 0000000000..22e46cf0d4 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505052021483_PdfConverterRoleFix.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 3eb328e5e1..40f76cf62b 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -260,6 +260,10 @@ 201504290937512_SendEmailsManually.cs + + + 201505052021483_PdfConverterRoleFix.cs + @@ -508,6 +512,9 @@ 201504290937512_SendEmailsManually.cs + + 201505052021483_PdfConverterRoleFix.cs + diff --git a/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs b/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs index 99984bd4d1..60107decb1 100644 --- a/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs +++ b/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs @@ -156,7 +156,7 @@ private void PopulateCustomersAndUsers(string defaultUserEmail, string defaultUs SaveRange(customerRoles.Where(x => x != null)); //admin user - var adminUser = new Customer() + var adminUser = new Customer { CustomerGuid = Guid.NewGuid(), Email = defaultUserEmail, From 4fe978a95865d81dd52a6570db49f3241f016f81 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 6 May 2015 12:34:41 +0200 Subject: [PATCH 0098/1256] Minor change --- .../Views/Country/_CreateOrUpdate.cshtml | 220 +++++++++--------- 1 file changed, 111 insertions(+), 109 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml index dbd98e66ab..4c5884ad39 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml @@ -11,39 +11,40 @@ //generate an event EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "country-edit", this.Html, this.Model)); }) + @helper TabInfo() - { +{ @(Html.LocalizedEditor("country-info-localized", - @
- @(Html.Telerik().Grid(Model.Categories.Data) + @(Html.Telerik().Grid() .Name("categories-grid") .ClientEvents(events => events .OnDataBinding("onDataBinding")) @@ -65,7 +73,7 @@ .Width(100) .Centered(); }) - .Pageable(settings => settings.Total(Model.Categories.Total).PageSize(Model.GridPageSize).Position(GridPagerPosition.Both)) + .Pageable(settings => settings.PageSize(Model.GridPageSize).Position(GridPagerPosition.Both)) .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "Category")) .PreserveGridState() .EnableCustomBinding(true)) @@ -94,7 +102,8 @@ function onDataBinding(e) { var searchModel = { SearchCategoryName: $('#@Html.FieldIdFor(model => model.SearchCategoryName)').val(), - SearchAlias: $('#@Html.FieldIdFor(model => model.SearchAlias)').val() + SearchAlias: $('#@Html.FieldIdFor(model => model.SearchAlias)').val(), + SearchStoreId: $('#SearchStoreId').val() }; e.data = searchModel; } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Category/Tree.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Category/Tree.cshtml index c9e519ec94..68162d1e32 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Category/Tree.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Category/Tree.cshtml @@ -1,10 +1,10 @@ -@model IList +@model CategoryTreeModel @using Telerik.Web.Mvc.UI; @using SmartStore.Services.Catalog; @{ - //page title ViewBag.Title = T("Admin.Catalog.Categories.Manage").Text; } +
@@ -14,39 +14,79 @@  @T("Admin.Common.AddNew")
+ +@using (Html.BeginForm()) +{ + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.SearchStoreId) + + @Html.DropDownList("SearchStoreId", Model.AvailableStores) +
+   + + +
+} + +

+
@(Html.Telerik().TreeView() .Name("category-treeview") - .ClientEvents(events => events.OnNodeDropped("onNodeDropped")) + .ClientEvents(events => events.OnNodeDropped("onNodeDropped").OnDataBinding("onDataBinding")) .DataBinding(dataBinding => dataBinding.Ajax().Enabled(true).Select("TreeLoadChildren", "Category")) .ShowLines(true) .DragAndDrop(true)) - -
+ + \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml index a20f817342..ff0728c169 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml @@ -1,6 +1,5 @@ @using Telerik.Web.Mvc.UI @{ - //page title ViewBag.Title = T("Admin.Common.Stores").Text; }
@@ -30,17 +29,9 @@ columns.Bound(x => x.SslEnabled) .Template(item => @Html.SymbolForBool(item.SslEnabled)) .ClientTemplate(@Html.SymbolForBool("SslEnabled")) - .Width(100) .Centered(); columns.Bound(x => x.DisplayOrder) - .Width(100) .Centered(); - columns.Bound(x => x.Id) - .Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id })) - .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") - .Width(100) - .Centered() - .HeaderTemplate(T("Admin.Common.Edit").Text); }) .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "Store")) .EnableCustomBinding(true)) From f6b593320c66eb69cc26f2c3e7ee98b2649b5963 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 29 Apr 2015 15:09:31 +0200 Subject: [PATCH 0085/1256] Resolves #554 Flag to indicate that a new payment notification (IPN) arrived for an order since last opening\editing of the order --- changelog.md | 1 + .../SmartStore.Core/Domain/Orders/Order.cs | 6 + .../201504271444091_SendEmailsManually.resx | 126 ------------------ ...4290937512_SendEmailsManually.Designer.cs} | 2 +- ... => 201504290937512_SendEmailsManually.cs} | 11 ++ .../201504290937512_SendEmailsManually.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../ExportImport/ExportManager.cs | 5 + .../SmartStore.AmazonPay/Description.txt | 2 +- .../Services/AmazonPayService.cs | 17 ++- .../Services/IAmazonPayService.cs | 2 +- src/Plugins/SmartStore.AmazonPay/changelog.md | 4 + .../Controllers/PayPalDirectController.cs | 5 +- .../Controllers/PayPalExpressController.cs | 5 +- .../Controllers/PayPalStandardController.cs | 4 +- src/Plugins/SmartStore.PayPal/Description.txt | 2 +- src/Plugins/SmartStore.PayPal/changelog.md | 4 + .../UI/ScaffoldExtensions.cs | 15 +++ .../Controllers/OrderController.cs | 19 ++- .../Models/Orders/OrderModel.cs | 2 + .../Administration/Views/Order/List.cshtml | 3 +- 21 files changed, 216 insertions(+), 155 deletions(-) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201504271444091_SendEmailsManually.resx rename src/Libraries/SmartStore.Data/Migrations/{201504271444091_SendEmailsManually.Designer.cs => 201504290937512_SendEmailsManually.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201504271444091_SendEmailsManually.cs => 201504290937512_SendEmailsManually.cs} (83%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.resx diff --git a/changelog.md b/changelog.md index 5b0e3141c9..63252bc2c8 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,7 @@ * New option to display product thumbnails in instant search (NOTE: the feature can be enabled via _Configuration > Settings > Catalog Settings > Search_) * #594 Option to prevent a message from being automatically sent * Category filtering by store for backend category tree and list +* #554 Flag to indicate that a new payment notification (IPN) arrived for an order since last opening\editing of the order ## SmartStore.NET 2.2.0 diff --git a/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs b/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs index edbf5ddf1f..2f4caea572 100644 --- a/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs +++ b/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs @@ -449,6 +449,12 @@ protected virtual SortedDictionary ParseTaxRates(string taxRat [DataMember] public int? RewardPointsRemaining { get; set; } + /// + /// Gets or sets a value indicating whether a new payment notification (IPN) arrived + /// + [DataMember] + public bool HasNewPaymentNotification { get; set; } + #endregion #region Navigation properties diff --git a/src/Libraries/SmartStore.Data/Migrations/201504271444091_SendEmailsManually.resx b/src/Libraries/SmartStore.Data/Migrations/201504271444091_SendEmailsManually.resx deleted file mode 100644 index dea3321b42..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201504271444091_SendEmailsManually.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201504271444091_SendEmailsManually.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201504271444091_SendEmailsManually.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.Designer.cs index 066d06f360..1a16386517 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201504271444091_SendEmailsManually.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class SendEmailsManually : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201504271444091_SendEmailsManually"; } + get { return "201504290937512_SendEmailsManually"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201504271444091_SendEmailsManually.cs b/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.cs similarity index 83% rename from src/Libraries/SmartStore.Data/Migrations/201504271444091_SendEmailsManually.cs rename to src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.cs index 8e9cfac8a4..a80896c5c9 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201504271444091_SendEmailsManually.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.cs @@ -8,6 +8,7 @@ public partial class SendEmailsManually : DbMigration, ILocaleResourcesProvider, { public override void Up() { + AddColumn("dbo.Order", "HasNewPaymentNotification", c => c.Boolean(nullable: false)); AddColumn("dbo.MessageTemplate", "SendManually", c => c.Boolean(nullable: false)); AddColumn("dbo.QueuedEmail", "SendManually", c => c.Boolean(nullable: false)); } @@ -16,6 +17,7 @@ public override void Down() { DropColumn("dbo.QueuedEmail", "SendManually"); DropColumn("dbo.MessageTemplate", "SendManually"); + DropColumn("dbo.Order", "HasNewPaymentNotification"); } public bool RollbackOnFailure @@ -65,6 +67,15 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Nur manuell senden", "Indicates whether emails derived from this message template should only be send manually.", "Legt fest, ob E-Mails, die von dieser Nachrichtenvorlage abgeleitet sind, ausschlielich manuell gesendet werden sollen."); + + + builder.AddOrUpdate("Admin.Orders.Payments.NewIpn", + "New IPN", + "Neue IPN"); + + builder.AddOrUpdate("Admin.Orders.Payments.NewIpn.Hint", + "A new notification from the payment provider has arrived in the order notes.", + "In den Auftragsnotizen ist eine neue Benachrichtigung vom Zahlungsanbieter eingetroffen."); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.resx b/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.resx new file mode 100644 index 0000000000..22e46cf0d4 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + H4sIAAAAAAAEAOy923LcOtIueD8R8w4OX+29o7e97O6O6H/FWrNDKku24rdltUq2/+4bBcWCJLRYZC0edOgd82RzMY80rzAAeMKZOJGsKteNXSKAD0AikUgkEon/7//5f3/7X8/r5NUjyAuYpb+/fvfml9evQBpnK5je/f66Km//599e/6//6//8P347Wa2fX31v8/0Z50Ml0+L31/dlufn17dsivgfrqHizhnGeFdlt+SbO1m+jVfb2/S+//Mfbd+/eAgTxGmG9evXbZZWWcA3IH+jPRZbGYFNWUfIlW4GkaL6jlCVBfXUerUGxiWLw++vlOsrLZZnl4M2HqIxevzpKYISasQTJ7etXUZpmZVSiRv76rQDLMs/Su+UGfYiSq5cNQPluo6QATeN/7bOb9uOX97gfb/uCLVRcFWW2tgR89+eGMG/54k7kfd0RDpHuBJG4fMG9JuT7/fXfq4h8+pbC8vUrvsJfF0mOMzMUXhAyo2wwffMB5iBGX1/e0EB/esVl/1PHJe/fvH/zy5tf/vRqUSVllYPfU1CVeZT86dVFdZPA+D/By1X2ANLf0ypJ6KajxqM05gP6dJFnG5CXL5fgtunQ2er1q7dsubd8wa4YVabu5lla/vn961fnqPLoJgEdZ1AkIb36CFKQRyVYXURlCfIUYwDSf6F2ri78b1sbYkU0pV6/+hI9fwbpXXn/++u/ojl0Cp/Bqv3QNACRFU1AVKbMKyBpoL7SD6CIc7ipeci37oGqYLFJopfPWRwlATpqVNnXfAXyoSHUI50VH8BthHiyhTnOsgRE6QDQb2/7GaWdZ6i6VRWXx1W6SsBZCdZHJaLJTVWCU5iUuPXWc2+BJF2S3b0Zgj7MRnVdPdGGa9UjdUQPBvQ9SipvtLPiIgdoGURSGqzseBuBnUeP8I4QWkm3168uQUKyFPdwUy+5gyx5TZc/zbP1ZZYYTBKq2PUyq/IYC5jMvuxVlN+BMtRMDjl1D3NVXVdDLN8ZURM7EFir9fihoGUszpD226J8ADFcR8nrV2juxrDRwv/2+tUSr6m/v/6LKd4FQFMkLaM7YD3z7bSWv/wSYjVf3md5aaaqoJ8BKqwlQycoCl8qfYIrcHVfrW/SCCa+YN/RwN8k3iNHhENx7yD8R9O1FjnAAuBr+q2MO5ZHX67g2l61/bZZeYApFzhu9SjmWubapcplmWuXSLtFvanBrMPXXBlNJ9msw+s3l1+2Zus6Y9cNow6YN13XaFtFw1+9OCgVGvFYkwhX56sLXEQ5qvNjnlUb1JAw+kWzCJylK/gIV1WUJC9bspRb1jr92o7aN2V9R6s1TBfZeg16PW60ylquBWu0JPtvOdHgPH1NP2VrcBFAV/wCyghN8acsXxWj64y4simHGdd3BUutaStMz46SJHtaENEP8kvwCMGTt4J6tNnk2SNYXSLZmd4tq7Uf35xnZWDEFu4KifeE67R3G8OBLqubfwE0/7Kj2FvP/wzXsMSNIyuZ9xAvH6rxJ12UVrdRjBWGHK165Tna8vSbgtGq/YhYbPRKzoqP8LZcRLn3hqnFCaFbXII/KpiDr+U9ongt/L05pcHsVRWdtH73SxihVmFNtoQx1mSOViuuDd59Ois+ZE9pkkX+290Gx3fkvqVJPcFbQO8+olGpJ9zXWwHT0f7UwJw8b2BO1OoP0QuPaQZxFJfwkUCEYPtPUbGMkI4DQo0qiyY0b7A13wqQH93lANBqnmtjGLAr8Dy+3nhWXIK4ymt0X+nRAC1e4gTUjfKVcTTiBchh5j37Okyy9hNgz7lyVizv4eYkxUW82fGsOEXDjwE3AYYEyVOIZ16UtIiLe2yAMDcrWzf/Kno+eUa7EO+5cFacFN7kRK1ZoO3QXZa/+DIOUnHQVugsfURTE8Ehtf/enxuRhhc/BDsywNZYgnj0GEFUFiYUqqeVV9pS5wULpgF7/jl7qnuNVxqE5jsoaIMAb1/I9v00y9s2HgO0+/I8aIrihwxby7H/kvepMN4NYsSzmpZoB9Jter01CmLTR6ME19U6zCDViNFzOERCALBqwCCYQFlFcwE38Lh6Oa7KsjcueMwtnPsHLO4TWJRhQJvJnwDEvEiuM8czrpgLpJ0TOBj7nz/RIMFXoK/JatwKmo3JIissTmdtl4UNwokSy46YYy5LtEdvz8Skx2TmWCfpygOpNWedpPhMLQh/NWKLQQYjM0Uj2CatE20+riCo56S3wEdrKCjK7uhwka1vYNqcogVkQtTm1hWhONpsEuivMf8A8O5+vKnI7mOCw/+AqxHRP41Lm26l8ZUnHZCfMAnnkBDORwIkwMXPbnsdJMQOwkeQv+DCltYT2kHcsuhxVIBm9Qmy7e7wvoCoqHJQO7+P66rc1Xm0Dunq1cHiHyy0GWmJ0wI50RqwQIUxrzdOHSDHfhKhDB8MKKZGaMzlfVbbU5DgC+dE2yyJ3RIp9VVpU6+b3FdZbyvvnVXUuQQPIk1WW4chWhroHG2u2YyCjw2TrnKvYTM5ugP1PjqGHl3uDk6DnlsKhyjLHjUGL7IhVneoNYtpHJ34LKoOCPkcG04fImrbTmfUtF+WTdUHaV7HflxAgqPtQpNH03ouh6rhfDbHNneH4Oom11k0LWYzqBrM5XJsL9mB3sKYZKH9ddXtlxfR9EdfQNW/gVKO/b2K7rSdu2byifKUSlaKUzqPozT9HuUQKXWyfaS2+ZpymgEyKKUaJZOijkPFQ1t13KK3tl107hd7I1TDg2xGkQnpdCUXMpls2ZA/G9Y0ls8qNpfNoWwwl822ybQNR9LcLlnGGUKiwAtiDtnoG3sg9/dSHC4GN0pt9+vghayua8An9/04PrntyITw1PhW4L1SoNtG6vtLwY1abVW2u3Lrk9/GZOZg52qsZA4lG++qYpFVmyxdIE7xtkwJSPLjtzCnb2RkiH8kmWW+PNojYeLZ+oEMbeOvsoGtmLjxpgvo9vJ9PmFZ0ma2XZwkJoYxLBLDfRCMF8YWiQaq4XzsWDXQCXkJST9kGdVdkeb2ug7U7rs97gO1EIelWF3XwFI80vUYfFslUM1DBvzp7kocZyXi00kv4eCwP6OvTO00CnX95nBhJkjP6vt3oRwAG0ub5UkVvj+1hP8GfnUzV3+Kq6yO38FjO3vkNDhfWecxj32HgQfQZZTeaX22goUQCHiTbQT/hS2+ObRtp+B7GXBAIBUJOvUdgqcv+k2VozQOffjosGUZPoCU7G+MrbC1mJa2vj+pajP1LebTBE1eyOB3l79tgbXu/gWsYPSmKX9Q3DXiqybRMUyjvHdZb/4ymUhDfoZrgDG1S9goN+dBdgoTkOp3B38OdPnxHDxZy+2gJ6TiVJXnGDwh5ea127RlMP0jcRym8VRRvlTq+3Q6iNOS5TwbFMdVqkljOYPD+jYMtTVE8ByJ/S3IKRaFd5jF2nlDyBVg/vFkv6wSsHwpSrAeMJiFsV8sN2D006FjmCTYuxBX4m+56C5/hoG7BAWibUw2ml04EjRvLS0jPUwn4XXmgDCDR1UavWDmqe9xTllxOxrD1pbQNTd2ActxOnlGgqoOoj7ZXrT3MxjvpEa5C9We67itPYy3q0dMdRrosNqo6xpYCMaJqb7Ikiz/BJ5JmObJa9+JMOu2+6wAR5wc0mHWqOsKtNMKdeByVpyCCA9EqyDMaD9WrlQ9hxr42veZ1c723Q/FpkjMOMIWzuV2wFB7g+ziLkR3fX/ZQKMd5MPo8oEm908hI1huNbzXwhbSX25h/lDMQ3WBEeSHzw0dk/YHkSWBhMhBemyzH9Wkni0UJxxcgbbLFejgvLODzjsHf5bd82dxOuViF3fxjEuWLigK0kwhdhv1lVX/fUaNE0xHeIUjPDT1E++WRsQssrTEp1tT6PJD0juUCRsTbpKAqHXYcj+ifALJ5rZK/gEKEmQ0CNh55oLlo8Pb3vdW6O2KW+GWDa1RGlqkoCjQXB0KcSCUuebms6JHyhL6K+3qYl5nB+2sdhE/rc7R/TrsT9R1tTT6WMGu1vq3QxTnAeesQPEoT9bUs2LjVXMRFQXegIwufNuKTrN8Hfl7/DRoyygZf92Y9LWXgGGWj25vYQIDbFRJ9F3v3UwgzfqsqB1CjmLmGUVnH/3pvEs+R0V5tjlardB+Z3zfgKD7Btz0z9kdTB0vJ+PybQxnJYT7pdyapAqVoRX+11Q2yjdcSBW9w8UstqpO4/TTjb2umXxeSVvZLOoGc/lsW83vOnTNbvJc9zqN2G4+j6B0KTPa3hSgfZcGyM1llVCbyaEmNpvNltYnz1iliZKjqrzHSk0dZOgSxLV1UNIDXQnpMBgVEMbErJTtACE1oFpfZIXiLkqXLO2ImCq0WpLFqYlX2QbGmjaSdHUj2WR5K7k8ts0kJiZ5C0mStHFsitAuLtm2SZcA7TJS7GMFVAPMZJE2UZ5DaKoim32Tn6J8dZHBtCw+waJUHftL8ilar84n6YMms21PWh9Eo7VGyCwRf1wetQDkM1pHeKICb6qjNvK5pORXZhJor87ptbXvCGq/s0cbjSx90wAcdvXquk5hXpSTae6TVDS06w+0NcjWmyh9maAeuVP6wI4McQcOlPoI09j2VG9BPT0yoj2ATM13U1X0fvSK/gk3WFeKkoFgT4FMQfdZCgafkQz0MnD7ft6W77fVO5l6DkmXwnah7fL0CyCXJCzafLr1Wk1PUm3juJxiE5kMyoayufyCK7Xk8vDWbzAOy7O6roEF0zQ8j4tHRtEYPrwtqAQsVOT6q6fsM8BEPCuyAUH7PoBAurrPATCt8M8BKkSCFuQw5irzfHT5e+Rt4g3nGzKCA6l4eay7tibd/NB5rvvCtTziInUM55ZshwaLWG9Iacmt6BYj3CXLmTSD2HhpLq99HEsPhyWjBeCG7rBwaOTI3nuThvMOO7tLEa3rp1/tnegMpBIlWKaQR7z6ZyHC3OY3q516aIQM0mF6q+sKdFV9JvXy5iYHjzAaEBNhYk9uteKi25g6rufC5Neu+l4uV92RZgDPqwbrMOc1c74hlfedMAP3iTC+8Gc4CCRivb164G/wvDz8Eb/qtEjpC+A0rY+T7K7z0LKe0rh08YbC2A4/7qYxk/hG485jE7D1BFW7vDSIUpaiaH3dZ+zZSZYusJI0kzcb1U3x4CEMcFgL1HV9jtK7Krrz9koMdT/BNn5TtgpxxOR00axmdu/LUu3K1uAtJA+J2irjWRketH7wbGTBN89jLYern9t4iXCkIzxqnZJbUZxWQ974qV0yTZvaymZlMwlqn4ttI5MoXa7ZHF5rdd8I67WaBFKC/yaZ37Q4hyVbXdc8tpZ2ZBqqa7d8Y9SPSv9RgSWY4rDuNInuztaoszj88wC5g4T5uiz390mCEaxddey1ejAuQUFEm1yYy3JKJaY2oyDe9bm9zrhk0N5SVYJ5kLDDsi5AAFdC6wERMtIjk23tQ2ESR9oknRV4dl0k1R1MBSEyeO0uq2KZ8AmiOgUSCrxKZSZCnITCheL+c6hQCRTkdljbmNb5TsMfUdF0MNyZ7AV7w33Ky/Ha+//Dd+qdGPAcPBXuJl1c+g0FsR081lp0J4msMaX5GFMa354IZz5uEaWMTg3sdZ+xZ2tZusDE0kzeLFs3xZ1fcfmDoqSua8etx8v7LA8xHS2rPSWia+pag+3o5jHS/ow2962yqB6M5kF65rZl6ZZE2TZFSJSurmwO2ysm1Post7Q4aQG8XUWrKrjtnLIk+Z6VZEsWk9A61toAhije8EDbocPiVh2lxZODM496a9Nhyvc1HCGu6fzUZkadTdzBaPL67ZuppnmMew1xUAT1fDiyD+lIalF9IfHrLeK/foXdoifrMiwiFNOwmSJ1HnbqUUnS6UanW4cK5KarIjigv5wQwgAayBRnOeElIQ6yQV1XqE3iPPKhDknWaLrj38YOtkkL+hw72Xx9JAFkrjIsKWc8FdyK3ajvzsxtF0CktWwHwCRI5b275t/LWLWcN1yIZPJctlB5XSbA0EFuEmCgg1xX1zV0qvnXv45iPMsBCHYHPFRwTwTUSDSMww3BgGgNEs6zjcNZM7/n0mEShNN0dI2lDMjXsCgGouzxudTxAvU5RUmkz+6nXHLYLveWQVzlCFUgwEE+OcunUfXFeWRj/+zd6DV7BPsMNokFPcdszjtNYl3gTS9tQwd8mN0aXg90iXGaIG/tKNe9u4UThMBqq2wUkwlr/op5mXDfNFUdxTEoimkqvMAXoNGmdcxI5W4XQ0eKQMwLWbu4xU6ytgsX7CBYSdmiD1l8EKHqukisY+9HiAPJ4UCeUbb7povhK+xhwkfs/MVz6yjgvOTQBAo3bWAfonugiXRGWSOpWN/qZlKZ/OVZ0xgvgUYwDhJNXReh0tZINDxaGMAXqAm/p/NFMbyFZH822rwK4NP87xA8eULgkM9OAREUOKGGuMWr5a7dEcJ+LAh2Ty5IZa3iWQarNWGogU0maevIT13T6gz+S4Cn9D8IfnVdhEAf86zajHzKPNJdrSmdG8/7h1S8CBVkccASNMg+ZB+XiJ/r3eJ+Dqul+TWdiZPmVJpcmtMZ/KV50wgvkU4wDnJdI2T2Xhr/hHNc84KX6fyWvt0lEwBO87sZDOupXb/+Vf93mNXqugiBJnoJhNTl/dQw6fC2GBbYhyS9rQvsQ2GWb/wQ8uLQsFWwhoRBu4he8DWSoGB13OsJH6nt7oJUeQ7S+GWSF4Hayi6j3s/zA4jhOkpev7rI0S8ixV6/+9vrV0sc8uD3139zngus55TvOH2PyinFyrK6KZFITM7SOLnCsEbE+ot1t5jKTp6nqewKV4bGhjzsPFUPmUqn6WkjdabpYVPZpD1DFVlMZfvKGOGIVhGIVYQoOQVgbJqqax6bwOqax6Z2gz9+LE7CQ6MzaTvXx62FiJXRqkCKd5WuwOpoPWpP6Idpf4AcILYLEA/9HsQPWVUelYiPbqoSTLn3FSov/ms9wYObjeoR6l7S0e0tTCCak8H2B5vRaUAu9OBNDX5sNwdIfi0Qb7G6kzNLISTaDX68gcRNnkQNF2gzXuSBqHgAK9WQjNrDxePj+I+b4opOnjcwJ4aEL1la3k9c5z9AND496flVv0r0AdxA73smFNRRTNbNT1mymoA/xIonYkyq4uMofZhkA8zVOYmIoes8W0xZXfcg0HRVnt1EEygXzWpKFMAudt3Y875CG4K8ibt6lUdpEcX4Z68aTF71JFNGVfklKKpkfLIvog02pE9LcLHSiXq7rG46HX3aLl9UeXwfFWBKA/5FBF1vafPvhY49Lk11eH+OBM6mqk9LJrcafwAJKPfqqSzNTvgS4KM36jKw0bHFp6g4B0+NFec8wxdjYuYZQf+b/OwpjfTIk0yjaz5jf+wpSxdcG6SZbJ3otI5+dQ0yHz82RdE0Z8++1jb0rUC79E+wKDPFC4eyjNfNIW7fWHUu4ThZk9X2EY+P8JZs5AY7Ict4/a0Aqx+wvBc6M5xb6JRBEdvOkVI4SJuGv0kMN6H9XJLQWD7dqWXndUwnVctwsqJlfZK8ZVS6bcsuwQqANVjRQuxE+XgnnWuQKQYzC50ZLmH9wDhquzpKYJsqkp1NkT6FTiW7tGpjJI2FnLy04zIohB6fy8vfTC4IHZ5HrmEKqcA8OKyo6+qOQT0tvLVU8zUTj/MwVn8SY7rC9iUGFtn2ozBX9Llt9YVGpoyhIBg1nJVcTjNdri24OqLJ0A7TXF1XSy/fGcqsoCHAmCdcgh8sjiRQWmqaa7t9iQFFt/0ozEt9bluBwilaUyjtRh2S63ReAsdfyBwEi7qu1m5GSQXZ+xxm0imEo9zIrgpnRdtYEt4sCmCNagEXWbWZyKh9iYixgdhANIXVrqttmog0S5DifewUPaurmqZbX9Bmiwp4Olo9Z0XPHcR8OLe9dSQDlP2SbGR2EhZw097IJam2P9eqMmKPFFmVq7Iqv9eSTLXQ6wbK4fEik804IpL37ZAgev5F/VqbL8zfq6jpvdemI4XlRQ7j0V14u4pG99idojeT9GRsD+PWtlHriGOTjK1tbNrN4uY6rXvrh+wpTbJoFeD9qbOiBQumxn9GEyQtQItruQXC0voHgHf3FluXgbt0VbpKAFKzovEdGWoBvyCB7ULxt1JROiqKLMZeyatWWZGfegTUklSa35BW5W/ftTholB7XSA4ijRXSelQHmtXlkjWsSdQ0rc3hr1eek8cbvPRKDHHQK9V1BdEGz6lHNqYLh9hexcx6Z4+t3NMOSAKzg33pdJMc/DtNNsnBuleYaAneYQ5q+C7QVfua4CEwjqMkSmPguS0rRr9lNpUBbSTJoHVkk3m7yNzadPkEsaHNHP7EKbBDkElvAh43tW48Lm9gNB41nQ/RQf6p6wqig1zlUfyAKD6Roze5pBt2d0d4Bri6j38ACXwE+Ytj8cl1H2PnOn7SK3zvbF3+1I6gdI7rXgaIDWQyKJ0A2VxeoZ5oyBBC6WB0H56RhE5BPOlkh+jT2MsHJ0PIeaCar/LZ4rhfQeyYXoI/8COP7gYCBuYwDzTzIERAsWCTINR2Kczh0yWIiiw9zfKam6Y3gzT8C4jZO8gBgV8D9JenzIa2uQE7ftyYZRnd3p5nU4SoOVqtYTp8tfcvvwR5wYORbWHiym3RFTvXHTVFE8VeWpZDsu+UZvPcbGZEOVugRcjPn4JHOqxsuvkfYGW7iPJGv7E8IazP8xwK0kMcwsMymAUyjFvIPCGW0JQEOeIh7BYxmsUyjNKxC6K4Z27F7oKVUtd0fnqPocwm2Wmo8wa9YyxUJFtLlJmG2+1skdWd7wq1SI55VXmGmxzk0LcBWW7QXGvvuHeywOVEKiqjJLt7o8U9LI+jy3M54b9u2EAgjmsFDl51ChPUsQCPrCO+fvqaNt2+oI6W3INgOUfMd5rlWlaXTXmjAuLrxUalrG2zGj5x6K0ezpQEOhRLumih/HYP2q46C04d7EFu2gq8kV97GtfNZgwJJieT4iH2uac6f74TQGr4yUW5lqetV4FDKYD2xUXd0AFjBOEXXOwdBN7PIJp03Ks4L55+yglnzR7T1mendhXd+W/LEMhhajlPrb8EelVsaK3WrsrX/VAWkuWWTlato0yeELz5PcphlPbh2hfZ+gamkadGPAx+4GV1XcuHKgArD9y9L6HuEDRMJV+itLqNYjyI+QUa7UGvszDVWtqmB243kYaEQvsBV+HAPoW9NhUVgFDO1hvZEBb/YKGNDnGOigLepWgWQcJHZyvdGfS7MMfCrZcgtu1bnjm1Jxf4EqztTbiCXMnzNqbt5PESEpnxQ5hjH2Lr/FqVX28JaH3ea01UdVA1ijl0q71m8btmMQRNwLSoyrBmXD7kyYlB3WrDqkEpl866mljpWezaWRbDqsd0UZduM+VDnDXxlYVXDQ/64OgCvYEJZmi9As8l+rTejB8eH4fm+aOCuf9ldWq+pGWeJSH8QmY6veKnkIV4tZWpzoKU5zmX/kjtQaZlbHuoN7YadJUHJnEetWYBaYlrpeQdpIG2vMqwYAcSwvIQcDE5rCIGq8hRAqOBvVMAST2TiXu00C++mlIT5jW0ukRgD9yurktBN38/mh2aRAPekVmS5cs/qigHxeXdzeidqm1Lq3+hmUA79wf3Ha2vm05Q0VmBkNBCDuIAQZQ8dEgOiYiGEGrtZ5g+YEffOWPY2Wpb26NnGeqdZsqa04rUBuRyWH2+gBWM3rQAh3VGM28bGnkHnPzWR1D7life4kSEGj063TFMo/7RyfYvk+qGFqq0RIOBYUfvyylMQDrF6nvyjPpUhNdXZcvUOXiy4ydjEXMFQd6ctjlruB3GQcyo6wq0Cge5yNXeu8DrmuPpmK8hM+jdo8HbLbijUsWiY91rNmuvOshzCMqBIlvI45m+ComZUEjUtFBnCjR3RsSM6BKcA38p6v8O8kJd10TuULwOo9U2Rqp0WSQnKc7vvQdbghjxSphODHhuZIX22n4gP4bP2V3W+U3MdsbB971cJ8fZ6mWK55xrzbE98j4H5VOWPwQeXTuZ9yUiNwI9RV+DcpCA6rpq8vuyfY0yjzR1UNbMFfd7sAbE3HCTuKzDpHzxhoE5cKO6LkKo0ZeVQHxqYF/U1PI+zNo1JvcfR/HDWUq8w5bVDXV05LyJVSAepkTQAR5tXxwqssccEXAVrCeNtjCUV9j2DRYIuUVVVSbZsA5kNe5HkM0s7eZ+BdZIT/ZyapDBHQSJuq55tLPvEDyhpt5PX7PrVsyYnxEjgrssfwnAyzzUgY8PfDwZHzfCPQAbc0gHLj5w8WRcTIYCxl7uktl6naVveKQDG6vrCmM+Qj36mGfVZnq2RDXPMAsHTAMjeX+OaSo4ipNLEGdOr6mT8wQE96YDOcy4sWfcnAZb7cG4tXPh2Srp+hDYbeNb7sPU2Zuu/IGf95mfl0l1N32toa5Bf47Suyq6G2thWMb3YFUl4CoqHlwOUFCx4g0NcphL6rrmuVWC1u8sXXk+FRfIbdFabITxiCizzdf0JM8z72cjP0ckwn5eOjx4gMuepCvHkssqjkFRuNZLdz6Uq4a5+nl7CxPoZrzoyhb9z4OQUdd1tFrliE+8PWVAAgJcCHFcBNWPR9e9kx68dOxx3eXqj1qEROFwRczhd5wCogLxX/tsnDXff4A5iPErh28YpAPrq+saWF9NL4DZri4vRQnWiA5PZCsydfWXmHSGbsR/2z67YMPcH9A61lwk8J8pHdhhshwmyz5NlkWV5yCNXR7s7idJC3KYHM6T468jGd7qgVkgCF3lI00MMPa8+JxhAH+ympgvT7N8jQadeiVirPo+wzVELHaV1Z7NvgozmWDF/TZdxd6iB4j4PhLZhvbUaGSDX0QwlsqI16q1pwcmwSjeCFAHIa2ui6aT98XlUL6TZAS9Y5JlGxjvohenwL9S/011LmFTrsnqGREQPiJafEHbfPLwj+uEZXEOs1UzW0M4SmMeCjVTr7JQSIg//wVi7UOv42iMOHbh9FZ5HMYw8tZPzorGxHj8clSV9/6meQrwEumtG0hFzXHFHEmG0mysiPVCi5VrNj8d0kWZTRK5RZ3X1v29nzomradzK9veZxpqOZXTawkgpmn06XPmco8RlbpD8+0NhXKQ/uq6KDLhKrfmpsvgE90jydCRBAtHZvkxSZ/nWshPHZios4lHJ5q8QR9jpSuSCRVZura1wUVJTcYQ4gTnP4gUdV0zm5IHTITvx6nVySPC4srMehPBOxcDRrM6F29ajAPrOvPOWI5Ag9uUkSrGcTJ2bYkNaeU1nn8naColR3FcPy/jPgdpnMM8VNdF6KQT4n8d5bClMc0PrSCGlevrwjF6pu/hRZbz7yPZnhMUaCTDEMi27VFRDKgUI9VcL+7LwjtuJo7CCW4jNKuRECRzAZUaSWY1QsfjemIntjiog+RS1zWP9nkcx/XSUjvIAd2Zm2kTfHWWQEHGAuko01wKoNd3//jYQc+vlyBd4dAPUZK8jCRxzsFT8RngCeN56NoJHjniQf5o5I+UYt6nsDMpZGFmZdANx5i3Qf9egQqsGlq7zxoK5jBV1HVd5DDLvaMFYxun1pVplAUf1zroCxdi+b3Kpu/cVTZJ1y7BJnkJ0j+jeibp02IxehVI1xy9jv3SLsOuP/itghwCz3uDGEbRoOlUXHedVHdQxRrrJIdV1Pp4zWbuD6xUeYRDK2VGr4OrxT2IH7LK6xW7+mXiNwLUQSdQ1zUgpEe6k76TT50u0YTa4PwXdfSqULhnxVX0fPIMKGq4QiGgNkJcsOfKt+Nh11D2C/VpPy81NA+NyvNeS2RYL19NywgPihoX9HpEVF5LQCF8eGFxSGniKeY72+YR7YdnCUeSgOaSa3qZxeuI1sLOSWZd4nhgmK8vohfMAp9gge8VugstBeBBaqnr4knmK7TISGzphRO+r9J5puCha7FwP89MywjzzLhg0HkWboIdZpaGiV/iBNRLs+dswEAXIIfZyv+mShklBM/XGoMjF+EpGcJCFOowM1CkmbMUYjeHbZZkdBONpNg1W0ItupiMg/KKzW3roK1c/6cWy/yWzVqeO4llcosd/ps8KU3I4uTtTTBI5jcC4EE8q+sKE47SLaiiBIdENJgvPHJX/1xVTxUqWSmM2pGUSh9hZl332Xt5o84lCFJNVk9VLyGzoX0hxjnCPwt0ECTqui7aJ5fe+YmADuf9PEZac1NjnhUFmhaJP5fxUAc+21Y+s9BqfC7BHi6/DqyVd5/BI0i8z7Hvs7zsQlZMfZ/mFGUPV/nAZm7ThfAc2cFYeZN46JLA3cATy2EIgZgc5DnIp6hrwjhPQ15n4I+qjnPntYuv303+FBX6B3VcSOd2fVl1bVl7XTncNeUlaCKiOTy9k97Cuyqvd6wNzkHkq+ua537GHr5cQ/lWOL1P8PyGQjhwrDPH7uq7YySUmgvn4HJF/d+BbTRzn0RhGGCeQEphGifVCpylS4iqjDp7m7sHWHvVEyWUQRwNDO6OhqHFFSy1oVTD1DKJ2/IXUEZNFA+duh+usg+AujQ2QX3TjFXge3yXIEUi+aj4AVf1IYsXWo3yzywdnw51VT/yaNPo/0LbTcqjrfYTM25+PT/O8AIXQL4EuUtEOnYV6UIju4yFak0+KooshmS1YY1ZF5A8D37d/M8tjyfp6lUbAE6Wvd8o1Z2oI8/ROVGP0KoMN2gdRs36/fX/EAgzWEd3xkjVIQd/95pfzL+m9dH2K3xOjh3iFlERRytxeBDdVuwXsu2v7+0jLi6QRgHTUlQWYBrDTZQYdYErbahs4NZ19fApH8AGS4m0NBonkwY0ReTt6KrjqDdErN/eUhxox5iNqdyUaeo/x2XMpg4ZY7aG/W1nTLYLMzAmO05GjNma32dizHYHOygr+YwyZuw31OZsKOCaS8Zf3rx5JyA7MZKqEROwkIquuyDV0Ca7vit2tEGDgnXEpjf4ep9qwHWFZEzV5rdhKm0dEgYzZFwv0jQz3YYwbZHxyNLVYC72A9Ck/dFcucK+UwZkkZWyoUzQ9cq0fRK6SvIND6KTWDMi3QQyzohEJu1oy8+tx10jvoGPIH8hp04DGhaTWaPDOShvLLSM1+h2jrZ86loznRYmpbMRV1Hl5uasTh3olqQBFhAKaDjMRT9TVmOxjG7NTkHZi+m4VDleJk2gbwNvBZcabmT5/CPz6A7vZVV9mIFBd3A3i4Nx3EZkU5QP7mhlmWWMSeez4Uop/hy7W11DJuArHZ13YZfbMDXTDYYnBsSSsqBGCrry3GCVEv7T1bU1cnGwR9MJyMHxNGkKXW6rONtwRZeVmYifd3h11/VjJgbewVWeRO6B6d0XUN5nq+tLgNAg9rJYYNuA1vg4XFTGxGwpG/41qE+2jyKJAa2RyxIpdWjYHhGjgOsWXtloWW4pXeiMVmSR1mBOifkntLYHE0xl7RgZbSXrIrNN4sYPf5AZuXwyNuxc+s0ZkEc1Z71warmiDRMwj4Kmu8Q2rOgZGmZ2toRlIRZbwkhaKRmenaTtmZCppLQ2qZ8pON+BeHsjon+LQMUBYlbpoXh3L8PiUFxEljCWGdO69P0YJgnSWtoKBpvJ5g9OBQ7enBTi7HKgRuPu11+wGWovX0BHj86X0J4sQjWyRUxB9vkVqKFeTCCxhsbLaD2krvnNIq/qeAm1pyXaXpCW9+EIVDykLSXjV1kBG6bVVyjh3D6iwrZxrlFXJmBfozE0aQcdtWQWHj5OsruLrCiH+VbIKePVNpMNf4rAO8WTyuZPwIfKMdkZ3mtea77uGEfHJXxmFQd2T0DbMaEAL+FDFYNvBx+qejARK6rGx6T6tszcFvlL8AjB0yeQbG6rJMU6L5MwZJwfKK6x0wslHYz1Q7Wr7fZN77aOq+06Np0h33CcLWz6dcHZ2B+//nVWgvWwIiDklDF1m8mGiUXgnVIElM2fgCuVY7ITigBufbt2dIyj4xI+s4oDHRQBKbyED1UMvh18qOrBRKyoGh+T6tsy8ykCWZIMS0Eml3RZRxmslnAGcKckn7TpU6zFsjHYCYmHW36UFk/YCyATokiwTEHlU/FZncWW22hgmWYoYeDt4DVJwyfiNslYGKl4KP+svPY9K4mpKs7y1TXFMTr2UJRR8SCd3ZYTVVUpuFLO7tvBmwNdmYhPB8bOlGfrUvNxLsjXsMBBeZqetCZ/3FH12Zi+mJR/uRJW/KuvTXMyhDOMcIJoRiR59uDnhzMR4+QZhzyKkqOqvMe8GJNEboCUtDEqLSOVrqAN+cwasFOHjlZdmkBKWo2xSXtmP448zfJqTcyugwwuZpVxc5fLhnUl0FZ8GsQhR92ICThLTdzdYSMSI8+Qj9i8SkZqovZZchIHPhMryVsxFS/JCbw7zHRN/q3f09AONpVRyUbWHESDStiHatvWrZmq9k/FeJLxMKm6L7UNQqzmGgMhU3d5DPFVI6uYb0v5TtL0aQUeMx7GfLcF6hfFL8NaEtXh8CoYBa7iPilfbwkLKvowqQ4njo9J9aTAbKxYPwJn6EksyyxjxSaeszkbSoHNHYgD6W+6VkzASDrqmlTPlpyZowb3A2y2gFy0mzYPedsn47qd3DG0caa+4Udp2uceu7hiKi7RltJFKqMLuMRzk1eoCT22fVxq1JUJmNZoDE3aMXuoMmlPaslnxU/c068jcy/7dOyQzN5SvmU6MRfTMuNm0ojuheP5FnfipqPnUS6fcnm39fvjcXeHBRUtn2qFF8dil5htKNyJkHMEhtvFgCbK1k/KdjsYvOQjvC0XEXaIQE2+jwqw+gHL+56DVOwyUE7Glm0RG64cqkYlFmXcH+5uu2GrJuA9w2Ew4kQpwuyMySgRHQsN8Yu0lI4pXbVGfYUS9lTNgvllqFFXJuRp7RiatKMts108/I2eYnaMzBSdjJvZWndHETXvzFxMLR1Pk8YwBedVW8+zEpjskfp8SpUVZ7FWWSnc3WFNRcunUlbFsdj+PdIleELT5yJDAEU7fwZt77pCMjaU5LdhSG11O2WlN+nJBNxqMn47YcGXdcRMERgsaSz2pPsfm4rcJoxX0CMcsJLcmtMTic2miplpe+2RQ92d5UXe8Anmq3wctn9xadtd75lbVhniCya3julsbXHyCmSx/BRcvT0sKO3ChJwoHSOT+juAed0L2oi9Zh4rXO6AzgY8sk/QOy+tWdWSqXRnFY1NeWqzBZ4rl6Cs8hS/egVMbkbIs8vVASqnneYsrWLHdGZdHybRlnXjtBN6ct9oQ7mnKhD80l5IAWilmWSk2kWU12vZcZWuEqA9m9GUkWspbHY7TUVdlfr8kOrDaIuFQcsmUUMGh8KkFX2pGVVkrieDy4ayxOhMuJvrx2A35uDXnVxFhF4MuVWoCozOqbvoazHUiTnYdAc9L9jYeEMcKs09GDnROVziTjKmtgcTcKV2jHaIJZcbEMPb5vb/UVnm8KYqgSmL6ktrWFZe0IGFB1qwgyxt1qPpWNxsjHeB5eU9+brBf14rOFK5uttjSRUMDYyVsuHQHJmN2Whazj9VPLo7hcbizhtGlkUpwpYuJFoGd5PtevLOtuRom2U81+RTf/4Z59/32VcsE75xn381ztyzsF2Wr6I7TXw4Ma9m3jjMEAZZrYKh5HARzxrM71EOo7TshmWRrW9gSjJeoxkDH0H+cgXXmri2djgawmkgHGhq3CDZ3Uu646NZYR0bOp1csB1Tk5bR5eae/Lr+GW7oDCC2guN3eH9n0a3tmBo7uNMz6NXfK5SCOONbCr1mBY2zFVODaZBkfjAdn3MxkDV0OzheNqYmLaPLbRvvu64ADmI/AEPvk4DfHqm+R6K87cqwpc4UYB4G15rjhD7uGsvPYX2zHW+LSbA1xja+c9+jpOp6KHCrJWtqwSxmCcEJMFX07VFPm6FZu7Wzx6jD880kI/6wmFU8xNyTy2prYKr/u1jRtkqTn1ld3wud/HoZrTcJ+JA9pUkWqSMbyLMH5i4OXGY2bNs5Om/J2zIhd8kpbXQawJScjcOuIMhRr2PAvDii5DB5dhmHdTlteEwBb/n8CeGzuddofVcmYFH9UJk0gC63BQw6ZIgQco7AlrtoXlC2flIm3F0TAuWOX/80tIipymnWY/WlB4OVWVnfLjGrYV+mW+KHRtGkJUzBLWJne0aejoVdmDekbqluyiy8tw/is9upn8KkxNHdh6+pWWAY8SRX3ItFNU1xuda2hbJ3uIdzzIVhFjCXybNelzuO4oezdFlm8cOyuiniHNY+ZYO35oYKyqaCoozNDBisdqeu0pn2ZgIWNx1Pm03b1nH1kLIxUG5int5F3dmwLzMy9A5qMUe3tzBBX8D1UJgBIaeMZbtMNkwqIk/+HJCyCRNwk5KwJnXPHUeFvINlt7yriyifOnMVf5qqZnoydO61eJj4O7EKo/4+ohnzBbF+dAeuT/NsPch3mjLyzRWd3W4rpa5oerYzaM0k25xB4pu0gi63Lcx3ldmyXl9iVMajqpmd7cS2TM90ItlN2tCXmk9JQwr2Ixqcz9ndNfUbD6ZaXVOXkSpufRYr1U1Ti0yJ4xq/dXsMg/5MoREOj52RbsgW3Qr2HRSVsswjMexuGnZ0PZiYN3dSdfx7BSqwOllHMLkm/x7F+kckVQVkXEnlteFKZRUSzmTavHXcOdSTCTh0aLxMmkCXmy8S5D2IH7KKdzEVPqsjQxoCSCNFSstaxY00rV0mfoU+bh2n23ZvAs63HW8jec0XnjFkb1zliBR3F9ELCWV9lkKMO/R4gKaUPIAvW8Auhq+uMvPo+UF2YEaNmYArjUbAqB1Uua3hwvadCIFtTHlEBWDCm04PtBhWL+HWoakxv1C27d0M7D803iZN4svONhs+Z3GUwH+DVdvG689Reldhu5WKAdVFZBwv5LbhdU1VEu7uWr51XD3cjwn4eHjcTBrRlpmRYw2MEEPGB0ujg6uxYSs8/WeyM+yIfeGE3KJCZUpUAuTt7Zd1lJdfb/4F4hIngWc03jFpWJSmWUlQfv1WgEWSYzYofn9d5pUoMjH0EpSSK1vF61d1svLem8CMLNiQ25msgmF3Q9tKjWoxhdWADUJ8gAXZ68sw2rRBkEVUgrssh0CG0iS+DPcGxmWVSzGaJFOC6JCYHMbkwQ9rwBxglUNHKSrbMDQVKUqKyQTpMuu4diDYPAbjUef/EqXVbUTIpZscdLZB6CFMK7BW8EmZr1tgBkAadxIp4ToPnKGGYBZQzQKSNkz09qmRL6C8z1YyJDbHMCASuviKwiNafqQtYzIYE5tId/lk4LIMQh4n2d1FVkix2rRBkFa9koH0+u0QCNb0wLLEG4xLUJC1VwooyTcIfg6eCpXob9OG52SWJEdp8aSYil2qEZAKwpgJsMKi44D6EudQS0C+hkWBFAO0uctyKc/zeQZBT57RspxGyVFV3mPtpg7Oqa5Al3+wMuJapOLgLtEM5irbwFiJQ1JNgCIVglkrPuZZtVG2gqQOAhFrlQyjMf0ZrrzUo9lyySrJOCxmJU9yy9Hlr6obousAzeinEhhdohkMfvRZCVM/vT0AIz72KqeX9FFYgzVPpVn1r1wagqgoxr7HOdhb6jU1eTeZx+4G28Y+WSJvH/+0jJl6Jo8+rFHUVHGvh/qgiXIs7Y82nLVTZebVmBKPhEVWUorEIzYD0kQP1FSgDQLpVrFFbaZVmGBbg0qDCFk0vjmUHVpEmjAc0nWji2YyANLddZehUHEHBhXxTL4lJQlmxb9EREYoUZr04S7doz0qIemNXINjMgxr8PJrIVKFXnW1x2LHeAXWmySS86Msn6n94kUHzOcxFjEaTC7LsF4BUoB4TTsh+TzDO984UevFXeIgzLdcA9MlDrN5fA9WVQKuouJByuZU+nDX2gsm0q71N3aGeA9EBeKnHwDe3Uu1ASaDKdwHiNSRQjFN+DwGW7I8B2msMD7UicOamHBJQrkHsJq8rDuyfCawrt+DPNv54sm5lnKRNIciFmk9XO28OyhO1psI3kmJ16YN72ApRyzpjpXxhhtkOUJXreBksxiZMz6DEm2bh/hFnnOwAsqbTW70pxwOhwaEd+WRjozoeWULq1RiVD5lg9sQ2Qm6auOl8JCwrMME28yQRh2ZypssOeIebCzmzZXm3IPNMTyEeVYUqGCigeTzGPReKpVMpBH6VaoUvDppWLeLnrXHAH36ML2V1ii5IYo6KlSdyVx3Jy9UZunZTJeTP8sUQndwBbpz6643koMh4YR0ELU9vqZRFXDMoSnK6UClltWGqSS7fq/tD3fvPhCVuHv1ImoIKrWMq+MiIY+6D3xWGU3ouaQhhwA1Lru0Rs/ro80mgWB1ldHtFImiza/ula6YjFjUabKGVlpUCd3UQxCEcj1/mtCty23Tv7ZQSJp1mONOua5i+VG4hmTSAgY9lJULQDgprIR28n6GEvDso2Nq8a55nEwmhuVvkBlwxDCYjESs60Io2nQytNdPlPQR8w52SyiioZOh1Fcijy3F+IqH9QUhq3mvhjUGR3JNozTQJkGd4iDNp+6MLLuMRJyvi4Y8UsRJ1E6mZtb5RslQ6jKDDKAsqmExczIOViIhqRY9EF2H56g0u11Hh+eqHyGnmbKsj9P1JSjKHDE9WFEuViIVDUqpOztcWEZTwV1LQ06DGmTLRt9jf7LSrl7XnUuahJLSjJquyfJL6cV5o+nIJcUcmUJtICoNbfgs6h5wOWX0oNwONaTggSYiAucZqCYFm3G4H+zQepOFhZMQR891LnaI1j+faqjEEiHm0hgQhMxSa0Tv66ozRohYEqooiexDkGOYJEjGdS6zGqpwWQ26w5YIQB8OcCIiNY6x/W0cDZWEvMO94ovo6NS78RqQSwCWySHVADjQS+Zm21+zkxBNX0DdQW05GfkUjsIaGuqrkBCScmj2JmTrRa0lnphJ3Rshr4xIlF+3hjAi1ATEWGRrcvO0dy+X00PIp+8Hn9175klBJfRRktp963IJHiF4+gSSzW2VpFg6MgmaXcxQycENxwCAN1UNq9FIN1U1DuRuXf+1c1PMpO6dkFdGL+oygoZQItTIcxNX2PJ7fydCTg8hn74ffHZvLpKCSuijJLXL3MySRMsobAbNFKDzSY0F9f0Q3SxiIEZmjP5my3V9Q0XedTqLvuVUTlX3u3s2A0SgoWRmERklHUnwPSuJ/oBd6a7p2z5ycqiy6/ujKOUvdjXYCrophsCFetwNomvuDpOEgPoSmn5qC0q5TbwCpaOjHl+zbDV9DbfbGySiIqfB1myQaJZbvcmJpLtSpt36mRVUd9movIyiA5fmNFQ2q3Lk7WJ3005LXUkudb/EzDK60ff/NESSgE1BEeKqNUwSLttAN9jcSqK0/mNDVOHgpiDLNX2VUUETOs9AD6isCmpEw2SgQSQ0YK5mhmSO5maoljPqPEbjWPclDE/UWHJiCBT1Ehr0BVud2KDymcx1qi8hRAcFp+IQOYEdaFPHqRu26ErzqTsjyy6jTXuBWEMXKdTIVty6Tp085XIMNV8nRY1pMJXslN22vu4DxajdweQF1N3SltO5g/FXug18w+R1aHzDRqNkczfekIySAKDD/WPjf45AQDbm5yAzu05BYm9R0ovPMjB/+pzKWThsLuORpiGBxq1EzGTSeI0LiTUhpnEXaWMqXF+gFt9HBVj9gOU9FSNBJM1QEXXnBkrKyEbFg9BQbQhYxU6hjIuyUBfXfbgKNQ3lBYY7Ki2no5+FZNLXISGlcoxCUfIbPaDG5GRLWfaXKTwmYdmKRpd7OGLJgOinsgzIqT6nUuI14VOGJB6FNCYJJCFWtOqoNr+6S7piMkopIsRoiKatYWQ9Vlb34AwdLmTXWcdpY4nrOlaOfpvkQExJQi6Hul9sRpXvpfR2hg5nzIlJhxi67gMXqYnAZhzuA5NfR5JhFU0OKfOdU1HZeevc+sEOWhT4jEN7YC6/136axxrZqMDEkxqQ5tKcOgEhKyCXCmzUK63UkYKOLLT7xg+zkDKvwVmRASNZnj5NzE58MLFrOqiwTB6ps+tEiLKUXDYJQdC08kkNrt5MMgGWw1NRNy/VmS06qZudnvSbao4KFWvsE8q8Fv3SWCs8KTaN7YL1ORu+I8Rl1LgJyPKH9Z2blkTyUH8GJBsoONhZfXnNVStlGMNhAg/UOfL1K03sxmtVxEXJ9HaA0cxPezSpUNDHsdQJCIcGyBRqM6YIPk/0ATltJ48WzZW79RSecJppG2I8pgqm8ggewIQtVQ4Zk22QBHRu78gBNJZaRtXtD0UVTRRV02gLxhCDFDBF0lBaH0t2eBCMmzBdZAddk4bXb5PSXlQZXsnHHJNJlShdQ9h3dJyGg4HwogqNNNPAME2QjA73LtFYQ+QwQ9ynhcNccKLzvFzf1q5VX43LOndeq6iOQW2tYsrnGZH+9fO8ikSLsdDjWJNJC2cxRm0cUPuB0rdAPWiDXOKhdBouC5ay31TAm+mdM4nq62W03iSgDyWvpg6Xc7hLbAFvCnFwMt2vD5bvTZ8uLD5z70JGH0VOdYfkBWT0oQP3ayikAJzgikhfs2aJFzOZdEWzjFuTZdKlmrLz1z+HtR9lkcFZoSqpmW2aIwarGqYmphUZXQg4JulmIhr3zOfAKZpNcYvOq1GMSC0+b2pDeU3lU53CKV4M0R7GDZZRk2CoqDTShfL9E11sh6GKRj6oU9WvERRDRew7qxEaQYk6jQDpnhS51jgmiJnU3RHySoNlUa+c6KJlCVgjOyEI74QMX0K0nazqQsrLVua8pAEfeWqyr6Fcn+bZWkc6XXadrFeWki8s3Bsu2mVEDT0t6a4yC8JRmY371pcJTDQKeGSSUc/bXAtP3Ujklya7RvqoS0llGvPAj06qaXBl8k147Sco+XTMJs1n1jEdizlRairWoh7puWYfLBLpo8yr7pKqiIxO7HNCGjopQSW04h5p8ndwlL4TdC15mkji8GhaVuOuaAgh9SJSPYakc480rU/GppI3nQK44bIPHV2fpbCEUaK5EaAroO65tpzcN1d4pknrnquDH/dyivQZqmvxCalhYirLmndcBWFCYtNLLIY1Sqg+OKiuQTPpR7WGI2bKc6u7rC6kjJXJvwWmIagGfeQgY0MruOHKPbRiD67UY6zQv72tAbCTZwRTkHdpv73Fb2quo+bDb29RlhhsyipKvmQrkBRtQvv4bF+y+fJquYliLM7/5/L1q+d1kha/v74vy82vb98WBLp4s4ZxnhXZbfkmztZvo1X29v0vv/zH23fv3q5rjLcxsw/+jWttVxOaW2i0uVQc/noFTmFelB+iMrqJCkTxxWotZFuuo7z8evMvEJfE2/WZkyW/dVRuK2z1GPr4SBw5nIb1ybYU/t24UuIacavBG9y0N7pDsp6ip6iTWCCQ/gLFOZZYHAEs0eSJ8nbqNM0/WyFyZEm1Tvu/ef5Tl8b/suXrL+YIHwD17CMNxCRY4MFik0QvdUxdDpFNssZsVnoJZJNijnhWfAC3UZWUHPH7zyLWb285DuB57a3AbJwE4DnYiL+HrcY+PD+E7jAP7CHHmRt9A3gcNsUcsesID8gkOOAR3VoJ2qXa8PdFDtDCCPAbFjyPM0nby+eBGTsEJ0/Fuk3FPAj12XYaKBCFRHPcdrljAfuvVuK9sTxwol36gLIJ0gVAih3SLO7EFUhIn3KxXd5nealcccVUc+RatNIbbhpZTDVH/gRX4Oq+Wt+k5DlnGpZLMsf8Dgt4w6sH3UeLeVLdJLC450Uc9XlOJWORA/ze8df0WxmziGyKOeK3zUqByKZsm1APIsrdBfjEYhv3RCG62yQLzChHPSORJbunswVwRR7rCXmWruAjXKHtZfIinZxshj0RnVWSKIGFRAvtbrWGaROFntPsmBR7/gLrDX5JXcVjVLIVfZ++pp+yNbgQlk0+zRz1Cyij/wQvT3WUYhqTTbFDVI6WkGiHewVLflGiPluMfJJkT51DIrmOy/VensOihs0mzx7B6jLCMduXOEIsAy8mW8zVrByAl+ewb/1VVkaJnD7SHE59UFeizGQxaypisLrKjmJON2JTzBE/wzUscYPIWsa1WEi0aOlDxTUQf7CYH9RLk2i9Kc+R2scrSqo85rV8RNzEYtZfbHa+fVg8dtvbf7doT1NGtqTzaeaozfPVX8t77MbbujjR2PIc1jX0yoAcn0m3mL8VklsRDiWP1ICj1YpD4+fyYG4ru13nz88Z7rrvFip/U4YfWfq7hXKeJvX0pJz1GRVdkm4z/57r6fT1VoEvz2FPjZPnDczJMcWH6KWQU4bPY18LcXkgCLK5pc5lsXGNCv4KCLN5FZMtpClTkm+9mGrV6m8F2qvf5QCImqOYasGfdMErfL7CsqeYbDMvu/NSfmJSCTbyqym0eIkT8Bmkd+U9L8FkOVxruAA5zIRxVOVxqIUoGARGkMSyHDaUx/GrTtII7c4Eocgk2WCeIj5o42LxoGyazX5oBfFMjpK29OIeH6DyeyNVLpv2X0XPJ89oHySc71AJNngnhUBb8skcA1W8QJuyuyx/4dmMS7LSydB+7Cx9RDMWFa4fr+bRlZkspB322Zbbe7kka3MbKX/0GMEkuoGJAK/O5VaTvBPyHBbjAFMNuphqsRvInuq+Nw6C/ODK0q12SfD2hVgjTrO8bd8xQHtTYaekzmhxFBHFDxm2omLnBeEogk+03G+r7yQIG2/z6wvqOok1GA0tXFdr+bjLc9jWED0P1cDnsKQbWDVFIb80SZKtZh1ed46rl+OqLAXnAiHVGvkHLO4TWJQaeD6LBWVqWZMAxO4XaB8mHgrIc1gcDqDdECkKY24FZFNsrIMClDXG12Qlgem/WtsqF+QFX4mVsk6wWINwGKcokbSOTXFDXJZRjv2TAA6uIxyu6HO61XiSrozq4/NZcFhjXjxJsZeIjNFkGaxWPSx4GBQgYx9tRqsdsGF9uoxWOzH6Oja3DdPd1FZjovUaFNKINpJ+DGa26kv3Ps7RZpNAfq8gzWCO/wPAu3tuorffLKgj2efZ7+x+wBUP0nyyoJekP5+s+9OtEXrxosnmUJdOsCgzzXlMHvQQHyRA8HjqPu7m0b2mr108OMF+xqXZu/VgL1YelU+z0fwL0CxnEkOFmOqA/AVERZWDOhKOFJ3J4VDD0Vr0UhISHXDxDy02ncHW8YscXorWPiHR2qGsftxIbiRSZHGsA9NAX0WXw7kXfXxpbU/obFvjZNO/fOfjZaN698/AzUZddBw/G/yvp9d702Lp2QOXZmVhV3kecknb4tLYlpaJHz7Nxl7Y6DHizoZJMUds9BUBj/5ufTpaLLJqk6X4for0dJRJt9AdFKhuaO0okKN/ovyr+JXNYelxUJ+x1ZFlBY8DOnFrpF5jMofSJ+vNxV5reXcQe+qi2yr2sDebiNJ/tVE+w14bOs5KtFlXokqSbcycMBJMm+STjbmuHmuV750s/eAmp8eq3VZVp2JiqgUyJE5IAmT/2aaVd2AJ/81bVruvjm6BxVVWX8KR4w/ltW//V9lxiJBoaW6+jNI7fslgEuZ2QB3b8LU7DoDbaGbZ7zsXauqRO6bfIXj6ImiJQuLWKFyN9PS8y1GDuNzlUJUcR9lqqjuGaZS/SJeRNsnmxGQN6tBN7PFI+9VC7IDsFCYgFXQ5JsHGw+UccGf+zaftYb/63DAMFzJY7heLpubJgNdCQ6pI7mJ8ZotZs9Gv47uEMJ5RgB52NC3KOKzVVq0yLrihUR25rBKwfClKsBY3oAbZrQ7Z5fYsJsFiZwqTBNt8cTlxlyKm2mi8jYOjHFqSbGPiKkqkhxNdkQ6NLrq4qvO51HahvHAgy+FUQx2PqfZjVNfC5XKpqR0A6c5Jk81tlIgw0A1Pl8HCbPpc5hEWUJzVtP+8PSKZed3KSxZrHgUzEcLa4ttq2UNls/wTeCaxQni7M5NkvaxvSSifedXOQNZmFs3F6DyIsP2qp8ri52brOytO0ca+6i+UCfcV+OT951b6ImYQhqUB3ZlWj7L9jEu3X3LNgkk7MLATA4fjXE+WnYNX/dWA0MdyNBVUR1+qPIfjLz3W4ZBq9w6pDocz+3I4M5fXSjNbSIhbX6tjoxDUcUvc1TJV+e1XyCSi2FoM170XPWTp7xZoJB4Oh9R8s7l+kGxuq+QfoCC3wvl7CFyiNe55pobt0sJPmQHuPivw76+3/01w0WLnzH93cdViIabi9bZaYadLfbfYKGy6p6uYJvWfbTYdbegjfrfRf/85BbulDD5Osrs2lJs9X2pLj8STdXWiwGMSLM5HUBcuskIMLUt9n32UmJWukXSp5H0320VTCzXq+lnXr1hF+0Rz3B9R0fSGhaS/zz6O5+CpcJ9t2tLjzjZRUWFT5pu/mCiyIOn099nH/SJLku8ZVqMuQZzlwhvdJvN2EGKk+YrqPUqLJ1ELYFO2bovi6VeveIzFQlmbWkv7WEGFnlanWF0EylPBmNd/tTjBXQtRt5tPNsaVosAWNN6q0n61RzrN8nUkCUPMp9ojLyP+TQ42xcKQFTz8buiwUt2rr8LLD3SCBR4OAsSb6Jpv05uPzoraf6d7VpClGJdo4TWjcCJy8xb6HCENVb6v4pLm3A3hpnzO7mAqvQQnptoht8GjlOBChq1Zq/o3kX3WKsVjzwZLlbLkOCsVeUZLZH3qs93Ii1D912nXKCSON1H6Imi09UcbHKkvnZt/Xon4HX17hGksyGgh0aKNQiCvhW3grprt3vHrWvvVGum9FOm9DdI/4QZv96NEvPnKJVloBfdZCmSRppkEi/nThsjl5k//eQopP5deT+aA933Zeia5qPWqktt6mE6ON4vGw1dy8tkn2WLKo2bwaRbnIE/ZZ1CWaCNZZOL0E1MtkO9zAHTYknSLMarQ5grGUmQ+zeFO3veIdwFnUmY6nt01l5yWIVtfah/pwWI5CJEhgG2VJSM9sxnyScy7FJG6DrbMnzCxSdvDmbQO5smYNJQLX+rLj2VcDqfsBlgub25y8Fg/cMwtbEzKQewaMXd7fubH1y2K49mkvOg43Nw+Fy7EuKa+T+sacpytuI1a/cXWm642NUqfgOqSLDCbA/qm7EK0rslzWMiC/mEkdSXKTBZjFN1xRKm/WG3RtzrS1M/p2TqWl+TObblb0eUnw1sUBxmuLrqtinLb4kWVkKv10qWgS7Q4kkvhHxVYAslOk0uyMCcl0d3ZGrUHh1yQmGXFZAtHwpIzqZIP88/Bn1onq+87LsuceBEUWZX77jtkiC7z3AhmF/S2tvXidGJT7BElV2O5JKs7W3m2vkiqO/69QjbF6nA5q2JhXlGft2YWtJ5Bfpzfojj6ccmL7gKHh9iZkPeOOYW3/mSxelUJt8TUX+ZZC7Zdkz/s5HT1bJ/G/3PuyOa6dt55MnpeaOpwHB08VYXHWRdwjTKnzqn3TO2zr9+zkp97XNIe6+aY8P7c58h3u6mJ+HNe7XTXSE2ZP16XNJNWMUpQWbLgf6xAUSLtHM8siT7AJs95sLftmpWv7jCzmzyOlhbGVR4jebjLy4tvq51P/cKw6/vCCudsJ9dsVKiZbmK8Vj5tagft1neajLfUq7pOGduleq51HuRrWBRIma7v8Xiu+Ryay/o/CLGtczCsK30Xkozdp3Vft4aDTp5LfBEnOarKe1QpjIljQghu0iE7cJYd3DhcFvYKewhX8ZYqZytMk1vI60mydHv0RsQPVSLJZl7XVzywV9kD4IwG9HdLtKM4BkWhwmRSLTRy7NeEtE6VvJClb81sP83yau3vSNPBOMxjTdlxJu1VtoExD9F9nGvyi1eWbe8qn13II2BcbMUtrZ0LRkT4krBFgLlBcFwnh6LwOLOD1MhDdB9nmx2YBLL3CJkEay94qQO8pXGxlp68XbH5ao6E3zThYJpPNgawopRFG6G/26OpRlKWbo9OIklLceuUg8yyk1mRv7BylVOTiqiPeVZtpHKqS9nlKwzn3drDS5b28xxCCk9NqfrEJBwEliHPHGJIjqS2EREQQG0jOK7iUFF4W+1d238J68DdrwnN/Bi7Jrs9TyvKjcPOpDLZbXQmwRJPDGFEfbY5MpS8RePw/kzYHVJz3brZ6wvxBoVUm2Pi+rhJAS1JthwXfD2wEnC5JPv2ymHFVAtTX/1ukhxYSLTGra/tKu2Iqkz2HLeo8hyk8YvkGXZpDpsa6nKXEX/uz6bYt5k9WFTNGTGXxQ48KmUSh/psy9fVTYnDBZ+lcYIaJmNvPodjDSfPQzV0OexrICGPu6fudH2R5/SsUds3eU7bGhuRoOkbn8OxBk1f+ByONaCy4tyT53CUT0jOQ6wLRskpAFKSGWQPUbeUmAbZQ9QtJbNBdisnC1xEuALafrXkDznXuXBaO9skcH2SbevEiOv0d5vrLLdVugIr2ROXfJoN6lOUry4ymJbFD5ADNLa8A54ii8U6dw/ih6wqj8oyhzdVCZT7MX1OjxqL/1onA1XVWexXb5VrpizdwmUocIzITvPeKDTyjbUjJN4XIKGLNqhIHCwQi8hUDH1OGyeTfCW6ZPVf7ZBEFbT/aokk6bNbD79ExQNY6ampymPX5sXj43uxxfVXO6ST5w3MiXPKlywt70VQIYMr/j9AJKEyn+7GwR9gDuLyA7iB/C0cVSYbU1FXrIl5+ilLJGYjVS6fmmQcpM7lVNNxlD6IWy1pBmd8cbJKM7jhny3U0DjNCbWNeKdC7tKd0M9uIt6MySfarwtEJ5FGTZbnsJhpFdIZc/hvMk2v8igtohj/FBY2TT7/2kQm1ef0r/ESFBUf03oor4103OBICBp6ynP41CDrkTqXlcdCp+VpOqTJZnPJJI/vowIorbDSDDb7Kii/I8Ek2Fv8mrh3Untfm2aPijdcONhuVdZrtNZKZ1zI5mAmTMzxbTo+MdlpXYJ1BFPhBoQii3kdn6LiHDw1m/XzDHumxpK4bJpsW3Mc1G64vxVo7/QJFqX/I9wSSJd4tmYw4xwedRZIfs5Q3y0NFNLDCculYtfiM32Et2T/FJC5JJAuzGUGMw5ztXXzKPR3CwlagNUPWN5LmUxItMOVhHShPv8EjBuGVz34c7Kr9o06RnGL5M0qdS577pedwfFpFrsDibXW3kp7VrQtINcGI0Fnkmaw7zvamG5keyVZuo3mE8MNxKqGoFNySQ6YkptFfJqFXgxSrPWLqi/13RZN0kAmwcJCCIpCuM3efbThpp7sRPkTuUmSYY+laicxArgfOYa20pQd0Q0JV6hwHeqTptcnLwI+Ff33KiJUZqH6rxaKRwpL8ny89GRYTHVAlp77iqk2lFS117Wt6na6tlF64OxwrNzugerlVdppRRbXOqRkUGSxUBkGj0l9j0c1x6LOx6Efsqc0yaKVJM4Yl2SzULVFlWqPJIOF3zti2LQALYbgVC8mW7Qdyc8fAN7d8y/gUd8tXCCrdJUAvMpwzo/Ud2v5usA3U2UStk7YruX5nASy8l6eMYzr8iwvO+by7L+UngtRis7dAhNdZd3zrDKPdzp5jzVF2kIbxm4kIrqYjYxQxuHUsL7edRc4qdR8s0U5Rin4VRYJWJdkZ3eS7ebp79Pv5XZuBuFTpDpgqs+saVEcX5Ka8iX4UJL8Ko/iB9Qx2aEln2aBit0QZXoKk2B5sgjkR6B8mtU5IXwEufylWiHxJ5g9/sYKGsljFk1psujqlJyDt98dDCDyuWltP7Y3NMymw5RVnl6CP0ikSk/lhYJyUlu05Udio0CX3EIzUFhFKpzd6xJERZaeZnk9WrytnUu0wSXDDsjenTdxCInOuGpPDm1G+3GTB4kXU204Nbq9PReDO9PfLaw+qzVMpS5+bIoNpanpK786qMiym649sy36GflzgYRviIWfRXNa/IcgtltyX0R5o7qIN13pFFv7nAyRTbFRdnoay46kZemzbdoDnteMYZtue4VYGORgRQ4q5P1mc8yx2h7kXcs3yw2IO8/Efuz9wv7qoF1iANvhjSMWQ04/eU++bqQO2QN5LW/jnMIETT7BKZZPsxKhT1/ThgyqdwCYZGur+O48k6EbLE+FQoPsolxYwY2kaEjbYMb/kwc32g9OHIMHg3HfDoW62jVuaOQveQA6wMqOcNyXcWnhuUd63nH5HuUQKbHdTFhk6xuYRv6rxjC++zhagY60gjxU3GKBP1h45Jb8A6P1F4sTxiitbqMY387L0bZWehtYlcfSHUziB2blhgPSO/7yePvNHOUHXPEgzSeL+1OSg7BP9s46UQEIEWTHxUKiAy7+ocWmM1ho4UUB71K0+4WEI874hxJl6fZneDiUqHB9iUuz33hjJ0kelU+zcTyTPdnTf90f0wiSoPGD3HrBJVnu5r5W5ddbAtEEdhQ3dWKWbV/9Rlnywq1zu2hwaAopN1mydAv3BvBcok/i42DUd7uLE39UMJfdl2i/O0znRZaWeZbIrLyqPPu/IQg75wJMtsln2VECI0Fskk+TbigdYydvl+AmN0NHkd71ndNgIlwBN6oc59ugEMGybLvGzahsli//qKIcFJd3N9wBC59ouQ06Wv2rKkrxeF1ItNjUkM2HClhMtVnLLnKwBAmIJbcqmKQp1hoVIpkOsoWRSbC58ZE+4OM9qf4iJO6h81d7mcUzkkaD4hI9Q1l0HBnX1idec2RTrBzB26Lfcm4fxqfZt1OA9MQ7hmkkhCLj0mzkZ1qiUZVEYqQTzPFOYQJSQar3X82R8MOMaSFoKdRnG9l4Dp54mUg+bc08voIgJ+uK30TuYBxmsqbs9m87Q790gJ9eVjnTtGlzuJPY2GfnOg+sX3j3Ov7DP11O++Tl5j7yUa48wnJjtyYsi+QkjW4SXuGjv1uggbjKgdAm6rOF4V18xOuT9Qte2V3WmaY5zY5NmlOj/VSuk+Ns9cI3kf5uvR639vNzUD5l+YN0aRbybJcAaD4FkANNNldxoCw+jlSoq+cx+q+2SKKUob+Pt0DOpQfdgzUglgkkvjx1IRrKRR/Slx+HfUilnG27/jTlwiSJx2Ydi21HGO44ih/OUnJqRQek9WM9BagDExojjcOOwTz0A6r6YX3dd+7KKO3jcQXWSGnxPVORITqwqhnMturi+AXri4j3OOm/7vEJ3QIN1F2Wv4ThJh7NgZOGIQ5ctHVc1PpcBmEiDszDBfTAQrvDQh9BCnIYB3IV4NFcouMOQmz7JvI/wUv9uDOD1H+1QhJADnsKKR8fxckliDPfsM4djAPnaspuO8uGtXuMY9A/K85WieBOWn/bGjb8lgdhww7GgQ01ZX8uNlwmFXcPsv4yhw+z6oVD/cuGcxmT43uwqhJwFRUPnsZkCsnFmKwtvq3a5BLNvpR3/O8+WtglBQ8BW9cA6UmVyzFVmW2+pid5nuWCHtAn2MwGEsgkLwUDEJtih3iSrqR47XfL9lVxDIpC3kIqzbKNIg2pz1sjAboXUj21qRbGRZtSlx1n4h+tVjkaVMF9vP9sdVEnyKNcsuVHvfjMZR0FUVHloPak9DSL0lAu9lB9+a1dMcjLb2hz94TVNlbCsknmmJf4riaL1XzaY2tGM/4f4Lr2WAvCjR2aO0NqIA48uec8uajyHKSxb5DrBsYlsrW66LYyX9ti8RklNsWK9fh3k+zfxsDs9TlDicJjykySraXkNMvXUVlCPmyPmGrjpb+GSNm4yhrXQM5Ln0u0OFWubhJY3PO6DfV5Ts+wbYr8pex1hl8lRZsS4qrFOZUzSVsjwhALVutwrhoCnINMM8AYR7jRdYoXIsTUuZwsCIF4qO6jhRUi28CYx+k+7rHTx0VOXsNpHhTwPVulsZyOVvUAI/F6IFek0zxbq7ibT7PhTBUmm2I1t/8F4lKY0vVHi5aBZ8lleTvL8yWIJFfkI8sjk8bmcPxyVJX3vOVJkuyE3b10qISncuyxxCCWGZTwOfP0waaAnM4hNaVHsp31VUpDMIjJs/keyoJ3O8Tt3mXmxMjBGJScSXgxqRxhpBVtBKuG/3bX9pxmNqfF9SaCd57af4vi5KSoKrqthoxQGgW+1sSC1F/m3Br7mhhm4mLyZvRRTB4Y9eNkGsmBm/XFx+FoyUva1m9oN8YZcXIwCXYXF8V7i1ZGqSzn44WQLxZmngLkqdCh/qtFW6KiEBeX/qvtqrAs+PHqP1v17wO4jaqkRLN9hbgRRkkhdFaWZWvmbbP3DXT/ggVzOtkZQNjWJek4jmvJUx9s84JbkryLy1041y1aTAtOblza/Pb5JUhX+FZQlCR8LEomZWum9Tl4Kj6DsgR5OAOzHNNhkpsCjTTXpbWLRmddvmlVAzt/lelU1R1xYv97BSqwIlT3mwAUkAPXa0uPw+oXOcxyyEdr6b/a2ZpFC7MtgrjM9l9tLNS8XdqutNiK9pvFwTfYJC98Q7qP1jhik5gEi0m+4Kb2wlKJEdSW3VRURhB2aE5fkUfV+fW//WyHJWka9XluRWrnFJ7FPYgfsipUdF4BzsWuNoyxrbuZbY5OTR7rxpv1i/pirBxbncum3VfR88kzEMjAJFhQNXpuL4QLZ6tskoVuuOWxusPtJLdFsASI2CzHDCFiJo3SLNQuHCbKMkwpxw7Rj/1m72wPwcdVjh9VvIhecK2fYIEY39fXV47q4vprjDTOvOOr59Fk6ebo9SPxHGT3cY/P8nmyheW2AGw2mVx/iRMge/uKSbDEuwA5zFbCCsEm2WzjyyghpbkNGZNgY8tCw4cGDoi7MiZlDlt5qHtvZynEx0/SCc6n7fE8JxcK4L9JQH3cEd91hcdzWVEMMEY6ug4WZsDtMr4Sjdz6kAd94dMcUBWA9liSYDBMwtZw/SXAB6rtIxK+axuN5bSy6QHGMoc3QRrf8RuB/rsD2nsF2vu91tEXeVYUaDeSBOEoHs1lLzwIsb9cNdtK6umS7eaKPaELNqrqM3gEibCoUd9tTJdZXra3TThzJZ1icapWJYkUkEmwUBE3jYcKR7T+81wu5heoJ0JI/+6jzeb5FuQ5yAUsJmG/Lkee5uCPitxV5g5fu882rv4kaP+nqOA3h3TC1ogo9KGE3tH7axCXWEuqktt68vMTBTfsz1x8d4DU6Y1LeH5d6W3lk53TV8nlWs9hxhAuAywvN87Q1hduxAGmv9uYjOKkWoGzdAlR6YjbiIupVgcdjfc2Sijlxx1ihjk8xq9gyYemaD5N6dHyBZRRc42KU87YFDtE5SO6QqIdroRm1Of5HXovQYrE01HxA67uQMkrgmyaxbEgKfHPLOW6Tn+3RfuRR5tGtZKBMsm22GjX8SQZKSHRFvc4w8Kfn9B82hx+jKRDV9GdZDqTr9MvV0dFkcUQx2tKxTdRYUF8t66PNpsEYk6nFBbdK6jacvzy1OZWKSFojVyJq7+ygutlVuXSdxuNVrsOWrbsYWJ2bfFs5lWU4+nt2MyWWJbN/O2tdLx9WKKzv1kxRF9KxQ4KM5oRmVv0reaFrpF+nNDATM0IxMEN/YmW1ftsdX0JijKHWEla4F4OSQiT0sJelilTZzQRFsN1ebIJV0EAZjFosqf4qKk3NdO0prdr6h6aLjiemFuMglfnae2Dw7QVUT2HvwMMMPCSxvkNdIMz20AfwyRBnzvzrcFo80VUQ24z1iymJ005sJDDzkH7MaZ1w5Aiv4J4PF+dFedVkvz++jZKCmDZe2/muQD5GhY4sGr95ME1/byEloeGSgoBuLj8dHYD9tJX5zl6AngAPhtosOeaQmHNJm+MWUVVQiVtLFlDDr+NK82+sMAleIry1UUG07JoHGKvvxVg9QOW940xWOdRMlhY9CERihjwxWBFniPAYgXgk+EGb+MiNUSGcAKnVdVtNByhTAgVhwP15CMeLaTE4bG3kYGG+++v5jQb9+b/q+hOr9vIsosRRUlin8dEixGBfVUXJ5OEceOC2EsQUvAVqrW1YoN4BFOQ81k6Y27zpfu7aD/gAY3uwJdsBZKiL4ffTFpHpEfFJorJDn4FTmFeYNfw6CYqQJ3l9SvU9keIpF575NYYXP5IFkkdq7PN8CVK4S0oyqvsAaS/v37/y7v3r18dJTAqsN9Acvv61fM6SYtfYzJvozTNStL131/fl+Xm17dvC1Jj8WYN4zwrstvyTZyt30ar7C3C+vPbd+/egtX6LV+8gTVC+eU/WpSiWDFhC6iD02ac/15F5NO3FHK88dt/AoHT2hG+BLevVHLkt7d8wd8kvIWb8PtriClLZiN56pJ4l0Y4eEeKcwHSstevsLjBl0I7kfNWC1+fltYVpI9RHt9HSBH5Ej3XdyB+f/3XX6wxmUM1Y+gyF10wBGQ2Xv4Y2JQe15Dcsvc4ei2JhtWC3MAhEPqARcuAjWA5rtJVAs7QzOuuHZ7CpOQX851lyr5/XEX8RP/1LF2B599f/29S8NdXZ/91TZf90ysymr+++uXV/23dCOZGpzs7sPdW/bC465Hjs9ee8NNF61lsy0xdQS9Oqunp3AiuuFdT2hXMhwvbY6YWYwViuI4SvOqjXwVZvt/9DY0iFtK/v/6LgyCuT+cA0g+RlnMHzFndYYH7yy/WSwVxZdascv9tHT3/d1vQWoJTwT08Ov0JKV9X99X6JiVxuNyBvqPxvEm8BoB64cUdJNTizDosN/yLvpQQc4klGOurbAVmK5L3SxC30Tncx/EiylETyOW47o6VH2LD6Uj8QrR1aWL/TCd2jEDHkTsod2jMo9Uapl1w/ACALeM0QVP9hhq7fX1NP2VrcOG5uLB+iWEXGcE9MQAZKQfFsI09SpLsqTPNg0cInrwWsKPNJs8ewQq/8pfeLau1z3ifZ2VQvBaM3MPnOuvZvlCQTUS6q+wo9lr/Bf9Td6jlQxV8ikRpdRvFZZWDHK0I5TnSeHr9IFQtHxHLhMY8Kz7C23IR5V5aUYvhv542scO+lvcgv2C87dxa1sYi65ZmvXh894uDyKnwxqmEMV6qj1Yrrkqv5p8VH7KnNMkiP6W1wfAbmm9pUk/CFs6rZ4jo9Sz5eivgOW0GG5CT5w3MyQ72Q/SiQjTa/TWAJIYIAfTn7k9RsYyQ5gBCjCqLZL+d58ur9vMmxEIdw08NHN3lANC6lku/GKD62bEAGgcOgNiE+PGTJw0IE5/HR97ReBdddJ4AiEx0Hh9bHz4f7N7y8ZFlp2hQ28NGL6VsVR9qRkmLtrjH52QuhiDDplNBKH0ocFJ4kZALXek+qEhhwWFi0kc0xRBY7XvruZkps/ghkFkPm1gI3tFjBFFZmFCYHmYbaRudVi+YBuvv5+yp7mvzoJjfMCAdHt6+kH3vaZa37TsGaFvkA3scxQ/kNhE+rfU8iMBbNIx3VtOQfTXBY1DI8oVGBq6rdYiBqfGi51B4pONg1UBBEF4VRWyOMx9XL8dVWfZ7dccpg3P/gMV9AovSH7CZywlAfIkEM2NCdcFbIH2bQMHYzy5MAwRfOr4mq3EraLYZC/Li1Eh1LDcIJ0qcO2J0lkHV0cUBvIJrMGDUtsU+SVcBkVtT00lagrzw5sVGejGoYGQGaiTcpHWi/cIVBPXc9ZL5aPEERUlF3V7fwJTseEZlVtT+9nSwaC65+fSijmI8GrXZbUpw+B9wNSL6p3Fp061KoWVOBxxW4IQ6gAxzGtoGRvVYxbfkIFTaOfgI8hc8cPbWFba0j22Fdvazbwdb2qcdx1EBmhXU2xbQYX0BUVHlgDgyhnWj66o4Wo/pJNJVg3+wVTkYHWsXmzpGgsTy5Wvtbzx4QI59qkJYYhhATIaQeMv7rDbuRPkYPoyd+9B+uDQMHvS/dzjob2nkb/r+VoAwflRqr6zgukFblbsEMbSc0VHP/dSDRtkIgNQcYxWLrNpkKXbB91rmBRSV0cPVS4+cEJNV0I9Rexy8dFuYzo0Fjzz4y/4KHhcPI+wMZAtsxC2BHVmOsxJpYMHdlvDNlNATpWW7ML5LB48jxgMwzLHMBSQ+JA7+4W1BHwUfO6Et4b+BTw8Y/6viKqsvCfDITmbaBuMre1BgouqYOfYhHf4ySu8GzPJuXtqB3PwCm5220DlrW8wS++bnLSMSuRz2HYKnLxK1zEDImvuO19JpT/SdpjfHMI3y7jwQUe2GfHBbnNAAYpwByWM/wUF2ChOQDilSf3ZxHDwHT+YzzPaewZ6xzLz3vsZTK0aUpdZ2nGbDKr7etrNs0/bMwfrclfQdOZ60l1UC6PjWAVTz5QaMbmNpInk1sQB9r200TmchwPp4h1cZHVJIiWpmu2lBL5R+z05DRQHX7yTWnmOhwVsKK3R9T/RGT/Wi8MlzmUc42sSYehN9hrQnIm3QpuMQ5mGRJVn+CTw3j2eEBd++SA+2qtSemRtn1qUUhh6D+vuSXg04K07RlrLqL5hMv8215UD6etSBC0NwIU1R+zawpX8abtxDNhzl7CW46Z2i++HwIezhw+HAYLB1u3dgcLCnK3G2xZ5uftjfxlRuHg7aj3WHflfUUgvuSvrpHRsmCG24aX1WtCEQ9sGr1ZpN94w/P1awq6hK4R8VgATyFmIxZO/Clg8epbhc2zpZU9GxgqH27+8F0GBasNMsX0eeEY5arGXUx6bcrig/ge77Ht3ewgR6a7vkYqiXKhRgAT8raqv/UczE3HNyOwh7fPA5KkrlcuCEGFR64+Z9zu5gGsgvE+O1V4UNIG1OR+gA4HarugDgs62QxSO3a46IYN4e4yVT+gzTzq6YJL520DkZDEy6PLpN7Gy9idKXQFiy0z8TDbgt6DVHEDwOxfoI09hh+88V92nJgroV77mKk/n0LiTY+yBg/4Sbi6zA0VTcHKUkKtB9lgJ5lDC32IltNKW51z/zDYfsTcOdlZ6Ddth3DnZYYhormqXVSw8lQCHue109ZZ8BJtZZkQ1e5nhvy3dX9zkA5vh/tsVHUwTkMOawvcIafo+8VOEZYxIbz1T2gc6fZcJuw8FJsJcg7lJEvTpGloU12ZxDaG1iTxhkPPVuxgXl5iYHjzAafBDF4XbRLkiy4yS7w4rcnrDo5yi9q3AYN2se7Ut6Man0SFOQdGYWiGw1vIuwOFCsjYFBQj83WAvN1X6zKd1HVw4F2b+j5uuCu5VXkA/H/OEPhKfY27XiZU/k7ChrcUujRZWQiy76Y0z7sypy2LUEI+zSTpPo7myNmo6vFg3Sxt4r9rLcr8uI4+o0tWPyssQRfy9BIXnLcmfn3ez6TUvPQSZ3Ca3Sgku91t1UHxxhOVtfJNUdVEXqNDz9zKpYzfYeZybn4KnYo/fcZufQgBo4edMnDBQO3hEGKYgE3k7l9mfap2yH/nrYYLSwxvc3siQ5SounvfELwx1ycJYmpYLb89xEYvtqyves9HvYYey7P4hoe8I1sy/z4bin9r1qZF6Yo+wgS3SwEDlkWf1YgaJEWiyeI9vgtb6dGojzqmztVYwvtO+JLBjeC/71r/YKc6CHcYJ4rSKQhu8xhoLtjTRcb7/V1umU8M8oHqe6ofNRnEC+hgWOW3EJYixp95f5fdahUSZTd9/dD9h4rE+eMVWj5Kgq7zFdY6IM7NW4z37dJ5wLaDtaZ9Q9kICwjeQMjP4V89ZV9gDCbCMJ3FEcg6IIB0r8P9AAe3n3G0+60yyv1nt0ln+VbWBsP72aYn4RLeae3EZvPJrpCxcmtwJdYufu2n0+Mj8Id+zJBCEdsmfRptiOTxA8jrhmz7hltdOq3nboECLpvJbEXsao774PjeMbJ7gVnsHfGxTFkDuikfhdnpv13ZRA+yR8PuZZtXGUQE3ZcV1CnR74CHxCcd6sOl5zOYRAwXNPplQdxMooFs7dFE9kWu6JjNoJ8fDTslvd4/3gNNKXgNcNCV7QSB36+K67ofSzV+p9r+R7Noa7UO99I9/vyjEpiS8dVXxLHLsVAqsJiBwQqr5wFzhaRhePqspzkMYvwa40t4CXUX/mOhDG+2/Os5I9o/Kj9veoDC3M0E67RHMhOUvjBDXVkBx/cZPEbWUnz9NUdoUr6wLMT9RDptJpetrIhml62FQ2ac9QRRaT1b4yRowhwQ/x2hAlpwCMTVN1zWMTWF3z2NRu8MPcByN8Mjojdi+wjloLER2jVYE09QppO6uR36+4BE9RvrrI0AJX/AA5QKzlGaHwHsQPWVUelWUOb6oShN7qCRUU/7UOFMWnUQIUbnm2DmNhgrR1Wv8mSB+JGxvexuB3RnKA5MgCjT+rpzgNO0Kh3Xr8BgI3KZhiKvTPM+h08QBWKtJ5t3Tx+BgmthAGO3newJzsnL5kaXk/Au4/QBSm7zRffoBIuJUfwE3/drubk2UH0wQX/JQlq0BjJYIHZAQK/DhKH4JtpTjcYFOMxj1bhIZsIzoFhj27iQItSI2EJkpByGih2JsGTYh/149G51FaRDH7DvUo8MHYTVXBJSiqQBFaF9EG33IOTxwROGCr0b6z04nCN/2iwmULENqcehHBUB7iXOinIDRtIPFeBYdjrGqT4Si2rgBhb7floEG/I7gE6wimlPO4g7f2pwi/6NnsX88zbHmPmUhBAe8FtBu/bwVS3z9BJJf3JhLg7G82kqL2tTfF/BylJogt8hHeEn1+D1mn7Zr94PUlvcbvWwFWP2B578hCXHHvpjCREYJbVKZk1j1h0FZjoUYZLdcO92kVOD5ngi2p/c+DRrbknRVtU8n9qMhTQWnB0O5rE3BPcIk6u4FYEwiljHWI4e5yLEGKVedQLazhwjXvCygK6jar54sU/YgQ3Ww2tdbO5WWPgr10/QnqqjKjunYx7xuWf6+iZiDcZfW3FJbkIbaxTxS7ikY/QJyiN5P0ZOwDz3a/VK/XY5OMrW1s2o12Khf+NO5D9pQmWbTyDhJ0VrRQQRSjz4jF0wK0mF6vvWOp/wPAu3sntdCkhuMqXSXA8UF5pWhf4AuSYXjUbtk/x4E39mnZn2WBPqfCl/hdjGyd5bLunb8tVx5p6+Z+WXlmdyyuierln0oQjqMkwvH+fdS3YnTHmZCbsLCHAbT9w+GNM778CC+c4bOa9f48WjujJL/Ko/gBpncBj/mIW9u4Sgk5qwOhDhM/gAQ+gtzk0cJteaSqnQB7ZMXouuR0haMuGeB8SrQbj249sNA9yipPL8EfOIrcvgy7/42oQAM3u/4Twu50CaIiS0+zvOaVMEp6w3GA7H8N9vsuoKYuCFZXibggxr4vkdzenmehHNl1T0PzQXPtXyqgBUWIi1/b4m1isUBmxJtnEeV7tUj6S8uLKG8UBy/LU20Xcjtmpcv6vcfcD7L/8ers8n/mY4/x7kOg2QlyxP7YuD/afjrE6rlzYq4Z+eUG0bB1i+vGcU9k3szTQk7brxvW4dZ4r6JF85u/+AbEKUwQuT2j9dZBrxvy+ca9HvsRWA1B92QCyLsYive2JgL8LIyyJyyyM6PQCJWr6G6PKW/5XrMt8b5HOUS6TsfDaBd5A9NonyTeQ2VDUyM3zBLqnxZ2eUknSqvbKMb3fHK0rVLc4POtxVltNnpqgbRrLPQfcDUe+Kdx/R6iAhDKux8DWlWDf7BVuTxsUBTwLkUzEBKmPBt4POqdg2mpPSzBMf4crpIwpX32/u12D/u/2beDLe3TjrPC/zWJvdv4o/UgfgixISd7mq9V+fWWQJJOjvEejGJl3ZPl1Je/2v87ulx/iYjhrWfAa1pv7LjxnbsVzGOfIyJ4R4FHn6jHa7wd5v+oYO7nREgpf2mZZ4m/+VOp+E/AJ+8Hh8V2Ju/bFD5KYBT88YCAu0Yvb2BfMV3fx9uPgVZ00VkKSmmlSgwpx+fjWKOjiSzJ8uUfVZSD4vLuJnQ7653D6l9omOgD3uCHHrWb1QQVnRUIaQkSEHt6vwdYZoKw9PCSI7adVOS/0n6G6QM+DZMpZdvjbNTeT9gTudp2J+gduW/9NY5veeI1LUSYIJdfjmEa9aGPEOIN+eAoM9MSkQpDBWnjKUxAGkqg43fO0iLUbaQzHHJkhH3mFeKy2p63H7Nq7rPZcOHU8Uue7p4fdekQ9iwv156ADhbm52p4DPaEnQMc5kgWCVGke2Mui+Qkxfm9dLEliKscWLbPyDRPP5ITzPT8ObvLOsv2KKYOS5xP5To5zlYvoULG1etrayM/B+VTlj/4jY3dNG7MNXsym+s++rFKjTGKXLBevMy1jHuwBmQjdLM3z5uTPoWWU7bjaoLJBIdSvXdkjToesxxH8cNZSo5X6LCSe8I2IRym59VxZ3dLnuI+G+1JcQXWaHXeG8v9KGsHfpUUNU2IyO0NPLL71wLR9C7LXw5jvL9j3Ii9wxDv7xATusJ43w5ZQ2wYUBfqxztDDykCDs9/Ml3V7QR4PAX1KE4uQZztTbDSLd+Wagyi1meGZ6vEwjHOmCO+5QeOmNJQkVR3wUFD+E26vLNkbhCL78GqSsBVVDzsCZ+F8/dZoumXrrxiNRkdIxqyvr8lvMw2X9OTPM+8ApDhB9CXZZSXAYIYYKyTdBUIaVnFMSiKUO2iCeVo3zdf/9t30PZkFjo/VRzmxeQAb4/YSm5zMxCIiioHTfCo/RjuwSX5ncuSTN6jQT17wlpQaPRLzIGG58j2TyWPvDdteOgDEm21P8iBjQ5s5GCpbF4N/1nY568uO0X1S+0stgvrmDqyOHPO5wwDWBDFPOTJaZav0ZBRYRgCwX+Ga4j44Soj/GFxE0pyrFXdJLC4H8mbd7ozJhEs6GtmHzL8ghlSxNFg+rq0GAsfxD/Veh9PY6kuBXXEnf2QlIyYnwXnKtvAeLYwbRbHOyQEfhu+eE8Y099N4DTP1u5syJb2u6+YuTeDLuvnmVvd/AvEA5ENHXQOfBkzjNUI38OMvBa/s6LZSx+/1C/VBgLrHlTywZtCFBA7APr0OdsXl0GqR7gWBxsND7Djvj+Gr1FvI0sSA/N+sOW4+/TBveF7B1Bro7yFD9F6E8G7fdGJAx7KyNdcNzDs1z77tA+4ATZmL/LM4lFM3tTaExaTvhzJzvC/2ttomr3/sPRgsU3vjwRv70WWq2IrmV72zFPLzpo1LCqKQcHuAlzL4GXhdTMV33EFt1GVlGgiEw5EpUY5+yEbyp/NbdBlbT2O41pK1QeCYkR6XQ1Gtw0Mdm8uN7iMFpWpom7Rgt73Qn8wqyx+6hc7w0dJ8jLCJDsHT8VngJl6D62L8s4FtTMqVlKDDRluXCI07poAXjfmJzbeiqfw958gQRU3mYUtNNkChpH6ewUqsKqHez9mx0UOs9zzgjm2Ug6caNmvZhjU4HjSerG5yoI39Sobo6GXYJO82LXWAnaMFi8WoRGRShMacuuVmLDyFUdmySHw8snEIEFeYNLoVgZCny3tdw4xrj61uAfxQ1btXbjBQaHh4vK9lYE0yVOSOP9FfW0tBOZZcRU9nzwDqqcuMAikvS/ptz+ZMFjo6LcA3KfmPkWJFDrncEIkQgR/CMRbZBziKIadgRZPjcZVjt8RuoheMEH266lzvnf2s0dECPD27Nb7/vC93hN2WLzECWBfwnAaAQxzAdA+e+XrCVZGCUHz0+bxTSSDR60nu68X4OrJWQrxAYTji+ls6a2PikI8lOG/SaxYUveezDfpfVeD4RPocb1Auwm0S1x5RapWXCMN06C/uDSIeKarIwmEadmfOSOzi37WtXSsRr4P1kjnWAcWq2NC5ke9kdyTuXrRBrF657MUdSjvp991mu8Y86wokG6eHEYwzAhaLHT74kCKevIZPILETwFc3md52XrYB3HCOkXZTQGNjG+bxvkgtOvBmC6vRi83IAqFCsKOOBXkOchD4c1yS8ooknsO/qjIbUmf7VMd/vZTVAzFwwp0y2oJ6it6+yF5RvE02okAUZSd/GcZyy2MCUeur+0J/Wt/e9kouC2WaZxUK3CWLiGCjbodndvZUusuihJKbzOyyvfUqZ9XsBQvVDshBTtj/wLKqLk3IagqzoB+r53JMcPRLqA34iVAWlZ+VPyAqzvgdZZZI/wzS8P0sYb7kUebRmtQtM0cC6ncT8wYuPfyOMMi1nNeBvDWIt3BL63bU9z8lShYEDcNnwW4xbgWVwJp/rYuSf7hlYOpzG6DQRX1Mx3T7bfc4/RFLZpgPZoeBhDbwWyq2tWxpJtv14K+5BgjSdxa0OYGLS332WqBu+o2OVkg4ylaV+g0qpIa7SgrAHhege27YjlZu5JjjHBr7mjtMA5j20KYjmpTldOoMnW5GXZ8R5Juvl0L+pJjjOQFyNewwM4ldVRbOgKvy7DyeMaTlqrXaYylFVtKRREiyA36rk9urNcUH3Me+4667WT2Hu0tmNHbP7rNKt/8h5Vxlwmt1JF02VFlbrN4WpVG2YC2/U5tqAuPOKKX4BGCp08g2dxWSeq4AAcwfZl4vQQZjrrDzgPSFvdqyo+oaCg+gsPwcZLdtfFO9nUsm/4ZRVEystMhml1khYMDZV9yjEmKrw3+LGMZzHAYmjnwIJyVgA+LZ3jrsy45igTPkuR7ho/+Zn1FYgLJjTp6lBZPLqfpdNnRl9H9HYF53w4MJxvqcQomGnBo6D44rtPbu7Ue8A9QEG/pAFDnmSWSitePiiKLIRlZbhdQP1583fzPcf1JunqFdyIoe5PetGQJkts33bcvVVLCTQJjVPPvr9+95mfK17R2s36F/bXxfZVFVMTRSqQCav1K2QKmwWxDuCS2Pf9DqIY4wdRhYxZZWpR5hCgrTm+YxnATJRwFuHyGggB3rkPkUz6ADT7VSkt5V01qpB6hFivu8DlqD9Hht7cU39ixk9RaLwymbBR/FnaSUWh72KlfJGZhp+5QKaBc+uXNm3fC2PVI3XEhDdV/3HWZIj8NVQ3/zNKkOwo72iCSY8eBpvkQFNfLrMpjNUe0ZZlx7D9OIlyEI2hZW0bmra7LEzCX/shdUaf+WHZ2NruKcuxgEkRc7DGbWQ35HGymcc2Yjc2a5XWnZJlMZRPS9kaS2ahn2yjIOg4bEGPzK+Lz89eEqrgLe2mP2iblrvZHE5AGW2b5M6btlF1Ug6XNYdL3RobRvbKRY3MbEa7RyMNHkL9c4Xs/yrGlMzGDyiRY7QEtpGEovlB2dRzesFrXqLbNzROdFqfw6t0uxZxrtIyf9kgt53tko5VvDV/tjMVyRqaa3mZpZ7Wa2WiJgzreRsRylk9ouKSrZeDYhF03YDK92QUjZsOODFeoO+E7oOMKHWWTpOmjsJr1+IeRQNbV0gW2ivd2ZoXbAmabfqWzF28zr3bclZZLgNAgvvtb3zExOKlhEZiR5pMmYT/5BSV1s7oco7AgR4IJONHggpaiYpMbWVvCk0PHOpJRV4zzT8GFNlwwG/upr/ZNxXcl2qegdj2iroJradO3i8fo9rK8xabsPE8x3bHgpdlYqb3XF5CJBvaPXNQsgtR923UGkF5F3fKh1zCt/xzeOmawn6ITsgTTuPm84dq7id3rekOqdVuCFQ/dx0kWGf42+P/f3pX1uI0j4b+ymD8QzHvvAp1zA+SadGfmUVDbbLcQt9WQ5Rz761eiLh5VxZIskpKTlyBtFlkHP5JFiqyCRPE8z3QKB0AV+fYdYUm/j42ELIeDPGKCuFhcjenjCLDCYyKERtXzbL+vPHo4HsQkTLku8Y6Z99aLBhYv3fjx0dCGxUpgJRa6eBmxvDRR+rKLWbw6jcYsXtFw1cRQvykL+WryKB2ipAucj4KrJ1B7dPgxCLggyXV5QAIvMIMN5gdmoFocvmo6hChY656GrwNfnbSaDMOPq8dRr8oqsNO9HF8HdjppNRmGH1ePnV6VVWCnfvK+DtzUkuofa+UPq8eLVGM1WGnCIyS20GN7yiNKGhktCbqf/XzP5/biDGhpFeFwq8nj4cWMa6fGHnOeMJq19f60CsOgi4paSMmnE/pBoGmSEGhkR3HE8MkK27gAsLq+6mNAoDr+FwTpaIDEBqgjYmTo885RM+iijrlcAyQg+IIeeE0F3OLAtqIZcImgCzXjnQ28uDPdqx91Gpt0f30qH+oWN7LQWJIXPeNRGmhy0YSrnwFJ9cYAMhoWX+fF6VEeys4NPPz7Ys9Ta0n5dfW4GHRZDwhknq/QKGiSi1kwaH++DBwACdQWDYRE/tukqCY7T8tiPXRe+3OQhUgytEXwBB3MMB7Bw2I0yLWEKQSQe3yP+cRLhEmH35dhZxxJvgDnAxP7nK7zCaHg3svIfg3qv0ixooFIhlH2cEmO8l20XKuykfaXtd+Na9TgMNINHrn3V7FpDguakG4uHzXRPdwuPNOXY7oT/80qaYqfCRxXaqFhuFTJQXl0gosJxKWpxeEbPRIXiDVgrIyfI34BiPHnlFj4khLGXfjkjbglI6qX0pbA41W4YNgZFFkTYJYfwyQObALGKxkHnNhRSt5k9+WLtNgmn051apij2P6TlQ+IDtO70fEsqZNCa2z40d9Mwu6nM0HR68LCBNgV0SGi+TqwQlO71NNcA0kOyhPA6RmFgJnQNtrv6SouC2tf1KGwUG9oSVAL5iNNxpnWo3Hdpg95KZbvZ9dS2hI0v64bQ4Miy/ezP4vvFdo/5VUDx25yWsX5JCC4Jg5YvvqzS0irVZxkQjibdRF0uOPLgUuwaWgqVrRuiRvYr85jsOiVrBPSCtbnMa9EMAD1eix/GetElSdGsNxTe80zcqwDB73AW5xRdsfOBCL2sURfIe5H2i40ZbhANr8/0/9hGD2it1KeikOdTEd4uGvsyR9WRDZcG63kAnxgVZ9VeL/9A57ws8rv8Fjo9BLTt82lIC/SonFZnp8O270gP0+0n1UUSuCLl1o6CiamRIZLYhb6/KKF2cIPgCzdODwHEZcDoVWsUkuAWci1ahK6oi9XFraW/w1+CcAK+EV+Eq5if5hv+d88iU12374+vC7LIrs7lWIFGCPlh+TCKNeOPlq9NUARFv3jU/1nwtFLnXrceOABwdfUSOjKkLIj9HMSNR1C586glLKszQTYwEInV762voHzS87NZ4Mt+oRNaRAb853rcJvu3DHMluJFDDJDsqilF+ItKCqN8BAihh8DwOWIuEP3KdCZvwLEuB0eE2UVeXSg/Z0WWXoo+7n1Rf54lx0kYYKnjFffw6hE2jsYrWDUsaBbNghaJLmfJ16ogbyijVKUI4Uq9pLxt5q9+eKBGn7dPRejsbfqDHj+dapKql76cshwjGpEKhb0goucHnEDLRp6qthLw99650QOJC929lvzlNdBzn0kaRECXR76GHKxaAx67DgDLBdz1mgq8Xe6P/UgpTX0g4uwyJXqcsRsCX1ieBKe/EC50XYEns0GYsM6ujvJcRnW7RiuzvtLbtLHp714mX8/7PMUfyLcE2jnL/2PC0cDrF58JOjGj4aF20wUlX4bocVhd963kkTc+OsSE15WsV56TRbl14sItj7ow2GmSrcAWC1/SxkHRAG3jePws5CN4nAdtb1IvHwgWZKPu828PmDZKnGYat25IJjNCjCnC/QbJTTTxeGj38u9zvZlHe/W+/OGUNOUoRktpEV8Oc8mnLryZ7eozyiep5uvbw83Zb75enO6O26KrLkDuorXFIjweg5ojGb1byswzcY4/ovD3fI9t+WBLuD6fA7mYq/S1/f32b76RSSB4s73DPWGhl/X/vh0UIXDLPajdpkmwesih0PB4m2no7iw1cnWaRXrUqXftwrQ7yugpjuRvC7yx3Ao0Zkba5xetHp8GApxOKqdsRSA3Oa/4bEQeAxdEc/FqPzKb5XJ3+W7RPl/3VG4s2HQab6CWRbEw1W4YtL48l0om/kBmqoUy4vRRVwE1FaxWY+HqpDz1lg4RZ+y/jqJk9i+ekyzfSL/vd7Q2XU0Ii17sFYQBFOK8MYdFOV3L5jCTeUHV6pGHHaqfPHCPj2Izdf8ZN6Qs37G5y2LUpvA7NIwydxBtWjRfN6Bc9jTDyARDVlznlk1Ypy7zamoNN59Sn/KWKtvD1nd7kwhV3FX3mRsBKwzC9cdR9XSh8VT6YnF4KOL3ExrNFc/e4uUCCpFiuY3JPQ0gMwLyjERos260fD5Lt+k++x/YtvJmLxLD7uTtWNWer8nULt7+DEIAi2xdWHsUi+og03lB222ThymnYQR8TX35tLf/U5zX3kZ+8nV7CPbr3ufxbdMfP+v2D/dn/aHOsho3SVD4/JEvcdU9XtZu123eYLVd8KubQNEX182+sqVLQfwxRkgYtxwPwtznUZBjmA5PTKKd0wcagV/orDSyPBOjwapee8MtMosHU1a5Xh3Vvb57kX+KDeKzFlNqRJ6IlNZa3dT1N8vaLpCTT2KXWAY1f//lB9LfD7qKKw+bH4Mc+VpPJRmmqZ6RRcIoE62aED6IL4fR85HSpXQ85HKWm1S+/2C5iPU1KPYBYZR/f/6PjI+H3UUVh8GvJU+AUozzUe9ogsEUCdbPNc73+//zsvssPssNnmxZW/9jHrBt3wmf80vtwovaI6iLT+KZwx81T9cH47fRUHs53oaq1u7n8O8pDkHZHNt+gallwquQcRlnCBMOr6KembFP7NY99Q10wFGcEC1fzlPoOI/Th6Lp/U9ZxkPorCPWF7JADD1qKpqiKI768+34nVWHMuXaZnepUf7Y19d60aUQCCZP/7VlKIBe242D+Ix/fcf27u86vn0zo71Y01DOjf3K1BLAncVSCp3rbGSckRjysJljrMkGTmbf5kd24t4VvtDEcRgKHVweJGWYifvBFgchiKIw1DqMlG2KU+FgEzUlYAm6gp5PUBwMQiI/khaouR9KvMSsfunTuOYFaLZsqJdpVFRvaYRukTQwmLbvLVikKlGwbM2gRqLgrJ3R8U2eFvxfXo43aeyr4iZSKei5FAp2bI4hHBz1ylcA9V0LO3xalKAw9YkYrIl+NGMnBz6J5kWg74Ear8vdClQDyh4futKQPG7QkfzXTLO96J8yLcAF5MAYmbSuHiW1bCpoPut8o+gMW+Ugxx1EgfD4UOFxWsogtgMpQ4Ow9Uli8NQBHEYSl0c6rs74qYs5E722ORXAbiBZCBnkNIhxXDEanEeiiBudal7dlSOQ+xJUSkE50KlnMEH4YC3zZ5qmoBy6HTTFFNTTkPh0kEUj9nxWLnq3WGNrY9FAupmUTk4v/pRubWHdH99Kh/q7USTjQiVgiaHJKJrOKSTL36Rwa6UQXxl8TFhDXhJe5s/ZRuMT1tIMGopOJwwJmT7LQWn/TdFfnrCmLSFBKeWwsGpvZ9uMWl/h9pvi5hu7Jf6lWZ/SRj1Y3UyypHVKR1SvMnuK7ex2DqkgMkgKWBKphQEZ5obrxuRRUApQ7uTtTGVlB/yEppJlTKUSVPsYPJZfK8U/pRnh/KIdxhIBTEGCRn+F7LtGoown4u1weoIkR7TiylOrH77LKrtwKHeAApwCjbKYTNqJE71zKzCgIomCaymScXby2EpDLFdHUZP7e+QfJLcnR6dGdK2F0kO2o6sMUk6tlxjJOL2qUzHhnWgLCR6S5bz+JA5aDD+ZCVCLrLeNHn5QjrOrYycCmPPUxgC8SQZjRQkywDXLC35iF5ra7g8oj7Yue0F9UWg59OXOjgo0YYtFkoZxEMpdp4U5OCZaPs7fDKQM05dJVUPMrj9vhhlw0XpbVVfyI68A7eGRjloM53EdeCBRX6zzz8wSvA4BCMecdJ4Kx6f9ik4UmEy18njQMn8VEBIYJNQnw7YnLuFAWdsUVDrC5ftG3EQ1TCjJkebBNwaWFSuM9HNHj0PUMrAc9Gh2MHkS4EzUcogJkqxa6Koam9Pe3GbHr9CE4VWDE4UGoXLbkNUPttuQxlot6HYNRpFeqwGzj8i2z1ALrpRDo4/nYTH8GVW7SKO8DRkkxBsFSrnkVxRiMMGPD3vi+CjuK6Uc3rimGMBGuIsZdTMakbcAiYWnYA69zJInWNciZgDjHKlFB7nCgGfVROAimLXUDhYNkTOBePxKc12UJcORfAC0ZW6jlK1YDX20alWDB6VahTOcSh7llqBTQp4FBpEjG8G70RZisIxTjBC7HsCROuQRQvJYwmglcJXUBQCF3rsuDA2jGwaEE822Vjm2L4EI2SJwduLoFEcgMMhhBI+JkKIR4rDkIMnAO8Tnh5SwGIN0KAf73Qyp9r1YN3iF35MAlhlncaFwiI/HqvG9zhXmwREnkXlNDW0KKGLEWcRqv5XIrvFrgT0/7pC1x4x/UHcStFKwf2hSuBihXy2Ir5Y8T5VdZ9NCEVsEur7S3L99LTPxPY2b+kz4f6K3FXGQWdR8GRoyd0S6Pch8BscCJ37isVncaymYHm3lnGDpP2sjF9UsSior9MtEaMjzC/Ljg/kNDnn03VSk7LPDvurRLzv9vzv91piurFHmZwTaOZBdDLQjZUCCACACQOQEjIB1IzLO/1zOvv8Si3FrvD0BAxPFWellWI+KZeV/dbGtq9Fgl1N0anG9LCrWxl9aTFUbpFj11yT/jarQgzed+0pzWvuyjsB/epsxRO9fQu9LwCrG0XmqwVdxQnqdwuPW334GQL0UMOWfzHq9/dkiX63aObvcdMvkRVRt2m8mpTbkty0N+xszTnVcKXMO/ZSKez+PFgTNItd6Nc8t2mxE+CI4FSbqc8XZp7O4RyFHbOST+RAc49V5tMwY1BjVpp/So1kFuDZxZE0CVjBJ06A9yVaI9SDkcmLbaK/DEGXWp2OUAZ4qdJoQbxAmYqr6Wr36+gwNaGq27Q+JlLk0Y2q/ozTqKma29eySL05W4FMoD0HIlwukG5+twt6aCQrkw+IJve88RhKZYFCAK8zs1oQKtCGwHIvZnIPEpDc20AJbBL9dC3pjtdEeyZHu+/8yrja8DMsqTH9uIpoxTh3BBrDHol5MSDuqvErE6sToCyi3lJMpj5hS/p2AfOAhB5MAT3La0xAvrYbr3p7hEwpbZLMr65xHC7rYY8yp6tomA5XVCecvZcCqt4fg/dfCojJEycmetx409t0OfJeF6wJGcAq82EIfBLEiWfpxyWY4Xm231cTad8yYQSD1J8JWBg6Q+kuONPQNK61RetzCBjv8LUGsMf1480APTIeskMAtqAr4GqZD7ClPtjjar0m8bC6aYXzUHq8abq35aQ5bCIfJjDfx8ua6Nv38ap2T8NJVW0iH6qaD9hlzeHH8zdX+X5PqqkT+FBRfd3e7Jmg1+vTVGse2CdNi7ByKsmZQlo19OAAfT3k2f8EFc0LBeqXfMqN4VUklENe8zcqOl7oky1BtxvAVsnoA7ObEneEeBXdC5ylMKXgIk0I3idhOdMj0TeDN+EyehjTMNzr4GiKZSIqigbpjvIq+kATJ7KIbG1UhJDxpuvjhJB2Aqh8GMUKaCKrKr/Oo6684enW1yDzprB2R3XQGL6HOlHlRI1uguir0jhE1mKoDCKDsVHs2nbFeXu2bZLs1obmbEHj9KYciWqz1IhV6GYUPfC4lYFOGKcqIN38RypaeB9ZC47eM1VRam4yKHxMS/7Ug6INJcP9CvwiB1yBuMFw9kUOKLaR1goZq2gm07R2Z9oFTDA8vl8XYY4+fhJuA5NkXsWt2E9DvZkOUAb5iW/SNtH8X6L9q9pF3Eo+Vfuzh/Qotv9k5YPCwVbcVWU2dbS6ZkwxWRWNFzbdENq4HdrHzQBXmEkRsCY64lnB2mYyzRe139n20WvNOy/EMk8f680xISokHiZENU7dUA8MQTdeRSCqHOkKkfQ+HCMiip5shBMWbx6zOMeFu9K86Ihjmi5gHz4mDIp5lTZDGt50t2hmut6rxiNMhnZxLXXCmQQHa1rrKxk7cepGqLuR5NzymYRr2vNpUSAdEx5I6WeqA6JbtiOZClp5xgE3o7NR2vn72/e1CTMIZ6LmMoFGOE7u3BHYGVfUvQGeRMUY+XD40Xb0O0KKzmAgamTgxD4GR3RTEBtGlHb+fWNoM5BhZRkXux0V5zcQK26u2hozlusEBBFha5GYuyC4JjRD4MdtF55BGK3qIYCJtpFQvnOjlWY+FsJka4FNtdARYEeKIG+54NTepgk7HobaglrqxRjEPRWc2qkUog2gxjJMQoSO5r6yZDdBnLrP9QCTEXZbteiYwNleTOxexDm1vQ3RtZlTTyQ5yaZaE7iBoJyX0hRULsu1mngCTMNjk2Mt/yYi3Ul2XafypNY8v3GRZpRxJxOULdukdDtBjMJpV4vdSTUOx+Oc7ggxJ8rgs6HfAArJTfr4tBdDJgRccYOScF2MfAyN24LkWgiocp+KQbsXC6mMULoPkqbfnLVSTMjqePaIc9Qn1i6baP7Vyr+q1rFme1bqXrTRKt4W7akns7OYZZRBLtoURiZzx1n8mOphzuZdEtFNu/K4T3jxB6dPIY/wnXV8nOQ70sfIhri5YOYzEzEwXVXmH55xTdQn+0iIz4I20fzfA62EJU1NNBfJxLvd7OFCUPsYKGj2j5v+rvfMPa8n6UheF/kjZQ+K3IdB4Hwk7agi04ucbYrbfIQhFOK1m0HJapJYGU6AWYEgJ8Y5nIGlGe10WhWsHayNmU1CgQKk84GHMGor2UkSPTGMrTpKiysBJauRWlBJaIwDACv7Srv/x9OqTLg6A6YpSYAkKsBVGm5dAiVY3pcGLq5ULnRb9lEQMynLlAtYenqT5O0hK7N0T1yupCrgSk67WAkncblp7mI5ErOcb4zu8qjNym0XtK4ndcmW4FupvMw6E8PBqGlr3LFgYGpcwTMDwUDpeZomnBl3ppiDXp+8r0vmejTPOtTun6xUD0ntHrzID8eySLNqfqi90V6/LvjRbZ5g9YlTh/l5uc09IYIStPVEU22oe1F32owZu0kr+HOU1Y2qTOVxjRdtQCW1CBduWjYS4BzjvBb9YxZIxtIcdRBZVs4zbBeGCsQhTEiLzw50FUFxJYMMt/+1pDO2hc5s0T+igJw7sg0qmc55hu2ifYGIgglp8dnxxCIobqYHYq+LVlohYBWYq+0Aay2SbqlZIlwplGYw+xCmDF5QKXparVEx0eIaRV2KJzloTl9kWquBfT2+u3O2kdu/3E7cQOntU+aMyl89axqpTV/1syj6sqtnTcKy9ofqz2rrWu383udbsT/KX6+efT5VtR9F89dLccx2QxNXVZsHIVMrDo12NG8P93m3/zMk6ki64j7ncplu0zK9LsqsDlhfFW8q71Om4pMnNfXx2Z3Yvj18PJVPp7JSWTze7bXd5dUzmv/VM0vmq+YW+nEOFSoxs0oF8fHw/JTtt73cr9P90dhRY028qKz/RlS/N31ZDc5S7H72LX3ID8yGWvO9FE/isK0GXZeE+vjxcJN+E1Nk+3IU78Qu3fz8VIfOlgdPWCPujtDNfvUyS3dF+nhs2xjqV39WGN4+/vjP/wEsFs3mO/YHAA== + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index ca987891da..3eb328e5e1 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -256,9 +256,9 @@ 201504270946381_TempFileCleanupTask.cs - - - 201504271444091_SendEmailsManually.cs + + + 201504290937512_SendEmailsManually.cs @@ -505,8 +505,8 @@ 201504270946381_TempFileCleanupTask.cs - - 201504271444091_SendEmailsManually.cs + + 201504290937512_SendEmailsManually.cs diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index a4b474dfb3..2b89be8e7b 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -1318,6 +1318,7 @@ public virtual string ExportOrdersToXml(IList orders) xmlWriter.WriteElementString("CreatedOnUtc", null, order.CreatedOnUtc.ToString()); xmlWriter.WriteElementString("UpdatedOnUtc", null, order.UpdatedOnUtc.ToString()); xmlWriter.WriteElementString("RewardPointsRemaining", null, order.RewardPointsRemaining.HasValue ? order.RewardPointsRemaining.Value.ToString() : ""); + xmlWriter.WriteElementString("HasNewPaymentNotification", null, order.HasNewPaymentNotification.ToString()); //products var orderItems = order.OrderItems; @@ -1433,6 +1434,7 @@ public virtual void ExportOrdersToXlsx(Stream stream, IList orders) "CreatedOnUtc", "UpdatedOnUtc", "RewardPointsRemaining", + "HasNewPaymentNotification", //billing address "BillingFirstName", "BillingLastName", @@ -1565,6 +1567,9 @@ public virtual void ExportOrdersToXlsx(Stream stream, IList orders) worksheet.Cells[row, col].Value = (order.RewardPointsRemaining.HasValue ? order.RewardPointsRemaining.Value.ToString() : ""); col++; + worksheet.Cells[row, col].Value = order.HasNewPaymentNotification; + col++; + //billing address worksheet.Cells[row, col].Value = order.BillingAddress != null ? order.BillingAddress.FirstName : ""; diff --git a/src/Plugins/SmartStore.AmazonPay/Description.txt b/src/Plugins/SmartStore.AmazonPay/Description.txt index 0aa0eb0902..bebde13958 100644 --- a/src/Plugins/SmartStore.AmazonPay/Description.txt +++ b/src/Plugins/SmartStore.AmazonPay/Description.txt @@ -1,6 +1,6 @@ FriendlyName: Pay with Amazon SystemName: SmartStore.AmazonPay -Version: 2.2.0 +Version: 2.2.0.1 Group: Payment MinAppVersion: 2.2.0 Author: SmartStore AG diff --git a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs index 22ddf54b15..457844290e 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs @@ -221,7 +221,7 @@ private bool IsActive(int storeId, bool logInactive = false) return isActive; } - public void AddOrderNote(AmazonPaySettings settings, Order order, AmazonPayOrderNote note, string anyString = null) + public void AddOrderNote(AmazonPaySettings settings, Order order, AmazonPayOrderNote note, string anyString = null, bool isIpn = false) { try { @@ -250,7 +250,10 @@ public void AddOrderNote(AmazonPaySettings settings, Order order, AmazonPayOrder sb.AppendFormat("{0}", anyString); } - order.OrderNotes.Add(new OrderNote() + if (isIpn) + order.HasNewPaymentNotification = true; + + order.OrderNotes.Add(new OrderNote { Note = sb.ToString(), DisplayToCustomer = false, @@ -663,7 +666,7 @@ private void ProcessAuthorizationResult(AmazonPayClient client, Order order, Ama _orderService.UpdateOrder(order); - AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data)); + AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data), true); } } private void ProcessCaptureResult(AmazonPayClient client, Order order, AmazonPayApiData data) @@ -692,7 +695,7 @@ private void ProcessCaptureResult(AmazonPayClient client, Order order, AmazonPay order.CaptureTransactionResult = newResult; _orderService.UpdateOrder(order); - AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data)); + AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data), true); } } private void ProcessRefundResult(AmazonPayClient client, Order order, AmazonPayApiData data) @@ -715,7 +718,7 @@ private void ProcessRefundResult(AmazonPayClient client, Order order, AmazonPayA _orderProcessingService.RefundOffline(order); if (client.Settings.DataFetching == AmazonPayDataFetchingType.Polling) - AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data)); + AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data), true); } } else @@ -725,14 +728,14 @@ private void ProcessRefundResult(AmazonPayClient client, Order order, AmazonPayA _orderProcessingService.PartiallyRefundOffline(order, refundAmount); if (client.Settings.DataFetching == AmazonPayDataFetchingType.Polling) - AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data)); + AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data), true); } } } } if (client.Settings.DataFetching == AmazonPayDataFetchingType.Ipn) - AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data)); + AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data), true); } private void PollingLoop(PollingLoopData data, Func poll) diff --git a/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayService.cs b/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayService.cs index be4aeacd01..5e14a4d77e 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayService.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayService.cs @@ -15,7 +15,7 @@ public partial interface IAmazonPayService void LogError(Exception exception, string shortMessage = null, string fullMessage = null, bool notify = false, IList errors = null); void LogAmazonError(OffAmazonPaymentsServiceException exception, bool notify = false, IList errors = null); - void AddOrderNote(AmazonPaySettings settings, Order order, AmazonPayOrderNote note, string anyString = null); + void AddOrderNote(AmazonPaySettings settings, Order order, AmazonPayOrderNote note, string anyString = null, bool isIpn = false); void SetupConfiguration(ConfigurationModel model); diff --git a/src/Plugins/SmartStore.AmazonPay/changelog.md b/src/Plugins/SmartStore.AmazonPay/changelog.md index e2b2170d7d..21aa9f7c0f 100644 --- a/src/Plugins/SmartStore.AmazonPay/changelog.md +++ b/src/Plugins/SmartStore.AmazonPay/changelog.md @@ -1,5 +1,9 @@ #Release Notes# +##Pay with Amazon 2.2.0.1 +### New Features +* Supports order list label for new incoming IPNs + ##Pay with Amazon 1.20## ###Bugfixes### * PlatformID must be .NET ID not merchant ID. PlatformID needs to be identical for all orders diff --git a/src/Plugins/SmartStore.PayPal/Controllers/PayPalDirectController.cs b/src/Plugins/SmartStore.PayPal/Controllers/PayPalDirectController.cs index 1103b9365f..d0a5d8434d 100644 --- a/src/Plugins/SmartStore.PayPal/Controllers/PayPalDirectController.cs +++ b/src/Plugins/SmartStore.PayPal/Controllers/PayPalDirectController.cs @@ -350,9 +350,10 @@ public ActionResult IPNHandler() var order = _orderService.GetOrderByGuid(orderNumberGuid); if (order != null) { - //order note - order.OrderNotes.Add(new OrderNote() + order.HasNewPaymentNotification = true; + + order.OrderNotes.Add(new OrderNote { Note = sb.ToString(), DisplayToCustomer = false, diff --git a/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs b/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs index 7ac577fcc6..a1e1b10db2 100644 --- a/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs +++ b/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs @@ -292,9 +292,10 @@ public ActionResult IPNHandler() var order = _orderService.GetOrderByGuid(orderNumberGuid); if (order != null) { - //order note - order.OrderNotes.Add(new OrderNote() + order.HasNewPaymentNotification = true; + + order.OrderNotes.Add(new OrderNote { Note = sb.ToString(), DisplayToCustomer = false, diff --git a/src/Plugins/SmartStore.PayPal/Controllers/PayPalStandardController.cs b/src/Plugins/SmartStore.PayPal/Controllers/PayPalStandardController.cs index bc28786e9d..10aa50046e 100644 --- a/src/Plugins/SmartStore.PayPal/Controllers/PayPalStandardController.cs +++ b/src/Plugins/SmartStore.PayPal/Controllers/PayPalStandardController.cs @@ -367,7 +367,9 @@ public ActionResult IPNHandler() if (order != null) { //order note - order.OrderNotes.Add(new OrderNote() + order.HasNewPaymentNotification = true; + + order.OrderNotes.Add(new OrderNote { Note = sb.ToString(), DisplayToCustomer = false, diff --git a/src/Plugins/SmartStore.PayPal/Description.txt b/src/Plugins/SmartStore.PayPal/Description.txt index bd0a996b74..84e4594446 100644 --- a/src/Plugins/SmartStore.PayPal/Description.txt +++ b/src/Plugins/SmartStore.PayPal/Description.txt @@ -2,7 +2,7 @@ Description: Provides the PayPal payment methods PayPal Express, PayPal Standard and PayPal Direct. SystemName: SmartStore.PayPal Group: Payment -Version: 2.2.0 +Version: 2.2.0.1 MinAppVersion: 2.2.0 DisplayOrder: 1 FileName: SmartStore.PayPal.dll diff --git a/src/Plugins/SmartStore.PayPal/changelog.md b/src/Plugins/SmartStore.PayPal/changelog.md index d264816dfd..cf618f7d59 100644 --- a/src/Plugins/SmartStore.PayPal/changelog.md +++ b/src/Plugins/SmartStore.PayPal/changelog.md @@ -1,5 +1,9 @@ #Release Notes# +##Paypal 2.2.0.1 +### New Features +* Supports order list label for new incoming IPNs + ##Paypal 1.22## ###Bugfixes### * PayPal Standard provider now using shipping rather than billing address if shipping is required diff --git a/src/Presentation/SmartStore.Web.Framework/UI/ScaffoldExtensions.cs b/src/Presentation/SmartStore.Web.Framework/UI/ScaffoldExtensions.cs index fb9ce28c76..71f761010f 100644 --- a/src/Presentation/SmartStore.Web.Framework/UI/ScaffoldExtensions.cs +++ b/src/Presentation/SmartStore.Web.Framework/UI/ScaffoldExtensions.cs @@ -4,6 +4,7 @@ using SmartStore.Core.Infrastructure; using SmartStore.Core.Domain.Common; using SmartStore.Core.Localization; +using SmartStore.Services.Localization; namespace SmartStore.Web.Framework.UI { @@ -58,6 +59,20 @@ public static HelperResult LabeledProductName(this HtmlHelper helper, int return new HelperResult(writer => writer.Write("{1}{2}".FormatInvariant(typeLabelHint, typeName, namePart))); } + public static string LabeledOrderNumber(this HtmlHelper helper) + { + var localize = EngineContext.Current.Resolve(); + string url = UrlHelper.GenerateContentUrl("~/Admin/Order/Edit/", helper.ViewContext.RequestContext.HttpContext); + + string link = "\"><#= OrderNumber #>".FormatInvariant(url); + + string label = "{1}".FormatInvariant( + localize.GetResource("Admin.Orders.Payments.NewIpn.Hint"), + localize.GetResource("Admin.Orders.Payments.NewIpn")); + + return "<# if(HasNewPaymentNotification) {{ #>{0}<# }} #>{1}".FormatInvariant(label, link); + } + public static string RichEditorFlavor(this HtmlHelper helper) { return EngineContext.Current.Resolve().RichEditorFlavor.NullEmpty() ?? "RichEditor"; diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs index a3c600b651..c4157b9b0a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs @@ -205,6 +205,7 @@ protected void PrepareOrderDetailsModel(OrderModel model, Order order) model.TaxDisplayType = _taxSettings.TaxDisplayType; model.AffiliateId = order.AffiliateId; model.CustomerComment = order.CustomerOrderComment; + model.HasNewPaymentNotification = order.HasNewPaymentNotification; if (order.AffiliateId != 0) { @@ -817,7 +818,7 @@ public ActionResult OrderList(GridCommand command, OrderListModel model) Data = orders.Select(x => { var store = _storeService.GetStoreById(x.StoreId); - return new OrderModel() + return new OrderModel { Id = x.Id, OrderNumber = x.GetOrderNumber(), @@ -827,7 +828,8 @@ public ActionResult OrderList(GridCommand command, OrderListModel model) PaymentStatus = x.PaymentStatus.GetLocalizedEnum(_localizationService, _workContext), ShippingStatus = x.ShippingStatus.GetLocalizedEnum(_localizationService, _workContext), CustomerEmail = x.BillingAddress.Email, - CreatedOn = _dateTimeHelper.ConvertToUserTime(x.CreatedOnUtc, DateTimeKind.Utc) + CreatedOn = _dateTimeHelper.ConvertToUserTime(x.CreatedOnUtc, DateTimeKind.Utc), + HasNewPaymentNotification = x.HasNewPaymentNotification }; }), Total = orders.TotalCount @@ -2428,12 +2430,11 @@ public ActionResult OrderNotesSelect(int orderId, GridCommand command) if (order == null) throw new ArgumentException("No order found with the specified id"); - //order notes var orderNoteModels = new List(); - foreach (var orderNote in order.OrderNotes - .OrderByDescending(on => on.CreatedOnUtc)) + + foreach (var orderNote in order.OrderNotes.OrderByDescending(on => on.CreatedOnUtc)) { - orderNoteModels.Add(new OrderModel.OrderNote() + orderNoteModels.Add(new OrderModel.OrderNote { Id = orderNote.Id, OrderId = orderNote.OrderId, @@ -2449,6 +2450,12 @@ public ActionResult OrderNotesSelect(int orderId, GridCommand command) Total = orderNoteModels.Count }; + if (order.HasNewPaymentNotification) + { + order.HasNewPaymentNotification = false; + _orderService.UpdateOrder(order); + } + return new JsonResult { MaxJsonLength = int.MaxValue, diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Orders/OrderModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Orders/OrderModel.cs index 00d3da4beb..f1c7919bbc 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Orders/OrderModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Orders/OrderModel.cs @@ -124,6 +124,8 @@ public OrderModel() public string PaymentMethod { get; set; } public string PaymentMethodSystemName { get; set; } + public bool HasNewPaymentNotification { get; set; } + //credit card info public bool AllowStoringCreditCardNumber { get; set; } [SmartResourceDisplayName("Admin.Orders.Fields.CardType")] diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Order/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Order/List.cshtml index 33a3d03565..e24ebaa5a1 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Order/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Order/List.cshtml @@ -192,8 +192,7 @@ .HeaderHtmlAttributes(new { style = "text-align:center" }); columns.Bound(x => x.OrderNumber) - .Template(x => Html.ActionLink(x.OrderNumber, "Edit", new { id = x.Id })) - .ClientTemplate("\"><#= OrderNumber #>"); + .ClientTemplate(@Html.LabeledOrderNumber()); columns.Bound(x => x.OrderStatus); columns.Bound(x => x.PaymentStatus); columns.Bound(x => x.ShippingStatus); From eed5d9600b521b1b11b96fd4959d67e881732b8d Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 30 Apr 2015 19:27:36 +0200 Subject: [PATCH 0086/1256] Store URL validation should not throw exception --- src/Libraries/SmartStore.Services/Stores/StoreService.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Stores/StoreService.cs b/src/Libraries/SmartStore.Services/Stores/StoreService.cs index cd0565d3c0..f763985753 100644 --- a/src/Libraries/SmartStore.Services/Stores/StoreService.cs +++ b/src/Libraries/SmartStore.Services/Stores/StoreService.cs @@ -183,10 +183,9 @@ public virtual bool IsStoreDataValid(Store store) return store.Url.IsWebUrl(); } } - catch (Exception exc) + catch (Exception) { - var message = "{0} ({1})".FormatInvariant(exc.Message.NaIfEmpty(), store.Url); - throw new Exception(message, exc); + return false; } } From 407a508956f1491cc2255a4cfe0fb56929dc7f8e Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Fri, 1 May 2015 12:18:05 +0200 Subject: [PATCH 0087/1256] Fixed System.NullReferenceException at admin/order/pdfpackagingslips --- .../Views/Order/ShipmentDetails.Print.cshtml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Order/ShipmentDetails.Print.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Order/ShipmentDetails.Print.cshtml index 6138daf35e..bdc45e4ea9 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Order/ShipmentDetails.Print.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Order/ShipmentDetails.Print.cshtml @@ -50,7 +50,7 @@
@if (address.Company.HasValue()) -{ + {
@address.Company
}
@JoinValues(new string[] { address.FirstName, address.LastName })
@@ -66,10 +66,17 @@ {
@JoinValues(new string[] { address.ZipPostalCode, address.City })
} - @if (address.StateProvince != null || address.Country != null) - { -
@JoinValues(new string[] { address.Country.Name, address.StateProvince.Name }, ", ")
- } + @if (address.Country != null) + { + if (address.StateProvince != null) + { +
@JoinValues(new string[] { address.Country.Name, address.StateProvince.Name }, ", ")
+ } + else + { +
@JoinValues(new string[] { address.Country.Name }, ", ")
+ } + }
From a3ca909dad4ef863fa44a37c8bd39e80c193445f Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Fri, 1 May 2015 12:20:06 +0200 Subject: [PATCH 0088/1256] Updated changelog --- changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.md b/changelog.md index 63252bc2c8..b59d48de47 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,9 @@ * Category filtering by store for backend category tree and list * #554 Flag to indicate that a new payment notification (IPN) arrived for an order since last opening\editing of the order +### Bugfixes +Fixed System.NullReferenceException at admin/order/pdfpackagingslips + ## SmartStore.NET 2.2.0 ### New Features From 6123f473a165e35c1e2e164fdc09ac5898a03e4c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 4 May 2015 10:10:29 +0200 Subject: [PATCH 0089/1256] WebApiAuthenticate attribute can be applied on methods. Product image upload requires manage catalog permission. --- .../Controllers/Api/UploadsController.cs | 4 +- src/Plugins/SmartStore.WebApi/Description.txt | 2 +- .../SmartStore.WebApi/Docs/Developer-Guide.md | 492 ------------------ .../SmartStore.WebApi.csproj | 1 - src/Plugins/SmartStore.WebApi/changelog.md | 5 + .../Security/WebApiAuthenticateAttribute.cs | 2 +- 6 files changed, 8 insertions(+), 498 deletions(-) delete mode 100644 src/Plugins/SmartStore.WebApi/Docs/Developer-Guide.md diff --git a/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs b/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs index 2990406b2d..db18f02946 100644 --- a/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs +++ b/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.IO; using System.Linq; using System.Net.Http; -using System.Net.Http.Headers; using System.Threading.Tasks; using System.Web.Http; using SmartStore.Core; @@ -19,7 +17,6 @@ namespace SmartStore.WebApi.Controllers.Api { - [WebApiAuthenticate] public class UploadsController : ApiController { private readonly Lazy _productService; @@ -40,6 +37,7 @@ public UploadsController( } /// + [WebApiAuthenticate(Permission = "ManageCatalog")] [WebApiQueryable(PagingOptional = true)] public async Task> PostProductImages() { diff --git a/src/Plugins/SmartStore.WebApi/Description.txt b/src/Plugins/SmartStore.WebApi/Description.txt index 9e2ff1c35a..53b6ca55d7 100644 --- a/src/Plugins/SmartStore.WebApi/Description.txt +++ b/src/Plugins/SmartStore.WebApi/Description.txt @@ -1,6 +1,6 @@ FriendlyName: SmartStore.NET Web Api SystemName: SmartStore.WebApi -Version: 2.2.0.1 +Version: 2.2.0.2 Group: Api MinAppVersion: 2.2.0 Author: SmartStore AG diff --git a/src/Plugins/SmartStore.WebApi/Docs/Developer-Guide.md b/src/Plugins/SmartStore.WebApi/Docs/Developer-Guide.md deleted file mode 100644 index 900bc6f0d1..0000000000 --- a/src/Plugins/SmartStore.WebApi/Docs/Developer-Guide.md +++ /dev/null @@ -1,492 +0,0 @@ -# Introduction -The SmartStore.Net Web API allows direct access to the data of an online store. It is build on the most recent technologies Microsoft offers for web based data consuming, the ASP.NET Web API and the OData provider. This documentation gives you an overview of how to build an API client, also known as API consumer. It uses C# code but you can build your consumer in any common programming language. As OData is a standardized protocol there are a lot of [frameworks and toolkits][4] available for various platforms. - -The ASP.NET Web API is a framework for building web APIs on top of the .NET framework. It uses HTTP as an application protocol (rather than a transport protocol) to return data based on the client requests. The Web API is able to return the data appropriately based on the media type specified with the request. By default it provides JSON and XML based responses. - -The [Open Data Protocol (OData)][5] is a standardized web protocol that provides an uniform way to expose, structure, query and manipulate data using REST practices. OData also provides an uniform way to represent metadata about the data, allowing clients to know more about the type system, relationships and structure of the data. - -# Prerequisites -The SmartStore.Net Web API requires configuration by the storekeeper to go into action. First of all he must install the Web API plugin in the backend of SmartStore.Net. The plugin technology gives him the opportunity to activate or deactivate the entire Web API at any time without any influence on the online store. - -Next step is to configure the API on the plugin's configuration page. The main thing here is to provide individual members access to the API and the data of the online store. Therefore the storekeeper can create a public and a secret key for each registered member. Only a registered member with both keys has access to the API. To exclude a member from the API the storekeeper can either delete the keys of the member (permanent exclusion) or disable them (temporary exclusion). Roles and rights of a member are taken into consideration when accessing data via the API. - -The consumer must transmit the public key through a custom HTTP header field. It identifies the member who is accessing the API. The secret key on the other hand should never ever be send over the wire! It is secret to the storekeeper and the member who is accessing the Web API. It is only used for encryption as described in the following chapters. - -# The SmartStore.Net Web API in detail -You can consume API services through HTTP calls in a RESTful manner by using HTTP methods GET, POST (insert), PUT (update), PATCH (partially update) and DELETE. OData options (like $filter, $top, $select etc.) and API specific options (like SmNetFulfillCountry) can be transfered through query strings. The web API offers two services. The OData service (path `/odata/v1/`) provides all entity related data and the API service (path `/api/v1/`) provides all remaining resources. - -Paging is required if you want to query multiple records. You can do that with OData $skip and $top. The maximum value for $top is returned in SmartStore-Net-Api-MaxTop header field. - -A request body needs to be UTF8 encoded. - -The OData metadata document ------- -The metadata document describes the entity data model (EDM) of the OData service, using an XML language called the Conceptual Schema Definition Language (CSDL). The metadata document shows the structure of the data in the OData service and can be used to generate client code. It is the recommended overview for the consumer to indicate where to find a particular resource. To get the metadata document, send a - - GET http://localhost:1260/odata/v1/$metadata - -Request HTTP header fields ------- -**User-Agent** (optional): Short description of the API consumer. Example: `My shopping data consumer v.1.0` - -**Accept** (required): The wanted response format. Example for JSON: `application/json, text/javascript, */*`. Example for XML: `application/atom+xml,application/atomsvc+xml,application/xml` - -**Accept-Charset** (required): Always UTF-8. - -**Content-Type** and **Content-Length** (conditional): Necessary for the methods POST, PUT, and PATCH, if new data is send via the HTTP body. Example: `application/json; charset=utf-8` - -**Content-MD5** (optional): For methods POST, PUT, and PATCH. Authentication provides the error `ContentMd5NotMatching` if the hash does not match the one calculated by the server. This header field has no safety relevance, because the content carried out using the HMAC signature. Example: `lgifXydL3FhffpTIilkwOw==` - -**SmartStore-Net-Api-Date** (required): Date and time of the request as coordinated universal time (UTC). Use ISO-8601 format including milliseconds. Example: `2013-11-09T11:42:48.4715986Z` - -**SmartStore-Net-Api-PublicKey** (required): The public key of a member. Example: `0c6b33651708eb09c8a8d6036b79d739` - -**Authorization** (required): The authorization schema and the HMAC signature, separated by a space. The schema is SmNetHmac plus its version. Example: `SmNetHmac1 +yvONYvJmQl19omu1uE3HVlQ7afd7Qqkk8DrNrfUbe8=` - -Example of a complete request header: - - User-Agent: My shopping data consumer v.1.0 - Accept: application/json, text/javascript, */* - Accept-Charset: UTF-8 - SmartStore-Net-Api-PublicKey: 0c6b33651708eb09c8a8d6036b79d739 - SmartStore-Net-Api-Date: 2013-11-09T11:42:48.4715986Z - Content-Type: application/json; charset=utf-8 - Content-MD5: lgifXydL3FhffpTIilkwOw== - Authorization: SmNetHmac1 +yvONYvJmQl19omu1uE3HVlQ7afd7Qqkk8DrNrfUbe8= - - -Response HTTP header fields ------- -**SmartStore-Net-Api-Version**: The highest API version supported by the server (unsigned integer) and the version of the installed API plugin (floating-point value). The API version is only increased when there is a fundamental break in API development without the ability of downward compatibility. The plugin version is typically increased when the API has been extended, for example when new ressouces were added. -Example: `1 1.0` - -**SmartStore-Net-Api-Date**: The current server date and time in ISO-8601 UTC. Example: `2013-11-11T14:35:33.7772907Z` - -**SmartStore-Net-Api-MaxTop**: The maximum value for OData $top option. Required for client driven paging. - -**SmartStore-Net-Api-HmacResultDesc**: Short description of the result of the HMAC authentication. Only returned if the authentication failed. Example: `InvalidTimestamp` - -**SmartStore-Net-Api-HmacResultId**: Unsigned ID that represents the result of the HMAC authentication. Only returned if the authentication failed. Example: `5` - -**WWW-Authenticate**: The name of the authentication method that failed. Note that CORS requests can lead to multiple of this header fields. The SmartStore.Net Web API returns `SmNetHmac1` if its authentication failed. - -List with HmacResultId and HmacResultDesc: - -- 0 Success -- 1 FailedForUnknownReason -- 2 ApiUnavailable -- 3 InvalidAuthorizationHeader -- 4 InvalidSignature -- 5 InvalidTimestamp -- 6 TimestampOutOfPeriod -- 7 TimestampOlderThanLastRequest -- 8 MissingMessageRepresentationParameter -- 9 ContentMd5NotMatching -- 10 UserUnknown -- 11 UserDisabled -- 12 UserInvalid -- 13 UserHasNoPermission - -Frequent HTTP response status codes ------- -**200 OK**: Standard response for successful HTTP requests. - -**201 Created**: The request has been fulfilled and resulted in a new resource being created. - -**204 No Content**: The server successfully processed the request, but is not returning any content. Usually used as a response to a successful delete request. - -**400 BadRequest**: There is something wrong with the request, for instance an invalid or missing parameter. - -**401 Unauthorized**: Authentication failed or the user is not authorized (in case of UserHasNoPermission). There is no content returned because no access can be granted to the client. - -**403 Forbidden**: The resource cannot be accessed through the API, for example for security reasons. - -**404 Not found**: The requested ressource cannot be found. - -**406 Not Acceptable**: The requested resource is only capable of generating content not acceptable according to the accept headers sent in the request. Typically generated by OData provider. - -**422 Unprocessable entity**: The request is ok but its processing failed due to sematic issues or unprocessable instructions. For example putting the payment status of an order to an unknown value. - -**500 Internal Server Error**: A generic error message, given when no more specific message is suitable. - -**501 Not implemented**: Accessing the ressource through the API is not implemented (yet). - -Query options ------- -[OData query options][2] allows to manipulate the querying of data like sorting, filtering, paging etc. They are send in the query string of the request URL. A more detailed overview can be found [here][3]. - -Custom query options should lighten the work with the SmartStore.Net Web API, especially when you work with entity relationships. - -**SmNetFulfill{property_name}**: Entities are often in multiple relationships with other entities. In most cases an ID has to be set to create or to change such a relation. But mostly this ID is unknown to you. To reduce the amount of API round trips this option can set an entity relation indirectly. Example: You want to add a german address but you don't know the ID of the german country entity which is required for inserting an address. Rather than calling the API again to get the ID you can add the query option SmNetFulfillCountry=DE and the API resolves the relationship automatically. The API can fulfill the following properties: - -- Country: The two or three letter ISO country code. Example: SmNetFulfillCountry=USA -- StateProvince: The abbreviation of a state province. Example for California: SmNetFulfillStateProvince=CA -- Language: The culture of a language. Example for German: SmNetFulfillLanguage=de-DE -- Currency: The ISO code of a currency. Example for Euro: SmNetFulfillCurrency=EUR - -# HMAC authentication -The SmartStore.Net Web API uses the HMAC authentication method to protect data from unauthorized access. - -HMAC (hash-based message authentication code) is a sessionless authentication method, where the integrity of a resource request is guaranteed through a this request representing code (called message representation) and a cryptological hash function. The procedure is considered to be very safe. It is used for example by Amazon to protect their S3 Web services. - -SmartStore.Net uses SHA-256 as hash function, which is why this authentication procedure is often called HMAC-SHA256. - -The consumer must transmit a timestamp with each request which may not differ too far from the server time, otherwise the authentication will fail. The storekeeper can configure this time window in the plugin configuration. The default value is 15 minutes. To prevent replay attacks the timestamp must be younger than the one of a previous request. - - -Message representation ------- -The message representation is a concatenation of various informations separated by newline characters. All values are required but can be empty (in case of Content-MD5). It must be build as follows: - - HTTP method\n - Content-MD5\n - Response content type (accept header)\n - Canonicalized URI\n - ISO-8601 UTC timestamp\n - Public key - -**HTTP method**: In lower case. Example: `post` - -**Content-MD5**: The base64 encoded MD5 hash of the HTTP body, so `base64(md5Hash(content))`. For GET requests this fied is empty. The value should be equal to the optional Content-MD5 request header field. For example the MD5 hash for the content - - {"OrderId":152,"Note":"Hello world!","DisplayToCustomer":false,"CreatedOnUtc":"2013-11-09T11:15:00"} - -is `lgifXydL3FhffpTIilkwOw==`. - -**Response content type**: The value of the accept header field. In lower case. Example: `application/json, text/javascript, */*` - -**Canonicalized URI**: The complete URI of the requested resource (including query string). In lower case. Example: `http://localhost:1260/odata/v1/ordernotes` - -**ISO-8601 UTC timestamp**: Current UTC date and time including milliseconds. Must be equal to the request header field SmartStore-Net-Api-Date. Example: `2013-11-09T11:37:21.1918793Z`. The API accepts milliseconds with 7 and 3 digits. Can be created in C# as follows: `string timestamp = DateTime.UtcNow.ToString("o");` - -**Public key**: The public key of the user. In lower case. Example: `0c6b33651708eb09c8a8d6036b79d739` - -A complete message representation might look like this: - - post - lgifXydL3FhffpTIilkwOw== - application/json, text/javascript, */* - http://localhost:1260/odata/v1/ordernotes - 2013-11-09T11:42:48.4715986Z - 0c6b33651708eb09c8a8d6036b79d739 - -HMAC signature ------- -The signature is the computed hash of the message representation by using SHA-256 and the user's secret key. Always UTF8 encode the secret key and the message representation while calculating the hash. Example of creating the HMAC signature: - - public string CreateSignature(string secretKey, string messageRepresentation) - { - if (string.IsNullOrWhiteSpace(secretKey) || string.IsNullOrWhiteSpace(messageRepresentation)) - return ""; - - string signature; - var secretBytes = Encoding.UTF8.GetBytes(secretKey); - var valueBytes = Encoding.UTF8.GetBytes(messageRepresentation); - - using (var hmac = new HMACSHA256(secretBytes)) - { - var hash = hmac.ComputeHash(valueBytes); - signature = Convert.ToBase64String(hash); - } - return signature; - } - -The signature is transmitted as a base64 encoded string together with the schema using authorization header field. -For above message representation and the secret key `3025c89ebaab20b71e0e42744239bf50` the authorization header field is - - Authorization: SmNetHmac1 +yvONYvJmQl19omu1uE3HVlQ7afd7Qqkk8DrNrfUbe8= - -# Code examples -See also [this tutorial][1] for more information about using the ASP.NET web API client libraries. - -Making a GET request ------- -Let us read orders created after a particular date. For security reasons query results needs to be paged, so we have to specify the $top option (and optionally $skip). - - string publicKey = "0c6b33651708eb09c8a8d6036b79d739"; - string secretKey = "3025c89ebaab20b71e0e42744239bf50"; - string method = "get"; - string accept = "application/json, text/javascript, */*"; - string timestamp = DateTime.UtcNow.ToString("o"); // 2013-11-11T10:15:54.1731069Z - string url = "http://localhost:1260/odata/v1/Orders?$top=10&$filter=CreatedOnUtc gt datetime'2013-02-20T00:00:00'"; - -First we create the message representation. - - string messageRepresentation = string.Join("\n", - get.ToLower(), - "", - accept.ToLower(), - url.ToLower(), - timestamp, - publicKey.ToLower() - ); - -It looks like: - - get - - application/json, text/javascript, */* - http://localhost:1260/odata/v1/orders?$top=10&$filter=createdonutc gt datetime'2013-02-20t00:00:00' - 2013-11-11T10:15:54.1731069Z - 0c6b33651708eb09c8a8d6036b79d739 - -Now we can calculate the HMAC signature by using our secret key. - - string signature = CreateSignature(secretKey, messageRepresentation); // hWce6V2KA0kkB0GBbIK0GSw5QAcS3+vj+m+WN/8k9EE= - -We have all informations to setup the request, so we create a web request object and pass the required headers. - - var request = (HttpWebRequest)WebRequest.Create(url); - request.Method = method; - request.UserAgent = "My shopping data consumer v.1.0"; - request.Accept = accept; - request.Headers.Add("Accept-Charset", "UTF-8"); - request.Headers.Add("SmartStore-Net-Api-PublicKey", publicKey); - request.Headers.Add("SmartStore-Net-Api-Date", timestamp); - request.Headers.Add("Authorization", "SmNetHmac1 " + signature); - -The complete header looks like: - - User-Agent: My shopping data consumer v.1.0 - Accept: application/json, text/javascript, */* - Accept-Charset: UTF-8 - SmartStore-Net-Api-PublicKey: 0c6b33651708eb09c8a8d6036b79d739 - SmartStore-Net-Api-Date: 2013-11-11T10:15:54.1731069Z - Authorization: SmNetHmac1 hWce6V2KA0kkB0GBbIK0GSw5QAcS3+vj+m+WN/8k9EE= - -Making a POST request ------- -Posting means inserting data via API. This example shows how to add a new order note "Hello world!" to the order with ID 152. Here is the function to create the MD5 hash of the request body: - - public string CreateContentMd5Hash(byte[] content) - { - string result = ""; - if (content != null && content.Length > 0) - { - using (var md5 = MD5.Create()) - { - byte[] hash = md5.ComputeHash(content); - result = Convert.ToBase64String(hash); - } - } - return result; - } - -All other variables have not changed. - - string content = "{\"OrderId\":152,\"Note\":\"Hello world!\",\"DisplayToCustomer\":false,\"CreatedOnUtc\":\"2013-11-09T11:15:00\"}"; - - byte[] data = Encoding.UTF8.GetBytes(content); - string contentMd5Hash = CreateContentMd5Hash(data); - - string method = "post"; - string timestamp = DateTime.UtcNow.ToString("o"); // 2013-11-11T19:44:04.9378268Z - string url = "http://localhost:1260/odata/v1/OrderNotes"; - -We add the same header fields as in the previous example and additionally: - - request.ContentLength = data.Length; - request.ContentType = "application/json; charset=utf-8"; - request.Headers.Add("Content-MD5", contentMd5Hash); // optional - -And we write the content into the request stream. - - using (var stream = request.GetRequestStream()) - { - stream.Write(data, 0, data.Length); - } - -The message representation is: - - post - lgifXydL3FhffpTIilkwOw== - application/json, text/javascript, */* - http://localhost:1260/odata/v1/ordernotes - 2013-11-11T19:44:04.9378268Z - 0c6b33651708eb09c8a8d6036b79d739 - -The header looks like: - - User-Agent: My shopping data consumer v.1.0 - Accept: application/json, text/javascript, */* - Accept-Charset: UTF-8 - SmartStore-Net-Api-PublicKey: 0c6b33651708eb09c8a8d6036b79d739 - SmartStore-Net-Api-Date: 2013-11-11T19:44:04.9378268Z - Content-Type: application/json; charset=utf-8 - Content-Length: 100 - Content-MD5: lgifXydL3FhffpTIilkwOw== - Authorization: SmNetHmac1 ejKxxtHNJYHCtBglZPg+cbSs3YTrA50pkfTHtVb1PMo= - -As a general rule POST, PUT and PATCH are returning the added or changed record. For example: - - { - "odata.metadata":"http://localhost:1260/odata/v1/$metadata#OrderNotes/@Element","OrderId":152,"Note":"Hello world!","DisplayToCustomer":false,"CreatedOnUtc":"2013-11-09T11:15:00","Id":692 - } - -Processing the response ------- -Example of reading the response into a string: - - HttpWebResponse webResponse = null; - string response; - - try - { - webResponse = request.GetResponse() as HttpWebResponse; - using (var reader = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8)) - { - response = reader.ReadToEnd(); - } - } - catch (WebException wexc) { /* ... */ } - catch (Exception exc) { /* ... */ } - finally - { - if (webResponse != null) - { - webResponse.Close(); - webResponse.Dispose(); - } - } - -JSON data can be easily parsed into dynamic or strongly typed objects using [Json.NET][6]. This example deserialize a JSON string into a list of customers. - - public class Customer - { - public string Id { get; set; } - public string CustomerGuid { get; set; } - public string Email { get; set; } - // more properties... - } - - JObject json = JObject.Parse(response); - string metadata = (string)json["odata.metadata"]; - - if (!string.IsNullOrWhiteSpace(metadata) && metadata.EndsWith("#Customers")) - { - List customers = json["value"].Select(x => x.ToObject()).ToList(); - } - -Dynamic JSON parsing might look like this: - - dynamic dynamicJson = JObject.Parse(response); - - foreach (dynamic customer in dynamicJson.value) - { - string str = string.Format("{0} {1} {2}", customer.Id, customer.CustomerGuid, customer.Email); - Debug.WriteLine(str); - } - - -# Working with the product entity - -#### Getting a product with name *SmartStore eBay SmartSeller* - - GET http://localhost:1260/odata/v1/Products?$top=1&$filter=Name eq 'SmartStore eBay SmartSeller' - -#### Get child products of group product with ID 210 - - GET http://localhost:1260/odata/v1/Products?$top=120&$filter=ParentGroupedProductId eq 210 - -#### Get final price of product with ID 211 - - POST http://localhost:1260/odata/v1/Products(211)/FinalPrice - -Note the post method. There is a second action `LowestPrice` which serves the lowest possible price for a product. - -#### Managing product attributes - -You can use the following endpoints: `ProductAttributes` (types of attributes), `ProductVariantAttributes` (attribute types mapped to a product), `ProductVariantAttributeValues` (attribute values assigned to product) and optionally `ProductVariantAttributeCombinations` (additional information for particular attribute combinations). Because managing attributes that way can lead to some extra work, there is an action method `ManageAttributes` that wraps up the most important steps. - - POST http://localhost:1260/odata/v1/Products(211)/ManageAttributes - {"Synchronize":true,"Attributes":[ - {"Name":"Color","IsRequired":false,"Values":[ - {"Name":"Red"},{"Name":"Green","IsPreSelected":true},{"Name":"Blue"} - ]}, - {"Name":"Size","Values":[ - {"Name":"Large"},{"Name":"X-Large","IsPreSelected":true} - ]} - ]} - -That request configurates a product with the ID 211 with two attributes `Color` and `Size` and its values `Red, Green, Blue` and `Large, X-Large`. The action parameter `Attributes` is of type `ManageAttributeType`. See the OData metadata document for a complete list of available properties. If `Synchronize` is set to `false` only missing attributes and attribute values are inserted. If set to `true` existing records are also updated and values that are not included in the request body are removed from the database. If you pass an empty value array the attribute and all its values are removed from the product. - -The following method creates all possible attribute combinations for a product with the ID 211 - - POST http://localhost:1260/odata/v1/Products(211)/CreateAttributeCombinations - -As a first step this action always deletes all existing attribute combinations (for a product). - - -# More examples - -#### Get installed payment methods - - GET http://localhost:1260/api/v1/Payments/Methods?$filter=Installed eq true - -Note that payment methods in SmartStore.Net are plugins and not entities, so we must use the `/api/v1/` service here. - -#### Get return requests for customer with ID 1 - - GET http://localhost:1260/odata/v1/Customers(1)/ReturnRequests?$top=25&$inlinecount=allpages - -Note the inlinecount option which tells OData to return an odata.count value with total count of matching entities in the response. - -#### Mark order with ID 145 as payed - - POST http://localhost:1260/odata/v1/Orders(145)/PaymentPaid - {"PaymentMethodName":"Payments.Sofortueberweisung"} - -This request is called OData action because it is initiating further data processing on the server. -Note the second line which are optional OData action parameters. They are send in the request body, not in the query string. This example additionally set the system name of the payment method to `Payments.Sofortueberweisung` with which order 145 was balanced. - -Other actions that would change the payment status are `PaymentPending` and `PaymentRefund`. `PaymentRefund` supports the action parameter `Online`. *True* would call the related payment gateway to refund the payment. Use the action `Cancel` to cancel an order. - -#### Get shipping address for order 145 - - GET http://localhost:1260/odata/v1/Orders(145)/ShippingAddress - -This request is called OData navigation. Use `BillingAddress` if you want the billing address of an order to be returned. - -#### Partially update address with ID 1 - - PATCH http://localhost:1260/odata/v1/Addresses(1)?SmNetFulfillCountry=US&SmNetFulfillStateProvince=NY - {"City":"New York","Address1":"21 West 52nd Street","ZipPostalCode":"10021","FirstName":"John","LastName":"Doe"} - -The example uses SmNetFulfillCountry and SmNetFulfillStateProvince options to update the country (USA) and province (New York). That avoids extra querying of country and province records and passing its IDs in the request body. -Note that you cannot use a path `/Orders(145)/ShippingAddress` to update an address because `ShippingAddress` is a navigation property and updates are not supported here. - -#### Get email address of customer with ID 1 - - GET http://localhost:1260/odata/v1/Customers(1)/Email - -#### Get ID of store with name *my nice store* - - GET http://localhost:1260/odata/v1/Stores?$top=1&$filter=Name eq 'my nice store'&$select=Id - -Note the select option which tells OData just to return the Id property. - -#### Getting localized property values - - GET http://localhost:1260/odata/v1/LocalizedPropertys?$top=120&$filter=LocaleKeyGroup eq 'Product' and EntityId eq 224 and Language/LanguageCulture eq 'en-US' - -That's where OData filter enter the equation. That request filters all english property values for a product with the ID 224. LocaleKeyGroup is typically the entity name (Product, Category, Manufacturer, ProductBundleItem, DeliveryTime etc.). -The result looks like - - { - "odata.metadata":"http://localhost:1260/odata/v1/$metadata#LocalizedPropertys","value":[ - { - "EntityId":224,"LanguageId":1,"LocaleKeyGroup":"Product","LocaleKey":"Name","LocaleValue":"My name for the product","Id":111 - },{ - "EntityId":224,"LanguageId":1,"LocaleKeyGroup":"Product","LocaleKey":"FullDescription","LocaleValue":"

Hello world! My product description goes here...

","Id":113 - }] - } - -LocaleKey is the context property name (here name and full description of the product entity). LocaleValue offers the localized value. - -
-[1]: http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client -[2]: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options -[3]: http://www.odata.org/documentation/odata-v2-documentation/uri-conventions/#4_Query_String_Options -[4]: http://msopentech.com/odataorg/libraries/ -[5]: http://msopentech.com/odataorg/introduction/ -[6]: https://json.codeplex.com/ \ No newline at end of file diff --git a/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj b/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj index 2aa46a00b5..114a7f15ce 100644 --- a/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj +++ b/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj @@ -274,7 +274,6 @@ PreserveNewest - Designer diff --git a/src/Plugins/SmartStore.WebApi/changelog.md b/src/Plugins/SmartStore.WebApi/changelog.md index d67eab6786..0ca6ad8919 100644 --- a/src/Plugins/SmartStore.WebApi/changelog.md +++ b/src/Plugins/SmartStore.WebApi/changelog.md @@ -1,5 +1,10 @@ #Release Notes# +##Web Api 2.2.0.2## +###Improvements### +* WebApiAuthenticate attribute can be applied on methods too +* Product image upload requires manage catalog permission + ##Web Api 2.2.0.1## ###New Features### * #652 Support for file upload and multipart mime diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs index ba40cda5b7..5878b455f7 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs @@ -18,7 +18,7 @@ namespace SmartStore.Web.Framework.WebApi.Security { - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] public class WebApiAuthenticateAttribute : System.Web.Http.AuthorizeAttribute { private readonly IWorkContext _workContext; From fbdc2de4e6bad8480d25ad0af232b4246930b86f Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 4 May 2015 13:51:46 +0200 Subject: [PATCH 0090/1256] Setting to display sub-categories on a category page (hide, above products, bottom of page) --- .../Domain/Catalog/CatalogSettings.cs | 16 +++++-- .../201504290937512_SendEmailsManually.cs | 19 ++++++++ .../Controllers/SettingController.cs | 2 + .../Infrastructure/AutoMapperStartupTask.cs | 1 + .../Models/Settings/CatalogSettingsModel.cs | 6 ++- .../Views/Setting/Catalog.cshtml | 7 +-- .../Controllers/CatalogController.cs | 8 +--- .../Models/Catalog/CategoryModel.cs | 3 +- ...egoryTemplate.ProductsInGridOrLines.cshtml | 47 ++++++++++++------- 9 files changed, 75 insertions(+), 34 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs index 967339791f..dd7d67edea 100644 --- a/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs @@ -3,6 +3,12 @@ namespace SmartStore.Core.Domain.Catalog { + public enum SubCategoryDisplayType + { + Hide = 0, + AboveProductList = 5, + Bottom = 10 + } public class CatalogSettings : ISettings { @@ -26,7 +32,7 @@ public CatalogSettings() CompareProductsEnabled = true; FilterEnabled = true; MaxFilterItemsToDisplay = 4; - ShowSubcategoriesAboveProductLists = true; + SubCategoryDisplayType = SubCategoryDisplayType.AboveProductList; ProductSearchAutoCompleteEnabled = true; ShowProductImagesInSearchAutoComplete = true; ProductSearchAutoCompleteNumberOfProducts = 10; @@ -162,10 +168,10 @@ public CatalogSettings() /// public bool ExpandAllFilterCriteria { get; set; } - /// - /// Gets or sets a value indicating whether sub categories above product lists are enabled - /// - public bool ShowSubcategoriesAboveProductLists { get; set; } + /// + /// Gets or sets a value indicating whether and where to display a list of subcategories + /// + public SubCategoryDisplayType SubCategoryDisplayType { get; set; } /// /// Gets or sets a value indicating whether a 'Share button' is enabled diff --git a/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.cs b/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.cs index a80896c5c9..d06f7cea83 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201504290937512_SendEmailsManually.cs @@ -76,6 +76,25 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Admin.Orders.Payments.NewIpn.Hint", "A new notification from the payment provider has arrived in the order notes.", "In den Auftragsnotizen ist eine neue Benachrichtigung vom Zahlungsanbieter eingetroffen."); + + + builder.AddOrUpdate("Admin.Configuration.Settings.Catalog.SubCategoryDisplayType", + "Show subcategories", + "Unterwarengruppen anzeigen", + "Indicates whether and where to show subcategories on a category page.", + "Legt fest, ob und wo Unterwarengruppen auf einer Warengruppenseite angezeigt werden sollen."); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Catalog.SubCategoryDisplayType.Hide", + "Do not display", + "Nicht anzeigen"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Catalog.SubCategoryDisplayType.AboveProductList", + "Above product list", + "ber der Produktliste"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Catalog.SubCategoryDisplayType.Bottom", + "At bottom of page", + "Am Seitenende"); } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs index 11e012f77a..48bd56cf5f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs @@ -566,6 +566,8 @@ public ActionResult Catalog() StoreDependingSettings.GetOverrideKeys(catalogSettings, model, storeScope, _settingService); + model.AvailableSubCategoryDisplayTypes = catalogSettings.SubCategoryDisplayType.ToSelectList(); + model.AvailableDefaultViewModes.Add( new SelectListItem { Value = "grid", Text = _localizationService.GetResource("Common.Grid"), Selected = model.DefaultViewMode.IsCaseInsensitiveEqual("grid") } ); diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index 5466cd9ac8..cd13fe7cbc 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -593,6 +593,7 @@ public void Execute() .ForMember(dest => dest.ActiveShippingRateComputationMethodSystemNames, mo => mo.Ignore()) .ForMember(dest => dest.ReturnValidOptionsIfThereAreAny, mo => mo.Ignore()); Mapper.CreateMap() + .ForMember(dest => dest.AvailableSubCategoryDisplayTypes, mo => mo.Ignore()) .ForMember(dest => dest.AvailableDefaultViewModes, mo => mo.Ignore()) .ForMember(dest => dest.AvailableDeliveryTimes, mo => mo.Ignore()); Mapper.CreateMap() diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs index b6fe64c34b..ba76a185ea 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Web.Mvc; +using SmartStore.Core.Domain.Catalog; using SmartStore.Web.Framework; namespace SmartStore.Admin.Models.Settings @@ -93,8 +94,9 @@ public CatalogSettingsModel() [SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.ExpandAllFilterCriteria")] public bool ExpandAllFilterCriteria { get; set; } - [SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.ShowSubcategoriesAboveProductLists")] - public bool ShowSubcategoriesAboveProductLists { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.SubCategoryDisplayType")] + public SubCategoryDisplayType SubCategoryDisplayType { get; set; } + public SelectList AvailableSubCategoryDisplayTypes { get; set; } #endregion diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml index 969f3c85cd..a55ae23614 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml @@ -401,11 +401,12 @@
- @Html.SmartLabelFor(model => model.ShowSubcategoriesAboveProductLists) + @Html.SmartLabelFor(model => model.SubCategoryDisplayType) - @Html.SettingEditorFor(model => model.ShowSubcategoriesAboveProductLists) - @Html.ValidationMessageFor(model => model.ShowSubcategoriesAboveProductLists) + @Html.SettingOverrideCheckbox(model => Model.SubCategoryDisplayType) + @Html.DropDownListFor(model => model.SubCategoryDisplayType, Model.AvailableSubCategoryDisplayTypes) + @Html.ValidationMessageFor(model => model.SubCategoryDisplayType)
- - - - - - - -
- @Html.SmartLabelFor(model => model.Locales[item].Name) - - @Html.EditorFor(model => Model.Locales[item].Name) - @Html.ValidationMessageFor(model => model.Locales[item].Name) -
- @Html.HiddenFor(model => model.Locales[item].LanguageId) -
- , - @ - - - - -
- @Html.SmartLabelFor(model => model.Name) - - @Html.EditorFor(model => model.Name) - @Html.ValidationMessageFor(model => model.Name) -
- )) - + @
+ + + + + + + +
+ @Html.SmartLabelFor(model => model.Locales[item].Name) + + @Html.EditorFor(model => Model.Locales[item].Name) + @Html.ValidationMessageFor(model => model.Locales[item].Name) +
+ @Html.HiddenFor(model => model.Locales[item].LanguageId) +
+ , + @ + + + + +
+ @Html.SmartLabelFor(model => model.Name) + + @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ )) +
@Html.SmartLabelFor(model => model.AllowsBilling) @@ -118,84 +119,85 @@
} -@helper TabStates() - { - if (Model.Id > 0) - { - - - - - - - - -
- @(Html.Telerik().Grid() - .Name("states-grid") - .DataKeys(x => - { - x.Add(y => y.Id).RouteKey("Id"); - }) - .Columns(columns => - { - columns.Bound(x => x.Name).Width(250); - //TODO display localized values here - columns.Bound(x => x.Abbreviation).Width(100); - columns.Bound(x => x.Published) - .Width(100) - .Template(item => @Html.SymbolForBool(item.Published)) - .ClientTemplate(@Html.SymbolForBool("Published")) - .Centered(); - columns.Bound(x => x.DisplayOrder1).Width(100); - columns.Bound(x => x.Id) - .Width(50) - .Centered() - .ClientTemplate("?btnId=btnRefresh&formId=country-form', 800, 250, true); return false;\" class='t-button' />") - .Title(T("Admin.Common.Edit").Text); - columns.Command(commands => - { - commands.Delete().Localize(T); - }).Width(50); - - }) - .DataBinding(dataBinding => - { - dataBinding.Ajax().Select("States", "Country", new { countryId = Model.Id }) - .Delete("StateDelete", "Country"); - }) - .ClientEvents(x => x.OnError("grid_onError")) - .EnableCustomBinding(true)) -
- - - -
- +@helper TabStates() +{ + if (Model.Id > 0) + { + + + + + + + +
+ @(Html.Telerik().Grid() + .Name("states-grid") + .DataKeys(x => + { + x.Add(y => y.Id).RouteKey("Id"); + }) + .DataBinding(dataBinding => + { + dataBinding.Ajax() + .Select("States", "Country", new { countryId = Model.Id }) + .Delete("StateDelete", "Country"); + }) + .Columns(columns => + { + columns.Bound(x => x.Name); + //TODO display localized values here + columns.Bound(x => x.Abbreviation); + columns.Bound(x => x.Published) + .Template(item => @Html.SymbolForBool(item.Published)) + .ClientTemplate(@Html.SymbolForBool("Published")) + .Width(120) + .Centered(); + columns.Bound(x => x.DisplayOrder1) + .Width(120) + .Centered(); + columns.Bound(x => x.Id) + .Centered() + .Width(120) + .ClientTemplate("?btnId=btnRefresh&formId=country-form', 800, 250, true); return false;\" class='t-button' />") + .Title(""); + columns.Command(commands => + { + commands.Delete().Localize(T); + }).Width(120); + }) + .ClientEvents(x => x.OnError("grid_onError")) + .EnableCustomBinding(true)) +
+ + + +
+ + + } + else + { + @T("Admin.Configuration.Countries.States.SaveBeforeEdit") + } } \ No newline at end of file From 0bccbc9b1db224e2bea55f0b5bea3e640db9f22b Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 6 May 2015 17:52:24 +0200 Subject: [PATCH 0099/1256] Resolves #508 Limit country settings to stores --- changelog.md | 1 + .../Domain/Directory/Country.cs | 11 +- ...505061135313_CountryMultistore.Designer.cs | 29 ++++ .../201505061135313_CountryMultistore.cs | 18 +++ .../201505061135313_CountryMultistore.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 7 + .../Directory/CountryService.cs | 74 ++++++---- .../ExportImport/ExportManager.cs | 1 + .../Controllers/CountryController.cs | 91 +++++++++---- .../Infrastructure/AutoMapperStartupTask.cs | 4 +- .../Models/Directory/CountryModel.cs | 12 +- .../Administration/Views/Country/List.cshtml | 13 +- .../Views/Country/_CreateOrUpdate.cshtml | 45 +++++++ .../Directory/CountryPersistenceTests.cs | 10 +- 14 files changed, 377 insertions(+), 65 deletions(-) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx diff --git a/changelog.md b/changelog.md index 1382f2738f..704960aa82 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,7 @@ * #554 Flag to indicate that a new payment notification (IPN) arrived for an order since last opening\editing of the order * Setting whether and how to display sub-categories on a category page (hide, above products, bottom of page) * Debitoor: Extend option "Book invoice if paid" to also (optionally) mail the invoice as a PDF +* #508 Limit country settings to stores ### Improvements * PDF converter: first init is much faster now diff --git a/src/Libraries/SmartStore.Core/Domain/Directory/Country.cs b/src/Libraries/SmartStore.Core/Domain/Directory/Country.cs index 39bb1ba887..117a487a07 100644 --- a/src/Libraries/SmartStore.Core/Domain/Directory/Country.cs +++ b/src/Libraries/SmartStore.Core/Domain/Directory/Country.cs @@ -1,7 +1,8 @@ using System.Collections.Generic; +using System.Runtime.Serialization; using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Shipping; -using System.Runtime.Serialization; +using SmartStore.Core.Domain.Stores; namespace SmartStore.Core.Domain.Directory { @@ -9,7 +10,7 @@ namespace SmartStore.Core.Domain.Directory /// Represents a country ///
[DataContract] - public partial class Country : BaseEntity, ILocalizedEntity + public partial class Country : BaseEntity, ILocalizedEntity, IStoreMappingSupported { private ICollection _stateProvinces; private ICollection _restrictedShippingMethods; @@ -68,6 +69,12 @@ public partial class Country : BaseEntity, ILocalizedEntity ///
[DataMember] public int DisplayOrder { get; set; } + + /// + /// Gets or sets a value indicating whether the entity is limited/restricted to certain stores + /// + [DataMember] + public bool LimitedToStores { get; set; } /// /// Gets or sets the state/provinces diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs new file mode 100644 index 0000000000..f761e5139e --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class CountryMultistore : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(CountryMultistore)); + + string IMigrationMetadata.Id + { + get { return "201505061135313_CountryMultistore"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs new file mode 100644 index 0000000000..e898f4427e --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs @@ -0,0 +1,18 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class CountryMultistore : DbMigration + { + public override void Up() + { + AddColumn("dbo.Country", "LimitedToStores", c => c.Boolean(nullable: false)); + } + + public override void Down() + { + DropColumn("dbo.Country", "LimitedToStores"); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx new file mode 100644 index 0000000000..9ccce9d534 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 40f76cf62b..dbe63ab8a1 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -264,6 +264,10 @@ 201505052021483_PdfConverterRoleFix.cs + + + 201505061135313_CountryMultistore.cs + @@ -515,6 +519,9 @@ 201505052021483_PdfConverterRoleFix.cs + + 201505061135313_CountryMultistore.cs + diff --git a/src/Libraries/SmartStore.Services/Directory/CountryService.cs b/src/Libraries/SmartStore.Services/Directory/CountryService.cs index aeda79b995..40b2e16a8b 100644 --- a/src/Libraries/SmartStore.Services/Directory/CountryService.cs +++ b/src/Libraries/SmartStore.Services/Directory/CountryService.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; +using SmartStore.Core; using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Directory; +using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; namespace SmartStore.Services.Directory @@ -25,26 +27,28 @@ public partial class CountryService : ICountryService private readonly IRepository _countryRepository; private readonly IEventPublisher _eventPublisher; private readonly ICacheManager _cacheManager; + private readonly IStoreContext _storeContext; + private readonly IRepository _storeMappingRepository; #endregion #region Ctor - /// - /// Ctor - /// - /// Cache manager - /// Country repository - /// Event published public CountryService(ICacheManager cacheManager, IRepository countryRepository, - IEventPublisher eventPublisher) + IEventPublisher eventPublisher, + IStoreContext storeContext, + IRepository storeMappingRepository) { _cacheManager = cacheManager; _countryRepository = countryRepository; _eventPublisher = eventPublisher; + _storeContext = storeContext; + _storeMappingRepository = storeMappingRepository; } + public DbQuerySettings QuerySettings { get; set; } + #endregion #region Methods @@ -76,10 +80,31 @@ public virtual IList GetAllCountries(bool showHidden = false) string key = string.Format(COUNTRIES_ALL_KEY, showHidden); return _cacheManager.Get(key, () => { - var query = from c in _countryRepository.Table - orderby c.DisplayOrder, c.Name - where showHidden || c.Published - select c; + var query = _countryRepository.Table; + + if (!showHidden) + query = query.Where(c => c.Published); + + query = query.OrderBy(c => c.DisplayOrder).ThenBy(c => c.Name); + + if (!showHidden && !QuerySettings.IgnoreMultiStore) + { + var currentStoreId = _storeContext.CurrentStore.Id; + query = from c in query + join sc in _storeMappingRepository.Table + on new { c1 = c.Id, c2 = "Country" } equals new { c1 = sc.EntityId, c2 = sc.EntityName } into c_sm + from sc in c_sm.DefaultIfEmpty() + where !c.LimitedToStores || currentStoreId == sc.StoreId + select c; + + query = from c in query + group c by c.Id into cGroup + orderby cGroup.Key + select cGroup.FirstOrDefault(); + + query = query.OrderBy(c => c.DisplayOrder).ThenBy(c => c.Name); + } + var countries = query.ToList(); return countries; }); @@ -95,11 +120,9 @@ public virtual IList GetAllCountriesForBilling(bool showHidden = false) string key = string.Format(COUNTRIES_BILLING_KEY, showHidden); return _cacheManager.Get(key, () => { - var query = from c in _countryRepository.Table - orderby c.DisplayOrder, c.Name - where (showHidden || c.Published) && c.AllowsBilling - select c; - var countries = query.ToList(); + var allCountries = GetAllCountries(showHidden); + + var countries = allCountries.Where(x => x.AllowsBilling).ToList(); return countries; }); } @@ -113,12 +136,10 @@ public virtual IList GetAllCountriesForShipping(bool showHidden = false { string key = string.Format(COUNTRIES_SHIPPING_KEY, showHidden); return _cacheManager.Get(key, () => - { - var query = from c in _countryRepository.Table - orderby c.DisplayOrder, c.Name - where (showHidden || c.Published) && c.AllowsShipping - select c; - var countries = query.ToList(); + { + var allCountries = GetAllCountries(showHidden); + + var countries = allCountries.Where(x => x.AllowsShipping).ToList(); return countries; }); } @@ -160,11 +181,14 @@ public virtual Country GetCountryByTwoOrThreeLetterIsoCode(string letterIsoCode) /// Country public virtual Country GetCountryByTwoLetterIsoCode(string twoLetterIsoCode) { + if (twoLetterIsoCode.IsEmpty()) + return null; + var query = from c in _countryRepository.Table where c.TwoLetterIsoCode == twoLetterIsoCode select c; - var country = query.FirstOrDefault(); + var country = query.FirstOrDefault(); return country; } @@ -175,9 +199,13 @@ public virtual Country GetCountryByTwoLetterIsoCode(string twoLetterIsoCode) /// Country public virtual Country GetCountryByThreeLetterIsoCode(string threeLetterIsoCode) { + if (threeLetterIsoCode.IsEmpty()) + return null; + var query = from c in _countryRepository.Table where c.ThreeLetterIsoCode == threeLetterIsoCode select c; + var country = query.FirstOrDefault(); return country; } diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 2b89be8e7b..804c967911 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -2029,6 +2029,7 @@ public virtual string ExportCustomersToXml(IList customers) xmlWriter.WriteElementString("SubjectToVat", null, address.Country.SubjectToVat.ToString()); xmlWriter.WriteElementString("Published", null, address.Country.Published.ToString()); xmlWriter.WriteElementString("DisplayOrder", null, address.Country.DisplayOrder.ToString()); + xmlWriter.WriteElementString("LimitedToStores", null, address.Country.LimitedToStores.ToString()); xmlWriter.WriteEndElement(); // Country } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs index 9554f642c0..9af684b301 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs @@ -9,6 +9,7 @@ using SmartStore.Services.Directory; using SmartStore.Services.Localization; using SmartStore.Services.Security; +using SmartStore.Services.Stores; using SmartStore.Web.Framework.Controllers; using Telerik.Web.Mvc; @@ -26,23 +27,32 @@ public class CountryController : AdminControllerBase private readonly IPermissionService _permissionService; private readonly ILocalizedEntityService _localizedEntityService; private readonly ILanguageService _languageService; + private readonly IStoreService _storeService; + private readonly IStoreMappingService _storeMappingService; #endregion #region Constructors public CountryController(ICountryService countryService, - IStateProvinceService stateProvinceService, ILocalizationService localizationService, - IAddressService addressService, IPermissionService permissionService, - ILocalizedEntityService localizedEntityService, ILanguageService languageService) + IStateProvinceService stateProvinceService, + ILocalizationService localizationService, + IAddressService addressService, + IPermissionService permissionService, + ILocalizedEntityService localizedEntityService, + ILanguageService languageService, + IStoreService storeService, + IStoreMappingService storeMappingService) { - this._countryService = countryService; - this._stateProvinceService = stateProvinceService; - this._localizationService = localizationService; - this._addressService = addressService; - this._permissionService = permissionService; - this._localizedEntityService = localizedEntityService; - this._languageService = languageService; + _countryService = countryService; + _stateProvinceService = stateProvinceService; + _localizationService = localizationService; + _addressService = addressService; + _permissionService = permissionService; + _localizedEntityService = localizedEntityService; + _languageService = languageService; + _storeService = storeService; + _storeMappingService = storeMappingService; } #endregion  @@ -50,7 +60,7 @@ public CountryController(ICountryService countryService, #region Utilities [NonAction] - public void UpdateLocales(Country country, CountryModel model) + private void UpdateLocales(Country country, CountryModel model) { foreach (var localized in model.Locales) { @@ -62,7 +72,7 @@ public void UpdateLocales(Country country, CountryModel model) } [NonAction] - public void UpdateLocales(StateProvince stateProvince, StateProvinceModel model) + private void UpdateLocales(StateProvince stateProvince, StateProvinceModel model) { foreach (var localized in model.Locales) { @@ -72,6 +82,28 @@ public void UpdateLocales(StateProvince stateProvince, StateProvinceModel model) localized.LanguageId); } } + + [NonAction] + private void PrepareCountryModel(CountryModel model, Country country, bool excludeProperties) + { + if (model == null) + throw new ArgumentNullException("model"); + + var allStores = _storeService.GetAllStores(); + + model.AvailableStores = allStores.Select(s => s.ToModel()).ToList(); + + if (!excludeProperties) + { + if (country != null) + model.SelectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(country); + else + model.SelectedStoreIds = new int[0]; + } + + ViewBag.StoreCount = allStores.Count; + } + #endregion #region Countries @@ -120,12 +152,15 @@ public ActionResult Create() return AccessDeniedView(); var model = new CountryModel(); - //locales + AddLocales(_languageService, model.Locales); - //default values + PrepareCountryModel(model, null, false); + + //default values model.Published = true; model.AllowsBilling = true; model.AllowsShipping = true; + return View(model); } @@ -139,14 +174,18 @@ public ActionResult Create(CountryModel model, bool continueEditing) { var country = model.ToEntity(); _countryService.InsertCountry(country); - //locales + UpdateLocales(country, model); + _storeMappingService.SaveStoreMappings(country, model.SelectedStoreIds); + NotifySuccess(_localizationService.GetResource("Admin.Configuration.Countries.Added")); + return continueEditing ? RedirectToAction("Edit", new { id = country.Id }) : RedirectToAction("List"); } - //If we got this far, something failed, redisplay form + PrepareCountryModel(model, null, true); + return View(model); } @@ -157,15 +196,17 @@ public ActionResult Edit(int id) var country = _countryService.GetCountryById(id); if (country == null) - //No country found with the specified id return RedirectToAction("List"); var model = country.ToModel(); - //locales + AddLocales(_languageService, model.Locales, (locale, languageId) => { locale.Name = country.GetLocalized(x => x.Name, languageId, false, false); }); + + PrepareCountryModel(model, country, false); + return View(model); } @@ -177,21 +218,24 @@ public ActionResult Edit(CountryModel model, bool continueEditing) var country = _countryService.GetCountryById(model.Id); if (country == null) - //No country found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) { country = model.ToEntity(country); _countryService.UpdateCountry(country); - //locales + UpdateLocales(country, model); + _storeMappingService.SaveStoreMappings(country, model.SelectedStoreIds); + NotifySuccess(_localizationService.GetResource("Admin.Configuration.Countries.Updated")); + return continueEditing ? RedirectToAction("Edit", new { id = country.Id }) : RedirectToAction("List"); } - //If we got this far, something failed, redisplay form + PrepareCountryModel(model, country, true); + return View(model); } @@ -203,7 +247,6 @@ public ActionResult DeleteConfirmed(int id) var country = _countryService.GetCountryById(id); if (country == null) - //No country found with the specified id return RedirectToAction("List"); try @@ -270,7 +313,6 @@ public ActionResult StateCreatePopup(string btnId, string formId, StateProvinceM var country = _countryService.GetCountryById(model.CountryId); if (country == null) - //No country found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) @@ -360,8 +402,7 @@ public ActionResult StateDelete(int id, GridCommand command) } [AcceptVerbs(HttpVerbs.Get)] - public ActionResult GetStatesByCountryId(string countryId, - bool? addEmptyStateIfRequired, bool? addAsterisk) + public ActionResult GetStatesByCountryId(string countryId, bool? addEmptyStateIfRequired, bool? addAsterisk) { //permission validation is not required here diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index cd13fe7cbc..f65a1d470d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -116,7 +116,9 @@ public void Execute() .ForMember(dest => dest.RestrictedShippingMethods, mo => mo.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.NumberOfStates, mo => mo.MapFrom(src => src.StateProvinces != null ? src.StateProvinces.Count : 0)) - .ForMember(dest => dest.Locales, mo => mo.Ignore()); + .ForMember(dest => dest.Locales, mo => mo.Ignore()) + .ForMember(dest => dest.AvailableStores, mo => mo.Ignore()) + .ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore()); //state/provinces Mapper.CreateMap() .ForMember(dest => dest.DisplayOrder1, mo => mo.MapFrom(src => src.DisplayOrder)) diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Directory/CountryModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Directory/CountryModel.cs index 6df12ca14f..ed1ca645c8 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Directory/CountryModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Directory/CountryModel.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Web.Mvc; using FluentValidation.Attributes; +using SmartStore.Admin.Models.Stores; using SmartStore.Admin.Validators.Directory; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Localization; @@ -15,6 +16,7 @@ public CountryModel() { Locales = new List(); } + [SmartResourceDisplayName("Admin.Configuration.Countries.Fields.Name")] [AllowHtml] public string Name { get; set; } @@ -45,13 +47,17 @@ public CountryModel() [SmartResourceDisplayName("Admin.Configuration.Countries.Fields.DisplayOrder")] public int DisplayOrder { get; set; } - - - [SmartResourceDisplayName("Admin.Configuration.Countries.Fields.NumberOfStates")] public int NumberOfStates { get; set; } public IList Locales { get; set; } + + [SmartResourceDisplayName("Admin.Common.Store.LimitedTo")] + public bool LimitedToStores { get; set; } + + [SmartResourceDisplayName("Admin.Common.Store.AvailableFor")] + public List AvailableStores { get; set; } + public int[] SelectedStoreIds { get; set; } } public class CountryLocalizedModel : ILocalizedModelLocal diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Country/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Country/List.cshtml index 6395a0a7d0..5285bcd4d5 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Country/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Country/List.cshtml @@ -1,7 +1,6 @@ @model Telerik.Web.Mvc.GridModel @using Telerik.Web.Mvc.UI @{ - //page title ViewBag.Title = T("Admin.Configuration.Countries").Text; }
@@ -55,17 +54,17 @@ columns.Bound(x => x.DisplayOrder) .Width(50) .Centered(); + columns.Bound(x => x.LimitedToStores) + .Template(item => @Html.SymbolForBool(item.LimitedToStores)) + .ClientTemplate(@Html.SymbolForBool("LimitedToStores")) + .Centered() + .Width(100) + .Hidden(ViewBag.StoreCount <= 1); columns.Bound(x => x.Published) .Width(50) .Template(item => @Html.SymbolForBool(item.Published)) .ClientTemplate(@Html.SymbolForBool("Published")) .Centered(); - //columns.Bound(x => x.Id) - // .Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id })) - // .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") - // .Width(50) - // .Centered() - // .HeaderTemplate(T("Admin.Common.Edit").Text); }) .DataBinding(dataBinding => dataBinding.Ajax().Select("CountryList", "Country")) .EnableCustomBinding(true)) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml index 4c5884ad39..c96abce377 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml @@ -7,6 +7,7 @@ { x.Add().Text(T("Admin.Configuration.Countries.Info").Text).Content(TabInfo()).Selected(true); x.Add().Text(T("Admin.Configuration.Countries.States").Text).Content(TabStates()); + x.Add().Text(T("Admin.Common.Stores").Text).Content(TabStores()); //generate an event EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "country-edit", this.Html, this.Model)); @@ -200,4 +201,48 @@ { @T("Admin.Configuration.Countries.States.SaveBeforeEdit") } +} + +@helper TabStores() +{ + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.LimitedToStores) + + @Html.EditorFor(model => model.LimitedToStores) + @Html.ValidationMessageFor(model => model.LimitedToStores) +
+ @Html.SmartLabelFor(model => model.AvailableStores) + + @if (Model.AvailableStores != null && Model.AvailableStores.Count > 0) + { + foreach (var store in Model.AvailableStores) + { + + } + } + else + { +
@T("Admin.Configuration.Stores.NoStoresDefined")
+ } +
} \ No newline at end of file diff --git a/src/Tests/SmartStore.Data.Tests/Directory/CountryPersistenceTests.cs b/src/Tests/SmartStore.Data.Tests/Directory/CountryPersistenceTests.cs index c83687092f..18dfac25d3 100644 --- a/src/Tests/SmartStore.Data.Tests/Directory/CountryPersistenceTests.cs +++ b/src/Tests/SmartStore.Data.Tests/Directory/CountryPersistenceTests.cs @@ -1,8 +1,8 @@ using System.Linq; +using NUnit.Framework; using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Shipping; using SmartStore.Tests; -using NUnit.Framework; namespace SmartStore.Data.Tests.Directory { @@ -22,7 +22,8 @@ public void Can_save_and_load_country() NumericIsoCode = 1, SubjectToVat = true, Published = true, - DisplayOrder = 1 + DisplayOrder = 1, + LimitedToStores = true }; var fromDb = SaveAndLoadEntity(country); @@ -36,6 +37,7 @@ public void Can_save_and_load_country() fromDb.SubjectToVat.ShouldEqual(true); fromDb.Published.ShouldEqual(true); fromDb.DisplayOrder.ShouldEqual(1); + fromDb.LimitedToStores.ShouldEqual(true); } [Test] @@ -55,7 +57,7 @@ public void Can_save_and_load_country_with_states() }; country.StateProvinces.Add ( - new StateProvince() + new StateProvince { Name = "California", Abbreviation = "CA", @@ -88,7 +90,7 @@ public void Can_save_and_load_country_with_restrictions() }; country.RestrictedShippingMethods.Add ( - new ShippingMethod() + new ShippingMethod { Name = "By train", } From 7e0bb2931926cc1f4727237b9b51aaa808f7203a Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Wed, 6 May 2015 18:30:24 +0200 Subject: [PATCH 0100/1256] Added attribute overrides to PDF header and footer --- src/Presentation/SmartStore.Web/Controllers/CommonController.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Presentation/SmartStore.Web/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Controllers/CommonController.cs index 725ba8a8a5..87febc0ba2 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CommonController.cs @@ -928,6 +928,7 @@ public ActionResult AccountDropdown() return PartialView(model); } + [OverrideActionFilters, OverrideAuthorization] public ActionResult PdfReceiptHeader(PdfHeaderFooterVariables vars, int storeId = 0, bool isPartial = false) { var model = PreparePdfReceiptHeaderFooterModel(storeId); @@ -940,6 +941,7 @@ public ActionResult PdfReceiptHeader(PdfHeaderFooterVariables vars, int storeId return View(model); } + [OverrideActionFilters, OverrideAuthorization] public ActionResult PdfReceiptFooter(PdfHeaderFooterVariables vars, int storeId = 0, bool isPartial = false) { var model = PreparePdfReceiptHeaderFooterModel(storeId); From bb0a6b9eaf8c2e72428230119af6e6b3af0fbbbf Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 6 May 2015 21:53:56 +0200 Subject: [PATCH 0101/1256] Increased version number to 2.2.1 --- SmartStoreNET.Tasks.Targets | 2 +- src/AssemblyVersionInfo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SmartStoreNET.Tasks.Targets b/SmartStoreNET.Tasks.Targets index 54d1699fa0..980f2060e3 100644 --- a/SmartStoreNET.Tasks.Targets +++ b/SmartStoreNET.Tasks.Targets @@ -44,7 +44,7 @@ x86 $(BUILD_NUMBER) - 2.2.0 + 2.2.1 $(StageFolder) .$(Version) diff --git a/src/AssemblyVersionInfo.cs b/src/AssemblyVersionInfo.cs index c7a921b937..8cf3480af0 100644 --- a/src/AssemblyVersionInfo.cs +++ b/src/AssemblyVersionInfo.cs @@ -12,4 +12,4 @@ [assembly: AssemblyVersion("2.2.0.0")] [assembly: AssemblyFileVersion("2.2.0.0")] -[assembly: AssemblyInformationalVersion("2.2.0.0")] +[assembly: AssemblyInformationalVersion("2.2.1.0")] From c182d1742aece8a3ba9d6aaab5a8836cc259df08 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 6 May 2015 22:16:35 +0200 Subject: [PATCH 0102/1256] Minor fix: mobile themes should not be previewable --- .../SmartStore.Web/Administration/Views/Theme/List.cshtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Theme/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Theme/List.cshtml index a6324211ee..ffcf8688ca 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Theme/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Theme/List.cshtml @@ -145,13 +145,13 @@ @if (!isBroken) {
- if (!theme.IsMobileTheme) + @if (!theme.IsMobileTheme) { } - if (theme.IsConfigurable) + @if (theme.IsConfigurable) { From d7b78276c804b68b4d645cf3c43d61b5c2a4fdb2 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 6 May 2015 22:18:16 +0200 Subject: [PATCH 0103/1256] Minor improvement --- .../Administration/Views/Common/CheckUpdate.cshtml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Common/CheckUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Common/CheckUpdate.cshtml index d0f7574f71..2996be7024 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Common/CheckUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Common/CheckUpdate.cshtml @@ -14,6 +14,10 @@
@if (!Model.UpdateAvailable) { +
+
@T("Admin.CheckUpdate.YourVersion")
+
@Model.CurrentVersion
+
@T("Admin.CheckUpdate.IsUpToDate")
From c70849ada13c72edf26f9a97d7d7a92f60f37ef9 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 7 May 2015 11:51:05 +0200 Subject: [PATCH 0104/1256] Resolves #205 Add multistore support for forums --- .../Domain/Forums/ForumGroup.cs | 8 +- .../201505061135313_CountryMultistore.resx | 126 -------- ...05061813010_CountryMultistore.Designer.cs} | 2 +- ...s => 201505061813010_CountryMultistore.cs} | 2 + .../201505061813010_CountryMultistore.resx | 126 ++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../Forums/ForumService.cs | 236 +++++++------- .../Forums/IForumService.cs | 6 +- .../Controllers/ForumController.cs | 137 +++++--- .../Infrastructure/AutoMapperStartupTask.cs | 2 + .../Models/Forums/ForumGroupModel.cs | 8 + .../Administration/Views/Forum/List.cshtml | 14 +- .../Forum/_CreateOrUpdateForumGroup.cshtml | 115 +++++-- .../Controllers/BoardsController.cs | 296 ++++++++++-------- 14 files changed, 632 insertions(+), 456 deletions(-) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx rename src/Libraries/SmartStore.Data/Migrations/{201505061135313_CountryMultistore.Designer.cs => 201505061813010_CountryMultistore.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201505061135313_CountryMultistore.cs => 201505061813010_CountryMultistore.cs} (73%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.resx diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs index 4e4cc99eba..77022b7047 100644 --- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs +++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; +using SmartStore.Core.Domain.Stores; namespace SmartStore.Core.Domain.Forums { /// /// Represents a forum group /// - public partial class ForumGroup : BaseEntity + public partial class ForumGroup : BaseEntity, IStoreMappingSupported { private ICollection _forums; @@ -35,6 +36,11 @@ public partial class ForumGroup : BaseEntity ///
public DateTime UpdatedOnUtc { get; set; } + /// + /// Gets or sets a value indicating whether the entity is limited/restricted to certain stores + /// + public bool LimitedToStores { get; set; } + /// /// Gets or sets the collection of Forums /// diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx deleted file mode 100644 index 9ccce9d534..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.Designer.cs index f761e5139e..a39bd3bf2f 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class CountryMultistore : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201505061135313_CountryMultistore"; } + get { return "201505061813010_CountryMultistore"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs similarity index 73% rename from src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs rename to src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs index e898f4427e..c701338fee 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs @@ -8,10 +8,12 @@ public partial class CountryMultistore : DbMigration public override void Up() { AddColumn("dbo.Country", "LimitedToStores", c => c.Boolean(nullable: false)); + AddColumn("dbo.Forums_Group", "LimitedToStores", c => c.Boolean(nullable: false)); } public override void Down() { + DropColumn("dbo.Forums_Group", "LimitedToStores"); DropColumn("dbo.Country", "LimitedToStores"); } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.resx b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.resx new file mode 100644 index 0000000000..8a4e44f84b --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index dbe63ab8a1..602115f62d 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -264,9 +264,9 @@ 201505052021483_PdfConverterRoleFix.cs - - - 201505061135313_CountryMultistore.cs + + + 201505061813010_CountryMultistore.cs @@ -519,8 +519,8 @@ 201505052021483_PdfConverterRoleFix.cs - - 201505061135313_CountryMultistore.cs + + 201505061813010_CountryMultistore.cs diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs index 6fed24aff9..4f5ca20ce4 100644 --- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs +++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs @@ -6,6 +6,7 @@ using SmartStore.Core.Data; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Forums; +using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; using SmartStore.Services.Common; using SmartStore.Services.Customers; @@ -19,13 +20,16 @@ namespace SmartStore.Services.Forums public partial class ForumService : IForumService { #region Constants - private const string FORUMGROUP_ALL_KEY = "SmartStore.forumgroup.all"; + + private const string FORUMGROUP_ALL_KEY = "SmartStore.forumgroup.all-{0}"; private const string FORUM_ALLBYFORUMGROUPID_KEY = "SmartStore.forum.allbyforumgroupid-{0}"; private const string FORUMGROUP_PATTERN_KEY = "SmartStore.forumgroup."; private const string FORUM_PATTERN_KEY = "SmartStore.forum."; - #endregion + + #endregion #region Fields + private readonly IRepository _forumGroupRepository; private readonly IRepository _forumRepository; private readonly IRepository _forumTopicRepository; @@ -40,28 +44,13 @@ public partial class ForumService : IForumService private readonly IWorkContext _workContext; private readonly IWorkflowMessageService _workflowMessageService; private readonly IEventPublisher _eventPublisher; + private readonly IStoreContext _storeContext; + private readonly IRepository _storeMappingRepository; #endregion #region Ctor - /// - /// Ctor - /// - /// Cache manager - /// Forum group repository - /// Forum repository - /// Forum topic repository - /// Forum post repository - /// Private message repository - /// Forum subscription repository - /// Forum settings - /// Customer repository - /// Generic attribute service - /// Customer service - /// Work context - /// Workflow message service - /// Event published public ForumService(ICacheManager cacheManager, IRepository forumGroupRepository, IRepository forumRepository, @@ -75,25 +64,31 @@ public ForumService(ICacheManager cacheManager, ICustomerService customerService, IWorkContext workContext, IWorkflowMessageService workflowMessageService, - IEventPublisher eventPublisher - ) + IEventPublisher eventPublisher, + IStoreContext storeContext, + IRepository storeMappingRepository) { - this._cacheManager = cacheManager; - this._forumGroupRepository = forumGroupRepository; - this._forumRepository = forumRepository; - this._forumTopicRepository = forumTopicRepository; - this._forumPostRepository = forumPostRepository; - this._forumPrivateMessageRepository = forumPrivateMessageRepository; - this._forumSubscriptionRepository = forumSubscriptionRepository; - this._forumSettings = forumSettings; - this._customerRepository = customerRepository; - this._genericAttributeService = genericAttributeService; - this._customerService = customerService; - this._workContext = workContext; - this._workflowMessageService = workflowMessageService; + _cacheManager = cacheManager; + _forumGroupRepository = forumGroupRepository; + _forumRepository = forumRepository; + _forumTopicRepository = forumTopicRepository; + _forumPostRepository = forumPostRepository; + _forumPrivateMessageRepository = forumPrivateMessageRepository; + _forumSubscriptionRepository = forumSubscriptionRepository; + _forumSettings = forumSettings; + _customerRepository = customerRepository; + _genericAttributeService = genericAttributeService; + _customerService = customerService; + _workContext = workContext; + _workflowMessageService = workflowMessageService; _eventPublisher = eventPublisher; + _storeContext = storeContext; + _storeMappingRepository = storeMappingRepository; } - #endregion + + public DbQuerySettings QuerySettings { get; set; } + + #endregion #region Utilities @@ -288,14 +283,33 @@ public virtual ForumGroup GetForumGroupById(int forumGroupId) /// Gets all forum groups ///
/// Forum groups - public virtual IList GetAllForumGroups() + public virtual IList GetAllForumGroups(bool showHidden = false) { - string key = string.Format(FORUMGROUP_ALL_KEY); + string key = string.Format(FORUMGROUP_ALL_KEY, showHidden); return _cacheManager.Get(key, () => { - var query = from fg in _forumGroupRepository.Table - orderby fg.DisplayOrder - select fg; + var query = _forumGroupRepository.Table; + + if (!showHidden && !QuerySettings.IgnoreMultiStore) + { + var currentStoreId = _storeContext.CurrentStore.Id; + + query = + from fg in query + join sm in _storeMappingRepository.Table on new { c1 = fg.Id, c2 = "ForumGroup" } equals new { c1 = sm.EntityId, c2 = sm.EntityName } into fg_sm + from sm in fg_sm.DefaultIfEmpty() + where !fg.LimitedToStores || currentStoreId == sm.StoreId + select fg; + + query = + from fg in query + group fg by fg.Id into fgGroup + orderby fgGroup.Key + select fgGroup.FirstOrDefault(); + } + + query = query.OrderBy(m => m.DisplayOrder); + return query.ToList(); }); } @@ -552,32 +566,33 @@ public virtual ForumTopic GetTopicById(int forumTopicId, bool increaseViews) /// Page index /// Page size /// Forum Topics - public virtual IPagedList GetAllTopics(int forumId, - int customerId, string keywords, ForumSearchType searchType, - int limitDays, int pageIndex, int pageSize) + public virtual IPagedList GetAllTopics(int forumId, int customerId, string keywords, ForumSearchType searchType, int limitDays, int pageIndex, int pageSize) { DateTime? limitDate = null; + if (limitDays > 0) { limitDate = DateTime.UtcNow.AddDays(-limitDays); } - var query1 = from ft in _forumTopicRepository.Table - join fp in _forumPostRepository.Table on ft.Id equals fp.TopicId - where - (forumId == 0 || ft.ForumId == forumId) && - (customerId == 0 || ft.CustomerId == customerId) && - ( - // following line causes SqlCeException on SQLCE4 (comparing parameter to IS NULL in query) -works on SQL Server - // String.IsNullOrEmpty(keywords) || - ((searchType == ForumSearchType.All || searchType == ForumSearchType.TopicTitlesOnly) && ft.Subject.Contains(keywords)) || - ((searchType == ForumSearchType.All || searchType == ForumSearchType.PostTextOnly) && fp.Text.Contains(keywords))) && - (!limitDate.HasValue || limitDate.Value <= ft.LastPostTime) - select ft.Id; - - var query2 = from ft in _forumTopicRepository.Table - where query1.Contains(ft.Id) - orderby ft.TopicTypeId descending, ft.LastPostTime descending, ft.Id descending - select ft; + + var query1 = + from ft in _forumTopicRepository.Table + join fp in _forumPostRepository.Table on ft.Id equals fp.TopicId + where + (forumId == 0 || ft.ForumId == forumId) && + (customerId == 0 || ft.CustomerId == customerId) && + (!limitDate.HasValue || limitDate.Value <= ft.LastPostTime) && + ( + ((searchType == ForumSearchType.All || searchType == ForumSearchType.TopicTitlesOnly) && ft.Subject.Contains(keywords)) || + ((searchType == ForumSearchType.All || searchType == ForumSearchType.PostTextOnly) && fp.Text.Contains(keywords)) + ) + select ft.Id; + + var query2 = + from ft in _forumTopicRepository.Table + where query1.Contains(ft.Id) + orderby ft.TopicTypeId descending, ft.LastPostTime descending, ft.Id descending + select ft; var topics = new PagedList(query2, pageIndex, pageSize); return topics; @@ -591,18 +606,34 @@ where query1.Contains(ft.Id) /// Forum Topics public virtual IList GetActiveTopics(int forumId, int count) { - var query1 = from ft in _forumTopicRepository.Table - where - (forumId == 0 || ft.ForumId == forumId) && - (ft.LastPostTime.HasValue) - select ft.Id; - - var query2 = from ft in _forumTopicRepository.Table - where query1.Contains(ft.Id) - orderby ft.LastPostTime descending - select ft; - - var forumTopics = query2.Take(count).ToList(); + var query = + from ft in _forumTopicRepository.Table + where (forumId == 0 || ft.ForumId == forumId) && (ft.LastPostTime.HasValue) + select ft; + + if (!QuerySettings.IgnoreMultiStore) + { + var currentStoreId = _storeContext.CurrentStore.Id; + + query = + from ft in query + join ff in _forumRepository.Table on ft.ForumId equals ff.Id + join fg in _forumGroupRepository.Table on ff.ForumGroupId equals fg.Id + join sm in _storeMappingRepository.Table on new { c1 = fg.Id, c2 = "ForumGroup" } equals new { c1 = sm.EntityId, c2 = sm.EntityName } into fg_sm + from sm in fg_sm.DefaultIfEmpty() + where !fg.LimitedToStores || currentStoreId == sm.StoreId + select ft; + + query = + from ft in query + group ft by ft.Id into ftGroup + orderby ftGroup.Key + select ftGroup.FirstOrDefault(); + } + + query = query.OrderByDescending(x => x.LastPostTime); + + var forumTopics = query.Take(count).ToList(); return forumTopics; } @@ -646,8 +677,7 @@ public virtual void InsertTopic(ForumTopic forumTopic, bool sendNotifications) if (!String.IsNullOrEmpty(subscription.Customer.Email)) { - _workflowMessageService.SendNewForumTopicMessage(subscription.Customer, forumTopic, - forum, languageId); + _workflowMessageService.SendNewForumTopicMessage(subscription.Customer, forumTopic, forum, languageId); } } } @@ -725,7 +755,7 @@ public virtual void DeletePost(ForumPost forumPost) //delete topic if it was the first post bool deleteTopic = false; - ForumPost firstPost = forumTopic.GetFirstPost(this); + var firstPost = forumTopic.GetFirstPost(this); if (firstPost != null && firstPost.Id == forumPost.Id) { deleteTopic = true; @@ -786,11 +816,9 @@ public virtual ForumPost GetPostById(int forumPostId) /// Page index /// Page size /// Posts - public virtual IPagedList GetAllPosts(int forumTopicId, - int customerId, string keywords, int pageIndex, int pageSize) + public virtual IPagedList GetAllPosts(int forumTopicId, int customerId, string keywords, int pageIndex, int pageSize) { - return GetAllPosts(forumTopicId, customerId, keywords, true, - pageIndex, pageSize); + return GetAllPosts(forumTopicId, customerId, keywords, true, pageIndex, pageSize); } /// @@ -803,8 +831,7 @@ public virtual IPagedList GetAllPosts(int forumTopicId, /// Page index /// Page size /// Forum Posts - public virtual IPagedList GetAllPosts(int forumTopicId, int customerId, - string keywords, bool ascSort, int pageIndex, int pageSize) + public virtual IPagedList GetAllPosts(int forumTopicId, int customerId, string keywords, bool ascSort, int pageIndex, int pageSize) { var query = _forumPostRepository.Table; if (forumTopicId > 0) @@ -866,14 +893,11 @@ public virtual void InsertPost(ForumPost forumPost, bool sendNotifications) if (sendNotifications) { var forum = forumTopic.Forum; - var subscriptions = GetAllSubscriptions(0, 0, - forumTopic.Id, 0, int.MaxValue); + var subscriptions = GetAllSubscriptions(0, 0, forumTopic.Id, 0, int.MaxValue); var languageId = _workContext.WorkingLanguage.Id; - int friendlyTopicPageIndex = CalculateTopicPageIndex(forumPost.TopicId, - _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 10, - forumPost.Id) + 1; + int friendlyTopicPageIndex = CalculateTopicPageIndex(forumPost.TopicId, _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 10, forumPost.Id) + 1; foreach (ForumSubscription subscription in subscriptions) { @@ -884,8 +908,7 @@ public virtual void InsertPost(ForumPost forumPost, bool sendNotifications) if (!String.IsNullOrEmpty(subscription.Customer.Email)) { - _workflowMessageService.SendNewForumPostMessage(subscription.Customer, forumPost, - forumTopic, forum, friendlyTopicPageIndex, languageId); + _workflowMessageService.SendNewForumPostMessage(subscription.Customer, forumPost, forumTopic, forum, friendlyTopicPageIndex, languageId); } } } @@ -1092,22 +1115,23 @@ public virtual ForumSubscription GetSubscriptionById(int forumSubscriptionId) /// Page index /// Page size /// Forum subscriptions - public virtual IPagedList GetAllSubscriptions(int customerId, int forumId, - int topicId, int pageIndex, int pageSize) + public virtual IPagedList GetAllSubscriptions(int customerId, int forumId, int topicId, int pageIndex, int pageSize) { - var fsQuery = from fs in _forumSubscriptionRepository.Table - join c in _customerRepository.Table on fs.CustomerId equals c.Id - where - (customerId == 0 || fs.CustomerId == customerId) && - (forumId == 0 || fs.ForumId == forumId) && - (topicId == 0 || fs.TopicId == topicId) && - (c.Active && !c.Deleted) - select fs.SubscriptionGuid; - - var query = from fs in _forumSubscriptionRepository.Table - where fsQuery.Contains(fs.SubscriptionGuid) - orderby fs.CreatedOnUtc descending, fs.SubscriptionGuid descending - select fs; + var fsQuery = + from fs in _forumSubscriptionRepository.Table + join c in _customerRepository.Table on fs.CustomerId equals c.Id + where + (customerId == 0 || fs.CustomerId == customerId) && + (forumId == 0 || fs.ForumId == forumId) && + (topicId == 0 || fs.TopicId == topicId) && + (c.Active && !c.Deleted) + select fs.SubscriptionGuid; + + var query = + from fs in _forumSubscriptionRepository.Table + where fsQuery.Contains(fs.SubscriptionGuid) + orderby fs.CreatedOnUtc descending, fs.SubscriptionGuid descending + select fs; var forumSubscriptions = new PagedList(query, pageIndex, pageSize); return forumSubscriptions; @@ -1438,8 +1462,7 @@ public virtual bool IsCustomerAllowedToSubscribe(Customer customer) public virtual int CalculateTopicPageIndex(int forumTopicId, int pageSize, int postId) { int pageIndex = 0; - var forumPosts = GetAllPosts(forumTopicId, 0, - string.Empty, true, 0, int.MaxValue); + var forumPosts = GetAllPosts(forumTopicId, 0, string.Empty, true, 0, int.MaxValue); for (int i = 0; i < forumPosts.TotalCount; i++) { @@ -1454,6 +1477,7 @@ public virtual int CalculateTopicPageIndex(int forumTopicId, int pageSize, int p return pageIndex; } - #endregion + + #endregion } } diff --git a/src/Libraries/SmartStore.Services/Forums/IForumService.cs b/src/Libraries/SmartStore.Services/Forums/IForumService.cs index a0de486d1c..46e0f2f428 100644 --- a/src/Libraries/SmartStore.Services/Forums/IForumService.cs +++ b/src/Libraries/SmartStore.Services/Forums/IForumService.cs @@ -27,7 +27,7 @@ public partial interface IForumService /// Gets all forum groups /// /// Forum groups - IList GetAllForumGroups(); + IList GetAllForumGroups(bool showHidden = false); /// /// Inserts a forum group @@ -105,9 +105,7 @@ public partial interface IForumService /// Page index /// Page size /// Forum Topics - IPagedList GetAllTopics(int forumId, - int customerId, string keywords, ForumSearchType searchType, - int limitDays, int pageIndex, int pageSize); + IPagedList GetAllTopics(int forumId, int customerId, string keywords, ForumSearchType searchType, int limitDays, int pageIndex, int pageSize); /// /// Gets active forum topics diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs index 6c71ef3dcd..1f59f64144 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs @@ -2,10 +2,12 @@ using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Forums; +using SmartStore.Core.Domain.Forums; +using SmartStore.Services; using SmartStore.Services.Forums; using SmartStore.Services.Helpers; -using SmartStore.Services.Localization; using SmartStore.Services.Security; +using SmartStore.Services.Stores; using SmartStore.Web.Framework.Controllers; namespace SmartStore.Admin.Controllers @@ -14,20 +16,51 @@ namespace SmartStore.Admin.Controllers public class ForumController : AdminControllerBase { private readonly IForumService _forumService; + private readonly ICommonServices _commonServices; private readonly IDateTimeHelper _dateTimeHelper; - private readonly ILocalizationService _localizationService; - private readonly IPermissionService _permissionService; + private readonly IStoreMappingService _storeMappingService; public ForumController(IForumService forumService, - IDateTimeHelper dateTimeHelper, ILocalizationService localizationService, - IPermissionService permissionService) + ICommonServices commonServices, + IDateTimeHelper dateTimeHelper, + IStoreMappingService storeMappingService) { - this._forumService = forumService; - this._dateTimeHelper = dateTimeHelper; - this._localizationService = localizationService; - this._permissionService = permissionService; + _forumService = forumService; + _commonServices = commonServices; + _dateTimeHelper = dateTimeHelper; + _storeMappingService = storeMappingService; } + #region Utilities + + [NonAction] + private void PrepareForumGroupModel(ForumGroupModel model, ForumGroup forumGroup, bool excludeProperties) + { + if (model == null) + throw new ArgumentNullException("model"); + + var allStores = _commonServices.StoreService.GetAllStores(); + + model.AvailableStores = allStores.Select(s => s.ToModel()).ToList(); + + if (forumGroup != null) + { + model.CreatedOn = _dateTimeHelper.ConvertToUserTime(forumGroup.CreatedOnUtc, DateTimeKind.Utc); + } + + if (!excludeProperties) + { + if (forumGroup != null) + model.SelectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(forumGroup); + else + model.SelectedStoreIds = new int[0]; + } + + ViewBag.StoreCount = allStores.Count; + } + + #endregion + #region List public ActionResult Index() @@ -37,23 +70,27 @@ public ActionResult Index() public ActionResult List() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); - var forumGroupsModel = _forumService.GetAllForumGroups() + var forumGroupsModel = _forumService.GetAllForumGroups(true) .Select(fg => { var forumGroupModel = fg.ToModel(); - forumGroupModel.CreatedOn = _dateTimeHelper.ConvertToUserTime(fg.CreatedOnUtc, DateTimeKind.Utc); + + PrepareForumGroupModel(forumGroupModel, fg, false); + foreach (var f in fg.Forums.OrderBy(x=>x.DisplayOrder)) { var forumModel = f.ToModel(); forumModel.CreatedOn = _dateTimeHelper.ConvertToUserTime(f.CreatedOnUtc, DateTimeKind.Utc); + forumGroupModel.ForumModels.Add(forumModel); } return forumGroupModel; }) .ToList(); + return View(forumGroupsModel); } @@ -63,40 +100,52 @@ public ActionResult List() public ActionResult CreateForumGroup() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); - return View(new ForumGroupModel { DisplayOrder = 1 }); + var model = new ForumGroupModel { DisplayOrder = 1 }; + + PrepareForumGroupModel(model, null, false); + + return View(model); } [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult CreateForumGroup(ForumGroupModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); if (ModelState.IsValid) { - var forumGroup = model.ToEntity(); - forumGroup.CreatedOnUtc = DateTime.UtcNow; - forumGroup.UpdatedOnUtc = DateTime.UtcNow; + var utcNow = DateTime.UtcNow; + var forumGroup = model.ToEntity(); + forumGroup.CreatedOnUtc = utcNow; + forumGroup.UpdatedOnUtc = utcNow; + _forumService.InsertForumGroup(forumGroup); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.ForumGroup.Added")); + _storeMappingService.SaveStoreMappings(forumGroup, model.SelectedStoreIds); + + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Added")); + return continueEditing ? RedirectToAction("EditForumGroup", new { forumGroup.Id }) : RedirectToAction("List"); } //If we got this far, something failed, redisplay form + + PrepareForumGroupModel(model, null, true); + return View(model); } public ActionResult CreateForum() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var model = new ForumModel(); - foreach (var forumGroup in _forumService.GetAllForumGroups()) + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); model.ForumGroups.Add(forumGroupModel); @@ -108,7 +157,7 @@ public ActionResult CreateForum() [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult CreateForum(ForumModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); if (ModelState.IsValid) @@ -118,12 +167,12 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing) forum.UpdatedOnUtc = DateTime.UtcNow; _forumService.InsertForum(forum); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.Forum.Added")); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Added")); return continueEditing ? RedirectToAction("EditForum", new { forum.Id }) : RedirectToAction("List"); } //If we got this far, something failed, redisplay form - foreach (var forumGroup in _forumService.GetAllForumGroups()) + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); model.ForumGroups.Add(forumGroupModel); @@ -137,55 +186,62 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing) public ActionResult EditForumGroup(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forumGroup = _forumService.GetForumGroupById(id); if (forumGroup == null) - //No forum group found with the specified id return RedirectToAction("List"); var model = forumGroup.ToModel(); + + PrepareForumGroupModel(model, forumGroup, false); + return View(model); } [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult EditForumGroup(ForumGroupModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forumGroup = _forumService.GetForumGroupById(model.Id); if (forumGroup == null) - //No forum group found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) { forumGroup = model.ToEntity(forumGroup); forumGroup.UpdatedOnUtc = DateTime.UtcNow; + _forumService.UpdateForumGroup(forumGroup); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.ForumGroup.Updated")); + _storeMappingService.SaveStoreMappings(forumGroup, model.SelectedStoreIds); + + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Updated")); + return continueEditing ? RedirectToAction("EditForumGroup", forumGroup.Id) : RedirectToAction("List"); } //If we got this far, something failed, redisplay form + + PrepareForumGroupModel(model, forumGroup, true); + return View(model); } public ActionResult EditForum(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forum = _forumService.GetForumById(id); if (forum == null) - //No forum found with the specified id return RedirectToAction("List"); var model = forum.ToModel(); - foreach (var forumGroup in _forumService.GetAllForumGroups()) + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); model.ForumGroups.Add(forumGroupModel); @@ -196,12 +252,11 @@ public ActionResult EditForum(int id) [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult EditForum(ForumModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forum = _forumService.GetForumById(model.Id); if (forum == null) - //No forum found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) @@ -210,12 +265,12 @@ public ActionResult EditForum(ForumModel model, bool continueEditing) forum.UpdatedOnUtc = DateTime.UtcNow; _forumService.UpdateForum(forum); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.Forum.Updated")); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Updated")); return continueEditing ? RedirectToAction("EditForum", forum.Id) : RedirectToAction("List"); } //If we got this far, something failed, redisplay form - foreach (var forumGroup in _forumService.GetAllForumGroups()) + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); model.ForumGroups.Add(forumGroupModel); @@ -230,34 +285,32 @@ public ActionResult EditForum(ForumModel model, bool continueEditing) [HttpPost] public ActionResult DeleteForumGroup(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forumGroup = _forumService.GetForumGroupById(id); if (forumGroup == null) - //No forum group found with the specified id return RedirectToAction("List"); _forumService.DeleteForumGroup(forumGroup); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.ForumGroup.Deleted")); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Deleted")); return RedirectToAction("List"); } [HttpPost] public ActionResult DeleteForum(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forum = _forumService.GetForumById(id); if (forum == null) - //No forum found with the specified id return RedirectToAction("List"); _forumService.DeleteForum(forum); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.Forum.Deleted")); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Deleted")); return RedirectToAction("List"); } diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index f65a1d470d..283c785f4f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -412,6 +412,8 @@ public void Execute() //forums Mapper.CreateMap() .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) + .ForMember(dest => dest.AvailableStores, mo => mo.Ignore()) + .ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore()) .ForMember(dest => dest.ForumModels, mo => mo.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.CreatedOnUtc, mo => mo.Ignore()) diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs index 825a2dc718..fc6a25d15f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Web.Mvc; using FluentValidation.Attributes; +using SmartStore.Admin.Models.Stores; using SmartStore.Admin.Validators.Forums; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Mvc; @@ -29,6 +30,13 @@ public ForumGroupModel() [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.CreatedOn")] public DateTime CreatedOn { get; set; } + + [SmartResourceDisplayName("Admin.Common.Store.LimitedTo")] + public bool LimitedToStores { get; set; } + + [SmartResourceDisplayName("Admin.Common.Store.AvailableFor")] + public List AvailableStores { get; set; } + public int[] SelectedStoreIds { get; set; } //use ForumModel public IList ForumModels { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Forum/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Forum/List.cshtml index 7609a604b3..56682a81bb 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Forum/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Forum/List.cshtml @@ -1,7 +1,6 @@ @model IEnumerable @using Telerik.Web.Mvc.UI; @{ - //page title ViewBag.Title = T("Admin.ContentManagement.Forums.Manage").Text; }
@@ -26,8 +25,17 @@ .Template(x => Html.ActionLink(x.Name, "EditForumGroup", new { id = x.Id })) .ClientTemplate("\"><#= Name #>"); - columns.Bound(x => x.DisplayOrder).Width(150).Centered(); - columns.Bound(x => x.CreatedOn).Width(200); + columns.Bound(x => x.DisplayOrder) + .Width(150) + .Centered(); + columns.Bound(x => x.LimitedToStores) + .Template(item => @Html.SymbolForBool(item.LimitedToStores)) + .ClientTemplate(@Html.SymbolForBool("LimitedToStores")) + .Centered() + .Width(100) + .Hidden(ViewBag.StoreCount <= 1); + columns.Bound(x => x.CreatedOn) + .Width(200); columns.Bound(x => x.Id) .Width(50) .Centered() diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml index 376faad25c..e6d13d8f57 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml @@ -4,32 +4,89 @@ @Html.ValidationSummary(true) @Html.HiddenFor(model => model.Id) - - - - - - - - - - - - - -
- @Html.SmartLabelFor(model => model.Name) - - @Html.EditorFor(model => model.Name) - @Html.ValidationMessageFor(model => model.Name) -
- @Html.SmartLabelFor(model => model.Description) - - @Html.TextAreaFor(model => model.Description) - @Html.ValidationMessageFor(model => model.Description) -
- @Html.SmartLabelFor(model => model.DisplayOrder) - - @Html.EditorFor(model => model.DisplayOrder) - @Html.ValidationMessageFor(model => model.DisplayOrder) -
+ +@Html.SmartStore().TabStrip().Name("forumgroup-edit").Items(x => +{ + x.Add().Text(T("Admin.Common.General").Text).Content(TabInfo()).Selected(true); + x.Add().Text(T("Admin.Common.Stores").Text).Content(TabStores()); + + //generate an event + EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "forumgroup-edit", this.Html, this.Model)); +}) + +@helper TabInfo() +{ + + + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Name) + + @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ @Html.SmartLabelFor(model => model.Description) + + @Html.TextAreaFor(model => model.Description) + @Html.ValidationMessageFor(model => model.Description) +
+ @Html.SmartLabelFor(model => model.DisplayOrder) + + @Html.EditorFor(model => model.DisplayOrder) + @Html.ValidationMessageFor(model => model.DisplayOrder) +
+} + +@helper TabStores() +{ + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.LimitedToStores) + + @Html.EditorFor(model => model.LimitedToStores) + @Html.ValidationMessageFor(model => model.LimitedToStores) +
+ @Html.SmartLabelFor(model => model.AvailableStores) + + @if (Model.AvailableStores != null && Model.AvailableStores.Count > 0) + { + foreach (var store in Model.AvailableStores) + { + + } + } + else + { +
@T("Admin.Configuration.Stores.NoStoresDefined")
+ } +
+} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs index 25390a8c2b..0a3643f1e7 100644 --- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs @@ -4,7 +4,6 @@ using System.ServiceModel.Syndication; using System.Web.Mvc; using SmartStore.Core; -using SmartStore.Core.Domain; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Forums; using SmartStore.Core.Domain.Media; @@ -77,7 +76,7 @@ public BoardsController(IForumService forumService, [NonAction] protected ForumTopicRowModel PrepareForumTopicRowModel(ForumTopic topic) { - var topicModel = new ForumTopicRowModel() + var topicModel = new ForumTopicRowModel { Id = topic.Id, Subject = topic.Subject, @@ -102,7 +101,7 @@ protected ForumTopicRowModel PrepareForumTopicRowModel(ForumTopic topic) [NonAction] protected ForumRowModel PrepareForumRowModel(Forum forum) { - var forumModel = new ForumRowModel() + var forumModel = new ForumRowModel { Id = forum.Id, Name = forum.Name, @@ -118,14 +117,16 @@ protected ForumRowModel PrepareForumRowModel(Forum forum) [NonAction] protected ForumGroupModel PrepareForumGroupModel(ForumGroup forumGroup) { - var forumGroupModel = new ForumGroupModel() + var forumGroupModel = new ForumGroupModel { Id = forumGroup.Id, Name = forumGroup.Name, SeName = forumGroup.GetSeName(), Description = forumGroup.Description, }; + var forums = _forumService.GetAllForumsByGroupId(forumGroup.Id); + foreach (var forum in forums) { var forumModel = PrepareForumRowModel(forum); @@ -195,10 +196,11 @@ public ActionResult Index() var forumGroups = _forumService.GetAllForumGroups(); - var model = new BoardsIndexModel() + var model = new BoardsIndexModel { CurrentTime = _dateTimeHelper.ConvertToUserTime(DateTime.UtcNow) }; + foreach (var forumGroup in forumGroups) { @@ -222,11 +224,13 @@ public ActionResult ActiveDiscussionsSmall() return Content(""); var model = new ActiveDiscussionsModel(); - foreach (var topic in topics) + + foreach (var topic in topics) { var topicModel = PrepareForumTopicRowModel(topic); model.ForumTopics.Add(topicModel); } + model.ViewAllLinkEnabled = true; model.ActiveDiscussionsFeedEnabled = _forumSettings.ActiveDiscussionsFeedEnabled; model.PostsPageSize = _forumSettings.PostsPageSize; @@ -245,14 +249,17 @@ public ActionResult ActiveDiscussions(int forumId = 0) var topics = _forumService.GetActiveTopics(forumId, topicLimit); var model = new ActiveDiscussionsModel(); + foreach (var topic in topics) { var topicModel = PrepareForumTopicRowModel(topic); model.ForumTopics.Add(topicModel); } + model.ViewAllLinkEnabled = false; model.ActiveDiscussionsFeedEnabled = _forumSettings.ActiveDiscussionsFeedEnabled; model.PostsPageSize = _forumSettings.PostsPageSize; + return View(model); } @@ -276,11 +283,11 @@ public ActionResult ActiveDiscussionsRss(int forumId = 0) var feedDescription = _localizationService.GetResource("Forum.ActiveDiscussionsFeedDescription"); var feed = new SyndicationFeed( - string.Format(feedTitle, _storeContext.CurrentStore.Name), - feedDescription, - new Uri(url), - "ActiveDiscussionsRSS", - DateTime.UtcNow); + string.Format(feedTitle, _storeContext.CurrentStore.Name), + feedDescription, + new Uri(url), + "ActiveDiscussionsRSS", + DateTime.UtcNow); var items = new List(); @@ -351,16 +358,18 @@ public ActionResult Forum(int id, int page = 1) } } - var topics = _forumService.GetAllTopics(forum.Id, 0, string.Empty, - ForumSearchType.All, 0, (page - 1), pageSize); + var topics = _forumService.GetAllTopics(forum.Id, 0, string.Empty, ForumSearchType.All, 0, (page - 1), pageSize); + model.TopicPageSize = topics.PageSize; model.TopicTotalRecords = topics.TotalCount; model.TopicPageIndex = topics.PageIndex; + foreach (var topic in topics) { var topicModel = PrepareForumTopicRowModel(topic); model.ForumTopics.Add(topicModel); } + model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer); model.ForumFeedsEnabled = _forumSettings.ForumFeedsEnabled; model.PostsPageSize = _forumSettings.PostsPageSize; @@ -388,8 +397,7 @@ public ActionResult ForumRss(int id) if (forum != null) { //Order by newest topic posts & limit the number of topics to return - var topics = _forumService.GetAllTopics(forum.Id, 0, string.Empty, - ForumSearchType.All, 0, 0, topicLimit); + var topics = _forumService.GetAllTopics(forum.Id, 0, string.Empty, ForumSearchType.All, 0, 0, topicLimit); string url = Url.Action("ForumRSS", null, new { id = forum.Id }, "http"); @@ -397,11 +405,11 @@ public ActionResult ForumRss(int id) var feedDescription = _localizationService.GetResource("Forum.ForumFeedDescription"); var feed = new SyndicationFeed( - string.Format(feedTitle, _storeContext.CurrentStore.Name, forum.Name), - feedDescription, - new Uri(url), - string.Format("ForumRSS:{0}", forum.Id), - DateTime.UtcNow); + string.Format(feedTitle, _storeContext.CurrentStore.Name, forum.Name), + feedDescription, + new Uri(url), + string.Format("ForumRSS:{0}", forum.Id), + DateTime.UtcNow); var items = new List(); @@ -444,18 +452,18 @@ public ActionResult ForumWatch(int id) return Json(new { Subscribed = subscribed, Text = returnText, Error = true }); } - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - forum.Id, 0, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, forum.Id, 0, 0, 1).FirstOrDefault(); if (forumSubscription == null) { - forumSubscription = new ForumSubscription() + forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, ForumId = forum.Id, CreatedOnUtc = DateTime.UtcNow }; + _forumService.InsertSubscription(forumSubscription); subscribed = true; returnText = unwatchTopic; @@ -481,8 +489,8 @@ public ActionResult Topic(int id, int page = 1) if (forumTopic != null) { //load posts - var posts = _forumService.GetAllPosts(forumTopic.Id, 0, string.Empty, - page - 1, _forumSettings.PostsPageSize); + var posts = _forumService.GetAllPosts(forumTopic.Id, 0, string.Empty, page - 1, _forumSettings.PostsPageSize); + // if no posts area loaded, redirect to the first page if (posts.Count == 0 && page > 1) { @@ -508,19 +516,20 @@ public ActionResult Topic(int id, int page = 1) { model.WatchTopicText = _localizationService.GetResource("Forum.WatchTopic"); - var forumTopicSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumTopic.Id, 0, 1).FirstOrDefault(); + var forumTopicSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault(); if (forumTopicSubscription != null) { model.WatchTopicText = _localizationService.GetResource("Forum.UnwatchTopic"); } } - model.PostsPageIndex = posts.PageIndex; + + model.PostsPageIndex = posts.PageIndex; model.PostsPageSize = posts.PageSize; model.PostsTotalRecords = posts.TotalCount; + foreach (var post in posts) { - var forumPostModel = new ForumPostModel() + var forumPostModel = new ForumPostModel { Id = post.Id, ForumTopicId = post.TopicId, @@ -541,12 +550,14 @@ public ActionResult Topic(int id, int page = 1) SignaturesEnabled = _forumSettings.SignaturesEnabled, FormattedSignature = post.Customer.GetAttribute(SystemCustomerAttributeNames.Signature).FormatForumSignatureText(), }; + //created on string if (_forumSettings.RelativeDateTimeFormattingEnabled) forumPostModel.PostCreatedOnStr = post.CreatedOnUtc.RelativeFormat(true, "f"); else forumPostModel.PostCreatedOnStr =_dateTimeHelper.ConvertToUserTime(post.CreatedOnUtc, DateTimeKind.Utc).ToString("f"); - //avatar + + //avatar if (_customerSettings.AllowCustomersToUploadAvatars) { var customer = post.Customer; @@ -555,6 +566,7 @@ public ActionResult Topic(int id, int page = 1) avatarUrl = _pictureService.GetDefaultPictureUrl(_mediaSettings.AvatarPictureSize, PictureType.Avatar); forumPostModel.CustomerAvatarUrl = avatarUrl; } + //location forumPostModel.ShowCustomersLocation = _customerSettings.ShowCustomersLocation; if (_customerSettings.ShowCustomersLocation) @@ -594,18 +606,18 @@ public ActionResult TopicWatch(int id) return Json(new { Subscribed = subscribed, Text = returnText, Error = true }); } - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumTopic.Id, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault(); if (forumSubscription == null) { - forumSubscription = new ForumSubscription() + forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, TopicId = forumTopic.Id, CreatedOnUtc = DateTime.UtcNow }; + _forumService.InsertSubscription(forumSubscription); subscribed = true; returnText = unwatchTopic; @@ -638,6 +650,7 @@ public ActionResult TopicMove(int id) model.Id = forumTopic.Id; model.TopicSeName = forumTopic.GetSeName(); model.ForumSelected = forumTopic.ForumId; + return View(model); } @@ -681,6 +694,7 @@ public ActionResult TopicDelete(int id) { return new HttpUnauthorizedResult(); } + var forum = _forumService.GetForumById(forumTopic.ForumId); _forumService.DeleteTopic(forumTopic); @@ -724,6 +738,7 @@ public ActionResult TopicCreate(int id) model.TopicPriorities = ForumTopicTypesList(); model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer); model.Subscribed = false; + return View(model); } @@ -767,18 +782,16 @@ public ActionResult TopicCreate(EditForumTopicModel model) } var topicType = ForumTopicType.Normal; - + var nowUtc = DateTime.UtcNow; string ipAddress = _webHelper.GetCurrentIpAddress(); - var nowUtc = DateTime.UtcNow; - if (_forumService.IsCustomerAllowedToSetTopicPriority(_workContext.CurrentCustomer)) { topicType = (ForumTopicType) Enum.ToObject(typeof (ForumTopicType), model.TopicTypeId); } //forum topic - var forumTopic = new ForumTopic() + var forumTopic = new ForumTopic { ForumId = forum.Id, CustomerId = _workContext.CurrentCustomer.Id, @@ -787,10 +800,11 @@ public ActionResult TopicCreate(EditForumTopicModel model) CreatedOnUtc = nowUtc, UpdatedOnUtc = nowUtc }; + _forumService.InsertTopic(forumTopic, true); //forum post - var forumPost = new ForumPost() + var forumPost = new ForumPost { TopicId = forumTopic.Id, CustomerId = _workContext.CurrentCustomer.Id, @@ -799,6 +813,7 @@ public ActionResult TopicCreate(EditForumTopicModel model) CreatedOnUtc = nowUtc, UpdatedOnUtc = nowUtc }; + _forumService.InsertPost(forumPost, false); //update forum topic @@ -807,6 +822,7 @@ public ActionResult TopicCreate(EditForumTopicModel model) forumTopic.LastPostCustomerId = forumPost.CustomerId; forumTopic.LastPostTime = forumPost.CreatedOnUtc; forumTopic.UpdatedOnUtc = nowUtc; + _forumService.UpdateTopic(forumTopic); //subscription @@ -814,7 +830,7 @@ public ActionResult TopicCreate(EditForumTopicModel model) { if (model.Subscribed) { - var forumSubscription = new ForumSubscription() + var forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, @@ -873,12 +889,13 @@ public ActionResult TopicEdit(int id) return RedirectToRoute("Boards"); } + var firstPost = forumTopic.GetFirstPost(_forumService); var model = new EditForumTopicModel(); + model.IsEdit = true; model.TopicPriorities = ForumTopicTypesList(); model.ForumName = forum.Name; model.ForumSeName = forum.GetSeName(); - var firstPost = forumTopic.GetFirstPost(_forumService); model.Text = firstPost.Text; model.Subject = forumTopic.Subject; model.TopicTypeId = forumTopic.TopicTypeId; @@ -892,8 +909,7 @@ public ActionResult TopicEdit(int id) //subscription if (model.IsCustomerAllowedToSubscribe) { - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumTopic.Id, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault(); model.Subscribed = forumSubscription != null; } @@ -959,6 +975,7 @@ public ActionResult TopicEdit(EditForumTopicModel model) forumTopic.TopicTypeId = (int) topicType; forumTopic.Subject = subject; forumTopic.UpdatedOnUtc = nowUtc; + _forumService.UpdateTopic(forumTopic); //forum post @@ -987,14 +1004,13 @@ public ActionResult TopicEdit(EditForumTopicModel model) //subscription if (_forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer)) { - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumTopic.Id, 0, 1).FirstOrDefault - (); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault(); + if (model.Subscribed) { if (forumSubscription == null) { - forumSubscription = new ForumSubscription() + forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, @@ -1100,7 +1116,7 @@ public ActionResult PostCreate(int id, int? quote) return RedirectToRoute("Boards"); } - var model = new EditForumPostModel() + var model = new EditForumPostModel { Id = 0, ForumTopicId = forumTopic.Id, @@ -1172,11 +1188,10 @@ public ActionResult PostCreate(EditForumPostModel model) if (maxPostLength > 0 && text.Length > maxPostLength) text = text.Substring(0, maxPostLength); + var nowUtc = DateTime.UtcNow; string ipAddress = _webHelper.GetCurrentIpAddress(); - DateTime nowUtc = DateTime.UtcNow; - - var forumPost = new ForumPost() + var forumPost = new ForumPost { TopicId = forumTopic.Id, CustomerId = _workContext.CurrentCustomer.Id, @@ -1185,18 +1200,18 @@ public ActionResult PostCreate(EditForumPostModel model) CreatedOnUtc = nowUtc, UpdatedOnUtc = nowUtc }; + _forumService.InsertPost(forumPost, true); //subscription if (_forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer)) { - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumPost.TopicId, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumPost.TopicId, 0, 1).FirstOrDefault(); if (model.Subscribed) { if (forumSubscription == null) { - forumSubscription = new ForumSubscription() + forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, @@ -1222,6 +1237,7 @@ public ActionResult PostCreate(EditForumPostModel model) int pageIndex = (_forumService.CalculateTopicPageIndex(forumPost.TopicId, pageSize, forumPost.Id) + 1); var url = string.Empty; + if (pageIndex > 1) { url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName(), page = pageIndex }); @@ -1230,6 +1246,7 @@ public ActionResult PostCreate(EditForumPostModel model) { url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName() }); } + return Redirect(string.Format("{0}#{1}", url, forumPost.Id)); } catch (Exception ex) @@ -1284,7 +1301,7 @@ public ActionResult PostEdit(int id) } - var model = new EditForumPostModel() + var model = new EditForumPostModel { Id = forumPost.Id, ForumTopicId = forumTopic.Id, @@ -1301,8 +1318,7 @@ public ActionResult PostEdit(int id) //subscription if (model.IsCustomerAllowedToSubscribe) { - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumTopic.Id, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault(); model.Subscribed = forumSubscription != null; } @@ -1345,7 +1361,7 @@ public ActionResult PostEdit(EditForumPostModel model) { try { - DateTime nowUtc = DateTime.UtcNow; + var nowUtc = DateTime.UtcNow; var text = model.Text; var maxPostLength = _forumSettings.PostMaxLength; @@ -1356,24 +1372,25 @@ public ActionResult PostEdit(EditForumPostModel model) forumPost.UpdatedOnUtc = nowUtc; forumPost.Text = text; + _forumService.UpdatePost(forumPost); //subscription if (_forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer)) { - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumPost.TopicId, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumPost.TopicId, 0, 1).FirstOrDefault(); if (model.Subscribed) { if (forumSubscription == null) { - forumSubscription = new ForumSubscription() + forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, TopicId = forumPost.TopicId, CreatedOnUtc = nowUtc }; + _forumService.InsertSubscription(forumSubscription); } } @@ -1393,6 +1410,7 @@ public ActionResult PostEdit(EditForumPostModel model) } int pageIndex = (_forumService.CalculateTopicPageIndex(forumPost.TopicId, pageSize, forumPost.Id) + 1); var url = string.Empty; + if (pageIndex > 1) { url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName(), page = pageIndex }); @@ -1401,6 +1419,7 @@ public ActionResult PostEdit(EditForumPostModel model) { url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName() }); } + return Redirect(string.Format("{0}#{1}", url, forumPost.Id)); } catch (Exception ex) @@ -1422,8 +1441,7 @@ public ActionResult PostEdit(EditForumPostModel model) return View(model); } - public ActionResult Search(string searchterms, bool? adv, string forumId, - string within, string limitDays, int page = 1) + public ActionResult Search(string searchterms, bool? adv, string forumId, string within, string limitDays, int page = 1) { if (!_forumSettings.ForumsEnabled) { @@ -1436,59 +1454,60 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, // Create the values for the "Limit results to previous" select list var limitList = new List - { - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.AllResults"), - Value = "0" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1day"), - Value = "1" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.7days"), - Value = "7" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.2weeks"), - Value = "14" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1month"), - Value = "30" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.3months"), - Value = "92" - }, - new SelectListItem - { - Text= _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.6months"), - Value = "183" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1year"), - Value = "365" - } - }; + { + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.AllResults"), + Value = "0" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1day"), + Value = "1" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.7days"), + Value = "7" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.2weeks"), + Value = "14" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1month"), + Value = "30" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.3months"), + Value = "92" + }, + new SelectListItem + { + Text= _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.6months"), + Value = "183" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1year"), + Value = "365" + } + }; + model.LimitList = limitList; // Create the values for the "Search in forum" select list var forumsSelectList = new List(); - forumsSelectList.Add( - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.SearchInForum.All"), - Value = "0", - Selected = true, - }); + forumsSelectList.Add(new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.SearchInForum.All"), + Value = "0", + Selected = true, + }); + var separator = "--"; var forumGroups = _forumService.GetAllForumGroups(); foreach (var fg in forumGroups) @@ -1499,35 +1518,35 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, var forums = _forumService.GetAllForumsByGroupId(fg.Id); foreach (var f in forums) { - forumsSelectList.Add( - new SelectListItem - { - Text = string.Format("{0}{1}", separator, f.Name), - Value = f.Id.ToString() - }); + forumsSelectList.Add(new SelectListItem + { + Text = string.Format("{0}{1}", separator, f.Name), + Value = f.Id.ToString() + }); } } model.ForumList = forumsSelectList; // Create the values for "Search within" select list var withinList = new List - { - new SelectListItem - { - Value = ((int)ForumSearchType.All).ToString(), - Text = _localizationService.GetResource("Forum.Search.SearchWithin.All") - }, - new SelectListItem - { - Value = ((int)ForumSearchType.TopicTitlesOnly).ToString(), - Text = _localizationService.GetResource("Forum.Search.SearchWithin.TopicTitlesOnly") - }, - new SelectListItem - { - Value = ((int)ForumSearchType.PostTextOnly).ToString(), - Text = _localizationService.GetResource("Forum.Search.SearchWithin.PostTextOnly") - } - }; + { + new SelectListItem + { + Value = ((int)ForumSearchType.All).ToString(), + Text = _localizationService.GetResource("Forum.Search.SearchWithin.All") + }, + new SelectListItem + { + Value = ((int)ForumSearchType.TopicTitlesOnly).ToString(), + Text = _localizationService.GetResource("Forum.Search.SearchWithin.TopicTitlesOnly") + }, + new SelectListItem + { + Value = ((int)ForumSearchType.PostTextOnly).ToString(), + Text = _localizationService.GetResource("Forum.Search.SearchWithin.PostTextOnly") + } + }; + model.WithinList = withinList; int forumIdSelected; @@ -1558,8 +1577,7 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, if (searchterms.Length < searchTermMinimumLength) { - throw new SmartException(string.Format(_localizationService.GetResource("Forum.SearchTermMinimumLengthIsNCharacters"), - searchTermMinimumLength)); + throw new SmartException(string.Format(_localizationService.GetResource("Forum.SearchTermMinimumLengthIsNCharacters"), searchTermMinimumLength)); } ForumSearchType searchWithin = 0; @@ -1575,11 +1593,12 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, pageSize = _forumSettings.SearchResultsPageSize; } - var topics = _forumService.GetAllTopics(forumIdSelected, 0, searchterms, searchWithin, - limitResultsToPrevious, page - 1, pageSize); + var topics = _forumService.GetAllTopics(forumIdSelected, 0, searchterms, searchWithin, limitResultsToPrevious, page - 1, pageSize); + model.TopicPageSize = topics.PageSize; model.TopicTotalRecords = topics.TotalCount; model.TopicPageIndex = topics.PageIndex; + foreach (var topic in topics) { var topicModel = PrepareForumTopicRowModel(topic); @@ -1673,5 +1692,4 @@ public ActionResult ForumBreadcrumb(int? forumGroupId, int? forumId, int? forumT #endregion } - } From 918d83302c36eb3931ad4531f9397b73528b846d Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 7 May 2015 16:00:52 +0200 Subject: [PATCH 0105/1256] Localized properties for forum groups --- changelog.md | 2 + .../Domain/Forums/ForumGroup.cs | 4 +- .../201505061813010_CountryMultistore.cs | 24 ++++++++- .../SmartStore.Services/Seo/SeoExtensions.cs | 16 ------ .../Controllers/ForumController.cs | 51 ++++++++++++++++-- .../Infrastructure/AutoMapperStartupTask.cs | 4 +- .../Models/Forums/ForumGroupModel.cs | 27 +++++++++- .../Forum/_CreateOrUpdateForumGroup.cshtml | 53 ++++++++++++++++++- .../Controllers/BoardsController.cs | 12 ++--- 9 files changed, 161 insertions(+), 32 deletions(-) diff --git a/changelog.md b/changelog.md index 704960aa82..287c5763cc 100644 --- a/changelog.md +++ b/changelog.md @@ -12,9 +12,11 @@ * Setting whether and how to display sub-categories on a category page (hide, above products, bottom of page) * Debitoor: Extend option "Book invoice if paid" to also (optionally) mail the invoice as a PDF * #508 Limit country settings to stores +* #205 Add multistore support for forums ### Improvements * PDF converter: first init is much faster now +* Localized properties for forum groups ### Bugfixes * PDF converter: fixed _QFont::setPixelSize_ bug diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs index 77022b7047..fc84ae983e 100644 --- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs +++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using SmartStore.Core.Domain.Localization; +using SmartStore.Core.Domain.Seo; using SmartStore.Core.Domain.Stores; namespace SmartStore.Core.Domain.Forums @@ -7,7 +9,7 @@ namespace SmartStore.Core.Domain.Forums /// /// Represents a forum group /// - public partial class ForumGroup : BaseEntity, IStoreMappingSupported + public partial class ForumGroup : BaseEntity, IStoreMappingSupported, ILocalizedEntity, ISlugSupported { private ICollection _forums; diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs index c701338fee..c067c886c9 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs @@ -2,8 +2,9 @@ namespace SmartStore.Data.Migrations { using System; using System.Data.Entity.Migrations; - - public partial class CountryMultistore : DbMigration + using SmartStore.Data.Setup; + + public partial class CountryMultistore : DbMigration, ILocaleResourcesProvider, IDataSeeder { public override void Up() { @@ -16,5 +17,24 @@ public override void Down() DropColumn("dbo.Forums_Group", "LimitedToStores"); DropColumn("dbo.Country", "LimitedToStores"); } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Admin.ContentManagement.Forums.ForumGroup.Fields.SeName", + "URL-Alias", + "URL-Alias", + "Set a search engine friendly page name e.g. 'the-best-forum' to make your page URL 'http://www.yourStore.com/the-best-forum'. Leave empty to generate it automatically based on the name of the forum group.", + "Legt einen Suchmaschinen-freundlichen Seitennamen fr die Forengruppe fest. 'Tolles Forum' resultiert bspw. in '~/tolles-forum'. Standard ist der Name der Forengruppe."); + } } } diff --git a/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs b/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs index ad1ccdb441..0c5e3e1699 100644 --- a/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs +++ b/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using SmartStore.Core; using SmartStore.Core.Domain.Blogs; using SmartStore.Core.Domain.Catalog; -using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Forums; using SmartStore.Core.Domain.News; using SmartStore.Core.Domain.Seo; @@ -79,19 +76,6 @@ public static string GetSeName(this NewsItem newsItem) #region Forum - /// - /// Gets ForumGroup SE (search engine) name - /// - /// ForumGroup - /// ForumGroup SE (search engine) name - public static string GetSeName(this ForumGroup forumGroup) - { - if (forumGroup == null) - throw new ArgumentNullException("forumGroup"); - string seName = GetSeName(forumGroup.Name); - return seName; - } - /// /// Gets Forum SE (search engine) name /// diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs index 1f59f64144..4b20161a69 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs @@ -6,7 +6,9 @@ using SmartStore.Services; using SmartStore.Services.Forums; using SmartStore.Services.Helpers; +using SmartStore.Services.Localization; using SmartStore.Services.Security; +using SmartStore.Services.Seo; using SmartStore.Services.Stores; using SmartStore.Web.Framework.Controllers; @@ -19,16 +21,25 @@ public class ForumController : AdminControllerBase private readonly ICommonServices _commonServices; private readonly IDateTimeHelper _dateTimeHelper; private readonly IStoreMappingService _storeMappingService; + private readonly ILanguageService _languageService; + private readonly ILocalizedEntityService _localizedEntityService; + private readonly IUrlRecordService _urlRecordService; public ForumController(IForumService forumService, ICommonServices commonServices, IDateTimeHelper dateTimeHelper, - IStoreMappingService storeMappingService) + IStoreMappingService storeMappingService, + ILanguageService languageService, + ILocalizedEntityService localizedEntityService, + IUrlRecordService urlRecordService) { _forumService = forumService; _commonServices = commonServices; _dateTimeHelper = dateTimeHelper; _storeMappingService = storeMappingService; + _languageService = languageService; + _localizedEntityService = localizedEntityService; + _urlRecordService = urlRecordService; } #region Utilities @@ -59,6 +70,19 @@ private void PrepareForumGroupModel(ForumGroupModel model, ForumGroup forumGroup ViewBag.StoreCount = allStores.Count; } + [NonAction] + private void UpdateLocales(ForumGroupModel model, ForumGroup forumGroup) + { + foreach (var localized in model.Locales) + { + _localizedEntityService.SaveLocalizedValue(forumGroup, x => x.Name, localized.Name, localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(forumGroup, x => x.Description, localized.Description, localized.LanguageId); + + var seName = forumGroup.ValidateSeName(localized.SeName, localized.Name, false, localized.LanguageId); + _urlRecordService.SaveSlug(forumGroup, seName, localized.LanguageId); + } + } + #endregion #region List @@ -105,6 +129,8 @@ public ActionResult CreateForumGroup() var model = new ForumGroupModel { DisplayOrder = 1 }; + AddLocales(_languageService, model.Locales); + PrepareForumGroupModel(model, null, false); return View(model); @@ -125,6 +151,11 @@ public ActionResult CreateForumGroup(ForumGroupModel model, bool continueEditing _forumService.InsertForumGroup(forumGroup); + model.SeName = forumGroup.ValidateSeName(model.SeName, forumGroup.Name, true); + _urlRecordService.SaveSlug(forumGroup, model.SeName, 0); + + UpdateLocales(model, forumGroup); + _storeMappingService.SaveStoreMappings(forumGroup, model.SelectedStoreIds); NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Added")); @@ -162,9 +193,11 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing) if (ModelState.IsValid) { + var utcNow = DateTime.UtcNow; var forum = model.ToEntity(); - forum.CreatedOnUtc = DateTime.UtcNow; - forum.UpdatedOnUtc = DateTime.UtcNow; + forum.CreatedOnUtc = utcNow; + forum.UpdatedOnUtc = utcNow; + _forumService.InsertForum(forum); NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Added")); @@ -195,6 +228,13 @@ public ActionResult EditForumGroup(int id) var model = forumGroup.ToModel(); + AddLocales(_languageService, model.Locales, (locale, languageId) => + { + locale.Name = forumGroup.GetLocalized(x => x.Name, languageId, false, false); + locale.Description = forumGroup.GetLocalized(x => x.Description, languageId, false, false); + locale.SeName = forumGroup.GetSeName(languageId, false, false); + }); + PrepareForumGroupModel(model, forumGroup, false); return View(model); @@ -217,6 +257,11 @@ public ActionResult EditForumGroup(ForumGroupModel model, bool continueEditing) _forumService.UpdateForumGroup(forumGroup); + model.SeName = forumGroup.ValidateSeName(model.SeName, forumGroup.Name, true); + _urlRecordService.SaveSlug(forumGroup, model.SeName, 0); + + UpdateLocales(model, forumGroup); + _storeMappingService.SaveStoreMappings(forumGroup, model.SelectedStoreIds); NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Updated")); diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index 283c785f4f..4ef685dcc3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -411,9 +411,11 @@ public void Execute() .ForMember(dest => dest.StoreId, mo => mo.Ignore()); //forums Mapper.CreateMap() - .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) + .ForMember(dest => dest.Locales, mo => mo.Ignore()) + .ForMember(dest => dest.SeName, mo => mo.MapFrom(src => src.GetSeName(0, true, false))) .ForMember(dest => dest.AvailableStores, mo => mo.Ignore()) .ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore()) + .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) .ForMember(dest => dest.ForumModels, mo => mo.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.CreatedOnUtc, mo => mo.Ignore()) diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs index fc6a25d15f..39a20675a4 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs @@ -5,22 +5,28 @@ using SmartStore.Admin.Models.Stores; using SmartStore.Admin.Validators.Forums; using SmartStore.Web.Framework; +using SmartStore.Web.Framework.Localization; using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Models.Forums { [Validator(typeof(ForumGroupValidator))] - public class ForumGroupModel : EntityModelBase + public class ForumGroupModel : EntityModelBase, ILocalizedModel { public ForumGroupModel() { ForumModels = new List(); + Locales = new List(); } [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.Name")] [AllowHtml] public string Name { get; set; } + [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.SeName")] + [AllowHtml] + public string SeName { get; set; } + [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.Description")] [AllowHtml] public string Description { get; set; } @@ -40,5 +46,24 @@ public ForumGroupModel() //use ForumModel public IList ForumModels { get; set; } + + public IList Locales { get; set; } } + + public class ForumGroupLocalizedModel : ILocalizedModelLocal + { + public int LanguageId { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.Name")] + [AllowHtml] + public string Name { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.SeName")] + [AllowHtml] + public string SeName { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.Description")] + [AllowHtml] + public string Description { get; set; } + } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml index e6d13d8f57..611d9cef72 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml @@ -16,7 +16,43 @@ @helper TabInfo() { - + @(Html.LocalizedEditor("forumgroup-localized", + @
+ + + + + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Locales[item].Name) + + @Html.EditorFor(model => Model.Locales[item].Name) + @Html.ValidationMessageFor(model => model.Locales[item].Name) +
+ @Html.SmartLabelFor(model => model.Locales[item].SeName) + + @Html.EditorFor(model => model.Locales[item].SeName) + @Html.ValidationMessageFor(model => model.Locales[item].SeName) +
+ @Html.SmartLabelFor(model => model.Locales[item].Description) + + @Html.TextAreaFor(model => model.Locales[item].Description, new { @class = "input-large" }) + @Html.ValidationMessageFor(model => model.Locales[item].Description) +
+ @Html.HiddenFor(model => model.Locales[item].LanguageId) +
+ , + @ + + + + +
@Html.SmartLabelFor(model => model.Name) @@ -26,15 +62,28 @@ @Html.ValidationMessageFor(model => model.Name)
+ @Html.SmartLabelFor(model => model.SeName) + + @Html.EditorFor(x => x.SeName) + @Html.ValidationMessageFor(model => model.SeName) +
@Html.SmartLabelFor(model => model.Description) - @Html.TextAreaFor(model => model.Description) + @Html.TextAreaFor(model => model.Description, new { @class = "input-large" }) @Html.ValidationMessageFor(model => model.Description)
+ )) + + @@ -132,7 +147,7 @@ "); } @@ -524,7 +522,6 @@ protected virtual string ProductListToHtmlTable(Shipment shipment, int languageI return result; } - //codehint: sm-add protected virtual string TopicToHtml(string systemName, int languageId) { var result = ""; @@ -676,8 +673,6 @@ public virtual void AddStoreTokens(IList tokens, Store store) tokens.Add(new Token("Store.Email", defaultEmailAccount.Email)); } - //codehint: sm-add begin - public virtual void AddCompanyTokens(IList tokens) { tokens.Add(new Token("Company.CompanyName", _companyInfoSettings.CompanyName)); @@ -720,8 +715,6 @@ public virtual void AddContactDataTokens(IList tokens) tokens.Add(new Token("Contact.ContactEmailAddress", _contactDataSettings.ContactEmailAddress)); } - //codehint: sm-add end - public virtual void AddOrderTokens(IList tokens, Order order, int languageId) { tokens.Add(new Token("Order.OrderNumber", order.GetOrderNumber())); @@ -1013,7 +1006,6 @@ public virtual string[] GetListOfCampaignAllowedTokens() "%NewsLetterSubscription.Email%", "%NewsLetterSubscription.ActivationUrl%", "%NewsLetterSubscription.DeactivationUrl%", - //codehint: sm-add "%Store.SupplierIdentification%", }; return allowedTokens.ToArray(); diff --git a/src/Presentation/SmartStore.Web.Framework/Mvc/Bundles/BundlePublisher.cs b/src/Presentation/SmartStore.Web.Framework/Mvc/Bundles/BundlePublisher.cs index f1e9fc271f..0fa0d70576 100644 --- a/src/Presentation/SmartStore.Web.Framework/Mvc/Bundles/BundlePublisher.cs +++ b/src/Presentation/SmartStore.Web.Framework/Mvc/Bundles/BundlePublisher.cs @@ -7,9 +7,6 @@ namespace SmartStore.Web.Framework.Mvc.Bundles { - /// - /// codehint: sm-add - /// public class BundlePublisher : IBundlePublisher { private readonly ITypeFinder _typeFinder; diff --git a/src/Presentation/SmartStore.Web.Framework/Mvc/Bundles/IBundlePublisher.cs b/src/Presentation/SmartStore.Web.Framework/Mvc/Bundles/IBundlePublisher.cs index e910605f06..171cd0c775 100644 --- a/src/Presentation/SmartStore.Web.Framework/Mvc/Bundles/IBundlePublisher.cs +++ b/src/Presentation/SmartStore.Web.Framework/Mvc/Bundles/IBundlePublisher.cs @@ -2,9 +2,6 @@ namespace SmartStore.Web.Framework.Mvc.Bundles { - /// - /// codehint: sm-add - /// public interface IBundlePublisher { void RegisterBundles(BundleCollection bundles); diff --git a/src/Presentation/SmartStore.Web.Framework/UI/DataListExtensions.cs b/src/Presentation/SmartStore.Web.Framework/UI/DataListExtensions.cs index 1e9b9843f0..ff5cfcdab2 100644 --- a/src/Presentation/SmartStore.Web.Framework/UI/DataListExtensions.cs +++ b/src/Presentation/SmartStore.Web.Framework/UI/DataListExtensions.cs @@ -9,8 +9,6 @@ namespace SmartStore.Web.Framework.UI { public static class DataListExtensions { - - // codehint: sm-edit public static IHtmlString DataList(this HtmlHelper helper, IEnumerable items, int columns, Func template, int gridColumns = 24) where T : class diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs index 53b839fbdd..a2b92fa3d4 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs @@ -718,17 +718,17 @@ public ActionResult Edit(CategoryModel model, bool continueEditing, FormCollecti } [ValidateInput(false)] - public ActionResult AssignAclToSubCategoriesAndProducts(int categoryId) + public ActionResult InheritAclIntoChildren(int categoryId) { - _categoryService.AssignAclToSubCategoriesAndProducts(categoryId, false, true, false ); + _categoryService.InheritAclIntoChildren(categoryId, false, true, false); return RedirectToAction("Edit", "Category", new { id = categoryId }); } [ValidateInput(false)] - public ActionResult AssignStoresToSubCategoriesAndProducts(int categoryId) + public ActionResult InheritStoresIntoChildren(int categoryId) { - _categoryService.AssignStoresToSubCategoriesAndProducts(categoryId, false, true, false); + _categoryService.InheritStoresIntoChildren(categoryId, false, true, false); return RedirectToAction("Edit", "Category", new { id = categoryId }); } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs index 9af684b301..32099acfcd 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs @@ -408,7 +408,6 @@ public ActionResult GetStatesByCountryId(string countryId, bool? addEmptyStateIf // This action method gets called via an ajax request - // codehint: sm-edit int cid = 0; int.TryParse(countryId, out cid); /*if (String.IsNullOrEmpty(countryId)) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerRoleController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerRoleController.cs index 270d77a83f..6cd925c770 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerRoleController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerRoleController.cs @@ -38,7 +38,6 @@ public CustomerRoleController(ICustomerService customerService, this._localizationService = localizationService; this._customerActivityService = customerActivityService; this._permissionService = permissionService; - //codehint: sm-add this._taxSettings = taxSettings; } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductModel.cs index 309911d728..110cfa4025 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductModel.cs @@ -392,8 +392,7 @@ public AddProductSpecificationAttributeModel() { AvailableAttributes = new List(); AvailableOptions = new List(); - - AllowFiltering = true; // codehint: sm-add + AllowFiltering = true; } [SmartResourceDisplayName("Admin.Catalog.Products.SpecificationAttributes.Fields.SpecificationAttribute")] diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Common/MaintenanceModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Common/MaintenanceModel.cs index 17653a87bf..49e85dd97a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Common/MaintenanceModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Common/MaintenanceModel.cs @@ -16,11 +16,8 @@ public MaintenanceModel() public DeleteGuestsModel DeleteGuests { get; set; } public DeleteExportedFilesModel DeleteExportedFiles { get; set; } - - // codehint: sm-add public DeleteImageCacheModel DeleteImageCache { get; set; } - // codehint: sm-add [SmartResourceDisplayName("Admin.System.Maintenance.SqlQuery")] public string SqlQuery { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Settings/MediaSettingsModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Settings/MediaSettingsModel.cs index da09a31233..a6d546997e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Settings/MediaSettingsModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Settings/MediaSettingsModel.cs @@ -51,11 +51,10 @@ public MediaSettingsModel() [SmartResourceDisplayName("Admin.Configuration.Settings.Media.MaximumImageSize")] public int MaximumImageSize { get; set; } - // codehint: sm-add [SmartResourceDisplayName("Admin.Configuration.Settings.Media.DefaultPictureZoomEnabled")] public bool DefaultPictureZoomEnabled { get; set; } - // codehint: sm-add (window || inner || lens) + // (window || inner || lens) [SmartResourceDisplayName("Admin.Configuration.Settings.Media.PictureZoomType")] public string PictureZoomType { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml index 5c41d2f6ee..9688af7525 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml @@ -485,7 +485,7 @@
@T("Admin.Configuration.Category.Acl.AssignToSubCategoriesAndProducts.Hint")
- +   @T("Admin.Configuration.Category.Acl.AssignToSubCategoriesAndProducts") @@ -556,7 +556,7 @@
@T("Admin.Configuration.Category.Stores.AssignToSubCategoriesAndProducts.Hint")
- +   @T("Admin.Configuration.Category.Stores.AssignToSubCategoriesAndProducts") diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Language/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Language/_CreateOrUpdate.cshtml index 4c01f7f071..621e963481 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Language/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Language/_CreateOrUpdate.cshtml @@ -44,7 +44,6 @@ @Html.SmartLabelFor(model => model.LanguageCulture)
+ +
@Html.SmartLabelFor(model => model.DisplayOrder) diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs index 0a3643f1e7..22368df310 100644 --- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs @@ -120,9 +120,9 @@ protected ForumGroupModel PrepareForumGroupModel(ForumGroup forumGroup) var forumGroupModel = new ForumGroupModel { Id = forumGroup.Id, - Name = forumGroup.Name, - SeName = forumGroup.GetSeName(), - Description = forumGroup.Description, + Name = forumGroup.GetLocalized(x => x.Name), + Description = forumGroup.GetLocalized(x => x.Description), + SeName = forumGroup.GetSeName() }; var forums = _forumService.GetAllForumsByGroupId(forumGroup.Id); @@ -171,7 +171,7 @@ protected IEnumerable ForumGroupsForumsList() foreach (var fg in forumGroups) { // Add the forum group with Value of 0 so it won't be used as a target forum - forumsList.Add(new SelectListItem { Text = fg.Name, Value = "0" }); + forumsList.Add(new SelectListItem { Text = fg.GetLocalized(x => x.Name), Value = "0" }); var forums = _forumService.GetAllForumsByGroupId(fg.Id); foreach (var f in forums) @@ -1513,7 +1513,7 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, string foreach (var fg in forumGroups) { // Add the forum group with value as '-' so it can't be used as a target forum id - forumsSelectList.Add(new SelectListItem { Text = fg.Name, Value = "-" }); + forumsSelectList.Add(new SelectListItem { Text = fg.GetLocalized(x => x.Name), Value = "-" }); var forums = _forumService.GetAllForumsByGroupId(fg.Id); foreach (var f in forums) @@ -1683,7 +1683,7 @@ public ActionResult ForumBreadcrumb(int? forumGroupId, int? forumId, int? forumT if (forumGroup != null) { model.ForumGroupId = forumGroup.Id; - model.ForumGroupName = forumGroup.Name; + model.ForumGroupName = forumGroup.GetLocalized(x => x.Name); model.ForumGroupSeName = forumGroup.GetSeName(); } From 7d206e8330609424794d8927a2767d5b43c1750c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 7 May 2015 18:09:52 +0200 Subject: [PATCH 0106/1256] Localized properties for forums --- changelog.md | 2 +- .../SmartStore.Core/Domain/Forums/Forum.cs | 4 +- .../201505061813010_CountryMultistore.cs | 10 +- .../Messages/MessageTokenProvider.cs | 2 +- .../SmartStore.Services/Seo/SeoExtensions.cs | 13 -- .../Controllers/ForumController.cs | 39 +++++- .../Infrastructure/AutoMapperStartupTask.cs | 2 + .../Models/Forums/ForumModel.cs | 27 +++- .../Views/Forum/_CreateOrUpdateForum.cshtml | 123 ++++++++++++------ .../Controllers/BoardsController.cs | 32 ++--- .../Controllers/CustomerController.cs | 4 +- 11 files changed, 182 insertions(+), 76 deletions(-) diff --git a/changelog.md b/changelog.md index 287c5763cc..22107a4bd1 100644 --- a/changelog.md +++ b/changelog.md @@ -16,7 +16,7 @@ ### Improvements * PDF converter: first init is much faster now -* Localized properties for forum groups +* Localized properties for forums and forum groups ### Bugfixes * PDF converter: fixed _QFont::setPixelSize_ bug diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs b/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs index 4823f78825..1af950f759 100644 --- a/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs +++ b/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs @@ -1,11 +1,13 @@ using System; +using SmartStore.Core.Domain.Localization; +using SmartStore.Core.Domain.Seo; namespace SmartStore.Core.Domain.Forums { /// /// Represents a forum /// - public partial class Forum : BaseEntity + public partial class Forum : BaseEntity, ILocalizedEntity, ISlugSupported { /// /// Gets or sets the forum group identifier diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs index c067c886c9..9ba99664ba 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs @@ -33,8 +33,14 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Admin.ContentManagement.Forums.ForumGroup.Fields.SeName", "URL-Alias", "URL-Alias", - "Set a search engine friendly page name e.g. 'the-best-forum' to make your page URL 'http://www.yourStore.com/the-best-forum'. Leave empty to generate it automatically based on the name of the forum group.", - "Legt einen Suchmaschinen-freundlichen Seitennamen fr die Forengruppe fest. 'Tolles Forum' resultiert bspw. in '~/tolles-forum'. Standard ist der Name der Forengruppe."); + "Set a search engine friendly page name e.g. 'the-best-forumgroup' to make your page URL 'http://www.yourStore.com/the-best-forumgroup'. Leave empty to generate it automatically based on the name of the forum group.", + "Legt einen Suchmaschinen-freundlichen Seitennamen fr die Forengruppe fest. 'Tolle Forengruppe' resultiert bspw. in '~/tolle-forengruppe'. Standard ist der Name der Forengruppe."); + + builder.AddOrUpdate("Admin.ContentManagement.Forums.Forum.Fields.SeName", + "URL-Alias", + "URL-Alias", + "Set a search engine friendly page name e.g. 'the-best-forum' to make your page URL 'http://www.yourStore.com/the-best-forum'. Leave empty to generate it automatically based on the name of the forum.", + "Legt einen Suchmaschinen-freundlichen Seitennamen fr das Forum fest. 'Tolles Forum' resultiert bspw. in '~/tolles-forum'. Standard ist der Name des Forums."); } } } diff --git a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs index 5b11022c3d..6f9a455c53 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs @@ -976,7 +976,7 @@ public virtual void AddForumTokens(IList tokens, Forum forum) //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) var forumUrl = string.Format("{0}boards/forum/{1}/{2}", _webHelper.GetStoreLocation(false), forum.Id, forum.GetSeName()); tokens.Add(new Token("Forums.ForumURL", forumUrl, true)); - tokens.Add(new Token("Forums.ForumName", forum.Name)); + tokens.Add(new Token("Forums.ForumName", forum.GetLocalized(x => x.Name))); //event notification _eventPublisher.EntityTokensAdded(forum, tokens); diff --git a/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs b/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs index 0c5e3e1699..8bbb6e60fe 100644 --- a/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs +++ b/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs @@ -76,19 +76,6 @@ public static string GetSeName(this NewsItem newsItem) #region Forum - /// - /// Gets Forum SE (search engine) name - /// - /// Forum - /// Forum SE (search engine) name - public static string GetSeName(this Forum forum) - { - if (forum == null) - throw new ArgumentNullException("forum"); - string seName = GetSeName(forum.Name); - return seName; - } - /// /// Gets ForumTopic SE (search engine) name /// diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs index 4b20161a69..988c4164de 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs @@ -83,6 +83,19 @@ private void UpdateLocales(ForumGroupModel model, ForumGroup forumGroup) } } + [NonAction] + private void UpdateLocales(ForumModel model, Forum forum) + { + foreach (var localized in model.Locales) + { + _localizedEntityService.SaveLocalizedValue(forum, x => x.Name, localized.Name, localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(forum, x => x.Description, localized.Description, localized.LanguageId); + + var seName = forum.ValidateSeName(localized.SeName, localized.Name, false, localized.LanguageId); + _urlRecordService.SaveSlug(forum, seName, localized.LanguageId); + } + } + #endregion #region List @@ -175,13 +188,16 @@ public ActionResult CreateForum() if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); - var model = new ForumModel(); + var model = new ForumModel { DisplayOrder = 1 }; + + AddLocales(_languageService, model.Locales); + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); model.ForumGroups.Add(forumGroupModel); } - model.DisplayOrder = 1; + return View(model); } @@ -200,7 +216,11 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing) _forumService.InsertForum(forum); + model.SeName = forum.ValidateSeName(model.SeName, forum.Name, true); + _urlRecordService.SaveSlug(forum, model.SeName, 0); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Added")); + return continueEditing ? RedirectToAction("EditForum", new { forum.Id }) : RedirectToAction("List"); } @@ -286,6 +306,14 @@ public ActionResult EditForum(int id) return RedirectToAction("List"); var model = forum.ToModel(); + + AddLocales(_languageService, model.Locales, (locale, languageId) => + { + locale.Name = forum.GetLocalized(x => x.Name, languageId, false, false); + locale.Description = forum.GetLocalized(x => x.Description, languageId, false, false); + locale.SeName = forum.GetSeName(languageId, false, false); + }); + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); @@ -308,9 +336,16 @@ public ActionResult EditForum(ForumModel model, bool continueEditing) { forum = model.ToEntity(forum); forum.UpdatedOnUtc = DateTime.UtcNow; + _forumService.UpdateForum(forum); + model.SeName = forum.ValidateSeName(model.SeName, forum.Name, true); + _urlRecordService.SaveSlug(forum, model.SeName, 0); + + UpdateLocales(model, forum); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Updated")); + return continueEditing ? RedirectToAction("EditForum", forum.Id) : RedirectToAction("List"); } diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index 4ef685dcc3..d9331cdd05 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -422,6 +422,8 @@ public void Execute() .ForMember(dest => dest.UpdatedOnUtc, mo => mo.Ignore()) .ForMember(dest => dest.Forums, mo => mo.Ignore()); Mapper.CreateMap() + .ForMember(dest => dest.Locales, mo => mo.Ignore()) + .ForMember(dest => dest.SeName, mo => mo.MapFrom(src => src.GetSeName(0, true, false))) .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) .ForMember(dest => dest.ForumGroups, mo => mo.Ignore()); Mapper.CreateMap() diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumModel.cs index fdf1d5d2c3..98fa537748 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumModel.cs @@ -4,16 +4,18 @@ using FluentValidation.Attributes; using SmartStore.Admin.Validators.Forums; using SmartStore.Web.Framework; +using SmartStore.Web.Framework.Localization; using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Models.Forums { [Validator(typeof(ForumValidator))] - public class ForumModel : EntityModelBase + public class ForumModel : EntityModelBase, ILocalizedModel { public ForumModel() { ForumGroups = new List(); + Locales = new List(); } [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.ForumGroupId")] @@ -23,6 +25,10 @@ public ForumModel() [AllowHtml] public string Name { get; set; } + [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.SeName")] + [AllowHtml] + public string SeName { get; set; } + [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.Description")] [AllowHtml] public string Description { get; set; } @@ -34,5 +40,24 @@ public ForumModel() public DateTime CreatedOn { get; set; } public List ForumGroups { get; set; } + + public IList Locales { get; set; } } + + public class ForumLocalizedModel : ILocalizedModelLocal + { + public int LanguageId { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.Name")] + [AllowHtml] + public string Name { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.SeName")] + [AllowHtml] + public string SeName { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.Description")] + [AllowHtml] + public string Description { get; set; } + } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForum.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForum.cshtml index 8f2a0c04d6..2d27a88242 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForum.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForum.cshtml @@ -3,42 +3,91 @@ @using Telerik.Web.Mvc.UI; @Html.ValidationSummary(true) @Html.HiddenFor(model => model.Id) + +@(Html.LocalizedEditor("forumgroup-localized", + @ + + + + + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Locales[item].Name) + + @Html.EditorFor(model => Model.Locales[item].Name) + @Html.ValidationMessageFor(model => model.Locales[item].Name) +
+ @Html.SmartLabelFor(model => model.Locales[item].SeName) + + @Html.EditorFor(model => model.Locales[item].SeName) + @Html.ValidationMessageFor(model => model.Locales[item].SeName) +
+ @Html.SmartLabelFor(model => model.Locales[item].Description) + + @Html.TextAreaFor(model => model.Locales[item].Description, new { @class = "input-large" }) + @Html.ValidationMessageFor(model => model.Locales[item].Description) +
+ @Html.HiddenFor(model => model.Locales[item].LanguageId) +
+ , + @ + + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Name) + + @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ @Html.SmartLabelFor(model => model.SeName) + + @Html.EditorFor(x => x.SeName) + @Html.ValidationMessageFor(model => model.SeName) +
+ @Html.SmartLabelFor(model => model.Description) + + @Html.TextAreaFor(model => model.Description, new { @class = "input-large" }) + @Html.ValidationMessageFor(model => model.Description) +
+)) + - - - - - - - - - - - - - - - - + + + + + + + +
- @Html.SmartLabelFor(model => model.ForumGroupId) - - @Html.DropDownListFor(model => model.ForumGroupId, Model.ForumGroups.Select(x => - new SelectListItem { Value = x.Id.ToString(), Text = x.Name })) - @Html.ValidationMessageFor(model => model.ForumGroupId) -
- @Html.SmartLabelFor(model => model.Name) - - @Html.EditorFor(model => model.Name) - @Html.ValidationMessageFor(model => model.Name) -
- @Html.SmartLabelFor(model => model.Description) - - @Html.TextAreaFor(model => model.Description) - @Html.ValidationMessageFor(model => model.Description) -
- @Html.SmartLabelFor(model => model.DisplayOrder) - - @Html.EditorFor(model => model.DisplayOrder) - @Html.ValidationMessageFor(model => model.DisplayOrder) -
+ @Html.SmartLabelFor(model => model.ForumGroupId) + + @Html.DropDownListFor(model => model.ForumGroupId, Model.ForumGroups.Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Name })) + @Html.ValidationMessageFor(model => model.ForumGroupId) +
+ @Html.SmartLabelFor(model => model.DisplayOrder) + + @Html.EditorFor(model => model.DisplayOrder) + @Html.ValidationMessageFor(model => model.DisplayOrder) +
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs index 22368df310..d9dcc8baaa 100644 --- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs @@ -104,9 +104,9 @@ protected ForumRowModel PrepareForumRowModel(Forum forum) var forumModel = new ForumRowModel { Id = forum.Id, - Name = forum.Name, + Name = forum.GetLocalized(x => x.Name), SeName = forum.GetSeName(), - Description = forum.Description, + Description = forum.GetLocalized(x => x.Description), NumTopics = forum.NumTopics, NumPosts = forum.NumPosts, LastPostId = forum.LastPostId, @@ -176,7 +176,7 @@ protected IEnumerable ForumGroupsForumsList() var forums = _forumService.GetAllForumsByGroupId(fg.Id); foreach (var f in forums) { - forumsList.Add(new SelectListItem { Text = string.Format("{0}{1}", separator, f.Name), Value = f.Id.ToString() }); + forumsList.Add(new SelectListItem { Text = string.Format("{0}{1}", separator, f.GetLocalized(x => x.Name)), Value = f.Id.ToString() }); } } @@ -335,9 +335,9 @@ public ActionResult Forum(int id, int page = 1) { var model = new ForumPageModel(); model.Id = forum.Id; - model.Name = forum.Name; + model.Name = forum.GetLocalized(x => x.Name); model.SeName = forum.GetSeName(); - model.Description = forum.Description; + model.Description = forum.GetLocalized(x => x.Description); int pageSize = 10; if (_forumSettings.TopicsPageSize > 0) @@ -405,7 +405,7 @@ public ActionResult ForumRss(int id) var feedDescription = _localizationService.GetResource("Forum.ForumFeedDescription"); var feed = new SyndicationFeed( - string.Format(feedTitle, _storeContext.CurrentStore.Name, forum.Name), + string.Format(feedTitle, _storeContext.CurrentStore.Name, forum.GetLocalized(x => x.Name)), feedDescription, new Uri(url), string.Format("ForumRSS:{0}", forum.Id), @@ -731,7 +731,7 @@ public ActionResult TopicCreate(int id) model.Id = 0; model.IsEdit = false; model.ForumId = forum.Id; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumSeName = forum.GetSeName(); model.ForumEditor = _forumSettings.ForumEditor; model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(_workContext.CurrentCustomer); @@ -854,7 +854,7 @@ public ActionResult TopicCreate(EditForumTopicModel model) model.TopicPriorities = ForumTopicTypesList(); model.IsEdit = false; model.ForumId = forum.Id; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumSeName = forum.GetSeName(); model.Id = 0; model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(_workContext.CurrentCustomer); @@ -894,7 +894,7 @@ public ActionResult TopicEdit(int id) model.IsEdit = true; model.TopicPriorities = ForumTopicTypesList(); - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumSeName = forum.GetSeName(); model.Text = firstPost.Text; model.Subject = forumTopic.Subject; @@ -1042,7 +1042,7 @@ public ActionResult TopicEdit(EditForumTopicModel model) // redisplay form model.TopicPriorities = ForumTopicTypesList(); model.IsEdit = true; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumSeName = forum.GetSeName(); model.ForumId = forum.Id; model.ForumEditor = _forumSettings.ForumEditor; @@ -1122,7 +1122,7 @@ public ActionResult PostCreate(int id, int? quote) ForumTopicId = forumTopic.Id, IsEdit = false, ForumEditor = _forumSettings.ForumEditor, - ForumName = forum.Name, + ForumName = forum.GetLocalized(x => x.Name), ForumTopicSubject = forumTopic.Subject, ForumTopicSeName = forumTopic.GetSeName(), IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer), @@ -1261,7 +1261,7 @@ public ActionResult PostCreate(EditForumPostModel model) return RedirectToRoute("Boards"); model.IsEdit = false; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumTopicId = forumTopic.Id; model.ForumTopicSubject = forumTopic.Subject; model.ForumTopicSeName = forumTopic.GetSeName(); @@ -1307,7 +1307,7 @@ public ActionResult PostEdit(int id) ForumTopicId = forumTopic.Id, IsEdit = true, ForumEditor = _forumSettings.ForumEditor, - ForumName = forum.Name, + ForumName = forum.GetLocalized(x => x.Name), ForumTopicSubject = forumTopic.Subject, ForumTopicSeName = forumTopic.GetSeName(), IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer), @@ -1430,7 +1430,7 @@ public ActionResult PostEdit(EditForumPostModel model) //redisplay form model.IsEdit = true; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumTopicId = forumTopic.Id; model.ForumTopicSubject = forumTopic.Subject; model.ForumTopicSeName = forumTopic.GetSeName(); @@ -1520,7 +1520,7 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, string { forumsSelectList.Add(new SelectListItem { - Text = string.Format("{0}{1}", separator, f.Name), + Text = string.Format("{0}{1}", separator, f.GetLocalized(x => x.Name)), Value = f.Id.ToString() }); } @@ -1675,7 +1675,7 @@ public ActionResult ForumBreadcrumb(int? forumGroupId, int? forumId, int? forumT if (forum != null) { model.ForumId = forum.Id; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumSeName = forum.GetSeName(); } diff --git a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs index d9e4d85eb7..52d7118d68 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs @@ -1738,12 +1738,12 @@ public ActionResult ForumSubscriptions(int? page) var forum = _forumService.GetForumById(forumId); if (forum != null) { - title = forum.Name; + title = forum.GetLocalized(x => x.Name); slug = forum.GetSeName(); } } - model.ForumSubscriptions.Add(new ForumSubscriptionModel() + model.ForumSubscriptions.Add(new ForumSubscriptionModel { Id = forumSubscription.Id, ForumTopicId = forumTopicId, From a14a71c0ef50becdd01318c9071a822bd0aeca1e Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 7 May 2015 18:52:55 +0200 Subject: [PATCH 0107/1256] Implemented 'Expand()' extension methods for IQueryable, encapsulating EF's Include(). Makes IRepository.Expand() obsolete. --- .../Data/IQueryableExtensions.cs | 44 +++++++++++++++++++ .../SmartStore.Core/Data/IRepository.cs | 17 +------ .../SmartStore.Core/SmartStore.Core.csproj | 1 + src/Libraries/SmartStore.Data/EfRepository.cs | 2 + .../Catalog/CategoryService.cs | 3 +- .../Catalog/ManufacturerService.cs | 3 +- .../Catalog/ProductService.cs | 2 +- .../ExportImport/ImportManager.cs | 2 +- .../Shipping/ShipmentService.cs | 4 +- .../WebApi/WebApiEntityController.cs | 9 ++-- 10 files changed, 60 insertions(+), 27 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Data/IQueryableExtensions.cs diff --git a/src/Libraries/SmartStore.Core/Data/IQueryableExtensions.cs b/src/Libraries/SmartStore.Core/Data/IQueryableExtensions.cs new file mode 100644 index 0000000000..6349fec29c --- /dev/null +++ b/src/Libraries/SmartStore.Core/Data/IQueryableExtensions.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Data.Entity; +using System.Linq.Expressions; + +namespace SmartStore.Core.Data +{ + public static class IQueryableExtensions + { + + /// + /// Instructs the repository to eager load entities that may be in the type's association path. + /// + /// A previously created query object which the expansion should be applied to. + /// + /// The path of the child entities to eager load. + /// Deeper paths can be specified by separating the path with dots. + /// + /// A new query object to which the expansion was applied. + public static IQueryable Expand(this IQueryable query, string path) where T : BaseEntity + { + Guard.ArgumentNotNull(query, "query"); + Guard.ArgumentNotEmpty(path, "path"); + + return query.Include(path); + } + + /// + /// Instructs the repository to eager load entities that may be in the type's association path. + /// + /// A previously created query object which the expansion should be applied to. + /// The path of the child entities to eager load. + /// A new query object to which the expansion was applied. + public static IQueryable Expand(this IQueryable query, Expression> path) where T : BaseEntity + { + Guard.ArgumentNotNull(query, "query"); + Guard.ArgumentNotNull(path, "path"); + + return query.Include(path); + } + + } +} diff --git a/src/Libraries/SmartStore.Core/Data/IRepository.cs b/src/Libraries/SmartStore.Core/Data/IRepository.cs index e82d1fb74e..225f7345c1 100644 --- a/src/Libraries/SmartStore.Core/Data/IRepository.cs +++ b/src/Libraries/SmartStore.Core/Data/IRepository.cs @@ -67,23 +67,10 @@ public partial interface IRepository where T : BaseEntity /// Implementors should delegate this to the current void Delete(T entity); - /// - /// Instructs the repository to eager load entities that may be in the type's association path. - /// - /// A previously created query object which the expansion should be applied to. - /// - /// The path of the child entities to eager load. - /// Deeper paths can be specified by separating the path with dots. - /// - /// A new query object to which the expansion was applied. + [Obsolete("Use the extension method from 'SmartStore.Core, SmartStore.Core.Data' instead")] IQueryable Expand(IQueryable query, string path); - /// - /// Instructs the repository to eager load entities that may be in the type's association path. - /// - /// A previously created query object which the expansion should be applied to. - /// The path of the child entities to eager load. - /// A new query object to which the expansion was applied. + [Obsolete("Use the extension method from 'SmartStore.Core, SmartStore.Core.Data' instead")] IQueryable Expand(IQueryable query, Expression> path); /// diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 07e111d920..367040dc86 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -160,6 +160,7 @@ + diff --git a/src/Libraries/SmartStore.Data/EfRepository.cs b/src/Libraries/SmartStore.Data/EfRepository.cs index d7c46eeba3..60667f549a 100644 --- a/src/Libraries/SmartStore.Data/EfRepository.cs +++ b/src/Libraries/SmartStore.Data/EfRepository.cs @@ -165,6 +165,7 @@ public void Delete(T entity) _context.SaveChanges(); } + [Obsolete("Use the extension method from 'SmartStore.Core, SmartStore.Core.Data' instead")] public IQueryable Expand(IQueryable query, string path) { Guard.ArgumentNotNull(query, "query"); @@ -173,6 +174,7 @@ public IQueryable Expand(IQueryable query, string path) return query.Include(path); } + [Obsolete("Use the extension method from 'SmartStore.Core, SmartStore.Core.Data' instead")] public IQueryable Expand(IQueryable query, Expression> path) { Guard.ArgumentNotNull(query, "query"); diff --git a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs index 05f2190515..d563031d2b 100644 --- a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs @@ -436,8 +436,7 @@ public virtual IList GetProductCategoriesByProductId(int produc string key = string.Format(PRODUCTCATEGORIES_ALLBYPRODUCTID_KEY, showHidden, productId, _workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id); return _cacheManager.Get(key, () => { - var table = _productCategoryRepository.Table; - var query = from pc in _productCategoryRepository.Expand(table, x => x.Category) + var query = from pc in _productCategoryRepository.Table.Expand(x => x.Category) join c in _categoryRepository.Table on pc.CategoryId equals c.Id where pc.ProductId == productId && !c.Deleted && diff --git a/src/Libraries/SmartStore.Services/Catalog/ManufacturerService.cs b/src/Libraries/SmartStore.Services/Catalog/ManufacturerService.cs index b4fadf1463..2bbf0d4f65 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ManufacturerService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ManufacturerService.cs @@ -298,8 +298,7 @@ public virtual IList GetProductManufacturersByProductId(int string key = string.Format(PRODUCTMANUFACTURERS_ALLBYPRODUCTID_KEY, showHidden, productId, _workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id); return _cacheManager.Get(key, () => { - var table = _productManufacturerRepository.Table; - var query = from pm in _productManufacturerRepository.Expand(table, x => x.Manufacturer.Picture) + var query = from pm in _productManufacturerRepository.Table.Expand(x => x.Manufacturer.Picture) join m in _manufacturerRepository.Table on pm.ManufacturerId equals m.Id where pm.ProductId == productId && diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs index 66f2b9ee76..f3963aaf34 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs @@ -1760,7 +1760,7 @@ join p in _productRepository.Table on pbi.ProductId equals p.Id orderby pbi.DisplayOrder select pbi; - query = _productBundleItemRepository.Expand(query, x => x.Product); + query = query.Expand(x => x.Product); var bundleItemData = new List(); diff --git a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs index ef5b8bce04..90b48cb473 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs @@ -694,7 +694,7 @@ private void ProcessProductPictures(ICollection> batch, Impor if (picture.IsEmpty() || !File.Exists(picture)) continue; - var currentPictures = _rsProductPicture.Expand(_rsProductPicture.TableUntracked, x => x.Picture).Where(x => x.ProductId == row.Entity.Id).Select(x => x.Picture).ToList(); + var currentPictures = _rsProductPicture.TableUntracked.Expand(x => x.Picture).Where(x => x.ProductId == row.Entity.Id).Select(x => x.Picture).ToList(); var pictureBinary = _pictureService.FindEqualPicture(picture, currentPictures, out equalPictureId); if (pictureBinary != null && pictureBinary.Length > 0) diff --git a/src/Libraries/SmartStore.Services/Shipping/ShipmentService.cs b/src/Libraries/SmartStore.Services/Shipping/ShipmentService.cs index 93d4e53d04..7afbb90cbb 100644 --- a/src/Libraries/SmartStore.Services/Shipping/ShipmentService.cs +++ b/src/Libraries/SmartStore.Services/Shipping/ShipmentService.cs @@ -84,7 +84,7 @@ public virtual void DeleteShipment(Shipment shipment) public virtual IPagedList GetAllShipments(string trackingNumber, DateTime? createdFrom, DateTime? createdTo, int pageIndex, int pageSize) { - var query = _shipmentRepository.Expand(_shipmentRepository.Table, x => x.Order); + var query = _shipmentRepository.Table.Expand(x => x.Order); if (!String.IsNullOrEmpty(trackingNumber)) query = query.Where(s => s.TrackingNumber.Contains(trackingNumber)); if (createdFrom.HasValue) @@ -108,7 +108,7 @@ public virtual IList GetShipmentsByIds(int[] shipmentIds) if (shipmentIds == null || shipmentIds.Length == 0) return new List(); - var query = from o in _shipmentRepository.Expand(_shipmentRepository.Table, x => x.Order) + var query = from o in _shipmentRepository.Table.Expand(x => x.Order) where shipmentIds.Contains(o.Id) select o; var shipments = query.ToList(); diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs index 24b1f7777d..4bec2890bf 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs @@ -134,17 +134,18 @@ protected internal virtual IQueryable GetEntitySet() protected internal virtual IQueryable GetExpandedEntitySet(Expression> path) { - var query = this.Repository - .Expand(GetEntitySet(), path); - + var query = GetEntitySet().Expand(path); return query; } + protected internal virtual IQueryable GetExpandedEntitySet(string properties) { var query = GetEntitySet(); foreach (var property in properties.SplitSafe(",")) - query = this.Repository.Expand(query, property.Trim()); + { + query = query.Expand(property.Trim()); + } return query; } From a93bb0e7a0fe925160cf2754b828a67236d3c640 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 7 May 2015 19:00:52 +0200 Subject: [PATCH 0108/1256] Fix #687: "There is already an open DataReader associated with this Command which must be closed first" --- .../Administration/Controllers/ProductController.cs | 6 ++++-- .../Controllers/SpecificationAttributeController.cs | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index 1faaf81100..3c323b9686 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -763,12 +763,14 @@ protected void PrepareProductModel(ProductModel model, Product product, bool set for (int i = 0; i < specificationAttributes.Count; i++) { var sa = specificationAttributes[i]; - model.AddSpecificationAttributeModel.AvailableAttributes.Add(new SelectListItem() { Text = sa.Name, Value = sa.Id.ToString() }); + model.AddSpecificationAttributeModel.AvailableAttributes.Add(new SelectListItem { Text = sa.Name, Value = sa.Id.ToString() }); if (i == 0) { //attribute options foreach (var sao in _specificationAttributeService.GetSpecificationAttributeOptionsBySpecificationAttribute(sa.Id)) - model.AddSpecificationAttributeModel.AvailableOptions.Add(new SelectListItem() { Text = sao.Name, Value = sao.Id.ToString() }); + { + model.AddSpecificationAttributeModel.AvailableOptions.Add(new SelectListItem { Text = sao.Name, Value = sao.Id.ToString() }); + } } } //default specs values diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/SpecificationAttributeController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/SpecificationAttributeController.cs index 06c73475a1..b0002f7fe0 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/SpecificationAttributeController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/SpecificationAttributeController.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Catalog; +using SmartStore.Core.Data; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Common; using SmartStore.Core.Logging; @@ -124,6 +125,7 @@ public ActionResult List(GridCommand command) var optionsText = _localizationService.GetResource("Admin.Catalog.Attributes.SpecificationAttributes.Options"); var data = _specificationAttributeService.GetSpecificationAttributes() + .Expand(x => x.SpecificationAttributeOptions) .ForCommand(command) .Select(x => { From 90c9e002f8d8335651c424f99b7dcb0ab21498a0 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 7 May 2015 21:22:20 +0200 Subject: [PATCH 0109/1256] Forum tokens are now resolved in context of language id --- .../SmartStore.Services/Messages/IMessageTokenProvider.cs | 2 +- .../SmartStore.Services/Messages/MessageTokenProvider.cs | 6 +++--- .../SmartStore.Services/Messages/WorkflowMessageService.cs | 7 +++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Messages/IMessageTokenProvider.cs b/src/Libraries/SmartStore.Services/Messages/IMessageTokenProvider.cs index b70bcdd0bf..add0f4e57a 100644 --- a/src/Libraries/SmartStore.Services/Messages/IMessageTokenProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/IMessageTokenProvider.cs @@ -39,7 +39,7 @@ public partial interface IMessageTokenProvider void AddProductTokens(IList tokens, Product product, int languageId); - void AddForumTokens(IList tokens, Forum forum); + void AddForumTokens(IList tokens, Forum forum, int languageId); void AddForumTopicTokens(IList tokens, ForumTopic forumTopic, int? friendlyForumTopicPageIndex = null, int? appendedPostIdentifierAnchor = null); diff --git a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs index 6f9a455c53..ea27f3092b 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs @@ -971,12 +971,12 @@ public virtual void AddForumPostTokens(IList tokens, ForumPost forumPost) _eventPublisher.EntityTokensAdded(forumPost, tokens); } - public virtual void AddForumTokens(IList tokens, Forum forum) + public virtual void AddForumTokens(IList tokens, Forum forum, int languageId) { //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) - var forumUrl = string.Format("{0}boards/forum/{1}/{2}", _webHelper.GetStoreLocation(false), forum.Id, forum.GetSeName()); + var forumUrl = string.Format("{0}boards/forum/{1}/{2}", _webHelper.GetStoreLocation(false), forum.Id, forum.GetSeName(languageId)); tokens.Add(new Token("Forums.ForumURL", forumUrl, true)); - tokens.Add(new Token("Forums.ForumName", forum.GetLocalized(x => x.Name))); + tokens.Add(new Token("Forums.ForumName", forum.GetLocalized(x => x.Name, languageId))); //event notification _eventPublisher.EntityTokensAdded(forum, tokens); diff --git a/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs b/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs index d5ce928649..bbad203299 100644 --- a/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs +++ b/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs @@ -993,7 +993,7 @@ public int SendNewForumTopicMessage(Customer customer, _messageTokenProvider.AddStoreTokens(tokens, store); _messageTokenProvider.AddCustomerTokens(tokens, customer); _messageTokenProvider.AddForumTopicTokens(tokens, forumTopic); - _messageTokenProvider.AddForumTokens(tokens, forumTopic.Forum); + _messageTokenProvider.AddForumTokens(tokens, forumTopic.Forum, languageId); //event notification _eventPublisher.MessageTokensAdded(messageTemplate, tokens); @@ -1037,9 +1037,8 @@ public int SendNewForumPostMessage(Customer customer, _messageTokenProvider.AddStoreTokens(tokens, store); _messageTokenProvider.AddForumPostTokens(tokens, forumPost); _messageTokenProvider.AddCustomerTokens(tokens, customer); - _messageTokenProvider.AddForumTopicTokens(tokens, forumPost.ForumTopic, - friendlyForumTopicPageIndex, forumPost.Id); - _messageTokenProvider.AddForumTokens(tokens, forumPost.ForumTopic.Forum); + _messageTokenProvider.AddForumTopicTokens(tokens, forumPost.ForumTopic, friendlyForumTopicPageIndex, forumPost.Id); + _messageTokenProvider.AddForumTokens(tokens, forumPost.ForumTopic.Forum, languageId); //event notification _eventPublisher.MessageTokensAdded(messageTemplate, tokens); From 048a49e5dae1752914a33e7f26c5e5b6a0b53da6 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 6 May 2015 17:52:24 +0200 Subject: [PATCH 0110/1256] Resolves #508 Limit country settings to stores --- changelog.md | 1 + .../Domain/Directory/Country.cs | 11 +- ...505061135313_CountryMultistore.Designer.cs | 29 ++++ .../201505061135313_CountryMultistore.cs | 18 +++ .../201505061135313_CountryMultistore.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 7 + .../Directory/CountryService.cs | 74 ++++++---- .../ExportImport/ExportManager.cs | 1 + .../Controllers/CountryController.cs | 91 +++++++++---- .../Infrastructure/AutoMapperStartupTask.cs | 4 +- .../Models/Directory/CountryModel.cs | 12 +- .../Administration/Views/Country/List.cshtml | 13 +- .../Views/Country/_CreateOrUpdate.cshtml | 45 +++++++ .../Directory/CountryPersistenceTests.cs | 10 +- 14 files changed, 377 insertions(+), 65 deletions(-) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx diff --git a/changelog.md b/changelog.md index 1382f2738f..704960aa82 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,7 @@ * #554 Flag to indicate that a new payment notification (IPN) arrived for an order since last opening\editing of the order * Setting whether and how to display sub-categories on a category page (hide, above products, bottom of page) * Debitoor: Extend option "Book invoice if paid" to also (optionally) mail the invoice as a PDF +* #508 Limit country settings to stores ### Improvements * PDF converter: first init is much faster now diff --git a/src/Libraries/SmartStore.Core/Domain/Directory/Country.cs b/src/Libraries/SmartStore.Core/Domain/Directory/Country.cs index 39bb1ba887..117a487a07 100644 --- a/src/Libraries/SmartStore.Core/Domain/Directory/Country.cs +++ b/src/Libraries/SmartStore.Core/Domain/Directory/Country.cs @@ -1,7 +1,8 @@ using System.Collections.Generic; +using System.Runtime.Serialization; using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Shipping; -using System.Runtime.Serialization; +using SmartStore.Core.Domain.Stores; namespace SmartStore.Core.Domain.Directory { @@ -9,7 +10,7 @@ namespace SmartStore.Core.Domain.Directory /// Represents a country /// [DataContract] - public partial class Country : BaseEntity, ILocalizedEntity + public partial class Country : BaseEntity, ILocalizedEntity, IStoreMappingSupported { private ICollection _stateProvinces; private ICollection _restrictedShippingMethods; @@ -68,6 +69,12 @@ public partial class Country : BaseEntity, ILocalizedEntity ///
[DataMember] public int DisplayOrder { get; set; } + + /// + /// Gets or sets a value indicating whether the entity is limited/restricted to certain stores + /// + [DataMember] + public bool LimitedToStores { get; set; } /// /// Gets or sets the state/provinces diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs new file mode 100644 index 0000000000..f761e5139e --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class CountryMultistore : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(CountryMultistore)); + + string IMigrationMetadata.Id + { + get { return "201505061135313_CountryMultistore"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs new file mode 100644 index 0000000000..e898f4427e --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs @@ -0,0 +1,18 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class CountryMultistore : DbMigration + { + public override void Up() + { + AddColumn("dbo.Country", "LimitedToStores", c => c.Boolean(nullable: false)); + } + + public override void Down() + { + DropColumn("dbo.Country", "LimitedToStores"); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx new file mode 100644 index 0000000000..9ccce9d534 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 40f76cf62b..dbe63ab8a1 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -264,6 +264,10 @@ 201505052021483_PdfConverterRoleFix.cs + + + 201505061135313_CountryMultistore.cs + @@ -515,6 +519,9 @@ 201505052021483_PdfConverterRoleFix.cs + + 201505061135313_CountryMultistore.cs + diff --git a/src/Libraries/SmartStore.Services/Directory/CountryService.cs b/src/Libraries/SmartStore.Services/Directory/CountryService.cs index aeda79b995..40b2e16a8b 100644 --- a/src/Libraries/SmartStore.Services/Directory/CountryService.cs +++ b/src/Libraries/SmartStore.Services/Directory/CountryService.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; +using SmartStore.Core; using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Directory; +using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; namespace SmartStore.Services.Directory @@ -25,26 +27,28 @@ public partial class CountryService : ICountryService private readonly IRepository _countryRepository; private readonly IEventPublisher _eventPublisher; private readonly ICacheManager _cacheManager; + private readonly IStoreContext _storeContext; + private readonly IRepository _storeMappingRepository; #endregion #region Ctor - /// - /// Ctor - /// - /// Cache manager - /// Country repository - /// Event published public CountryService(ICacheManager cacheManager, IRepository countryRepository, - IEventPublisher eventPublisher) + IEventPublisher eventPublisher, + IStoreContext storeContext, + IRepository storeMappingRepository) { _cacheManager = cacheManager; _countryRepository = countryRepository; _eventPublisher = eventPublisher; + _storeContext = storeContext; + _storeMappingRepository = storeMappingRepository; } + public DbQuerySettings QuerySettings { get; set; } + #endregion #region Methods @@ -76,10 +80,31 @@ public virtual IList GetAllCountries(bool showHidden = false) string key = string.Format(COUNTRIES_ALL_KEY, showHidden); return _cacheManager.Get(key, () => { - var query = from c in _countryRepository.Table - orderby c.DisplayOrder, c.Name - where showHidden || c.Published - select c; + var query = _countryRepository.Table; + + if (!showHidden) + query = query.Where(c => c.Published); + + query = query.OrderBy(c => c.DisplayOrder).ThenBy(c => c.Name); + + if (!showHidden && !QuerySettings.IgnoreMultiStore) + { + var currentStoreId = _storeContext.CurrentStore.Id; + query = from c in query + join sc in _storeMappingRepository.Table + on new { c1 = c.Id, c2 = "Country" } equals new { c1 = sc.EntityId, c2 = sc.EntityName } into c_sm + from sc in c_sm.DefaultIfEmpty() + where !c.LimitedToStores || currentStoreId == sc.StoreId + select c; + + query = from c in query + group c by c.Id into cGroup + orderby cGroup.Key + select cGroup.FirstOrDefault(); + + query = query.OrderBy(c => c.DisplayOrder).ThenBy(c => c.Name); + } + var countries = query.ToList(); return countries; }); @@ -95,11 +120,9 @@ public virtual IList GetAllCountriesForBilling(bool showHidden = false) string key = string.Format(COUNTRIES_BILLING_KEY, showHidden); return _cacheManager.Get(key, () => { - var query = from c in _countryRepository.Table - orderby c.DisplayOrder, c.Name - where (showHidden || c.Published) && c.AllowsBilling - select c; - var countries = query.ToList(); + var allCountries = GetAllCountries(showHidden); + + var countries = allCountries.Where(x => x.AllowsBilling).ToList(); return countries; }); } @@ -113,12 +136,10 @@ public virtual IList GetAllCountriesForShipping(bool showHidden = false { string key = string.Format(COUNTRIES_SHIPPING_KEY, showHidden); return _cacheManager.Get(key, () => - { - var query = from c in _countryRepository.Table - orderby c.DisplayOrder, c.Name - where (showHidden || c.Published) && c.AllowsShipping - select c; - var countries = query.ToList(); + { + var allCountries = GetAllCountries(showHidden); + + var countries = allCountries.Where(x => x.AllowsShipping).ToList(); return countries; }); } @@ -160,11 +181,14 @@ public virtual Country GetCountryByTwoOrThreeLetterIsoCode(string letterIsoCode) /// Country public virtual Country GetCountryByTwoLetterIsoCode(string twoLetterIsoCode) { + if (twoLetterIsoCode.IsEmpty()) + return null; + var query = from c in _countryRepository.Table where c.TwoLetterIsoCode == twoLetterIsoCode select c; - var country = query.FirstOrDefault(); + var country = query.FirstOrDefault(); return country; } @@ -175,9 +199,13 @@ public virtual Country GetCountryByTwoLetterIsoCode(string twoLetterIsoCode) /// Country public virtual Country GetCountryByThreeLetterIsoCode(string threeLetterIsoCode) { + if (threeLetterIsoCode.IsEmpty()) + return null; + var query = from c in _countryRepository.Table where c.ThreeLetterIsoCode == threeLetterIsoCode select c; + var country = query.FirstOrDefault(); return country; } diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 2b89be8e7b..804c967911 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -2029,6 +2029,7 @@ public virtual string ExportCustomersToXml(IList customers) xmlWriter.WriteElementString("SubjectToVat", null, address.Country.SubjectToVat.ToString()); xmlWriter.WriteElementString("Published", null, address.Country.Published.ToString()); xmlWriter.WriteElementString("DisplayOrder", null, address.Country.DisplayOrder.ToString()); + xmlWriter.WriteElementString("LimitedToStores", null, address.Country.LimitedToStores.ToString()); xmlWriter.WriteEndElement(); // Country } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs index 9554f642c0..9af684b301 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CountryController.cs @@ -9,6 +9,7 @@ using SmartStore.Services.Directory; using SmartStore.Services.Localization; using SmartStore.Services.Security; +using SmartStore.Services.Stores; using SmartStore.Web.Framework.Controllers; using Telerik.Web.Mvc; @@ -26,23 +27,32 @@ public class CountryController : AdminControllerBase private readonly IPermissionService _permissionService; private readonly ILocalizedEntityService _localizedEntityService; private readonly ILanguageService _languageService; + private readonly IStoreService _storeService; + private readonly IStoreMappingService _storeMappingService; #endregion #region Constructors public CountryController(ICountryService countryService, - IStateProvinceService stateProvinceService, ILocalizationService localizationService, - IAddressService addressService, IPermissionService permissionService, - ILocalizedEntityService localizedEntityService, ILanguageService languageService) + IStateProvinceService stateProvinceService, + ILocalizationService localizationService, + IAddressService addressService, + IPermissionService permissionService, + ILocalizedEntityService localizedEntityService, + ILanguageService languageService, + IStoreService storeService, + IStoreMappingService storeMappingService) { - this._countryService = countryService; - this._stateProvinceService = stateProvinceService; - this._localizationService = localizationService; - this._addressService = addressService; - this._permissionService = permissionService; - this._localizedEntityService = localizedEntityService; - this._languageService = languageService; + _countryService = countryService; + _stateProvinceService = stateProvinceService; + _localizationService = localizationService; + _addressService = addressService; + _permissionService = permissionService; + _localizedEntityService = localizedEntityService; + _languageService = languageService; + _storeService = storeService; + _storeMappingService = storeMappingService; } #endregion  @@ -50,7 +60,7 @@ public CountryController(ICountryService countryService, #region Utilities [NonAction] - public void UpdateLocales(Country country, CountryModel model) + private void UpdateLocales(Country country, CountryModel model) { foreach (var localized in model.Locales) { @@ -62,7 +72,7 @@ public void UpdateLocales(Country country, CountryModel model) } [NonAction] - public void UpdateLocales(StateProvince stateProvince, StateProvinceModel model) + private void UpdateLocales(StateProvince stateProvince, StateProvinceModel model) { foreach (var localized in model.Locales) { @@ -72,6 +82,28 @@ public void UpdateLocales(StateProvince stateProvince, StateProvinceModel model) localized.LanguageId); } } + + [NonAction] + private void PrepareCountryModel(CountryModel model, Country country, bool excludeProperties) + { + if (model == null) + throw new ArgumentNullException("model"); + + var allStores = _storeService.GetAllStores(); + + model.AvailableStores = allStores.Select(s => s.ToModel()).ToList(); + + if (!excludeProperties) + { + if (country != null) + model.SelectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(country); + else + model.SelectedStoreIds = new int[0]; + } + + ViewBag.StoreCount = allStores.Count; + } + #endregion #region Countries @@ -120,12 +152,15 @@ public ActionResult Create() return AccessDeniedView(); var model = new CountryModel(); - //locales + AddLocales(_languageService, model.Locales); - //default values + PrepareCountryModel(model, null, false); + + //default values model.Published = true; model.AllowsBilling = true; model.AllowsShipping = true; + return View(model); } @@ -139,14 +174,18 @@ public ActionResult Create(CountryModel model, bool continueEditing) { var country = model.ToEntity(); _countryService.InsertCountry(country); - //locales + UpdateLocales(country, model); + _storeMappingService.SaveStoreMappings(country, model.SelectedStoreIds); + NotifySuccess(_localizationService.GetResource("Admin.Configuration.Countries.Added")); + return continueEditing ? RedirectToAction("Edit", new { id = country.Id }) : RedirectToAction("List"); } - //If we got this far, something failed, redisplay form + PrepareCountryModel(model, null, true); + return View(model); } @@ -157,15 +196,17 @@ public ActionResult Edit(int id) var country = _countryService.GetCountryById(id); if (country == null) - //No country found with the specified id return RedirectToAction("List"); var model = country.ToModel(); - //locales + AddLocales(_languageService, model.Locales, (locale, languageId) => { locale.Name = country.GetLocalized(x => x.Name, languageId, false, false); }); + + PrepareCountryModel(model, country, false); + return View(model); } @@ -177,21 +218,24 @@ public ActionResult Edit(CountryModel model, bool continueEditing) var country = _countryService.GetCountryById(model.Id); if (country == null) - //No country found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) { country = model.ToEntity(country); _countryService.UpdateCountry(country); - //locales + UpdateLocales(country, model); + _storeMappingService.SaveStoreMappings(country, model.SelectedStoreIds); + NotifySuccess(_localizationService.GetResource("Admin.Configuration.Countries.Updated")); + return continueEditing ? RedirectToAction("Edit", new { id = country.Id }) : RedirectToAction("List"); } - //If we got this far, something failed, redisplay form + PrepareCountryModel(model, country, true); + return View(model); } @@ -203,7 +247,6 @@ public ActionResult DeleteConfirmed(int id) var country = _countryService.GetCountryById(id); if (country == null) - //No country found with the specified id return RedirectToAction("List"); try @@ -270,7 +313,6 @@ public ActionResult StateCreatePopup(string btnId, string formId, StateProvinceM var country = _countryService.GetCountryById(model.CountryId); if (country == null) - //No country found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) @@ -360,8 +402,7 @@ public ActionResult StateDelete(int id, GridCommand command) } [AcceptVerbs(HttpVerbs.Get)] - public ActionResult GetStatesByCountryId(string countryId, - bool? addEmptyStateIfRequired, bool? addAsterisk) + public ActionResult GetStatesByCountryId(string countryId, bool? addEmptyStateIfRequired, bool? addAsterisk) { //permission validation is not required here diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index cd13fe7cbc..f65a1d470d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -116,7 +116,9 @@ public void Execute() .ForMember(dest => dest.RestrictedShippingMethods, mo => mo.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.NumberOfStates, mo => mo.MapFrom(src => src.StateProvinces != null ? src.StateProvinces.Count : 0)) - .ForMember(dest => dest.Locales, mo => mo.Ignore()); + .ForMember(dest => dest.Locales, mo => mo.Ignore()) + .ForMember(dest => dest.AvailableStores, mo => mo.Ignore()) + .ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore()); //state/provinces Mapper.CreateMap() .ForMember(dest => dest.DisplayOrder1, mo => mo.MapFrom(src => src.DisplayOrder)) diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Directory/CountryModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Directory/CountryModel.cs index 6df12ca14f..ed1ca645c8 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Directory/CountryModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Directory/CountryModel.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Web.Mvc; using FluentValidation.Attributes; +using SmartStore.Admin.Models.Stores; using SmartStore.Admin.Validators.Directory; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Localization; @@ -15,6 +16,7 @@ public CountryModel() { Locales = new List(); } + [SmartResourceDisplayName("Admin.Configuration.Countries.Fields.Name")] [AllowHtml] public string Name { get; set; } @@ -45,13 +47,17 @@ public CountryModel() [SmartResourceDisplayName("Admin.Configuration.Countries.Fields.DisplayOrder")] public int DisplayOrder { get; set; } - - - [SmartResourceDisplayName("Admin.Configuration.Countries.Fields.NumberOfStates")] public int NumberOfStates { get; set; } public IList Locales { get; set; } + + [SmartResourceDisplayName("Admin.Common.Store.LimitedTo")] + public bool LimitedToStores { get; set; } + + [SmartResourceDisplayName("Admin.Common.Store.AvailableFor")] + public List AvailableStores { get; set; } + public int[] SelectedStoreIds { get; set; } } public class CountryLocalizedModel : ILocalizedModelLocal diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Country/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Country/List.cshtml index 6395a0a7d0..5285bcd4d5 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Country/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Country/List.cshtml @@ -1,7 +1,6 @@ @model Telerik.Web.Mvc.GridModel @using Telerik.Web.Mvc.UI @{ - //page title ViewBag.Title = T("Admin.Configuration.Countries").Text; }
@@ -55,17 +54,17 @@ columns.Bound(x => x.DisplayOrder) .Width(50) .Centered(); + columns.Bound(x => x.LimitedToStores) + .Template(item => @Html.SymbolForBool(item.LimitedToStores)) + .ClientTemplate(@Html.SymbolForBool("LimitedToStores")) + .Centered() + .Width(100) + .Hidden(ViewBag.StoreCount <= 1); columns.Bound(x => x.Published) .Width(50) .Template(item => @Html.SymbolForBool(item.Published)) .ClientTemplate(@Html.SymbolForBool("Published")) .Centered(); - //columns.Bound(x => x.Id) - // .Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id })) - // .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") - // .Width(50) - // .Centered() - // .HeaderTemplate(T("Admin.Common.Edit").Text); }) .DataBinding(dataBinding => dataBinding.Ajax().Select("CountryList", "Country")) .EnableCustomBinding(true)) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml index 4c5884ad39..c96abce377 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Country/_CreateOrUpdate.cshtml @@ -7,6 +7,7 @@ { x.Add().Text(T("Admin.Configuration.Countries.Info").Text).Content(TabInfo()).Selected(true); x.Add().Text(T("Admin.Configuration.Countries.States").Text).Content(TabStates()); + x.Add().Text(T("Admin.Common.Stores").Text).Content(TabStores()); //generate an event EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "country-edit", this.Html, this.Model)); @@ -200,4 +201,48 @@ { @T("Admin.Configuration.Countries.States.SaveBeforeEdit") } +} + +@helper TabStores() +{ + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.LimitedToStores) + + @Html.EditorFor(model => model.LimitedToStores) + @Html.ValidationMessageFor(model => model.LimitedToStores) +
+ @Html.SmartLabelFor(model => model.AvailableStores) + + @if (Model.AvailableStores != null && Model.AvailableStores.Count > 0) + { + foreach (var store in Model.AvailableStores) + { + + } + } + else + { +
@T("Admin.Configuration.Stores.NoStoresDefined")
+ } +
} \ No newline at end of file diff --git a/src/Tests/SmartStore.Data.Tests/Directory/CountryPersistenceTests.cs b/src/Tests/SmartStore.Data.Tests/Directory/CountryPersistenceTests.cs index c83687092f..18dfac25d3 100644 --- a/src/Tests/SmartStore.Data.Tests/Directory/CountryPersistenceTests.cs +++ b/src/Tests/SmartStore.Data.Tests/Directory/CountryPersistenceTests.cs @@ -1,8 +1,8 @@ using System.Linq; +using NUnit.Framework; using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Shipping; using SmartStore.Tests; -using NUnit.Framework; namespace SmartStore.Data.Tests.Directory { @@ -22,7 +22,8 @@ public void Can_save_and_load_country() NumericIsoCode = 1, SubjectToVat = true, Published = true, - DisplayOrder = 1 + DisplayOrder = 1, + LimitedToStores = true }; var fromDb = SaveAndLoadEntity(country); @@ -36,6 +37,7 @@ public void Can_save_and_load_country() fromDb.SubjectToVat.ShouldEqual(true); fromDb.Published.ShouldEqual(true); fromDb.DisplayOrder.ShouldEqual(1); + fromDb.LimitedToStores.ShouldEqual(true); } [Test] @@ -55,7 +57,7 @@ public void Can_save_and_load_country_with_states() }; country.StateProvinces.Add ( - new StateProvince() + new StateProvince { Name = "California", Abbreviation = "CA", @@ -88,7 +90,7 @@ public void Can_save_and_load_country_with_restrictions() }; country.RestrictedShippingMethods.Add ( - new ShippingMethod() + new ShippingMethod { Name = "By train", } From c8aa80ec556d940714e4c194bec1fea07f365771 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 7 May 2015 11:51:05 +0200 Subject: [PATCH 0111/1256] Resolves #205 Add multistore support for forums --- .../Domain/Forums/ForumGroup.cs | 8 +- .../201505061135313_CountryMultistore.resx | 126 -------- ...05061813010_CountryMultistore.Designer.cs} | 2 +- ...s => 201505061813010_CountryMultistore.cs} | 2 + .../201505061813010_CountryMultistore.resx | 126 ++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../Forums/ForumService.cs | 236 +++++++------- .../Forums/IForumService.cs | 6 +- .../Controllers/ForumController.cs | 137 +++++--- .../Infrastructure/AutoMapperStartupTask.cs | 2 + .../Models/Forums/ForumGroupModel.cs | 8 + .../Administration/Views/Forum/List.cshtml | 14 +- .../Forum/_CreateOrUpdateForumGroup.cshtml | 115 +++++-- .../Controllers/BoardsController.cs | 296 ++++++++++-------- 14 files changed, 632 insertions(+), 456 deletions(-) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx rename src/Libraries/SmartStore.Data/Migrations/{201505061135313_CountryMultistore.Designer.cs => 201505061813010_CountryMultistore.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201505061135313_CountryMultistore.cs => 201505061813010_CountryMultistore.cs} (73%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.resx diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs index 4e4cc99eba..77022b7047 100644 --- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs +++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; +using SmartStore.Core.Domain.Stores; namespace SmartStore.Core.Domain.Forums { /// /// Represents a forum group /// - public partial class ForumGroup : BaseEntity + public partial class ForumGroup : BaseEntity, IStoreMappingSupported { private ICollection _forums; @@ -35,6 +36,11 @@ public partial class ForumGroup : BaseEntity ///
public DateTime UpdatedOnUtc { get; set; } + /// + /// Gets or sets a value indicating whether the entity is limited/restricted to certain stores + /// + public bool LimitedToStores { get; set; } + /// /// Gets or sets the collection of Forums /// diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx b/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx deleted file mode 100644 index 9ccce9d534..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.Designer.cs index f761e5139e..a39bd3bf2f 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class CountryMultistore : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201505061135313_CountryMultistore"; } + get { return "201505061813010_CountryMultistore"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs similarity index 73% rename from src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs rename to src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs index e898f4427e..c701338fee 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505061135313_CountryMultistore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs @@ -8,10 +8,12 @@ public partial class CountryMultistore : DbMigration public override void Up() { AddColumn("dbo.Country", "LimitedToStores", c => c.Boolean(nullable: false)); + AddColumn("dbo.Forums_Group", "LimitedToStores", c => c.Boolean(nullable: false)); } public override void Down() { + DropColumn("dbo.Forums_Group", "LimitedToStores"); DropColumn("dbo.Country", "LimitedToStores"); } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.resx b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.resx new file mode 100644 index 0000000000..8a4e44f84b --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index dbe63ab8a1..602115f62d 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -264,9 +264,9 @@ 201505052021483_PdfConverterRoleFix.cs - - - 201505061135313_CountryMultistore.cs + + + 201505061813010_CountryMultistore.cs @@ -519,8 +519,8 @@ 201505052021483_PdfConverterRoleFix.cs - - 201505061135313_CountryMultistore.cs + + 201505061813010_CountryMultistore.cs diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs index 6fed24aff9..4f5ca20ce4 100644 --- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs +++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs @@ -6,6 +6,7 @@ using SmartStore.Core.Data; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Forums; +using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; using SmartStore.Services.Common; using SmartStore.Services.Customers; @@ -19,13 +20,16 @@ namespace SmartStore.Services.Forums public partial class ForumService : IForumService { #region Constants - private const string FORUMGROUP_ALL_KEY = "SmartStore.forumgroup.all"; + + private const string FORUMGROUP_ALL_KEY = "SmartStore.forumgroup.all-{0}"; private const string FORUM_ALLBYFORUMGROUPID_KEY = "SmartStore.forum.allbyforumgroupid-{0}"; private const string FORUMGROUP_PATTERN_KEY = "SmartStore.forumgroup."; private const string FORUM_PATTERN_KEY = "SmartStore.forum."; - #endregion + + #endregion #region Fields + private readonly IRepository _forumGroupRepository; private readonly IRepository _forumRepository; private readonly IRepository _forumTopicRepository; @@ -40,28 +44,13 @@ public partial class ForumService : IForumService private readonly IWorkContext _workContext; private readonly IWorkflowMessageService _workflowMessageService; private readonly IEventPublisher _eventPublisher; + private readonly IStoreContext _storeContext; + private readonly IRepository _storeMappingRepository; #endregion #region Ctor - /// - /// Ctor - /// - /// Cache manager - /// Forum group repository - /// Forum repository - /// Forum topic repository - /// Forum post repository - /// Private message repository - /// Forum subscription repository - /// Forum settings - /// Customer repository - /// Generic attribute service - /// Customer service - /// Work context - /// Workflow message service - /// Event published public ForumService(ICacheManager cacheManager, IRepository forumGroupRepository, IRepository forumRepository, @@ -75,25 +64,31 @@ public ForumService(ICacheManager cacheManager, ICustomerService customerService, IWorkContext workContext, IWorkflowMessageService workflowMessageService, - IEventPublisher eventPublisher - ) + IEventPublisher eventPublisher, + IStoreContext storeContext, + IRepository storeMappingRepository) { - this._cacheManager = cacheManager; - this._forumGroupRepository = forumGroupRepository; - this._forumRepository = forumRepository; - this._forumTopicRepository = forumTopicRepository; - this._forumPostRepository = forumPostRepository; - this._forumPrivateMessageRepository = forumPrivateMessageRepository; - this._forumSubscriptionRepository = forumSubscriptionRepository; - this._forumSettings = forumSettings; - this._customerRepository = customerRepository; - this._genericAttributeService = genericAttributeService; - this._customerService = customerService; - this._workContext = workContext; - this._workflowMessageService = workflowMessageService; + _cacheManager = cacheManager; + _forumGroupRepository = forumGroupRepository; + _forumRepository = forumRepository; + _forumTopicRepository = forumTopicRepository; + _forumPostRepository = forumPostRepository; + _forumPrivateMessageRepository = forumPrivateMessageRepository; + _forumSubscriptionRepository = forumSubscriptionRepository; + _forumSettings = forumSettings; + _customerRepository = customerRepository; + _genericAttributeService = genericAttributeService; + _customerService = customerService; + _workContext = workContext; + _workflowMessageService = workflowMessageService; _eventPublisher = eventPublisher; + _storeContext = storeContext; + _storeMappingRepository = storeMappingRepository; } - #endregion + + public DbQuerySettings QuerySettings { get; set; } + + #endregion #region Utilities @@ -288,14 +283,33 @@ public virtual ForumGroup GetForumGroupById(int forumGroupId) /// Gets all forum groups /// /// Forum groups - public virtual IList GetAllForumGroups() + public virtual IList GetAllForumGroups(bool showHidden = false) { - string key = string.Format(FORUMGROUP_ALL_KEY); + string key = string.Format(FORUMGROUP_ALL_KEY, showHidden); return _cacheManager.Get(key, () => { - var query = from fg in _forumGroupRepository.Table - orderby fg.DisplayOrder - select fg; + var query = _forumGroupRepository.Table; + + if (!showHidden && !QuerySettings.IgnoreMultiStore) + { + var currentStoreId = _storeContext.CurrentStore.Id; + + query = + from fg in query + join sm in _storeMappingRepository.Table on new { c1 = fg.Id, c2 = "ForumGroup" } equals new { c1 = sm.EntityId, c2 = sm.EntityName } into fg_sm + from sm in fg_sm.DefaultIfEmpty() + where !fg.LimitedToStores || currentStoreId == sm.StoreId + select fg; + + query = + from fg in query + group fg by fg.Id into fgGroup + orderby fgGroup.Key + select fgGroup.FirstOrDefault(); + } + + query = query.OrderBy(m => m.DisplayOrder); + return query.ToList(); }); } @@ -552,32 +566,33 @@ public virtual ForumTopic GetTopicById(int forumTopicId, bool increaseViews) /// Page index /// Page size /// Forum Topics - public virtual IPagedList GetAllTopics(int forumId, - int customerId, string keywords, ForumSearchType searchType, - int limitDays, int pageIndex, int pageSize) + public virtual IPagedList GetAllTopics(int forumId, int customerId, string keywords, ForumSearchType searchType, int limitDays, int pageIndex, int pageSize) { DateTime? limitDate = null; + if (limitDays > 0) { limitDate = DateTime.UtcNow.AddDays(-limitDays); } - var query1 = from ft in _forumTopicRepository.Table - join fp in _forumPostRepository.Table on ft.Id equals fp.TopicId - where - (forumId == 0 || ft.ForumId == forumId) && - (customerId == 0 || ft.CustomerId == customerId) && - ( - // following line causes SqlCeException on SQLCE4 (comparing parameter to IS NULL in query) -works on SQL Server - // String.IsNullOrEmpty(keywords) || - ((searchType == ForumSearchType.All || searchType == ForumSearchType.TopicTitlesOnly) && ft.Subject.Contains(keywords)) || - ((searchType == ForumSearchType.All || searchType == ForumSearchType.PostTextOnly) && fp.Text.Contains(keywords))) && - (!limitDate.HasValue || limitDate.Value <= ft.LastPostTime) - select ft.Id; - - var query2 = from ft in _forumTopicRepository.Table - where query1.Contains(ft.Id) - orderby ft.TopicTypeId descending, ft.LastPostTime descending, ft.Id descending - select ft; + + var query1 = + from ft in _forumTopicRepository.Table + join fp in _forumPostRepository.Table on ft.Id equals fp.TopicId + where + (forumId == 0 || ft.ForumId == forumId) && + (customerId == 0 || ft.CustomerId == customerId) && + (!limitDate.HasValue || limitDate.Value <= ft.LastPostTime) && + ( + ((searchType == ForumSearchType.All || searchType == ForumSearchType.TopicTitlesOnly) && ft.Subject.Contains(keywords)) || + ((searchType == ForumSearchType.All || searchType == ForumSearchType.PostTextOnly) && fp.Text.Contains(keywords)) + ) + select ft.Id; + + var query2 = + from ft in _forumTopicRepository.Table + where query1.Contains(ft.Id) + orderby ft.TopicTypeId descending, ft.LastPostTime descending, ft.Id descending + select ft; var topics = new PagedList(query2, pageIndex, pageSize); return topics; @@ -591,18 +606,34 @@ where query1.Contains(ft.Id) /// Forum Topics public virtual IList GetActiveTopics(int forumId, int count) { - var query1 = from ft in _forumTopicRepository.Table - where - (forumId == 0 || ft.ForumId == forumId) && - (ft.LastPostTime.HasValue) - select ft.Id; - - var query2 = from ft in _forumTopicRepository.Table - where query1.Contains(ft.Id) - orderby ft.LastPostTime descending - select ft; - - var forumTopics = query2.Take(count).ToList(); + var query = + from ft in _forumTopicRepository.Table + where (forumId == 0 || ft.ForumId == forumId) && (ft.LastPostTime.HasValue) + select ft; + + if (!QuerySettings.IgnoreMultiStore) + { + var currentStoreId = _storeContext.CurrentStore.Id; + + query = + from ft in query + join ff in _forumRepository.Table on ft.ForumId equals ff.Id + join fg in _forumGroupRepository.Table on ff.ForumGroupId equals fg.Id + join sm in _storeMappingRepository.Table on new { c1 = fg.Id, c2 = "ForumGroup" } equals new { c1 = sm.EntityId, c2 = sm.EntityName } into fg_sm + from sm in fg_sm.DefaultIfEmpty() + where !fg.LimitedToStores || currentStoreId == sm.StoreId + select ft; + + query = + from ft in query + group ft by ft.Id into ftGroup + orderby ftGroup.Key + select ftGroup.FirstOrDefault(); + } + + query = query.OrderByDescending(x => x.LastPostTime); + + var forumTopics = query.Take(count).ToList(); return forumTopics; } @@ -646,8 +677,7 @@ public virtual void InsertTopic(ForumTopic forumTopic, bool sendNotifications) if (!String.IsNullOrEmpty(subscription.Customer.Email)) { - _workflowMessageService.SendNewForumTopicMessage(subscription.Customer, forumTopic, - forum, languageId); + _workflowMessageService.SendNewForumTopicMessage(subscription.Customer, forumTopic, forum, languageId); } } } @@ -725,7 +755,7 @@ public virtual void DeletePost(ForumPost forumPost) //delete topic if it was the first post bool deleteTopic = false; - ForumPost firstPost = forumTopic.GetFirstPost(this); + var firstPost = forumTopic.GetFirstPost(this); if (firstPost != null && firstPost.Id == forumPost.Id) { deleteTopic = true; @@ -786,11 +816,9 @@ public virtual ForumPost GetPostById(int forumPostId) /// Page index /// Page size /// Posts - public virtual IPagedList GetAllPosts(int forumTopicId, - int customerId, string keywords, int pageIndex, int pageSize) + public virtual IPagedList GetAllPosts(int forumTopicId, int customerId, string keywords, int pageIndex, int pageSize) { - return GetAllPosts(forumTopicId, customerId, keywords, true, - pageIndex, pageSize); + return GetAllPosts(forumTopicId, customerId, keywords, true, pageIndex, pageSize); } /// @@ -803,8 +831,7 @@ public virtual IPagedList GetAllPosts(int forumTopicId, /// Page index /// Page size /// Forum Posts - public virtual IPagedList GetAllPosts(int forumTopicId, int customerId, - string keywords, bool ascSort, int pageIndex, int pageSize) + public virtual IPagedList GetAllPosts(int forumTopicId, int customerId, string keywords, bool ascSort, int pageIndex, int pageSize) { var query = _forumPostRepository.Table; if (forumTopicId > 0) @@ -866,14 +893,11 @@ public virtual void InsertPost(ForumPost forumPost, bool sendNotifications) if (sendNotifications) { var forum = forumTopic.Forum; - var subscriptions = GetAllSubscriptions(0, 0, - forumTopic.Id, 0, int.MaxValue); + var subscriptions = GetAllSubscriptions(0, 0, forumTopic.Id, 0, int.MaxValue); var languageId = _workContext.WorkingLanguage.Id; - int friendlyTopicPageIndex = CalculateTopicPageIndex(forumPost.TopicId, - _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 10, - forumPost.Id) + 1; + int friendlyTopicPageIndex = CalculateTopicPageIndex(forumPost.TopicId, _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 10, forumPost.Id) + 1; foreach (ForumSubscription subscription in subscriptions) { @@ -884,8 +908,7 @@ public virtual void InsertPost(ForumPost forumPost, bool sendNotifications) if (!String.IsNullOrEmpty(subscription.Customer.Email)) { - _workflowMessageService.SendNewForumPostMessage(subscription.Customer, forumPost, - forumTopic, forum, friendlyTopicPageIndex, languageId); + _workflowMessageService.SendNewForumPostMessage(subscription.Customer, forumPost, forumTopic, forum, friendlyTopicPageIndex, languageId); } } } @@ -1092,22 +1115,23 @@ public virtual ForumSubscription GetSubscriptionById(int forumSubscriptionId) /// Page index /// Page size /// Forum subscriptions - public virtual IPagedList GetAllSubscriptions(int customerId, int forumId, - int topicId, int pageIndex, int pageSize) + public virtual IPagedList GetAllSubscriptions(int customerId, int forumId, int topicId, int pageIndex, int pageSize) { - var fsQuery = from fs in _forumSubscriptionRepository.Table - join c in _customerRepository.Table on fs.CustomerId equals c.Id - where - (customerId == 0 || fs.CustomerId == customerId) && - (forumId == 0 || fs.ForumId == forumId) && - (topicId == 0 || fs.TopicId == topicId) && - (c.Active && !c.Deleted) - select fs.SubscriptionGuid; - - var query = from fs in _forumSubscriptionRepository.Table - where fsQuery.Contains(fs.SubscriptionGuid) - orderby fs.CreatedOnUtc descending, fs.SubscriptionGuid descending - select fs; + var fsQuery = + from fs in _forumSubscriptionRepository.Table + join c in _customerRepository.Table on fs.CustomerId equals c.Id + where + (customerId == 0 || fs.CustomerId == customerId) && + (forumId == 0 || fs.ForumId == forumId) && + (topicId == 0 || fs.TopicId == topicId) && + (c.Active && !c.Deleted) + select fs.SubscriptionGuid; + + var query = + from fs in _forumSubscriptionRepository.Table + where fsQuery.Contains(fs.SubscriptionGuid) + orderby fs.CreatedOnUtc descending, fs.SubscriptionGuid descending + select fs; var forumSubscriptions = new PagedList(query, pageIndex, pageSize); return forumSubscriptions; @@ -1438,8 +1462,7 @@ public virtual bool IsCustomerAllowedToSubscribe(Customer customer) public virtual int CalculateTopicPageIndex(int forumTopicId, int pageSize, int postId) { int pageIndex = 0; - var forumPosts = GetAllPosts(forumTopicId, 0, - string.Empty, true, 0, int.MaxValue); + var forumPosts = GetAllPosts(forumTopicId, 0, string.Empty, true, 0, int.MaxValue); for (int i = 0; i < forumPosts.TotalCount; i++) { @@ -1454,6 +1477,7 @@ public virtual int CalculateTopicPageIndex(int forumTopicId, int pageSize, int p return pageIndex; } - #endregion + + #endregion } } diff --git a/src/Libraries/SmartStore.Services/Forums/IForumService.cs b/src/Libraries/SmartStore.Services/Forums/IForumService.cs index a0de486d1c..46e0f2f428 100644 --- a/src/Libraries/SmartStore.Services/Forums/IForumService.cs +++ b/src/Libraries/SmartStore.Services/Forums/IForumService.cs @@ -27,7 +27,7 @@ public partial interface IForumService /// Gets all forum groups /// /// Forum groups - IList GetAllForumGroups(); + IList GetAllForumGroups(bool showHidden = false); /// /// Inserts a forum group @@ -105,9 +105,7 @@ public partial interface IForumService /// Page index /// Page size /// Forum Topics - IPagedList GetAllTopics(int forumId, - int customerId, string keywords, ForumSearchType searchType, - int limitDays, int pageIndex, int pageSize); + IPagedList GetAllTopics(int forumId, int customerId, string keywords, ForumSearchType searchType, int limitDays, int pageIndex, int pageSize); /// /// Gets active forum topics diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs index 6c71ef3dcd..1f59f64144 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs @@ -2,10 +2,12 @@ using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Forums; +using SmartStore.Core.Domain.Forums; +using SmartStore.Services; using SmartStore.Services.Forums; using SmartStore.Services.Helpers; -using SmartStore.Services.Localization; using SmartStore.Services.Security; +using SmartStore.Services.Stores; using SmartStore.Web.Framework.Controllers; namespace SmartStore.Admin.Controllers @@ -14,20 +16,51 @@ namespace SmartStore.Admin.Controllers public class ForumController : AdminControllerBase { private readonly IForumService _forumService; + private readonly ICommonServices _commonServices; private readonly IDateTimeHelper _dateTimeHelper; - private readonly ILocalizationService _localizationService; - private readonly IPermissionService _permissionService; + private readonly IStoreMappingService _storeMappingService; public ForumController(IForumService forumService, - IDateTimeHelper dateTimeHelper, ILocalizationService localizationService, - IPermissionService permissionService) + ICommonServices commonServices, + IDateTimeHelper dateTimeHelper, + IStoreMappingService storeMappingService) { - this._forumService = forumService; - this._dateTimeHelper = dateTimeHelper; - this._localizationService = localizationService; - this._permissionService = permissionService; + _forumService = forumService; + _commonServices = commonServices; + _dateTimeHelper = dateTimeHelper; + _storeMappingService = storeMappingService; } + #region Utilities + + [NonAction] + private void PrepareForumGroupModel(ForumGroupModel model, ForumGroup forumGroup, bool excludeProperties) + { + if (model == null) + throw new ArgumentNullException("model"); + + var allStores = _commonServices.StoreService.GetAllStores(); + + model.AvailableStores = allStores.Select(s => s.ToModel()).ToList(); + + if (forumGroup != null) + { + model.CreatedOn = _dateTimeHelper.ConvertToUserTime(forumGroup.CreatedOnUtc, DateTimeKind.Utc); + } + + if (!excludeProperties) + { + if (forumGroup != null) + model.SelectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(forumGroup); + else + model.SelectedStoreIds = new int[0]; + } + + ViewBag.StoreCount = allStores.Count; + } + + #endregion + #region List public ActionResult Index() @@ -37,23 +70,27 @@ public ActionResult Index() public ActionResult List() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); - var forumGroupsModel = _forumService.GetAllForumGroups() + var forumGroupsModel = _forumService.GetAllForumGroups(true) .Select(fg => { var forumGroupModel = fg.ToModel(); - forumGroupModel.CreatedOn = _dateTimeHelper.ConvertToUserTime(fg.CreatedOnUtc, DateTimeKind.Utc); + + PrepareForumGroupModel(forumGroupModel, fg, false); + foreach (var f in fg.Forums.OrderBy(x=>x.DisplayOrder)) { var forumModel = f.ToModel(); forumModel.CreatedOn = _dateTimeHelper.ConvertToUserTime(f.CreatedOnUtc, DateTimeKind.Utc); + forumGroupModel.ForumModels.Add(forumModel); } return forumGroupModel; }) .ToList(); + return View(forumGroupsModel); } @@ -63,40 +100,52 @@ public ActionResult List() public ActionResult CreateForumGroup() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); - return View(new ForumGroupModel { DisplayOrder = 1 }); + var model = new ForumGroupModel { DisplayOrder = 1 }; + + PrepareForumGroupModel(model, null, false); + + return View(model); } [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult CreateForumGroup(ForumGroupModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); if (ModelState.IsValid) { - var forumGroup = model.ToEntity(); - forumGroup.CreatedOnUtc = DateTime.UtcNow; - forumGroup.UpdatedOnUtc = DateTime.UtcNow; + var utcNow = DateTime.UtcNow; + var forumGroup = model.ToEntity(); + forumGroup.CreatedOnUtc = utcNow; + forumGroup.UpdatedOnUtc = utcNow; + _forumService.InsertForumGroup(forumGroup); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.ForumGroup.Added")); + _storeMappingService.SaveStoreMappings(forumGroup, model.SelectedStoreIds); + + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Added")); + return continueEditing ? RedirectToAction("EditForumGroup", new { forumGroup.Id }) : RedirectToAction("List"); } //If we got this far, something failed, redisplay form + + PrepareForumGroupModel(model, null, true); + return View(model); } public ActionResult CreateForum() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var model = new ForumModel(); - foreach (var forumGroup in _forumService.GetAllForumGroups()) + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); model.ForumGroups.Add(forumGroupModel); @@ -108,7 +157,7 @@ public ActionResult CreateForum() [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult CreateForum(ForumModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); if (ModelState.IsValid) @@ -118,12 +167,12 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing) forum.UpdatedOnUtc = DateTime.UtcNow; _forumService.InsertForum(forum); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.Forum.Added")); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Added")); return continueEditing ? RedirectToAction("EditForum", new { forum.Id }) : RedirectToAction("List"); } //If we got this far, something failed, redisplay form - foreach (var forumGroup in _forumService.GetAllForumGroups()) + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); model.ForumGroups.Add(forumGroupModel); @@ -137,55 +186,62 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing) public ActionResult EditForumGroup(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forumGroup = _forumService.GetForumGroupById(id); if (forumGroup == null) - //No forum group found with the specified id return RedirectToAction("List"); var model = forumGroup.ToModel(); + + PrepareForumGroupModel(model, forumGroup, false); + return View(model); } [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult EditForumGroup(ForumGroupModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forumGroup = _forumService.GetForumGroupById(model.Id); if (forumGroup == null) - //No forum group found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) { forumGroup = model.ToEntity(forumGroup); forumGroup.UpdatedOnUtc = DateTime.UtcNow; + _forumService.UpdateForumGroup(forumGroup); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.ForumGroup.Updated")); + _storeMappingService.SaveStoreMappings(forumGroup, model.SelectedStoreIds); + + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Updated")); + return continueEditing ? RedirectToAction("EditForumGroup", forumGroup.Id) : RedirectToAction("List"); } //If we got this far, something failed, redisplay form + + PrepareForumGroupModel(model, forumGroup, true); + return View(model); } public ActionResult EditForum(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forum = _forumService.GetForumById(id); if (forum == null) - //No forum found with the specified id return RedirectToAction("List"); var model = forum.ToModel(); - foreach (var forumGroup in _forumService.GetAllForumGroups()) + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); model.ForumGroups.Add(forumGroupModel); @@ -196,12 +252,11 @@ public ActionResult EditForum(int id) [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult EditForum(ForumModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forum = _forumService.GetForumById(model.Id); if (forum == null) - //No forum found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) @@ -210,12 +265,12 @@ public ActionResult EditForum(ForumModel model, bool continueEditing) forum.UpdatedOnUtc = DateTime.UtcNow; _forumService.UpdateForum(forum); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.Forum.Updated")); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Updated")); return continueEditing ? RedirectToAction("EditForum", forum.Id) : RedirectToAction("List"); } //If we got this far, something failed, redisplay form - foreach (var forumGroup in _forumService.GetAllForumGroups()) + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); model.ForumGroups.Add(forumGroupModel); @@ -230,34 +285,32 @@ public ActionResult EditForum(ForumModel model, bool continueEditing) [HttpPost] public ActionResult DeleteForumGroup(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forumGroup = _forumService.GetForumGroupById(id); if (forumGroup == null) - //No forum group found with the specified id return RedirectToAction("List"); _forumService.DeleteForumGroup(forumGroup); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.ForumGroup.Deleted")); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Deleted")); return RedirectToAction("List"); } [HttpPost] public ActionResult DeleteForum(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageForums)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forum = _forumService.GetForumById(id); if (forum == null) - //No forum found with the specified id return RedirectToAction("List"); _forumService.DeleteForum(forum); - NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Forums.Forum.Deleted")); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Deleted")); return RedirectToAction("List"); } diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index f65a1d470d..283c785f4f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -412,6 +412,8 @@ public void Execute() //forums Mapper.CreateMap() .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) + .ForMember(dest => dest.AvailableStores, mo => mo.Ignore()) + .ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore()) .ForMember(dest => dest.ForumModels, mo => mo.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.CreatedOnUtc, mo => mo.Ignore()) diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs index 825a2dc718..fc6a25d15f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Web.Mvc; using FluentValidation.Attributes; +using SmartStore.Admin.Models.Stores; using SmartStore.Admin.Validators.Forums; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Mvc; @@ -29,6 +30,13 @@ public ForumGroupModel() [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.CreatedOn")] public DateTime CreatedOn { get; set; } + + [SmartResourceDisplayName("Admin.Common.Store.LimitedTo")] + public bool LimitedToStores { get; set; } + + [SmartResourceDisplayName("Admin.Common.Store.AvailableFor")] + public List AvailableStores { get; set; } + public int[] SelectedStoreIds { get; set; } //use ForumModel public IList ForumModels { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Forum/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Forum/List.cshtml index 7609a604b3..56682a81bb 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Forum/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Forum/List.cshtml @@ -1,7 +1,6 @@ @model IEnumerable @using Telerik.Web.Mvc.UI; @{ - //page title ViewBag.Title = T("Admin.ContentManagement.Forums.Manage").Text; }
@@ -26,8 +25,17 @@ .Template(x => Html.ActionLink(x.Name, "EditForumGroup", new { id = x.Id })) .ClientTemplate("\"><#= Name #>"); - columns.Bound(x => x.DisplayOrder).Width(150).Centered(); - columns.Bound(x => x.CreatedOn).Width(200); + columns.Bound(x => x.DisplayOrder) + .Width(150) + .Centered(); + columns.Bound(x => x.LimitedToStores) + .Template(item => @Html.SymbolForBool(item.LimitedToStores)) + .ClientTemplate(@Html.SymbolForBool("LimitedToStores")) + .Centered() + .Width(100) + .Hidden(ViewBag.StoreCount <= 1); + columns.Bound(x => x.CreatedOn) + .Width(200); columns.Bound(x => x.Id) .Width(50) .Centered() diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml index 376faad25c..e6d13d8f57 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml @@ -4,32 +4,89 @@ @Html.ValidationSummary(true) @Html.HiddenFor(model => model.Id) - - - - - - - - - - - - - -
- @Html.SmartLabelFor(model => model.Name) - - @Html.EditorFor(model => model.Name) - @Html.ValidationMessageFor(model => model.Name) -
- @Html.SmartLabelFor(model => model.Description) - - @Html.TextAreaFor(model => model.Description) - @Html.ValidationMessageFor(model => model.Description) -
- @Html.SmartLabelFor(model => model.DisplayOrder) - - @Html.EditorFor(model => model.DisplayOrder) - @Html.ValidationMessageFor(model => model.DisplayOrder) -
+ +@Html.SmartStore().TabStrip().Name("forumgroup-edit").Items(x => +{ + x.Add().Text(T("Admin.Common.General").Text).Content(TabInfo()).Selected(true); + x.Add().Text(T("Admin.Common.Stores").Text).Content(TabStores()); + + //generate an event + EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "forumgroup-edit", this.Html, this.Model)); +}) + +@helper TabInfo() +{ + + + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Name) + + @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ @Html.SmartLabelFor(model => model.Description) + + @Html.TextAreaFor(model => model.Description) + @Html.ValidationMessageFor(model => model.Description) +
+ @Html.SmartLabelFor(model => model.DisplayOrder) + + @Html.EditorFor(model => model.DisplayOrder) + @Html.ValidationMessageFor(model => model.DisplayOrder) +
+} + +@helper TabStores() +{ + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.LimitedToStores) + + @Html.EditorFor(model => model.LimitedToStores) + @Html.ValidationMessageFor(model => model.LimitedToStores) +
+ @Html.SmartLabelFor(model => model.AvailableStores) + + @if (Model.AvailableStores != null && Model.AvailableStores.Count > 0) + { + foreach (var store in Model.AvailableStores) + { + + } + } + else + { +
@T("Admin.Configuration.Stores.NoStoresDefined")
+ } +
+} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs index 25390a8c2b..0a3643f1e7 100644 --- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs @@ -4,7 +4,6 @@ using System.ServiceModel.Syndication; using System.Web.Mvc; using SmartStore.Core; -using SmartStore.Core.Domain; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Forums; using SmartStore.Core.Domain.Media; @@ -77,7 +76,7 @@ public BoardsController(IForumService forumService, [NonAction] protected ForumTopicRowModel PrepareForumTopicRowModel(ForumTopic topic) { - var topicModel = new ForumTopicRowModel() + var topicModel = new ForumTopicRowModel { Id = topic.Id, Subject = topic.Subject, @@ -102,7 +101,7 @@ protected ForumTopicRowModel PrepareForumTopicRowModel(ForumTopic topic) [NonAction] protected ForumRowModel PrepareForumRowModel(Forum forum) { - var forumModel = new ForumRowModel() + var forumModel = new ForumRowModel { Id = forum.Id, Name = forum.Name, @@ -118,14 +117,16 @@ protected ForumRowModel PrepareForumRowModel(Forum forum) [NonAction] protected ForumGroupModel PrepareForumGroupModel(ForumGroup forumGroup) { - var forumGroupModel = new ForumGroupModel() + var forumGroupModel = new ForumGroupModel { Id = forumGroup.Id, Name = forumGroup.Name, SeName = forumGroup.GetSeName(), Description = forumGroup.Description, }; + var forums = _forumService.GetAllForumsByGroupId(forumGroup.Id); + foreach (var forum in forums) { var forumModel = PrepareForumRowModel(forum); @@ -195,10 +196,11 @@ public ActionResult Index() var forumGroups = _forumService.GetAllForumGroups(); - var model = new BoardsIndexModel() + var model = new BoardsIndexModel { CurrentTime = _dateTimeHelper.ConvertToUserTime(DateTime.UtcNow) }; + foreach (var forumGroup in forumGroups) { @@ -222,11 +224,13 @@ public ActionResult ActiveDiscussionsSmall() return Content(""); var model = new ActiveDiscussionsModel(); - foreach (var topic in topics) + + foreach (var topic in topics) { var topicModel = PrepareForumTopicRowModel(topic); model.ForumTopics.Add(topicModel); } + model.ViewAllLinkEnabled = true; model.ActiveDiscussionsFeedEnabled = _forumSettings.ActiveDiscussionsFeedEnabled; model.PostsPageSize = _forumSettings.PostsPageSize; @@ -245,14 +249,17 @@ public ActionResult ActiveDiscussions(int forumId = 0) var topics = _forumService.GetActiveTopics(forumId, topicLimit); var model = new ActiveDiscussionsModel(); + foreach (var topic in topics) { var topicModel = PrepareForumTopicRowModel(topic); model.ForumTopics.Add(topicModel); } + model.ViewAllLinkEnabled = false; model.ActiveDiscussionsFeedEnabled = _forumSettings.ActiveDiscussionsFeedEnabled; model.PostsPageSize = _forumSettings.PostsPageSize; + return View(model); } @@ -276,11 +283,11 @@ public ActionResult ActiveDiscussionsRss(int forumId = 0) var feedDescription = _localizationService.GetResource("Forum.ActiveDiscussionsFeedDescription"); var feed = new SyndicationFeed( - string.Format(feedTitle, _storeContext.CurrentStore.Name), - feedDescription, - new Uri(url), - "ActiveDiscussionsRSS", - DateTime.UtcNow); + string.Format(feedTitle, _storeContext.CurrentStore.Name), + feedDescription, + new Uri(url), + "ActiveDiscussionsRSS", + DateTime.UtcNow); var items = new List(); @@ -351,16 +358,18 @@ public ActionResult Forum(int id, int page = 1) } } - var topics = _forumService.GetAllTopics(forum.Id, 0, string.Empty, - ForumSearchType.All, 0, (page - 1), pageSize); + var topics = _forumService.GetAllTopics(forum.Id, 0, string.Empty, ForumSearchType.All, 0, (page - 1), pageSize); + model.TopicPageSize = topics.PageSize; model.TopicTotalRecords = topics.TotalCount; model.TopicPageIndex = topics.PageIndex; + foreach (var topic in topics) { var topicModel = PrepareForumTopicRowModel(topic); model.ForumTopics.Add(topicModel); } + model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer); model.ForumFeedsEnabled = _forumSettings.ForumFeedsEnabled; model.PostsPageSize = _forumSettings.PostsPageSize; @@ -388,8 +397,7 @@ public ActionResult ForumRss(int id) if (forum != null) { //Order by newest topic posts & limit the number of topics to return - var topics = _forumService.GetAllTopics(forum.Id, 0, string.Empty, - ForumSearchType.All, 0, 0, topicLimit); + var topics = _forumService.GetAllTopics(forum.Id, 0, string.Empty, ForumSearchType.All, 0, 0, topicLimit); string url = Url.Action("ForumRSS", null, new { id = forum.Id }, "http"); @@ -397,11 +405,11 @@ public ActionResult ForumRss(int id) var feedDescription = _localizationService.GetResource("Forum.ForumFeedDescription"); var feed = new SyndicationFeed( - string.Format(feedTitle, _storeContext.CurrentStore.Name, forum.Name), - feedDescription, - new Uri(url), - string.Format("ForumRSS:{0}", forum.Id), - DateTime.UtcNow); + string.Format(feedTitle, _storeContext.CurrentStore.Name, forum.Name), + feedDescription, + new Uri(url), + string.Format("ForumRSS:{0}", forum.Id), + DateTime.UtcNow); var items = new List(); @@ -444,18 +452,18 @@ public ActionResult ForumWatch(int id) return Json(new { Subscribed = subscribed, Text = returnText, Error = true }); } - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - forum.Id, 0, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, forum.Id, 0, 0, 1).FirstOrDefault(); if (forumSubscription == null) { - forumSubscription = new ForumSubscription() + forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, ForumId = forum.Id, CreatedOnUtc = DateTime.UtcNow }; + _forumService.InsertSubscription(forumSubscription); subscribed = true; returnText = unwatchTopic; @@ -481,8 +489,8 @@ public ActionResult Topic(int id, int page = 1) if (forumTopic != null) { //load posts - var posts = _forumService.GetAllPosts(forumTopic.Id, 0, string.Empty, - page - 1, _forumSettings.PostsPageSize); + var posts = _forumService.GetAllPosts(forumTopic.Id, 0, string.Empty, page - 1, _forumSettings.PostsPageSize); + // if no posts area loaded, redirect to the first page if (posts.Count == 0 && page > 1) { @@ -508,19 +516,20 @@ public ActionResult Topic(int id, int page = 1) { model.WatchTopicText = _localizationService.GetResource("Forum.WatchTopic"); - var forumTopicSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumTopic.Id, 0, 1).FirstOrDefault(); + var forumTopicSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault(); if (forumTopicSubscription != null) { model.WatchTopicText = _localizationService.GetResource("Forum.UnwatchTopic"); } } - model.PostsPageIndex = posts.PageIndex; + + model.PostsPageIndex = posts.PageIndex; model.PostsPageSize = posts.PageSize; model.PostsTotalRecords = posts.TotalCount; + foreach (var post in posts) { - var forumPostModel = new ForumPostModel() + var forumPostModel = new ForumPostModel { Id = post.Id, ForumTopicId = post.TopicId, @@ -541,12 +550,14 @@ public ActionResult Topic(int id, int page = 1) SignaturesEnabled = _forumSettings.SignaturesEnabled, FormattedSignature = post.Customer.GetAttribute(SystemCustomerAttributeNames.Signature).FormatForumSignatureText(), }; + //created on string if (_forumSettings.RelativeDateTimeFormattingEnabled) forumPostModel.PostCreatedOnStr = post.CreatedOnUtc.RelativeFormat(true, "f"); else forumPostModel.PostCreatedOnStr =_dateTimeHelper.ConvertToUserTime(post.CreatedOnUtc, DateTimeKind.Utc).ToString("f"); - //avatar + + //avatar if (_customerSettings.AllowCustomersToUploadAvatars) { var customer = post.Customer; @@ -555,6 +566,7 @@ public ActionResult Topic(int id, int page = 1) avatarUrl = _pictureService.GetDefaultPictureUrl(_mediaSettings.AvatarPictureSize, PictureType.Avatar); forumPostModel.CustomerAvatarUrl = avatarUrl; } + //location forumPostModel.ShowCustomersLocation = _customerSettings.ShowCustomersLocation; if (_customerSettings.ShowCustomersLocation) @@ -594,18 +606,18 @@ public ActionResult TopicWatch(int id) return Json(new { Subscribed = subscribed, Text = returnText, Error = true }); } - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumTopic.Id, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault(); if (forumSubscription == null) { - forumSubscription = new ForumSubscription() + forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, TopicId = forumTopic.Id, CreatedOnUtc = DateTime.UtcNow }; + _forumService.InsertSubscription(forumSubscription); subscribed = true; returnText = unwatchTopic; @@ -638,6 +650,7 @@ public ActionResult TopicMove(int id) model.Id = forumTopic.Id; model.TopicSeName = forumTopic.GetSeName(); model.ForumSelected = forumTopic.ForumId; + return View(model); } @@ -681,6 +694,7 @@ public ActionResult TopicDelete(int id) { return new HttpUnauthorizedResult(); } + var forum = _forumService.GetForumById(forumTopic.ForumId); _forumService.DeleteTopic(forumTopic); @@ -724,6 +738,7 @@ public ActionResult TopicCreate(int id) model.TopicPriorities = ForumTopicTypesList(); model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer); model.Subscribed = false; + return View(model); } @@ -767,18 +782,16 @@ public ActionResult TopicCreate(EditForumTopicModel model) } var topicType = ForumTopicType.Normal; - + var nowUtc = DateTime.UtcNow; string ipAddress = _webHelper.GetCurrentIpAddress(); - var nowUtc = DateTime.UtcNow; - if (_forumService.IsCustomerAllowedToSetTopicPriority(_workContext.CurrentCustomer)) { topicType = (ForumTopicType) Enum.ToObject(typeof (ForumTopicType), model.TopicTypeId); } //forum topic - var forumTopic = new ForumTopic() + var forumTopic = new ForumTopic { ForumId = forum.Id, CustomerId = _workContext.CurrentCustomer.Id, @@ -787,10 +800,11 @@ public ActionResult TopicCreate(EditForumTopicModel model) CreatedOnUtc = nowUtc, UpdatedOnUtc = nowUtc }; + _forumService.InsertTopic(forumTopic, true); //forum post - var forumPost = new ForumPost() + var forumPost = new ForumPost { TopicId = forumTopic.Id, CustomerId = _workContext.CurrentCustomer.Id, @@ -799,6 +813,7 @@ public ActionResult TopicCreate(EditForumTopicModel model) CreatedOnUtc = nowUtc, UpdatedOnUtc = nowUtc }; + _forumService.InsertPost(forumPost, false); //update forum topic @@ -807,6 +822,7 @@ public ActionResult TopicCreate(EditForumTopicModel model) forumTopic.LastPostCustomerId = forumPost.CustomerId; forumTopic.LastPostTime = forumPost.CreatedOnUtc; forumTopic.UpdatedOnUtc = nowUtc; + _forumService.UpdateTopic(forumTopic); //subscription @@ -814,7 +830,7 @@ public ActionResult TopicCreate(EditForumTopicModel model) { if (model.Subscribed) { - var forumSubscription = new ForumSubscription() + var forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, @@ -873,12 +889,13 @@ public ActionResult TopicEdit(int id) return RedirectToRoute("Boards"); } + var firstPost = forumTopic.GetFirstPost(_forumService); var model = new EditForumTopicModel(); + model.IsEdit = true; model.TopicPriorities = ForumTopicTypesList(); model.ForumName = forum.Name; model.ForumSeName = forum.GetSeName(); - var firstPost = forumTopic.GetFirstPost(_forumService); model.Text = firstPost.Text; model.Subject = forumTopic.Subject; model.TopicTypeId = forumTopic.TopicTypeId; @@ -892,8 +909,7 @@ public ActionResult TopicEdit(int id) //subscription if (model.IsCustomerAllowedToSubscribe) { - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumTopic.Id, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault(); model.Subscribed = forumSubscription != null; } @@ -959,6 +975,7 @@ public ActionResult TopicEdit(EditForumTopicModel model) forumTopic.TopicTypeId = (int) topicType; forumTopic.Subject = subject; forumTopic.UpdatedOnUtc = nowUtc; + _forumService.UpdateTopic(forumTopic); //forum post @@ -987,14 +1004,13 @@ public ActionResult TopicEdit(EditForumTopicModel model) //subscription if (_forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer)) { - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumTopic.Id, 0, 1).FirstOrDefault - (); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault(); + if (model.Subscribed) { if (forumSubscription == null) { - forumSubscription = new ForumSubscription() + forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, @@ -1100,7 +1116,7 @@ public ActionResult PostCreate(int id, int? quote) return RedirectToRoute("Boards"); } - var model = new EditForumPostModel() + var model = new EditForumPostModel { Id = 0, ForumTopicId = forumTopic.Id, @@ -1172,11 +1188,10 @@ public ActionResult PostCreate(EditForumPostModel model) if (maxPostLength > 0 && text.Length > maxPostLength) text = text.Substring(0, maxPostLength); + var nowUtc = DateTime.UtcNow; string ipAddress = _webHelper.GetCurrentIpAddress(); - DateTime nowUtc = DateTime.UtcNow; - - var forumPost = new ForumPost() + var forumPost = new ForumPost { TopicId = forumTopic.Id, CustomerId = _workContext.CurrentCustomer.Id, @@ -1185,18 +1200,18 @@ public ActionResult PostCreate(EditForumPostModel model) CreatedOnUtc = nowUtc, UpdatedOnUtc = nowUtc }; + _forumService.InsertPost(forumPost, true); //subscription if (_forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer)) { - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumPost.TopicId, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumPost.TopicId, 0, 1).FirstOrDefault(); if (model.Subscribed) { if (forumSubscription == null) { - forumSubscription = new ForumSubscription() + forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, @@ -1222,6 +1237,7 @@ public ActionResult PostCreate(EditForumPostModel model) int pageIndex = (_forumService.CalculateTopicPageIndex(forumPost.TopicId, pageSize, forumPost.Id) + 1); var url = string.Empty; + if (pageIndex > 1) { url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName(), page = pageIndex }); @@ -1230,6 +1246,7 @@ public ActionResult PostCreate(EditForumPostModel model) { url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName() }); } + return Redirect(string.Format("{0}#{1}", url, forumPost.Id)); } catch (Exception ex) @@ -1284,7 +1301,7 @@ public ActionResult PostEdit(int id) } - var model = new EditForumPostModel() + var model = new EditForumPostModel { Id = forumPost.Id, ForumTopicId = forumTopic.Id, @@ -1301,8 +1318,7 @@ public ActionResult PostEdit(int id) //subscription if (model.IsCustomerAllowedToSubscribe) { - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumTopic.Id, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault(); model.Subscribed = forumSubscription != null; } @@ -1345,7 +1361,7 @@ public ActionResult PostEdit(EditForumPostModel model) { try { - DateTime nowUtc = DateTime.UtcNow; + var nowUtc = DateTime.UtcNow; var text = model.Text; var maxPostLength = _forumSettings.PostMaxLength; @@ -1356,24 +1372,25 @@ public ActionResult PostEdit(EditForumPostModel model) forumPost.UpdatedOnUtc = nowUtc; forumPost.Text = text; + _forumService.UpdatePost(forumPost); //subscription if (_forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer)) { - var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, - 0, forumPost.TopicId, 0, 1).FirstOrDefault(); + var forumSubscription = _forumService.GetAllSubscriptions(_workContext.CurrentCustomer.Id, 0, forumPost.TopicId, 0, 1).FirstOrDefault(); if (model.Subscribed) { if (forumSubscription == null) { - forumSubscription = new ForumSubscription() + forumSubscription = new ForumSubscription { SubscriptionGuid = Guid.NewGuid(), CustomerId = _workContext.CurrentCustomer.Id, TopicId = forumPost.TopicId, CreatedOnUtc = nowUtc }; + _forumService.InsertSubscription(forumSubscription); } } @@ -1393,6 +1410,7 @@ public ActionResult PostEdit(EditForumPostModel model) } int pageIndex = (_forumService.CalculateTopicPageIndex(forumPost.TopicId, pageSize, forumPost.Id) + 1); var url = string.Empty; + if (pageIndex > 1) { url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName(), page = pageIndex }); @@ -1401,6 +1419,7 @@ public ActionResult PostEdit(EditForumPostModel model) { url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName() }); } + return Redirect(string.Format("{0}#{1}", url, forumPost.Id)); } catch (Exception ex) @@ -1422,8 +1441,7 @@ public ActionResult PostEdit(EditForumPostModel model) return View(model); } - public ActionResult Search(string searchterms, bool? adv, string forumId, - string within, string limitDays, int page = 1) + public ActionResult Search(string searchterms, bool? adv, string forumId, string within, string limitDays, int page = 1) { if (!_forumSettings.ForumsEnabled) { @@ -1436,59 +1454,60 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, // Create the values for the "Limit results to previous" select list var limitList = new List - { - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.AllResults"), - Value = "0" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1day"), - Value = "1" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.7days"), - Value = "7" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.2weeks"), - Value = "14" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1month"), - Value = "30" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.3months"), - Value = "92" - }, - new SelectListItem - { - Text= _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.6months"), - Value = "183" - }, - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1year"), - Value = "365" - } - }; + { + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.AllResults"), + Value = "0" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1day"), + Value = "1" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.7days"), + Value = "7" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.2weeks"), + Value = "14" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1month"), + Value = "30" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.3months"), + Value = "92" + }, + new SelectListItem + { + Text= _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.6months"), + Value = "183" + }, + new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.LimitResultsToPrevious.1year"), + Value = "365" + } + }; + model.LimitList = limitList; // Create the values for the "Search in forum" select list var forumsSelectList = new List(); - forumsSelectList.Add( - new SelectListItem - { - Text = _localizationService.GetResource("Forum.Search.SearchInForum.All"), - Value = "0", - Selected = true, - }); + forumsSelectList.Add(new SelectListItem + { + Text = _localizationService.GetResource("Forum.Search.SearchInForum.All"), + Value = "0", + Selected = true, + }); + var separator = "--"; var forumGroups = _forumService.GetAllForumGroups(); foreach (var fg in forumGroups) @@ -1499,35 +1518,35 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, var forums = _forumService.GetAllForumsByGroupId(fg.Id); foreach (var f in forums) { - forumsSelectList.Add( - new SelectListItem - { - Text = string.Format("{0}{1}", separator, f.Name), - Value = f.Id.ToString() - }); + forumsSelectList.Add(new SelectListItem + { + Text = string.Format("{0}{1}", separator, f.Name), + Value = f.Id.ToString() + }); } } model.ForumList = forumsSelectList; // Create the values for "Search within" select list var withinList = new List - { - new SelectListItem - { - Value = ((int)ForumSearchType.All).ToString(), - Text = _localizationService.GetResource("Forum.Search.SearchWithin.All") - }, - new SelectListItem - { - Value = ((int)ForumSearchType.TopicTitlesOnly).ToString(), - Text = _localizationService.GetResource("Forum.Search.SearchWithin.TopicTitlesOnly") - }, - new SelectListItem - { - Value = ((int)ForumSearchType.PostTextOnly).ToString(), - Text = _localizationService.GetResource("Forum.Search.SearchWithin.PostTextOnly") - } - }; + { + new SelectListItem + { + Value = ((int)ForumSearchType.All).ToString(), + Text = _localizationService.GetResource("Forum.Search.SearchWithin.All") + }, + new SelectListItem + { + Value = ((int)ForumSearchType.TopicTitlesOnly).ToString(), + Text = _localizationService.GetResource("Forum.Search.SearchWithin.TopicTitlesOnly") + }, + new SelectListItem + { + Value = ((int)ForumSearchType.PostTextOnly).ToString(), + Text = _localizationService.GetResource("Forum.Search.SearchWithin.PostTextOnly") + } + }; + model.WithinList = withinList; int forumIdSelected; @@ -1558,8 +1577,7 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, if (searchterms.Length < searchTermMinimumLength) { - throw new SmartException(string.Format(_localizationService.GetResource("Forum.SearchTermMinimumLengthIsNCharacters"), - searchTermMinimumLength)); + throw new SmartException(string.Format(_localizationService.GetResource("Forum.SearchTermMinimumLengthIsNCharacters"), searchTermMinimumLength)); } ForumSearchType searchWithin = 0; @@ -1575,11 +1593,12 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, pageSize = _forumSettings.SearchResultsPageSize; } - var topics = _forumService.GetAllTopics(forumIdSelected, 0, searchterms, searchWithin, - limitResultsToPrevious, page - 1, pageSize); + var topics = _forumService.GetAllTopics(forumIdSelected, 0, searchterms, searchWithin, limitResultsToPrevious, page - 1, pageSize); + model.TopicPageSize = topics.PageSize; model.TopicTotalRecords = topics.TotalCount; model.TopicPageIndex = topics.PageIndex; + foreach (var topic in topics) { var topicModel = PrepareForumTopicRowModel(topic); @@ -1673,5 +1692,4 @@ public ActionResult ForumBreadcrumb(int? forumGroupId, int? forumId, int? forumT #endregion } - } From 345f4426f0c2509525f9f212a7e463defe4fd10b Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 7 May 2015 16:00:52 +0200 Subject: [PATCH 0112/1256] Localized properties for forum groups --- changelog.md | 2 + .../Domain/Forums/ForumGroup.cs | 4 +- .../201505061813010_CountryMultistore.cs | 24 ++++++++- .../SmartStore.Services/Seo/SeoExtensions.cs | 16 ------ .../Controllers/ForumController.cs | 51 ++++++++++++++++-- .../Infrastructure/AutoMapperStartupTask.cs | 4 +- .../Models/Forums/ForumGroupModel.cs | 27 +++++++++- .../Forum/_CreateOrUpdateForumGroup.cshtml | 53 ++++++++++++++++++- .../Controllers/BoardsController.cs | 12 ++--- 9 files changed, 161 insertions(+), 32 deletions(-) diff --git a/changelog.md b/changelog.md index 704960aa82..287c5763cc 100644 --- a/changelog.md +++ b/changelog.md @@ -12,9 +12,11 @@ * Setting whether and how to display sub-categories on a category page (hide, above products, bottom of page) * Debitoor: Extend option "Book invoice if paid" to also (optionally) mail the invoice as a PDF * #508 Limit country settings to stores +* #205 Add multistore support for forums ### Improvements * PDF converter: first init is much faster now +* Localized properties for forum groups ### Bugfixes * PDF converter: fixed _QFont::setPixelSize_ bug diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs index 77022b7047..fc84ae983e 100644 --- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs +++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using SmartStore.Core.Domain.Localization; +using SmartStore.Core.Domain.Seo; using SmartStore.Core.Domain.Stores; namespace SmartStore.Core.Domain.Forums @@ -7,7 +9,7 @@ namespace SmartStore.Core.Domain.Forums /// /// Represents a forum group /// - public partial class ForumGroup : BaseEntity, IStoreMappingSupported + public partial class ForumGroup : BaseEntity, IStoreMappingSupported, ILocalizedEntity, ISlugSupported { private ICollection _forums; diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs index c701338fee..c067c886c9 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs @@ -2,8 +2,9 @@ namespace SmartStore.Data.Migrations { using System; using System.Data.Entity.Migrations; - - public partial class CountryMultistore : DbMigration + using SmartStore.Data.Setup; + + public partial class CountryMultistore : DbMigration, ILocaleResourcesProvider, IDataSeeder { public override void Up() { @@ -16,5 +17,24 @@ public override void Down() DropColumn("dbo.Forums_Group", "LimitedToStores"); DropColumn("dbo.Country", "LimitedToStores"); } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Admin.ContentManagement.Forums.ForumGroup.Fields.SeName", + "URL-Alias", + "URL-Alias", + "Set a search engine friendly page name e.g. 'the-best-forum' to make your page URL 'http://www.yourStore.com/the-best-forum'. Leave empty to generate it automatically based on the name of the forum group.", + "Legt einen Suchmaschinen-freundlichen Seitennamen fr die Forengruppe fest. 'Tolles Forum' resultiert bspw. in '~/tolles-forum'. Standard ist der Name der Forengruppe."); + } } } diff --git a/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs b/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs index ad1ccdb441..0c5e3e1699 100644 --- a/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs +++ b/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using SmartStore.Core; using SmartStore.Core.Domain.Blogs; using SmartStore.Core.Domain.Catalog; -using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Forums; using SmartStore.Core.Domain.News; using SmartStore.Core.Domain.Seo; @@ -79,19 +76,6 @@ public static string GetSeName(this NewsItem newsItem) #region Forum - /// - /// Gets ForumGroup SE (search engine) name - /// - /// ForumGroup - /// ForumGroup SE (search engine) name - public static string GetSeName(this ForumGroup forumGroup) - { - if (forumGroup == null) - throw new ArgumentNullException("forumGroup"); - string seName = GetSeName(forumGroup.Name); - return seName; - } - /// /// Gets Forum SE (search engine) name /// diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs index 1f59f64144..4b20161a69 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs @@ -6,7 +6,9 @@ using SmartStore.Services; using SmartStore.Services.Forums; using SmartStore.Services.Helpers; +using SmartStore.Services.Localization; using SmartStore.Services.Security; +using SmartStore.Services.Seo; using SmartStore.Services.Stores; using SmartStore.Web.Framework.Controllers; @@ -19,16 +21,25 @@ public class ForumController : AdminControllerBase private readonly ICommonServices _commonServices; private readonly IDateTimeHelper _dateTimeHelper; private readonly IStoreMappingService _storeMappingService; + private readonly ILanguageService _languageService; + private readonly ILocalizedEntityService _localizedEntityService; + private readonly IUrlRecordService _urlRecordService; public ForumController(IForumService forumService, ICommonServices commonServices, IDateTimeHelper dateTimeHelper, - IStoreMappingService storeMappingService) + IStoreMappingService storeMappingService, + ILanguageService languageService, + ILocalizedEntityService localizedEntityService, + IUrlRecordService urlRecordService) { _forumService = forumService; _commonServices = commonServices; _dateTimeHelper = dateTimeHelper; _storeMappingService = storeMappingService; + _languageService = languageService; + _localizedEntityService = localizedEntityService; + _urlRecordService = urlRecordService; } #region Utilities @@ -59,6 +70,19 @@ private void PrepareForumGroupModel(ForumGroupModel model, ForumGroup forumGroup ViewBag.StoreCount = allStores.Count; } + [NonAction] + private void UpdateLocales(ForumGroupModel model, ForumGroup forumGroup) + { + foreach (var localized in model.Locales) + { + _localizedEntityService.SaveLocalizedValue(forumGroup, x => x.Name, localized.Name, localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(forumGroup, x => x.Description, localized.Description, localized.LanguageId); + + var seName = forumGroup.ValidateSeName(localized.SeName, localized.Name, false, localized.LanguageId); + _urlRecordService.SaveSlug(forumGroup, seName, localized.LanguageId); + } + } + #endregion #region List @@ -105,6 +129,8 @@ public ActionResult CreateForumGroup() var model = new ForumGroupModel { DisplayOrder = 1 }; + AddLocales(_languageService, model.Locales); + PrepareForumGroupModel(model, null, false); return View(model); @@ -125,6 +151,11 @@ public ActionResult CreateForumGroup(ForumGroupModel model, bool continueEditing _forumService.InsertForumGroup(forumGroup); + model.SeName = forumGroup.ValidateSeName(model.SeName, forumGroup.Name, true); + _urlRecordService.SaveSlug(forumGroup, model.SeName, 0); + + UpdateLocales(model, forumGroup); + _storeMappingService.SaveStoreMappings(forumGroup, model.SelectedStoreIds); NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Added")); @@ -162,9 +193,11 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing) if (ModelState.IsValid) { + var utcNow = DateTime.UtcNow; var forum = model.ToEntity(); - forum.CreatedOnUtc = DateTime.UtcNow; - forum.UpdatedOnUtc = DateTime.UtcNow; + forum.CreatedOnUtc = utcNow; + forum.UpdatedOnUtc = utcNow; + _forumService.InsertForum(forum); NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Added")); @@ -195,6 +228,13 @@ public ActionResult EditForumGroup(int id) var model = forumGroup.ToModel(); + AddLocales(_languageService, model.Locales, (locale, languageId) => + { + locale.Name = forumGroup.GetLocalized(x => x.Name, languageId, false, false); + locale.Description = forumGroup.GetLocalized(x => x.Description, languageId, false, false); + locale.SeName = forumGroup.GetSeName(languageId, false, false); + }); + PrepareForumGroupModel(model, forumGroup, false); return View(model); @@ -217,6 +257,11 @@ public ActionResult EditForumGroup(ForumGroupModel model, bool continueEditing) _forumService.UpdateForumGroup(forumGroup); + model.SeName = forumGroup.ValidateSeName(model.SeName, forumGroup.Name, true); + _urlRecordService.SaveSlug(forumGroup, model.SeName, 0); + + UpdateLocales(model, forumGroup); + _storeMappingService.SaveStoreMappings(forumGroup, model.SelectedStoreIds); NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Updated")); diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index 283c785f4f..4ef685dcc3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -411,9 +411,11 @@ public void Execute() .ForMember(dest => dest.StoreId, mo => mo.Ignore()); //forums Mapper.CreateMap() - .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) + .ForMember(dest => dest.Locales, mo => mo.Ignore()) + .ForMember(dest => dest.SeName, mo => mo.MapFrom(src => src.GetSeName(0, true, false))) .ForMember(dest => dest.AvailableStores, mo => mo.Ignore()) .ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore()) + .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) .ForMember(dest => dest.ForumModels, mo => mo.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.CreatedOnUtc, mo => mo.Ignore()) diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs index fc6a25d15f..39a20675a4 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs @@ -5,22 +5,28 @@ using SmartStore.Admin.Models.Stores; using SmartStore.Admin.Validators.Forums; using SmartStore.Web.Framework; +using SmartStore.Web.Framework.Localization; using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Models.Forums { [Validator(typeof(ForumGroupValidator))] - public class ForumGroupModel : EntityModelBase + public class ForumGroupModel : EntityModelBase, ILocalizedModel { public ForumGroupModel() { ForumModels = new List(); + Locales = new List(); } [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.Name")] [AllowHtml] public string Name { get; set; } + [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.SeName")] + [AllowHtml] + public string SeName { get; set; } + [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.Description")] [AllowHtml] public string Description { get; set; } @@ -40,5 +46,24 @@ public ForumGroupModel() //use ForumModel public IList ForumModels { get; set; } + + public IList Locales { get; set; } } + + public class ForumGroupLocalizedModel : ILocalizedModelLocal + { + public int LanguageId { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.Name")] + [AllowHtml] + public string Name { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.SeName")] + [AllowHtml] + public string SeName { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.ForumGroup.Fields.Description")] + [AllowHtml] + public string Description { get; set; } + } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml index e6d13d8f57..611d9cef72 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml @@ -16,7 +16,43 @@ @helper TabInfo() { - + @(Html.LocalizedEditor("forumgroup-localized", + @
+ + + + + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Locales[item].Name) + + @Html.EditorFor(model => Model.Locales[item].Name) + @Html.ValidationMessageFor(model => model.Locales[item].Name) +
+ @Html.SmartLabelFor(model => model.Locales[item].SeName) + + @Html.EditorFor(model => model.Locales[item].SeName) + @Html.ValidationMessageFor(model => model.Locales[item].SeName) +
+ @Html.SmartLabelFor(model => model.Locales[item].Description) + + @Html.TextAreaFor(model => model.Locales[item].Description, new { @class = "input-large" }) + @Html.ValidationMessageFor(model => model.Locales[item].Description) +
+ @Html.HiddenFor(model => model.Locales[item].LanguageId) +
+ , + @ + + + + +
@Html.SmartLabelFor(model => model.Name) @@ -26,15 +62,28 @@ @Html.ValidationMessageFor(model => model.Name)
+ @Html.SmartLabelFor(model => model.SeName) + + @Html.EditorFor(x => x.SeName) + @Html.ValidationMessageFor(model => model.SeName) +
@Html.SmartLabelFor(model => model.Description) - @Html.TextAreaFor(model => model.Description) + @Html.TextAreaFor(model => model.Description, new { @class = "input-large" }) @Html.ValidationMessageFor(model => model.Description)
+ )) + + } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml index 9108c6a380..ea9c2f4f27 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml @@ -471,8 +471,8 @@ dialog.find('[name="Licenses[0].LicenseKey"]').focus(); }, 1000); - dialog.find('.btn-primary').click(function() { - e.preventDefault(); + dialog.find('.btn-primary').click(function(e2) { + e2.preventDefault(); if (confirm('@T("Admin.Configuration.Plugins.ConfirmLicensing")')) { dialog.find('form:first').submit(); } From a95a3f0e462ee6b3d8731c7aaf38dd4971e826ad Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 11 May 2015 10:18:56 +0200 Subject: [PATCH 0118/1256] Unit testing --- .../Orders/OrderTotalCalculationService.cs | 12 ++- .../Catalog/PriceFormatterTests.cs | 17 ++-- .../Helpers/DateTimeHelperTests.cs | 6 +- .../Orders/OrderProcessingServiceTests.cs | 33 ++++---- .../OrderTotalCalculationServiceTests.cs | 83 +++++++++---------- 5 files changed, 70 insertions(+), 81 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Orders/OrderTotalCalculationService.cs b/src/Libraries/SmartStore.Services/Orders/OrderTotalCalculationService.cs index 3de602a094..8beaa3da51 100644 --- a/src/Libraries/SmartStore.Services/Orders/OrderTotalCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Orders/OrderTotalCalculationService.cs @@ -9,7 +9,6 @@ using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Shipping; using SmartStore.Core.Domain.Tax; -using SmartStore.Core.Infrastructure; using SmartStore.Services.Catalog; using SmartStore.Services.Common; using SmartStore.Services.Discounts; @@ -36,11 +35,13 @@ public partial class OrderTotalCalculationService : IOrderTotalCalculationServic private readonly IDiscountService _discountService; private readonly IGiftCardService _giftCardService; private readonly IGenericAttributeService _genericAttributeService; + private readonly IProductAttributeParser _productAttributeParser; private readonly TaxSettings _taxSettings; private readonly RewardPointsSettings _rewardPointsSettings; private readonly ShippingSettings _shippingSettings; private readonly ShoppingCartSettings _shoppingCartSettings; private readonly CatalogSettings _catalogSettings; + #endregion #region Ctor @@ -73,6 +74,7 @@ public OrderTotalCalculationService(IWorkContext workContext, IDiscountService discountService, IGiftCardService giftCardService, IGenericAttributeService genericAttributeService, + IProductAttributeParser productAttributeParser, TaxSettings taxSettings, RewardPointsSettings rewardPointsSettings, ShippingSettings shippingSettings, @@ -89,6 +91,7 @@ public OrderTotalCalculationService(IWorkContext workContext, this._discountService = discountService; this._giftCardService = giftCardService; this._genericAttributeService = genericAttributeService; + this._productAttributeParser = productAttributeParser; this._taxSettings = taxSettings; this._rewardPointsSettings = rewardPointsSettings; this._shippingSettings = shippingSettings; @@ -186,12 +189,7 @@ public virtual void GetShoppingCartSubTotal(IList car decimal taxRate, sciSubTotal, sciExclTax, sciInclTax = decimal.Zero; - IProductAttributeParser productAttrParser; - if (EngineContext.Current.ContainerManager.TryResolve(null, out productAttrParser)) - { - // make the call unit test safe - shoppingCartItem.Item.Product.MergeWithCombination(shoppingCartItem.Item.AttributesXml, productAttrParser); - } + shoppingCartItem.Item.Product.MergeWithCombination(shoppingCartItem.Item.AttributesXml, _productAttributeParser); if (_shoppingCartSettings.RoundPricesDuringCalculation) { diff --git a/src/Tests/SmartStore.Services.Tests/Catalog/PriceFormatterTests.cs b/src/Tests/SmartStore.Services.Tests/Catalog/PriceFormatterTests.cs index 6f9bfcb495..73ab646fc2 100644 --- a/src/Tests/SmartStore.Services.Tests/Catalog/PriceFormatterTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Catalog/PriceFormatterTests.cs @@ -3,23 +3,20 @@ using System.Globalization; using System.Linq; using System.Threading; +using NUnit.Framework; +using Rhino.Mocks; using SmartStore.Core; using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Localization; -using SmartStore.Core.Domain.Stores; using SmartStore.Core.Domain.Tax; -using SmartStore.Core.Infrastructure; using SmartStore.Core.Plugins; using SmartStore.Services.Catalog; -using SmartStore.Services.Customers; using SmartStore.Services.Directory; using SmartStore.Services.Localization; -using SmartStore.Tests; -using NUnit.Framework; -using Rhino.Mocks; using SmartStore.Services.Stores; +using SmartStore.Tests; namespace SmartStore.Services.Tests.Catalog { @@ -120,9 +117,9 @@ public void Can_formatPrice_with_distinct_currencyDisplayLocale() var rub_currency = new Currency() { Id = 2, - Name = "Russian Ruble", - CurrencyCode = "RUB", - DisplayLocale = "ru-RU", + Name = "British Pound", + CurrencyCode = "GBP", + DisplayLocale = "en-GB", }; var language = new Language() { @@ -131,7 +128,7 @@ public void Can_formatPrice_with_distinct_currencyDisplayLocale() LanguageCulture = "en-US" }; _priceFormatter.FormatPrice(1234.5M, true, usd_currency, language, false, false).ShouldEqual("$1,234.50"); - _priceFormatter.FormatPrice(1234.5M, true, rub_currency, language, false, false).ShouldEqual("1 234,50р."); + _priceFormatter.FormatPrice(1234.5M, true, rub_currency, language, false, false).ShouldEqual("£1,234.50"); } [Test] diff --git a/src/Tests/SmartStore.Services.Tests/Helpers/DateTimeHelperTests.cs b/src/Tests/SmartStore.Services.Tests/Helpers/DateTimeHelperTests.cs index 757d327b6d..b3550078fe 100644 --- a/src/Tests/SmartStore.Services.Tests/Helpers/DateTimeHelperTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Helpers/DateTimeHelperTests.cs @@ -127,16 +127,16 @@ public void Can_convert_dateTime_to_userTime() var sourceDateTime = TimeZoneInfo.FindSystemTimeZoneById("E. Europe Standard Time"); //(GMT+02:00) Minsk; sourceDateTime.ShouldNotBeNull(); - var destinationDateTime = TimeZoneInfo.FindSystemTimeZoneById("North Asia Standard Time"); //(GMT+08:00) Krasnoyarsk; + var destinationDateTime = TimeZoneInfo.FindSystemTimeZoneById("North Asia Standard Time"); //(GMT+07:00) Krasnoyarsk; destinationDateTime.ShouldNotBeNull(); //summer time _dateTimeHelper.ConvertToUserTime(new DateTime(2010, 06, 01, 0, 0, 0), sourceDateTime, destinationDateTime) - .ShouldEqual(new DateTime(2010, 06, 01, 6, 0, 0)); + .ShouldEqual(new DateTime(2010, 06, 01, 5, 0, 0)); //winter time _dateTimeHelper.ConvertToUserTime(new DateTime(2010, 01, 01, 0, 0, 0), sourceDateTime, destinationDateTime) - .ShouldEqual(new DateTime(2010, 01, 01, 6, 0, 0)); + .ShouldEqual(new DateTime(2010, 01, 01, 5, 0, 0)); } [Test] diff --git a/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs index ca52c5a295..9e5208c5b1 100644 --- a/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs @@ -1,5 +1,8 @@ using System; using System.Collections.Generic; +using System.Web; +using NUnit.Framework; +using Rhino.Mocks; using SmartStore.Core; using SmartStore.Core.Caching; using SmartStore.Core.Data; @@ -11,18 +14,20 @@ using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; using SmartStore.Core.Domain.Shipping; +using SmartStore.Core.Domain.Stores; using SmartStore.Core.Domain.Tax; +using SmartStore.Core.Events; +using SmartStore.Core.Logging; using SmartStore.Core.Plugins; using SmartStore.Services.Affiliates; using SmartStore.Services.Catalog; using SmartStore.Services.Common; +using SmartStore.Services.Configuration; using SmartStore.Services.Customers; using SmartStore.Services.Directory; using SmartStore.Services.Discounts; -using SmartStore.Core.Events; using SmartStore.Services.Localization; -using SmartStore.Core.Logging; -using SmartStore.Services.Logging; +using SmartStore.Services.Media; using SmartStore.Services.Messages; using SmartStore.Services.Orders; using SmartStore.Services.Payments; @@ -30,12 +35,6 @@ using SmartStore.Services.Shipping; using SmartStore.Services.Tax; using SmartStore.Tests; -using NUnit.Framework; -using Rhino.Mocks; -using SmartStore.Core.Domain.Stores; -using SmartStore.Services.Configuration; -using SmartStore.Services.Media; -using System.Web; namespace SmartStore.Services.Tests.Orders { @@ -114,6 +113,7 @@ public class OrderProcessingServiceTests : ServiceTest _categoryService = MockRepository.GenerateMock(); _productAttributeParser = MockRepository.GenerateMock(); _productAttributeService = MockRepository.GenerateMock(); + _genericAttributeService = MockRepository.GenerateMock(); _eventPublisher = MockRepository.GenerateMock(); _eventPublisher.Expect(x => x.Publish(Arg.Is.Anything)); @@ -140,11 +140,9 @@ public class OrderProcessingServiceTests : ServiceTest this.ProviderManager); _shipmentService = MockRepository.GenerateMock(); - _paymentService = MockRepository.GenerateMock(); _checkoutAttributeParser = MockRepository.GenerateMock(); _giftCardService = MockRepository.GenerateMock(); - _genericAttributeService = MockRepository.GenerateMock(); //tax _taxSettings = new TaxSettings(); @@ -168,19 +166,18 @@ public class OrderProcessingServiceTests : ServiceTest _orderTotalCalcService = new OrderTotalCalculationService(_workContext, _storeContext, _priceCalcService, _taxService, _shippingService, _paymentService, - _checkoutAttributeParser, _discountService, _giftCardService, - _genericAttributeService, + _checkoutAttributeParser, _discountService, _giftCardService, _genericAttributeService, _productAttributeParser, _taxSettings, _rewardPointsSettings, _shippingSettings, _shoppingCartSettings, _catalogSettings); _orderService = MockRepository.GenerateMock(); _webHelper = MockRepository.GenerateMock(); _languageService = MockRepository.GenerateMock(); _productService = MockRepository.GenerateMock(); - _priceFormatter= MockRepository.GenerateMock(); - _productAttributeFormatter= MockRepository.GenerateMock(); - _shoppingCartService= MockRepository.GenerateMock(); - _checkoutAttributeFormatter= MockRepository.GenerateMock(); - _customerService= MockRepository.GenerateMock(); + _priceFormatter = MockRepository.GenerateMock(); + _productAttributeFormatter = MockRepository.GenerateMock(); + _shoppingCartService = MockRepository.GenerateMock(); + _checkoutAttributeFormatter = MockRepository.GenerateMock(); + _customerService = MockRepository.GenerateMock(); _encryptionService = MockRepository.GenerateMock(); _workflowMessageService = MockRepository.GenerateMock(); _customerActivityService = MockRepository.GenerateMock(); diff --git a/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs index 711e6763b9..79ed7ea6bd 100644 --- a/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs @@ -1,4 +1,8 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Web; +using NUnit.Framework; +using Rhino.Mocks; using SmartStore.Core; using SmartStore.Core.Caching; using SmartStore.Core.Data; @@ -8,26 +12,23 @@ using SmartStore.Core.Domain.Discounts; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Shipping; +using SmartStore.Core.Domain.Stores; using SmartStore.Core.Domain.Tax; +using SmartStore.Core.Events; +using SmartStore.Core.Logging; using SmartStore.Core.Plugins; using SmartStore.Services.Catalog; using SmartStore.Services.Common; +using SmartStore.Services.Configuration; +using SmartStore.Services.Directory; using SmartStore.Services.Discounts; -using SmartStore.Core.Events; using SmartStore.Services.Localization; -using SmartStore.Core.Logging; +using SmartStore.Services.Media; using SmartStore.Services.Orders; using SmartStore.Services.Payments; using SmartStore.Services.Shipping; using SmartStore.Services.Tax; using SmartStore.Tests; -using NUnit.Framework; -using Rhino.Mocks; -using SmartStore.Core.Domain.Stores; -using SmartStore.Services.Configuration; -using SmartStore.Services.Directory; -using SmartStore.Services.Media; -using System.Web; namespace SmartStore.Services.Tests.Orders { @@ -71,32 +72,28 @@ public class OrderTotalCalculationServiceTests : ServiceTest { _workContext = MockRepository.GenerateMock(); - _store = new Store() { Id = 1 }; + _store = new Store { Id = 1 }; _storeContext = MockRepository.GenerateMock(); _storeContext.Expect(x => x.CurrentStore).Return(_store); var pluginFinder = new PluginFinder(); var cacheManager = new NullCache(); + _shoppingCartSettings = new ShoppingCartSettings(); + _catalogSettings = new CatalogSettings(); + //price calculation service _discountService = MockRepository.GenerateMock(); _categoryService = MockRepository.GenerateMock(); _productAttributeParser = MockRepository.GenerateMock(); _productService = MockRepository.GenerateMock(); _productAttributeService = MockRepository.GenerateMock(); - _settingService = MockRepository.GenerateMock(); - - _downloadService = MockRepository.GenerateMock(); - _commonServices = MockRepository.GenerateMock(); - _httpRequestBase = MockRepository.GenerateMock(); - - _shoppingCartSettings = new ShoppingCartSettings(); - _catalogSettings = new CatalogSettings(); - + _genericAttributeService = MockRepository.GenerateMock(); _eventPublisher = MockRepository.GenerateMock(); _eventPublisher.Expect(x => x.Publish(Arg.Is.Anything)); - - _localizationService = MockRepository.GenerateMock(); + + _localizationService = MockRepository.GenerateMock(); + _settingService = MockRepository.GenerateMock(); //shipping _shippingSettings = new ShippingSettings(); @@ -117,14 +114,9 @@ public class OrderTotalCalculationServiceTests : ServiceTest _settingService, this.ProviderManager); - _paymentService = MockRepository.GenerateMock(); _checkoutAttributeParser = MockRepository.GenerateMock(); _giftCardService = MockRepository.GenerateMock(); - _genericAttributeService = MockRepository.GenerateMock(); - - _eventPublisher = MockRepository.GenerateMock(); - _eventPublisher.Expect(x => x.Publish(Arg.Is.Anything)); //tax _taxSettings = new TaxSettings(); @@ -133,9 +125,14 @@ public class OrderTotalCalculationServiceTests : ServiceTest _taxSettings.PricesIncludeTax = false; _taxSettings.TaxDisplayType = TaxDisplayType.IncludingTax; _taxSettings.DefaultTaxAddressId = 10; + _addressService = MockRepository.GenerateMock(); - _addressService.Expect(x => x.GetAddressById(_taxSettings.DefaultTaxAddressId)).Return(new Address() { Id = _taxSettings.DefaultTaxAddressId }); + _addressService.Expect(x => x.GetAddressById(_taxSettings.DefaultTaxAddressId)).Return(new Address { Id = _taxSettings.DefaultTaxAddressId }); + _downloadService = MockRepository.GenerateMock(); + _commonServices = MockRepository.GenerateMock(); + _httpRequestBase = MockRepository.GenerateMock(); _geoCountryLookup = MockRepository.GenerateMock(); + _taxService = new TaxService(_addressService, _workContext, _taxSettings, _shoppingCartSettings, pluginFinder, _settingService, _geoCountryLookup, this.ProviderManager); _rewardPointsSettings = new RewardPointsSettings(); @@ -145,7 +142,7 @@ public class OrderTotalCalculationServiceTests : ServiceTest _orderTotalCalcService = new OrderTotalCalculationService(_workContext, _storeContext, _priceCalcService, _taxService, _shippingService, _paymentService, - _checkoutAttributeParser, _discountService, _giftCardService, _genericAttributeService, + _checkoutAttributeParser, _discountService, _giftCardService, _genericAttributeService, _productAttributeParser, _taxSettings, _rewardPointsSettings, _shippingSettings, _shoppingCartSettings, _catalogSettings); } @@ -278,8 +275,7 @@ public void Can_get_shopping_cart_subTotal_including_tax() [Test] public void Can_get_shopping_cart_subTotal_discount_excluding_tax() { - //customer - Customer customer = new Customer(); + var customer = new Customer(); //shopping cart var product1 = new Product @@ -290,7 +286,7 @@ public void Can_get_shopping_cart_subTotal_discount_excluding_tax() CustomerEntersPrice = false, Published = true, }; - var sci1 = new ShoppingCartItem() + var sci1 = new ShoppingCartItem { Product = product1, ProductId = product1.Id, @@ -304,7 +300,7 @@ public void Can_get_shopping_cart_subTotal_discount_excluding_tax() CustomerEntersPrice = false, Published = true, }; - var sci2 = new ShoppingCartItem() + var sci2 = new ShoppingCartItem { Product = product2, ProductId = product2.Id, @@ -319,7 +315,7 @@ public void Can_get_shopping_cart_subTotal_discount_excluding_tax() cart.ForEach(sci => sci.Item.CustomerId = customer.Id); //discounts - var discount1 = new Discount() + var discount1 = new Discount { Id = 1, Name = "Discount 1", @@ -328,7 +324,7 @@ public void Can_get_shopping_cart_subTotal_discount_excluding_tax() DiscountLimitation = DiscountLimitationType.Unlimited, }; _discountService.Expect(ds => ds.IsDiscountValid(discount1, customer)).Return(true); - _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToOrderSubTotal)).Return(new List() { discount1 }); + _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToOrderSubTotal)).Return(new List { discount1 }); _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToCategories)).Return(new List()); decimal discountAmount; @@ -337,9 +333,11 @@ public void Can_get_shopping_cart_subTotal_discount_excluding_tax() decimal subTotalWithDiscount; SortedDictionary taxRates; //10% - default tax rate + _orderTotalCalcService.GetShoppingCartSubTotal(cart, false, out discountAmount, out appliedDiscount, out subTotalWithoutDiscount, out subTotalWithDiscount, out taxRates); + discountAmount.ShouldEqual(3); appliedDiscount.ShouldNotBeNull(); appliedDiscount.Name.ShouldEqual("Discount 1"); @@ -353,8 +351,7 @@ public void Can_get_shopping_cart_subTotal_discount_excluding_tax() [Test] public void Can_get_shopping_cart_subTotal_discount_including_tax() { - //customer - Customer customer = new Customer(); + var customer = new Customer(); //shopping cart var product1 = new Product @@ -365,7 +362,7 @@ public void Can_get_shopping_cart_subTotal_discount_including_tax() CustomerEntersPrice = false, Published = true, }; - var sci1 = new ShoppingCartItem() + var sci1 = new ShoppingCartItem { Product = product1, ProductId = product1.Id, @@ -379,7 +376,7 @@ public void Can_get_shopping_cart_subTotal_discount_including_tax() CustomerEntersPrice = false, Published = true, }; - var sci2 = new ShoppingCartItem() + var sci2 = new ShoppingCartItem { Product = product2, ProductId = product2.Id, @@ -394,7 +391,7 @@ public void Can_get_shopping_cart_subTotal_discount_including_tax() cart.ForEach(sci => sci.Item.CustomerId = customer.Id); //discounts - var discount1 = new Discount() + var discount1 = new Discount { Id = 1, Name = "Discount 1", @@ -403,7 +400,7 @@ public void Can_get_shopping_cart_subTotal_discount_including_tax() DiscountLimitation = DiscountLimitationType.Unlimited, }; _discountService.Expect(ds => ds.IsDiscountValid(discount1, customer)).Return(true); - _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToOrderSubTotal)).Return(new List() { discount1 }); + _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToOrderSubTotal)).Return(new List { discount1 }); _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToCategories)).Return(new List()); decimal discountAmount; @@ -411,12 +408,12 @@ public void Can_get_shopping_cart_subTotal_discount_including_tax() decimal subTotalWithoutDiscount; decimal subTotalWithDiscount; SortedDictionary taxRates; + _orderTotalCalcService.GetShoppingCartSubTotal(cart, true, out discountAmount, out appliedDiscount, out subTotalWithoutDiscount, out subTotalWithDiscount, out taxRates); - //TODO strange. Why does the commented test fail? discountAmount.ShouldEqual(3.3); - //discountAmount.ShouldEqual(3.3); + (3.3M == Math.Round(discountAmount, 8)).ShouldBeTrue(); appliedDiscount.ShouldNotBeNull(); appliedDiscount.Name.ShouldEqual("Discount 1"); subTotalWithoutDiscount.ShouldEqual(98.329); From 743b6bdea8007fad3913813045df49bce850f561 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 11 May 2015 14:17:32 +0200 Subject: [PATCH 0119/1256] Added fields AvailableStartDateTimeUtc & AvailableEndDateTimeUtc to Import & Export --- .../SmartStore.Services/ExportImport/ExportManager.cs | 10 +++++++++- .../SmartStore.Services/ExportImport/ImportManager.cs | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 587cc3cac0..3ffeb19847 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -879,7 +879,9 @@ public virtual void ExportProductsToXlsx(Stream stream, IList products) "BundlePerItemShipping", "BundlePerItemPricing", "BundlePerItemShoppingCart", - "BundleItemSkus" + "BundleItemSkus", + "AvailableStartDateTimeUtc", + "AvailableEndDateTimeUtc" }; //BEGIN: add headers for languages @@ -1196,6 +1198,12 @@ public virtual void ExportProductsToXlsx(Stream stream, IList products) cells[row, col].Value = bundleItemSkus; col++; + cells[row, col].Value = p.AvailableStartDateTimeUtc; + col++; + + cells[row, col].Value = p.AvailableEndDateTimeUtc; + col++; + //BEGIN: export localized values foreach (var lang in languages) { diff --git a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs index 90b48cb473..cf489dd468 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs @@ -422,6 +422,9 @@ private int ProcessProducts(ICollection> batch, ImportResult row.SetProperty(result, product, (x) => x.BundlePerItemShipping); row.SetProperty(result, product, (x) => x.BundlePerItemShoppingCart); row.SetProperty(result, product, (x) => x.BundleTitleText); + row.SetProperty(result, product, (x) => x.AvailableStartDateTimeUtc, null, OADateToUtcDate); + row.SetProperty(result, product, (x) => x.AvailableEndDateTimeUtc, null, OADateToUtcDate); + row.SetProperty(result, product, (x) => x.CreatedOnUtc, DateTime.UtcNow, OADateToUtcDate); product.UpdatedOnUtc = DateTime.UtcNow; From a1e56394628ec14ba34fbf79bc9afada483c14b6 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Mon, 11 May 2015 19:27:32 +0200 Subject: [PATCH 0120/1256] Added hidden setting to disable autoupdate (CommonSettings.AutoUpdateEnabled) --- .../SmartStore.Core/Domain/Common/CommonSettings.cs | 3 +++ .../Administration/Controllers/CommonController.cs | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Libraries/SmartStore.Core/Domain/Common/CommonSettings.cs b/src/Libraries/SmartStore.Core/Domain/Common/CommonSettings.cs index d6af1d213a..9ecb41ae4f 100644 --- a/src/Libraries/SmartStore.Core/Domain/Common/CommonSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Common/CommonSettings.cs @@ -13,6 +13,7 @@ public CommonSettings() SitemapIncludeManufacturers = true; SitemapIncludeTopics = true; FullTextMode = FulltextSearchMode.ExactMatch; + AutoUpdateEnabled = true; } public bool UseSystemEmailForContactUsForm { get; set; } @@ -42,5 +43,7 @@ public CommonSettings() /// public FulltextSearchMode FullTextMode { get; set; } + public bool AutoUpdateEnabled { get; set; } + } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs index a15fb090b5..3b070a3d9b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs @@ -57,6 +57,7 @@ public class CommonController : AdminControllerBase private readonly Lazy _measureService; private readonly ICustomerService _customerService; private readonly IUrlRecordService _urlRecordService; + private readonly Lazy _commonSettings; private readonly Lazy _currencySettings; private readonly Lazy _measureSettings; private readonly Lazy _dateTimeHelper; @@ -83,6 +84,7 @@ public CommonController( Lazy measureService, ICustomerService customerService, IUrlRecordService urlRecordService, + Lazy commonSettings, Lazy currencySettings, Lazy measureSettings, Lazy dateTimeHelper, @@ -102,6 +104,7 @@ public CommonController( this._measureService = measureService; this._customerService = customerService; this._urlRecordService = urlRecordService; + this._commonSettings = commonSettings; this._currencySettings = currencySettings; this._measureSettings = measureSettings; this._dateTimeHelper = dateTimeHelper; @@ -328,7 +331,7 @@ private async Task CheckUpdateAsync(bool enforce = false, boo model.CurrentVersion = curVersion; model.LanguageCode = lang; - if (CommonHelper.IsDevEnvironment || !_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (CommonHelper.IsDevEnvironment || !_commonSettings.Value.AutoUpdateEnabled || !_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) { model.AutoUpdatePossible = false; } From 1454e430cfb3da0676c136410d7b2e12ceee8109 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 12 May 2015 18:36:17 +0200 Subject: [PATCH 0121/1256] Minor fix --- src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs b/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs index 43c1308998..2e6e8ac414 100644 --- a/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs +++ b/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs @@ -64,10 +64,9 @@ public static IQueryable Get( query = query.Where(predicate); } - foreach (var includeProperty in includeProperties.Split - (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { - query = rs.Expand(query, includeProperty.Trim()); + query = query.Expand(includeProperty.Trim()); } if (orderBy != null) From ca1165ecdb7753a30ece67a1c40674153744b892 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 13 May 2015 18:10:11 +0200 Subject: [PATCH 0122/1256] Unit test fix --- .../Helpers/DateTimeHelperTests.cs | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Tests/SmartStore.Services.Tests/Helpers/DateTimeHelperTests.cs b/src/Tests/SmartStore.Services.Tests/Helpers/DateTimeHelperTests.cs index b3550078fe..29160fe4b9 100644 --- a/src/Tests/SmartStore.Services.Tests/Helpers/DateTimeHelperTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Helpers/DateTimeHelperTests.cs @@ -124,19 +124,26 @@ public void Can_get_customer_timeZone_with_customTimeZones_disabled() [Test] public void Can_convert_dateTime_to_userTime() { - var sourceDateTime = TimeZoneInfo.FindSystemTimeZoneById("E. Europe Standard Time"); //(GMT+02:00) Minsk; + var sourceDateTime = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); // (GMT+01:00) Berlin; sourceDateTime.ShouldNotBeNull(); - var destinationDateTime = TimeZoneInfo.FindSystemTimeZoneById("North Asia Standard Time"); //(GMT+07:00) Krasnoyarsk; + var destinationDateTime = TimeZoneInfo.FindSystemTimeZoneById("GTB Standard Time"); // (GMT+02:00) Istanbul; destinationDateTime.ShouldNotBeNull(); - //summer time - _dateTimeHelper.ConvertToUserTime(new DateTime(2010, 06, 01, 0, 0, 0), sourceDateTime, destinationDateTime) - .ShouldEqual(new DateTime(2010, 06, 01, 5, 0, 0)); + // Berlin > Istanbul + _dateTimeHelper + .ConvertToUserTime(new DateTime(2015, 06, 1, 0, 0, 0), sourceDateTime, destinationDateTime) + .ShouldEqual(new DateTime(2015, 06, 1, 1, 0, 0)); - //winter time - _dateTimeHelper.ConvertToUserTime(new DateTime(2010, 01, 01, 0, 0, 0), sourceDateTime, destinationDateTime) - .ShouldEqual(new DateTime(2010, 01, 01, 5, 0, 0)); + // UTC > Istanbul (summer) + _dateTimeHelper + .ConvertToUserTime(new DateTime(2015, 06, 1, 0, 0, 0), TimeZoneInfo.Utc, destinationDateTime) + .ShouldEqual(new DateTime(2015, 06, 1, 3, 0, 0)); + + // UTC > Istanbul (winter) + _dateTimeHelper + .ConvertToUserTime(new DateTime(2015, 01, 01, 0, 0, 0), TimeZoneInfo.Utc, destinationDateTime) + .ShouldEqual(new DateTime(2015, 01, 1, 2, 0, 0)); } [Test] From 698ab2d5e66949135ba29e3e863dd21f861b8e34 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 20 May 2015 20:53:04 +0200 Subject: [PATCH 0123/1256] License checker now supports IDN mapping for domain names --- .../SmartStore.Licensing.dll | Bin 145408 -> 146432 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/SmartStore.Licensing/SmartStore.Licensing.dll b/lib/SmartStore.Licensing/SmartStore.Licensing.dll index e8d9a01512c3d42521183a72cadd7e0a484cc5cd..4c4579257f738be7306a256678bdace011cb2be2 100644 GIT binary patch literal 146432 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 literal 145408 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 From fe5fe2666ce072b4b9b0060f7b5e0404839d40f5 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 20 May 2015 20:53:04 +0200 Subject: [PATCH 0124/1256] License checker now supports IDN mapping for domain names --- .../SmartStore.Licensing.dll | Bin 145408 -> 146432 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/SmartStore.Licensing/SmartStore.Licensing.dll b/lib/SmartStore.Licensing/SmartStore.Licensing.dll index e8d9a01512c3d42521183a72cadd7e0a484cc5cd..4c4579257f738be7306a256678bdace011cb2be2 100644 GIT binary patch literal 146432 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 literal 145408 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 From 2e62536059d366bacacfc1fca708731bf44a2e03 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 21 May 2015 20:44:18 +0200 Subject: [PATCH 0125/1256] Minor enhancement --- src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs | 5 +++++ src/Libraries/SmartStore.Services/Media/PictureService.cs | 1 + 2 files changed, 6 insertions(+) diff --git a/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs b/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs index 86c8f4400e..922ba78a78 100644 --- a/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs +++ b/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs @@ -32,6 +32,11 @@ public static void Fatal(this ILogger logger, string message, Exception exceptio FilteredLog(logger, LogLevel.Fatal, message, exception, customer); } + public static void Error(this ILogger logger, Exception exception, Customer customer = null) + { + FilteredLog(logger, LogLevel.Error, exception.Message, exception, customer); + } + private static void FilteredLog(ILogger logger, LogLevel level, string message, Exception exception = null, Customer customer = null) { //don't log thread abort exception diff --git a/src/Libraries/SmartStore.Services/Media/PictureService.cs b/src/Libraries/SmartStore.Services/Media/PictureService.cs index 5bd399bd9a..019165ab60 100644 --- a/src/Libraries/SmartStore.Services/Media/PictureService.cs +++ b/src/Libraries/SmartStore.Services/Media/PictureService.cs @@ -873,6 +873,7 @@ protected int MovePictures(bool toDb) tx.Rollback(); _settingService.SetSetting("Media.Images.StoreInDB", !toDb); _notifier.Error(ex.Message); + _logger.Error(ex); } } } From f47b64b6c49111ecdc11909d9bfd5b372477bd2f Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 22 May 2015 18:22:25 +0200 Subject: [PATCH 0126/1256] Minor fix --- src/Libraries/SmartStore.Services/Media/PictureService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Libraries/SmartStore.Services/Media/PictureService.cs b/src/Libraries/SmartStore.Services/Media/PictureService.cs index 019165ab60..bc11e71a36 100644 --- a/src/Libraries/SmartStore.Services/Media/PictureService.cs +++ b/src/Libraries/SmartStore.Services/Media/PictureService.cs @@ -828,7 +828,7 @@ protected int MovePictures(bool toDb) if (!toDb) { - if (picture.PictureBinary.Length > 0) + if (picture.PictureBinary != null && picture.PictureBinary.Length > 0) { // save picture as file SavePictureInFile(picture.Id, picture.PictureBinary, picture.MimeType, out filePath); From d638f7185e27ce6c073e5f5699c0f1ae5fb90498 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 18 May 2015 18:27:15 +0200 Subject: [PATCH 0127/1256] Closes #210 Implement multi-store support for import/export --- changelog.md | 5 ++++ .../ExportImport/ExportManager.cs | 24 ++++++++++++++++--- .../ExportImport/ImportManager.cs | 19 +++++++++++++-- .../ExportImport/ExportManagerTests.cs | 5 +++- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/changelog.md b/changelog.md index b456e5ffb2..0820d1ab89 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,10 @@ # Release Notes +## SmartStore.NET 3.0.0 + +### New Features +* #210 Implement multi-store support for import/export + ## SmartStore.NET 2.2.1 ### New Features diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 3ffeb19847..acd9041154 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -24,6 +24,7 @@ using SmartStore.Services.Media; using SmartStore.Services.Messages; using SmartStore.Services.Seo; +using SmartStore.Services.Stores; namespace SmartStore.Services.ExportImport { @@ -43,7 +44,8 @@ public partial class ExportManager : IExportManager private readonly ILanguageService _languageService; private readonly MediaSettings _mediaSettings; private readonly ICommonServices _commonServices; - + private readonly IStoreMappingService _storeMappingService; + #endregion #region Ctor @@ -56,7 +58,8 @@ public ExportManager(ICategoryService categoryService, INewsLetterSubscriptionService newsLetterSubscriptionService, ILanguageService languageService, MediaSettings mediaSettings, - ICommonServices commonServices) + ICommonServices commonServices, + IStoreMappingService storeMappingService) { this._categoryService = categoryService; this._manufacturerService = manufacturerService; @@ -67,6 +70,7 @@ public ExportManager(ICategoryService categoryService, this._languageService = languageService; this._mediaSettings = mediaSettings; this._commonServices = commonServices; + this._storeMappingService = storeMappingService; Logger = NullLogger.Instance; } @@ -881,7 +885,9 @@ public virtual void ExportProductsToXlsx(Stream stream, IList products) "BundlePerItemShoppingCart", "BundleItemSkus", "AvailableStartDateTimeUtc", - "AvailableEndDateTimeUtc" + "AvailableEndDateTimeUtc", + "StoreIds", + "LimitedToStores" }; //BEGIN: add headers for languages @@ -1204,6 +1210,18 @@ public virtual void ExportProductsToXlsx(Stream stream, IList products) cells[row, col].Value = p.AvailableEndDateTimeUtc; col++; + string storeIds = ""; + + if (p.LimitedToStores) + { + storeIds = string.Join(";", _storeMappingService.GetStoreMappings(p).Select(x => x.StoreId)); + } + cells[row, col].Value = storeIds; + col++; + + cells[row, col].Value = p.LimitedToStores; + col++; + //BEGIN: export localized values foreach (var lang in languages) { diff --git a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs index cf489dd468..8ba2fe85ae 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs @@ -16,6 +16,8 @@ using System.Text; using SmartStore.Core.Domain.Seo; using SmartStore.Core.Domain.Media; +using SmartStore.Services.Stores; +using SmartStore.Core.Domain.Stores; namespace SmartStore.Services.ExportImport { @@ -39,6 +41,7 @@ public partial class ImportManager : IImportManager private readonly IRepository _rsUrlRecord; private readonly ILanguageService _languageService; private readonly ILocalizedEntityService _localizedEntityService; + private readonly IStoreMappingService _storeMappingService; public ImportManager( IProductService productService, @@ -55,7 +58,8 @@ public ImportManager( IRepository rsProductPicture, IRepository rsUrlRecord, ILanguageService languageService, - ILocalizedEntityService localizedEntityService) + ILocalizedEntityService localizedEntityService, + IStoreMappingService storeMappingService) { this._productService = productService; this._categoryService = categoryService; @@ -72,6 +76,7 @@ public ImportManager( this._rsPicture = rsPicture; this._languageService = languageService; this._localizedEntityService = localizedEntityService; + this._storeMappingService = storeMappingService; } public virtual string CreateTextReport(ImportResult result) @@ -256,6 +261,7 @@ public virtual ImportResult ImportProductsFromExcel( result.AddError(ex, segmenter.CurrentSegment, "ProcessProductManufacturers"); } } + // =========================================================================== // 6.) Import product picture mappings @@ -424,6 +430,15 @@ private int ProcessProducts(ICollection> batch, ImportResult row.SetProperty(result, product, (x) => x.BundleTitleText); row.SetProperty(result, product, (x) => x.AvailableStartDateTimeUtc, null, OADateToUtcDate); row.SetProperty(result, product, (x) => x.AvailableEndDateTimeUtc, null, OADateToUtcDate); + row.SetProperty(result, product, (x) => x.LimitedToStores); + + string storeIds = row.GetValue("StoreIds"); + if (storeIds.HasValue()) + { + _storeMappingService.SaveStoreMappings(product, + row["StoreIds"].ToString() + .Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(x => Convert.ToInt32(x.Trim())).ToArray()); + } row.SetProperty(result, product, (x) => x.CreatedOnUtc, DateTime.UtcNow, OADateToUtcDate); @@ -668,7 +683,7 @@ private int ProcessProductManufacturers(ICollection> batch, I return num; } - + private void ProcessProductPictures(ICollection> batch, ImportResult result) { // true, cause pictures must be saved and assigned an id diff --git a/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs b/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs index d11de81706..19f85f9865 100644 --- a/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs +++ b/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs @@ -19,6 +19,7 @@ using NUnit.Framework; using Rhino.Mocks; using SmartStore.Core.Domain.Media; +using SmartStore.Services.Stores; namespace SmartStore.Services.Tests.ExportImport { @@ -35,6 +36,7 @@ public class ExportManagerTests : ServiceTest ILanguageService _languageService; MediaSettings _mediaSettings; ICommonServices _commonServices; + IStoreMappingService _storeMapping; [SetUp] public new void SetUp() @@ -48,9 +50,10 @@ public class ExportManagerTests : ServiceTest _languageService = MockRepository.GenerateMock(); _mediaSettings = MockRepository.GenerateMock(); _commonServices = MockRepository.GenerateMock(); + _storeMapping = MockRepository.GenerateMock(); _exportManager = new ExportManager(_categoryService, _manufacturerService, _productService, _productTemplateService, _pictureService, - _newsLetterSubscriptionService, _languageService, _mediaSettings, _commonServices); + _newsLetterSubscriptionService, _languageService, _mediaSettings, _commonServices, _storeMapping); } //[Test] From 13730e9a8f4e053e7382d1e24914a60287464c6e Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 27 May 2015 20:42:21 +0200 Subject: [PATCH 0128/1256] Update README.md --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 3ff934079c..9652a45276 100644 --- a/README.md +++ b/README.md @@ -54,18 +54,18 @@ The state-of-the-art architecture of SmartStore.NET - with `ASP.NET 4.5` + `MVC * and many more... ## Project Status -SmartStore.NET V2.1 has been released on November 24. 2014. The highlights are: - -* Drastically **simplified plugin development, debugging & deployment** -* **Theme inheritance**: create derived child themes with minimum effort by overriding only small parts (static files and even variables) -* New backend design and cleaner frontend theme -* More comfortable catalog management & product editing -* New payment plugins `Pay with Amazon` & `Accarda-Kar` -* **Preview Mode**: virtually test themes and shops more easily -* **Simplified checkout** process -* **New Image Gallery** component in public product details page -* Support for **hierarchical SEO slugs**, e.g.: samsung/galaxy/s5/16gb/white -* Support for new EU VAT regulation for digital goods (2008/8/EG directive) +SmartStore.NET V2.2.1 has been released on May 15, 2015. The highlights are: + +* Overall performance increase +* Added multistore support for forums +* New option to display product thumbnails in instant search +* New mobile theme: _MobileLight_ (a light variant of the default mobile theme) +* Quantity unit management +* Limit country settings to stores +* Web API: Support for file upload and multipart mime +* More reliable mobile device detection +* Performance: product list rendering up to 10x (!) faster now +* Lots of bug fixes ##Try it online From 5e604b624e0cc8f30382108aacc85968caa20ff5 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 27 May 2015 23:26:38 +0200 Subject: [PATCH 0129/1256] Minor UI fix --- .../Product/EditorTemplates/TierPriceCustomer.cshtml | 2 +- .../Product/EditorTemplates/TierPriceStore.cshtml | 11 +++++------ .../Views/Product/_CreateOrUpdate.Price.cshtml | 1 + .../SmartStore.Web/Views/Product/_Attributes.cshtml | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/EditorTemplates/TierPriceCustomer.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/EditorTemplates/TierPriceCustomer.cshtml index a7703a72b3..4b6c4391f6 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/EditorTemplates/TierPriceCustomer.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/EditorTemplates/TierPriceCustomer.cshtml @@ -2,7 +2,7 @@ diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/EditorTemplates/TierPriceStore.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/EditorTemplates/TierPriceStore.cshtml index 79d6b09ee1..28cf2f3f95 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/EditorTemplates/TierPriceStore.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/EditorTemplates/TierPriceStore.cshtml @@ -1,10 +1,9 @@  - \ No newline at end of file From c8bd0221ee8b79dc877089ce2444f8af38ed7ca1 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sun, 7 Jun 2015 16:49:23 +0200 Subject: [PATCH 0140/1256] Updated changelog --- changelog.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index 0820d1ab89..4330a37635 100644 --- a/changelog.md +++ b/changelog.md @@ -1,9 +1,16 @@ -# Release Notes +# Release Notes -## SmartStore.NET 3.0.0 +## SmartStore.NET 2.2.2 ### New Features -* #210 Implement multi-store support for import/export +* #210 Implement multi-store support for import/export + +### Improvements +* License checker now supports IDN mapping for domain names + +### Bugfixes +* #694 Product variant attribute in product page should not be preselected implicitly + ## SmartStore.NET 2.2.1 From e27de70196cb4e24fbcdb51c93e2eb73e8fd3eef Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 8 Jun 2015 13:04:17 +0200 Subject: [PATCH 0141/1256] Fixed: If currencies are limited to one for a multi-store, this currency should dominate the setting for the primary store currency --- changelog.md | 1 + .../WebWorkContext.cs | 21 ++++++++++--------- .../Views/Shared/_AdminLayout.cshtml | 2 ++ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/changelog.md b/changelog.md index 4330a37635..b82b37753b 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,7 @@ ### Bugfixes * #694 Product variant attribute in product page should not be preselected implicitly +* Fixed: If currencies are limited to one for a multi-store, this currency should dominate the setting for the primary store currency ## SmartStore.NET 2.2.1 diff --git a/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs b/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs index cae01c060a..9d33ae5f24 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs @@ -352,6 +352,7 @@ public Currency WorkingCurrency bool fixPrimaryStoreCurrency = false; Currency currency = null; + // return primary store currency when we're in admin area/mode if (this.IsAdmin) { @@ -362,6 +363,7 @@ public Currency WorkingCurrency { // find current customer language var customer = this.CurrentCustomer; + var currentStoreCurrencies = _currencyService.GetAllCurrencies(storeId: _storeContext.CurrentStore.Id); if (customer != null && !customer.IsSearchEngineAccount()) { @@ -380,9 +382,13 @@ public Currency WorkingCurrency // find currency by domain ending if (currency == null && _httpContext != null && _httpContext.Request != null && _httpContext.Request.Url != null) { - currency = _currencyService - .GetAllCurrencies(storeId: _storeContext.CurrentStore.Id) - .GetByDomainEnding(_httpContext.Request.Url.Authority); + currency = currentStoreCurrencies.GetByDomainEnding(_httpContext.Request.Url.Authority); + } + + // if there's only one currency for current store it dominates the primary currency + if (currentStoreCurrencies.Count == 1) + { + currency = currentStoreCurrencies.First(); } // get PrimaryStoreCurrency @@ -395,11 +401,7 @@ public Currency WorkingCurrency // get the first published currency for current store if (currency == null) { - var allStoreCurrencies = _currencyService.GetAllCurrencies(storeId: _storeContext.CurrentStore.Id); - if (allStoreCurrencies.Count > 0) - { - currency = allStoreCurrencies.FirstOrDefault(); - } + currency = currentStoreCurrencies.FirstOrDefault(); } } @@ -424,8 +426,7 @@ public Currency WorkingCurrency { _currencySettings.PrimaryStoreCurrencyId = currency.Id; _settingService.UpdateSetting(_currencySettings, x => x.PrimaryStoreCurrencyId, true, _storeContext.CurrentStore.Id); - } - + } _cachedCurrency = currency; return _cachedCurrency; diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/_AdminLayout.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/_AdminLayout.cshtml index a643b8e9ff..2ac0f3243b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/_AdminLayout.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/_AdminLayout.cshtml @@ -6,6 +6,8 @@ @using SmartStore.Core.Domain.Localization; @using SmartStore; +@* Please keep in mind that this layout view is also referenced and used by plugins! *@ + @{ Layout = "~/Administration/Views/Shared/_AdminRoot.cshtml"; } From 7f0e40a06cd9b1d7ecdf22a6e60d8ba5b81cd12c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 8 Jun 2015 16:05:52 +0200 Subject: [PATCH 0142/1256] Added link to news list to frontend's main menu --- .../SmartStore.Web/Controllers/CommonController.cs | 5 +++++ .../SmartStore.Web/Models/Common/MenuModel.cs | 1 + .../SmartStore.Web/Views/Common/Menu.cshtml | 11 ++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Controllers/CommonController.cs index 87febc0ba2..ba7a63234c 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CommonController.cs @@ -15,6 +15,7 @@ using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Messages; +using SmartStore.Core.Domain.News; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Security; using SmartStore.Core.Domain.Seo; @@ -64,6 +65,7 @@ public partial class CommonController : PublicControllerBase private readonly CatalogSettings _catalogSettings; private readonly ThemeSettings _themeSettings; private readonly CommonSettings _commonSettings; + private readonly NewsSettings _newsSettings; private readonly BlogSettings _blogSettings; private readonly ForumSettings _forumSettings; private readonly LocalizationSettings _localizationSettings; @@ -93,6 +95,7 @@ public CommonController( CatalogSettings catalogSettings, EmailAccountSettings emailAccountSettings, CommonSettings commonSettings, + NewsSettings newsSettings, BlogSettings blogSettings, ForumSettings forumSettings, LocalizationSettings localizationSettings, @@ -117,6 +120,7 @@ public CommonController( this._taxSettings = taxSettings; this._catalogSettings = catalogSettings; this._commonSettings = commonSettings; + this._newsSettings = newsSettings; this._blogSettings = blogSettings; this._forumSettings = forumSettings; this._localizationSettings = localizationSettings; @@ -648,6 +652,7 @@ public ActionResult Menu() var model = new MenuModel { RecentlyAddedProductsEnabled = _catalogSettings.RecentlyAddedProductsEnabled, + NewsEnabled = _newsSettings.Enabled, BlogEnabled = _blogSettings.Enabled, ForumEnabled = _forumSettings.ForumsEnabled, AllowPrivateMessages = _forumSettings.AllowPrivateMessages && customer.IsRegistered(), diff --git a/src/Presentation/SmartStore.Web/Models/Common/MenuModel.cs b/src/Presentation/SmartStore.Web/Models/Common/MenuModel.cs index 17680fb249..d461318081 100644 --- a/src/Presentation/SmartStore.Web/Models/Common/MenuModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Common/MenuModel.cs @@ -4,6 +4,7 @@ namespace SmartStore.Web.Models.Common { public partial class MenuModel : ModelBase { + public bool NewsEnabled { get; set; } public bool BlogEnabled { get; set; } public bool RecentlyAddedProductsEnabled { get; set; } public bool ForumEnabled { get; set; } diff --git a/src/Presentation/SmartStore.Web/Views/Common/Menu.cshtml b/src/Presentation/SmartStore.Web/Views/Common/Menu.cshtml index 27e16701ae..1299dfda8e 100644 --- a/src/Presentation/SmartStore.Web/Views/Common/Menu.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Common/Menu.cshtml @@ -48,9 +48,18 @@ @Html.Widget("header_menu_after") -@if (Model.BlogEnabled || Model.ForumEnabled || Model.DisplayAdminLink || Model.DisplayAdminLink) +@if (Model.NewsEnabled || Model.BlogEnabled || Model.ForumEnabled || Model.DisplayAdminLink || Model.DisplayAdminLink) {

    + @if (Model.NewsEnabled) + { +
  • + + + @T("News") + +
  • + } @if (Model.BlogEnabled) {
  • From 826ea7969e7459000945fe41b7de4303f530804e Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 9 Jun 2015 11:23:27 +0200 Subject: [PATCH 0143/1256] Resolves #563 Scheduled Tasks: ensure, that 'LastEndUtc' is ALWAYS set --- changelog.md | 1 + .../Tasks/IScheduleTaskService.cs | 6 ---- .../Tasks/ScheduleTaskService.cs | 31 +++++++------------ .../Plugins/FeedPluginHelper.cs | 13 +++----- .../Controllers/ScheduleTaskController.cs | 6 +--- 5 files changed, 19 insertions(+), 38 deletions(-) diff --git a/changelog.md b/changelog.md index b82b37753b..649abc4e24 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,7 @@ ### Bugfixes * #694 Product variant attribute in product page should not be preselected implicitly * Fixed: If currencies are limited to one for a multi-store, this currency should dominate the setting for the primary store currency +* #563 Scheduled Tasks: ensure, that 'LastEndUtc' is ALWAYS set ## SmartStore.NET 2.2.1 diff --git a/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs b/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs index 54207b308f..fcd853d341 100644 --- a/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs +++ b/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs @@ -47,12 +47,6 @@ public partial interface IScheduleTaskService /// Task void UpdateTask(ScheduleTask task); - /// - /// Ensures that a task is not marked as running - /// - /// Task type - void EnsureTaskIsNotRunning(string type); - /// /// Ensures that a task is not marked as running /// diff --git a/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs b/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs index d31eaa1b0f..25f8fe6f98 100644 --- a/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs +++ b/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs @@ -123,30 +123,23 @@ public virtual void UpdateTask(ScheduleTask task) } /// - /// Ensures that a task is not marked as running - /// - /// Task type - public virtual void EnsureTaskIsNotRunning(string type) - { - var task = GetTaskByType(type); - if (task != null && task.IsRunning) - { - task.LastEndUtc = task.LastStartUtc; - UpdateTask(task); - } - } - - /// - /// Ensures that a task is not marked as running + /// Ensures that a task is not marked as running (normalize last start and end date). /// /// Task identifier + /// Problem can be reproduced by inserting a news object without a language identifier. public virtual void EnsureTaskIsNotRunning(int taskId) { - var task = GetTaskById(taskId); - if (task != null && task.IsRunning) + try { - task.LastEndUtc = task.LastStartUtc; - UpdateTask(task); + if (taskId != 0) + { + _taskRepository.Context.ExecuteSqlCommand("Update [dbo].[ScheduleTask] Set [LastEndUtc] = [LastStartUtc] Where Id = {0} And [LastEndUtc] < [LastStartUtc]", + true, null, taskId); + } + } + catch (Exception exc) + { + exc.Dump(); } } diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs index 633c273f42..235c0bbf40 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs @@ -606,6 +606,7 @@ public bool RunScheduleTask() var task = AsyncRunner.Run((container, ct) => { + int taskId = 0; try { var svc = container.Resolve(); @@ -615,19 +616,15 @@ public bool RunScheduleTask() if (scheduleTask == null) throw new Exception("Schedule task cannot be loaded"); + taskId = scheduleTask.Id; + var job = new Job(scheduleTask); job.Enabled = true; job.Execute(ct, container, false); } - catch (Exception exc) + catch (Exception) { - exc.Dump(); - - try - { - _scheduleTaskService.EnsureTaskIsNotRunning(scheduleTaskType); - } - catch (Exception) { } + _scheduleTaskService.EnsureTaskIsNotRunning(taskId); } }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs index d0f05c079a..16745ce28f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs @@ -182,11 +182,7 @@ public ActionResult RunJob(int id, string returnUrl = "") } catch { - try - { - svc.EnsureTaskIsNotRunning(id); - } - catch { } + svc.EnsureTaskIsNotRunning(id); } }); From c446b8e7944769c090cca91c3208d8debd0727d5 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 9 Jun 2015 11:40:19 +0200 Subject: [PATCH 0144/1256] New resource for inactive attribute combination --- .../Migrations/201505272236124_V222.cs | 23 +++++++++++++++++-- .../Controllers/CatalogHelper.cs | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs b/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs index 6a5f7969a3..62653a9d70 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs @@ -2,8 +2,9 @@ namespace SmartStore.Data.Migrations { using System; using System.Data.Entity.Migrations; - - public partial class V222 : DbMigration + using SmartStore.Data.Setup; + + public partial class V222 : DbMigration, ILocaleResourcesProvider, IDataSeeder { public override void Up() { @@ -26,5 +27,23 @@ public override void Down() DropIndex("dbo.Product", new[] { "Deleted" }); AlterColumn("dbo.Customer", "SystemName", c => c.String()); } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Products.Availability.IsNotActive", + "Not in assortment", + "Nicht im Sortiment"); + + } } } diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index d048a07105..6ecce2697c 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -599,7 +599,7 @@ public ProductDetailsModel PrepareProductDetailModel( if (model.CombinationSelected != null && model.CombinationSelected.IsActive == false) { model.IsAvailable = false; - model.StockAvailability = T("Products.Availability.OutOfStock"); + model.StockAvailability = T("Products.Availability.IsNotActive"); } product.MergeWithCombination(model.CombinationSelected); From 4689e8353f6b634f1f13c99ffb5d663dfe900b57 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 11 Jun 2015 18:57:14 +0200 Subject: [PATCH 0145/1256] Minor change --- src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index acd9041154..21cb3055a1 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -621,7 +621,7 @@ public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExpo var manu = productManufacturer.Manufacturer; writer.WriteStartElement("ProductManufacturer"); - writer.Write("ProductManufacturerId", productManufacturer.Id.ToString()); + writer.Write("Id", productManufacturer.Id.ToString()); writer.Write("IsFeaturedProduct", productManufacturer.IsFeaturedProduct.ToString()); writer.Write("DisplayOrder", productManufacturer.DisplayOrder.ToString()); From e006494117e318db6c9e5a05d83206d53159b122 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 13 Jun 2015 13:03:44 +0200 Subject: [PATCH 0146/1256] New payment method entity and stand-alone page for editing a payment method (no popup window anymore) --- .../Domain/Payments/PaymentMethod.cs | 35 +++++ .../SmartStore.Core/SmartStore.Core.csproj | 1 + .../Mapping/Payments/PaymentMethodMap.cs | 20 +++ ...62_PaymentShippingRestrictions.Designer.cs | 29 ++++ ...06130926062_PaymentShippingRestrictions.cs | 29 ++++ ...130926062_PaymentShippingRestrictions.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 8 ++ .../DependencyRegistrar.cs | 42 +++--- .../Mvc/ProviderModel.cs | 14 +- .../Plugins/PluginMediator.cs | 1 + .../Controllers/PaymentController.cs | 14 ++ .../Models/Payments/PaymentMethodEditModel.cs | 13 ++ .../Administration/SmartStore.Admin.csproj | 2 + .../Administration/Views/Payment/Edit.cshtml | 21 +++ .../Views/Shared/_Providers.cshtml | 18 ++- 15 files changed, 345 insertions(+), 28 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs create mode 100644 src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.resx create mode 100644 src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml diff --git a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs new file mode 100644 index 0000000000..dae3e3dddd --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs @@ -0,0 +1,35 @@ +using System.Runtime.Serialization; + +namespace SmartStore.Core.Domain.Payments +{ + /// + /// Represents a payment method + /// + [DataContract] + public partial class PaymentMethod : BaseEntity + { + /// + /// Gets or sets the payment method system name + /// + [DataMember] + public string PaymentMethodSystemName { get; set; } + + /// + /// Gets or sets identifiers of customer roles (comma separated) to be excluded in checkout + /// + [DataMember] + public string ExcludedCustomerRoleIds { get; set; } + + /// + /// Gets or sets identifiers of countries (comma separated) to be excluded in checkout + /// + [DataMember] + public string ExcludedCountryIds { get; set; } + + /// + /// Gets or sets identifiers of shipping methods (comma separated) to be excluded in checkout + /// + [DataMember] + public string ExcludedShippingMethodIds { get; set; } + } +} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 367040dc86..d9418948fb 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -157,6 +157,7 @@ + diff --git a/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs b/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs new file mode 100644 index 0000000000..3544292bef --- /dev/null +++ b/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs @@ -0,0 +1,20 @@ +using System.Data.Entity.ModelConfiguration; +using SmartStore.Core.Domain.Payments; + +namespace SmartStore.Data.Mapping.Payments +{ + public partial class PaymentMethodMap : EntityTypeConfiguration + { + public PaymentMethodMap() + { + this.ToTable("PaymentMethod"); + this.HasKey(x => x.Id); + + this.Property(x => x.PaymentMethodSystemName).IsRequired().HasMaxLength(4000); + + this.Property(x => x.ExcludedCustomerRoleIds).IsMaxLength(); + this.Property(x => x.ExcludedCountryIds).IsMaxLength(); + this.Property(x => x.ExcludedShippingMethodIds).IsMaxLength(); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.Designer.cs new file mode 100644 index 0000000000..1432d4c15b --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class PaymentShippingRestrictions : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(PaymentShippingRestrictions)); + + string IMigrationMetadata.Id + { + get { return "201506130926062_PaymentShippingRestrictions"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs new file mode 100644 index 0000000000..dad5d45220 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs @@ -0,0 +1,29 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class PaymentShippingRestrictions : DbMigration + { + public override void Up() + { + CreateTable( + "dbo.PaymentMethod", + c => new + { + Id = c.Int(nullable: false, identity: true), + PaymentMethodSystemName = c.String(nullable: false, maxLength: 4000), + ExcludedCustomerRoleIds = c.String(), + ExcludedCountryIds = c.String(), + ExcludedShippingMethodIds = c.String(), + }) + .PrimaryKey(t => t.Id) + .Index(t => t.PaymentMethodSystemName); + } + + public override void Down() + { + DropTable("dbo.PaymentMethod"); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.resx b/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.resx new file mode 100644 index 0000000000..621557bdf4 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 0eeab2be55..103589f9cc 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -116,6 +116,7 @@ Properties\AssemblyVersionInfo.cs + 201403112331027_Initial.cs @@ -272,6 +273,10 @@ 201505272236124_V222.cs + + + 201506130926062_PaymentShippingRestrictions.cs + @@ -529,6 +534,9 @@ 201505272236124_V222.cs + + 201506130926062_PaymentShippingRestrictions.cs + diff --git a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs index 839a8fd01e..549ad459a9 100644 --- a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs +++ b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs @@ -13,12 +13,22 @@ using SmartStore.Core.Caching; using SmartStore.Core.Configuration; using SmartStore.Core.Data; +using SmartStore.Core.Data.Hooks; +using SmartStore.Core.Email; using SmartStore.Core.Events; using SmartStore.Core.Fakes; using SmartStore.Core.Infrastructure; using SmartStore.Core.Infrastructure.DependencyManagement; +using SmartStore.Core.IO.Media; +using SmartStore.Core.IO.VirtualPath; +using SmartStore.Core.IO.WebSite; +using SmartStore.Core.Localization; +using SmartStore.Core.Logging; +using SmartStore.Core.Packaging; using SmartStore.Core.Plugins; +using SmartStore.Core.Themes; using SmartStore.Data; +using SmartStore.Services; using SmartStore.Services.Affiliates; using SmartStore.Services.Authentication; using SmartStore.Services.Authentication.External; @@ -30,49 +40,39 @@ using SmartStore.Services.Customers; using SmartStore.Services.Directory; using SmartStore.Services.Discounts; +using SmartStore.Services.Events; using SmartStore.Services.ExportImport; +using SmartStore.Services.Filter; using SmartStore.Services.Forums; using SmartStore.Services.Helpers; using SmartStore.Services.Localization; -using SmartStore.Core.Logging; +using SmartStore.Services.Logging; using SmartStore.Services.Media; using SmartStore.Services.Messages; using SmartStore.Services.News; using SmartStore.Services.Orders; using SmartStore.Services.Payments; +using SmartStore.Services.Pdf; using SmartStore.Services.Polls; using SmartStore.Services.Security; using SmartStore.Services.Seo; using SmartStore.Services.Shipping; +using SmartStore.Services.Stores; using SmartStore.Services.Tasks; using SmartStore.Services.Tax; +using SmartStore.Services.Themes; using SmartStore.Services.Topics; -using SmartStore.Web.Framework.Mvc.Routes; +using SmartStore.Utilities; +using SmartStore.Web.Framework.Controllers; +using SmartStore.Web.Framework.Localization; using SmartStore.Web.Framework.Mvc.Bundles; +using SmartStore.Web.Framework.Mvc.Routes; +using SmartStore.Web.Framework.Plugins; using SmartStore.Web.Framework.Themes; using SmartStore.Web.Framework.UI; using SmartStore.Web.Framework.WebApi; -using SmartStore.Web.Framework.Plugins; -using SmartStore.Web.Framework.Controllers; -using SmartStore.Services.Filter; -using SmartStore.Core.Data.Hooks; -using SmartStore.Core.Themes; -using SmartStore.Services.Themes; -using SmartStore.Services.Stores; using SmartStore.Web.Framework.WebApi.Configuration; -using SmartStore.Services; using Module = Autofac.Module; -using SmartStore.Core.Localization; -using SmartStore.Web.Framework.Localization; -using SmartStore.Core.Email; -using SmartStore.Services.Events; -using SmartStore.Services.Logging; -using SmartStore.Core.Packaging; -using SmartStore.Core.IO.Media; -using SmartStore.Core.IO.VirtualPath; -using SmartStore.Core.IO.WebSite; -using SmartStore.Utilities; -using SmartStore.Services.Pdf; namespace SmartStore.Web.Framework { diff --git a/src/Presentation/SmartStore.Web.Framework/Mvc/ProviderModel.cs b/src/Presentation/SmartStore.Web.Framework/Mvc/ProviderModel.cs index bcef0c17b5..5b1d1ecfc7 100644 --- a/src/Presentation/SmartStore.Web.Framework/Mvc/ProviderModel.cs +++ b/src/Presentation/SmartStore.Web.Framework/Mvc/ProviderModel.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Web; using System.Web.Mvc; -using System.Web.Routing; using SmartStore.Core.Plugins; +using SmartStore.Services.Payments; using SmartStore.Web.Framework.Localization; namespace SmartStore.Web.Framework.Mvc @@ -12,6 +10,8 @@ namespace SmartStore.Web.Framework.Mvc public class ProviderModel : ModelBase, ILocalizedModel { private IList _locales; + + public Type ProviderType { get; set; } [SmartResourceDisplayName("Common.SystemName")] public string SystemName { get; set; } @@ -61,6 +61,14 @@ public IList Locales _locales = value; } } + + public bool IsPaymentMethod + { + get + { + return ProviderType.Equals(typeof(IPaymentMethod)); + } + } } public class ProviderLocalizedModel : ILocalizedModelLocal diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/PluginMediator.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/PluginMediator.cs index 312c587703..5e19ca26c8 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/PluginMediator.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/PluginMediator.cs @@ -153,6 +153,7 @@ public TModel ToProviderModel(Provider provider, b var metadata = provider.Metadata; var model = new TModel(); + model.ProviderType = typeof(TProvider); model.SystemName = metadata.SystemName; model.FriendlyName = forEdit ? metadata.FriendlyName : GetLocalizedFriendlyName(metadata); model.Description = forEdit ? metadata.Description : GetLocalizedDescription(metadata); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs index 9a8fa7de43..4f5069d636 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs @@ -93,6 +93,20 @@ public ActionResult ActivateProvider(string systemName, bool activate) return RedirectToAction("Providers"); } + public ActionResult Edit(string systemName) + { + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) + return AccessDeniedView(); + + var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(systemName); + + var model = _pluginMediator.ToProviderModel(paymentMethod); + + model.IconUrl = _pluginMediator.GetIconUrl(model.PluginDescriptor); + + return View(model); + } + #endregion } } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs new file mode 100644 index 0000000000..2bd13383ca --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using SmartStore.Web.Framework.Mvc; + +namespace SmartStore.Admin.Models.Payments +{ + public class PaymentMethodEditModel : ProviderModel + { + public string IconUrl { get; set; } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index fd2aa999ac..51dabda6e7 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -251,6 +251,7 @@ + @@ -493,6 +494,7 @@ + diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml new file mode 100644 index 0000000000..dce17feea7 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml @@ -0,0 +1,21 @@ +@model PaymentMethodEditModel + +@{ + ViewBag.Title = T("Common.Edit").Text + " - " + Model.FriendlyName; +} + +@using (Html.BeginForm()) +{ +
    +
    + @Model.FriendlyName + @ViewBag.Title (@(Model.SystemName)) + (@T("Admin.Common.BackToList")) +
    +
    + + +
    +
    + +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/_Providers.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/_Providers.cshtml index fa393778d5..c0907267c1 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/_Providers.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/_Providers.cshtml @@ -84,10 +84,20 @@
    @if (item.IsEditable) { - - - @T("Admin.Common.Edit") - + if (item.IsPaymentMethod) + { + + + @T("Admin.Common.Edit") + + } + else + { + + + @T("Admin.Common.Edit") + + } } @if (item.IsConfigurable) { From 2548956e15d3770dbb3433cc063aca0ce82e77a8 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 15 Jun 2015 14:35:23 +0200 Subject: [PATCH 0147/1256] Editing of payment method restrictions --- ...06130926062_PaymentShippingRestrictions.cs | 26 ++- .../Payments/IPaymentService.cs | 21 +++ .../Payments/PaymentService.cs | 52 +++++- .../Administration/Content/admin.less | 23 +++ .../Controllers/PaymentController.cs | 147 +++++++++++++++- .../Models/Payments/PaymentMethodEditModel.cs | 10 +- .../Administration/Views/Payment/Edit.cshtml | 159 +++++++++++++++++- .../Payments/PaymentServiceTests.cs | 12 +- 8 files changed, 429 insertions(+), 21 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs index dad5d45220..175f4ea9ce 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs @@ -2,8 +2,9 @@ namespace SmartStore.Data.Migrations { using System; using System.Data.Entity.Migrations; - - public partial class PaymentShippingRestrictions : DbMigration + using SmartStore.Data.Setup; + + public partial class PaymentShippingRestrictions : DbMigration, ILocaleResourcesProvider, IDataSeeder { public override void Up() { @@ -25,5 +26,26 @@ public override void Down() { DropTable("dbo.PaymentMethod"); } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Admin.Common.Restrictions", + "Restrictions", + "Einschrnkungen"); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.RestrictionNote", + "Select customer roles, shipping methods and countries for which you do not want to offer this payment method.", + "Whlen Sie Kundengruppen, Versandarten und Lnder, bei denen sie diese Zahlungsmethode nicht anbieten mchten."); + } } } diff --git a/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs b/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs index 0d56507652..3757dcb42d 100644 --- a/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Domain.Payments; using SmartStore.Core.Plugins; namespace SmartStore.Services.Payments @@ -37,6 +38,26 @@ public partial interface IPaymentService IEnumerable> LoadAllPaymentMethods(int storeId = 0); + /// + /// Gets a payment method by system name + /// + /// Provider system name + /// Payment method entity + PaymentMethod GetPaymentMethodBySystemName(string systemName); + + /// + /// Insert a payment method + /// + /// Payment method + void InsertPaymentMethod(PaymentMethod paymentMethod); + + /// + /// Updates a payment method + /// + /// Payment method + void UpdatePaymentMethod(PaymentMethod paymentMethod); + + /// /// Pre process a payment diff --git a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs index 69f2d391de..ea0d560fce 100644 --- a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs @@ -4,6 +4,7 @@ using SmartStore.Core.Data; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; +using SmartStore.Core.Events; using SmartStore.Core.Plugins; using SmartStore.Services.Configuration; using SmartStore.Services.Localization; @@ -17,12 +18,14 @@ public partial class PaymentService : IPaymentService { #region Fields + private readonly IRepository _paymentMethodRepository; private readonly PaymentSettings _paymentSettings; private readonly IPluginFinder _pluginFinder; private readonly ShoppingCartSettings _shoppingCartSettings; private readonly ISettingService _settingService; private readonly ILocalizationService _localizationService; private readonly IProviderManager _providerManager; + private readonly IEventPublisher _eventPublisher; #endregion @@ -36,19 +39,23 @@ public partial class PaymentService : IPaymentService /// Shopping cart settings /// Plugin service public PaymentService( + IRepository paymentMethodRepository, PaymentSettings paymentSettings, IPluginFinder pluginFinder, ShoppingCartSettings shoppingCartSettings, ISettingService settingService, ILocalizationService localizationService, - IProviderManager providerManager) + IProviderManager providerManager, + IEventPublisher eventPublisher) { + this._paymentMethodRepository = paymentMethodRepository; this._paymentSettings = paymentSettings; this._pluginFinder = pluginFinder; this._shoppingCartSettings = shoppingCartSettings; this._settingService = settingService; this._localizationService = localizationService; this._providerManager = providerManager; + this._eventPublisher = eventPublisher; } #endregion @@ -122,6 +129,49 @@ public virtual IEnumerable> LoadAllPaymentMethods(int s } + /// + /// Gets a payment method by system name + /// + /// Provider system name + /// Payment method entity + public virtual PaymentMethod GetPaymentMethodBySystemName(string systemName) + { + if (systemName.HasValue()) + { + return _paymentMethodRepository.Table.FirstOrDefault(x => x.PaymentMethodSystemName == systemName); + } + return null; + } + + /// + /// Insert a payment method + /// + /// Payment method + public virtual void InsertPaymentMethod(PaymentMethod paymentMethod) + { + if (paymentMethod == null) + throw new ArgumentNullException("paymentMethod"); + + _paymentMethodRepository.Insert(paymentMethod); + + _eventPublisher.EntityInserted(paymentMethod); + } + + /// + /// Updates a payment method + /// + /// Payment method + public virtual void UpdatePaymentMethod(PaymentMethod paymentMethod) + { + if (paymentMethod == null) + throw new ArgumentNullException("paymentMethod"); + + _paymentMethodRepository.Update(paymentMethod); + + _eventPublisher.EntityUpdated(paymentMethod); + } + + /// /// Pre process a payment /// diff --git a/src/Presentation/SmartStore.Web/Administration/Content/admin.less b/src/Presentation/SmartStore.Web/Administration/Content/admin.less index c743cf9e3f..20f7c1f835 100644 --- a/src/Presentation/SmartStore.Web/Administration/Content/admin.less +++ b/src/Presentation/SmartStore.Web/Administration/Content/admin.less @@ -1197,6 +1197,29 @@ table.payment-method-features td { font-size: 12px; } +/* payment methods restrictions +-------------------------------------------------------------- */ +.payment-restrictions th label { + margin: 0; +} +.payment-restrictions .column-customerroles, +.payment-restrictions .column-shippingmethods { + width: 18%; +} +.payment-restrictions .column-countries { + width: 64%; + + > div { + display: table-row; + } + + .country-countainer { + display: table-cell; + width: 25%; + padding-right: 10px; + } +} + /* Special icons */ .icon-active-true { diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs index 4f5069d636..2f725737b7 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs @@ -1,14 +1,19 @@ -using System.Collections.Generic; +using System.Linq; +using System.Collections.Generic; using System.Web.Mvc; using SmartStore.Admin.Models.Payments; using SmartStore.Core.Domain.Payments; using SmartStore.Core.Plugins; using SmartStore.Services; +using SmartStore.Services.Customers; +using SmartStore.Services.Directory; using SmartStore.Services.Localization; using SmartStore.Services.Payments; using SmartStore.Services.Security; +using SmartStore.Services.Shipping; using SmartStore.Web.Framework.Controllers; using SmartStore.Web.Framework.Plugins; +using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Controllers { @@ -22,6 +27,10 @@ public partial class PaymentController : AdminControllerBase private readonly PaymentSettings _paymentSettings; private readonly IPluginFinder _pluginFinder; private readonly PluginMediator _pluginMediator; + private readonly ILanguageService _languageService; + private readonly ICustomerService _customerService; + private readonly IShippingService _shippingService; + private readonly ICountryService _countryService; #endregion @@ -32,20 +41,80 @@ public PaymentController( IPaymentService paymentService, PaymentSettings paymentSettings, IPluginFinder pluginFinder, - PluginMediator pluginMediator) + PluginMediator pluginMediator, + ILanguageService languageService, + ICustomerService customerService, + IShippingService shippingService, + ICountryService countryService) { this._commonServices = commonServices; this._paymentService = paymentService; this._paymentSettings = paymentSettings; this._pluginFinder = pluginFinder; this._pluginMediator = pluginMediator; + this._languageService = languageService; + this._customerService = customerService; + this._shippingService = shippingService; + this._countryService = countryService; } - #endregion  + #endregion + + #region Utilities + + private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, PaymentMethod paymentMethod) + { + SelectListItem item = null; + var customerRoles = _customerService.GetAllCustomerRoles(true); + var shippingMethods = _shippingService.GetAllShippingMethods(); + var countries = _countryService.GetAllCountries(true); - #region Methods + model.AvailableCustomerRoles = new List(); + model.AvailableShippingMethods = new List(); + model.AvaliableCountries = new List(); - public ActionResult Providers() + foreach (var role in customerRoles.OrderBy(x => x.Name)) + { + model.AvailableCustomerRoles.Add(new SelectListItem { Text = role.Name, Value = role.Id.ToString() }); + } + + foreach (var shippingMethod in shippingMethods.OrderBy(x => x.Name)) + { + model.AvailableShippingMethods.Add(new SelectListItem { Text = shippingMethod.GetLocalized(x => x.Name), Value = shippingMethod.Id.ToString() }); + } + + foreach (var country in countries.OrderBy(x => x.Name)) + { + model.AvaliableCountries.Add(new SelectListItem { Text = country.GetLocalized(x => x.Name), Value = country.Id.ToString() }); + } + + if (paymentMethod != null) + { + foreach (var id in paymentMethod.ExcludedCustomerRoleIds.SplitSafe(",")) + { + if ((item = model.AvailableCustomerRoles.FirstOrDefault(x => x.Value == id)) != null) + item.Selected = true; + } + + foreach (var id in paymentMethod.ExcludedShippingMethodIds.SplitSafe(",")) + { + if ((item = model.AvailableShippingMethods.FirstOrDefault(x => x.Value == id)) != null) + item.Selected = true; + } + + foreach (var id in paymentMethod.ExcludedCountryIds.SplitSafe(",")) + { + if ((item = model.AvaliableCountries.FirstOrDefault(x => x.Value == id)) != null) + item.Selected = true; + } + } + } + + #endregion + + #region Methods + + public ActionResult Providers() { if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) return AccessDeniedView(); @@ -98,15 +167,77 @@ public ActionResult Edit(string systemName) if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) return AccessDeniedView(); - var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(systemName); + var provider = _paymentService.LoadPaymentMethodBySystemName(systemName); + var paymentMethod = _paymentService.GetPaymentMethodBySystemName(systemName); + + var model = _pluginMediator.ToProviderModel(provider, true); - var model = _pluginMediator.ToProviderModel(paymentMethod); + AddLocales(_languageService, model.Locales, (locale, languageId) => + { + locale.FriendlyName = _pluginMediator.GetLocalizedFriendlyName(provider.Metadata, languageId, false); + locale.Description = _pluginMediator.GetLocalizedDescription(provider.Metadata, languageId, false); + }); - model.IconUrl = _pluginMediator.GetIconUrl(model.PluginDescriptor); + PreparePaymentMethodEditModel(model, paymentMethod); return View(model); } + [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] + public ActionResult Edit(string systemName, bool continueEditing, ProviderModel model) + { + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) + return AccessDeniedView(); + + var provider = _paymentService.LoadPaymentMethodBySystemName(systemName); + if (provider == null) + return HttpNotFound(); + + _pluginMediator.SetSetting(provider.Metadata, "FriendlyName", model.FriendlyName); + _pluginMediator.SetSetting(provider.Metadata, "Description", model.Description); + + foreach (var localized in model.Locales) + { + _pluginMediator.SaveLocalizedValue(provider.Metadata, localized.LanguageId, "FriendlyName", localized.FriendlyName); + _pluginMediator.SaveLocalizedValue(provider.Metadata, localized.LanguageId, "Description", localized.Description); + } + + var paymentMethod = _paymentService.GetPaymentMethodBySystemName(systemName); + + if (paymentMethod == null) + paymentMethod = new PaymentMethod { PaymentMethodSystemName = systemName }; + + var customerRoleIds = Request.Form.AllKeys + .Where(x => x.StartsWith("CustomerRole_")) + .Select(x => x.Replace("CustomerRole_", "")) + .ToList(); + + var shippingMethodIds = Request.Form.AllKeys + .Where(x => x.StartsWith("ShippingMethod_")) + .Select(x => x.Replace("ShippingMethod_", "")) + .ToList(); + + var countryIds = Request.Form.AllKeys + .Where(x => x.StartsWith("Country_")) + .Select(x => x.Replace("Country_", "")) + .ToList(); + + paymentMethod.ExcludedCustomerRoleIds = string.Join(",", customerRoleIds); + paymentMethod.ExcludedShippingMethodIds = string.Join(",", shippingMethodIds); + paymentMethod.ExcludedCountryIds = string.Join(",", countryIds); + + if (paymentMethod.Id == 0) + _paymentService.InsertPaymentMethod(paymentMethod); + else + _paymentService.UpdatePaymentMethod(paymentMethod); + + NotifySuccess(_commonServices.Localization.GetResource("Admin.Common.DataEditSuccess")); + + return (continueEditing ? + RedirectToAction("Edit", "Payment", new { systemName = systemName }) : + RedirectToAction("Providers", "Payment")); + } + #endregion } } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs index 2bd13383ca..e2f2f40437 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs @@ -1,13 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; +using System.Collections.Generic; +using System.Web.Mvc; using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Models.Payments { public class PaymentMethodEditModel : ProviderModel { - public string IconUrl { get; set; } + public List AvailableCustomerRoles { get; set; } + public List AvailableShippingMethods { get; set; } + public List AvaliableCountries { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml index dce17feea7..df02bbbd14 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml @@ -4,7 +4,7 @@ ViewBag.Title = T("Common.Edit").Text + " - " + Model.FriendlyName; } -@using (Html.BeginForm()) +@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "paymentmethod-form" })) {
    @@ -17,5 +17,160 @@
    + + @Html.ValidationSummary(false) + @Html.HiddenFor(model => model.SystemName) -} \ No newline at end of file + + @Html.SmartStore().TabStrip().Name("paymentmethod-edit").Items(x => + { + x.Add().Text(T("Admin.Common.General").Text).Content(TabGeneral()).Selected(true); + x.Add().Text(T("Admin.Common.Restrictions").Text).Content(TabRestrictions()); + + EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "paymentmethod-edit", this.Html, this.Model)); + }) +} + +@helper TabGeneral() +{ + @(Html.LocalizedEditor("paymentmethod-general-localized", + @
@Html.SmartLabelFor(model => model.DisplayOrder) diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs index 0a3643f1e7..22368df310 100644 --- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs @@ -120,9 +120,9 @@ protected ForumGroupModel PrepareForumGroupModel(ForumGroup forumGroup) var forumGroupModel = new ForumGroupModel { Id = forumGroup.Id, - Name = forumGroup.Name, - SeName = forumGroup.GetSeName(), - Description = forumGroup.Description, + Name = forumGroup.GetLocalized(x => x.Name), + Description = forumGroup.GetLocalized(x => x.Description), + SeName = forumGroup.GetSeName() }; var forums = _forumService.GetAllForumsByGroupId(forumGroup.Id); @@ -171,7 +171,7 @@ protected IEnumerable ForumGroupsForumsList() foreach (var fg in forumGroups) { // Add the forum group with Value of 0 so it won't be used as a target forum - forumsList.Add(new SelectListItem { Text = fg.Name, Value = "0" }); + forumsList.Add(new SelectListItem { Text = fg.GetLocalized(x => x.Name), Value = "0" }); var forums = _forumService.GetAllForumsByGroupId(fg.Id); foreach (var f in forums) @@ -1513,7 +1513,7 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, string foreach (var fg in forumGroups) { // Add the forum group with value as '-' so it can't be used as a target forum id - forumsSelectList.Add(new SelectListItem { Text = fg.Name, Value = "-" }); + forumsSelectList.Add(new SelectListItem { Text = fg.GetLocalized(x => x.Name), Value = "-" }); var forums = _forumService.GetAllForumsByGroupId(fg.Id); foreach (var f in forums) @@ -1683,7 +1683,7 @@ public ActionResult ForumBreadcrumb(int? forumGroupId, int? forumId, int? forumT if (forumGroup != null) { model.ForumGroupId = forumGroup.Id; - model.ForumGroupName = forumGroup.Name; + model.ForumGroupName = forumGroup.GetLocalized(x => x.Name); model.ForumGroupSeName = forumGroup.GetSeName(); } From 92fa8035b2b849cab8d7cebc7b93ca5e21e7c61e Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 7 May 2015 18:09:52 +0200 Subject: [PATCH 0113/1256] Localized properties for forums --- changelog.md | 2 +- .../SmartStore.Core/Domain/Forums/Forum.cs | 4 +- .../201505061813010_CountryMultistore.cs | 10 +- .../Messages/MessageTokenProvider.cs | 2 +- .../SmartStore.Services/Seo/SeoExtensions.cs | 13 -- .../Controllers/ForumController.cs | 39 +++++- .../Infrastructure/AutoMapperStartupTask.cs | 2 + .../Models/Forums/ForumModel.cs | 27 +++- .../Views/Forum/_CreateOrUpdateForum.cshtml | 123 ++++++++++++------ .../Controllers/BoardsController.cs | 32 ++--- .../Controllers/CustomerController.cs | 4 +- 11 files changed, 182 insertions(+), 76 deletions(-) diff --git a/changelog.md b/changelog.md index 287c5763cc..22107a4bd1 100644 --- a/changelog.md +++ b/changelog.md @@ -16,7 +16,7 @@ ### Improvements * PDF converter: first init is much faster now -* Localized properties for forum groups +* Localized properties for forums and forum groups ### Bugfixes * PDF converter: fixed _QFont::setPixelSize_ bug diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs b/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs index 4823f78825..1af950f759 100644 --- a/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs +++ b/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs @@ -1,11 +1,13 @@ using System; +using SmartStore.Core.Domain.Localization; +using SmartStore.Core.Domain.Seo; namespace SmartStore.Core.Domain.Forums { /// /// Represents a forum /// - public partial class Forum : BaseEntity + public partial class Forum : BaseEntity, ILocalizedEntity, ISlugSupported { /// /// Gets or sets the forum group identifier diff --git a/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs index c067c886c9..9ba99664ba 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505061813010_CountryMultistore.cs @@ -33,8 +33,14 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Admin.ContentManagement.Forums.ForumGroup.Fields.SeName", "URL-Alias", "URL-Alias", - "Set a search engine friendly page name e.g. 'the-best-forum' to make your page URL 'http://www.yourStore.com/the-best-forum'. Leave empty to generate it automatically based on the name of the forum group.", - "Legt einen Suchmaschinen-freundlichen Seitennamen fr die Forengruppe fest. 'Tolles Forum' resultiert bspw. in '~/tolles-forum'. Standard ist der Name der Forengruppe."); + "Set a search engine friendly page name e.g. 'the-best-forumgroup' to make your page URL 'http://www.yourStore.com/the-best-forumgroup'. Leave empty to generate it automatically based on the name of the forum group.", + "Legt einen Suchmaschinen-freundlichen Seitennamen fr die Forengruppe fest. 'Tolle Forengruppe' resultiert bspw. in '~/tolle-forengruppe'. Standard ist der Name der Forengruppe."); + + builder.AddOrUpdate("Admin.ContentManagement.Forums.Forum.Fields.SeName", + "URL-Alias", + "URL-Alias", + "Set a search engine friendly page name e.g. 'the-best-forum' to make your page URL 'http://www.yourStore.com/the-best-forum'. Leave empty to generate it automatically based on the name of the forum.", + "Legt einen Suchmaschinen-freundlichen Seitennamen fr das Forum fest. 'Tolles Forum' resultiert bspw. in '~/tolles-forum'. Standard ist der Name des Forums."); } } } diff --git a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs index 5b11022c3d..6f9a455c53 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs @@ -976,7 +976,7 @@ public virtual void AddForumTokens(IList tokens, Forum forum) //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) var forumUrl = string.Format("{0}boards/forum/{1}/{2}", _webHelper.GetStoreLocation(false), forum.Id, forum.GetSeName()); tokens.Add(new Token("Forums.ForumURL", forumUrl, true)); - tokens.Add(new Token("Forums.ForumName", forum.Name)); + tokens.Add(new Token("Forums.ForumName", forum.GetLocalized(x => x.Name))); //event notification _eventPublisher.EntityTokensAdded(forum, tokens); diff --git a/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs b/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs index 0c5e3e1699..8bbb6e60fe 100644 --- a/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs +++ b/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs @@ -76,19 +76,6 @@ public static string GetSeName(this NewsItem newsItem) #region Forum - /// - /// Gets Forum SE (search engine) name - /// - /// Forum - /// Forum SE (search engine) name - public static string GetSeName(this Forum forum) - { - if (forum == null) - throw new ArgumentNullException("forum"); - string seName = GetSeName(forum.Name); - return seName; - } - /// /// Gets ForumTopic SE (search engine) name /// diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs index 4b20161a69..988c4164de 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs @@ -83,6 +83,19 @@ private void UpdateLocales(ForumGroupModel model, ForumGroup forumGroup) } } + [NonAction] + private void UpdateLocales(ForumModel model, Forum forum) + { + foreach (var localized in model.Locales) + { + _localizedEntityService.SaveLocalizedValue(forum, x => x.Name, localized.Name, localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(forum, x => x.Description, localized.Description, localized.LanguageId); + + var seName = forum.ValidateSeName(localized.SeName, localized.Name, false, localized.LanguageId); + _urlRecordService.SaveSlug(forum, seName, localized.LanguageId); + } + } + #endregion #region List @@ -175,13 +188,16 @@ public ActionResult CreateForum() if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); - var model = new ForumModel(); + var model = new ForumModel { DisplayOrder = 1 }; + + AddLocales(_languageService, model.Locales); + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); model.ForumGroups.Add(forumGroupModel); } - model.DisplayOrder = 1; + return View(model); } @@ -200,7 +216,11 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing) _forumService.InsertForum(forum); + model.SeName = forum.ValidateSeName(model.SeName, forum.Name, true); + _urlRecordService.SaveSlug(forum, model.SeName, 0); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Added")); + return continueEditing ? RedirectToAction("EditForum", new { forum.Id }) : RedirectToAction("List"); } @@ -286,6 +306,14 @@ public ActionResult EditForum(int id) return RedirectToAction("List"); var model = forum.ToModel(); + + AddLocales(_languageService, model.Locales, (locale, languageId) => + { + locale.Name = forum.GetLocalized(x => x.Name, languageId, false, false); + locale.Description = forum.GetLocalized(x => x.Description, languageId, false, false); + locale.SeName = forum.GetSeName(languageId, false, false); + }); + foreach (var forumGroup in _forumService.GetAllForumGroups(true)) { var forumGroupModel = forumGroup.ToModel(); @@ -308,9 +336,16 @@ public ActionResult EditForum(ForumModel model, bool continueEditing) { forum = model.ToEntity(forum); forum.UpdatedOnUtc = DateTime.UtcNow; + _forumService.UpdateForum(forum); + model.SeName = forum.ValidateSeName(model.SeName, forum.Name, true); + _urlRecordService.SaveSlug(forum, model.SeName, 0); + + UpdateLocales(model, forum); + NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Updated")); + return continueEditing ? RedirectToAction("EditForum", forum.Id) : RedirectToAction("List"); } diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index 4ef685dcc3..d9331cdd05 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -422,6 +422,8 @@ public void Execute() .ForMember(dest => dest.UpdatedOnUtc, mo => mo.Ignore()) .ForMember(dest => dest.Forums, mo => mo.Ignore()); Mapper.CreateMap() + .ForMember(dest => dest.Locales, mo => mo.Ignore()) + .ForMember(dest => dest.SeName, mo => mo.MapFrom(src => src.GetSeName(0, true, false))) .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) .ForMember(dest => dest.ForumGroups, mo => mo.Ignore()); Mapper.CreateMap() diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumModel.cs index fdf1d5d2c3..98fa537748 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumModel.cs @@ -4,16 +4,18 @@ using FluentValidation.Attributes; using SmartStore.Admin.Validators.Forums; using SmartStore.Web.Framework; +using SmartStore.Web.Framework.Localization; using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Models.Forums { [Validator(typeof(ForumValidator))] - public class ForumModel : EntityModelBase + public class ForumModel : EntityModelBase, ILocalizedModel { public ForumModel() { ForumGroups = new List(); + Locales = new List(); } [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.ForumGroupId")] @@ -23,6 +25,10 @@ public ForumModel() [AllowHtml] public string Name { get; set; } + [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.SeName")] + [AllowHtml] + public string SeName { get; set; } + [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.Description")] [AllowHtml] public string Description { get; set; } @@ -34,5 +40,24 @@ public ForumModel() public DateTime CreatedOn { get; set; } public List ForumGroups { get; set; } + + public IList Locales { get; set; } } + + public class ForumLocalizedModel : ILocalizedModelLocal + { + public int LanguageId { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.Name")] + [AllowHtml] + public string Name { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.SeName")] + [AllowHtml] + public string SeName { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.Forums.Forum.Fields.Description")] + [AllowHtml] + public string Description { get; set; } + } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForum.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForum.cshtml index 8f2a0c04d6..2d27a88242 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForum.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForum.cshtml @@ -3,42 +3,91 @@ @using Telerik.Web.Mvc.UI; @Html.ValidationSummary(true) @Html.HiddenFor(model => model.Id) + +@(Html.LocalizedEditor("forumgroup-localized", + @ + + + + + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Locales[item].Name) + + @Html.EditorFor(model => Model.Locales[item].Name) + @Html.ValidationMessageFor(model => model.Locales[item].Name) +
+ @Html.SmartLabelFor(model => model.Locales[item].SeName) + + @Html.EditorFor(model => model.Locales[item].SeName) + @Html.ValidationMessageFor(model => model.Locales[item].SeName) +
+ @Html.SmartLabelFor(model => model.Locales[item].Description) + + @Html.TextAreaFor(model => model.Locales[item].Description, new { @class = "input-large" }) + @Html.ValidationMessageFor(model => model.Locales[item].Description) +
+ @Html.HiddenFor(model => model.Locales[item].LanguageId) +
+ , + @ + + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Name) + + @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ @Html.SmartLabelFor(model => model.SeName) + + @Html.EditorFor(x => x.SeName) + @Html.ValidationMessageFor(model => model.SeName) +
+ @Html.SmartLabelFor(model => model.Description) + + @Html.TextAreaFor(model => model.Description, new { @class = "input-large" }) + @Html.ValidationMessageFor(model => model.Description) +
+)) + - - - - - - - - - - - - - - - - + + + + + + + +
- @Html.SmartLabelFor(model => model.ForumGroupId) - - @Html.DropDownListFor(model => model.ForumGroupId, Model.ForumGroups.Select(x => - new SelectListItem { Value = x.Id.ToString(), Text = x.Name })) - @Html.ValidationMessageFor(model => model.ForumGroupId) -
- @Html.SmartLabelFor(model => model.Name) - - @Html.EditorFor(model => model.Name) - @Html.ValidationMessageFor(model => model.Name) -
- @Html.SmartLabelFor(model => model.Description) - - @Html.TextAreaFor(model => model.Description) - @Html.ValidationMessageFor(model => model.Description) -
- @Html.SmartLabelFor(model => model.DisplayOrder) - - @Html.EditorFor(model => model.DisplayOrder) - @Html.ValidationMessageFor(model => model.DisplayOrder) -
+ @Html.SmartLabelFor(model => model.ForumGroupId) + + @Html.DropDownListFor(model => model.ForumGroupId, Model.ForumGroups.Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Name })) + @Html.ValidationMessageFor(model => model.ForumGroupId) +
+ @Html.SmartLabelFor(model => model.DisplayOrder) + + @Html.EditorFor(model => model.DisplayOrder) + @Html.ValidationMessageFor(model => model.DisplayOrder) +
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs index 22368df310..d9dcc8baaa 100644 --- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs @@ -104,9 +104,9 @@ protected ForumRowModel PrepareForumRowModel(Forum forum) var forumModel = new ForumRowModel { Id = forum.Id, - Name = forum.Name, + Name = forum.GetLocalized(x => x.Name), SeName = forum.GetSeName(), - Description = forum.Description, + Description = forum.GetLocalized(x => x.Description), NumTopics = forum.NumTopics, NumPosts = forum.NumPosts, LastPostId = forum.LastPostId, @@ -176,7 +176,7 @@ protected IEnumerable ForumGroupsForumsList() var forums = _forumService.GetAllForumsByGroupId(fg.Id); foreach (var f in forums) { - forumsList.Add(new SelectListItem { Text = string.Format("{0}{1}", separator, f.Name), Value = f.Id.ToString() }); + forumsList.Add(new SelectListItem { Text = string.Format("{0}{1}", separator, f.GetLocalized(x => x.Name)), Value = f.Id.ToString() }); } } @@ -335,9 +335,9 @@ public ActionResult Forum(int id, int page = 1) { var model = new ForumPageModel(); model.Id = forum.Id; - model.Name = forum.Name; + model.Name = forum.GetLocalized(x => x.Name); model.SeName = forum.GetSeName(); - model.Description = forum.Description; + model.Description = forum.GetLocalized(x => x.Description); int pageSize = 10; if (_forumSettings.TopicsPageSize > 0) @@ -405,7 +405,7 @@ public ActionResult ForumRss(int id) var feedDescription = _localizationService.GetResource("Forum.ForumFeedDescription"); var feed = new SyndicationFeed( - string.Format(feedTitle, _storeContext.CurrentStore.Name, forum.Name), + string.Format(feedTitle, _storeContext.CurrentStore.Name, forum.GetLocalized(x => x.Name)), feedDescription, new Uri(url), string.Format("ForumRSS:{0}", forum.Id), @@ -731,7 +731,7 @@ public ActionResult TopicCreate(int id) model.Id = 0; model.IsEdit = false; model.ForumId = forum.Id; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumSeName = forum.GetSeName(); model.ForumEditor = _forumSettings.ForumEditor; model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(_workContext.CurrentCustomer); @@ -854,7 +854,7 @@ public ActionResult TopicCreate(EditForumTopicModel model) model.TopicPriorities = ForumTopicTypesList(); model.IsEdit = false; model.ForumId = forum.Id; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumSeName = forum.GetSeName(); model.Id = 0; model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(_workContext.CurrentCustomer); @@ -894,7 +894,7 @@ public ActionResult TopicEdit(int id) model.IsEdit = true; model.TopicPriorities = ForumTopicTypesList(); - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumSeName = forum.GetSeName(); model.Text = firstPost.Text; model.Subject = forumTopic.Subject; @@ -1042,7 +1042,7 @@ public ActionResult TopicEdit(EditForumTopicModel model) // redisplay form model.TopicPriorities = ForumTopicTypesList(); model.IsEdit = true; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumSeName = forum.GetSeName(); model.ForumId = forum.Id; model.ForumEditor = _forumSettings.ForumEditor; @@ -1122,7 +1122,7 @@ public ActionResult PostCreate(int id, int? quote) ForumTopicId = forumTopic.Id, IsEdit = false, ForumEditor = _forumSettings.ForumEditor, - ForumName = forum.Name, + ForumName = forum.GetLocalized(x => x.Name), ForumTopicSubject = forumTopic.Subject, ForumTopicSeName = forumTopic.GetSeName(), IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer), @@ -1261,7 +1261,7 @@ public ActionResult PostCreate(EditForumPostModel model) return RedirectToRoute("Boards"); model.IsEdit = false; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumTopicId = forumTopic.Id; model.ForumTopicSubject = forumTopic.Subject; model.ForumTopicSeName = forumTopic.GetSeName(); @@ -1307,7 +1307,7 @@ public ActionResult PostEdit(int id) ForumTopicId = forumTopic.Id, IsEdit = true, ForumEditor = _forumSettings.ForumEditor, - ForumName = forum.Name, + ForumName = forum.GetLocalized(x => x.Name), ForumTopicSubject = forumTopic.Subject, ForumTopicSeName = forumTopic.GetSeName(), IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(_workContext.CurrentCustomer), @@ -1430,7 +1430,7 @@ public ActionResult PostEdit(EditForumPostModel model) //redisplay form model.IsEdit = true; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumTopicId = forumTopic.Id; model.ForumTopicSubject = forumTopic.Subject; model.ForumTopicSeName = forumTopic.GetSeName(); @@ -1520,7 +1520,7 @@ public ActionResult Search(string searchterms, bool? adv, string forumId, string { forumsSelectList.Add(new SelectListItem { - Text = string.Format("{0}{1}", separator, f.Name), + Text = string.Format("{0}{1}", separator, f.GetLocalized(x => x.Name)), Value = f.Id.ToString() }); } @@ -1675,7 +1675,7 @@ public ActionResult ForumBreadcrumb(int? forumGroupId, int? forumId, int? forumT if (forum != null) { model.ForumId = forum.Id; - model.ForumName = forum.Name; + model.ForumName = forum.GetLocalized(x => x.Name); model.ForumSeName = forum.GetSeName(); } diff --git a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs index d9e4d85eb7..52d7118d68 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs @@ -1738,12 +1738,12 @@ public ActionResult ForumSubscriptions(int? page) var forum = _forumService.GetForumById(forumId); if (forum != null) { - title = forum.Name; + title = forum.GetLocalized(x => x.Name); slug = forum.GetSeName(); } } - model.ForumSubscriptions.Add(new ForumSubscriptionModel() + model.ForumSubscriptions.Add(new ForumSubscriptionModel { Id = forumSubscription.Id, ForumTopicId = forumTopicId, From 1488a230a7f69879a1946700594fcb65b654e317 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 7 May 2015 21:22:20 +0200 Subject: [PATCH 0114/1256] Forum tokens are now resolved in context of language id --- .../SmartStore.Services/Messages/IMessageTokenProvider.cs | 2 +- .../SmartStore.Services/Messages/MessageTokenProvider.cs | 6 +++--- .../SmartStore.Services/Messages/WorkflowMessageService.cs | 7 +++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Messages/IMessageTokenProvider.cs b/src/Libraries/SmartStore.Services/Messages/IMessageTokenProvider.cs index b70bcdd0bf..add0f4e57a 100644 --- a/src/Libraries/SmartStore.Services/Messages/IMessageTokenProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/IMessageTokenProvider.cs @@ -39,7 +39,7 @@ public partial interface IMessageTokenProvider void AddProductTokens(IList tokens, Product product, int languageId); - void AddForumTokens(IList tokens, Forum forum); + void AddForumTokens(IList tokens, Forum forum, int languageId); void AddForumTopicTokens(IList tokens, ForumTopic forumTopic, int? friendlyForumTopicPageIndex = null, int? appendedPostIdentifierAnchor = null); diff --git a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs index 6f9a455c53..ea27f3092b 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs @@ -971,12 +971,12 @@ public virtual void AddForumPostTokens(IList tokens, ForumPost forumPost) _eventPublisher.EntityTokensAdded(forumPost, tokens); } - public virtual void AddForumTokens(IList tokens, Forum forum) + public virtual void AddForumTokens(IList tokens, Forum forum, int languageId) { //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) - var forumUrl = string.Format("{0}boards/forum/{1}/{2}", _webHelper.GetStoreLocation(false), forum.Id, forum.GetSeName()); + var forumUrl = string.Format("{0}boards/forum/{1}/{2}", _webHelper.GetStoreLocation(false), forum.Id, forum.GetSeName(languageId)); tokens.Add(new Token("Forums.ForumURL", forumUrl, true)); - tokens.Add(new Token("Forums.ForumName", forum.GetLocalized(x => x.Name))); + tokens.Add(new Token("Forums.ForumName", forum.GetLocalized(x => x.Name, languageId))); //event notification _eventPublisher.EntityTokensAdded(forum, tokens); diff --git a/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs b/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs index d5ce928649..bbad203299 100644 --- a/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs +++ b/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs @@ -993,7 +993,7 @@ public int SendNewForumTopicMessage(Customer customer, _messageTokenProvider.AddStoreTokens(tokens, store); _messageTokenProvider.AddCustomerTokens(tokens, customer); _messageTokenProvider.AddForumTopicTokens(tokens, forumTopic); - _messageTokenProvider.AddForumTokens(tokens, forumTopic.Forum); + _messageTokenProvider.AddForumTokens(tokens, forumTopic.Forum, languageId); //event notification _eventPublisher.MessageTokensAdded(messageTemplate, tokens); @@ -1037,9 +1037,8 @@ public int SendNewForumPostMessage(Customer customer, _messageTokenProvider.AddStoreTokens(tokens, store); _messageTokenProvider.AddForumPostTokens(tokens, forumPost); _messageTokenProvider.AddCustomerTokens(tokens, customer); - _messageTokenProvider.AddForumTopicTokens(tokens, forumPost.ForumTopic, - friendlyForumTopicPageIndex, forumPost.Id); - _messageTokenProvider.AddForumTokens(tokens, forumPost.ForumTopic.Forum); + _messageTokenProvider.AddForumTopicTokens(tokens, forumPost.ForumTopic, friendlyForumTopicPageIndex, forumPost.Id); + _messageTokenProvider.AddForumTokens(tokens, forumPost.ForumTopic.Forum, languageId); //event notification _eventPublisher.MessageTokensAdded(messageTemplate, tokens); From 9c6afbeb51d6b0bcb921831c8704d9c6ce463142 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 6 May 2015 17:52:24 +0200 Subject: [PATCH 0115/1256] Resolves #508 Limit country settings to stores --- .../SmartStore.Services/ExportImport/ExportManager.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 804c967911..587cc3cac0 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -207,14 +207,14 @@ public virtual string ExportManufacturersToXml(IList manufacturers { xmlWriter.WriteStartElement("Manufacturer"); - xmlWriter.WriteElementString("ManufacturerId", null, manufacturer.Id.ToString()); + xmlWriter.WriteElementString("Id", null, manufacturer.Id.ToString()); xmlWriter.WriteElementString("Name", null, manufacturer.Name); + xmlWriter.WriteElementString("SeName", null, manufacturer.GetSeName(0, true, false)); xmlWriter.WriteElementString("Description", null, manufacturer.Description); xmlWriter.WriteElementString("ManufacturerTemplateId", null, manufacturer.ManufacturerTemplateId.ToString()); xmlWriter.WriteElementString("MetaKeywords", null, manufacturer.MetaKeywords); xmlWriter.WriteElementString("MetaDescription", null, manufacturer.MetaDescription); xmlWriter.WriteElementString("MetaTitle", null, manufacturer.MetaTitle); - xmlWriter.WriteElementString("SEName", null, manufacturer.GetSeName(0)); xmlWriter.WriteElementString("PictureId", null, manufacturer.PictureId.ToString()); xmlWriter.WriteElementString("PageSize", null, manufacturer.PageSize.ToString()); xmlWriter.WriteElementString("AllowCustomersToSelectPageSize", null, manufacturer.AllowCustomersToSelectPageSize.ToString()); @@ -236,7 +236,7 @@ public virtual string ExportManufacturersToXml(IList manufacturers if (product != null && !product.Deleted) { xmlWriter.WriteStartElement("ProductManufacturer"); - xmlWriter.WriteElementString("ProductManufacturerId", null, productManufacturer.Id.ToString()); + xmlWriter.WriteElementString("Id", null, productManufacturer.Id.ToString()); xmlWriter.WriteElementString("ProductId", null, productManufacturer.ProductId.ToString()); xmlWriter.WriteElementString("IsFeaturedProduct", null, productManufacturer.IsFeaturedProduct.ToString()); xmlWriter.WriteElementString("DisplayOrder", null, productManufacturer.DisplayOrder.ToString()); @@ -246,7 +246,6 @@ public virtual string ExportManufacturersToXml(IList manufacturers } xmlWriter.WriteEndElement(); - xmlWriter.WriteEndElement(); } From 6dee57243dca919ddec0d5d2141e77caad22b071 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 8 May 2015 16:50:27 +0200 Subject: [PATCH 0116/1256] #660 Don't show shipping cost hint in product detail page if product has free shipping --- changelog.md | 3 ++- .../SmartStore.Web/Controllers/CatalogHelper.cs | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index 22107a4bd1..b456e5ffb2 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,4 @@ -# Release Notes +# Release Notes ## SmartStore.NET 2.2.1 @@ -21,6 +21,7 @@ ### Bugfixes * PDF converter: fixed _QFont::setPixelSize_ bug * Fixed System.NullReferenceException at admin/order/pdfpackagingslips +* #660 Don't show shipping cost hint in product detail page if product has free shipping ## SmartStore.NET 2.2.0 diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index bdd621726f..a3f35fc41f 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -686,7 +686,18 @@ public ProductDetailsModel PrepareProductDetailModel( } string shippingInfoLink = _urlHelper.RouteUrl("Topic", new { SystemName = "shippinginfo" }); - model.LegalInfo = T("Tax.LegalInfoProductDetail", taxInfo, defaultTaxRate, additionalShippingCosts, shippingInfoLink); + + if (!product.IsTaxExempt && !product.IsShipEnabled) + model.LegalInfo += taxInfo + " " + defaultTaxRate; + + if(product.IsShipEnabled) + { + model.LegalInfo = T("Tax.LegalInfoProductDetail", + product.IsTaxExempt ? "" : taxInfo, + product.IsTaxExempt ? "" : defaultTaxRate, + additionalShippingCosts, + shippingInfoLink); + } string dimension = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId).Name; From 9d5e787335b2cba87576efd9e566a834044cd298 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 9 May 2015 12:38:16 +0200 Subject: [PATCH 0117/1256] Updated licensing --- .../SmartStore.Licensing.dll | Bin 146944 -> 145408 bytes .../Views/Plugin/LicensePlugin.cshtml | 2 +- .../Administration/Views/Plugin/List.cshtml | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/SmartStore.Licensing/SmartStore.Licensing.dll b/lib/SmartStore.Licensing/SmartStore.Licensing.dll index a5da31044be70036a6ca6d1ba09e32819e80eac5..e8d9a01512c3d42521183a72cadd7e0a484cc5cd 100644 GIT binary patch literal 145408 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 literal 146944 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 SXTc%-op#rM`}_Yc1OFEX5b&%3 diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml index 19288ebf7a..5897e38319 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/LicensePlugin.cshtml @@ -32,7 +32,7 @@ @Html.HiddenFor(model => model.Licenses[i].StoreId) @Html.HiddenFor(model => model.Licenses[i].StoreUrl) - @Html.TextBoxFor(model => model.Licenses[i].LicenseKey, new { @class = "input-large" }) + @Html.TextBoxFor(model => model.Licenses[i].LicenseKey, new { @class = "input-large", autocomplete = "off" })
+ + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Locales[item].FriendlyName) + + @Html.EditorFor(model => Model.Locales[item].FriendlyName) + @Html.ValidationMessageFor(model => model.Locales[item].FriendlyName) +
+ @Html.SmartLabelFor(model => model.Locales[item].Description) + + @Html.TextAreaFor(model => Model.Locales[item].Description, new { @class = "input-large" }) + @Html.ValidationMessageFor(model => model.Locales[item].Description) +
+ @Html.HiddenFor(model => model.Locales[item].LanguageId) +
+ , + @ + + + + + + + + +
+ @Html.SmartLabelFor(model => model.FriendlyName) + + @Html.EditorFor(model => model.FriendlyName) + @Html.ValidationMessageFor(model => model.FriendlyName) +
+ @Html.SmartLabelFor(model => model.Description) + + @Html.TextAreaFor(model => model.Description, new { @class = "input-large" }) + @Html.ValidationMessageFor(model => model.Description) +
+ )) +} + +@helper TabRestrictions() +{ +
+ @Html.Raw(T("Admin.Configuration.Payment.Methods.RestrictionNote")) +
+ +
+ + + + + + + + + + + +
+
+ +
+
+
+ +
+
+
+ +
+
+ @foreach (var item in Model.AvailableCustomerRoles) + { + @RenderCheckbox(item, "CustomerRole_") + } + + @foreach (var item in Model.AvailableShippingMethods) + { + @RenderCheckbox(item, "ShippingMethod_") + } + + + @foreach (var grp in Model.AvaliableCountries.Select((x, i) => new { Key = i / 4, Value = x }).GroupBy(x => x.Key, x => x.Value)) + { +
+ @foreach (var item in grp) + { +
+ @RenderCheckbox(item, "Country_") +
+ } +
+ } + +
+
+} + + +@helper RenderCheckbox(SelectListItem item, string prefix) +{ +
+ +
+} + + \ No newline at end of file diff --git a/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs index 8abc5990ff..329cf092bd 100644 --- a/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs @@ -1,10 +1,11 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using NUnit.Framework; using Rhino.Mocks; +using SmartStore.Core.Data; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; +using SmartStore.Core.Events; using SmartStore.Core.Plugins; using SmartStore.Services.Configuration; using SmartStore.Services.Localization; @@ -16,10 +17,12 @@ namespace SmartStore.Services.Tests.Payments [TestFixture] public class PaymentServiceTests : ServiceTest { + IRepository _paymentMethodRepository; PaymentSettings _paymentSettings; ShoppingCartSettings _shoppingCartSettings; IPaymentService _paymentService; ISettingService _settingService; + IEventPublisher _eventPublisher; [SetUp] public new void SetUp() @@ -31,12 +34,15 @@ public class PaymentServiceTests : ServiceTest var pluginFinder = new PluginFinder(); _shoppingCartSettings = new ShoppingCartSettings(); + _paymentMethodRepository = MockRepository.GenerateMock>(); _settingService = MockRepository.GenerateMock(); + _eventPublisher = MockRepository.GenerateMock(); var localizationService = MockRepository.GenerateMock(); localizationService.Expect(ls => ls.GetResource(null)).IgnoreArguments().Return("NotSupported").Repeat.Any(); - _paymentService = new PaymentService(_paymentSettings, pluginFinder, _shoppingCartSettings, _settingService, localizationService, this.ProviderManager); + _paymentService = new PaymentService(_paymentMethodRepository, _paymentSettings, pluginFinder, _shoppingCartSettings, + _settingService, localizationService, this.ProviderManager, _eventPublisher); } [Test] From ef8c21c8beece9307229f21c84b8af2a3cabc944 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 16 Jun 2015 00:00:58 +0200 Subject: [PATCH 0148/1256] MsieJsEngine now is the default LESS script engine --- .../Administration/Controllers/DiscountController.cs | 2 +- src/Presentation/SmartStore.Web/Web.Release.config | 2 +- src/Presentation/SmartStore.Web/Web.config | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/DiscountController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/DiscountController.cs index 799f4a7a51..ff5d7b75ca 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/DiscountController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/DiscountController.cs @@ -408,7 +408,7 @@ public ActionResult UsageHistoryList(int discountId, GridCommand command) { Data = duh.Select(x => { - return new DiscountModel.DiscountUsageHistoryModel() + return new DiscountModel.DiscountUsageHistoryModel { Id = x.Id, DiscountId = x.DiscountId, diff --git a/src/Presentation/SmartStore.Web/Web.Release.config b/src/Presentation/SmartStore.Web/Web.Release.config index 4c0c59c9b4..f4b9a73aaa 100644 --- a/src/Presentation/SmartStore.Web/Web.Release.config +++ b/src/Presentation/SmartStore.Web/Web.Release.config @@ -5,7 +5,7 @@ - + diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config index 2c83f69c00..4cf9b75964 100644 --- a/src/Presentation/SmartStore.Web/Web.config +++ b/src/Presentation/SmartStore.Web/Web.config @@ -42,7 +42,7 @@ - + From 7fa48e659fc1a8fd4001d3fd0cc8347ceccffd0d Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 16 Jun 2015 13:53:49 +0200 Subject: [PATCH 0149/1256] Resolves #141 Payment methods by customer roles Resolves #67 Restrict payment methods to certain countries Resolves #94 Restrict payment methods to certain shipping methods --- changelog.md | 3 + .../Domain/Payments/PaymentMethod.cs | 2 +- .../Domain/Shipping/ShippingOption.cs | 5 + .../Payments/IPaymentService.cs | 24 +++- .../Payments/PaymentService.cs | 131 +++++++++++++++--- .../Providers/ByTotalProvider.cs | 1 + .../Providers/FixedRateProvider.cs | 1 + .../ByWeightShippingComputationMethod.cs | 1 + .../Controllers/CheckoutController.cs | 16 ++- .../Controllers/ShoppingCartController.cs | 9 +- .../Checkout/CheckoutShippingMethodModel.cs | 1 + .../ShoppingCart/EstimateShippingModel.cs | 2 + .../SmartStore.Core.Tests/ConversionTests.cs | 19 ++- .../ShippingOptionListTypeConverterTests.cs | 4 + .../ShippingOptionTypeConverterTests.cs | 2 + .../Payments/PaymentServiceTests.cs | 5 +- ...edRateTestShippingRateComputationMethod.cs | 2 + 17 files changed, 192 insertions(+), 36 deletions(-) diff --git a/changelog.md b/changelog.md index 649abc4e24..3c5e567274 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,9 @@ ### New Features * #210 Implement multi-store support for import/export +* #141 Payment methods by customer roles +* #67 Restrict payment methods to certain countries +* #94 Restrict payment methods to certain shipping methods ### Improvements * License checker now supports IDN mapping for domain names diff --git a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs index dae3e3dddd..e85e14bf9d 100644 --- a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs +++ b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs @@ -27,7 +27,7 @@ public partial class PaymentMethod : BaseEntity public string ExcludedCountryIds { get; set; } /// - /// Gets or sets identifiers of shipping methods (comma separated) to be excluded in checkout + /// Gets or sets shipping methods (comma separated) to be excluded in checkout /// [DataMember] public string ExcludedShippingMethodIds { get; set; } diff --git a/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingOption.cs b/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingOption.cs index d059f630b7..ad29aba1aa 100644 --- a/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingOption.cs +++ b/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingOption.cs @@ -13,6 +13,11 @@ namespace SmartStore.Core.Domain.Shipping ///
public partial class ShippingOption { + /// + /// Shipping method identifier + /// + public int ShippingMethodId { get; set; } + /// /// Gets or sets the system name of shipping rate computation method /// diff --git a/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs b/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs index 3757dcb42d..1013a7bae5 100644 --- a/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; using SmartStore.Core.Plugins; @@ -13,10 +14,10 @@ public partial interface IPaymentService /// /// Load active payment methods /// - /// Filter payment methods by customer; null to load all records - /// Load records allows only in specified store; pass 0 to load all records + /// Filter payment methods by customer and apply payment method restrictions; null to load all records + /// Filter payment methods by store identifier; pass 0 to load all records /// Payment methods - IEnumerable> LoadActivePaymentMethods(int? filterByCustomerId = null, int storeId = 0); + IEnumerable> LoadActivePaymentMethods(Customer customer = null, int storeId = 0); /// /// Determines whether a payment method is active\enabled for a shop @@ -39,24 +40,35 @@ public partial interface IPaymentService /// - /// Gets a payment method by system name + /// Gets all payment method extra data + /// + /// List of payment method objects + IList GetAllPaymentMethods(); + + /// + /// Gets payment method extra data by system name /// /// Provider system name /// Payment method entity PaymentMethod GetPaymentMethodBySystemName(string systemName); /// - /// Insert a payment method + /// Insert payment method extra data /// /// Payment method void InsertPaymentMethod(PaymentMethod paymentMethod); /// - /// Updates a payment method + /// Updates payment method extra data /// /// Payment method void UpdatePaymentMethod(PaymentMethod paymentMethod); + /// + /// Delete payment method extra data + /// + /// Payment method + void DeletePaymentMethod(PaymentMethod paymentMethod); /// diff --git a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs index ea0d560fce..bae549304a 100644 --- a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs @@ -1,11 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; +using SmartStore.Core.Caching; using SmartStore.Core.Data; +using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; +using SmartStore.Core.Domain.Shipping; using SmartStore.Core.Events; using SmartStore.Core.Plugins; +using SmartStore.Services.Common; using SmartStore.Services.Configuration; using SmartStore.Services.Localization; @@ -16,6 +20,12 @@ namespace SmartStore.Services.Payments /// public partial class PaymentService : IPaymentService { + #region Constants + + private const string PAYMENTMETHOD_ALL_KEY = "SmartStore.paymentmethod.all"; + + #endregion + #region Fields private readonly IRepository _paymentMethodRepository; @@ -26,6 +36,7 @@ public partial class PaymentService : IPaymentService private readonly ILocalizationService _localizationService; private readonly IProviderManager _providerManager; private readonly IEventPublisher _eventPublisher; + private readonly ICacheManager _cacheManager; #endregion @@ -46,7 +57,8 @@ public PaymentService( ISettingService settingService, ILocalizationService localizationService, IProviderManager providerManager, - IEventPublisher eventPublisher) + IEventPublisher eventPublisher, + ICacheManager cacheManager) { this._paymentMethodRepository = paymentMethodRepository; this._paymentSettings = paymentSettings; @@ -56,32 +68,83 @@ public PaymentService( this._localizationService = localizationService; this._providerManager = providerManager; this._eventPublisher = eventPublisher; + this._cacheManager = cacheManager; } #endregion - #region Methods + #region Methods - /// + /// /// Load active payment methods /// - /// Filter payment methods by customer; null to load all records - /// Load records allows only in specified store; pass 0 to load all records + /// Filter payment methods by customer and apply payment method restrictions; null to load all records + /// Filter payment methods by store identifier; pass 0 to load all records /// Payment methods - public virtual IEnumerable> LoadActivePaymentMethods(int? filterByCustomerId = null, int storeId = 0) + public virtual IEnumerable> LoadActivePaymentMethods(Customer customer = null, int storeId = 0) { - var allMethods = LoadAllPaymentMethods(storeId); - var activeMethods = allMethods - .Where(p => p.Value.IsActive && _paymentSettings.ActivePaymentMethodSystemNames.Contains(p.Metadata.SystemName, StringComparer.InvariantCultureIgnoreCase)); + List customerRoleIds = null; + int? selectedShippingMethodId = null; - if (!activeMethods.Any()) + var allProviders = LoadAllPaymentMethods(storeId); + + var activeProviders = allProviders + .Where(p => + { + if (!p.Value.IsActive || !_paymentSettings.ActivePaymentMethodSystemNames.Contains(p.Metadata.SystemName, StringComparer.InvariantCultureIgnoreCase)) + return false; + + if (customer != null) + { + var method = GetPaymentMethodBySystemName(p.Metadata.SystemName); + if (method != null) + { + // method restricted by customer role id? + var excludedRoleIds = method.ExcludedCustomerRoleIds.ToIntArray(); + if (excludedRoleIds.Any()) + { + if (customerRoleIds == null) + customerRoleIds = customer.CustomerRoles.Where(r => r.Active).Select(r => r.Id).ToList(); + + if (customerRoleIds != null && !customerRoleIds.Except(excludedRoleIds).Any()) + return false; + } + + // method restricted by selected shipping method? + var excludedShippingMethodIds = method.ExcludedShippingMethodIds.ToIntArray(); + if (excludedShippingMethodIds.Any()) + { + if (!selectedShippingMethodId.HasValue) + { + var selectedShipping = customer.GetAttribute(SystemCustomerAttributeNames.SelectedShippingOption, storeId); + selectedShippingMethodId = (selectedShipping == null ? 0 : selectedShipping.ShippingMethodId); + } + + if ((selectedShippingMethodId ?? 0) != 0 && excludedShippingMethodIds.Contains(selectedShippingMethodId.Value)) + return false; + } + + // method restricted by country of selected billing address? + var excludedCountryIds = method.ExcludedCountryIds.ToIntArray(); + if (excludedCountryIds.Any() && customer.BillingAddress != null && (customer.BillingAddress.CountryId ?? 0) != 0) + { + if (excludedCountryIds.Contains(customer.BillingAddress.CountryId.Value)) + return false; + } + } + } + return true; + }); + + if (!activeProviders.Any()) { - var fallbackMethod = allMethods.FirstOrDefault(); + var fallbackMethod = allProviders.FirstOrDefault(); if (fallbackMethod != null) { _paymentSettings.ActivePaymentMethodSystemNames.Clear(); _paymentSettings.ActivePaymentMethodSystemNames.Add(fallbackMethod.Metadata.SystemName); _settingService.SaveSetting(_paymentSettings); + return new Provider[] { fallbackMethod }; } else @@ -91,7 +154,7 @@ public virtual IEnumerable> LoadActivePaymentMethods(in } } - return activeMethods; + return activeProviders; } /// @@ -130,7 +193,21 @@ public virtual IEnumerable> LoadAllPaymentMethods(int s /// - /// Gets a payment method by system name + /// Gets all payment method extra data + /// + /// List of payment method objects + public virtual IList GetAllPaymentMethods() + { + var paymentMethods = _cacheManager.Get(PAYMENTMETHOD_ALL_KEY, () => + { + return _paymentMethodRepository.Table.ToList(); + }); + + return paymentMethods; + } + + /// + /// Gets payment method extra data by system name /// /// Provider system name /// Payment method entity @@ -138,13 +215,15 @@ public virtual PaymentMethod GetPaymentMethodBySystemName(string systemName) { if (systemName.HasValue()) { - return _paymentMethodRepository.Table.FirstOrDefault(x => x.PaymentMethodSystemName == systemName); + var allPaymentMethods = GetAllPaymentMethods(); + + return allPaymentMethods.FirstOrDefault(x => x.PaymentMethodSystemName.IsCaseInsensitiveEqual(systemName)); } return null; } /// - /// Insert a payment method + /// Insert payment method extra data /// /// Payment method public virtual void InsertPaymentMethod(PaymentMethod paymentMethod) @@ -154,11 +233,13 @@ public virtual void InsertPaymentMethod(PaymentMethod paymentMethod) _paymentMethodRepository.Insert(paymentMethod); + _cacheManager.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); + _eventPublisher.EntityInserted(paymentMethod); } /// - /// Updates a payment method + /// Updates payment method extra data /// /// Payment method public virtual void UpdatePaymentMethod(PaymentMethod paymentMethod) @@ -168,9 +249,27 @@ public virtual void UpdatePaymentMethod(PaymentMethod paymentMethod) _paymentMethodRepository.Update(paymentMethod); + _cacheManager.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); + _eventPublisher.EntityUpdated(paymentMethod); } + /// + /// Delete payment method extra data + /// + /// Payment method + public virtual void DeletePaymentMethod(PaymentMethod paymentMethod) + { + if (paymentMethod == null) + throw new ArgumentNullException("paymentMethod"); + + _paymentMethodRepository.Delete(paymentMethod); + + _cacheManager.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); + + _eventPublisher.EntityDeleted(paymentMethod); + } + /// /// Pre process a payment diff --git a/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs b/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs index a4eb6d3def..1f4113e071 100644 --- a/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs +++ b/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs @@ -200,6 +200,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get } var shippingOption = new ShippingOption(); + shippingOption.ShippingMethodId = shippingMethod.Id; shippingOption.Name = shippingMethod.Name; shippingOption.Description = shippingMethod.Description; shippingOption.Rate = rate.Value; diff --git a/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs b/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs index fc73a0c460..1f273a0a45 100644 --- a/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs +++ b/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs @@ -60,6 +60,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get foreach (var shippingMethod in shippingMethods) { var shippingOption = new ShippingOption(); + shippingOption.ShippingMethodId = shippingMethod.Id; shippingOption.Name = shippingMethod.GetLocalized(x => x.Name); shippingOption.Description = shippingMethod.GetLocalized(x => x.Description); shippingOption.Rate = GetRate(shippingMethod.Id); diff --git a/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs b/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs index 48d3ef8851..2b59cf5ff7 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs @@ -150,6 +150,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get if (rate.HasValue) { var shippingOption = new ShippingOption(); + shippingOption.ShippingMethodId = shippingMethod.Id; shippingOption.Name = shippingMethod.GetLocalized(x => x.Name); if (record != null && record.SmallQuantityThreshold > subTotal) diff --git a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs index 8b1e37d65e..e2e5bfd066 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs @@ -205,6 +205,7 @@ protected CheckoutShippingMethodModel PrepareShippingMethodModel(IList decimal.Zero) { model.DisplayRewardPoints = true; @@ -277,8 +279,10 @@ protected CheckoutPaymentMethodModel PreparePaymentMethodModel(IList pm.Value.PaymentMethodType == PaymentMethodType.Standard || pm.Value.PaymentMethodType == PaymentMethodType.Redirection || + .LoadActivePaymentMethods(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id) + .Where(pm => + pm.Value.PaymentMethodType == PaymentMethodType.Standard || + pm.Value.PaymentMethodType == PaymentMethodType.Redirection || pm.Value.PaymentMethodType == PaymentMethodType.StandardAndRedirection) .ToList(); @@ -619,9 +623,11 @@ public ActionResult SelectShippingMethod(string shippingoption) //parse selected method if (String.IsNullOrEmpty(shippingoption)) return ShippingMethod(); - var splittedOption = shippingoption.Split(new string[] { "___" }, StringSplitOptions.RemoveEmptyEntries); + + var splittedOption = shippingoption.Split(new string[] { "___" }, StringSplitOptions.RemoveEmptyEntries); if (splittedOption.Length != 2) return ShippingMethod(); + string selectedName = splittedOption[0]; string shippingRateComputationMethodSystemName = splittedOption[1]; @@ -643,8 +649,8 @@ public ActionResult SelectShippingMethod(string shippingoption) .ToList(); } - var shippingOption = shippingOptions - .Find(so => !String.IsNullOrEmpty(so.Name) && so.Name.Equals(selectedName, StringComparison.InvariantCultureIgnoreCase)); + var shippingOption = shippingOptions.Find(so => !String.IsNullOrEmpty(so.Name) && so.Name.Equals(selectedName, StringComparison.InvariantCultureIgnoreCase)); + if (shippingOption == null) return ShippingMethod(); diff --git a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs index 9229462276..c2385539c6 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs @@ -546,8 +546,10 @@ private void PrepareButtonPaymentMethodModel(ButtonPaymentMethodModel model, ILi model.Items.Clear(); var boundPaymentMethods = _paymentService - .LoadActivePaymentMethods(_workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id) - .Where(pm => pm.Value.PaymentMethodType == PaymentMethodType.Button || pm.Value.PaymentMethodType == PaymentMethodType.StandardAndButton) + .LoadActivePaymentMethods(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id) + .Where(pm => + pm.Value.PaymentMethodType == PaymentMethodType.Button || + pm.Value.PaymentMethodType == PaymentMethodType.StandardAndButton) .ToList(); foreach (var pm in boundPaymentMethods) @@ -560,7 +562,7 @@ private void PrepareButtonPaymentMethodModel(ButtonPaymentMethodModel model, ILi RouteValueDictionary routeValues; pm.Value.GetPaymentInfoRoute(out actionName, out controllerName, out routeValues); - model.Items.Add(new ButtonPaymentMethodModel.ButtonPaymentMethodItem() + model.Items.Add(new ButtonPaymentMethodModel.ButtonPaymentMethodItem { ActionName = actionName, ControllerName = controllerName, @@ -1845,6 +1847,7 @@ public ActionResult GetEstimateShipping(EstimateShippingModel shippingModel, For { var soModel = new EstimateShippingModel.ShippingOptionModel() { + ShippingMethodId = shippingOption.ShippingMethodId, Name = shippingOption.Name, Description = shippingOption.Description, diff --git a/src/Presentation/SmartStore.Web/Models/Checkout/CheckoutShippingMethodModel.cs b/src/Presentation/SmartStore.Web/Models/Checkout/CheckoutShippingMethodModel.cs index bb81c51809..ab1ab0f69a 100644 --- a/src/Presentation/SmartStore.Web/Models/Checkout/CheckoutShippingMethodModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Checkout/CheckoutShippingMethodModel.cs @@ -19,6 +19,7 @@ public CheckoutShippingMethodModel() public partial class ShippingMethodModel : ModelBase { + public int ShippingMethodId { get; set; } public string ShippingRateComputationMethodSystemName { get; set; } public string Name { get; set; } public string BrandUrl { get; set; } diff --git a/src/Presentation/SmartStore.Web/Models/ShoppingCart/EstimateShippingModel.cs b/src/Presentation/SmartStore.Web/Models/ShoppingCart/EstimateShippingModel.cs index aed18dadf1..c540bf5709 100644 --- a/src/Presentation/SmartStore.Web/Models/ShoppingCart/EstimateShippingModel.cs +++ b/src/Presentation/SmartStore.Web/Models/ShoppingCart/EstimateShippingModel.cs @@ -36,6 +36,8 @@ public EstimateShippingModel() public partial class ShippingOptionModel : ModelBase { + public int ShippingMethodId { get; set; } + public string Name { get; set; } public string Description { get; set; } diff --git a/src/Tests/SmartStore.Core.Tests/ConversionTests.cs b/src/Tests/SmartStore.Core.Tests/ConversionTests.cs index 89d548e348..8899b041ee 100644 --- a/src/Tests/SmartStore.Core.Tests/ConversionTests.cs +++ b/src/Tests/SmartStore.Core.Tests/ConversionTests.cs @@ -32,30 +32,41 @@ public void Can_get_typed_value() r1.ShouldBe(); Assert.AreEqual(r1.Value, 3); - var shippingOption = new ShippingOption { Name = "Name", Description = "Desc", Rate = 1, ShippingRateComputationMethodSystemName = "SystemName" }; + var shippingOption = new ShippingOption + { + ShippingMethodId = 2, + Name = "Name", + Description = "Desc", + Rate = 1, + ShippingRateComputationMethodSystemName = "SystemName" + }; var soStr = shippingOption.Convert(); Assert.IsNotEmpty(soStr); shippingOption = soStr.Convert(); Assert.IsNotNull(shippingOption); + Assert.AreEqual(shippingOption.ShippingMethodId, 2); Assert.AreEqual(shippingOption.Name, "Name"); Assert.AreEqual(shippingOption.Description, "Desc"); Assert.AreEqual(shippingOption.Rate, 1); Assert.AreEqual(shippingOption.ShippingRateComputationMethodSystemName, "SystemName"); - var shippingOptions = new List { - new ShippingOption { Name = "Name1", Description = "Desc1" }, - new ShippingOption { Name = "Name2", Description = "Desc2" } + var shippingOptions = new List + { + new ShippingOption { ShippingMethodId = 1, Name = "Name1", Description = "Desc1" }, + new ShippingOption { ShippingMethodId = 2, Name = "Name2", Description = "Desc2" } }; soStr = shippingOptions.Convert(); Assert.IsNotEmpty(soStr); shippingOptions = soStr.Convert>(); Assert.AreEqual(shippingOptions.Count, 2); + Assert.AreEqual(shippingOptions[1].ShippingMethodId, 2); Assert.AreEqual(shippingOptions[1].Description, "Desc2"); var shippingOptions2 = soStr.Convert>(); Assert.AreEqual(shippingOptions2.Count, 2); + Assert.AreEqual(shippingOptions[1].ShippingMethodId, 2); Assert.AreEqual(shippingOptions2[1].Description, "Desc2"); var enu = SmartStore.Core.Domain.Catalog.AttributeControlType.FileUpload; diff --git a/src/Tests/SmartStore.Core.Tests/Domain/Shipping/ShippingOptionListTypeConverterTests.cs b/src/Tests/SmartStore.Core.Tests/Domain/Shipping/ShippingOptionListTypeConverterTests.cs index c86b955de7..653b851dda 100644 --- a/src/Tests/SmartStore.Core.Tests/Domain/Shipping/ShippingOptionListTypeConverterTests.cs +++ b/src/Tests/SmartStore.Core.Tests/Domain/Shipping/ShippingOptionListTypeConverterTests.cs @@ -28,6 +28,7 @@ public void Can_convert_shippingOptionList_to_string_and_back() var shippingOptionsInput = new List(); shippingOptionsInput.Add(new ShippingOption() { + ShippingMethodId = 1, Name = "a1", Description = "a2", Rate = 3.57M, @@ -35,6 +36,7 @@ public void Can_convert_shippingOptionList_to_string_and_back() }); shippingOptionsInput.Add(new ShippingOption() { + ShippingMethodId = 2, Name = "b1", Description = "b2", Rate = 7.00M, @@ -47,11 +49,13 @@ public void Can_convert_shippingOptionList_to_string_and_back() var shippingOptionsOutput = converter.ConvertFrom(result) as List; shippingOptionsOutput.ShouldNotBeNull(); shippingOptionsOutput.Count.ShouldEqual(2); + shippingOptionsOutput[0].ShippingMethodId.ShouldEqual(1); shippingOptionsOutput[0].Name.ShouldEqual("a1"); shippingOptionsOutput[0].Description.ShouldEqual("a2"); shippingOptionsOutput[0].Rate.ShouldEqual(3.57M); shippingOptionsOutput[0].ShippingRateComputationMethodSystemName.ShouldEqual("a4"); + shippingOptionsOutput[1].ShippingMethodId.ShouldEqual(2); shippingOptionsOutput[1].Name.ShouldEqual("b1"); shippingOptionsOutput[1].Description.ShouldEqual("b2"); shippingOptionsOutput[1].Rate.ShouldEqual(7.00M); diff --git a/src/Tests/SmartStore.Core.Tests/Domain/Shipping/ShippingOptionTypeConverterTests.cs b/src/Tests/SmartStore.Core.Tests/Domain/Shipping/ShippingOptionTypeConverterTests.cs index f51e8981f3..5f40a3b0aa 100644 --- a/src/Tests/SmartStore.Core.Tests/Domain/Shipping/ShippingOptionTypeConverterTests.cs +++ b/src/Tests/SmartStore.Core.Tests/Domain/Shipping/ShippingOptionTypeConverterTests.cs @@ -26,6 +26,7 @@ public void Can_convert_shippingOption_to_string_and_back() { var shippingOptionInput = new ShippingOption() { + ShippingMethodId = 1, Name = "1", Description = "2", Rate = 3.57M, @@ -36,6 +37,7 @@ public void Can_convert_shippingOption_to_string_and_back() var shippingOptionOutput = converter.ConvertFrom(result) as ShippingOption; shippingOptionOutput.ShouldNotBeNull(); + shippingOptionInput.ShippingMethodId.ShouldEqual(1); shippingOptionOutput.Name.ShouldEqual("1"); shippingOptionOutput.Description.ShouldEqual("2"); shippingOptionOutput.Rate.ShouldEqual(3.57M); diff --git a/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs index 329cf092bd..1e5a74de19 100644 --- a/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs @@ -2,6 +2,7 @@ using System.Linq; using NUnit.Framework; using Rhino.Mocks; +using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; @@ -23,6 +24,7 @@ public class PaymentServiceTests : ServiceTest IPaymentService _paymentService; ISettingService _settingService; IEventPublisher _eventPublisher; + ICacheManager _cacheManager; [SetUp] public new void SetUp() @@ -37,12 +39,13 @@ public class PaymentServiceTests : ServiceTest _paymentMethodRepository = MockRepository.GenerateMock>(); _settingService = MockRepository.GenerateMock(); _eventPublisher = MockRepository.GenerateMock(); + _cacheManager = MockRepository.GenerateMock(); var localizationService = MockRepository.GenerateMock(); localizationService.Expect(ls => ls.GetResource(null)).IgnoreArguments().Return("NotSupported").Repeat.Any(); _paymentService = new PaymentService(_paymentMethodRepository, _paymentSettings, pluginFinder, _shoppingCartSettings, - _settingService, localizationService, this.ProviderManager, _eventPublisher); + _settingService, localizationService, this.ProviderManager, _eventPublisher, _cacheManager); } [Test] diff --git a/src/Tests/SmartStore.Services.Tests/Shipping/FixedRateTestShippingRateComputationMethod.cs b/src/Tests/SmartStore.Services.Tests/Shipping/FixedRateTestShippingRateComputationMethod.cs index e42e2ac094..5848b454e5 100644 --- a/src/Tests/SmartStore.Services.Tests/Shipping/FixedRateTestShippingRateComputationMethod.cs +++ b/src/Tests/SmartStore.Services.Tests/Shipping/FixedRateTestShippingRateComputationMethod.cs @@ -28,12 +28,14 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get var response = new GetShippingOptionResponse(); response.ShippingOptions.Add(new ShippingOption() { + ShippingMethodId = 1, Name = "Shipping option 1", Description = "", Rate = GetRate() }); response.ShippingOptions.Add(new ShippingOption() { + ShippingMethodId = 2, Name = "Shipping option 2", Description = "", Rate = GetRate() From 68bc18da22e6ce28ee7b3f7d17c18b1f904297c3 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 16 Jun 2015 16:32:49 +0200 Subject: [PATCH 0150/1256] Added a country exclusion context type (billing versus shipping address) --- .../Payments/CountryExclusionContextType.cs | 9 ++ .../Domain/Payments/PaymentMethod.cs | 22 +++ .../SmartStore.Core/SmartStore.Core.csproj | 1 + .../Mapping/Payments/PaymentMethodMap.cs | 2 + ...130926062_PaymentShippingRestrictions.resx | 126 ------------------ ...5_PaymentShippingRestrictions.Designer.cs} | 2 +- ...6161226375_PaymentShippingRestrictions.cs} | 37 +++-- ...161226375_PaymentShippingRestrictions.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../Payments/PaymentService.cs | 10 +- .../Administration/Content/admin.less | 44 +++--- .../Controllers/PaymentController.cs | 12 +- .../Models/Payments/PaymentMethodEditModel.cs | 5 +- .../Administration/Views/Payment/Edit.cshtml | 19 ++- 14 files changed, 257 insertions(+), 168 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Domain/Payments/CountryExclusionContextType.cs delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.resx rename src/Libraries/SmartStore.Data/Migrations/{201506130926062_PaymentShippingRestrictions.Designer.cs => 201506161226375_PaymentShippingRestrictions.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201506130926062_PaymentShippingRestrictions.cs => 201506161226375_PaymentShippingRestrictions.cs} (56%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.resx diff --git a/src/Libraries/SmartStore.Core/Domain/Payments/CountryExclusionContextType.cs b/src/Libraries/SmartStore.Core/Domain/Payments/CountryExclusionContextType.cs new file mode 100644 index 0000000000..d629d01a36 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/Payments/CountryExclusionContextType.cs @@ -0,0 +1,9 @@ + +namespace SmartStore.Core.Domain.Payments +{ + public enum CountryExclusionContextType + { + BillingAddress = 0, + ShippingAddress + } +} diff --git a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs index e85e14bf9d..8be069bc96 100644 --- a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs +++ b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs @@ -31,5 +31,27 @@ public partial class PaymentMethod : BaseEntity /// [DataMember] public string ExcludedShippingMethodIds { get; set; } + + /// + /// Gets or sets the context identifier for country exclusion + /// + [DataMember] + public int CountryExclusionContextId { get; set; } + + /// + /// Gets or sets the country exclusion context + /// + [DataMember] + public CountryExclusionContextType CountryExclusionContext + { + get + { + return (CountryExclusionContextType)this.CountryExclusionContextId; + } + set + { + this.CountryExclusionContextId = (int)value; + } + } } } diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index d9418948fb..d389e35e66 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -157,6 +157,7 @@ + diff --git a/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs b/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs index 3544292bef..86073bffc7 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs @@ -15,6 +15,8 @@ public PaymentMethodMap() this.Property(x => x.ExcludedCustomerRoleIds).IsMaxLength(); this.Property(x => x.ExcludedCountryIds).IsMaxLength(); this.Property(x => x.ExcludedShippingMethodIds).IsMaxLength(); + + this.Ignore(x => x.CountryExclusionContext); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.resx b/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.resx deleted file mode 100644 index 621557bdf4..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.Designer.cs index 1432d4c15b..eec91358a2 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class PaymentShippingRestrictions : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201506130926062_PaymentShippingRestrictions"; } + get { return "201506161226375_PaymentShippingRestrictions"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.cs similarity index 56% rename from src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs rename to src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.cs index 175f4ea9ce..ac1308c4c6 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506130926062_PaymentShippingRestrictions.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.cs @@ -8,18 +8,19 @@ public partial class PaymentShippingRestrictions : DbMigration, ILocaleResources { public override void Up() { - CreateTable( - "dbo.PaymentMethod", - c => new - { - Id = c.Int(nullable: false, identity: true), - PaymentMethodSystemName = c.String(nullable: false, maxLength: 4000), - ExcludedCustomerRoleIds = c.String(), - ExcludedCountryIds = c.String(), - ExcludedShippingMethodIds = c.String(), - }) - .PrimaryKey(t => t.Id) - .Index(t => t.PaymentMethodSystemName); + CreateTable( + "dbo.PaymentMethod", + c => new + { + Id = c.Int(nullable: false, identity: true), + PaymentMethodSystemName = c.String(nullable: false, maxLength: 4000), + ExcludedCustomerRoleIds = c.String(), + ExcludedCountryIds = c.String(), + ExcludedShippingMethodIds = c.String(), + CountryExclusionContextId = c.Int(nullable: false), + }) + .PrimaryKey(t => t.Id) + .Index(t => t.PaymentMethodSystemName); } public override void Down() @@ -43,9 +44,21 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Restrictions", "Einschrnkungen"); + builder.AddOrUpdate("Admin.Common.AppliedTo", + "applied to", + "bezogen auf"); + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.RestrictionNote", "Select customer roles, shipping methods and countries for which you do not want to offer this payment method.", "Whlen Sie Kundengruppen, Versandarten und Lnder, bei denen sie diese Zahlungsmethode nicht anbieten mchten."); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Payments.CountryExclusionContextType.BillingAddress", + "Billing address", + "Rechnungsadresse"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Payments.CountryExclusionContextType.ShippingAddress", + "Shipping address", + "Versandadresse"); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.resx b/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.resx new file mode 100644 index 0000000000..2761a39c37 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 103589f9cc..c6eeba74f5 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -273,9 +273,9 @@ 201505272236124_V222.cs - - - 201506130926062_PaymentShippingRestrictions.cs + + + 201506161226375_PaymentShippingRestrictions.cs @@ -534,8 +534,8 @@ 201505272236124_V222.cs - - 201506130926062_PaymentShippingRestrictions.cs + + 201506161226375_PaymentShippingRestrictions.cs diff --git a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs index bae549304a..f2e02400f5 100644 --- a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs @@ -126,9 +126,15 @@ public virtual IEnumerable> LoadActivePaymentMethods(Cu // method restricted by country of selected billing address? var excludedCountryIds = method.ExcludedCountryIds.ToIntArray(); - if (excludedCountryIds.Any() && customer.BillingAddress != null && (customer.BillingAddress.CountryId ?? 0) != 0) + if (excludedCountryIds.Any()) { - if (excludedCountryIds.Contains(customer.BillingAddress.CountryId.Value)) + int countryId = 0; + if (method.CountryExclusionContext == CountryExclusionContextType.ShippingAddress) + countryId = (customer.ShippingAddress != null ? (customer.ShippingAddress.CountryId ?? 0) : 0); + else + countryId = (customer.BillingAddress != null ? (customer.BillingAddress.CountryId ?? 0) : 0); + + if (countryId != 0 && excludedCountryIds.Contains(countryId)) return false; } } diff --git a/src/Presentation/SmartStore.Web/Administration/Content/admin.less b/src/Presentation/SmartStore.Web/Administration/Content/admin.less index 20f7c1f835..0828ff57e8 100644 --- a/src/Presentation/SmartStore.Web/Administration/Content/admin.less +++ b/src/Presentation/SmartStore.Web/Administration/Content/admin.less @@ -1199,25 +1199,39 @@ table.payment-method-features td { /* payment methods restrictions -------------------------------------------------------------- */ -.payment-restrictions th label { - margin: 0; -} -.payment-restrictions .column-customerroles, -.payment-restrictions .column-shippingmethods { - width: 18%; -} -.payment-restrictions .column-countries { - width: 64%; - - > div { - display: table-row; +.payment-restrictions { + th label { + margin: 0 10px 0 0; + display: inline-block; } - .country-countainer { - display: table-cell; - width: 25%; + th > div { + display: inline-block; padding-right: 10px; } + + .normal-font { + font-weight: normal; + } + + .column-customerroles, + .column-shippingmethods { + width: 18%; + } + + .column-countries { + width: 64%; + + > div { + display: table-row; + } + + .country-countainer { + display: table-cell; + width: 25%; + padding-right: 10px; + } + } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs index 2f725737b7..df69321ffa 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs @@ -71,7 +71,7 @@ private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, Payment model.AvailableCustomerRoles = new List(); model.AvailableShippingMethods = new List(); - model.AvaliableCountries = new List(); + model.AvailableCountries = new List(); foreach (var role in customerRoles.OrderBy(x => x.Name)) { @@ -85,11 +85,13 @@ private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, Payment foreach (var country in countries.OrderBy(x => x.Name)) { - model.AvaliableCountries.Add(new SelectListItem { Text = country.GetLocalized(x => x.Name), Value = country.Id.ToString() }); + model.AvailableCountries.Add(new SelectListItem { Text = country.GetLocalized(x => x.Name), Value = country.Id.ToString() }); } if (paymentMethod != null) { + model.CountryExclusionContext = paymentMethod.CountryExclusionContext; + foreach (var id in paymentMethod.ExcludedCustomerRoleIds.SplitSafe(",")) { if ((item = model.AvailableCustomerRoles.FirstOrDefault(x => x.Value == id)) != null) @@ -104,7 +106,7 @@ private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, Payment foreach (var id in paymentMethod.ExcludedCountryIds.SplitSafe(",")) { - if ((item = model.AvaliableCountries.FirstOrDefault(x => x.Value == id)) != null) + if ((item = model.AvailableCountries.FirstOrDefault(x => x.Value == id)) != null) item.Selected = true; } } @@ -184,7 +186,7 @@ public ActionResult Edit(string systemName) } [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] - public ActionResult Edit(string systemName, bool continueEditing, ProviderModel model) + public ActionResult Edit(string systemName, bool continueEditing, PaymentMethodEditModel model) { if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) return AccessDeniedView(); @@ -226,6 +228,8 @@ public ActionResult Edit(string systemName, bool continueEditing, ProviderModel paymentMethod.ExcludedShippingMethodIds = string.Join(",", shippingMethodIds); paymentMethod.ExcludedCountryIds = string.Join(",", countryIds); + paymentMethod.CountryExclusionContext = model.CountryExclusionContext; + if (paymentMethod.Id == 0) _paymentService.InsertPaymentMethod(paymentMethod); else diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs index e2f2f40437..180d7c756b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Web.Mvc; +using SmartStore.Core.Domain.Payments; using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Models.Payments @@ -8,6 +9,8 @@ public class PaymentMethodEditModel : ProviderModel { public List AvailableCustomerRoles { get; set; } public List AvailableShippingMethods { get; set; } - public List AvaliableCountries { get; set; } + public List AvailableCountries { get; set; } + + public CountryExclusionContextType CountryExclusionContext { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml index df02bbbd14..61283a2345 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml @@ -1,4 +1,6 @@ -@model PaymentMethodEditModel +@using SmartStore.Core.Domain.Payments; + +@model PaymentMethodEditModel @{ ViewBag.Title = T("Common.Edit").Text + " - " + Model.FriendlyName; @@ -115,6 +117,19 @@ @T("Admin.Configuration.Countries") +
+ @T("Admin.Common.AppliedTo") +
+
+ + +
- @foreach (var grp in Model.AvaliableCountries.Select((x, i) => new { Key = i / 4, Value = x }).GroupBy(x => x.Key, x => x.Value)) + @foreach (var grp in Model.AvailableCountries.Select((x, i) => new { Key = i / 4, Value = x }).GroupBy(x => x.Key, x => x.Value)) {
@foreach (var item in grp) From 65a1e3ebf4bfdadd4acc60d7b0bc3529fbd5d6bb Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 17 Jun 2015 14:51:42 +0200 Subject: [PATCH 0151/1256] Resolves #141 Shipping methods by customer roles --- .../Domain/Shipping/ShippingMethod.cs | 6 + .../Mapping/Shipping/ShippingMethodMap.cs | 2 + ...161226375_PaymentShippingRestrictions.resx | 126 ----------- ...7_PaymentShippingRestrictions.Designer.cs} | 2 +- ...6170941137_PaymentShippingRestrictions.cs} | 31 +-- ...170941137_PaymentShippingRestrictions.resx | 126 +++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../Shipping/IShippingService.cs | 4 +- .../Shipping/ShippingService.cs | 66 ++++-- .../SmartStore.Shipping/Description.txt | 2 +- .../Providers/ByTotalProvider.cs | 2 +- .../Providers/FixedRateProvider.cs | 12 +- .../ByWeightShippingComputationMethod.cs | 2 +- .../Description.txt | 2 +- .../Administration/Content/admin.less | 6 +- .../Controllers/ShippingController.cs | 46 +++- .../Models/Shipping/ShippingMethodModel.cs | 4 +- .../Administration/Views/Payment/Edit.cshtml | 14 +- .../Views/Shipping/Methods.cshtml | 15 +- .../Shipping/_CreateOrUpdateMethod.cshtml | 204 ++++++++++++------ .../Controllers/CheckoutController.cs | 13 +- 21 files changed, 425 insertions(+), 270 deletions(-) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.resx rename src/Libraries/SmartStore.Data/Migrations/{201506161226375_PaymentShippingRestrictions.Designer.cs => 201506170941137_PaymentShippingRestrictions.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201506161226375_PaymentShippingRestrictions.cs => 201506170941137_PaymentShippingRestrictions.cs} (60%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.resx diff --git a/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingMethod.cs b/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingMethod.cs index 527dbbb655..9651718a85 100644 --- a/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingMethod.cs +++ b/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingMethod.cs @@ -34,6 +34,12 @@ public partial class ShippingMethod : BaseEntity, ILocalizedEntity [DataMember] public bool IgnoreCharges { get; set; } + /// + /// Gets or sets identifiers of customer roles (comma separated) to be excluded in checkout + /// + [DataMember] + public string ExcludedCustomerRoleIds { get; set; } + /// /// Gets or sets the restricted countries /// diff --git a/src/Libraries/SmartStore.Data/Mapping/Shipping/ShippingMethodMap.cs b/src/Libraries/SmartStore.Data/Mapping/Shipping/ShippingMethodMap.cs index dc37957d85..947070d588 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Shipping/ShippingMethodMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Shipping/ShippingMethodMap.cs @@ -9,7 +9,9 @@ public ShippingMethodMap() { this.ToTable("ShippingMethod"); this.HasKey(sm => sm.Id); + this.Property(sm => sm.Name).IsRequired().HasMaxLength(400); + this.Property(sm => sm.ExcludedCustomerRoleIds).IsMaxLength(); this.HasMany(sm => sm.RestrictedCountries) .WithMany(c => c.RestrictedShippingMethods) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.resx b/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.resx deleted file mode 100644 index 2761a39c37..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.Designer.cs index eec91358a2..2093e737e1 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class PaymentShippingRestrictions : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201506161226375_PaymentShippingRestrictions"; } + get { return "201506170941137_PaymentShippingRestrictions"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.cs similarity index 60% rename from src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.cs rename to src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.cs index ac1308c4c6..c9398dc915 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506161226375_PaymentShippingRestrictions.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.cs @@ -8,23 +8,26 @@ public partial class PaymentShippingRestrictions : DbMigration, ILocaleResources { public override void Up() { - CreateTable( - "dbo.PaymentMethod", - c => new - { - Id = c.Int(nullable: false, identity: true), - PaymentMethodSystemName = c.String(nullable: false, maxLength: 4000), - ExcludedCustomerRoleIds = c.String(), - ExcludedCountryIds = c.String(), - ExcludedShippingMethodIds = c.String(), - CountryExclusionContextId = c.Int(nullable: false), - }) - .PrimaryKey(t => t.Id) + CreateTable( + "dbo.PaymentMethod", + c => new + { + Id = c.Int(nullable: false, identity: true), + PaymentMethodSystemName = c.String(nullable: false, maxLength: 4000), + ExcludedCustomerRoleIds = c.String(), + ExcludedCountryIds = c.String(), + ExcludedShippingMethodIds = c.String(), + CountryExclusionContextId = c.Int(nullable: false), + }) + .PrimaryKey(t => t.Id) .Index(t => t.PaymentMethodSystemName); + + AddColumn("dbo.ShippingMethod", "ExcludedCustomerRoleIds", c => c.String()); } public override void Down() { + DropColumn("dbo.ShippingMethod", "ExcludedCustomerRoleIds"); DropTable("dbo.PaymentMethod"); } @@ -59,6 +62,10 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Payments.CountryExclusionContextType.ShippingAddress", "Shipping address", "Versandadresse"); + + builder.AddOrUpdate("Admin.Configuration.Shipping.Methods.RestrictionNote", + "Select customer roles for which you do not want to offer this shipping method.", + "Whlen Sie Kundengruppen, bei denen sie diese Versandart nicht anbieten mchten."); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.resx b/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.resx new file mode 100644 index 0000000000..f332ef3c76 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index c6eeba74f5..e82f356741 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -273,9 +273,9 @@ 201505272236124_V222.cs - - - 201506161226375_PaymentShippingRestrictions.cs + + + 201506170941137_PaymentShippingRestrictions.cs @@ -534,8 +534,8 @@ 201505272236124_V222.cs - - 201506161226375_PaymentShippingRestrictions.cs + + 201506170941137_PaymentShippingRestrictions.cs diff --git a/src/Libraries/SmartStore.Services/Shipping/IShippingService.cs b/src/Libraries/SmartStore.Services/Shipping/IShippingService.cs index a8fccc065b..501c236c22 100644 --- a/src/Libraries/SmartStore.Services/Shipping/IShippingService.cs +++ b/src/Libraries/SmartStore.Services/Shipping/IShippingService.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using SmartStore.Core.Domain.Common; +using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Shipping; using SmartStore.Core.Plugins; @@ -53,8 +54,9 @@ public partial interface IShippingService /// Gets all shipping methods /// /// The country indentifier to filter by + /// Filter methods by roles of a customer /// Shipping method collection - IList GetAllShippingMethods(int? filterByCountryId = null); + IList GetAllShippingMethods(int? filterByCountryId = null, Customer customer = null); /// /// Inserts a shipping method diff --git a/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs b/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs index 2b834b4194..857aabdc54 100644 --- a/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs +++ b/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs @@ -103,6 +103,7 @@ public ShippingService(ICacheManager cacheManager, public virtual IEnumerable> LoadActiveShippingRateComputationMethods(int storeId = 0) { var allMethods = LoadAllShippingRateComputationMethods(storeId); + var activeMethods = allMethods .Where(p => p.Value.IsActive && _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Contains(p.Metadata.SystemName, StringComparer.InvariantCultureIgnoreCase)); @@ -114,6 +115,7 @@ public virtual IEnumerable> LoadActiveS _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Clear(); _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Add(fallbackMethod.Metadata.SystemName); _settingService.SaveSetting(_shippingSettings); + return new Provider[] { fallbackMethod }; } else @@ -182,32 +184,57 @@ public virtual ShippingMethod GetShippingMethodById(int shippingMethodId) /// Gets all shipping methods /// /// The country indentifier to filter by + /// Filter methods by roles of a customer /// Shipping method collection - public virtual IList GetAllShippingMethods(int? filterByCountryId = null) + public virtual IList GetAllShippingMethods(int? filterByCountryId = null, Customer customer = null) { + IQueryable query = null; + if (filterByCountryId.HasValue && filterByCountryId.Value > 0) { - var query1 = from sm in _shippingMethodRepository.Table - where - sm.RestrictedCountries.Select(c => c.Id).Contains(filterByCountryId.Value) - select sm.Id; - - var query2 = from sm in _shippingMethodRepository.Table - where !query1.Contains(sm.Id) - orderby sm.DisplayOrder - select sm; - - var shippingMethods = query2.ToList(); - return shippingMethods; + var query1 = + from sm in _shippingMethodRepository.Table + where sm.RestrictedCountries.Select(c => c.Id).Contains(filterByCountryId.Value) + select sm.Id; + + query = + from sm in _shippingMethodRepository.Table + where !query1.Contains(sm.Id) + orderby sm.DisplayOrder + select sm; } else { - var query = from sm in _shippingMethodRepository.Table - orderby sm.DisplayOrder - select sm; - var shippingMethods = query.ToList(); - return shippingMethods; + query = + from sm in _shippingMethodRepository.Table + orderby sm.DisplayOrder + select sm; } + + var shippingMethods = query.ToList(); + + if (customer != null) + { + List customerRoleIds = null; + + for (int i = shippingMethods.Count - 1; i >= 0; --i) + { + var method = shippingMethods[i]; + + // method restricted by customer role id? + var excludedRoleIds = method.ExcludedCustomerRoleIds.ToIntArray(); + if (excludedRoleIds.Any()) + { + if (customerRoleIds == null) + customerRoleIds = customer.CustomerRoles.Where(r => r.Active).Select(r => r.Id).ToList(); + + if (customerRoleIds != null && !customerRoleIds.Except(excludedRoleIds).Any()) + shippingMethods.Remove(method); + } + } + } + + return shippingMethods; } /// @@ -357,7 +384,8 @@ public virtual GetShippingOptionRequest CreateShippingOptionRequest(IListFilter by shipping rate computation method identifier; null to load shipping options of all shipping rate computation methods /// Load records allows only in specified store; pass 0 to load all records /// Shipping options - public virtual GetShippingOptionResponse GetShippingOptions(IList cart, Address shippingAddress, string allowedShippingRateComputationMethodSystemName = "", int storeId = 0) + public virtual GetShippingOptionResponse GetShippingOptions(IList cart, Address shippingAddress, + string allowedShippingRateComputationMethodSystemName = "", int storeId = 0) { if (cart == null) throw new ArgumentNullException("cart"); diff --git a/src/Plugins/SmartStore.Shipping/Description.txt b/src/Plugins/SmartStore.Shipping/Description.txt index e4b70d8120..533761599a 100644 --- a/src/Plugins/SmartStore.Shipping/Description.txt +++ b/src/Plugins/SmartStore.Shipping/Description.txt @@ -2,7 +2,7 @@ Description: Provides shipping methods for fixed rate shipping and computation based on weight. SystemName: SmartStore.Shipping Group: Shipping -Version: 2.2.0 +Version: 2.2.0.1 MinAppVersion: 2.2.0 DisplayOrder: 1 FileName: SmartStore.Shipping.dll diff --git a/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs b/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs index 1f4113e071..44926d497c 100644 --- a/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs +++ b/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs @@ -187,7 +187,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get decimal sqThreshold = _shippingByTotalSettings.SmallQuantityThreshold; decimal sqSurcharge = _shippingByTotalSettings.SmallQuantitySurcharge; - var shippingMethods = _shippingService.GetAllShippingMethods(countryId); + var shippingMethods = _shippingService.GetAllShippingMethods(countryId, getShippingOptionRequest.Customer); foreach (var shippingMethod in shippingMethods) { decimal? rate = GetRate(subTotal, shippingMethod.Id, storeId, countryId, stateProvinceId, zip); diff --git a/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs b/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs index 1f273a0a45..673f3b5c85 100644 --- a/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs +++ b/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs @@ -55,8 +55,10 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get return response; } - int? restrictByCountryId = (getShippingOptionRequest.ShippingAddress != null && getShippingOptionRequest.ShippingAddress.Country != null) ? (int?)getShippingOptionRequest.ShippingAddress.Country.Id : null; - var shippingMethods = this._shippingService.GetAllShippingMethods(restrictByCountryId); + int? restrictByCountryId = (getShippingOptionRequest.ShippingAddress != null && getShippingOptionRequest.ShippingAddress.Country != null) + ? (int?)getShippingOptionRequest.ShippingAddress.Country.Id : null; + + var shippingMethods = this._shippingService.GetAllShippingMethods(restrictByCountryId, getShippingOptionRequest.Customer); foreach (var shippingMethod in shippingMethods) { var shippingOption = new ShippingOption(); @@ -80,8 +82,10 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get if (getShippingOptionRequest == null) throw new ArgumentNullException("getShippingOptionRequest"); - int? restrictByCountryId = (getShippingOptionRequest.ShippingAddress != null && getShippingOptionRequest.ShippingAddress.Country != null) ? (int?)getShippingOptionRequest.ShippingAddress.Country.Id : null; - var shippingMethods = this._shippingService.GetAllShippingMethods(restrictByCountryId); + int? restrictByCountryId = (getShippingOptionRequest.ShippingAddress != null && getShippingOptionRequest.ShippingAddress.Country != null) + ? (int?)getShippingOptionRequest.ShippingAddress.Country.Id : null; + + var shippingMethods = this._shippingService.GetAllShippingMethods(restrictByCountryId, getShippingOptionRequest.Customer); var rates = new List(); foreach (var shippingMethod in shippingMethods) diff --git a/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs b/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs index 2b59cf5ff7..9c9d9d69f6 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs @@ -141,7 +141,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get } decimal weight = _shippingService.GetShoppingCartTotalWeight(getShippingOptionRequest.Items); - var shippingMethods = _shippingService.GetAllShippingMethods(countryId); + var shippingMethods = _shippingService.GetAllShippingMethods(countryId, getShippingOptionRequest.Customer); foreach (var shippingMethod in shippingMethods) { var record = _shippingByWeightService.FindRecord(shippingMethod.Id, storeId, countryId, weight); diff --git a/src/Plugins/SmartStore.ShippingByWeight/Description.txt b/src/Plugins/SmartStore.ShippingByWeight/Description.txt index 9dd67c0819..65f72e227d 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Description.txt +++ b/src/Plugins/SmartStore.ShippingByWeight/Description.txt @@ -1,7 +1,7 @@ FriendlyName: Shipping by weight SystemName: SmartStore.ShippingByWeight Group: Shipping -Version: 2.2.0 +Version: 2.2.0.1 MinAppVersion: 2.2.0 DisplayOrder: 1 FileName: SmartStore.ShippingByWeight.dll diff --git a/src/Presentation/SmartStore.Web/Administration/Content/admin.less b/src/Presentation/SmartStore.Web/Administration/Content/admin.less index 0828ff57e8..7c7a6017d3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Content/admin.less +++ b/src/Presentation/SmartStore.Web/Administration/Content/admin.less @@ -1197,9 +1197,9 @@ table.payment-method-features td { font-size: 12px; } -/* payment methods restrictions +/* payment and shipping restrictions -------------------------------------------------------------- */ -.payment-restrictions { +.restriction-container { th label { margin: 0 10px 0 0; display: inline-block; @@ -1226,7 +1226,7 @@ table.payment-method-features td { display: table-row; } - .country-countainer { + .country-container { display: table-cell; width: 25%; padding-right: 10px; diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs index e554dbdf20..996f0af0a5 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs @@ -7,6 +7,7 @@ using SmartStore.Core.Domain.Shipping; using SmartStore.Core.Plugins; using SmartStore.Services; +using SmartStore.Services.Customers; using SmartStore.Services.Directory; using SmartStore.Services.Localization; using SmartStore.Services.Security; @@ -31,6 +32,7 @@ public partial class ShippingController : AdminControllerBase private readonly IPluginFinder _pluginFinder; private readonly PluginMediator _pluginMediator; private readonly ICommonServices _commonServices; + private readonly ICustomerService _customerService; #endregion @@ -43,7 +45,8 @@ public ShippingController(IShippingService shippingService, ILanguageService languageService, IPluginFinder pluginFinder, PluginMediator pluginMediator, - ICommonServices commonServices) + ICommonServices commonServices, + ICustomerService customerService) { this._shippingService = shippingService; this._shippingSettings = shippingSettings; @@ -53,6 +56,7 @@ public ShippingController(IShippingService shippingService, this._pluginFinder = pluginFinder; this._pluginMediator = pluginMediator; this._commonServices = commonServices; + this._customerService = customerService; } #endregion  @@ -76,6 +80,38 @@ protected void UpdateLocales(ShippingMethod shippingMethod, ShippingMethodModel } } + private void PrepareShippingMethodModel(ShippingMethodModel model, ShippingMethod shippingMethod) + { + SelectListItem item = null; + var customerRoles = _customerService.GetAllCustomerRoles(true); + + model.AvailableCustomerRoles = new List(); + + foreach (var role in customerRoles.OrderBy(x => x.Name)) + { + model.AvailableCustomerRoles.Add(new SelectListItem { Text = role.Name, Value = role.Id.ToString() }); + } + + if (shippingMethod != null) + { + foreach (var id in shippingMethod.ExcludedCustomerRoleIds.SplitSafe(",")) + { + if ((item = model.AvailableCustomerRoles.FirstOrDefault(x => x.Value == id)) != null) + item.Selected = true; + } + } + } + + private void ApplyRestrictions(ShippingMethod shippingMethod) + { + var customerRoleIds = Request.Form.AllKeys + .Where(x => x.StartsWith("CustomerRole_")) + .Select(x => x.Replace("CustomerRole_", "")) + .ToList(); + + shippingMethod.ExcludedCustomerRoleIds = string.Join(",", customerRoleIds); + } + #endregion #region Shipping rate computation methods @@ -173,6 +209,7 @@ public ActionResult CreateMethod() return AccessDeniedView(); var model = new ShippingMethodModel(); + PrepareShippingMethodModel(model, null); //locales AddLocales(_languageService, model.Locales); @@ -188,6 +225,8 @@ public ActionResult CreateMethod(ShippingMethodModel model, bool continueEditing if (ModelState.IsValid) { var sm = model.ToEntity(); + ApplyRestrictions(sm); + _shippingService.InsertShippingMethod(sm); //locales @@ -209,10 +248,11 @@ public ActionResult EditMethod(int id) var sm = _shippingService.GetShippingMethodById(id); if (sm == null) - //No shipping method found with the specified id return RedirectToAction("Methods"); var model = sm.ToModel(); + PrepareShippingMethodModel(model, sm); + //locales AddLocales(_languageService, model.Locales, (locale, languageId) => { @@ -236,6 +276,8 @@ public ActionResult EditMethod(ShippingMethodModel model, bool continueEditing) if (ModelState.IsValid) { sm = model.ToEntity(sm); + ApplyRestrictions(sm); + _shippingService.UpdateShippingMethod(sm); //locales diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodModel.cs index 134d4af1ea..c9690b4695 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodModel.cs @@ -15,6 +15,7 @@ public ShippingMethodModel() { Locales = new List(); } + [SmartResourceDisplayName("Admin.Configuration.Shipping.Methods.Fields.Name")] [AllowHtml] public string Name { get; set; } @@ -30,6 +31,8 @@ public ShippingMethodModel() public bool IgnoreCharges { get; set; } public IList Locales { get; set; } + + public List AvailableCustomerRoles { get; set; } } public class ShippingMethodLocalizedModel : ILocalizedModelLocal @@ -43,6 +46,5 @@ public class ShippingMethodLocalizedModel : ILocalizedModelLocal [SmartResourceDisplayName("Admin.Configuration.Shipping.Methods.Fields.Description")] [AllowHtml] public string Description { get; set; } - } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml index 61283a2345..51d94abb2e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml @@ -6,7 +6,7 @@ ViewBag.Title = T("Common.Edit").Text + " - " + Model.FriendlyName; } -@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "paymentmethod-form" })) +@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "payment-method-form" })) {
@@ -24,12 +24,12 @@ @Html.HiddenFor(model => model.SystemName) - @Html.SmartStore().TabStrip().Name("paymentmethod-edit").Items(x => + @Html.SmartStore().TabStrip().Name("payment-method-edit").Items(x => { x.Add().Text(T("Admin.Common.General").Text).Content(TabGeneral()).Selected(true); x.Add().Text(T("Admin.Common.Restrictions").Text).Content(TabRestrictions()); - EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "paymentmethod-edit", this.Html, this.Model)); + EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "payment-method-edit", this.Html, this.Model)); }) } @@ -91,7 +91,7 @@ @Html.Raw(T("Admin.Configuration.Payment.Methods.RestrictionNote"))
-
+
- + @@ -524,7 +543,24 @@ else {
@T("Admin.Configuration.Stores.NoStoresDefined")
- } + } + + + + + + +
@@ -152,7 +152,7 @@
@foreach (var item in grp) { -
+
@RenderCheckbox(item, "Country_")
} @@ -180,11 +180,11 @@ jQuery(document).ready(function () { // restictions column header checkbox clicked - $('.payment-restrictions th input[type="checkbox"]').change(function () { + $('.restriction-container th input[type="checkbox"]').change(function () { var id = $(this).attr('id').replace('Master', ''), isChecked = $(this).is(':checked'); - $('.payment-restrictions td input[name^="' + id + '"]').attr('checked', isChecked); + $('.restriction-container td input[name^="' + id + '"]').attr('checked', isChecked); }); }); diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Methods.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Methods.cshtml index 494932317a..f74ed89677 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Methods.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Methods.cshtml @@ -2,9 +2,9 @@ @using Telerik.Web.Mvc.UI; @using System.Linq; @{ - //page title ViewBag.Title = T("Admin.Configuration.Shipping.Methods").Text; } +
@@ -14,6 +14,7 @@  @T("Admin.Common.AddNew")
+ - + @@ -466,11 +466,30 @@ @customerRole.Name - } - } - else { -
No customer roles defined
- } + } + } + else + { +
+ @T("Admin.Configuration.Acl.NoRolesDefined") +
+ } + + + + + +
@@ -25,22 +26,18 @@ }) .Columns(columns => { - columns.Bound(x => x.Name); + columns.Bound(x => x.Name) + .Template(x => Html.ActionLink(x.Name, "EditMethod", new { id = x.Id })) + .ClientTemplate("\"><#= Name #>"); columns.Bound(x => x.Description); columns.Bound(x => x.IgnoreCharges) .Template(item => @Html.SymbolForBool(item.IgnoreCharges)) .ClientTemplate(@Html.SymbolForBool("IgnoreCharges")) - .Width(160) + .Width(250) .Centered(); columns.Bound(x => x.DisplayOrder) .Width(160) .Centered(); - columns.Bound(x => x.Id) - .Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "EditMethod", new { id = x.Id })) - .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") - .Width(160) - .Centered() - .HeaderTemplate(T("Admin.Common.Edit").Text); }) .DataBinding(dataBinding => dataBinding.Ajax().Select("Methods", "Shipping")) .EnableCustomBinding(true)) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml index dbd129ab13..9033b3beb7 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml @@ -1,72 +1,140 @@ @model ShippingMethodModel @using Telerik.Web.Mvc.UI; + @Html.ValidationSummary(true) @Html.HiddenFor(model => model.Id) -@(Html.LocalizedEditor("shipping-method-localized", - @ - - - - - - - - - - - -
- @Html.SmartLabelFor(model => model.Locales[item].Name) - - @Html.EditorFor(model => Model.Locales[item].Name) - @Html.ValidationMessageFor(model => model.Locales[item].Name) -
- @Html.SmartLabelFor(model => model.Locales[item].Description) - - @Html.TextAreaFor(model => model.Locales[item].Description) - @Html.ValidationMessageFor(model => model.Locales[item].Description) -
- @Html.HiddenFor(model => model.Locales[item].LanguageId) -
- , - @ - - - - - - - - -
- @Html.SmartLabelFor(model => model.Name) - - @Html.EditorFor(model => model.Name) - @Html.ValidationMessageFor(model => model.Name) -
- @Html.SmartLabelFor(model => model.Description) - - @Html.TextAreaFor(model => model.Description) - @Html.ValidationMessageFor(model => model.Description) -
- )) - - - - - - - - - -
- @Html.SmartLabelFor(model => model.DisplayOrder) - - @Html.EditorFor(model => model.DisplayOrder) - @Html.ValidationMessageFor(model => model.DisplayOrder) -
- @Html.SmartLabelFor(model => model.IgnoreCharges) - - @Html.EditorFor(model => model.IgnoreCharges) - @Html.ValidationMessageFor(model => model.IgnoreCharges) -
+ +@Html.SmartStore().TabStrip().Name("shipping-method-edit").Items(x => +{ + x.Add().Text(T("Admin.Common.General").Text).Content(TabGeneral()).Selected(true); + x.Add().Text(T("Admin.Common.Restrictions").Text).Content(TabRestrictions()); + + EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "shipping-method-edit", this.Html, this.Model)); +}) + +@helper TabGeneral() +{ + @(Html.LocalizedEditor("shipping-method-localized", + @ + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Locales[item].Name) + + @Html.EditorFor(model => Model.Locales[item].Name) + @Html.ValidationMessageFor(model => model.Locales[item].Name) +
+ @Html.SmartLabelFor(model => model.Locales[item].Description) + + @Html.TextAreaFor(model => model.Locales[item].Description) + @Html.ValidationMessageFor(model => model.Locales[item].Description) +
+ @Html.HiddenFor(model => model.Locales[item].LanguageId) +
+ , + @ + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Name) + + @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ @Html.SmartLabelFor(model => model.Description) + + @Html.TextAreaFor(model => model.Description) + @Html.ValidationMessageFor(model => model.Description) +
+ )) + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.DisplayOrder) + + @Html.EditorFor(model => model.DisplayOrder) + @Html.ValidationMessageFor(model => model.DisplayOrder) +
+ @Html.SmartLabelFor(model => model.IgnoreCharges) + + @Html.EditorFor(model => model.IgnoreCharges) + @Html.ValidationMessageFor(model => model.IgnoreCharges) +
+} + +@helper TabRestrictions() +{ +
+ @Html.Raw(T("Admin.Configuration.Shipping.Methods.RestrictionNote")) +
+ +
+ + + + + + + +
+
+ +
+
+ @foreach (var item in Model.AvailableCustomerRoles) + { + @RenderCheckbox(item, "CustomerRole_") + } +
+
+} + +@helper RenderCheckbox(SelectListItem item, string prefix) +{ +
+ +
+} + + \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs index e2e5bfd066..f155909a21 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Web; using System.Web.Mvc; -using System.Web.Routing; using SmartStore.Core; using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Customers; @@ -11,24 +10,22 @@ using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; using SmartStore.Core.Domain.Shipping; -using SmartStore.Core.Plugins; +using SmartStore.Core.Logging; using SmartStore.Services.Catalog; using SmartStore.Services.Common; +using SmartStore.Services.Configuration; using SmartStore.Services.Customers; using SmartStore.Services.Directory; using SmartStore.Services.Localization; -using SmartStore.Core.Logging; using SmartStore.Services.Orders; using SmartStore.Services.Payments; using SmartStore.Services.Shipping; using SmartStore.Services.Tax; using SmartStore.Web.Framework.Controllers; +using SmartStore.Web.Framework.Plugins; using SmartStore.Web.Framework.Security; using SmartStore.Web.Models.Checkout; using SmartStore.Web.Models.Common; -using SmartStore.Services.Configuration; -using SmartStore.Web.Framework.Plugins; -using SmartStore.Web.Models.ShoppingCart; namespace SmartStore.Web.Controllers { @@ -238,6 +235,7 @@ protected CheckoutShippingMethodModel PrepareShippingMethodModel(IList !String.IsNullOrEmpty(so.Name) && so.Name.Equals(selectedShippingOption.Name, StringComparison.InvariantCultureIgnoreCase) && !String.IsNullOrEmpty(so.ShippingRateComputationMethodSystemName) && so.ShippingRateComputationMethodSystemName.Equals(selectedShippingOption.ShippingRateComputationMethodSystemName, StringComparison.InvariantCultureIgnoreCase)); + if (shippingOptionToSelect != null) shippingOptionToSelect.Selected = true; } @@ -592,8 +590,7 @@ public ActionResult ShippingMethod() { _genericAttributeService.SaveAttribute(_workContext.CurrentCustomer, SystemCustomerAttributeNames.SelectedShippingOption, null, _storeContext.CurrentStore.Id); return RedirectToAction("PaymentMethod"); - } - + } //model var model = PrepareShippingMethodModel(cart); From 99057824e87d3bd3030eebc23198d9ea5bc3ba7f Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 17 Jun 2015 18:08:11 +0200 Subject: [PATCH 0152/1256] A frontend request should not revoke merchant settings (like provider activation). Improved fallback for payment and shipping method. --- .../Payments/IPaymentService.cs | 4 +++- .../Payments/PaymentService.cs | 23 ++++++++++++------- .../Shipping/ShippingService.cs | 16 +++++++++---- .../Controllers/CheckoutController.cs | 8 +++---- .../Controllers/ShoppingCartController.cs | 7 +++--- 5 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs b/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs index 1013a7bae5..709c6eafc2 100644 --- a/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs @@ -16,8 +16,10 @@ public partial interface IPaymentService /// /// Filter payment methods by customer and apply payment method restrictions; null to load all records /// Filter payment methods by store identifier; pass 0 to load all records + /// Filter payment methods by payment method types + /// Provide a fallback payment method if none is active /// Payment methods - IEnumerable> LoadActivePaymentMethods(Customer customer = null, int storeId = 0); + IEnumerable> LoadActivePaymentMethods(Customer customer = null, int storeId = 0, PaymentMethodType[] types = null, bool provideFallbackMethod = true); /// /// Determines whether a payment method is active\enabled for a shop diff --git a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs index f2e02400f5..7923546540 100644 --- a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs @@ -80,13 +80,20 @@ public PaymentService( /// /// Filter payment methods by customer and apply payment method restrictions; null to load all records /// Filter payment methods by store identifier; pass 0 to load all records + /// Filter payment methods by payment method types + /// Provide a fallback payment method if none is active /// Payment methods - public virtual IEnumerable> LoadActivePaymentMethods(Customer customer = null, int storeId = 0) + public virtual IEnumerable> LoadActivePaymentMethods(Customer customer = null, int storeId = 0, PaymentMethodType[] types = null, + bool provideFallbackMethod = true) { List customerRoleIds = null; int? selectedShippingMethodId = null; + IEnumerable> allProviders = null; - var allProviders = LoadAllPaymentMethods(storeId); + if (types != null && types.Any()) + allProviders = LoadAllPaymentMethods(storeId).Where(x => types.Contains(x.Value.PaymentMethodType)); + else + allProviders = LoadAllPaymentMethods(storeId); var activeProviders = allProviders .Where(p => @@ -142,15 +149,15 @@ public virtual IEnumerable> LoadActivePaymentMethods(Cu return true; }); - if (!activeProviders.Any()) + if (!activeProviders.Any() && provideFallbackMethod) { - var fallbackMethod = allProviders.FirstOrDefault(); + var fallbackMethod = allProviders.FirstOrDefault(x => x.IsPaymentMethodActive(_paymentSettings)); + + if (fallbackMethod == null) + fallbackMethod = allProviders.FirstOrDefault(); + if (fallbackMethod != null) { - _paymentSettings.ActivePaymentMethodSystemNames.Clear(); - _paymentSettings.ActivePaymentMethodSystemNames.Add(fallbackMethod.Metadata.SystemName); - _settingService.SaveSetting(_paymentSettings); - return new Provider[] { fallbackMethod }; } else diff --git a/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs b/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs index 857aabdc54..d29ce01907 100644 --- a/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs +++ b/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs @@ -109,18 +109,24 @@ public virtual IEnumerable> LoadActiveS if (!activeMethods.Any()) { - var fallbackMethod = allMethods.FirstOrDefault(); + var fallbackMethod = allMethods.FirstOrDefault(x => x.IsShippingRateComputationMethodActive(_shippingSettings)); + + if (fallbackMethod == null) + fallbackMethod = allMethods.FirstOrDefault(); + if (fallbackMethod != null) { - _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Clear(); - _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Add(fallbackMethod.Metadata.SystemName); - _settingService.SaveSetting(_shippingSettings); + // a frontend request should not revoke merchant settings + //_shippingSettings.ActiveShippingRateComputationMethodSystemNames.Clear(); + //_shippingSettings.ActiveShippingRateComputationMethodSystemNames.Add(fallbackMethod.Metadata.SystemName); + //_settingService.SaveSetting(_shippingSettings); return new Provider[] { fallbackMethod }; } else { - throw Error.Application("At least one shipping method provider is required to be active."); + if (DataSettings.DatabaseIsInstalled()) + throw Error.Application("At least one shipping method provider is required to be active."); } } diff --git a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs index f155909a21..bb52c695f7 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs @@ -276,12 +276,10 @@ protected CheckoutPaymentMethodModel PreparePaymentMethodModel(IList - pm.Value.PaymentMethodType == PaymentMethodType.Standard || - pm.Value.PaymentMethodType == PaymentMethodType.Redirection || - pm.Value.PaymentMethodType == PaymentMethodType.StandardAndRedirection) + .LoadActivePaymentMethods(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id, paymentTypes) .ToList(); foreach (var pm in boundPaymentMethods) diff --git a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs index c2385539c6..e0a06c16c6 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs @@ -545,11 +545,10 @@ private void PrepareButtonPaymentMethodModel(ButtonPaymentMethodModel model, ILi { model.Items.Clear(); + var paymentTypes = new PaymentMethodType[] { PaymentMethodType.Button, PaymentMethodType.StandardAndButton }; + var boundPaymentMethods = _paymentService - .LoadActivePaymentMethods(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id) - .Where(pm => - pm.Value.PaymentMethodType == PaymentMethodType.Button || - pm.Value.PaymentMethodType == PaymentMethodType.StandardAndButton) + .LoadActivePaymentMethods(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id, paymentTypes, false) .ToList(); foreach (var pm in boundPaymentMethods) From e59f0c3f4f0ae3361183371815509631f1163fbb Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 18 Jun 2015 01:22:38 +0200 Subject: [PATCH 0153/1256] (Soft) deletion of ISlugSupported entities now also deletes corresponding url records --- .../SmartStore.Data/ObjectContextBase.cs | 2 +- .../Catalog/ProductService.cs | 6 +- .../ExportImport/ImportManager.cs | 2 +- .../Hooks/SlugSupportedPostDeleteHook.cs | 31 ++++++ .../Hooks/SoftDeletablePreUpdateHook.cs | 48 ++++++--- .../Seo/IUrlRecordService.cs | 10 ++ .../SmartStore.Services/Seo/SeoExtensions.cs | 22 ++--- .../Seo/UrlRecordService.cs | 98 +++++++------------ .../SmartStore.Services.csproj | 1 + .../Seo/GenericPathRoute.cs | 10 +- 10 files changed, 130 insertions(+), 100 deletions(-) create mode 100644 src/Libraries/SmartStore.Services/Hooks/SlugSupportedPostDeleteHook.cs diff --git a/src/Libraries/SmartStore.Data/ObjectContextBase.cs b/src/Libraries/SmartStore.Data/ObjectContextBase.cs index 201e6fe9e1..851a066d8c 100644 --- a/src/Libraries/SmartStore.Data/ObjectContextBase.cs +++ b/src/Libraries/SmartStore.Data/ObjectContextBase.cs @@ -80,7 +80,7 @@ private void PerformPreSaveActions(out IList modifiedEntries, out if (hooksEnabled) { modifiedHookEntries = modifiedEntries - .Select(x => new HookedEntityEntry() + .Select(x => new HookedEntityEntry { Entity = x.Entity, PreSaveState = (SmartStore.Core.Data.EntityState)((int)x.State) diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs index f3963aaf34..2f8c1270e3 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs @@ -327,13 +327,13 @@ public virtual void UpdateProduct(Product product, bool publishEvent = true) modified = _productRepository.IsModified(product); } - //update + // update _productRepository.Update(product); - //cache + // cache _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); - //event notification + // event notification if (publishEvent && modified) { _eventPublisher.EntityUpdated(product); diff --git a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs index 8ba2fe85ae..2dd762b398 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs @@ -603,7 +603,7 @@ private int ProcessProductCategories(ICollection> batch, Impo var category = _categoryService.GetCategoryById(id); if (category != null) { - var productCategory = new ProductCategory() + var productCategory = new ProductCategory { ProductId = row.Entity.Id, CategoryId = category.Id, diff --git a/src/Libraries/SmartStore.Services/Hooks/SlugSupportedPostDeleteHook.cs b/src/Libraries/SmartStore.Services/Hooks/SlugSupportedPostDeleteHook.cs new file mode 100644 index 0000000000..9c7c0cbb49 --- /dev/null +++ b/src/Libraries/SmartStore.Services/Hooks/SlugSupportedPostDeleteHook.cs @@ -0,0 +1,31 @@ +using System; +using SmartStore.Core; +using SmartStore.Core.Data.Hooks; +using SmartStore.Core.Domain.Seo; +using SmartStore.Services.Seo; + +namespace SmartStore.Services.Common +{ + public class SlugSupportedPostDeleteHook : PostDeleteHook + { + private readonly Lazy _urlRecordService; + + public SlugSupportedPostDeleteHook(Lazy urlRecordService) + { + this._urlRecordService = urlRecordService; + } + + public override void Hook(ISlugSupported entity, HookEntityMetadata metadata) + { + var baseEntity = entity as BaseEntity; + + if (baseEntity == null) + return; + + var entityType = baseEntity.GetUnproxiedType(); + + var records = _urlRecordService.Value.GetUrlRecordsFor(entityType.Name, baseEntity.Id); + records.Each(x => _urlRecordService.Value.DeleteUrlRecord(x)); + } + } +} diff --git a/src/Libraries/SmartStore.Services/Hooks/SoftDeletablePreUpdateHook.cs b/src/Libraries/SmartStore.Services/Hooks/SoftDeletablePreUpdateHook.cs index ae87d21fa5..1b3f9fba24 100644 --- a/src/Libraries/SmartStore.Services/Hooks/SoftDeletablePreUpdateHook.cs +++ b/src/Libraries/SmartStore.Services/Hooks/SoftDeletablePreUpdateHook.cs @@ -1,22 +1,22 @@ -using System; +using Autofac; using SmartStore.Core; using SmartStore.Core.Data; using SmartStore.Core.Data.Hooks; using SmartStore.Core.Domain.Security; +using SmartStore.Core.Domain.Seo; using SmartStore.Services.Security; +using SmartStore.Services.Seo; namespace SmartStore.Services.Hooks { public class SoftDeletablePreUpdateHook : PreUpdateHook { - private readonly Lazy _aclService; - private readonly Lazy _dbContext; + private readonly IComponentContext _ctx; - public SoftDeletablePreUpdateHook(Lazy aclService, Lazy dbContext) + public SoftDeletablePreUpdateHook(IComponentContext ctx) { - this._aclService = aclService; - this._dbContext = dbContext; + this._ctx = ctx; } public override void Hook(ISoftDeletable entity, HookEntityMetadata metadata) @@ -26,22 +26,42 @@ public override void Hook(ISoftDeletable entity, HookEntityMetadata metadata) if (baseEntity == null) return; - var aclEntity = baseEntity as IAclSupported; - if (aclEntity == null || !aclEntity.SubjectToAcl) + var dbContext = _ctx.Resolve(); + var modifiedProps = dbContext.GetModifiedProperties(baseEntity); + + if (!modifiedProps.ContainsKey("Deleted")) return; - var ctx = _dbContext.Value; - var modProps = ctx.GetModifiedProperties(baseEntity); - if (modProps.ContainsKey("Deleted")) + var entityType = baseEntity.GetUnproxiedType(); + + // mark orphaned ACL records as idle + var aclSupported = baseEntity as IAclSupported; + if (aclSupported != null && aclSupported.SubjectToAcl) { var shouldSetIdle = entity.Deleted; - var entityType = baseEntity.GetUnproxiedType(); - var records = _aclService.Value.GetAclRecordsFor(entityType.Name, baseEntity.Id); + var aclService = _ctx.Resolve(); + var records = aclService.GetAclRecordsFor(entityType.Name, baseEntity.Id); foreach (var record in records) { record.IsIdle = shouldSetIdle; - _aclService.Value.UpdateAclRecord(record); + aclService.UpdateAclRecord(record); + } + } + + // Delete orphaned inactive UrlRecords. + // We keep the active ones on purpose in order to be able to fully restore a soft deletable entity once we implemented the "recycle bin" feature + var slugSupported = baseEntity as ISlugSupported; + if (slugSupported != null && entity.Deleted) + { + var urlRecordService = _ctx.Resolve(); + var activeRecords = urlRecordService.GetUrlRecordsFor(entityType.Name, baseEntity.Id); + foreach (var record in activeRecords) + { + if (!record.IsActive) + { + urlRecordService.DeleteUrlRecord(record); + } } } } diff --git a/src/Libraries/SmartStore.Services/Seo/IUrlRecordService.cs b/src/Libraries/SmartStore.Services/Seo/IUrlRecordService.cs index 4f6f5f00ae..3f3451c12d 100644 --- a/src/Libraries/SmartStore.Services/Seo/IUrlRecordService.cs +++ b/src/Libraries/SmartStore.Services/Seo/IUrlRecordService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq.Expressions; using SmartStore.Core; using SmartStore.Core.Domain.Seo; @@ -51,6 +52,15 @@ public partial interface IUrlRecordService /// Customer collection IPagedList GetAllUrlRecords(string slug, int pageIndex, int pageSize); + /// + /// Gets all URL records for the specified entity + /// + /// Type + /// Entity + /// Specifies whether only active URL records should be returned + /// List of URL records + IList GetUrlRecordsFor(string entityName, int entityId, bool activeOnly = false); + /// /// Find slug /// diff --git a/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs b/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs index 8bbb6e60fe..1d1c5a6c9d 100644 --- a/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs +++ b/src/Libraries/SmartStore.Services/Seo/SeoExtensions.cs @@ -160,20 +160,20 @@ public static string GetSeName(this T entity, if (languageId > 0) { - //ensure that we have at least two published languages + // ensure that we have at least two published languages bool loadLocalizedValue = true; if (ensureTwoPublishedLanguages) { var totalPublishedLanguages = languageService.GetLanguagesCount(false); loadLocalizedValue = totalPublishedLanguages >= 2; } - //localized value + // localized value if (loadLocalizedValue) { result = urlRecordService.GetActiveSlug(entity.Id, entityName, languageId); } } - //set default value if required + // set default value if required if (String.IsNullOrEmpty(result) && returnDefaultValue) { result = urlRecordService.GetActiveSlug(entity.Id, entityName, 0); @@ -218,31 +218,31 @@ public static string ValidateSeName(this T entity, if (entity == null) throw new ArgumentNullException("entity"); - //use name if sename is not specified + // use name if sename is not specified if (String.IsNullOrWhiteSpace(seName) && !String.IsNullOrWhiteSpace(name)) seName = name; - //validation + // validation seName = GetSeName(seName, seoSettings); - //max length + // max length seName = seName.Truncate(400); if (String.IsNullOrWhiteSpace(seName)) { if (ensureNotEmpty) { - //use entity identifier as sename if empty + // use entity identifier as sename if empty seName = entity.Id.ToString(); } else { - //return. no need for further processing + // return. no need for further processing return seName; } } - //ensure this sename is not reserved yet + // ensure this sename is not reserved yet string entityName = typeof(T).Name; int i = 2; var tempSeName = seName; @@ -251,14 +251,14 @@ public static string ValidateSeName(this T entity, while (true) { - // check whether such slug already exists (and that is not the current product) + // check whether such slug already exists (and that it's not the current entity) var urlRecord = urlRecordService.GetBySlug(tempSeName) ?? extraSlugLookup(tempSeName); var reserved1 = urlRecord != null && !(urlRecord.EntityId == entity.Id && urlRecord.EntityName.Equals(entityName, StringComparison.InvariantCultureIgnoreCase)); if (!reserved1 && urlRecord != null && languageId.HasValue) reserved1 = (urlRecord.LanguageId != languageId.Value); - //and it's not in the list of reserved slugs + // and it's not in the list of reserved slugs var reserved2 = seoSettings.ReservedUrlRecordSlugs.Contains(tempSeName, StringComparer.InvariantCultureIgnoreCase); if (!reserved1 && !reserved2) break; diff --git a/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs b/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs index 5d071432d3..0a48b005f9 100644 --- a/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs +++ b/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using SmartStore.Core; @@ -39,10 +40,6 @@ public UrlRecordService(ICacheManager cacheManager, IRepository urlRe #region Methods - /// - /// Deletes an URL record - /// - /// URL record public virtual void DeleteUrlRecord(UrlRecord urlRecord) { if (urlRecord == null) @@ -54,11 +51,6 @@ public virtual void DeleteUrlRecord(UrlRecord urlRecord) _cacheManager.RemoveByPattern(URLRECORD_PATTERN_KEY); } - /// - /// Gets an URL record - /// - /// URL record identifier - /// URL record public virtual UrlRecord GetUrlRecordById(int urlRecordId) { if (urlRecordId == 0) @@ -68,10 +60,6 @@ public virtual UrlRecord GetUrlRecordById(int urlRecordId) return urlRecord; } - /// - /// Inserts an URL record - /// - /// URL record public virtual void InsertUrlRecord(UrlRecord urlRecord) { if (urlRecord == null) @@ -83,10 +71,6 @@ public virtual void InsertUrlRecord(UrlRecord urlRecord) _cacheManager.RemoveByPattern(URLRECORD_PATTERN_KEY); } - /// - /// Updates the URL record - /// - /// URL record public virtual void UpdateUrlRecord(UrlRecord urlRecord) { if (urlRecord == null) @@ -98,11 +82,6 @@ public virtual void UpdateUrlRecord(UrlRecord urlRecord) _cacheManager.RemoveByPattern(URLRECORD_PATTERN_KEY); } - /// - /// Find URL record - /// - /// Slug - /// Found URL record public virtual UrlRecord GetBySlug(string slug) { if (String.IsNullOrEmpty(slug)) @@ -115,13 +94,6 @@ public virtual UrlRecord GetBySlug(string slug) return urlRecord; } - /// - /// Gets all URL records - /// - /// Slug - /// Page index - /// Page size - /// Customer collection public virtual IPagedList GetAllUrlRecords(string slug, int pageIndex, int pageSize) { var query = _urlRecordRepository.Table; @@ -133,13 +105,23 @@ public virtual IPagedList GetAllUrlRecords(string slug, int pageIndex return urlRecords; } - /// - /// Find slug - /// - /// Entity identifier - /// Entity name - /// Language identifier - /// Found slug + public virtual IList GetUrlRecordsFor(string entityName, int entityId, bool activeOnly = false) + { + Guard.ArgumentNotEmpty(() => entityName); + + var query = from ur in _urlRecordRepository.Table + where ur.EntityId == entityId && + ur.EntityName == entityName + select ur; + + if (activeOnly) + { + query = query.Where(ur => ur.IsActive); + } + + return query.ToList(); + } + public virtual string GetActiveSlug(int entityId, string entityName, int languageId) { string key = string.Format(URLRECORD_ACTIVE_BY_ID_NAME_LANGUAGE_KEY, entityId, entityName, languageId); @@ -157,13 +139,6 @@ orderby ur.Id descending }); } - /// - /// Save slug - /// - /// Type - /// Entity - /// Slug - /// Language ID public virtual UrlRecord SaveSlug(T entity, string slug, int languageId) where T : BaseEntity, ISlugSupported { if (entity == null) @@ -184,18 +159,18 @@ orderby ur.Id descending var activeUrlRecord = allUrlRecords.FirstOrDefault(x => x.IsActive); if (activeUrlRecord == null && !string.IsNullOrWhiteSpace(slug)) { - //find in non-active records with the specified slug + // find in non-active records with the specified slug var nonActiveRecordWithSpecifiedSlug = allUrlRecords.FirstOrDefault(x => x.Slug.Equals(slug, StringComparison.InvariantCultureIgnoreCase) && !x.IsActive); if (nonActiveRecordWithSpecifiedSlug != null) { - //mark non-active record as active + // mark non-active record as active nonActiveRecordWithSpecifiedSlug.IsActive = true; UpdateUrlRecord(nonActiveRecordWithSpecifiedSlug); } else { - //new record - var urlRecord = new UrlRecord() + // new record + var urlRecord = new UrlRecord { EntityId = entity.Id, EntityName = entityName, @@ -210,27 +185,27 @@ orderby ur.Id descending if (activeUrlRecord != null && string.IsNullOrWhiteSpace(slug)) { - //disable the previous active URL record + // disable the previous active URL record activeUrlRecord.IsActive = false; UpdateUrlRecord(activeUrlRecord); } if (activeUrlRecord != null && !string.IsNullOrWhiteSpace(slug)) { - //is it the same slug as in active URL record? + // is it the same slug as in active URL record? if (activeUrlRecord.Slug.Equals(slug, StringComparison.InvariantCultureIgnoreCase)) { - //yes. do nothing - //P.S. wrote this way for more source code readability + // yes. do nothing + // P.S. wrote this way for more source code readability } else { - //find in non-active records with the specified slug + // find in non-active records with the specified slug var nonActiveRecordWithSpecifiedSlug = allUrlRecords .FirstOrDefault(x => x.Slug.Equals(slug, StringComparison.InvariantCultureIgnoreCase) && !x.IsActive); if (nonActiveRecordWithSpecifiedSlug != null) { - //mark non-active record as active + // mark non-active record as active nonActiveRecordWithSpecifiedSlug.IsActive = true; UpdateUrlRecord(nonActiveRecordWithSpecifiedSlug); @@ -255,10 +230,10 @@ orderby ur.Id descending } else { - //insert new record - //we do not update the existing record because we should track all previously entered slugs - //to ensure that URLs will work fine - var urlRecord = new UrlRecord() + // insert new record + // we do not update the existing record because we should track all previously entered slugs + // to ensure that URLs will work fine + var urlRecord = new UrlRecord { EntityId = entity.Id, EntityName = entityName, @@ -269,7 +244,7 @@ orderby ur.Id descending InsertUrlRecord(urlRecord); result = urlRecord; - //disable the previous active URL record + // disable the previous active URL record activeUrlRecord.IsActive = false; UpdateUrlRecord(activeUrlRecord); } @@ -281,13 +256,6 @@ orderby ur.Id descending return result; } - /// - /// Save slug - /// - /// Type - /// Entity - /// Name of a property - /// Url record public virtual UrlRecord SaveSlug(T entity, Expression> nameProperty) where T : BaseEntity, ISlugSupported { string name = nameProperty.Compile().Invoke(entity); diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index 5d5e01f9a6..91cca5e43a 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -159,6 +159,7 @@ + diff --git a/src/Presentation/SmartStore.Web.Framework/Seo/GenericPathRoute.cs b/src/Presentation/SmartStore.Web.Framework/Seo/GenericPathRoute.cs index 2e37000e2d..6ea897dfa0 100644 --- a/src/Presentation/SmartStore.Web.Framework/Seo/GenericPathRoute.cs +++ b/src/Presentation/SmartStore.Web.Framework/Seo/GenericPathRoute.cs @@ -90,11 +90,11 @@ public override RouteData GetRouteData(HttpContextBase httpContext) } if (!urlRecord.IsActive) { - //URL record is not active. let's find the latest one + // URL record is not active. let's find the latest one var activeSlug = urlRecordService.GetActiveSlug(urlRecord.EntityId, urlRecord.EntityName, urlRecord.LanguageId); if (!string.IsNullOrWhiteSpace(activeSlug)) { - //the active one is found + // the active one is found var webHelper = EngineContext.Current.Resolve(); var response = httpContext.Response; response.Status = "301 Moved Permanently"; @@ -104,14 +104,14 @@ public override RouteData GetRouteData(HttpContextBase httpContext) } else { - //no active slug found + // no active slug found data.Values["controller"] = "Error"; data.Values["action"] = "NotFound"; return data; } } - //process URL + // process URL data.Values["SeName"] = urlRecord.Slug; switch (urlRecord.EntityName.ToLowerInvariant()) { @@ -152,7 +152,7 @@ public override RouteData GetRouteData(HttpContextBase httpContext) break; default: { - throw new SmartException(string.Format("Not supported EntityName for UrlRecord: {0}", urlRecord.EntityName)); + throw new SmartException(string.Format("Unsupported EntityName for UrlRecord: {0}", urlRecord.EntityName)); } } } From 9b80c504202111821169351a633d36f3afe49d0c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 18 Jun 2015 11:02:47 +0200 Subject: [PATCH 0154/1256] Updated changelog --- changelog.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index 3c5e567274..2810999e98 100644 --- a/changelog.md +++ b/changelog.md @@ -1,13 +1,17 @@ # Release Notes -## SmartStore.NET 2.2.2 +## SmartStore.NET 2.5 ### New Features -* #210 Implement multi-store support for import/export -* #141 Payment methods by customer roles +* #141 Payment and shipping methods by customer roles * #67 Restrict payment methods to certain countries * #94 Restrict payment methods to certain shipping methods +## SmartStore.NET 2.2.2 + +### New Features +* #210 Implement multi-store support for import/export + ### Improvements * License checker now supports IDN mapping for domain names From 93629326c72920bbd0053a0ac21f90e7e8c835ed Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 18 Jun 2015 19:15:44 +0200 Subject: [PATCH 0155/1256] Resolves #526 Min\max amount option for which the payment method should be offered during checkout --- changelog.md | 1 + .../Domain/Payments/PaymentMethod.cs | 34 +++++ ...textType.cs => RestrictionContextTypes.cs} | 6 + .../SmartStore.Core/SmartStore.Core.csproj | 2 +- .../Mapping/Payments/PaymentMethodMap.cs | 4 + ...170941137_PaymentShippingRestrictions.resx | 126 ------------------ ...0_PaymentShippingRestrictions.Designer.cs} | 2 +- ...6181501470_PaymentShippingRestrictions.cs} | 37 ++++- ...181501470_PaymentShippingRestrictions.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../Payments/IPaymentService.cs | 8 +- .../Payments/PaymentService.cs | 103 ++++++++++---- .../Shipping/ShippingService.cs | 7 +- .../Controllers/PaymentController.cs | 13 +- .../Models/Payments/PaymentMethodEditModel.cs | 11 ++ .../Administration/Views/Payment/Edit.cshtml | 36 ++++- .../Controllers/CheckoutController.cs | 2 +- .../Controllers/ShoppingCartController.cs | 2 +- .../Payments/PaymentServiceTests.cs | 16 +-- 19 files changed, 359 insertions(+), 187 deletions(-) rename src/Libraries/SmartStore.Core/Domain/Payments/{CountryExclusionContextType.cs => RestrictionContextTypes.cs} (61%) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.resx rename src/Libraries/SmartStore.Data/Migrations/{201506170941137_PaymentShippingRestrictions.Designer.cs => 201506181501470_PaymentShippingRestrictions.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201506170941137_PaymentShippingRestrictions.cs => 201506181501470_PaymentShippingRestrictions.cs} (58%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.resx diff --git a/changelog.md b/changelog.md index 2810999e98..65879024c7 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,7 @@ * #141 Payment and shipping methods by customer roles * #67 Restrict payment methods to certain countries * #94 Restrict payment methods to certain shipping methods +* #526 Min\max amount option for which the payment method should be offered during checkout ## SmartStore.NET 2.2.2 diff --git a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs index 8be069bc96..28fa9f66a0 100644 --- a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs +++ b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs @@ -53,5 +53,39 @@ public CountryExclusionContextType CountryExclusionContext this.CountryExclusionContextId = (int)value; } } + + /// + /// Gets or sets the minimum order amount for which to offer the payment method + /// + [DataMember] + public decimal? MinimumOrderAmount { get; set; } + + /// + /// Gets or sets the maximum order amount for which to offer the payment method + /// + [DataMember] + public decimal? MaximumOrderAmount { get; set; } + + /// + /// Gets or sets the context identifier for amount restriction + /// + [DataMember] + public int AmountRestrictionContextId { get; set; } + + /// + /// Gets or sets the amount restriction context + /// + [DataMember] + public AmountRestrictionContextType AmountRestrictionContext + { + get + { + return (AmountRestrictionContextType)this.AmountRestrictionContextId; + } + set + { + this.AmountRestrictionContextId = (int)value; + } + } } } diff --git a/src/Libraries/SmartStore.Core/Domain/Payments/CountryExclusionContextType.cs b/src/Libraries/SmartStore.Core/Domain/Payments/RestrictionContextTypes.cs similarity index 61% rename from src/Libraries/SmartStore.Core/Domain/Payments/CountryExclusionContextType.cs rename to src/Libraries/SmartStore.Core/Domain/Payments/RestrictionContextTypes.cs index d629d01a36..be4756574b 100644 --- a/src/Libraries/SmartStore.Core/Domain/Payments/CountryExclusionContextType.cs +++ b/src/Libraries/SmartStore.Core/Domain/Payments/RestrictionContextTypes.cs @@ -6,4 +6,10 @@ public enum CountryExclusionContextType BillingAddress = 0, ShippingAddress } + + public enum AmountRestrictionContextType + { + SubtotalAmount = 0, + TotalAmount + } } diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index d389e35e66..4a9d7bc280 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -157,7 +157,7 @@ - + diff --git a/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs b/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs index 86073bffc7..d222942dad 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs @@ -16,7 +16,11 @@ public PaymentMethodMap() this.Property(x => x.ExcludedCountryIds).IsMaxLength(); this.Property(x => x.ExcludedShippingMethodIds).IsMaxLength(); + this.Property(x => x.MinimumOrderAmount).HasPrecision(18, 4); + this.Property(x => x.MaximumOrderAmount).HasPrecision(18, 4); + this.Ignore(x => x.CountryExclusionContext); + this.Ignore(x => x.AmountRestrictionContext); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.resx b/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.resx deleted file mode 100644 index f332ef3c76..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.Designer.cs index 2093e737e1..97d631de8c 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class PaymentShippingRestrictions : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201506170941137_PaymentShippingRestrictions"; } + get { return "201506181501470_PaymentShippingRestrictions"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.cs similarity index 58% rename from src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.cs rename to src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.cs index c9398dc915..e957c22ff7 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506170941137_PaymentShippingRestrictions.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.cs @@ -18,6 +18,9 @@ public override void Up() ExcludedCountryIds = c.String(), ExcludedShippingMethodIds = c.String(), CountryExclusionContextId = c.Int(nullable: false), + MinimumOrderAmount = c.Decimal(precision: 18, scale: 4), + MaximumOrderAmount = c.Decimal(precision: 18, scale: 4), + AmountRestrictionContextId = c.Int(nullable: false), }) .PrimaryKey(t => t.Id) .Index(t => t.PaymentMethodSystemName); @@ -47,13 +50,13 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Restrictions", "Einschrnkungen"); - builder.AddOrUpdate("Admin.Common.AppliedTo", - "applied to", + builder.AddOrUpdate("Admin.Common.RelatedTo", + "related to", "bezogen auf"); builder.AddOrUpdate("Admin.Configuration.Payment.Methods.RestrictionNote", "Select customer roles, shipping methods and countries for which you do not want to offer this payment method.", - "Whlen Sie Kundengruppen, Versandarten und Lnder, bei denen sie diese Zahlungsmethode nicht anbieten mchten."); + "Whlen Sie Kundengruppen, Versandarten und Lnder, bei denen Sie diese Zahlungsmethode nicht anbieten mchten."); builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Payments.CountryExclusionContextType.BillingAddress", "Billing address", @@ -65,7 +68,33 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Admin.Configuration.Shipping.Methods.RestrictionNote", "Select customer roles for which you do not want to offer this shipping method.", - "Whlen Sie Kundengruppen, bei denen sie diese Versandart nicht anbieten mchten."); + "Whlen Sie Kundengruppen, bei denen Sie diese Versandart nicht anbieten mchten."); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.MinimumOrderAmount", + "Minimum order amount", + "Mindestbestellwert", + "Specifies the minimum order amount from which on the payment method should be offered.", + "Legt den Mindestbestellwert fest, ab dem die Zahlungsmethode angeboten werden soll."); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.MaximumOrderAmount", + "Maximum amount", + "Maximalbestellwert", + "Specifies the maximum order amount up to which the payment methods should be offered.", + "Legt den maximalen Bestellwert fest, bis zu dem die Zahlungsmethode angeboten werden soll."); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.AmountRestrictionContext", + "Amount related to", + "Betrag bezieht sich auf", + "Specifies the amount to which the minimum and maximum order amounts are related to.", + "Legt den Betrag fest, auf den sich die Minimal- und Maximalbestellwerte beziehen."); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Payments.AmountRestrictionContextType.SubtotalAmount", + "Subtotal", + "Zwischensumme"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Payments.AmountRestrictionContextType.TotalAmount", + "Order total", + "Gesamtsumme"); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.resx b/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.resx new file mode 100644 index 0000000000..4ac037f18e --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index e82f356741..cd96c73f3a 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -273,9 +273,9 @@ 201505272236124_V222.cs - - - 201506170941137_PaymentShippingRestrictions.cs + + + 201506181501470_PaymentShippingRestrictions.cs @@ -534,8 +534,8 @@ 201505272236124_V222.cs - - 201506170941137_PaymentShippingRestrictions.cs + + 201506181501470_PaymentShippingRestrictions.cs diff --git a/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs b/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs index 709c6eafc2..6e45d3d0e2 100644 --- a/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/IPaymentService.cs @@ -15,11 +15,17 @@ public partial interface IPaymentService /// Load active payment methods /// /// Filter payment methods by customer and apply payment method restrictions; null to load all records + /// Filter payment methods by cart amount; null to load all records /// Filter payment methods by store identifier; pass 0 to load all records /// Filter payment methods by payment method types /// Provide a fallback payment method if none is active /// Payment methods - IEnumerable> LoadActivePaymentMethods(Customer customer = null, int storeId = 0, PaymentMethodType[] types = null, bool provideFallbackMethod = true); + IEnumerable> LoadActivePaymentMethods( + Customer customer = null, + IList cart = null, + int storeId = 0, + PaymentMethodType[] types = null, + bool provideFallbackMethod = true); /// /// Determines whether a payment method is active\enabled for a shop diff --git a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs index 7923546540..4e7137c764 100644 --- a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs @@ -1,17 +1,18 @@ using System; using System.Collections.Generic; using System.Linq; -using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Domain.Discounts; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; using SmartStore.Core.Domain.Shipping; using SmartStore.Core.Events; +using SmartStore.Core.Infrastructure; using SmartStore.Core.Plugins; using SmartStore.Services.Common; -using SmartStore.Services.Configuration; -using SmartStore.Services.Localization; +using SmartStore.Services.Directory; +using SmartStore.Services.Orders; namespace SmartStore.Services.Payments { @@ -32,11 +33,9 @@ public partial class PaymentService : IPaymentService private readonly PaymentSettings _paymentSettings; private readonly IPluginFinder _pluginFinder; private readonly ShoppingCartSettings _shoppingCartSettings; - private readonly ISettingService _settingService; - private readonly ILocalizationService _localizationService; private readonly IProviderManager _providerManager; - private readonly IEventPublisher _eventPublisher; - private readonly ICacheManager _cacheManager; + private readonly ICurrencyService _currencyService; + private readonly ICommonServices _commonServices; #endregion @@ -54,21 +53,17 @@ public PaymentService( PaymentSettings paymentSettings, IPluginFinder pluginFinder, ShoppingCartSettings shoppingCartSettings, - ISettingService settingService, - ILocalizationService localizationService, IProviderManager providerManager, - IEventPublisher eventPublisher, - ICacheManager cacheManager) + ICurrencyService currencyService, + ICommonServices commonServices) { this._paymentMethodRepository = paymentMethodRepository; this._paymentSettings = paymentSettings; this._pluginFinder = pluginFinder; this._shoppingCartSettings = shoppingCartSettings; - this._settingService = settingService; - this._localizationService = localizationService; this._providerManager = providerManager; - this._eventPublisher = eventPublisher; - this._cacheManager = cacheManager; + this._currencyService = currencyService; + this._commonServices = commonServices; } #endregion @@ -79,15 +74,22 @@ public PaymentService( /// Load active payment methods /// /// Filter payment methods by customer and apply payment method restrictions; null to load all records + /// Filter payment methods by cart amount; null to load all records /// Filter payment methods by store identifier; pass 0 to load all records /// Filter payment methods by payment method types /// Provide a fallback payment method if none is active /// Payment methods - public virtual IEnumerable> LoadActivePaymentMethods(Customer customer = null, int storeId = 0, PaymentMethodType[] types = null, + public virtual IEnumerable> LoadActivePaymentMethods( + Customer customer = null, + IList cart = null, + int storeId = 0, + PaymentMethodType[] types = null, bool provideFallbackMethod = true) { List customerRoleIds = null; int? selectedShippingMethodId = null; + decimal? orderSubTotal = null; + decimal? orderTotal = null; IEnumerable> allProviders = null; if (types != null && types.Any()) @@ -143,7 +145,50 @@ public virtual IEnumerable> LoadActivePaymentMethods(Cu if (countryId != 0 && excludedCountryIds.Contains(countryId)) return false; - } + } + + // method restricted by min\max order amount? + if ((method.MinimumOrderAmount.HasValue || method.MaximumOrderAmount.HasValue) && cart != null) + { + decimal compareAmount = decimal.Zero; + // TODO: resolve circular object dependencies + var orderTotalCalculationService = EngineContext.Current.Resolve(); + + if (method.AmountRestrictionContext == AmountRestrictionContextType.SubtotalAmount) + { + if (!orderSubTotal.HasValue) + { + decimal orderSubTotalDiscountAmountBase = decimal.Zero; + Discount orderSubTotalAppliedDiscount = null; + decimal subTotalWithoutDiscountBase = decimal.Zero; + decimal subTotalWithDiscountBase = decimal.Zero; + + orderTotalCalculationService.GetShoppingCartSubTotal(cart, out orderSubTotalDiscountAmountBase, out orderSubTotalAppliedDiscount, + out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); + + orderSubTotal = _currencyService.ConvertFromPrimaryStoreCurrency(subTotalWithoutDiscountBase, _commonServices.WorkContext.WorkingCurrency); + } + + compareAmount = orderSubTotal.Value; + } + else if (method.AmountRestrictionContext == AmountRestrictionContextType.TotalAmount) + { + if (!orderTotal.HasValue) + { + orderTotal = orderTotalCalculationService.GetShoppingCartTotal(cart) ?? decimal.Zero; + + orderTotal = _currencyService.ConvertFromPrimaryStoreCurrency(orderTotal.Value, _commonServices.WorkContext.WorkingCurrency); + } + + compareAmount = orderTotal.Value; + } + + if (method.MinimumOrderAmount.HasValue && compareAmount < method.MinimumOrderAmount.Value) + return false; + + if (method.MaximumOrderAmount.HasValue && compareAmount > method.MaximumOrderAmount.Value) + return false; + } } } return true; @@ -211,7 +256,7 @@ public virtual IEnumerable> LoadAllPaymentMethods(int s /// List of payment method objects public virtual IList GetAllPaymentMethods() { - var paymentMethods = _cacheManager.Get(PAYMENTMETHOD_ALL_KEY, () => + var paymentMethods = _commonServices.Cache.Get(PAYMENTMETHOD_ALL_KEY, () => { return _paymentMethodRepository.Table.ToList(); }); @@ -246,9 +291,9 @@ public virtual void InsertPaymentMethod(PaymentMethod paymentMethod) _paymentMethodRepository.Insert(paymentMethod); - _cacheManager.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); + _commonServices.Cache.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); - _eventPublisher.EntityInserted(paymentMethod); + _commonServices.EventPublisher.EntityInserted(paymentMethod); } /// @@ -262,9 +307,9 @@ public virtual void UpdatePaymentMethod(PaymentMethod paymentMethod) _paymentMethodRepository.Update(paymentMethod); - _cacheManager.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); + _commonServices.Cache.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); - _eventPublisher.EntityUpdated(paymentMethod); + _commonServices.EventPublisher.EntityUpdated(paymentMethod); } /// @@ -278,9 +323,9 @@ public virtual void DeletePaymentMethod(PaymentMethod paymentMethod) _paymentMethodRepository.Delete(paymentMethod); - _cacheManager.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); + _commonServices.Cache.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); - _eventPublisher.EntityDeleted(paymentMethod); + _commonServices.EventPublisher.EntityDeleted(paymentMethod); } @@ -436,7 +481,7 @@ public virtual CapturePaymentResult Capture(CapturePaymentRequest capturePayment catch (NotSupportedException) { var result = new CapturePaymentResult(); - result.AddError(_localizationService.GetResource("Common.Payment.NoCaptureSupport")); + result.AddError(_commonServices.Localization.GetResource("Common.Payment.NoCaptureSupport")); return result; } catch @@ -491,7 +536,7 @@ public virtual RefundPaymentResult Refund(RefundPaymentRequest refundPaymentRequ catch (NotSupportedException) { var result = new RefundPaymentResult(); - result.AddError(_localizationService.GetResource("Common.Payment.NoRefundSupport")); + result.AddError(_commonServices.Localization.GetResource("Common.Payment.NoRefundSupport")); return result; } catch @@ -533,7 +578,7 @@ public virtual VoidPaymentResult Void(VoidPaymentRequest voidPaymentRequest) catch (NotSupportedException) { var result = new VoidPaymentResult(); - result.AddError(_localizationService.GetResource("Common.Payment.NoVoidSupport")); + result.AddError(_commonServices.Localization.GetResource("Common.Payment.NoVoidSupport")); return result; } catch @@ -585,7 +630,7 @@ public virtual ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentReques catch (NotSupportedException) { var result = new ProcessPaymentResult(); - result.AddError(_localizationService.GetResource("Common.Payment.NoRecurringPaymentSupport")); + result.AddError(_commonServices.Localization.GetResource("Common.Payment.NoRecurringPaymentSupport")); return result; } catch @@ -616,7 +661,7 @@ public virtual CancelRecurringPaymentResult CancelRecurringPayment(CancelRecurri catch (NotSupportedException) { var result = new CancelRecurringPaymentResult(); - result.AddError(_localizationService.GetResource("Common.Payment.NoRecurringPaymentSupport")); + result.AddError(_commonServices.Localization.GetResource("Common.Payment.NoRecurringPaymentSupport")); return result; } catch diff --git a/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs b/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs index d29ce01907..74d78b69e9 100644 --- a/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs +++ b/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs @@ -116,10 +116,9 @@ public virtual IEnumerable> LoadActiveS if (fallbackMethod != null) { - // a frontend request should not revoke merchant settings - //_shippingSettings.ActiveShippingRateComputationMethodSystemNames.Clear(); - //_shippingSettings.ActiveShippingRateComputationMethodSystemNames.Add(fallbackMethod.Metadata.SystemName); - //_settingService.SaveSetting(_shippingSettings); + _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Clear(); + _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Add(fallbackMethod.Metadata.SystemName); + _settingService.SaveSetting(_shippingSettings); return new Provider[] { fallbackMethod }; } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs index df69321ffa..7b81ffd118 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs @@ -1,5 +1,5 @@ -using System.Linq; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Payments; using SmartStore.Core.Domain.Payments; @@ -11,9 +11,9 @@ using SmartStore.Services.Payments; using SmartStore.Services.Security; using SmartStore.Services.Shipping; +using SmartStore.Web.Framework; using SmartStore.Web.Framework.Controllers; using SmartStore.Web.Framework.Plugins; -using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Controllers { @@ -72,6 +72,7 @@ private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, Payment model.AvailableCustomerRoles = new List(); model.AvailableShippingMethods = new List(); model.AvailableCountries = new List(); + model.AvailableAmountRestrictionContextTypes = AmountRestrictionContextType.SubtotalAmount.ToSelectList(false).ToList(); foreach (var role in customerRoles.OrderBy(x => x.Name)) { @@ -91,6 +92,9 @@ private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, Payment if (paymentMethod != null) { model.CountryExclusionContext = paymentMethod.CountryExclusionContext; + model.AmountRestrictionContext = paymentMethod.AmountRestrictionContext; + model.MinimumOrderAmount = paymentMethod.MinimumOrderAmount; + model.MaximumOrderAmount = paymentMethod.MaximumOrderAmount; foreach (var id in paymentMethod.ExcludedCustomerRoleIds.SplitSafe(",")) { @@ -229,6 +233,9 @@ public ActionResult Edit(string systemName, bool continueEditing, PaymentMethodE paymentMethod.ExcludedCountryIds = string.Join(",", countryIds); paymentMethod.CountryExclusionContext = model.CountryExclusionContext; + paymentMethod.AmountRestrictionContext = model.AmountRestrictionContext; + paymentMethod.MinimumOrderAmount = model.MinimumOrderAmount; + paymentMethod.MaximumOrderAmount = model.MaximumOrderAmount; if (paymentMethod.Id == 0) _paymentService.InsertPaymentMethod(paymentMethod); diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs index 180d7c756b..9857d0f0e3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Web.Mvc; using SmartStore.Core.Domain.Payments; +using SmartStore.Web.Framework; using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Models.Payments @@ -10,7 +11,17 @@ public class PaymentMethodEditModel : ProviderModel public List AvailableCustomerRoles { get; set; } public List AvailableShippingMethods { get; set; } public List AvailableCountries { get; set; } + public List AvailableAmountRestrictionContextTypes { get; set; } public CountryExclusionContextType CountryExclusionContext { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.AmountRestrictionContext")] + public AmountRestrictionContextType AmountRestrictionContext { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.MinimumOrderAmount")] + public decimal? MinimumOrderAmount { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.MaximumOrderAmount")] + public decimal? MaximumOrderAmount { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml index 51d94abb2e..ef2d508ae3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml @@ -87,6 +87,40 @@ @helper TabRestrictions() { +
+ + + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.MinimumOrderAmount) + + @Html.EditorFor(model => model.MinimumOrderAmount) + @Html.ValidationMessageFor(model => model.MinimumOrderAmount) +
+ @Html.SmartLabelFor(model => model.MaximumOrderAmount) + + @Html.EditorFor(model => model.MaximumOrderAmount) + @Html.ValidationMessageFor(model => model.MaximumOrderAmount) +
+ @Html.SmartLabelFor(model => model.AmountRestrictionContext) + + @Html.DropDownListFor(model => model.AmountRestrictionContext, Model.AvailableAmountRestrictionContextTypes) + @Html.ValidationMessageFor(model => model.AmountRestrictionContext) +
+
+ +

 

+
@Html.Raw(T("Admin.Configuration.Payment.Methods.RestrictionNote"))
@@ -118,7 +152,7 @@
- @T("Admin.Common.AppliedTo") + @T("Admin.Common.RelatedTo")
/// SmartStore.Email.Message /// System.Net.Mail.Message - protected virtual net.MailMessage BuildMailMessage(EmailMessage original) + protected virtual MailMessage BuildMailMessage(EmailMessage original) { - net.MailMessage msg = new net.MailMessage(); + MailMessage msg = new MailMessage(); if (String.IsNullOrEmpty(original.Subject)) { @@ -37,15 +37,15 @@ protected virtual net.MailMessage BuildMailMessage(EmailMessage original) if (original.AltText.HasValue()) { - msg.AlternateViews.Add(net.AlternateView.CreateAlternateViewFromString(original.AltText, new ContentType("text/html"))); - msg.AlternateViews.Add(net.AlternateView.CreateAlternateViewFromString(original.Body, new ContentType("text/plain"))); + msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(original.AltText, new ContentType("text/html"))); + msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(original.Body, new ContentType("text/plain"))); } else { msg.Body = original.Body; } - msg.DeliveryNotificationOptions = net.DeliveryNotificationOptions.None; + msg.DeliveryNotificationOptions = DeliveryNotificationOptions.None; msg.From = original.From.ToMailAddress(); @@ -54,30 +54,9 @@ protected virtual net.MailMessage BuildMailMessage(EmailMessage original) msg.Bcc.AddRange(original.Bcc.Where(x => x.Address.HasValue()).Select(x => x.ToMailAddress())); msg.ReplyToList.AddRange(original.ReplyTo.Where(x => x.Address.HasValue()).Select(x => x.ToMailAddress())); - foreach (Attachment attachment in original.Attachments) + foreach (var attachment in original.Attachments) { - byte[] byteData; - - if (attachment.ContentTransferEncoding == TransferEncoding.Base64) - { - using (var sr = new StreamReader(attachment.Stream)) - { - byteData = Convert.FromBase64String(sr.ReadToEnd()); - } - } - else - { - byteData = attachment.Stream.ToByteArray(); - } - - MemoryStream s = new MemoryStream(byteData); - net.Attachment att = new net.Attachment(s, attachment.Name, attachment.ContentType.MediaType); - - att.ContentType.MediaType = attachment.MediaType; - att.TransferEncoding = attachment.ContentTransferEncoding; - att.ContentDisposition.DispositionType = attachment.ContentDisposition.DispositionType; - - msg.Attachments.Add(att); + msg.Attachments.Add(attachment); } if (original.Headers != null) diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 4a9d7bc280..55a91b1f35 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -224,7 +224,6 @@ - diff --git a/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs index 08c82ec8cd..e01c330ba0 100644 --- a/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs @@ -53,9 +53,10 @@ public partial interface IQueuedEmailService /// Page size /// A value indicating whether to load manually send emails /// Email item collection - IPagedList SearchEmails(string fromEmail, - string toEmail, DateTime? startTime, DateTime? endTime, - bool loadNotSentItemsOnly, int maxSendTries, + IPagedList SearchEmails( + string fromEmail, string toEmail, + DateTime? startTime, DateTime? endTime, + bool loadUnsentItemsOnly, int maxSendTries, bool loadNewest, int pageIndex, int pageSize, bool? sendManually = null); diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs index fb53c2aa04..4dc57c2c83 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs @@ -133,7 +133,7 @@ where queuedEmailIds.Contains(qe.Id) /// To Email /// The start time /// The end time - /// A value indicating whether to load only not sent emails + /// A value indicating whether to load only not sent emails /// Maximum send tries /// A value indicating whether we should sort queued email descending; otherwise, ascending. /// Page index @@ -142,7 +142,7 @@ where queuedEmailIds.Contains(qe.Id) /// Email item list public virtual IPagedList SearchEmails(string fromEmail, string toEmail, DateTime? startTime, DateTime? endTime, - bool loadNotSentItemsOnly, int maxSendTries, + bool loadUnsentItemsOnly, int maxSendTries, bool loadNewest, int pageIndex, int pageSize, bool? sendManually = null) { @@ -163,7 +163,7 @@ public virtual IPagedList SearchEmails(string fromEmail, if (endTime.HasValue) query = query.Where(qe => qe.CreatedOnUtc <= endTime); - if (loadNotSentItemsOnly) + if (loadUnsentItemsOnly) query = query.Where(qe => !qe.SentOnUtc.HasValue); if (sendManually.HasValue) diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs index cd3110c81d..3223633b5f 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs @@ -9,8 +9,7 @@ public partial class QueuedMessagesSendTask : ITask { private readonly IQueuedEmailService _queuedEmailService; - public QueuedMessagesSendTask( - IQueuedEmailService queuedEmailService) + public QueuedMessagesSendTask(IQueuedEmailService queuedEmailService) { _queuedEmailService = queuedEmailService; } From eb36a083f6d75542ccc72b44739812741c1213af Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 22 Jun 2015 10:44:34 +0200 Subject: [PATCH 0162/1256] Review payment and shipping method restrictions --- .../RestrictionContextTypes.cs | 4 +- .../Domain/Payments/PaymentMethod.cs | 5 +- .../Domain/Shipping/ShippingMethod.cs | 23 +++ .../SmartStore.Core/SmartStore.Core.csproj | 2 +- .../Mapping/Payments/PaymentMethodMap.cs | 6 +- .../Mapping/Shipping/ShippingMethodMap.cs | 4 +- ...06181501470_PaymentShippingRestrictions.cs | 100 ----------- ...181501470_PaymentShippingRestrictions.resx | 126 -------------- ...3_PaymentShippingRestrictions.Designer.cs} | 2 +- ...06211043073_PaymentShippingRestrictions.cs | 143 ++++++++++++++++ ...211043073_PaymentShippingRestrictions.resx | 126 ++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../Payments/PaymentService.cs | 11 +- .../Shipping/IShippingService.cs | 5 +- .../Shipping/ShippingService.cs | 75 ++++----- .../Providers/ByTotalProvider.cs | 2 +- .../Providers/FixedRateProvider.cs | 10 +- .../ByWeightShippingComputationMethod.cs | 2 +- .../Administration/Content/admin.less | 46 +---- .../Controllers/PaymentController.cs | 53 ++---- .../Controllers/ShippingController.cs | 150 +++++------------ .../Infrastructure/AutoMapperStartupTask.cs | 4 +- .../Models/Payments/PaymentMethodEditModel.cs | 22 ++- .../Models/Shipping/ShippingMethodModel.cs | 11 ++ .../ShippingMethodRestrictionModel.cs | 21 --- .../Administration/SmartStore.Admin.csproj | 4 - .../Administration/Views/Payment/Edit.cshtml | 150 +++++------------ .../Views/Shipping/Restrictions.cshtml | 91 ---------- .../Shipping/_CreateOrUpdateMethod.cshtml | 159 ++++++++---------- .../Administration/sitemap.config | 1 - 30 files changed, 574 insertions(+), 794 deletions(-) rename src/Libraries/SmartStore.Core/Domain/{Payments => Common}/RestrictionContextTypes.cs (62%) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.cs delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.resx rename src/Libraries/SmartStore.Data/Migrations/{201506181501470_PaymentShippingRestrictions.Designer.cs => 201506211043073_PaymentShippingRestrictions.Designer.cs} (92%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.resx delete mode 100644 src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodRestrictionModel.cs delete mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml diff --git a/src/Libraries/SmartStore.Core/Domain/Payments/RestrictionContextTypes.cs b/src/Libraries/SmartStore.Core/Domain/Common/RestrictionContextTypes.cs similarity index 62% rename from src/Libraries/SmartStore.Core/Domain/Payments/RestrictionContextTypes.cs rename to src/Libraries/SmartStore.Core/Domain/Common/RestrictionContextTypes.cs index be4756574b..98a1590c7e 100644 --- a/src/Libraries/SmartStore.Core/Domain/Payments/RestrictionContextTypes.cs +++ b/src/Libraries/SmartStore.Core/Domain/Common/RestrictionContextTypes.cs @@ -1,7 +1,7 @@  -namespace SmartStore.Core.Domain.Payments +namespace SmartStore.Core.Domain.Common { - public enum CountryExclusionContextType + public enum CountryRestrictionContextType { BillingAddress = 0, ShippingAddress diff --git a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs index 28fa9f66a0..0567ad5dfe 100644 --- a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs +++ b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs @@ -1,4 +1,5 @@ using System.Runtime.Serialization; +using SmartStore.Core.Domain.Common; namespace SmartStore.Core.Domain.Payments { @@ -42,11 +43,11 @@ public partial class PaymentMethod : BaseEntity /// Gets or sets the country exclusion context ///
[DataMember] - public CountryExclusionContextType CountryExclusionContext + public CountryRestrictionContextType CountryExclusionContext { get { - return (CountryExclusionContextType)this.CountryExclusionContextId; + return (CountryRestrictionContextType)this.CountryExclusionContextId; } set { diff --git a/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingMethod.cs b/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingMethod.cs index 9651718a85..86d5390e85 100644 --- a/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingMethod.cs +++ b/src/Libraries/SmartStore.Core/Domain/Shipping/ShippingMethod.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Runtime.Serialization; +using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Localization; @@ -40,6 +41,28 @@ public partial class ShippingMethod : BaseEntity, ILocalizedEntity [DataMember] public string ExcludedCustomerRoleIds { get; set; } + /// + /// Gets or sets the context identifier for country exclusion + /// + [DataMember] + public int CountryExclusionContextId { get; set; } + + /// + /// Gets or sets the country exclusion context + /// + [DataMember] + public CountryRestrictionContextType CountryExclusionContext + { + get + { + return (CountryRestrictionContextType)this.CountryExclusionContextId; + } + set + { + this.CountryExclusionContextId = (int)value; + } + } + /// /// Gets or sets the restricted countries /// diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 4a9d7bc280..9502cdf6c9 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -157,7 +157,7 @@ - + diff --git a/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs b/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs index d222942dad..c009204c13 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs @@ -12,9 +12,9 @@ public PaymentMethodMap() this.Property(x => x.PaymentMethodSystemName).IsRequired().HasMaxLength(4000); - this.Property(x => x.ExcludedCustomerRoleIds).IsMaxLength(); - this.Property(x => x.ExcludedCountryIds).IsMaxLength(); - this.Property(x => x.ExcludedShippingMethodIds).IsMaxLength(); + this.Property(x => x.ExcludedCustomerRoleIds).HasMaxLength(500); + this.Property(x => x.ExcludedCountryIds).HasMaxLength(2000); + this.Property(x => x.ExcludedShippingMethodIds).HasMaxLength(500); this.Property(x => x.MinimumOrderAmount).HasPrecision(18, 4); this.Property(x => x.MaximumOrderAmount).HasPrecision(18, 4); diff --git a/src/Libraries/SmartStore.Data/Mapping/Shipping/ShippingMethodMap.cs b/src/Libraries/SmartStore.Data/Mapping/Shipping/ShippingMethodMap.cs index 947070d588..e1c566088a 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Shipping/ShippingMethodMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Shipping/ShippingMethodMap.cs @@ -11,11 +11,13 @@ public ShippingMethodMap() this.HasKey(sm => sm.Id); this.Property(sm => sm.Name).IsRequired().HasMaxLength(400); - this.Property(sm => sm.ExcludedCustomerRoleIds).IsMaxLength(); + this.Property(sm => sm.ExcludedCustomerRoleIds).HasMaxLength(500); this.HasMany(sm => sm.RestrictedCountries) .WithMany(c => c.RestrictedShippingMethods) .Map(m => m.ToTable("ShippingMethodRestrictions")); + + this.Ignore(sm => sm.CountryExclusionContext); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.cs deleted file mode 100644 index e957c22ff7..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.cs +++ /dev/null @@ -1,100 +0,0 @@ -namespace SmartStore.Data.Migrations -{ - using System; - using System.Data.Entity.Migrations; - using SmartStore.Data.Setup; - - public partial class PaymentShippingRestrictions : DbMigration, ILocaleResourcesProvider, IDataSeeder - { - public override void Up() - { - CreateTable( - "dbo.PaymentMethod", - c => new - { - Id = c.Int(nullable: false, identity: true), - PaymentMethodSystemName = c.String(nullable: false, maxLength: 4000), - ExcludedCustomerRoleIds = c.String(), - ExcludedCountryIds = c.String(), - ExcludedShippingMethodIds = c.String(), - CountryExclusionContextId = c.Int(nullable: false), - MinimumOrderAmount = c.Decimal(precision: 18, scale: 4), - MaximumOrderAmount = c.Decimal(precision: 18, scale: 4), - AmountRestrictionContextId = c.Int(nullable: false), - }) - .PrimaryKey(t => t.Id) - .Index(t => t.PaymentMethodSystemName); - - AddColumn("dbo.ShippingMethod", "ExcludedCustomerRoleIds", c => c.String()); - } - - public override void Down() - { - DropColumn("dbo.ShippingMethod", "ExcludedCustomerRoleIds"); - DropTable("dbo.PaymentMethod"); - } - - public bool RollbackOnFailure - { - get { return false; } - } - - public void Seed(SmartObjectContext context) - { - context.MigrateLocaleResources(MigrateLocaleResources); - } - - public void MigrateLocaleResources(LocaleResourcesBuilder builder) - { - builder.AddOrUpdate("Admin.Common.Restrictions", - "Restrictions", - "Einschrnkungen"); - - builder.AddOrUpdate("Admin.Common.RelatedTo", - "related to", - "bezogen auf"); - - builder.AddOrUpdate("Admin.Configuration.Payment.Methods.RestrictionNote", - "Select customer roles, shipping methods and countries for which you do not want to offer this payment method.", - "Whlen Sie Kundengruppen, Versandarten und Lnder, bei denen Sie diese Zahlungsmethode nicht anbieten mchten."); - - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Payments.CountryExclusionContextType.BillingAddress", - "Billing address", - "Rechnungsadresse"); - - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Payments.CountryExclusionContextType.ShippingAddress", - "Shipping address", - "Versandadresse"); - - builder.AddOrUpdate("Admin.Configuration.Shipping.Methods.RestrictionNote", - "Select customer roles for which you do not want to offer this shipping method.", - "Whlen Sie Kundengruppen, bei denen Sie diese Versandart nicht anbieten mchten."); - - builder.AddOrUpdate("Admin.Configuration.Payment.Methods.MinimumOrderAmount", - "Minimum order amount", - "Mindestbestellwert", - "Specifies the minimum order amount from which on the payment method should be offered.", - "Legt den Mindestbestellwert fest, ab dem die Zahlungsmethode angeboten werden soll."); - - builder.AddOrUpdate("Admin.Configuration.Payment.Methods.MaximumOrderAmount", - "Maximum amount", - "Maximalbestellwert", - "Specifies the maximum order amount up to which the payment methods should be offered.", - "Legt den maximalen Bestellwert fest, bis zu dem die Zahlungsmethode angeboten werden soll."); - - builder.AddOrUpdate("Admin.Configuration.Payment.Methods.AmountRestrictionContext", - "Amount related to", - "Betrag bezieht sich auf", - "Specifies the amount to which the minimum and maximum order amounts are related to.", - "Legt den Betrag fest, auf den sich die Minimal- und Maximalbestellwerte beziehen."); - - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Payments.AmountRestrictionContextType.SubtotalAmount", - "Subtotal", - "Zwischensumme"); - - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Payments.AmountRestrictionContextType.TotalAmount", - "Order total", - "Gesamtsumme"); - } - } -} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.resx b/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.resx deleted file mode 100644 index 4ac037f18e..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.Designer.cs index 97d631de8c..e5e31c1659 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506181501470_PaymentShippingRestrictions.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class PaymentShippingRestrictions : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201506181501470_PaymentShippingRestrictions"; } + get { return "201506211043073_PaymentShippingRestrictions"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs new file mode 100644 index 0000000000..bd0333f18d --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs @@ -0,0 +1,143 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + using SmartStore.Data.Setup; + + public partial class PaymentShippingRestrictions : DbMigration, ILocaleResourcesProvider, IDataSeeder + { + public override void Up() + { + CreateTable( + "dbo.PaymentMethod", + c => new + { + Id = c.Int(nullable: false, identity: true), + PaymentMethodSystemName = c.String(nullable: false, maxLength: 4000), + ExcludedCustomerRoleIds = c.String(maxLength: 500), + ExcludedCountryIds = c.String(maxLength: 2000), + ExcludedShippingMethodIds = c.String(maxLength: 500), + CountryExclusionContextId = c.Int(nullable: false), + MinimumOrderAmount = c.Decimal(precision: 18, scale: 4), + MaximumOrderAmount = c.Decimal(precision: 18, scale: 4), + AmountRestrictionContextId = c.Int(nullable: false), + }) + .PrimaryKey(t => t.Id) + .Index(t => t.PaymentMethodSystemName); + + AddColumn("dbo.ShippingMethod", "ExcludedCustomerRoleIds", c => c.String(maxLength: 500)); + AddColumn("dbo.ShippingMethod", "CountryExclusionContextId", c => c.Int(nullable: false)); + } + + public override void Down() + { + DropColumn("dbo.ShippingMethod", "CountryExclusionContextId"); + DropColumn("dbo.ShippingMethod", "ExcludedCustomerRoleIds"); + DropTable("dbo.PaymentMethod"); + } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Admin.Common.Restrictions", + "Restrictions", + "Einschrnkungen"); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.RestrictionNote", + "Select customer roles, shipping methods, countries and order amounts for which you do not want to offer this payment method.", + "Whlen Sie Kundengruppen, Versandarten, Lnder und Bestellwerte, bei denen Sie diese Zahlungsmethode nicht anbieten mchten."); + + builder.AddOrUpdate("Admin.Configuration.Shipping.Methods.RestrictionNote", + "Select customer roles and countries for which you do not want to offer this shipping method.", + "Whlen Sie Kundengruppen und Lnder, bei denen Sie diese Versandart nicht anbieten mchten."); + + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.ExcludedCustomerRole", + "Customer roles", + "Kundengruppen", + "Specifies customer roles for which the payment method should not be offered.", + "Legt Kundengruppen fest, fr die die Zahlungsmethode nicht angeboten werden soll."); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.ExcludedShippingMethod", + "Shipping method", + "Versandarten", + "Specifies shipping methods for which the payment method should not be offered.", + "Legt Versandarten fest, fr die die Zahlungsmethode nicht angeboten werden soll."); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.ExcludedCountry", + "Countries", + "Lnder", + "Specifies countries for which the payment method should not be offered.", + "Legt Lnder fest, fr die die Zahlungsmethode nicht angeboten werden soll."); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.MinimumOrderAmount", + "Minimum order amount", + "Mindestbestellwert", + "Specifies the minimum order amount from which on the payment method should be offered.", + "Legt den Mindestbestellwert fest, ab dem die Zahlungsmethode angeboten werden soll."); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.MaximumOrderAmount", + "Maximum amount", + "Maximalbestellwert", + "Specifies the maximum order amount up to which the payment methods should be offered.", + "Legt den maximalen Bestellwert fest, bis zu dem die Zahlungsmethode angeboten werden soll."); + + + builder.AddOrUpdate("Admin.Configuration.Shipping.Methods.ExcludedCustomerRole", + "Customer roles", + "Kundengruppen", + "Specifies customer roles for which the shipping method should not be offered.", + "Legt Kundengruppen fest, fr die die Versandart nicht angeboten werden soll."); + + builder.AddOrUpdate("Admin.Configuration.Shipping.Methods.ExcludedCountry", + "Countries", + "Lnder", + "Specifies countries for which the shipping method should not be offered.", + "Legt Lnder fest, fr die die Versandart nicht angeboten werden soll."); + + + builder.AddOrUpdate("Admin.Configuration.Restrictions.AmountRestrictionContext", + "Amount related to", + "Betrag bezieht sich auf", + "Specifies the amount to which the minimum and maximum order amounts are related to.", + "Legt den Betrag fest, auf den sich die Mindest- und Maximalbestellwerte beziehen."); + + builder.AddOrUpdate("Admin.Configuration.Restrictions.CountryExclusionContext", + "Countries related to", + "Lnder beziehen sich auf", + "Specifies the address to which the selected countries are related to.", + "Legt die Adresse fest, auf den sich die gewhlten Lnder beziehen."); + + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Common.CountryRestrictionContextType.BillingAddress", + "Billing address", + "Rechnungsadresse"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Common.CountryRestrictionContextType.ShippingAddress", + "Shipping address", + "Versandadresse"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Common.AmountRestrictionContextType.SubtotalAmount", + "Subtotal", + "Zwischensumme"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Common.AmountRestrictionContextType.TotalAmount", + "Order total", + "Gesamtsumme"); + + builder.Delete("Admin.Configuration.Shipping.Restrictions.Updated"); + builder.Delete("Admin.Configuration.Shipping.Restrictions.Description"); + builder.Delete("Admin.Configuration.Shipping.Restrictions.Country"); + builder.Delete("Admin.Configuration.Shipping.Restrictions"); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.resx b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.resx new file mode 100644 index 0000000000..43c6122456 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index cd96c73f3a..25b190e056 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -273,9 +273,9 @@ 201505272236124_V222.cs - - - 201506181501470_PaymentShippingRestrictions.cs + + + 201506211043073_PaymentShippingRestrictions.cs @@ -534,8 +534,8 @@ 201505272236124_V222.cs - - 201506181501470_PaymentShippingRestrictions.cs + + 201506211043073_PaymentShippingRestrictions.cs diff --git a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs index 3b6a3f66b8..24e39c2d32 100644 --- a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using SmartStore.Core.Data; +using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Discounts; using SmartStore.Core.Domain.Orders; @@ -139,12 +140,12 @@ public virtual IEnumerable> LoadActivePaymentMethods( return false; } - // method restricted by country of selected billing address? + // method restricted by country of selected billing or shipping address? var excludedCountryIds = method.ExcludedCountryIds.ToIntArray(); if (excludedCountryIds.Any()) { int countryId = 0; - if (method.CountryExclusionContext == CountryExclusionContextType.ShippingAddress) + if (method.CountryExclusionContext == CountryRestrictionContextType.ShippingAddress) countryId = (customer.ShippingAddress != null ? (customer.ShippingAddress.CountryId ?? 0) : 0); else countryId = (customer.BillingAddress != null ? (customer.BillingAddress.CountryId ?? 0) : 0); @@ -262,7 +263,11 @@ public virtual IList GetAllPaymentMethods() { var paymentMethods = _commonServices.Cache.Get(PAYMENTMETHOD_ALL_KEY, () => { - return _paymentMethodRepository.Table.ToList(); + var methods = _paymentMethodRepository.TableUntracked.ToList(); + + methods.Each(x => _paymentMethodRepository.Context.DetachEntity(x)); + + return methods; }); return paymentMethods; diff --git a/src/Libraries/SmartStore.Services/Shipping/IShippingService.cs b/src/Libraries/SmartStore.Services/Shipping/IShippingService.cs index 501c236c22..8ec9c19c40 100644 --- a/src/Libraries/SmartStore.Services/Shipping/IShippingService.cs +++ b/src/Libraries/SmartStore.Services/Shipping/IShippingService.cs @@ -53,10 +53,9 @@ public partial interface IShippingService /// /// Gets all shipping methods /// - /// The country indentifier to filter by - /// Filter methods by roles of a customer + /// Filter shipping methods by customer and apply payment method restrictions; null to load all records /// Shipping method collection - IList GetAllShippingMethods(int? filterByCountryId = null, Customer customer = null); + IList GetAllShippingMethods(Customer customer = null); /// /// Inserts a shipping method diff --git a/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs b/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs index 74d78b69e9..553156b912 100644 --- a/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs +++ b/src/Libraries/SmartStore.Services/Shipping/ShippingService.cs @@ -188,58 +188,49 @@ public virtual ShippingMethod GetShippingMethodById(int shippingMethodId) /// /// Gets all shipping methods /// - /// The country indentifier to filter by - /// Filter methods by roles of a customer + /// Filter shipping methods by customer and apply payment method restrictions; null to load all records /// Shipping method collection - public virtual IList GetAllShippingMethods(int? filterByCountryId = null, Customer customer = null) + public virtual IList GetAllShippingMethods(Customer customer = null) { - IQueryable query = null; + List customerRoleIds = null; - if (filterByCountryId.HasValue && filterByCountryId.Value > 0) - { - var query1 = - from sm in _shippingMethodRepository.Table - where sm.RestrictedCountries.Select(c => c.Id).Contains(filterByCountryId.Value) - select sm.Id; - - query = - from sm in _shippingMethodRepository.Table - where !query1.Contains(sm.Id) - orderby sm.DisplayOrder - select sm; - } - else - { - query = - from sm in _shippingMethodRepository.Table - orderby sm.DisplayOrder - select sm; - } + var query = + from sm in _shippingMethodRepository.Table + orderby sm.DisplayOrder + select sm; - var shippingMethods = query.ToList(); + var allMethods = query.ToList(); - if (customer != null) - { - List customerRoleIds = null; + if (customer == null) + return allMethods; - for (int i = shippingMethods.Count - 1; i >= 0; --i) + var activeShippingMethods = allMethods.Where(x => + { + // method restricted by customer role id? + var excludedRoleIds = x.ExcludedCustomerRoleIds.ToIntArray(); + if (excludedRoleIds.Any()) { - var method = shippingMethods[i]; - - // method restricted by customer role id? - var excludedRoleIds = method.ExcludedCustomerRoleIds.ToIntArray(); - if (excludedRoleIds.Any()) - { - if (customerRoleIds == null) - customerRoleIds = customer.CustomerRoles.Where(r => r.Active).Select(r => r.Id).ToList(); + if (customerRoleIds == null) + customerRoleIds = customer.CustomerRoles.Where(r => r.Active).Select(r => r.Id).ToList(); - if (customerRoleIds != null && !customerRoleIds.Except(excludedRoleIds).Any()) - shippingMethods.Remove(method); - } + if (customerRoleIds != null && !customerRoleIds.Except(excludedRoleIds).Any()) + return false; } - } - return shippingMethods; + // method restricted by country of selected billing or shipping address? + int countryId = 0; + if (x.CountryExclusionContext == CountryRestrictionContextType.ShippingAddress) + countryId = (customer.ShippingAddress != null ? (customer.ShippingAddress.CountryId ?? 0) : 0); + else + countryId = (customer.BillingAddress != null ? (customer.BillingAddress.CountryId ?? 0) : 0); + + if (countryId != 0 && x.CountryRestrictionExists(countryId)) + return false; + + return true; + }); + + return activeShippingMethods.ToList(); } /// diff --git a/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs b/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs index 44926d497c..9ca91fdca8 100644 --- a/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs +++ b/src/Plugins/SmartStore.Shipping/Providers/ByTotalProvider.cs @@ -187,7 +187,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get decimal sqThreshold = _shippingByTotalSettings.SmallQuantityThreshold; decimal sqSurcharge = _shippingByTotalSettings.SmallQuantitySurcharge; - var shippingMethods = _shippingService.GetAllShippingMethods(countryId, getShippingOptionRequest.Customer); + var shippingMethods = _shippingService.GetAllShippingMethods(getShippingOptionRequest.Customer); foreach (var shippingMethod in shippingMethods) { decimal? rate = GetRate(subTotal, shippingMethod.Id, storeId, countryId, stateProvinceId, zip); diff --git a/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs b/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs index 673f3b5c85..3f51635f18 100644 --- a/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs +++ b/src/Plugins/SmartStore.Shipping/Providers/FixedRateProvider.cs @@ -55,10 +55,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get return response; } - int? restrictByCountryId = (getShippingOptionRequest.ShippingAddress != null && getShippingOptionRequest.ShippingAddress.Country != null) - ? (int?)getShippingOptionRequest.ShippingAddress.Country.Id : null; - - var shippingMethods = this._shippingService.GetAllShippingMethods(restrictByCountryId, getShippingOptionRequest.Customer); + var shippingMethods = this._shippingService.GetAllShippingMethods(getShippingOptionRequest.Customer); foreach (var shippingMethod in shippingMethods) { var shippingOption = new ShippingOption(); @@ -82,10 +79,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get if (getShippingOptionRequest == null) throw new ArgumentNullException("getShippingOptionRequest"); - int? restrictByCountryId = (getShippingOptionRequest.ShippingAddress != null && getShippingOptionRequest.ShippingAddress.Country != null) - ? (int?)getShippingOptionRequest.ShippingAddress.Country.Id : null; - - var shippingMethods = this._shippingService.GetAllShippingMethods(restrictByCountryId, getShippingOptionRequest.Customer); + var shippingMethods = this._shippingService.GetAllShippingMethods(getShippingOptionRequest.Customer); var rates = new List(); foreach (var shippingMethod in shippingMethods) diff --git a/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs b/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs index 9c9d9d69f6..bc94c7a947 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs @@ -141,7 +141,7 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get } decimal weight = _shippingService.GetShoppingCartTotalWeight(getShippingOptionRequest.Items); - var shippingMethods = _shippingService.GetAllShippingMethods(countryId, getShippingOptionRequest.Customer); + var shippingMethods = _shippingService.GetAllShippingMethods(getShippingOptionRequest.Customer); foreach (var shippingMethod in shippingMethods) { var record = _shippingByWeightService.FindRecord(shippingMethod.Id, storeId, countryId, weight); diff --git a/src/Presentation/SmartStore.Web/Administration/Content/admin.less b/src/Presentation/SmartStore.Web/Administration/Content/admin.less index 7c7a6017d3..c3bf87312d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Content/admin.less +++ b/src/Presentation/SmartStore.Web/Administration/Content/admin.less @@ -748,9 +748,16 @@ td.adminData .text-box.single-line { width: 300px; } td.adminData input[type=text].input-large, -td.adminData textarea.input-large { +td.adminData textarea.input-large, +td.adminData .control-large { width: 500px; } +td.adminData input[type=text].input-xlarge, +td.adminData textarea.input-xlarge, +td.adminData .control-xlarge { + width: 800px; +} + .t-grid .text-box.single-line { /* ... */ @@ -1197,43 +1204,6 @@ table.payment-method-features td { font-size: 12px; } -/* payment and shipping restrictions --------------------------------------------------------------- */ -.restriction-container { - th label { - margin: 0 10px 0 0; - display: inline-block; - } - - th > div { - display: inline-block; - padding-right: 10px; - } - - .normal-font { - font-weight: normal; - } - - .column-customerroles, - .column-shippingmethods { - width: 18%; - } - - .column-countries { - width: 64%; - - > div { - display: table-row; - } - - .country-container { - display: table-cell; - width: 25%; - padding-right: 10px; - } - } -} - /* Special icons */ .icon-active-true { diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs index 7b81ffd118..d66429e90d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Payments; +using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Payments; using SmartStore.Core.Plugins; using SmartStore.Services; @@ -64,7 +65,6 @@ public PaymentController( private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, PaymentMethod paymentMethod) { - SelectListItem item = null; var customerRoles = _customerService.GetAllCustomerRoles(true); var shippingMethods = _shippingService.GetAllShippingMethods(); var countries = _countryService.GetAllCountries(true); @@ -72,6 +72,8 @@ private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, Payment model.AvailableCustomerRoles = new List(); model.AvailableShippingMethods = new List(); model.AvailableCountries = new List(); + + model.AvailableCountryExclusionContextTypes = CountryRestrictionContextType.BillingAddress.ToSelectList(false).ToList(); model.AvailableAmountRestrictionContextTypes = AmountRestrictionContextType.SubtotalAmount.ToSelectList(false).ToList(); foreach (var role in customerRoles.OrderBy(x => x.Name)) @@ -91,28 +93,15 @@ private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, Payment if (paymentMethod != null) { - model.CountryExclusionContext = paymentMethod.CountryExclusionContext; - model.AmountRestrictionContext = paymentMethod.AmountRestrictionContext; + model.ExcludedCustomerRoleIds = paymentMethod.ExcludedCustomerRoleIds.SplitSafe(","); + model.ExcludedShippingMethodIds = paymentMethod.ExcludedShippingMethodIds.SplitSafe(","); + model.ExcludedCountryIds = paymentMethod.ExcludedCountryIds.SplitSafe(","); + model.MinimumOrderAmount = paymentMethod.MinimumOrderAmount; model.MaximumOrderAmount = paymentMethod.MaximumOrderAmount; - foreach (var id in paymentMethod.ExcludedCustomerRoleIds.SplitSafe(",")) - { - if ((item = model.AvailableCustomerRoles.FirstOrDefault(x => x.Value == id)) != null) - item.Selected = true; - } - - foreach (var id in paymentMethod.ExcludedShippingMethodIds.SplitSafe(",")) - { - if ((item = model.AvailableShippingMethods.FirstOrDefault(x => x.Value == id)) != null) - item.Selected = true; - } - - foreach (var id in paymentMethod.ExcludedCountryIds.SplitSafe(",")) - { - if ((item = model.AvailableCountries.FirstOrDefault(x => x.Value == id)) != null) - item.Selected = true; - } + model.CountryExclusionContext = paymentMethod.CountryExclusionContext; + model.AmountRestrictionContext = paymentMethod.AmountRestrictionContext; } } @@ -213,29 +202,15 @@ public ActionResult Edit(string systemName, bool continueEditing, PaymentMethodE if (paymentMethod == null) paymentMethod = new PaymentMethod { PaymentMethodSystemName = systemName }; - var customerRoleIds = Request.Form.AllKeys - .Where(x => x.StartsWith("CustomerRole_")) - .Select(x => x.Replace("CustomerRole_", "")) - .ToList(); + paymentMethod.ExcludedCustomerRoleIds = Request.Form["ExcludedCustomerRoleIds"]; + paymentMethod.ExcludedShippingMethodIds = Request.Form["ExcludedShippingMethodIds"]; + paymentMethod.ExcludedCountryIds = Request.Form["ExcludedCountryIds"]; - var shippingMethodIds = Request.Form.AllKeys - .Where(x => x.StartsWith("ShippingMethod_")) - .Select(x => x.Replace("ShippingMethod_", "")) - .ToList(); - - var countryIds = Request.Form.AllKeys - .Where(x => x.StartsWith("Country_")) - .Select(x => x.Replace("Country_", "")) - .ToList(); - - paymentMethod.ExcludedCustomerRoleIds = string.Join(",", customerRoleIds); - paymentMethod.ExcludedShippingMethodIds = string.Join(",", shippingMethodIds); - paymentMethod.ExcludedCountryIds = string.Join(",", countryIds); + paymentMethod.MinimumOrderAmount = model.MinimumOrderAmount; + paymentMethod.MaximumOrderAmount = model.MaximumOrderAmount; paymentMethod.CountryExclusionContext = model.CountryExclusionContext; paymentMethod.AmountRestrictionContext = model.AmountRestrictionContext; - paymentMethod.MinimumOrderAmount = model.MinimumOrderAmount; - paymentMethod.MaximumOrderAmount = model.MaximumOrderAmount; if (paymentMethod.Id == 0) _paymentService.InsertPaymentMethod(paymentMethod); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs index 996f0af0a5..4dd03455e0 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs @@ -1,11 +1,9 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Web.Mvc; -using SmartStore.Admin.Models.Directory; using SmartStore.Admin.Models.Shipping; +using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Shipping; -using SmartStore.Core.Plugins; using SmartStore.Services; using SmartStore.Services.Customers; using SmartStore.Services.Directory; @@ -29,7 +27,6 @@ public partial class ShippingController : AdminControllerBase private readonly ICountryService _countryService; private readonly ILocalizedEntityService _localizedEntityService; private readonly ILanguageService _languageService; - private readonly IPluginFinder _pluginFinder; private readonly PluginMediator _pluginMediator; private readonly ICommonServices _commonServices; private readonly ICustomerService _customerService; @@ -43,7 +40,6 @@ public ShippingController(IShippingService shippingService, ICountryService countryService, ILocalizedEntityService localizedEntityService, ILanguageService languageService, - IPluginFinder pluginFinder, PluginMediator pluginMediator, ICommonServices commonServices, ICustomerService customerService) @@ -53,7 +49,6 @@ public ShippingController(IShippingService shippingService, this._countryService = countryService; this._localizedEntityService = localizedEntityService; this._languageService = languageService; - this._pluginFinder = pluginFinder; this._pluginMediator = pluginMediator; this._commonServices = commonServices; this._customerService = customerService; @@ -82,34 +77,61 @@ protected void UpdateLocales(ShippingMethod shippingMethod, ShippingMethodModel private void PrepareShippingMethodModel(ShippingMethodModel model, ShippingMethod shippingMethod) { - SelectListItem item = null; var customerRoles = _customerService.GetAllCustomerRoles(true); + var countries = _countryService.GetAllCountries(true); model.AvailableCustomerRoles = new List(); + model.AvailableCountries = new List(); + + model.AvailableCountryExclusionContextTypes = CountryRestrictionContextType.BillingAddress.ToSelectList(false).ToList(); foreach (var role in customerRoles.OrderBy(x => x.Name)) { model.AvailableCustomerRoles.Add(new SelectListItem { Text = role.Name, Value = role.Id.ToString() }); } + foreach (var country in countries.OrderBy(x => x.Name)) + { + model.AvailableCountries.Add(new SelectListItem { Text = country.GetLocalized(x => x.Name), Value = country.Id.ToString() }); + } + if (shippingMethod != null) { - foreach (var id in shippingMethod.ExcludedCustomerRoleIds.SplitSafe(",")) - { - if ((item = model.AvailableCustomerRoles.FirstOrDefault(x => x.Value == id)) != null) - item.Selected = true; - } + model.ExcludedCustomerRoleIds = shippingMethod.ExcludedCustomerRoleIds.SplitSafe(","); + model.ExcludedCountryIds = shippingMethod.RestrictedCountries.Select(x => x.Id.ToString()).ToArray(); + + model.CountryExclusionContext = shippingMethod.CountryExclusionContext; } } - private void ApplyRestrictions(ShippingMethod shippingMethod) + private void ApplyRestrictions(ShippingMethod shippingMethod, ShippingMethodModel model) { - var customerRoleIds = Request.Form.AllKeys - .Where(x => x.StartsWith("CustomerRole_")) - .Select(x => x.Replace("CustomerRole_", "")) - .ToList(); + var countries = _countryService.GetAllCountries(true); + + shippingMethod.ExcludedCustomerRoleIds = Request.Form["ExcludedCustomerRoleIds"]; + shippingMethod.CountryExclusionContext = model.CountryExclusionContext; + + string[] excludedCountryIds = Request.Form["ExcludedCountryIds"].SplitSafe(","); - shippingMethod.ExcludedCustomerRoleIds = string.Join(",", customerRoleIds); + foreach (var country in countries) + { + if (excludedCountryIds.Contains(country.Id.ToString())) + { + if (shippingMethod.RestrictedCountries.Where(c => c.Id == country.Id).FirstOrDefault() == null) + { + shippingMethod.RestrictedCountries.Add(country); + _shippingService.UpdateShippingMethod(shippingMethod); + } + } + else + { + if (shippingMethod.RestrictedCountries.Where(c => c.Id == country.Id).FirstOrDefault() != null) + { + shippingMethod.RestrictedCountries.Remove(country); + _shippingService.UpdateShippingMethod(shippingMethod); + } + } + } } #endregion @@ -225,7 +247,7 @@ public ActionResult CreateMethod(ShippingMethodModel model, bool continueEditing if (ModelState.IsValid) { var sm = model.ToEntity(); - ApplyRestrictions(sm); + ApplyRestrictions(sm, model); _shippingService.InsertShippingMethod(sm); @@ -276,12 +298,13 @@ public ActionResult EditMethod(ShippingMethodModel model, bool continueEditing) if (ModelState.IsValid) { sm = model.ToEntity(sm); - ApplyRestrictions(sm); + ApplyRestrictions(sm, model); _shippingService.UpdateShippingMethod(sm); //locales UpdateLocales(sm, model); + NotifySuccess(_commonServices.Localization.GetResource("Admin.Configuration.Shipping.Methods.Updated")); return continueEditing ? RedirectToAction("EditMethod", sm.Id) : RedirectToAction("Methods"); @@ -307,89 +330,6 @@ public ActionResult DeleteMethod(int id) return RedirectToAction("Methods"); } - #endregion - - #region Restrictions - - public ActionResult Restrictions() - { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) - return AccessDeniedView(); - - var model = new ShippingMethodRestrictionModel(); - - var countries = _countryService.GetAllCountries(true); - var shippingMethods = _shippingService.GetAllShippingMethods(); - foreach (var country in countries) - { - model.AvailableCountries.Add(new CountryModel() - { - Id = country.Id, - Name = country.Name - }); - } - foreach (var sm in shippingMethods) - { - model.AvailableShippingMethods.Add(new ShippingMethodModel() - { - Id = sm.Id, - Name = sm.Name - }); - } - foreach (var country in countries) - foreach (var shippingMethod in shippingMethods) - { - bool restricted = shippingMethod.CountryRestrictionExists(country.Id); - if (!model.Restricted.ContainsKey(country.Id)) - model.Restricted[country.Id] = new Dictionary(); - model.Restricted[country.Id][shippingMethod.Id] = restricted; - } - - return View(model); - } - - [HttpPost, ActionName("Restrictions")] - public ActionResult RestrictionSave(FormCollection form) - { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) - return AccessDeniedView(); - - var countries = _countryService.GetAllCountries(true); - var shippingMethods = _shippingService.GetAllShippingMethods(); - - - foreach (var shippingMethod in shippingMethods) - { - string formKey = "restrict_" + shippingMethod.Id; - var countryIdsToRestrict = form[formKey] != null ? form[formKey].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => int.Parse(x)).ToList() : new List(); - - foreach (var country in countries) - { - - bool restrict = countryIdsToRestrict.Contains(country.Id); - if (restrict) - { - if (shippingMethod.RestrictedCountries.Where(c => c.Id == country.Id).FirstOrDefault() == null) - { - shippingMethod.RestrictedCountries.Add(country); - _shippingService.UpdateShippingMethod(shippingMethod); - } - } - else - { - if (shippingMethod.RestrictedCountries.Where(c => c.Id == country.Id).FirstOrDefault() != null) - { - shippingMethod.RestrictedCountries.Remove(country); - _shippingService.UpdateShippingMethod(shippingMethod); - } - } - } - } - - NotifySuccess(_commonServices.Localization.GetResource("Admin.Configuration.Shipping.Restrictions.Updated")); - return RedirectToAction("Restrictions"); - } - - #endregion + #endregion } } diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index cd06725772..958b035003 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -387,7 +387,9 @@ public void Execute() //shipping methods Mapper.CreateMap() .ForMember(dest => dest.Locales, mo => mo.Ignore()) - .ForMember(dest => dest.AvailableCustomerRoles, mo => mo.Ignore()); + .ForMember(dest => dest.AvailableCustomerRoles, mo => mo.Ignore()) + .ForMember(dest => dest.AvailableCountries, mo => mo.Ignore()) + .ForMember(dest => dest.AvailableCountryExclusionContextTypes, mo => mo.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.RestrictedCountries, mo => mo.Ignore()) .ForMember(dest => dest.ExcludedCustomerRoleIds, mo => mo.Ignore()); diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs index 9857d0f0e3..12abe357ea 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Web.Mvc; -using SmartStore.Core.Domain.Payments; +using SmartStore.Core.Domain.Common; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Mvc; @@ -8,20 +8,30 @@ namespace SmartStore.Admin.Models.Payments { public class PaymentMethodEditModel : ProviderModel { + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.ExcludedCustomerRole")] + public string[] ExcludedCustomerRoleIds { get; set; } public List AvailableCustomerRoles { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.ExcludedShippingMethod")] + public string[] ExcludedShippingMethodIds { get; set; } public List AvailableShippingMethods { get; set; } - public List AvailableCountries { get; set; } - public List AvailableAmountRestrictionContextTypes { get; set; } - public CountryExclusionContextType CountryExclusionContext { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.ExcludedCountry")] + public string[] ExcludedCountryIds { get; set; } + public List AvailableCountries { get; set; } - [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.AmountRestrictionContext")] - public AmountRestrictionContextType AmountRestrictionContext { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Restrictions.CountryExclusionContext")] + public CountryRestrictionContextType CountryExclusionContext { get; set; } + public List AvailableCountryExclusionContextTypes { get; set; } [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.MinimumOrderAmount")] public decimal? MinimumOrderAmount { get; set; } [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.MaximumOrderAmount")] public decimal? MaximumOrderAmount { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Restrictions.AmountRestrictionContext")] + public AmountRestrictionContextType AmountRestrictionContext { get; set; } + public List AvailableAmountRestrictionContextTypes { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodModel.cs index c9690b4695..4a8e380e73 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodModel.cs @@ -2,6 +2,7 @@ using System.Web.Mvc; using FluentValidation.Attributes; using SmartStore.Admin.Validators.Shipping; +using SmartStore.Core.Domain.Common; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Localization; using SmartStore.Web.Framework.Mvc; @@ -32,7 +33,17 @@ public ShippingMethodModel() public IList Locales { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Shipping.Methods.ExcludedCustomerRole")] + public string[] ExcludedCustomerRoleIds { get; set; } public List AvailableCustomerRoles { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Shipping.Methods.ExcludedCountry")] + public string[] ExcludedCountryIds { get; set; } + public List AvailableCountries { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Restrictions.CountryExclusionContext")] + public CountryRestrictionContextType CountryExclusionContext { get; set; } + public List AvailableCountryExclusionContextTypes { get; set; } } public class ShippingMethodLocalizedModel : ILocalizedModelLocal diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodRestrictionModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodRestrictionModel.cs deleted file mode 100644 index 1fa24bac73..0000000000 --- a/src/Presentation/SmartStore.Web/Administration/Models/Shipping/ShippingMethodRestrictionModel.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using SmartStore.Admin.Models.Directory; -using SmartStore.Web.Framework.Mvc; - -namespace SmartStore.Admin.Models.Shipping -{ - public class ShippingMethodRestrictionModel : ModelBase - { - public ShippingMethodRestrictionModel() - { - AvailableShippingMethods = new List(); - AvailableCountries = new List(); - Restricted = new Dictionary>(); - } - public IList AvailableShippingMethods { get; set; } - public IList AvailableCountries { get; set; } - - //[country id] / [shipping method id] / [restricted] - public IDictionary> Restricted { get; set; } - } -} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index 51dabda6e7..60c5ff77f0 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -309,7 +309,6 @@ - @@ -893,9 +892,6 @@ - - - diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml index ef2d508ae3..c891471a5d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml @@ -87,8 +87,54 @@ @helper TabRestrictions() { +
+ @Html.Raw(T("Admin.Configuration.Payment.Methods.RestrictionNote")) +
+
+ + + + + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.ExcludedCustomerRoleIds) + + @Html.ListBoxFor(model => model.ExcludedCustomerRoleIds, + new MultiSelectList(Model.AvailableCustomerRoles, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.ExcludedCustomerRoleIds) +
+ @Html.SmartLabelFor(model => model.ExcludedShippingMethodIds) + + @Html.ListBoxFor(model => model.ExcludedShippingMethodIds, + new MultiSelectList(Model.AvailableShippingMethods, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.ExcludedShippingMethodIds) +
+ @Html.SmartLabelFor(model => model.ExcludedCountryIds) + + @Html.ListBoxFor(model => model.ExcludedCountryIds, + new MultiSelectList(Model.AvailableCountries, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.ExcludedCountryIds) +
+ @Html.SmartLabelFor(model => model.CountryExclusionContext) + + @Html.DropDownListFor(model => model.CountryExclusionContext, Model.AvailableCountryExclusionContextTypes) + @Html.ValidationMessageFor(model => model.CountryExclusionContext) +
@Html.SmartLabelFor(model => model.MinimumOrderAmount) @@ -118,108 +164,4 @@
- -

 

- -
- @Html.Raw(T("Admin.Configuration.Payment.Methods.RestrictionNote")) -
- -
- - - - - - - - - - - -
-
- -
-
-
- -
-
-
- -
-
- @T("Admin.Common.RelatedTo") -
-
- - -
-
- @foreach (var item in Model.AvailableCustomerRoles) - { - @RenderCheckbox(item, "CustomerRole_") - } - - @foreach (var item in Model.AvailableShippingMethods) - { - @RenderCheckbox(item, "ShippingMethod_") - } - - - @foreach (var grp in Model.AvailableCountries.Select((x, i) => new { Key = i / 4, Value = x }).GroupBy(x => x.Key, x => x.Value)) - { -
- @foreach (var item in grp) - { -
- @RenderCheckbox(item, "Country_") -
- } -
- } - -
-
} - - -@helper RenderCheckbox(SelectListItem item, string prefix) -{ -
- -
-} - - \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml deleted file mode 100644 index e13f1fe8e5..0000000000 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml +++ /dev/null @@ -1,91 +0,0 @@ -@model ShippingMethodRestrictionModel -@{ - ViewBag.Title = T("Admin.Configuration.Shipping.Restrictions").Text; -} -@using (Html.BeginForm()) -{ -
-
- - @T("Admin.Configuration.Shipping.Restrictions") -
-
- -
-
- -
- - @T("Admin.Configuration.Shipping.Restrictions.Description") -
- - - - - -
- @if (Model.AvailableCountries.Count == 0) - { - No countries defined - } - else if (Model.AvailableShippingMethods.Count == 0) - { - No shipping methods available - } - else - { - - -
- - - - - @foreach (var sm in Model.AvailableShippingMethods) - { - - } - - - - @foreach (var c in Model.AvailableCountries) - { - - - @foreach (var sm in Model.AvailableShippingMethods) - { - var restricted = Model.Restricted.ContainsKey(c.Id) && Model.Restricted[c.Id][sm.Id]; - - } - - } - -
- @T("Admin.Configuration.Shipping.Restrictions.Country") - - - -
- @c.Name - - -
-
- } -
-} diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml index 9033b3beb7..9163a2f8db 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml @@ -15,52 +15,52 @@ @helper TabGeneral() { @(Html.LocalizedEditor("shipping-method-localized", - @ - - - - - - - - - - - -
- @Html.SmartLabelFor(model => model.Locales[item].Name) - - @Html.EditorFor(model => Model.Locales[item].Name) - @Html.ValidationMessageFor(model => model.Locales[item].Name) -
- @Html.SmartLabelFor(model => model.Locales[item].Description) - - @Html.TextAreaFor(model => model.Locales[item].Description) - @Html.ValidationMessageFor(model => model.Locales[item].Description) -
- @Html.HiddenFor(model => model.Locales[item].LanguageId) -
- , - @ - - - - - - - - -
- @Html.SmartLabelFor(model => model.Name) - - @Html.EditorFor(model => model.Name) - @Html.ValidationMessageFor(model => model.Name) -
- @Html.SmartLabelFor(model => model.Description) - - @Html.TextAreaFor(model => model.Description) - @Html.ValidationMessageFor(model => model.Description) -
+ @ + + + + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Locales[item].Name) + + @Html.EditorFor(model => Model.Locales[item].Name) + @Html.ValidationMessageFor(model => model.Locales[item].Name) +
+ @Html.SmartLabelFor(model => model.Locales[item].Description) + + @Html.TextAreaFor(model => model.Locales[item].Description) + @Html.ValidationMessageFor(model => model.Locales[item].Description) +
+ @Html.HiddenFor(model => model.Locales[item].LanguageId) +
+ , + @ + + + + + + + + +
+ @Html.SmartLabelFor(model => model.Name) + + @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ @Html.SmartLabelFor(model => model.Description) + + @Html.TextAreaFor(model => model.Description) + @Html.ValidationMessageFor(model => model.Description) +
)) @@ -91,50 +91,39 @@ @Html.Raw(T("Admin.Configuration.Shipping.Methods.RestrictionNote")) -
-
+
+
- + + - + + + + +
-
- -
-
+ @Html.SmartLabelFor(model => model.ExcludedCustomerRoleIds) + + @Html.ListBoxFor(model => model.ExcludedCustomerRoleIds, + new MultiSelectList(Model.AvailableCustomerRoles, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.ExcludedCustomerRoleIds) +
- @foreach (var item in Model.AvailableCustomerRoles) - { - @RenderCheckbox(item, "CustomerRole_") - } + + @Html.SmartLabelFor(model => model.ExcludedCountryIds) + + @Html.ListBoxFor(model => model.ExcludedCountryIds, + new MultiSelectList(Model.AvailableCountries, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.ExcludedCountryIds) +
+ @Html.SmartLabelFor(model => model.CountryExclusionContext) + + @Html.DropDownListFor(model => model.CountryExclusionContext, Model.AvailableCountryExclusionContextTypes) + @Html.ValidationMessageFor(model => model.CountryExclusionContext)
} - -@helper RenderCheckbox(SelectListItem item, string prefix) -{ -
- -
-} - - \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/sitemap.config b/src/Presentation/SmartStore.Web/Administration/sitemap.config index 0035df8219..33a9fd264f 100644 --- a/src/Presentation/SmartStore.Web/Administration/sitemap.config +++ b/src/Presentation/SmartStore.Web/Administration/sitemap.config @@ -107,7 +107,6 @@ - From 2e03fd56976bfdccd0d886d21a5e3aef5d2eabf4 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 22 Jun 2015 11:02:30 +0200 Subject: [PATCH 0163/1256] Resolved merging conflict --- src/Libraries/SmartStore.Data/SmartStore.Data.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 1854f65f2c..4d60239cc6 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -277,9 +277,9 @@ 201506181858349_AclRecordCustomerRole.cs - - - 201506181501470_PaymentShippingRestrictions.cs + + + 201506211043073_PaymentShippingRestrictions.cs @@ -541,8 +541,8 @@ 201506181858349_AclRecordCustomerRole.cs - - 201506181501470_PaymentShippingRestrictions.cs + + 201506211043073_PaymentShippingRestrictions.cs From 8c812002d677eddf43ff95b8be60a224385cf3cd Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 22 Jun 2015 14:06:35 +0200 Subject: [PATCH 0164/1256] Stock of product was shown when an attribute for an attribute combination was selected --- .../Orders/IShoppingCartService.cs | 8 ++ .../Orders/ShoppingCartService.cs | 52 +++++++ .../Controllers/CatalogHelper.cs | 2 +- .../Controllers/ProductController.cs | 129 ++++++++++-------- .../Scripts/public.product-detail.js | 10 +- 5 files changed, 143 insertions(+), 58 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Orders/IShoppingCartService.cs b/src/Libraries/SmartStore.Services/Orders/IShoppingCartService.cs index e8ec6bcd06..517811cc78 100644 --- a/src/Libraries/SmartStore.Services/Orders/IShoppingCartService.cs +++ b/src/Libraries/SmartStore.Services/Orders/IShoppingCartService.cs @@ -170,6 +170,14 @@ List AddToCart(Customer customer, Product product, ShoppingCartType cart /// Add to cart context void AddToCartStoring(AddToCartContext ctx); + /// + /// Validates if all required attributes are selected + /// + /// Selected attributes + /// Product + /// bool + bool AreAllAttributesForCombinationSelected(string selectedAttributes, Product product); + /// /// Updates the shopping cart item /// diff --git a/src/Libraries/SmartStore.Services/Orders/ShoppingCartService.cs b/src/Libraries/SmartStore.Services/Orders/ShoppingCartService.cs index 5882bda05e..c6c63519e8 100644 --- a/src/Libraries/SmartStore.Services/Orders/ShoppingCartService.cs +++ b/src/Libraries/SmartStore.Services/Orders/ShoppingCartService.cs @@ -591,6 +591,58 @@ public virtual IList GetShoppingCartItemAttributeWarnings(Customer custo return warnings; } + /// + /// Validates if all required attributes are selected + /// + /// Selected attributes + /// Product + /// bool + public virtual bool AreAllAttributesForCombinationSelected(string selectedAttributes, Product product) + { + if (product.ProductVariantAttributeCombinations.Count == 0) + return true; + + //selected attributes + var pva1Collection = _productAttributeParser.ParseProductVariantAttributes(selectedAttributes); + + //existing product attributes + var pva2Collection = product.ProductVariantAttributes; + foreach (var pva2 in pva2Collection) + { + if (pva2.IsRequired) + { + bool found = false; + //selected product attributes + foreach (var pva1 in pva1Collection) + { + if (pva1.Id == pva2.Id) + { + var pvaValuesStr = _productAttributeParser.ParseValues(selectedAttributes, pva1.Id); + foreach (string str1 in pvaValuesStr) + { + if (!String.IsNullOrEmpty(str1.Trim())) + { + found = true; + break; + } + } + } + } + + if (!found) + { + return found; + } + } + else + { + return true; + } + } + + return true; + } + /// /// Validates shopping cart item (gift card) /// diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index 6ecce2697c..7c54a404b2 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -628,7 +628,7 @@ public ProductDetailsModel PrepareProductDetailModel( { // cases where stock inventory is not functional. determined by what ShoppingCartService.GetStandardWarnings and ProductService.AdjustInventory is not handling. model.IsAvailable = true; - model.StockAvailability = ""; + model.StockAvailability = product.ProductVariantAttributeCombinations.Count == 0 ? product.FormatStockMessage(_localizationService) : ""; } else if (model.IsAvailable) { diff --git a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs index d778b741b5..a05ac33df4 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs @@ -59,6 +59,8 @@ public partial class ProductController : PublicControllerBase private readonly LocalizationSettings _localizationSettings; private readonly CaptchaSettings _captchaSettings; private readonly CatalogHelper _helper; + private readonly IDownloadService _downloadService; + private readonly ILocalizationService _localizationService; #endregion @@ -90,7 +92,9 @@ public ProductController( ShoppingCartSettings shoppingCartSettings, LocalizationSettings localizationSettings, CaptchaSettings captchaSettings, - CatalogHelper helper) + CatalogHelper helper, + IDownloadService downloadService, + ILocalizationService localizationService) { this._services = services; this._manufacturerService = manufacturerService; @@ -118,6 +122,8 @@ public ProductController( this._localizationSettings = localizationSettings; this._captchaSettings = captchaSettings; this._helper = helper; + this._downloadService = downloadService; + this._localizationService = localizationService; T = NullLocalizer.Instance; } @@ -662,62 +668,73 @@ public ActionResult UpdateProductDetails(int productId, string itemType, int bun } } + var attributes = _productAttributeService.GetProductVariantAttributesByProductId(productId); + var warnings = new List(); + string attributeXml = form.CreateSelectedAttributesXml(productId, attributes, _productAttributeParser, + _localizationService, _downloadService, _catalogSettings, this.Request, warnings, true); + #region data object - object data = new - { - Delivery = new - { - Id = 0, - Name = m.DeliveryTimeName, - Color = m.DeliveryTimeHexValue, - DisplayAccordingToStock = m.DisplayDeliveryTimeAccordingToStock - }, - Measure = new - { - Weight = new { Value = m.WeightValue, Text = m.Weight }, - Height = new { Value = product.Height, Text = m.Height }, - Width = new { Value = product.Width, Text = m.Width }, - Length = new { Value = product.Length, Text = m.Length } - }, - Number = new - { - Sku = new { Value = m.Sku, Show = m.ShowSku }, - Gtin = new { Value = m.Gtin, Show = m.ShowGtin }, - Mpn = new { Value = m.ManufacturerPartNumber, Show = m.ShowManufacturerPartNumber } - }, - Price = new - { - Base = new - { - Enabled = m.IsBasePriceEnabled, - Info = m.BasePriceInfo - }, - Old = new - { - Value = decimal.Zero, - Text = m.ProductPrice.OldPrice - }, - WithoutDiscount = new - { - Value = m.ProductPrice.PriceValue, - Text = m.ProductPrice.Price - }, - WithDiscount = new - { - Value = m.ProductPrice.PriceWithDiscountValue, - Text = m.ProductPrice.PriceWithDiscount - } - }, - Stock = new - { - Quantity = new { Value = product.StockQuantity, Show = product.DisplayStockQuantity }, - Availability = new { Text = m.StockAvailability, Show = product.DisplayStockAvailability, Available = m.IsAvailable } - }, - - DynamicThumblUrl = dynamicThumbUrl, - GalleryStartIndex = galleryStartIndex, - GalleryHtml = galleryHtml - }; + object data = new + { + Delivery = new + { + Id = 0, + Name = m.DeliveryTimeName, + Color = m.DeliveryTimeHexValue, + DisplayAccordingToStock = m.DisplayDeliveryTimeAccordingToStock + }, + Measure = new + { + Weight = new { Value = m.WeightValue, Text = m.Weight }, + Height = new { Value = product.Height, Text = m.Height }, + Width = new { Value = product.Width, Text = m.Width }, + Length = new { Value = product.Length, Text = m.Length } + }, + Number = new + { + Sku = new { Value = m.Sku, Show = m.ShowSku }, + Gtin = new { Value = m.Gtin, Show = m.ShowGtin }, + Mpn = new { Value = m.ManufacturerPartNumber, Show = m.ShowManufacturerPartNumber } + }, + Price = new + { + Base = new + { + Enabled = m.IsBasePriceEnabled, + Info = m.BasePriceInfo + }, + Old = new + { + Value = decimal.Zero, + Text = m.ProductPrice.OldPrice + }, + WithoutDiscount = new + { + Value = m.ProductPrice.PriceValue, + Text = m.ProductPrice.Price + }, + WithDiscount = new + { + Value = m.ProductPrice.PriceWithDiscountValue, + Text = m.ProductPrice.PriceWithDiscount + } + }, + Stock = new + { + Quantity = new { + Value = product.StockQuantity, + Show = _shoppingCartService.AreAllAttributesForCombinationSelected(attributeXml, product) ? product.DisplayStockQuantity : false + }, + Availability = new { + Text = m.StockAvailability, + Show = _shoppingCartService.AreAllAttributesForCombinationSelected(attributeXml, product) ? product.DisplayStockAvailability : false, + Available = m.IsAvailable } + }, + + DynamicThumblUrl = dynamicThumbUrl, + GalleryStartIndex = galleryStartIndex, + GalleryHtml = galleryHtml + }; #endregion return new JsonResult { Data = data }; diff --git a/src/Presentation/SmartStore.Web/Scripts/public.product-detail.js b/src/Presentation/SmartStore.Web/Scripts/public.product-detail.js index 23a2bd410b..c86e55904f 100644 --- a/src/Presentation/SmartStore.Web/Scripts/public.product-detail.js +++ b/src/Presentation/SmartStore.Web/Scripts/public.product-detail.js @@ -130,7 +130,15 @@ updateAttrLine(".attr-length", data.Measure.Length.Text); updateAttrLine(".attr-width", data.Measure.Width.Text); updateAttrLine(".attr-height", data.Measure.Height.Text); - updateAttrLine(".attr-stock", data.Stock.Availability.Text); + + if (data.Stock.Quantity.Show) + { + updateAttrLine(".attr-stock", data.Stock.Availability.Text); + } + else + { + updateAttrLine(".attr-stock", ""); + } context.find('.add-to-cart .form-inline').toggle(data.Stock.Availability.Available); From e3aed9743f25ed530b159ee7e7a137a2446130b0 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 23 Jun 2015 10:31:21 +0200 Subject: [PATCH 0165/1256] Minor performance change on previous commit --- .../Controllers/ProductController.cs | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs index a05ac33df4..c630094401 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs @@ -610,6 +610,14 @@ public ActionResult UpdateProductDetails(int productId, string itemType, int bun IList bundleItems = null; ProductBundleItemData bundleItem = (bItem == null ? null : new ProductBundleItemData(bItem)); + var warnings = new List(); + var attributes = _productAttributeService.GetProductVariantAttributesByProductId(productId); + + string attributeXml = form.CreateSelectedAttributesXml(productId, attributes, _productAttributeParser, + _localizationService, _downloadService, _catalogSettings, this.Request, warnings, true); + + var areAllAttributesForCombinationSelected = _shoppingCartService.AreAllAttributesForCombinationSelected(attributeXml, product); + // quantity required for tier prices string quantityKey = form.AllKeys.FirstOrDefault(k => k.EndsWith("EnteredQuantity")); if (quantityKey.HasValue()) @@ -667,13 +675,9 @@ public ActionResult UpdateProductDetails(int productId, string itemType, int bun galleryHtml = this.RenderPartialViewToString("_PictureGallery", pictureModel); } } - - var attributes = _productAttributeService.GetProductVariantAttributesByProductId(productId); - var warnings = new List(); - string attributeXml = form.CreateSelectedAttributesXml(productId, attributes, _productAttributeParser, - _localizationService, _downloadService, _catalogSettings, this.Request, warnings, true); #region data object + object data = new { Delivery = new @@ -721,20 +725,24 @@ public ActionResult UpdateProductDetails(int productId, string itemType, int bun }, Stock = new { - Quantity = new { + Quantity = new + { Value = product.StockQuantity, - Show = _shoppingCartService.AreAllAttributesForCombinationSelected(attributeXml, product) ? product.DisplayStockQuantity : false + Show = areAllAttributesForCombinationSelected ? product.DisplayStockQuantity : false }, - Availability = new { + Availability = new + { Text = m.StockAvailability, - Show = _shoppingCartService.AreAllAttributesForCombinationSelected(attributeXml, product) ? product.DisplayStockAvailability : false, - Available = m.IsAvailable } + Show = areAllAttributesForCombinationSelected ? product.DisplayStockAvailability : false, + Available = m.IsAvailable + } }, DynamicThumblUrl = dynamicThumbUrl, GalleryStartIndex = galleryStartIndex, GalleryHtml = galleryHtml }; + #endregion return new JsonResult { Data = data }; From f8a107b24252fd23d1612cc9cf4b57059768c082 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 23 Jun 2015 12:45:49 +0200 Subject: [PATCH 0166/1256] Resolves #716 Supporting of paged google-product data query for SQL-Server Compact Edition --- changelog.md | 1 + .../Description.txt | 2 +- .../Services/GoogleFeedService.cs | 63 ++++++++++++++----- .../changelog.md | 4 ++ 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/changelog.md b/changelog.md index 5f64928215..0600e50dfb 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,7 @@ ### Improvements * (Soft) deletion of SEO slug supporting entities now also deletes the corresponding url records * License checker now supports IDN mapping for domain names +* #716 Supporting of paged google-product data query for SQL-Server Compact Edition ### Bugfixes * #694 Product variant attribute in product page should not be preselected implicitly diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/Description.txt b/src/Plugins/SmartStore.GoogleMerchantCenter/Description.txt index e2a36fb2e7..5d20784e8c 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/Description.txt +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/Description.txt @@ -1,7 +1,7 @@ FriendlyName: Google Merchant Center (GMC) SystemName: SmartStore.GoogleMerchantCenter Group: Marketing -Version: 2.2.0.1 +Version: 2.2.0.2 MinAppVersion: 2.2.0 Author: SmartStore AG DisplayOrder: 1 diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs b/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs index c0e67eff5a..1b1d047b26 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs @@ -556,7 +556,6 @@ public GridModel GetGridModel(GridCommand command, string se var textInfo = CultureInfo.InvariantCulture.TextInfo; // there's no way to share a context instance across repositories which makes GoogleProductObjectContext pretty useless here. - // so let's fallback to good old sql... by the way, fastest possible paged data query ever. var whereClause = new StringBuilder("(NOT ([t2].[Deleted] = 1)) AND ([t2].[VisibleIndividually] = 1)"); @@ -573,19 +572,43 @@ public GridModel GetGridModel(GridCommand command, string se whereClause.Append(" AND ([t2].[IsTouched] = 0 OR [t2].[IsTouched] IS NULL)"); } - string sql = -"SELECT [TotalCount], [t3].[Id], [t3].[Name], [t3].[SKU], [t3].[ProductTypeId], [t3].[value] AS [Taxonomy], [t3].[value2] AS [Gender], [t3].[value3] AS [AgeGroup], [t3].[value4] AS [Color], [t3].[value5] AS [Size], [t3].[value6] AS [Material], [t3].[value7] AS [Pattern], [t3].[value8] AS [Export]" + -" FROM (" + -" SELECT COUNT(id) OVER() [TotalCount], ROW_NUMBER() OVER (ORDER BY [t2].[Name]) AS [ROW_NUMBER], [t2].[Id], [t2].[Name], [t2].[SKU], [t2].[ProductTypeId], [t2].[value], [t2].[value2], [t2].[value3], [t2].[value4], [t2].[value5], [t2].[value6], [t2].[value7], [t2].[value8]" + -" FROM (" + -" SELECT [t0].[Id], [t0].[Name], [t0].[SKU], [t0].[ProductTypeId], [t1].[Taxonomy] AS [value], [t1].[Gender] AS [value2], [t1].[AgeGroup] AS [value3], [t1].[Color] AS [value4], [t1].[Size] AS [value5], [t1].[Material] AS [value6], [t1].[Pattern] AS [value7], COALESCE([t1].[Export],1) AS [value8], [t0].[Deleted], [t0].[VisibleIndividually], [t1].[IsTouched]" + -" FROM [Product] AS [t0]" + -" LEFT OUTER JOIN [GoogleProduct] AS [t1] ON [t0].[Id] = [t1].[ProductId]" + -" ) AS [t2]" + -" WHERE " + whereClause.ToString() + -" ) AS [t3]" + -" WHERE [t3].[ROW_NUMBER] BETWEEN {0} + 1 AND {0} + {1}" + -" ORDER BY [t3].[ROW_NUMBER]"; + string sql = null; + var isSqlServer = DataSettings.Current.IsSqlServer; + + if (isSqlServer) + { + // fastest possible paged data query + sql = + "SELECT [TotalCount], [t3].[Id], [t3].[Name], [t3].[SKU], [t3].[ProductTypeId], [t3].[value] AS [Taxonomy], [t3].[value2] AS [Gender], [t3].[value3] AS [AgeGroup], [t3].[value4] AS [Color], [t3].[value5] AS [Size], [t3].[value6] AS [Material], [t3].[value7] AS [Pattern], [t3].[value8] AS [Export]" + + " FROM (" + + " SELECT COUNT(id) OVER() [TotalCount], ROW_NUMBER() OVER (ORDER BY [t2].[Name]) AS [ROW_NUMBER], [t2].[Id], [t2].[Name], [t2].[SKU], [t2].[ProductTypeId], [t2].[value], [t2].[value2], [t2].[value3], [t2].[value4], [t2].[value5], [t2].[value6], [t2].[value7], [t2].[value8]" + + " FROM (" + + " SELECT [t0].[Id], [t0].[Name], [t0].[SKU], [t0].[ProductTypeId], [t1].[Taxonomy] AS [value], [t1].[Gender] AS [value2], [t1].[AgeGroup] AS [value3], [t1].[Color] AS [value4], [t1].[Size] AS [value5], [t1].[Material] AS [value6], [t1].[Pattern] AS [value7], COALESCE([t1].[Export],1) AS [value8], [t0].[Deleted], [t0].[VisibleIndividually], [t1].[IsTouched]" + + " FROM [Product] AS [t0]" + + " LEFT OUTER JOIN [GoogleProduct] AS [t1] ON [t0].[Id] = [t1].[ProductId]" + + " ) AS [t2]" + + " WHERE " + whereClause.ToString() + + " ) AS [t3]" + + " WHERE [t3].[ROW_NUMBER] BETWEEN {0} + 1 AND {0} + {1}" + + " ORDER BY [t3].[ROW_NUMBER]"; + } + else + { + // OFFSET... FETCH NEXT requires SQL Server 2012 or SQL CE 4 + sql = + "SELECT [t3].[Id], [t3].[Name], [t3].[SKU], [t3].[ProductTypeId], [t3].[value] AS [Taxonomy], [t3].[value2] AS [Gender], [t3].[value3] AS [AgeGroup], [t3].[value4] AS [Color], [t3].[value5] AS [Size], [t3].[value6] AS [Material], [t3].[value7] AS [Pattern], [t3].[value8] AS [Export]" + + " FROM (" + + " SELECT [t2].[Id], [t2].[Name], [t2].[SKU], [t2].[ProductTypeId], [t2].[value], [t2].[value2], [t2].[value3], [t2].[value4], [t2].[value5], [t2].[value6], [t2].[value7], [t2].[value8]" + + " FROM (" + + " SELECT [t0].[Id], [t0].[Name], [t0].[SKU], [t0].[ProductTypeId], [t1].[Taxonomy] AS [value], [t1].[Gender] AS [value2], [t1].[AgeGroup] AS [value3], [t1].[Color] AS [value4], [t1].[Size] AS [value5], [t1].[Material] AS [value6], [t1].[Pattern] AS [value7], COALESCE([t1].[Export],1) AS [value8], [t0].[Deleted], [t0].[VisibleIndividually], [t1].[IsTouched]" + + " FROM [Product] AS [t0]" + + " LEFT OUTER JOIN [GoogleProduct] AS [t1] ON [t0].[Id] = [t1].[ProductId]" + + " ) AS [t2]" + + " WHERE " + whereClause.ToString() + + " ) AS [t3]" + + " ORDER BY [t3].[Name]" + + " OFFSET {0} ROWS FETCH NEXT {1} ROWS ONLY"; + } var data = _gpRepository.Context.SqlQuery(sql, (command.Page - 1) * command.PageSize, command.PageSize).ToList(); @@ -611,6 +634,18 @@ public GridModel GetGridModel(GridCommand command, string se model.Data = data; model.Total = (data.Count > 0 ? data.First().TotalCount : 0); + if (data.Count > 0) + { + if (isSqlServer) + model.Total = data.First().TotalCount; + else + model.Total = _gpRepository.Context.SqlQuery("Select Count(*) From [Product] As [t2] Where " + whereClause.ToString()).FirstOrDefault(); + } + else + { + model.Total = 0; + } + return model; #region old code diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/changelog.md b/src/Plugins/SmartStore.GoogleMerchantCenter/changelog.md index 5b2fb699b8..550a335079 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/changelog.md +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/changelog.md @@ -1,5 +1,9 @@ #Release Notes# +##Google Merchant Center (GMC) 2.2.0.2## +###Improvements +* Supporting of paged google-product data query for SQL-Server Compact Edition + ##Google Merchant Center (GMC) 2.2.0.1## ###New Features * #582 Option to include\exclude a product From 25927b40742d85bf021c6fa3bc198088ed6e9ccc Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 23 Jun 2015 13:57:44 +0200 Subject: [PATCH 0167/1256] Closes #620 Products can be accessed by search or new products section when category is subject to ACL or just one store --- .../201506181858349_AclRecordCustomerRole.cs | 47 ++++- .../Catalog/CategoryService.cs | 195 +++++++++++++++++- .../Catalog/ICategoryService.cs | 25 +++ .../Catalog/IProductAttributeService.cs | 1 - .../Controllers/CategoryController.cs | 22 +- .../Views/Category/_CreateOrUpdate.cshtml | 60 ++++-- .../Controllers/PrivateMessagesController.cs | 2 - 7 files changed, 332 insertions(+), 20 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs index 1528793d5c..c04b8f50cf 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs @@ -2,8 +2,9 @@ namespace SmartStore.Data.Migrations { using System; using System.Data.Entity.Migrations; - - public partial class AclRecordCustomerRole : DbMigration + using SmartStore.Data.Setup; + + public partial class AclRecordCustomerRole : DbMigration, ILocaleResourcesProvider, IDataSeeder { public override void Up() { @@ -16,5 +17,47 @@ public override void Down() DropForeignKey("dbo.AclRecord", "CustomerRoleId", "dbo.CustomerRole"); DropIndex("dbo.AclRecord", new[] { "CustomerRoleId" }); } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Admin.Configuration.Category.Acl.AssignToSubCategoriesAndProducts", + "Assign this ACL configuration to all subcategories and products included in this category", + "Diese Konfiguration fr alle Unterwarengruppen und Produkte bernehmen"); + + builder.AddOrUpdate("Admin.Configuration.Category.Acl.AssignToSubCategoriesAndProducts.Hint", + @"Please keep in mind you have to save changes in the ACL configuration
+ before you can assign them to all subcategories and products.
+ Attention: Please keep in mind that existing acl records will be deleted", + @"Bitte beachten Sie, dass die nderungen der Zugriffsrechte zunchst gespeichert werden mssen,
+ bevor diese fr Unterkategorien und Produkte bernommen werden knnen.
+ Vorsicht: Bitte beachten Sie, dass vorhandene Zugriffsrechte berschrieben bzw. gelscht werden."); + + builder.AddOrUpdate("Admin.Configuration.Category.Stores.AssignToSubCategoriesAndProducts", + "Assign this store configuration to all subcategories and products included in this category", + "Diese Konfiguration fr alle Unterwarengruppen und Produkte bernehmen"); + + builder.AddOrUpdate("Admin.Configuration.Category.Stores.AssignToSubCategoriesAndProducts.Hint", + @"Please keep in mind you have to save changes in the store configuration
+ before you can assign them to all subcategories and products.
+ Attention: Please keep in mind that existing store mappings will be deleted", + @"Bitte beachten Sie, dass die nderungen an der Store-Konfiguration zunchst gespeichert werden mssen,
+ bevor diese fr Unterkategorien und Produkte bernommen werden knnen.
+ Vorsicht: Bitte beachten Sie, dass vorhandene Store-Konfiguration berschrieben bzw. gelscht werden."); + + builder.AddOrUpdate("Admin.Configuration.Acl.NoRolesDefined", + "No customer roles defined", + "Es sind keine Kundengruppen definiert"); + + } } } diff --git a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs index d563031d2b..8ccec2ade1 100644 --- a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs @@ -8,6 +8,7 @@ using SmartStore.Core.Domain.Security; using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; +using SmartStore.Services.Customers; using SmartStore.Services.Localization; using SmartStore.Services.Security; using SmartStore.Services.Stores; @@ -44,7 +45,10 @@ public partial class CategoryService : ICategoryService private readonly IStoreMappingService _storeMappingService; private readonly IAclService _aclService; private readonly Lazy> _navigationFilters; - + private readonly ICustomerService _customerService; + private readonly IProductService _productService; + private readonly IStoreService _storeService; + #endregion #region Ctor @@ -72,7 +76,10 @@ public CategoryService(ICacheManager cacheManager, IEventPublisher eventPublisher, IStoreMappingService storeMappingService, IAclService aclService, - Lazy> navigationFilters) + Lazy> navigationFilters, + ICustomerService customerService, + IProductService productService, + IStoreService storeService) { this._cacheManager = cacheManager; this._categoryRepository = categoryRepository; @@ -86,6 +93,9 @@ public CategoryService(ICacheManager cacheManager, this._storeMappingService = storeMappingService; this._aclService = aclService; this._navigationFilters = navigationFilters; + this._customerService = customerService; + this._productService = productService; + this._storeService = storeService; this.QuerySettings = DbQuerySettings.Default; } @@ -116,6 +126,187 @@ private void DeleteAllCategories(IList categories, bool delete) #region Methods + /// + /// Assign acl to sub categories and products + /// + /// Category Id + /// Whether to assign acl's to products which are contained in multiple categories. + /// Whether to delete existing Acls. + /// Whether to assign acl's only to categories. + public virtual void AssignAclToSubCategoriesAndProducts(int categoryId, + bool touchProductsWithMultipleCategories = false, + bool touchExistingAcls = false, + bool categoriesOnly = false) + { + + var category = GetCategoryById(categoryId); + var subcategories = GetAllCategoriesByParentCategoryId(categoryId, true); + var context = new ProductSearchContext { PageSize = int.MaxValue, ShowHidden = true }; + context.CategoryIds.AddRange(subcategories.Select(x => x.Id)); + context.CategoryIds.Add(categoryId); + var products = _productService.SearchProducts(context); + var allCustomerRoles = _customerService.GetAllCustomerRoles(true); + var categoryCustomerRoles = _aclService.GetCustomerRoleIdsWithAccess(category); + + using (var scope = new DbContextScope(ctx: _aclRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false)) + { + _aclRepository.AutoCommitEnabled = false; + + foreach (var subcategory in subcategories) + { + if (subcategory.SubjectToAcl != category.SubjectToAcl) + { + subcategory.SubjectToAcl = category.SubjectToAcl; + _categoryRepository.Update(subcategory); + } + + var existingAclRecords = _aclService.GetAclRecords(subcategory).ToDictionary(x => x.CustomerRoleId); + + foreach (var customerRole in allCustomerRoles) + { + if (categoryCustomerRoles.Contains(customerRole.Id)) + { + if (!existingAclRecords.ContainsKey(customerRole.Id)) + { + _aclRepository.Insert(new AclRecord { CustomerRole = customerRole, CustomerRoleId = customerRole.Id, EntityId = subcategory.Id, EntityName = "Category" }); + } + } + else + { + AclRecord aclRecordToDelete; + if (existingAclRecords.TryGetValue(customerRole.Id, out aclRecordToDelete)) + { + _aclRepository.Delete(aclRecordToDelete); + } + } + } + } + + foreach (var product in products) + { + if (product.SubjectToAcl != category.SubjectToAcl) + { + product.SubjectToAcl = category.SubjectToAcl; + _productRepository.Update(product); + } + + var existingAclRecords = _aclService.GetAclRecords(product).ToDictionary(x => x.CustomerRoleId); + + foreach (var customerRole in allCustomerRoles) + { + if (categoryCustomerRoles.Contains(customerRole.Id)) + { + if (!existingAclRecords.ContainsKey(customerRole.Id)) + { + _aclRepository.Insert(new AclRecord { CustomerRole = customerRole, CustomerRoleId = customerRole.Id, EntityId = product.Id, EntityName = "Product" }); + } + } + else + { + AclRecord aclRecordToDelete; + if (existingAclRecords.TryGetValue(customerRole.Id, out aclRecordToDelete)) + { + _aclRepository.Delete(aclRecordToDelete); + } + } + } + } + + _aclRepository.Context.SaveChanges(); + } + } + + /// + /// Assign stores to sub categories and products + /// + /// Category Id + /// Whether to assign stores to products which are contained in multiple categories. + /// Whether to delete existing store assingments. + /// Whether to assign store only to categories. + public virtual void AssignStoresToSubCategoriesAndProducts(int categoryId, + bool touchProductsWithMultipleCategories = false, + bool touchExistingAcls = false, + bool categoriesOnly = false) + { + + var category = GetCategoryById(categoryId); + var subcategories = GetAllCategoriesByParentCategoryId(categoryId, true); + var context = new ProductSearchContext { PageSize = int.MaxValue , ShowHidden = true }; + context.CategoryIds.AddRange(subcategories.Select(x => x.Id)); + context.CategoryIds.Add(categoryId); + var products = _productService.SearchProducts(context); + + var allStores = _storeService.GetAllStores(); + var categoryStoreMappings = _storeMappingService.GetStoresIdsWithAccess(category); + + using (var scope = new DbContextScope(ctx: _storeMappingRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false)) + { + _storeMappingRepository.AutoCommitEnabled = false; + + foreach (var subcategory in subcategories) + { + if (subcategory.LimitedToStores != category.LimitedToStores) + { + subcategory.LimitedToStores = category.LimitedToStores; + _categoryRepository.Update(subcategory); + } + + var existingStoreMappingsRecords = _storeMappingService.GetStoreMappings(subcategory).ToDictionary(x => x.StoreId); + + foreach (var store in allStores) + { + if (categoryStoreMappings.Contains(store.Id)) + { + if (!existingStoreMappingsRecords.ContainsKey(store.Id)) + { + _storeMappingRepository.Insert(new StoreMapping { StoreId = store.Id, EntityId = subcategory.Id, EntityName = "Category" }); + } + } + else + { + StoreMapping storeMappingToDelete; + if (existingStoreMappingsRecords.TryGetValue(store.Id, out storeMappingToDelete)) + { + _storeMappingRepository.Delete(storeMappingToDelete); + } + } + } + } + + foreach (var product in products) + { + if (product.LimitedToStores != category.LimitedToStores) + { + product.LimitedToStores = category.LimitedToStores; + _productRepository.Update(product); + } + + var existingStoreMappingsRecords = _storeMappingService.GetStoreMappings(product).ToDictionary(x => x.StoreId); + + foreach (var store in allStores) + { + if (categoryStoreMappings.Contains(store.Id)) + { + if (!existingStoreMappingsRecords.ContainsKey(store.Id)) + { + _storeMappingRepository.Insert(new StoreMapping { StoreId = store.Id, EntityId = product.Id, EntityName = "Product" }); + } + } + else + { + StoreMapping storeMappingToDelete; + if (existingStoreMappingsRecords.TryGetValue(store.Id, out storeMappingToDelete)) + { + _storeMappingRepository.Delete(storeMappingToDelete); + } + } + } + } + + _storeMappingRepository.Context.SaveChanges(); + } + } + /// /// Delete category /// diff --git a/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs index 6b7650d69b..77548a3f95 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs @@ -10,6 +10,31 @@ namespace SmartStore.Services.Catalog ///
public partial interface ICategoryService { + + /// + /// Assign acl to sub-categories and products + /// + /// Category Id + /// Whether to assign acl's to products which are contained in multiple categories. + /// Whether to delete existing Acls. + /// Whether to assign acl's only to categories. + void AssignAclToSubCategoriesAndProducts(int categoryId, + bool touchProductsWithMultipleCategories = false, + bool touchExistingAcls = false, + bool categoriesOnly = false); + + /// + /// Assign stores to sub-categories and products + /// + /// Category Id + /// Whether to assign acl's to products which are contained in multiple categories. + /// Whether to delete existing Acls. + /// Whether to assign acl's only to categories. + void AssignStoresToSubCategoriesAndProducts(int categoryId, + bool touchProductsWithMultipleCategories = false, + bool touchExistingAcls = false, + bool categoriesOnly = false); + /// /// Delete category /// diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs index c23e5de26e..da1cf6b287 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs @@ -66,7 +66,6 @@ public partial interface IProductAttributeService /// Product variant attribute mapping ProductVariantAttribute GetProductVariantAttributeById(int productVariantAttributeId); - // codehint: sm-add /// /// Gets multiple product variant attribute mappings by their keys /// diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs index ceda143ff6..53b839fbdd 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Catalog; @@ -15,6 +16,7 @@ using SmartStore.Services.Customers; using SmartStore.Services.Discounts; using SmartStore.Services.ExportImport; +using SmartStore.Services.Filter; using SmartStore.Services.Helpers; using SmartStore.Services.Localization; using SmartStore.Services.Media; @@ -56,6 +58,7 @@ public partial class CategoryController : AdminControllerBase private readonly AdminAreaSettings _adminAreaSettings; private readonly CatalogSettings _catalogSettings; private readonly IEventPublisher _eventPublisher; + private readonly IFilterService _filterService; #endregion @@ -73,7 +76,7 @@ public CategoryController(ICategoryService categoryService, ICategoryTemplateSer IDateTimeHelper dateTimeHelper, AdminAreaSettings adminAreaSettings, CatalogSettings catalogSettings, - IEventPublisher eventPublisher) + IEventPublisher eventPublisher, IFilterService filterService) { this._categoryService = categoryService; this._categoryTemplateService = categoryTemplateService; @@ -97,6 +100,7 @@ public CategoryController(ICategoryService categoryService, ICategoryTemplateSer this._adminAreaSettings = adminAreaSettings; this._catalogSettings = catalogSettings; this._eventPublisher = eventPublisher; + this._filterService = filterService; } #endregion @@ -713,6 +717,22 @@ public ActionResult Edit(CategoryModel model, bool continueEditing, FormCollecti return View(model); } + [ValidateInput(false)] + public ActionResult AssignAclToSubCategoriesAndProducts(int categoryId) + { + _categoryService.AssignAclToSubCategoriesAndProducts(categoryId, false, true, false ); + + return RedirectToAction("Edit", "Category", new { id = categoryId }); + } + + [ValidateInput(false)] + public ActionResult AssignStoresToSubCategoriesAndProducts(int categoryId) + { + _categoryService.AssignStoresToSubCategoriesAndProducts(categoryId, false, true, false); + + return RedirectToAction("Edit", "Category", new { id = categoryId }); + } + [HttpPost] public ActionResult Delete(int id, string deleteType) { diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml index dc94281687..5c41d2f6ee 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml @@ -436,10 +436,10 @@ function toggleAcl() { if ($('#@Html.FieldIdFor(model => model.SubjectToAcl)').is(':checked')) { - $('#pnl-acl').show(); + $('.pnl-acl').show(); } else { - $('#pnl-acl').hide(); + $('.pnl-acl').hide(); } } @@ -454,7 +454,7 @@ @Html.ValidationMessageFor(model => model.SubjectToAcl)
@Html.SmartLabelFor(model => model.AvailableCustomerRoles)

+   + +
+ @T("Admin.Configuration.Category.Acl.AssignToSubCategoriesAndProducts.Hint") +
+ +   + @T("Admin.Configuration.Category.Acl.AssignToSubCategoriesAndProducts") + +
} @@ -488,10 +507,10 @@ function toggleStoreMapping() { if ($('#@Html.FieldIdFor(model => model.LimitedToStores)').is(':checked')) { - $('#pnl-available-stores').show(); + $('.pnl-available-stores').show(); } else { - $('#pnl-available-stores').hide(); + $('.pnl-available-stores').hide(); } } @@ -506,7 +525,7 @@ @Html.ValidationMessageFor(model => model.LimitedToStores)
@Html.SmartLabelFor(model => model.AvailableStores)

+   + +
+ @T("Admin.Configuration.Category.Stores.AssignToSubCategoriesAndProducts.Hint") +
+ +   + @T("Admin.Configuration.Category.Stores.AssignToSubCategoriesAndProducts") + +
} diff --git a/src/Presentation/SmartStore.Web/Controllers/PrivateMessagesController.cs b/src/Presentation/SmartStore.Web/Controllers/PrivateMessagesController.cs index e2886f2bc0..878f691f3d 100644 --- a/src/Presentation/SmartStore.Web/Controllers/PrivateMessagesController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/PrivateMessagesController.cs @@ -192,13 +192,11 @@ public ActionResult SentItems(int page, string tab) }); } - // codehint: sm-edit ViewData["PagerRouteValues"] = new PrivateMessageRouteValues { page = page, tab = tab }; var model = new PrivateMessageListModel(list) { Messages = sentItems - // codehint: sm-delete }; return PartialView(model); From be90cf52fd3fa4cf785b3ed946359915f17996b3 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 23 Jun 2015 15:44:00 +0200 Subject: [PATCH 0168/1256] GMC: Updates SQL query statement for SQL Server CE --- .../Services/GoogleFeedService.cs | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs b/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs index 1b1d047b26..c5b6812ee9 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs @@ -573,6 +573,7 @@ public GridModel GetGridModel(GridCommand command, string se } string sql = null; + string sqlCount = null; var isSqlServer = DataSettings.Current.IsSqlServer; if (isSqlServer) @@ -596,18 +597,24 @@ public GridModel GetGridModel(GridCommand command, string se { // OFFSET... FETCH NEXT requires SQL Server 2012 or SQL CE 4 sql = - "SELECT [t3].[Id], [t3].[Name], [t3].[SKU], [t3].[ProductTypeId], [t3].[value] AS [Taxonomy], [t3].[value2] AS [Gender], [t3].[value3] AS [AgeGroup], [t3].[value4] AS [Color], [t3].[value5] AS [Size], [t3].[value6] AS [Material], [t3].[value7] AS [Pattern], [t3].[value8] AS [Export]" + + "SELECT [t2].[Id], [t2].[Name], [t2].[SKU], [t2].[ProductTypeId], [t2].[value] AS [Taxonomy], [t2].[value2] AS [Gender], [t2].[value3] AS [AgeGroup], [t2].[value4] AS [Color], [t2].[value5] AS [Size], [t2].[value6] AS [Material], [t2].[value7] AS [Pattern], [t2].[value8] AS [Export]" + " FROM (" + - " SELECT [t2].[Id], [t2].[Name], [t2].[SKU], [t2].[ProductTypeId], [t2].[value], [t2].[value2], [t2].[value3], [t2].[value4], [t2].[value5], [t2].[value6], [t2].[value7], [t2].[value8]" + - " FROM (" + - " SELECT [t0].[Id], [t0].[Name], [t0].[SKU], [t0].[ProductTypeId], [t1].[Taxonomy] AS [value], [t1].[Gender] AS [value2], [t1].[AgeGroup] AS [value3], [t1].[Color] AS [value4], [t1].[Size] AS [value5], [t1].[Material] AS [value6], [t1].[Pattern] AS [value7], COALESCE([t1].[Export],1) AS [value8], [t0].[Deleted], [t0].[VisibleIndividually], [t1].[IsTouched]" + - " FROM [Product] AS [t0]" + - " LEFT OUTER JOIN [GoogleProduct] AS [t1] ON [t0].[Id] = [t1].[ProductId]" + - " ) AS [t2]" + - " WHERE " + whereClause.ToString() + - " ) AS [t3]" + - " ORDER BY [t3].[Name]" + + " SELECT [t0].[Id], [t0].[Name], [t0].[SKU], [t0].[ProductTypeId], [t1].[Taxonomy] AS [value], [t1].[Gender] AS [value2], [t1].[AgeGroup] AS [value3], [t1].[Color] AS [value4], [t1].[Size] AS [value5], [t1].[Material] AS [value6], [t1].[Pattern] AS [value7], COALESCE([t1].[Export],1) AS [value8], [t0].[Deleted], [t0].[VisibleIndividually], [t1].[IsTouched] AS [IsTouched]" + + " FROM [Product] AS [t0]" + + " LEFT OUTER JOIN [GoogleProduct] AS [t1] ON [t0].[Id] = [t1].[ProductId]" + + " ) AS [t2]" + + " WHERE " + whereClause.ToString() + + " ORDER BY [t2].[Name]" + " OFFSET {0} ROWS FETCH NEXT {1} ROWS ONLY"; + + sqlCount = + "SELECT COUNT(*)" + + " FROM (" + + " SELECT [t0].[Id], [t0].[Name], [t0].[Deleted], [t0].[VisibleIndividually], [t1].[IsTouched] AS [IsTouched]" + + " FROM [Product] AS [t0]" + + " LEFT OUTER JOIN [GoogleProduct] AS [t1] ON [t0].[Id] = [t1].[ProductId]" + + " ) AS [t2]" + + " WHERE " + whereClause.ToString(); } @@ -639,7 +646,7 @@ public GridModel GetGridModel(GridCommand command, string se if (isSqlServer) model.Total = data.First().TotalCount; else - model.Total = _gpRepository.Context.SqlQuery("Select Count(*) From [Product] As [t2] Where " + whereClause.ToString()).FirstOrDefault(); + model.Total = _gpRepository.Context.SqlQuery(sqlCount).FirstOrDefault(); } else { From 60736d649f200399fb6849ac782df1472251e030 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 23 Jun 2015 20:09:03 +0200 Subject: [PATCH 0169/1256] Updated changelog --- changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.md b/changelog.md index 2ef9701964..c3d2d7762e 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,8 @@ * #67 Restrict payment methods to certain countries * #94 Restrict payment methods to certain shipping methods * #526 Min\max amount option for which the payment method should be offered during checkout +* #718 ShopConnector: Import option for "Published" and "Disable buy\wishlist button" + ## SmartStore.NET 2.2.2 From fd2b1f799548470ef8df420eae4248ee32443b92 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 24 Jun 2015 11:18:38 +0200 Subject: [PATCH 0170/1256] Resolves #705 Methods like PasswordRecoveryConfirm should not make home page redirects without any notification --- ...06211043073_PaymentShippingRestrictions.cs | 4 +++ .../Controllers/SmartController.cs | 22 +++++++------ .../Controllers/CustomerController.cs | 31 +++++++++---------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs index bd0333f18d..99a1467c9d 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs @@ -52,6 +52,10 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Restrictions", "Einschrnkungen"); + builder.AddOrUpdate("Common.RequestProcessingFailed", + "The request could not be processed.
Controller: {0}, Action: {1}, Reason: {2}.", + "Die Anfrage konnte nicht ausgefhrt werden.
Controller: {0}, Action: {1}, Grund: {2}."); + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.RestrictionNote", "Select customer roles, shipping methods, countries and order amounts for which you do not want to offer this payment method.", "Whlen Sie Kundengruppen, Versandarten, Lnder und Bestellwerte, bei denen Sie diese Zahlungsmethode nicht anbieten mchten."); diff --git a/src/Presentation/SmartStore.Web.Framework/Controllers/SmartController.cs b/src/Presentation/SmartStore.Web.Framework/Controllers/SmartController.cs index 455f4c5e8a..5e69151979 100644 --- a/src/Presentation/SmartStore.Web.Framework/Controllers/SmartController.cs +++ b/src/Presentation/SmartStore.Web.Framework/Controllers/SmartController.cs @@ -1,16 +1,9 @@ using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -using System.Web; using System.Web.Mvc; -using System.Web.Routing; using SmartStore.Core; using SmartStore.Core.Infrastructure; +using SmartStore.Core.Localization; using SmartStore.Core.Logging; -using SmartStore.Web.Framework.Controllers; -using SmartStore.Web.Framework.Security; -using SmartStore.Web.Framework.UI; namespace SmartStore.Web.Framework.Controllers { @@ -23,11 +16,13 @@ public abstract partial class SmartController : Controller protected SmartController() { this.Logger = NullLogger.Instance; + this.T = NullLocalizer.Instance; + this._notifier = EngineContext.Current.Resolve>(); } - public ILogger Logger { get; set; } + public Localizer T { get; set; } /// /// Pushes an info message to the notification queue @@ -95,6 +90,15 @@ protected virtual ActionResult RedirectToReferrer() return RedirectToRoute("HomePage"); } + protected virtual ActionResult RedirectToHomePageWithError(string reason, bool durable = true) + { + string message = T("Common.RequestProcessingFailed", this.RouteData.Values["controller"], this.RouteData.Values["action"], reason.NaIfEmpty()); + + _notifier.Value.Error(message, durable); + + return RedirectToRoute("HomePage"); + } + /// /// On exception /// diff --git a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs index 52d7118d68..c070f2dd37 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs @@ -1,18 +1,17 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using SmartStore.Core; using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Customers; -using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Forums; using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Messages; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Tax; +using SmartStore.Core.Logging; using SmartStore.Services.Authentication; using SmartStore.Services.Authentication.External; using SmartStore.Services.Catalog; @@ -27,14 +26,13 @@ using SmartStore.Services.Orders; using SmartStore.Services.Seo; using SmartStore.Services.Tax; +using SmartStore.Utilities; using SmartStore.Web.Framework.Controllers; +using SmartStore.Web.Framework.Plugins; using SmartStore.Web.Framework.Security; using SmartStore.Web.Framework.UI.Captcha; using SmartStore.Web.Models.Common; using SmartStore.Web.Models.Customer; -using SmartStore.Core.Logging; -using SmartStore.Web.Framework.Plugins; -using SmartStore.Utilities; namespace SmartStore.Web.Controllers { @@ -393,7 +391,6 @@ public ActionResult Login(bool? checkoutAsGuest) model.CheckoutAsGuest = checkoutAsGuest.HasValue ? checkoutAsGuest.Value : false; model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnLoginPage; - // codehint: sm-add if (_customerSettings.PrefillLoginUsername.HasValue()) { if (model.UsernamesEnabled) @@ -875,14 +872,14 @@ public ActionResult AccountActivation(string token, string email) { var customer = _customerService.GetCustomerByEmail(email); if (customer == null) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Email"); var cToken = customer.GetAttribute(SystemCustomerAttributeNames.AccountActivationToken); if (String.IsNullOrEmpty(cToken)) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Token"); if (!cToken.Equals(token, StringComparison.InvariantCultureIgnoreCase)) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Token"); //activate user account customer.Active = true; @@ -1381,11 +1378,11 @@ public ActionResult UserAgreement(Guid id /* orderItemId */) var orderItem = _orderService.GetOrderItemByGuid(id); if (orderItem == null) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Guid"); var product = orderItem.Product; if (product == null || !product.HasUserAgreement) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Product"); var model = new UserAgreementModel(); model.UserAgreementText = product.UserAgreementText; @@ -1637,14 +1634,14 @@ public ActionResult PasswordRecoveryConfirm(string token, string email) { var customer = _customerService.GetCustomerByEmail(email); if (customer == null ) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Email"); var cPrt = customer.GetAttribute(SystemCustomerAttributeNames.PasswordRecoveryToken); if (String.IsNullOrEmpty(cPrt)) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Token"); if (!cPrt.Equals(token, StringComparison.InvariantCultureIgnoreCase)) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Token"); var model = new PasswordRecoveryConfirmModel(); return View(model); @@ -1656,14 +1653,14 @@ public ActionResult PasswordRecoveryConfirmPOST(string token, string email, Pass { var customer = _customerService.GetCustomerByEmail(email); if (customer == null) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Email"); var cPrt = customer.GetAttribute(SystemCustomerAttributeNames.PasswordRecoveryToken); if (String.IsNullOrEmpty(cPrt)) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Token"); if (!cPrt.Equals(token, StringComparison.InvariantCultureIgnoreCase)) - return RedirectToRoute("HomePage"); + return RedirectToHomePageWithError("Token"); if (ModelState.IsValid) { From 14f5b593fc37356f751822565be5e4eabd90663b Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Wed, 24 Jun 2015 12:41:11 +0200 Subject: [PATCH 0171/1256] Renamed functions of last commit and other minor changes --- .../Domain/Customers/CustomerRole.cs | 1 - .../Customers/SystemCustomerRoleNames.cs | 1 - .../Domain/Media/PictureType.cs | 1 - .../SmartStore.Core/Domain/Orders/Order.cs | 1 - .../Domain/Orders/ShoppingCartSettings.cs | 1 - .../Domain/StoreInformationSettings.cs | 2 -- .../201506181858349_AclRecordCustomerRole.cs | 22 +++++++++------- .../Catalog/CategoryService.cs | 24 ++++++------------ .../Catalog/ICategoryService.cs | 16 ++++++------ .../Catalog/IProductAttributeService.cs | 1 - .../Catalog/ISpecificationAttributeService.cs | 1 - .../Catalog/ProductAttributeParser.cs | 2 -- .../Catalog/ProductAttributeService.cs | 4 --- .../Catalog/SpecificationAttributeService.cs | 3 +-- .../Common/AddressService.cs | 1 - .../Common/IAddressService.cs | 1 - .../Configuration/SettingService.cs | 2 -- .../Filter/FilterOperator.cs | 1 - .../Messages/MessageTokenProvider.cs | 8 ------ .../Mvc/Bundles/BundlePublisher.cs | 3 --- .../Mvc/Bundles/IBundlePublisher.cs | 3 --- .../UI/DataListExtensions.cs | 2 -- .../Controllers/CategoryController.cs | 8 +++--- .../Controllers/CountryController.cs | 1 - .../Controllers/CustomerRoleController.cs | 1 - .../Models/Catalog/ProductModel.cs | 3 +-- .../Models/Common/MaintenanceModel.cs | 3 --- .../Models/Settings/MediaSettingsModel.cs | 3 +-- .../Views/Category/_CreateOrUpdate.cshtml | 4 +-- .../Views/Language/_CreateOrUpdate.cshtml | 1 - .../Views/Setting/AllSettings.cshtml | 1 - .../Controllers/CustomerController.cs | 1 - .../Controllers/InstallController.cs | 3 +-- .../Controllers/NewsController.cs | 2 +- .../Controllers/PrivateMessagesController.cs | 2 -- .../Controllers/ProfileController.cs | 2 -- .../Cache/ModelCacheEventConsumer.cs | 2 +- .../Models/Blogs/BlogPagingFilteringModel.cs | 4 +-- .../Models/Blogs/BlogPostModel.cs | 1 - .../Catalog/CatalogPagingFilteringModel.cs | 2 +- .../Models/Catalog/PagingFilteringModel.cs | 6 +---- .../Models/Catalog/ProductDetailsModel.cs | 2 -- .../Catalog/SearchPagingFilteringModel.cs | 6 ++--- .../Models/Common/CurrencyModel.cs | 2 -- .../Models/Common/PagerModel.cs | 2 -- .../Models/Install/InstallModel.cs | 1 - .../Models/Media/PictureModel.cs | 3 +-- .../Models/News/NewsItemModel.cs | 1 - .../Models/News/NewsPagingFilteringModel.cs | 2 -- .../RecentlyViewedProductsBlock.cshtml | 3 +-- .../Views/Customer/Addresses.cshtml | 2 -- .../Views/Home/ContactUs.cshtml | 3 +-- .../SmartStore.Web/Views/Poll/_Poll.cshtml | 2 -- .../Views/Product/ProductManufacturers.cshtml | 25 ++++++------------- .../Views/Product/ProductTags.cshtml | 2 -- .../Views/Product/RelatedProducts.cshtml | 3 +-- .../Views/ShoppingCart/EmailWishlist.cshtml | 2 -- 57 files changed, 56 insertions(+), 156 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Domain/Customers/CustomerRole.cs b/src/Libraries/SmartStore.Core/Domain/Customers/CustomerRole.cs index 7c6bddf03c..6d3b2003e8 100644 --- a/src/Libraries/SmartStore.Core/Domain/Customers/CustomerRole.cs +++ b/src/Libraries/SmartStore.Core/Domain/Customers/CustomerRole.cs @@ -26,7 +26,6 @@ public partial class CustomerRole : BaseEntity /// public bool TaxExempt { get; set; } - /// codehint: sm-add /// /// Gets or sets the tax display type /// diff --git a/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerRoleNames.cs b/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerRoleNames.cs index 760d14d9be..214fd18191 100644 --- a/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerRoleNames.cs +++ b/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerRoleNames.cs @@ -3,7 +3,6 @@ namespace SmartStore.Core.Domain.Customers { public static partial class SystemCustomerRoleNames { - /// codehint: sm-add public static string SuperAdministrators { get { return "SuperAdmins"; } } public static string Administrators { get { return "Administrators"; } } diff --git a/src/Libraries/SmartStore.Core/Domain/Media/PictureType.cs b/src/Libraries/SmartStore.Core/Domain/Media/PictureType.cs index 618b4f5052..8fdb9118df 100644 --- a/src/Libraries/SmartStore.Core/Domain/Media/PictureType.cs +++ b/src/Libraries/SmartStore.Core/Domain/Media/PictureType.cs @@ -15,7 +15,6 @@ public enum PictureType : int Avatar = 10, } - // codehint: sm-add public enum ThumbnailScaleMode { Auto, diff --git a/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs b/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs index a8fae7b574..b48ef9fcf6 100644 --- a/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs +++ b/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs @@ -320,7 +320,6 @@ protected virtual SortedDictionary ParseTaxRates(string taxRat ///
public string CardExpirationYear { get; set; } - /// codehint:sm-add begin /// /// Gets or sets a value indicating whether storing of credit card number is allowed /// diff --git a/src/Libraries/SmartStore.Core/Domain/Orders/ShoppingCartSettings.cs b/src/Libraries/SmartStore.Core/Domain/Orders/ShoppingCartSettings.cs index f96d5d35db..7398790f67 100644 --- a/src/Libraries/SmartStore.Core/Domain/Orders/ShoppingCartSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Orders/ShoppingCartSettings.cs @@ -132,7 +132,6 @@ public ShoppingCartSettings() /// public bool RoundPricesDuringCalculation { get; set; } - // codehint: sm-add /// /// Gets or sets a value indicating whether to show a legal hint in the order summary /// diff --git a/src/Libraries/SmartStore.Core/Domain/StoreInformationSettings.cs b/src/Libraries/SmartStore.Core/Domain/StoreInformationSettings.cs index 079e3831a1..b486b2acc3 100644 --- a/src/Libraries/SmartStore.Core/Domain/StoreInformationSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/StoreInformationSettings.cs @@ -19,8 +19,6 @@ public StoreInformationSettings() /// public bool StoreClosedAllowForAdmins { get; set; } - // codehint: sm-delete - /// /// Gets or sets a value indicating whether mini profiler should be displayed in public store (used for debugging) /// diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs index c04b8f50cf..2641ef6b47 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs @@ -31,26 +31,30 @@ public void Seed(SmartObjectContext context) public void MigrateLocaleResources(LocaleResourcesBuilder builder) { builder.AddOrUpdate("Admin.Configuration.Category.Acl.AssignToSubCategoriesAndProducts", - "Assign this ACL configuration to all subcategories and products included in this category", - "Diese Konfiguration fr alle Unterwarengruppen und Produkte bernehmen"); + "Transfer this ACL configuration to children", + "Diese Konfiguration fr Kindelemente bernehmen"); builder.AddOrUpdate("Admin.Configuration.Category.Acl.AssignToSubCategoriesAndProducts.Hint", - @"Please keep in mind you have to save changes in the ACL configuration
+ @"This function assigns the ACL configuration of this category to all subcategories and products included in this category.
+ Please keep in mind you have to save changes in the ACL configuration
before you can assign them to all subcategories and products.
- Attention: Please keep in mind that existing acl records will be deleted", - @"Bitte beachten Sie, dass die nderungen der Zugriffsrechte zunchst gespeichert werden mssen,
+ Attention: Please keep in mind that existing ACL records will be deleted", + @"Diese Funktion bernimmt die Zugriffsrecht-Konfiguration dieser Warengruppe fr alle Unterwarengruppen und Produkte.
+ Bitte beachten Sie, dass die nderungen der Zugriffsrechte zunchst gespeichert werden mssen,
bevor diese fr Unterkategorien und Produkte bernommen werden knnen.
Vorsicht: Bitte beachten Sie, dass vorhandene Zugriffsrechte berschrieben bzw. gelscht werden."); builder.AddOrUpdate("Admin.Configuration.Category.Stores.AssignToSubCategoriesAndProducts", - "Assign this store configuration to all subcategories and products included in this category", - "Diese Konfiguration fr alle Unterwarengruppen und Produkte bernehmen"); + "Transfer this store configuration to children", + "Diese Konfiguration fr Kindelemente bernehmen"); builder.AddOrUpdate("Admin.Configuration.Category.Stores.AssignToSubCategoriesAndProducts.Hint", - @"Please keep in mind you have to save changes in the store configuration
+ @"This function assigns the store configuration of this category to all subcategories and products included in this category.
+ Please keep in mind you have to save changes in the store configuration
before you can assign them to all subcategories and products.
Attention: Please keep in mind that existing store mappings will be deleted", - @"Bitte beachten Sie, dass die nderungen an der Store-Konfiguration zunchst gespeichert werden mssen,
+ @"Diese Funktion bernimmt die Shop-Konfiguration dieser Warengruppe fr alle Unterwarengruppen und Produkte.
+ Bitte beachten Sie, dass die nderungen an der Store-Konfiguration zunchst gespeichert werden mssen,
bevor diese fr Unterkategorien und Produkte bernommen werden knnen.
Vorsicht: Bitte beachten Sie, dass vorhandene Store-Konfiguration berschrieben bzw. gelscht werden."); diff --git a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs index 8ccec2ade1..f496feb5b4 100644 --- a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs @@ -126,14 +126,7 @@ private void DeleteAllCategories(IList categories, bool delete) #region Methods - /// - /// Assign acl to sub categories and products - /// - /// Category Id - /// Whether to assign acl's to products which are contained in multiple categories. - /// Whether to delete existing Acls. - /// Whether to assign acl's only to categories. - public virtual void AssignAclToSubCategoriesAndProducts(int categoryId, + public virtual void InheritAclIntoChildren(int categoryId, bool touchProductsWithMultipleCategories = false, bool touchExistingAcls = false, bool categoriesOnly = false) @@ -181,6 +174,8 @@ public virtual void AssignAclToSubCategoriesAndProducts(int categoryId, } } } + + _aclRepository.Context.SaveChanges(); foreach (var product in products) { @@ -215,15 +210,8 @@ public virtual void AssignAclToSubCategoriesAndProducts(int categoryId, _aclRepository.Context.SaveChanges(); } } - - /// - /// Assign stores to sub categories and products - /// - /// Category Id - /// Whether to assign stores to products which are contained in multiple categories. - /// Whether to delete existing store assingments. - /// Whether to assign store only to categories. - public virtual void AssignStoresToSubCategoriesAndProducts(int categoryId, + + public virtual void InheritStoresIntoChildren(int categoryId, bool touchProductsWithMultipleCategories = false, bool touchExistingAcls = false, bool categoriesOnly = false) @@ -273,6 +261,8 @@ public virtual void AssignStoresToSubCategoriesAndProducts(int categoryId, } } + _storeMappingRepository.Context.SaveChanges(); + foreach (var product in products) { if (product.LimitedToStores != category.LimitedToStores) diff --git a/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs index 77548a3f95..2942ed7276 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs @@ -15,10 +15,10 @@ public partial interface ICategoryService /// Assign acl to sub-categories and products /// /// Category Id - /// Whether to assign acl's to products which are contained in multiple categories. - /// Whether to delete existing Acls. - /// Whether to assign acl's only to categories. - void AssignAclToSubCategoriesAndProducts(int categoryId, + /// Reserved for future use: Whether to assign acl's to products which are contained in multiple categories. + /// Reserved for future use: Whether to delete existing Acls. + /// Reserved for future use: Whether to assign acl's only to categories. + void InheritAclIntoChildren(int categoryId, bool touchProductsWithMultipleCategories = false, bool touchExistingAcls = false, bool categoriesOnly = false); @@ -27,10 +27,10 @@ void AssignAclToSubCategoriesAndProducts(int categoryId, /// Assign stores to sub-categories and products /// /// Category Id - /// Whether to assign acl's to products which are contained in multiple categories. - /// Whether to delete existing Acls. - /// Whether to assign acl's only to categories. - void AssignStoresToSubCategoriesAndProducts(int categoryId, + /// Reserved for future use: Whether to assign acl's to products which are contained in multiple categories. + /// Reserved for future use: Whether to delete existing Acls. + /// Reserved for future use: Whether to assign acl's only to categories. + void InheritStoresIntoChildren(int categoryId, bool touchProductsWithMultipleCategories = false, bool touchExistingAcls = false, bool categoriesOnly = false); diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs index da1cf6b287..5a5a2f8616 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs @@ -109,7 +109,6 @@ public partial interface IProductAttributeService /// Product variant attribute value ProductVariantAttributeValue GetProductVariantAttributeValueById(int productVariantAttributeValueId); - // codehint: sm-add /// /// Gets multiple product variant attribute value /// diff --git a/src/Libraries/SmartStore.Services/Catalog/ISpecificationAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/ISpecificationAttributeService.cs index e0d765eb5b..e9bc4a786e 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ISpecificationAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ISpecificationAttributeService.cs @@ -131,7 +131,6 @@ IList GetProductSpecificationAttributesByProductI /// Product specification attribute mapping void UpdateProductSpecificationAttribute(ProductSpecificationAttribute productSpecificationAttribute); - /// codehint: sm-add void UpdateProductSpecificationMapping(int specificationAttributeId, string field, bool value); #endregion diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs index 1546a5e9d7..35b07ac42f 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs @@ -105,8 +105,6 @@ public virtual Multimap DeserializeProductVariantAttributes(string public virtual IList ParseProductVariantAttributes(string attributes) { var pvaCollection = new List(); - - // codehint: sm-edit var ids = ParseProductVariantAttributeIds(attributes); return this.ParseProductVariantAttributes(ids.ToList()).ToList(); } diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs index cda03df832..c7fc659823 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs @@ -234,7 +234,6 @@ public virtual ProductVariantAttribute GetProductVariantAttributeById(int produc }); } - // codehint: sm-add public virtual IEnumerable GetProductVariantAttributesByIds(params int[] ids) { if (ids == null || ids.Length == 0) @@ -245,7 +244,6 @@ public virtual IEnumerable GetProductVariantAttributesB return _productVariantAttributeRepository.GetMany(ids); } - // codehint: sm-add public virtual IEnumerable GetProductVariantAttributeValuesByIds(params int[] productVariantAttributeValueIds) { if (productVariantAttributeValueIds == null || productVariantAttributeValueIds.Length == 0) @@ -488,7 +486,6 @@ public virtual void InsertProductVariantAttributeCombination(ProductVariantAttri if (combination == null) throw new ArgumentNullException("combination"); - // codehint: sm-add //if (combination.IsDefaultCombination) //{ // EnsureSingleDefaultVariant(combination); @@ -509,7 +506,6 @@ public virtual void UpdateProductVariantAttributeCombination(ProductVariantAttri if (combination == null) throw new ArgumentNullException("combination"); - // codehint: sm-add //if (combination.IsDefaultCombination) //{ // EnsureSingleDefaultVariant(combination); diff --git a/src/Libraries/SmartStore.Services/Catalog/SpecificationAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/SpecificationAttributeService.cs index bb0bb7d806..cc146a0f5b 100644 --- a/src/Libraries/SmartStore.Services/Catalog/SpecificationAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/SpecificationAttributeService.cs @@ -113,7 +113,7 @@ public virtual void DeleteSpecificationAttribute(SpecificationAttribute specific if (specificationAttribute == null) throw new ArgumentNullException("specificationAttribute"); - // codehint: sm-add (delete localized properties of options) + // (delete localized properties of options) var options = GetSpecificationAttributeOptionsBySpecificationAttribute(specificationAttribute.Id); foreach (var itm in options) { DeleteSpecificationAttributeOption(itm); @@ -356,7 +356,6 @@ public virtual void UpdateProductSpecificationAttribute(ProductSpecificationAttr _eventPublisher.EntityUpdated(productSpecificationAttribute); } - /// codehint: sm-add public virtual void UpdateProductSpecificationMapping(int specificationAttributeId, string field, bool value) { if (specificationAttributeId == 0 || field.IsEmpty()) return; diff --git a/src/Libraries/SmartStore.Services/Common/AddressService.cs b/src/Libraries/SmartStore.Services/Common/AddressService.cs index 026b110713..29d705e13b 100644 --- a/src/Libraries/SmartStore.Services/Common/AddressService.cs +++ b/src/Libraries/SmartStore.Services/Common/AddressService.cs @@ -62,7 +62,6 @@ public virtual void DeleteAddress(Address address) _eventPublisher.EntityDeleted(address); } - /// codehint: sm-add public virtual void DeleteAddress(int id) { var address = GetAddressById(id); diff --git a/src/Libraries/SmartStore.Services/Common/IAddressService.cs b/src/Libraries/SmartStore.Services/Common/IAddressService.cs index 3aa5c9338c..e1fcde7e67 100644 --- a/src/Libraries/SmartStore.Services/Common/IAddressService.cs +++ b/src/Libraries/SmartStore.Services/Common/IAddressService.cs @@ -15,7 +15,6 @@ public partial interface IAddressService /// Address void DeleteAddress(Address address); - /// codehint: sm-add void DeleteAddress(int id); /// diff --git a/src/Libraries/SmartStore.Services/Configuration/SettingService.cs b/src/Libraries/SmartStore.Services/Configuration/SettingService.cs index c0c153badb..f9b7c7afe8 100644 --- a/src/Libraries/SmartStore.Services/Configuration/SettingService.cs +++ b/src/Libraries/SmartStore.Services/Configuration/SettingService.cs @@ -151,7 +151,6 @@ public virtual void UpdateSetting(Setting setting, bool clearCache = true) _eventPublisher.EntityUpdated(setting); } - /// codehint: sm-add private T LoadSettingsJson(int storeId = 0) { Type t = typeof(T); @@ -466,7 +465,6 @@ public virtual void SaveSetting(T settings, SetSetting(key, value ?? "", storeId, false); } - /// codehint: sm-add public virtual void UpdateSetting(T settings, Expression> keySelector, bool overrideForStore, int storeId = 0) where T : ISettings, new() { if (overrideForStore || storeId == 0) diff --git a/src/Libraries/SmartStore.Services/Filter/FilterOperator.cs b/src/Libraries/SmartStore.Services/Filter/FilterOperator.cs index 0e5dc79bf1..7ae4fe9609 100644 --- a/src/Libraries/SmartStore.Services/Filter/FilterOperator.cs +++ b/src/Libraries/SmartStore.Services/Filter/FilterOperator.cs @@ -7,7 +7,6 @@ namespace SmartStore.Services.Filter { - /// codehint: sm-add public sealed class FilterOperator { private const string _equal = "="; diff --git a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs index ea27f3092b..c91c6cf510 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs @@ -259,8 +259,6 @@ protected virtual string ProductListToHtmlTable(Order order, int languageId) if (!String.IsNullOrEmpty(order.CheckoutAttributeDescription)) { sb.AppendLine("
 "); - //codehint: sm-edit - //sb.AppendLine(order.CheckoutAttributeDescription); sb.AppendLine(HtmlUtils.ConvertPlainTextToTable(HtmlUtils.ConvertHtmlToPlainText(order.CheckoutAttributeDescription))); sb.AppendLine("
- @* codehint: sm-edit *@ @Html.DropDownListFor(x => x.LanguageCulture, cultures.Select(x => new SelectListItem { Value = x.IetfLanguageTag, Text = string.Format("{0} [{1}]", x.DisplayName, x.IetfLanguageTag) })) @Html.ValidationMessageFor(model => model.LanguageCulture) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/AllSettings.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/AllSettings.cshtml index b5ed46eae0..2ad6b7fb2e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/AllSettings.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/AllSettings.cshtml @@ -63,7 +63,6 @@ } function grid_onStoreEdit(e) { - @* codehint: sm-edit *@ $(e.form).find('#Store').select2('val', e.dataItem['StoreId']); } diff --git a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs index 52d7118d68..4f61b36436 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs @@ -393,7 +393,6 @@ public ActionResult Login(bool? checkoutAsGuest) model.CheckoutAsGuest = checkoutAsGuest.HasValue ? checkoutAsGuest.Value : false; model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnLoginPage; - // codehint: sm-add if (_customerSettings.PrefillLoginUsername.HasValue()) { if (model.UsernamesEnabled) diff --git a/src/Presentation/SmartStore.Web/Controllers/InstallController.cs b/src/Presentation/SmartStore.Web/Controllers/InstallController.cs index 844c3c36b9..1ed1d7d418 100644 --- a/src/Presentation/SmartStore.Web/Controllers/InstallController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/InstallController.cs @@ -146,7 +146,7 @@ protected string CreateDatabase(string connectionString, string collation) protected string CreateConnectionString( bool trustedConnection, string serverName, string databaseName, - string userName, string password, int timeout = 15 /* codehint: sm-edit (was 0) */) + string userName, string password, int timeout = 15) { var builder = new SqlConnectionStringBuilder(); builder.IntegratedSecurity = trustedConnection; @@ -160,7 +160,6 @@ protected string CreateConnectionString( builder.PersistSecurityInfo = false; //builder.MultipleActiveResultSets = true; - // codehint: sm-add builder.UserInstance = false; builder.Pooling = true; builder.MinPoolSize = 1; diff --git a/src/Presentation/SmartStore.Web/Controllers/NewsController.cs b/src/Presentation/SmartStore.Web/Controllers/NewsController.cs index ccc30b1c10..84d2ac0257 100644 --- a/src/Presentation/SmartStore.Web/Controllers/NewsController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/NewsController.cs @@ -110,7 +110,7 @@ protected void PrepareNewsItemModel(NewsItemModel model, NewsItem newsItem, bool model.Short = newsItem.Short; model.Full = newsItem.Full; model.AllowComments = newsItem.AllowComments; - model.AvatarPictureSize = _mediaSettings.AvatarPictureSize; // codehint: sm-add + model.AvatarPictureSize = _mediaSettings.AvatarPictureSize; model.CreatedOn = _dateTimeHelper.ConvertToUserTime(newsItem.CreatedOnUtc, DateTimeKind.Utc); model.NumberOfComments = newsItem.ApprovedCommentCount; model.AddNewComment.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnNewsCommentPage; diff --git a/src/Presentation/SmartStore.Web/Controllers/PrivateMessagesController.cs b/src/Presentation/SmartStore.Web/Controllers/PrivateMessagesController.cs index 878f691f3d..6d1f6ddcf2 100644 --- a/src/Presentation/SmartStore.Web/Controllers/PrivateMessagesController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/PrivateMessagesController.cs @@ -146,13 +146,11 @@ public ActionResult Inbox(int page, string tab) }); } - // codehint: sm-edit ViewData["PagerRouteValues"] = new PrivateMessageRouteValues { page = page, tab = tab }; var model = new PrivateMessageListModel(list) { Messages = inbox - // codehint: sm-delete }; return PartialView(model); diff --git a/src/Presentation/SmartStore.Web/Controllers/ProfileController.cs b/src/Presentation/SmartStore.Web/Controllers/ProfileController.cs index e9ab34b7b0..6f79a4ebcc 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ProfileController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ProfileController.cs @@ -240,12 +240,10 @@ public ActionResult Posts(int customerProfileId, int page) }); } - // codehint: sm-edit ViewData["PagerRouteValues"] = new RouteValues { page = page, id = customerProfileId }; var model = new ProfilePostsModel(list) { - // codehint: sm-delete Posts = latestPosts, }; diff --git a/src/Presentation/SmartStore.Web/Infrastructure/Cache/ModelCacheEventConsumer.cs b/src/Presentation/SmartStore.Web/Infrastructure/Cache/ModelCacheEventConsumer.cs index ce7362d2ec..652defa00a 100644 --- a/src/Presentation/SmartStore.Web/Infrastructure/Cache/ModelCacheEventConsumer.cs +++ b/src/Presentation/SmartStore.Web/Infrastructure/Cache/ModelCacheEventConsumer.cs @@ -40,7 +40,7 @@ public partial class ModelCacheEventConsumer: IConsumer>, IConsumer>, //categories - IConsumer>, // codehint: sm-add + IConsumer>, IConsumer>, IConsumer>, //product categories diff --git a/src/Presentation/SmartStore.Web/Models/Blogs/BlogPagingFilteringModel.cs b/src/Presentation/SmartStore.Web/Models/Blogs/BlogPagingFilteringModel.cs index 052b5938fe..90292d014a 100644 --- a/src/Presentation/SmartStore.Web/Models/Blogs/BlogPagingFilteringModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Blogs/BlogPagingFilteringModel.cs @@ -1,11 +1,9 @@ using System; -// codehint: sm-delete using SmartStore.Core; namespace SmartStore.Web.Models.Blogs { - // codehint: sm-edit (formerly inherited BasePageableModel) - public partial class BlogPagingFilteringModel : PagedListBase // BasePageableModel + public partial class BlogPagingFilteringModel : PagedListBase { #region Methods diff --git a/src/Presentation/SmartStore.Web/Models/Blogs/BlogPostModel.cs b/src/Presentation/SmartStore.Web/Models/Blogs/BlogPostModel.cs index 745c2cb1e0..67b8ee3b2c 100644 --- a/src/Presentation/SmartStore.Web/Models/Blogs/BlogPostModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Blogs/BlogPostModel.cs @@ -36,7 +36,6 @@ public BlogPostModel() public IList Comments { get; set; } public AddBlogCommentModel AddNewComment { get; set; } - // codehint: sm-add public int AvatarPictureSize { get; set; } public bool AllowCustomersToUploadAvatars { get; set; } } diff --git a/src/Presentation/SmartStore.Web/Models/Catalog/CatalogPagingFilteringModel.cs b/src/Presentation/SmartStore.Web/Models/Catalog/CatalogPagingFilteringModel.cs index ecea17d7cb..9e8da38ee9 100644 --- a/src/Presentation/SmartStore.Web/Models/Catalog/CatalogPagingFilteringModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Catalog/CatalogPagingFilteringModel.cs @@ -73,7 +73,7 @@ protected virtual IList GetPriceRangeList(string priceRangesStr) { string[] fromTo = str1.Trim().Split(new char[] { '-' }); - if (fromTo.Length > 1) { // codehint: sm-edit + if (fromTo.Length > 1) { decimal? from = null; if (!String.IsNullOrEmpty(fromTo[0]) && !String.IsNullOrEmpty(fromTo[0].Trim())) from = decimal.Parse(fromTo[0].Trim(), new CultureInfo("en-US")); diff --git a/src/Presentation/SmartStore.Web/Models/Catalog/PagingFilteringModel.cs b/src/Presentation/SmartStore.Web/Models/Catalog/PagingFilteringModel.cs index 983ed49765..4fd52cee47 100644 --- a/src/Presentation/SmartStore.Web/Models/Catalog/PagingFilteringModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Catalog/PagingFilteringModel.cs @@ -1,5 +1,4 @@ -// codehint: sm-delete -using System.Collections.Generic; +using System.Collections.Generic; using System.Web.Mvc; using SmartStore.Core; using SmartStore.Web.Framework; @@ -7,9 +6,6 @@ namespace SmartStore.Web.Models.Catalog { - - // codehint: sm-add (whole file) - public partial class ListOptionItem : ModelBase { public string Text { get; set; } diff --git a/src/Presentation/SmartStore.Web/Models/Catalog/ProductDetailsModel.cs b/src/Presentation/SmartStore.Web/Models/Catalog/ProductDetailsModel.cs index 4f092cf362..fdfce95aff 100644 --- a/src/Presentation/SmartStore.Web/Models/Catalog/ProductDetailsModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Catalog/ProductDetailsModel.cs @@ -16,8 +16,6 @@ public partial class ProductDetailsModel : EntityModelBase public ProductDetailsModel() { - //codehint: sm-edit - //Manufacturers = new List(); Manufacturers = new List(); GiftCard = new GiftCardModel(); ProductPrice = new ProductPriceModel(); diff --git a/src/Presentation/SmartStore.Web/Models/Catalog/SearchPagingFilteringModel.cs b/src/Presentation/SmartStore.Web/Models/Catalog/SearchPagingFilteringModel.cs index 54591c656a..99ab88bebf 100644 --- a/src/Presentation/SmartStore.Web/Models/Catalog/SearchPagingFilteringModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Catalog/SearchPagingFilteringModel.cs @@ -1,5 +1,4 @@ -// codehint: sm-delete -using System.Collections.Generic; +using System.Collections.Generic; using System.Web.Mvc; using SmartStore.Core; using SmartStore.Web.Framework; @@ -7,8 +6,7 @@ namespace SmartStore.Web.Models.Catalog { - // codehint: sm-edit - public partial class SearchPagingFilteringModel : PagingFilteringModel // BasePageableModel + public partial class SearchPagingFilteringModel : PagingFilteringModel { } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Models/Common/CurrencyModel.cs b/src/Presentation/SmartStore.Web/Models/Common/CurrencyModel.cs index 730a2ee0fb..a9a910f39e 100644 --- a/src/Presentation/SmartStore.Web/Models/Common/CurrencyModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Common/CurrencyModel.cs @@ -5,8 +5,6 @@ namespace SmartStore.Web.Models.Common public partial class CurrencyModel : EntityModelBase { public string Name { get; set; } - - // codehint: sm-add public string ISOCode { get; set; } public string Symbol { get; set; } } diff --git a/src/Presentation/SmartStore.Web/Models/Common/PagerModel.cs b/src/Presentation/SmartStore.Web/Models/Common/PagerModel.cs index bc416d03be..d42a70eaf7 100644 --- a/src/Presentation/SmartStore.Web/Models/Common/PagerModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Common/PagerModel.cs @@ -3,8 +3,6 @@ namespace SmartStore.Web.Models.Common { - //codehint: sm-delete (whole PagerModel class) - #region Classes /// diff --git a/src/Presentation/SmartStore.Web/Models/Install/InstallModel.cs b/src/Presentation/SmartStore.Web/Models/Install/InstallModel.cs index 9e9ce393fc..8da7d84e94 100644 --- a/src/Presentation/SmartStore.Web/Models/Install/InstallModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Install/InstallModel.cs @@ -13,7 +13,6 @@ public partial class InstallModel : ModelBase public InstallModel() { this.AvailableLanguages = new List(); - // codehint: sm-add this.AvailableAppLanguages = new List(); this.AvailableMediaStorages = new List(); } diff --git a/src/Presentation/SmartStore.Web/Models/Media/PictureModel.cs b/src/Presentation/SmartStore.Web/Models/Media/PictureModel.cs index 8c4b4c48d6..c07f995020 100644 --- a/src/Presentation/SmartStore.Web/Models/Media/PictureModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Media/PictureModel.cs @@ -4,10 +4,9 @@ namespace SmartStore.Web.Models.Media { public partial class PictureModel : ModelBase { - // codehint: sm-add public int PictureId { get; set; } - public string ThumbImageUrl { get; set; } // codehint: sm-add + public string ThumbImageUrl { get; set; } public string ImageUrl { get; set; } diff --git a/src/Presentation/SmartStore.Web/Models/News/NewsItemModel.cs b/src/Presentation/SmartStore.Web/Models/News/NewsItemModel.cs index 3e4eb262e4..fadd949b5d 100644 --- a/src/Presentation/SmartStore.Web/Models/News/NewsItemModel.cs +++ b/src/Presentation/SmartStore.Web/Models/News/NewsItemModel.cs @@ -34,7 +34,6 @@ public NewsItemModel() public IList Comments { get; set; } public AddNewsCommentModel AddNewComment { get; set; } - // codehint: sm-add public int AvatarPictureSize { get; set; } public bool AllowCustomersToUploadAvatars { get; set; } } diff --git a/src/Presentation/SmartStore.Web/Models/News/NewsPagingFilteringModel.cs b/src/Presentation/SmartStore.Web/Models/News/NewsPagingFilteringModel.cs index 326dc22682..e5ffffbacd 100644 --- a/src/Presentation/SmartStore.Web/Models/News/NewsPagingFilteringModel.cs +++ b/src/Presentation/SmartStore.Web/Models/News/NewsPagingFilteringModel.cs @@ -1,9 +1,7 @@ using SmartStore.Core; -// codehint: sm-delete namespace SmartStore.Web.Models.News { - // codehint: sm-edit public partial class NewsPagingFilteringModel : PagedListBase { } diff --git a/src/Presentation/SmartStore.Web/Views/Catalog/RecentlyViewedProductsBlock.cshtml b/src/Presentation/SmartStore.Web/Views/Catalog/RecentlyViewedProductsBlock.cshtml index 19d35797c0..978bb9c0c9 100644 --- a/src/Presentation/SmartStore.Web/Views/Catalog/RecentlyViewedProductsBlock.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Catalog/RecentlyViewedProductsBlock.cshtml @@ -1,5 +1,4 @@ -@*codehint: sm-edit nearly completly*@ -@model IList +@model IList @using SmartStore.Core; @using SmartStore.Core.Infrastructure; @using SmartStore.Web.Models.Catalog; diff --git a/src/Presentation/SmartStore.Web/Views/Customer/Addresses.cshtml b/src/Presentation/SmartStore.Web/Views/Customer/Addresses.cshtml index 8648587f97..591e0329d8 100644 --- a/src/Presentation/SmartStore.Web/Views/Customer/Addresses.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Customer/Addresses.cshtml @@ -98,7 +98,6 @@ }
- @*codehint: sm-edit begin*@ - @*codehint: sm-edit end*@
diff --git a/src/Presentation/SmartStore.Web/Views/Home/ContactUs.cshtml b/src/Presentation/SmartStore.Web/Views/Home/ContactUs.cshtml index c57fc164e8..02e6e71ddf 100644 --- a/src/Presentation/SmartStore.Web/Views/Home/ContactUs.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Home/ContactUs.cshtml @@ -30,7 +30,7 @@ } @T("PageTitle.ContactUs") - @*codehint: sm-edit begin *@ +
@Html.LabelFor(model => model.FullName, new { @class="control-label required" , @for="FullName" } )
@@ -72,7 +72,6 @@
- @*codehint: sm-edit end *@ } diff --git a/src/Presentation/SmartStore.Web/Views/Poll/_Poll.cshtml b/src/Presentation/SmartStore.Web/Views/Poll/_Poll.cshtml index e1c49b12f3..df162f46fd 100644 --- a/src/Presentation/SmartStore.Web/Views/Poll/_Poll.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Poll/_Poll.cshtml @@ -31,11 +31,9 @@
@foreach (var item in Model.Answers) { - @*codehint: sm-edit (begin) *@ - @*codehint: sm-edit (end) *@ }
diff --git a/src/Presentation/SmartStore.Web/Views/Product/RelatedProducts.cshtml b/src/Presentation/SmartStore.Web/Views/Product/RelatedProducts.cshtml index e5978ca689..5153add698 100644 --- a/src/Presentation/SmartStore.Web/Views/Product/RelatedProducts.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Product/RelatedProducts.cshtml @@ -1,5 +1,4 @@ -@*codehint: sm-edit complete *@ -@model IList +@model IList @using SmartStore.Web.Models.Catalog; @if (Model.Count > 0) { diff --git a/src/Presentation/SmartStore.Web/Views/ShoppingCart/EmailWishlist.cshtml b/src/Presentation/SmartStore.Web/Views/ShoppingCart/EmailWishlist.cshtml index 94457c013f..98e44d6a34 100644 --- a/src/Presentation/SmartStore.Web/Views/ShoppingCart/EmailWishlist.cshtml +++ b/src/Presentation/SmartStore.Web/Views/ShoppingCart/EmailWishlist.cshtml @@ -21,7 +21,6 @@ } else { - @*codehint: sm-edit begin *@ using (Html.BeginForm("EmailWishlist", null, FormMethod.Post, new { @class = "form-horizontal" })) {
@@ -70,7 +69,6 @@
} - @*codehint: sm-edit end *@ } From 48d44f149117a63c8aae516998e452a44648c952 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 24 Jun 2015 13:05:27 +0200 Subject: [PATCH 0172/1256] #702 Facebook external authentication suitable for multi-stores --- changelog.md | 1 + .../ExternalAuthFacebookController.cs | 67 +++++++++++-------- .../Core/FacebookProviderAuthorizer.cs | 38 ++++++++--- .../DependencyRegistrar.cs | 3 - .../SmartStore.FacebookAuth/Description.txt | 2 +- .../FacebookExternalAuthMethod.cs | 8 ++- .../Models/ConfigurationModel.cs | 1 + .../SmartStore.FacebookAuth/RouteProvider.cs | 3 +- .../ExternalAuthFacebook/Configure.cshtml | 27 +++++--- 9 files changed, 92 insertions(+), 58 deletions(-) diff --git a/changelog.md b/changelog.md index c3d2d7762e..d393151d15 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,7 @@ * #94 Restrict payment methods to certain shipping methods * #526 Min\max amount option for which the payment method should be offered during checkout * #718 ShopConnector: Import option for "Published" and "Disable buy\wishlist button" +* #702 Facebook external authentication suitable for multi-stores ## SmartStore.NET 2.2.2 diff --git a/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs b/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs index 386027e411..e0d41c6e42 100644 --- a/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs +++ b/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs @@ -1,54 +1,52 @@ using System.Web.Mvc; -using SmartStore.Core; using SmartStore.Core.Domain.Customers; using SmartStore.FacebookAuth.Core; using SmartStore.FacebookAuth.Models; +using SmartStore.Services; using SmartStore.Services.Authentication.External; -using SmartStore.Services.Configuration; using SmartStore.Services.Security; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Controllers; +using SmartStore.Web.Framework.Settings; namespace SmartStore.FacebookAuth.Controllers { //[UnitOfWork] public class ExternalAuthFacebookController : PluginControllerBase { - private readonly ISettingService _settingService; - private readonly FacebookExternalAuthSettings _facebookExternalAuthSettings; private readonly IOAuthProviderFacebookAuthorizer _oAuthProviderFacebookAuthorizer; private readonly IOpenAuthenticationService _openAuthenticationService; private readonly ExternalAuthenticationSettings _externalAuthenticationSettings; - private readonly IStoreContext _storeContext; - private readonly IPermissionService _permissionService; + private readonly ICommonServices _commonServices; - public ExternalAuthFacebookController(ISettingService settingService, - FacebookExternalAuthSettings facebookExternalAuthSettings, + public ExternalAuthFacebookController( IOAuthProviderFacebookAuthorizer oAuthProviderFacebookAuthorizer, IOpenAuthenticationService openAuthenticationService, ExternalAuthenticationSettings externalAuthenticationSettings, - IStoreContext storeContext, - IPermissionService permissionService) + ICommonServices commonServices) { - this._settingService = settingService; - this._facebookExternalAuthSettings = facebookExternalAuthSettings; this._oAuthProviderFacebookAuthorizer = oAuthProviderFacebookAuthorizer; this._openAuthenticationService = openAuthenticationService; this._externalAuthenticationSettings = externalAuthenticationSettings; - this._storeContext = storeContext; - this._permissionService = permissionService; + this._commonServices = commonServices; } [AdminAuthorize] [ChildActionOnly] public ActionResult Configure() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageExternalAuthenticationMethods)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageExternalAuthenticationMethods)) return Content("Access denied"); var model = new ConfigurationModel(); - model.ClientKeyIdentifier = _facebookExternalAuthSettings.ClientKeyIdentifier; - model.ClientSecret = _facebookExternalAuthSettings.ClientSecret; + int storeScope = this.GetActiveStoreScopeConfiguration(_commonServices.StoreService, _commonServices.WorkContext); + var settings = _commonServices.Settings.LoadSetting(storeScope); + + model.ClientKeyIdentifier = settings.ClientKeyIdentifier; + model.ClientSecret = settings.ClientSecret; + + var storeDependingSettingHelper = new StoreDependingSettingHelper(ViewData); + storeDependingSettingHelper.GetOverrideKeys(settings, model, storeScope, _commonServices.Settings); return View(model); } @@ -56,20 +54,27 @@ public ActionResult Configure() [HttpPost] [AdminAuthorize] [ChildActionOnly] - public ActionResult Configure(ConfigurationModel model) + public ActionResult Configure(ConfigurationModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageExternalAuthenticationMethods)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageExternalAuthenticationMethods)) return Content("Access denied"); if (!ModelState.IsValid) return Configure(); - - //save settings - _facebookExternalAuthSettings.ClientKeyIdentifier = model.ClientKeyIdentifier; - _facebookExternalAuthSettings.ClientSecret = model.ClientSecret; - _settingService.SaveSetting(_facebookExternalAuthSettings); - - return View(model); + + var storeDependingSettingHelper = new StoreDependingSettingHelper(ViewData); + int storeScope = this.GetActiveStoreScopeConfiguration(_commonServices.StoreService, _commonServices.WorkContext); + var settings = _commonServices.Settings.LoadSetting(storeScope); + + settings.ClientKeyIdentifier = model.ClientKeyIdentifier; + settings.ClientSecret = model.ClientSecret; + + storeDependingSettingHelper.UpdateSettings(settings, form, storeScope, _commonServices.Settings); + _commonServices.Settings.ClearCache(); + + NotifySuccess(_commonServices.Localization.GetResource("Admin.Common.DataSuccessfullySaved")); + + return Configure(); } [ChildActionOnly] @@ -81,7 +86,7 @@ public ActionResult PublicInfo() [NonAction] private ActionResult LoginInternal(string returnUrl, bool verifyResponse) { - var processor = _openAuthenticationService.LoadExternalAuthenticationMethodBySystemName("SmartStore.FacebookAuth", _storeContext.CurrentStore.Id); + var processor = _openAuthenticationService.LoadExternalAuthenticationMethodBySystemName(Provider.SystemName, _commonServices.StoreContext.CurrentStore.Id); if (processor == null || !processor.IsMethodActive(_externalAuthenticationSettings)) { throw new SmartException("Facebook module cannot be loaded"); @@ -122,8 +127,12 @@ private ActionResult LoginInternal(string returnUrl, bool verifyResponse) break; } - if (result.Result != null) return result.Result; - return HttpContext.Request.IsAuthenticated ? new RedirectResult(!string.IsNullOrEmpty(returnUrl) ? returnUrl : "~/") : new RedirectResult(Url.LogOn(returnUrl)); + if (result.Result != null) + return result.Result; + + return HttpContext.Request.IsAuthenticated ? + new RedirectResult(!string.IsNullOrEmpty(returnUrl) ? returnUrl : "~/") : + new RedirectResult(Url.LogOn(returnUrl)); } public ActionResult Login(string returnUrl) diff --git a/src/Plugins/SmartStore.FacebookAuth/Core/FacebookProviderAuthorizer.cs b/src/Plugins/SmartStore.FacebookAuth/Core/FacebookProviderAuthorizer.cs index 6da9e37086..34eabdbffc 100644 --- a/src/Plugins/SmartStore.FacebookAuth/Core/FacebookProviderAuthorizer.cs +++ b/src/Plugins/SmartStore.FacebookAuth/Core/FacebookProviderAuthorizer.cs @@ -8,8 +8,8 @@ using System.Web.Mvc; using DotNetOpenAuth.AspNet; using DotNetOpenAuth.AspNet.Clients; -using SmartStore.Core; using SmartStore.Core.Domain.Customers; +using SmartStore.Services; using SmartStore.Services.Authentication.External; namespace SmartStore.FacebookAuth.Core @@ -21,9 +21,9 @@ public class FacebookProviderAuthorizer : IOAuthProviderFacebookAuthorizer private readonly IExternalAuthorizer _authorizer; private readonly IOpenAuthenticationService _openAuthenticationService; private readonly ExternalAuthenticationSettings _externalAuthenticationSettings; - private readonly FacebookExternalAuthSettings _facebookExternalAuthSettings; private readonly HttpContextBase _httpContext; - private readonly IWebHelper _webHelper; + private readonly ICommonServices _commonServices; + private FacebookClient _facebookApplication; #endregion @@ -33,16 +33,14 @@ public class FacebookProviderAuthorizer : IOAuthProviderFacebookAuthorizer public FacebookProviderAuthorizer(IExternalAuthorizer authorizer, IOpenAuthenticationService openAuthenticationService, ExternalAuthenticationSettings externalAuthenticationSettings, - FacebookExternalAuthSettings facebookExternalAuthSettings, HttpContextBase httpContext, - IWebHelper webHelper) + ICommonServices commonServices) { this._authorizer = authorizer; this._openAuthenticationService = openAuthenticationService; this._externalAuthenticationSettings = externalAuthenticationSettings; - this._facebookExternalAuthSettings = facebookExternalAuthSettings; this._httpContext = httpContext; - this._webHelper = webHelper; + this._commonServices = commonServices; } #endregion @@ -51,7 +49,17 @@ public FacebookProviderAuthorizer(IExternalAuthorizer authorizer, private FacebookClient FacebookApplication { - get { return _facebookApplication ?? (_facebookApplication = new FacebookClient(_facebookExternalAuthSettings.ClientKeyIdentifier, _facebookExternalAuthSettings.ClientSecret)); } + get + { + if (_facebookApplication == null) + { + var settings = _commonServices.Settings.LoadSetting(_commonServices.StoreContext.CurrentStore.Id); + + _facebookApplication = new FacebookClient(settings.ClientKeyIdentifier, settings.ClientSecret); + } + + return _facebookApplication; + } } private AuthorizeState VerifyAuthentication(string returnUrl) @@ -91,9 +99,12 @@ private void ParseClaims(AuthenticationResult authenticationResult, OAuthAuthent { var claims = new UserClaims(); claims.Contact = new ContactClaims(); + if (authenticationResult.ExtraData.ContainsKey("username")) claims.Contact.Email = authenticationResult.ExtraData["username"]; + claims.Name = new NameClaims(); + if (authenticationResult.ExtraData.ContainsKey("name")) { var name = authenticationResult.ExtraData["name"]; @@ -122,7 +133,7 @@ private AuthorizeState RequestAuthentication(string returnUrl) private Uri GenerateLocalCallbackUri() { - string url = string.Format("{0}Plugins/SmartStore.FacebookAuth/logincallback/", _webHelper.GetStoreLocation()); + string url = string.Format("{0}Plugins/SmartStore.FacebookAuth/logincallback/", _commonServices.WebHelper.GetStoreLocation()); return new Uri(url); } @@ -131,10 +142,14 @@ private Uri GenerateServiceLoginUrl() //code copied from DotNetOpenAuth.AspNet.Clients.FacebookClient file var builder = new UriBuilder("https://www.facebook.com/dialog/oauth"); var args = new Dictionary(); - args.Add("client_id", _facebookExternalAuthSettings.ClientKeyIdentifier); + var settings = _commonServices.Settings.LoadSetting(_commonServices.StoreContext.CurrentStore.Id); + + args.Add("client_id", settings.ClientKeyIdentifier); args.Add("redirect_uri", GenerateLocalCallbackUri().AbsoluteUri); args.Add("scope", "email"); + AppendQueryArgs(builder, args); + return builder.Uri; } @@ -152,6 +167,7 @@ private void AppendQueryArgs(UriBuilder builder, IEnumerable> args) { if (!args.Any>()) @@ -169,7 +185,9 @@ private string CreateQueryString(IEnumerable> args) builder.Length--; return builder.ToString(); } + private readonly string[] UriRfc3986CharsToEscape = new string[] { "!", "*", "'", "(", ")" }; + private string EscapeUriDataStringRfc3986(string value) { StringBuilder builder = new StringBuilder(Uri.EscapeDataString(value)); diff --git a/src/Plugins/SmartStore.FacebookAuth/DependencyRegistrar.cs b/src/Plugins/SmartStore.FacebookAuth/DependencyRegistrar.cs index 69f5a94064..ef4c32cf34 100644 --- a/src/Plugins/SmartStore.FacebookAuth/DependencyRegistrar.cs +++ b/src/Plugins/SmartStore.FacebookAuth/DependencyRegistrar.cs @@ -1,7 +1,4 @@ -using System; -using System.Linq.Expressions; using Autofac; -using Autofac.Integration.Mvc; using SmartStore.Core.Infrastructure; using SmartStore.Core.Infrastructure.DependencyManagement; using SmartStore.FacebookAuth.Core; diff --git a/src/Plugins/SmartStore.FacebookAuth/Description.txt b/src/Plugins/SmartStore.FacebookAuth/Description.txt index 081bf95dd1..f7cc05d671 100644 --- a/src/Plugins/SmartStore.FacebookAuth/Description.txt +++ b/src/Plugins/SmartStore.FacebookAuth/Description.txt @@ -1,7 +1,7 @@ FriendlyName: Facebook SystemName: SmartStore.FacebookAuth Group: Security -Version: 2.2.0 +Version: 2.2.0.1 MinAppVersion: 2.2.0 DisplayOrder: 5 FileName: SmartStore.FacebookAuth.dll diff --git a/src/Plugins/SmartStore.FacebookAuth/FacebookExternalAuthMethod.cs b/src/Plugins/SmartStore.FacebookAuth/FacebookExternalAuthMethod.cs index 2c4c183c76..d3a0ea7b26 100644 --- a/src/Plugins/SmartStore.FacebookAuth/FacebookExternalAuthMethod.cs +++ b/src/Plugins/SmartStore.FacebookAuth/FacebookExternalAuthMethod.cs @@ -1,5 +1,6 @@ using System.Web.Routing; using SmartStore.Core.Plugins; +using SmartStore.FacebookAuth.Core; using SmartStore.Services.Authentication.External; using SmartStore.Services.Localization; @@ -11,8 +12,10 @@ namespace SmartStore.FacebookAuth public class FacebookExternalAuthMethod : BasePlugin, IExternalAuthenticationMethod, IConfigurable { #region Fields + private readonly FacebookExternalAuthSettings _facebookExternalAuthSettings; private readonly ILocalizationService _localizationService; + #endregion #region Ctor @@ -37,7 +40,7 @@ public void GetConfigurationRoute(out string actionName, out string controllerNa { actionName = "Configure"; controllerName = "ExternalAuthFacebook"; - routeValues = new RouteValueDictionary(new { Namespaces = "SmartStore.FacebookAuth.Controllers", area = "SmartStore.FacebookAuth" }); + routeValues = new RouteValueDictionary(new { Namespaces = "SmartStore.FacebookAuth.Controllers", area = Provider.SystemName }); } /// @@ -50,7 +53,7 @@ public void GetPublicInfoRoute(out string actionName, out string controllerName, { actionName = "PublicInfo"; controllerName = "ExternalAuthFacebook"; - routeValues = new RouteValueDictionary(new { Namespaces = "SmartStore.FacebookAuth.Controllers", area = "SmartStore.FacebookAuth" }); + routeValues = new RouteValueDictionary(new { Namespaces = "SmartStore.FacebookAuth.Controllers", area = Provider.SystemName }); } /// @@ -68,7 +71,6 @@ public override void Uninstall() { //locales _localizationService.DeleteLocaleStringResources(this.PluginDescriptor.ResourceRootKey); - _localizationService.DeleteLocaleStringResources("Plugins.FriendlyName.ExternalAuth.Facebook", false); base.Uninstall(); } diff --git a/src/Plugins/SmartStore.FacebookAuth/Models/ConfigurationModel.cs b/src/Plugins/SmartStore.FacebookAuth/Models/ConfigurationModel.cs index 5c78e61896..4676db9b6b 100644 --- a/src/Plugins/SmartStore.FacebookAuth/Models/ConfigurationModel.cs +++ b/src/Plugins/SmartStore.FacebookAuth/Models/ConfigurationModel.cs @@ -7,6 +7,7 @@ public class ConfigurationModel : ModelBase { [SmartResourceDisplayName("Plugins.ExternalAuth.Facebook.ClientKeyIdentifier")] public string ClientKeyIdentifier { get; set; } + [SmartResourceDisplayName("Plugins.ExternalAuth.Facebook.ClientSecret")] public string ClientSecret { get; set; } } diff --git a/src/Plugins/SmartStore.FacebookAuth/RouteProvider.cs b/src/Plugins/SmartStore.FacebookAuth/RouteProvider.cs index 1326663260..0353105d2b 100644 --- a/src/Plugins/SmartStore.FacebookAuth/RouteProvider.cs +++ b/src/Plugins/SmartStore.FacebookAuth/RouteProvider.cs @@ -1,5 +1,6 @@ using System.Web.Mvc; using System.Web.Routing; +using SmartStore.FacebookAuth.Core; using SmartStore.Web.Framework.Mvc.Routes; namespace SmartStore.FacebookAuth @@ -13,7 +14,7 @@ public void RegisterRoutes(RouteCollection routes) new { controller = "ExternalAuthFacebook" }, new[] { "SmartStore.FacebookAuth.Controllers" } ) - .DataTokens["area"] = "SmartStore.FacebookAuth"; + .DataTokens["area"] = Provider.SystemName; } public int Priority { diff --git a/src/Plugins/SmartStore.FacebookAuth/Views/ExternalAuthFacebook/Configure.cshtml b/src/Plugins/SmartStore.FacebookAuth/Views/ExternalAuthFacebook/Configure.cshtml index 94d69f5d8a..60dc28cea5 100644 --- a/src/Plugins/SmartStore.FacebookAuth/Views/ExternalAuthFacebook/Configure.cshtml +++ b/src/Plugins/SmartStore.FacebookAuth/Views/ExternalAuthFacebook/Configure.cshtml @@ -3,23 +3,29 @@ } @model SmartStore.FacebookAuth.Models.ConfigurationModel @using SmartStore.Web.Framework; + +
+ + @Html.Raw(T("Plugins.ExternalAuth.Facebook.AdminInstruction")) +
+ +
+ +@Html.Action("StoreScopeConfiguration", "Setting", new { area = "Admin" }) + +@Html.ValidationSummary(false) + +
+ @using (Html.BeginForm()) { - - - @@ -28,7 +34,7 @@ @Html.SmartLabelFor(model => model.ClientSecret) @@ -43,5 +49,4 @@
-
- - @Html.Raw(T("Plugins.ExternalAuth.Facebook.AdminInstruction")) -
-
@Html.SmartLabelFor(model => model.ClientKeyIdentifier) - @Html.EditorFor(model => model.ClientKeyIdentifier) + @Html.SettingEditorFor(model => model.ClientKeyIdentifier) @Html.ValidationMessageFor(model => model.ClientKeyIdentifier)
- @Html.EditorFor(model => model.ClientSecret) + @Html.SettingEditorFor(model => model.ClientSecret) @Html.ValidationMessageFor(model => model.ClientSecret)
- } \ No newline at end of file From 4ce968c0df4a7d96adb8649152084a3302546f5a Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 24 Jun 2015 13:48:08 +0200 Subject: [PATCH 0173/1256] Minor change --- changelog.md | 2 +- .../ExternalAuthFacebookController.cs | 25 ++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/changelog.md b/changelog.md index d393151d15..6bc68c22a9 100644 --- a/changelog.md +++ b/changelog.md @@ -8,7 +8,7 @@ * #94 Restrict payment methods to certain shipping methods * #526 Min\max amount option for which the payment method should be offered during checkout * #718 ShopConnector: Import option for "Published" and "Disable buy\wishlist button" -* #702 Facebook external authentication suitable for multi-stores +* #702 Facebook and Twitter external authentication suitable for multi-stores ## SmartStore.NET 2.2.2 diff --git a/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs b/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs index e0d41c6e42..1ed000f3bb 100644 --- a/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs +++ b/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs @@ -30,13 +30,22 @@ public ExternalAuthFacebookController( this._externalAuthenticationSettings = externalAuthenticationSettings; this._commonServices = commonServices; } + + private bool HasPermission(bool notify = true) + { + bool hasPermission = _commonServices.Permissions.Authorize(StandardPermissionProvider.ManageExternalAuthenticationMethods); + + if (notify && !hasPermission) + NotifyError(_commonServices.Localization.GetResource("Admin.AccessDenied.Description")); + + return hasPermission; + } - [AdminAuthorize] - [ChildActionOnly] + [AdminAuthorize, ChildActionOnly] public ActionResult Configure() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageExternalAuthenticationMethods)) - return Content("Access denied"); + if (!HasPermission(false)) + return AccessDeniedPartialView(); var model = new ConfigurationModel(); int storeScope = this.GetActiveStoreScopeConfiguration(_commonServices.StoreService, _commonServices.WorkContext); @@ -51,13 +60,11 @@ public ActionResult Configure() return View(model); } - [HttpPost] - [AdminAuthorize] - [ChildActionOnly] + [HttpPost, AdminAuthorize, ChildActionOnly] public ActionResult Configure(ConfigurationModel model, FormCollection form) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageExternalAuthenticationMethods)) - return Content("Access denied"); + if (!HasPermission(false)) + return Configure(); if (!ModelState.IsValid) return Configure(); From 35f0b3a610979d93f942e42e711276698493f898 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 24 Jun 2015 14:49:49 +0200 Subject: [PATCH 0174/1256] Resolves #692 System warnings: Add test for sitemap reachability --- ...06211043073_PaymentShippingRestrictions.cs | 9 + .../Controllers/CommonController.cs | 321 ++++++++++-------- 2 files changed, 196 insertions(+), 134 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs index 99a1467c9d..cc83f0e114 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs @@ -56,6 +56,15 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "The request could not be processed.
Controller: {0}, Action: {1}, Reason: {2}.", "Die Anfrage konnte nicht ausgefhrt werden.
Controller: {0}, Action: {1}, Grund: {2}."); + builder.AddOrUpdate("Admin.System.Warnings.SitemapReachable.OK", + "The sitemap for the store is reachable.", + "Die Sitemap fr den Shop ist erreichbar."); + + builder.AddOrUpdate("Admin.System.Warnings.SitemapReachable.Wrong", + "The sitemap for the store is not reachable.", + "Die Sitemap fr den Shop ist nicht erreichbar."); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.RestrictionNote", "Select customer roles, shipping methods, countries and order amounts for which you do not want to offer this payment method.", "Whlen Sie Kundengruppen, Versandarten, Lnder und Bestellwerte, bei denen Sie diese Zahlungsmethode nicht anbieten mchten."); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs index 3b070a3d9b..82b4cffdee 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs @@ -68,7 +68,7 @@ public class CommonController : AdminControllerBase private readonly Lazy _menuPublisher; private readonly Lazy _pluginFinder; private readonly IGenericAttributeService _genericAttributeService; - private readonly ICommonServices _services; + private readonly ICommonServices _commonServices; private readonly Func _cache; private readonly static object s_lock = new object(); @@ -95,7 +95,7 @@ public CommonController( Lazy menuPublisher, Lazy pluginFinder, IGenericAttributeService genericAttributeService, - ICommonServices services, + ICommonServices commonServices, Func cache) { this._paymentService = paymentService; @@ -115,7 +115,7 @@ public CommonController( this._menuPublisher = menuPublisher; this._pluginFinder = pluginFinder; this._genericAttributeService = genericAttributeService; - this._services = services; + this._commonServices = commonServices; this._cache = cache; } @@ -128,11 +128,11 @@ public CommonController( [ChildActionOnly] public ActionResult Navbar() { - var currentCustomer = _services.WorkContext.CurrentCustomer; + var currentCustomer = _commonServices.WorkContext.CurrentCustomer; - ViewBag.UserName = _services.Settings.LoadSetting().UsernamesEnabled ? currentCustomer.Username : currentCustomer.Email; - ViewBag.Stores = _services.StoreService.GetAllStores(); - if (_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + ViewBag.UserName = _commonServices.Settings.LoadSetting().UsernamesEnabled ? currentCustomer.Username : currentCustomer.Email; + ViewBag.Stores = _commonServices.StoreService.GetAllStores(); + if (_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) { ViewBag.CheckUpdateResult = AsyncRunner.RunSync(() => CheckUpdateAsync(false)); } @@ -143,10 +143,10 @@ public ActionResult Navbar() [ChildActionOnly] public ActionResult Menu() { - var cacheManager = _services.Cache; + var cacheManager = _commonServices.Cache; - var customerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); - string cacheKey = string.Format("smartstore.pres.adminmenu.navigation-{0}-{1}", _services.WorkContext.WorkingLanguage.Id, string.Join(",", customerRolesIds)); + var customerRolesIds = _commonServices.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); + string cacheKey = string.Format("smartstore.pres.adminmenu.navigation-{0}-{1}", _commonServices.WorkContext.WorkingLanguage.Id, string.Join(",", customerRolesIds)); var rootNode = cacheManager.Get(cacheKey, () => { @@ -255,7 +255,7 @@ private bool MenuItemAccessPermitted(MenuItem item) if (_securitySettings.Value.HideAdminMenuItemsBasedOnPermissions && item.PermissionNames.HasValue()) { - var permitted = item.PermissionNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Any(x => _services.Permissions.Authorize(x.Trim())); + var permitted = item.PermissionNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Any(x => _commonServices.Permissions.Authorize(x.Trim())); if (!permitted) { result = false; @@ -284,24 +284,24 @@ public ActionResult CheckUpdateSuppress(string myVersion, string newVersion) public void CheckUpdateSuppressInternal(string myVersion, string newVersion) { var suppressKey = "SuppressUpdateMessage.{0}.{1}".FormatInvariant(myVersion, newVersion); - _genericAttributeService.SaveAttribute(_services.WorkContext.CurrentCustomer, suppressKey, true); - _services.Cache.RemoveByPattern("Common.CheckUpdateResult"); + _genericAttributeService.SaveAttribute(_commonServices.WorkContext.CurrentCustomer, suppressKey, true); + _commonServices.Cache.RemoveByPattern("Common.CheckUpdateResult"); } [NonAction] private async Task CheckUpdateAsync(bool enforce = false, bool forSuppress = false) { var curVersion = SmartStoreVersion.CurrentFullVersion; - var lang = _services.WorkContext.WorkingLanguage.UniqueSeoCode; + var lang = _commonServices.WorkContext.WorkingLanguage.UniqueSeoCode; var cacheKeyPattern = "Common.CheckUpdateResult"; var cacheKey = "{0}.{1}".FormatInvariant(cacheKeyPattern, lang); if (enforce) { - _services.Cache.RemoveByPattern(cacheKeyPattern); + _commonServices.Cache.RemoveByPattern(cacheKeyPattern); } - var result = await _services.Cache.Get(cacheKey, async () => + var result = await _commonServices.Cache.Get(cacheKey, async () => { var noUpdateResult = new CheckUpdateResult { UpdateAvailable = false, LanguageCode = lang, CurrentVersion = curVersion }; @@ -315,7 +315,7 @@ private async Task CheckUpdateAsync(bool enforce = false, boo client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.UserAgent.ParseAdd("SmartStore.NET {0}".FormatInvariant(curVersion)); - client.DefaultRequestHeaders.Add("Authorization-Key", _services.StoreContext.CurrentStore.Url.TrimEnd('/')); + client.DefaultRequestHeaders.Add("Authorization-Key", _commonServices.StoreContext.CurrentStore.Url.TrimEnd('/')); HttpResponseMessage response = await client.GetAsync(url); @@ -331,7 +331,7 @@ private async Task CheckUpdateAsync(bool enforce = false, boo model.CurrentVersion = curVersion; model.LanguageCode = lang; - if (CommonHelper.IsDevEnvironment || !_commonSettings.Value.AutoUpdateEnabled || !_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (CommonHelper.IsDevEnvironment || !_commonSettings.Value.AutoUpdateEnabled || !_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) { model.AutoUpdatePossible = false; } @@ -341,9 +341,9 @@ private async Task CheckUpdateAsync(bool enforce = false, boo if (enforce) { // but ignore user's decision if 'enforce' - _genericAttributeService.SaveAttribute(_services.WorkContext.CurrentCustomer, suppressKey, null); + _genericAttributeService.SaveAttribute(_commonServices.WorkContext.CurrentCustomer, suppressKey, null); } - var showMessage = enforce || _services.WorkContext.CurrentCustomer.GetAttribute(suppressKey, _genericAttributeService).GetValueOrDefault() == false; + var showMessage = enforce || _commonServices.WorkContext.CurrentCustomer.GetAttribute(suppressKey, _genericAttributeService).GetValueOrDefault() == false; if (!showMessage) { return noUpdateResult; @@ -364,7 +364,7 @@ private async Task CheckUpdateAsync(bool enforce = false, boo public ActionResult InstallUpdate(string packageUrl) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); try @@ -385,7 +385,7 @@ public ActionResult InstallUpdate(string packageUrl) } else { - _services.WebHelper.RestartAppDomain(); + _commonServices.WebHelper.RestartAppDomain(); } } @@ -453,12 +453,12 @@ public ActionResult SystemInfo() model.ServerTimeZone = TimeZone.CurrentTimeZone.StandardName; model.ServerLocalTime = DateTime.Now; model.UtcTime = DateTime.UtcNow; - model.HttpHost = _services.WebHelper.ServerVariables("HTTP_HOST"); + model.HttpHost = _commonServices.WebHelper.ServerVariables("HTTP_HOST"); //Environment.GetEnvironmentVariable("USERNAME"); try { - var mbSize = _services.DbContext.SqlQuery("Select Sum(size)/128.0 From sysfiles").FirstOrDefault(); + var mbSize = _commonServices.DbContext.SqlQuery("Select Sum(size)/128.0 From sysfiles").FirstOrDefault(); model.DatabaseSize = Convert.ToDouble(mbSize); } catch (Exception) { } @@ -468,7 +468,7 @@ public ActionResult SystemInfo() if (DataSettings.Current.IsValid()) { model.DataProviderFriendlyName = DataSettings.Current.ProviderFriendlyName; - model.ShrinkDatabaseEnabled = _services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance) && DataSettings.Current.IsSqlServer; + model.ShrinkDatabaseEnabled = _commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance) && DataSettings.Current.IsSqlServer; } } catch (Exception) { } @@ -498,33 +498,70 @@ public ActionResult Warnings() var model = new List(); //store URL - var currentStoreUrl = _services.StoreContext.CurrentStore.Url.EnsureEndsWith("/"); - if (currentStoreUrl.HasValue() && (currentStoreUrl.IsCaseInsensitiveEqual(_services.WebHelper.GetStoreLocation(false)) || currentStoreUrl.IsCaseInsensitiveEqual(_services.WebHelper.GetStoreLocation(true)))) - model.Add(new SystemWarningModel() - { - Level = SystemWarningLevel.Pass, - Text = _localizationService.GetResource("Admin.System.Warnings.URL.Match") - }); - else - model.Add(new SystemWarningModel() - { - Level = SystemWarningLevel.Warning, - Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.URL.NoMatch"), currentStoreUrl, _services.WebHelper.GetStoreLocation(false)) - }); + var storeUrl = _commonServices.StoreContext.CurrentStore.Url.EnsureEndsWith("/"); + if (storeUrl.HasValue() && (storeUrl.IsCaseInsensitiveEqual(_commonServices.WebHelper.GetStoreLocation(false)) || storeUrl.IsCaseInsensitiveEqual(_commonServices.WebHelper.GetStoreLocation(true)))) + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Pass, + Text = _localizationService.GetResource("Admin.System.Warnings.URL.Match") + }); + } + else + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Warning, + Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.URL.NoMatch"), storeUrl, _commonServices.WebHelper.GetStoreLocation(false)) + }); + } + + // sitemap reachability + var sitemapReachable = false; + try + { + var sitemapUrl = Url.RouteUrl("SitemapSEO", (object)null, _securitySettings.Value.ForceSslForAllPages ? "https" : "http"); + var request = (HttpWebRequest)WebRequest.Create(sitemapUrl); + request.Method = "HEAD"; + request.Timeout = 15000; + + using (var response = (HttpWebResponse)request.GetResponse()) + { + sitemapReachable = (response.StatusCode == HttpStatusCode.OK); + } + } + catch (WebException) { } + if (sitemapReachable) + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Pass, + Text = _localizationService.GetResource("Admin.System.Warnings.SitemapReachable.OK") + }); + } + else + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Warning, + Text = _localizationService.GetResource("Admin.System.Warnings.SitemapReachable.Wrong") + }); + } //primary exchange rate currency var perCurrency = _currencyService.Value.GetCurrencyById(_currencySettings.Value.PrimaryExchangeRateCurrencyId); if (perCurrency != null) { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = _localizationService.GetResource("Admin.System.Warnings.ExchangeCurrency.Set"), }); + if (perCurrency.Rate != 1) { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = _localizationService.GetResource("Admin.System.Warnings.ExchangeCurrency.Rate1") @@ -533,7 +570,7 @@ public ActionResult Warnings() } else { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = _localizationService.GetResource("Admin.System.Warnings.ExchangeCurrency.NotSet") @@ -544,7 +581,7 @@ public ActionResult Warnings() var pscCurrency = _currencyService.Value.GetCurrencyById(_currencySettings.Value.PrimaryStoreCurrencyId); if (pscCurrency != null) { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = _localizationService.GetResource("Admin.System.Warnings.PrimaryCurrency.Set"), @@ -552,7 +589,7 @@ public ActionResult Warnings() } else { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = _localizationService.GetResource("Admin.System.Warnings.PrimaryCurrency.NotSet") @@ -564,7 +601,7 @@ public ActionResult Warnings() var bWeight = _measureService.Value.GetMeasureWeightById(_measureSettings.Value.BaseWeightId); if (bWeight != null) { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = _localizationService.GetResource("Admin.System.Warnings.DefaultWeight.Set"), @@ -572,7 +609,7 @@ public ActionResult Warnings() if (bWeight.Ratio != 1) { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = _localizationService.GetResource("Admin.System.Warnings.DefaultWeight.Ratio1") @@ -581,7 +618,7 @@ public ActionResult Warnings() } else { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = _localizationService.GetResource("Admin.System.Warnings.DefaultWeight.NotSet") @@ -593,7 +630,7 @@ public ActionResult Warnings() var bDimension = _measureService.Value.GetMeasureDimensionById(_measureSettings.Value.BaseDimensionId); if (bDimension != null) { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Pass, Text = _localizationService.GetResource("Admin.System.Warnings.DefaultDimension.Set"), @@ -601,7 +638,7 @@ public ActionResult Warnings() if (bDimension.Ratio != 1) { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = _localizationService.GetResource("Admin.System.Warnings.DefaultDimension.Ratio1") @@ -610,7 +647,7 @@ public ActionResult Warnings() } else { - model.Add(new SystemWarningModel() + model.Add(new SystemWarningModel { Level = SystemWarningLevel.Fail, Text = _localizationService.GetResource("Admin.System.Warnings.DefaultDimension.NotSet") @@ -619,91 +656,107 @@ public ActionResult Warnings() // shipping rate coputation methods if (_shippingService.Value.LoadActiveShippingRateComputationMethods() - .Where(x => x.Value.ShippingRateComputationMethodType == ShippingRateComputationMethodType.Offline) - .Count() > 1) - model.Add(new SystemWarningModel() - { - Level = SystemWarningLevel.Warning, - Text = _localizationService.GetResource("Admin.System.Warnings.Shipping.OnlyOneOffline") - }); + .Where(x => x.Value.ShippingRateComputationMethodType == ShippingRateComputationMethodType.Offline) + .Count() > 1) + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Warning, + Text = _localizationService.GetResource("Admin.System.Warnings.Shipping.OnlyOneOffline") + }); + } //payment methods - if (_paymentService.Value.LoadActivePaymentMethods() - .Count() > 0) - model.Add(new SystemWarningModel() - { - Level = SystemWarningLevel.Pass, - Text = _localizationService.GetResource("Admin.System.Warnings.PaymentMethods.OK") - }); - else - model.Add(new SystemWarningModel() - { - Level = SystemWarningLevel.Fail, - Text = _localizationService.GetResource("Admin.System.Warnings.PaymentMethods.NoActive") - }); + if (_paymentService.Value.LoadActivePaymentMethods().Count() > 0) + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Pass, + Text = _localizationService.GetResource("Admin.System.Warnings.PaymentMethods.OK") + }); + } + else + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Fail, + Text = _localizationService.GetResource("Admin.System.Warnings.PaymentMethods.NoActive") + }); + } //incompatible plugins - if (PluginManager.IncompatiblePlugins != null) - foreach (var pluginName in PluginManager.IncompatiblePlugins) - model.Add(new SystemWarningModel() - { - Level = SystemWarningLevel.Warning, - Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.IncompatiblePlugin"), pluginName ) - }); + if (PluginManager.IncompatiblePlugins != null) + { + foreach (var pluginName in PluginManager.IncompatiblePlugins) + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Warning, + Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.IncompatiblePlugin"), pluginName) + }); + } + } //validate write permissions (the same procedure like during installation) var dirPermissionsOk = true; - var dirsToCheck = FilePermissionHelper.GetDirectoriesWrite(_services.WebHelper); - foreach (string dir in dirsToCheck) - if (!FilePermissionHelper.CheckPermissions(dir, false, true, true, false)) - { - model.Add(new SystemWarningModel() - { - Level = SystemWarningLevel.Warning, - Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.DirectoryPermission.Wrong"), WindowsIdentity.GetCurrent().Name, dir) - }); - dirPermissionsOk = false; - } - if (dirPermissionsOk) - model.Add(new SystemWarningModel() - { - Level = SystemWarningLevel.Pass, - Text = _localizationService.GetResource("Admin.System.Warnings.DirectoryPermission.OK") - }); + var dirsToCheck = FilePermissionHelper.GetDirectoriesWrite(_commonServices.WebHelper); + foreach (string dir in dirsToCheck) + { + if (!FilePermissionHelper.CheckPermissions(dir, false, true, true, false)) + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Warning, + Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.DirectoryPermission.Wrong"), WindowsIdentity.GetCurrent().Name, dir) + }); + dirPermissionsOk = false; + } + } + if (dirPermissionsOk) + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Pass, + Text = _localizationService.GetResource("Admin.System.Warnings.DirectoryPermission.OK") + }); + } var filePermissionsOk = true; - var filesToCheck = FilePermissionHelper.GetFilesWrite(_services.WebHelper); - foreach (string file in filesToCheck) - if (!FilePermissionHelper.CheckPermissions(file, false, true, true, true)) - { - model.Add(new SystemWarningModel - { - Level = SystemWarningLevel.Warning, - Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.FilePermission.Wrong"), WindowsIdentity.GetCurrent().Name, file) - }); - filePermissionsOk = false; - } - if (filePermissionsOk) - model.Add(new SystemWarningModel - { - Level = SystemWarningLevel.Pass, - Text = _localizationService.GetResource("Admin.System.Warnings.FilePermission.OK") - }); - + var filesToCheck = FilePermissionHelper.GetFilesWrite(_commonServices.WebHelper); + foreach (string file in filesToCheck) + { + if (!FilePermissionHelper.CheckPermissions(file, false, true, true, true)) + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Warning, + Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.FilePermission.Wrong"), WindowsIdentity.GetCurrent().Name, file) + }); + filePermissionsOk = false; + } + } + if (filePermissionsOk) + { + model.Add(new SystemWarningModel + { + Level = SystemWarningLevel.Pass, + Text = _localizationService.GetResource("Admin.System.Warnings.FilePermission.OK") + }); + } return View(model); } public ActionResult ShrinkDatabase() { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); try { if (DataSettings.Current.IsSqlServer) { - _services.DbContext.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); + _commonServices.DbContext.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); NotifySuccess(_localizationService.GetResource("Common.ShrinkDatabaseSuccessful")); } } @@ -717,7 +770,7 @@ public ActionResult ShrinkDatabase() public ActionResult Maintenance() { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); var model = new MaintenanceModel(); @@ -738,7 +791,7 @@ public ActionResult Maintenance() [FormValueRequired("delete-image-cache")] public ActionResult MaintenanceDeleteImageCache() { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); _imageCache.Value.DeleteCachedImages(); @@ -750,7 +803,7 @@ public ActionResult MaintenanceDeleteImageCache() [FormValueRequired("delete-guests")] public ActionResult MaintenanceDeleteGuests(MaintenanceModel model) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); DateTime? startDateValue = (model.DeleteGuests.StartDate == null) ? null @@ -768,7 +821,7 @@ public ActionResult MaintenanceDeleteGuests(MaintenanceModel model) [FormValueRequired("delete-exported-files")] public ActionResult MaintenanceDeleteFiles(MaintenanceModel model) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); DateTime? startDateValue = (model.DeleteExportedFiles.StartDate == null) ? null @@ -812,7 +865,7 @@ public ActionResult MaintenanceDeleteFiles(MaintenanceModel model) [FormValueRequired("execute-sql-query")] public ActionResult MaintenanceExecuteSql(MaintenanceModel model) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); if (model.SqlQuery.HasValue()) @@ -837,9 +890,9 @@ public ActionResult MaintenanceExecuteSql(MaintenanceModel model) public ActionResult LanguageSelector() { var model = new LanguageSelectorModel(); - model.CurrentLanguage = _services.WorkContext.WorkingLanguage.ToModel(); + model.CurrentLanguage = _commonServices.WorkContext.WorkingLanguage.ToModel(); model.AvailableLanguages = _languageService - .GetAllLanguages(storeId: _services.StoreContext.CurrentStore.Id) + .GetAllLanguages(storeId: _commonServices.StoreContext.CurrentStore.Id) .Select(x => x.ToModel()) .ToList(); return PartialView(model); @@ -849,14 +902,14 @@ public ActionResult LanguageSelected(int customerlanguage) var language = _languageService.GetLanguageById(customerlanguage); if (language != null) { - _services.WorkContext.WorkingLanguage = language; + _commonServices.WorkContext.WorkingLanguage = language; } return Content(_localizationService.GetResource("Admin.Common.DataEditSuccess")); } public ActionResult ClearCache(string previousUrl) { - var cacheManager = _services.Cache; + var cacheManager = _commonServices.Cache; cacheManager.Clear(); cacheManager = _cache("aspnet"); @@ -872,10 +925,10 @@ public ActionResult ClearCache(string previousUrl) public ActionResult RestartApplication(string previousUrl) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); - _services.WebHelper.RestartAppDomain(); + _commonServices.WebHelper.RestartAppDomain(); if (previousUrl.HasValue()) return Redirect(previousUrl); @@ -889,7 +942,7 @@ public ActionResult RestartApplication(string previousUrl) public ActionResult SeNames() { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); var model = new UrlRecordListModel(); @@ -899,7 +952,7 @@ public ActionResult SeNames() [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult SeNames(GridCommand command, UrlRecordListModel model) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); var urlRecords = _urlRecordService.GetAllUrlRecords(model.SeName, command.Page - 1, command.PageSize); @@ -938,7 +991,7 @@ public ActionResult SeNames(GridCommand command, UrlRecordListModel model) [HttpPost] public ActionResult DeleteSelectedSeNames(ICollection selectedIds) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); if (selectedIds != null) @@ -973,10 +1026,10 @@ public ActionResult GenericAttributes(string entityName, int entityId) [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributesSelect(string entityName, int entityId, GridCommand command) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); - var storeId = _services.StoreContext.CurrentStore.Id; + var storeId = _commonServices.StoreContext.CurrentStore.Id; ViewBag.StoreId = storeId; var model = new List(); @@ -1011,7 +1064,7 @@ public ActionResult GenericAttributesSelect(string entityName, int entityId, Gri [GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributeAdd(GenericAttributeModel model, GridCommand command) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); model.Key = model.Key.TrimSafe(); @@ -1024,7 +1077,7 @@ public ActionResult GenericAttributeAdd(GenericAttributeModel model, GridCommand return Content(modelStateErrorMessages.FirstOrDefault()); } - var storeId = _services.StoreContext.CurrentStore.Id; + var storeId = _commonServices.StoreContext.CurrentStore.Id; var attr = _genericAttributeService.GetAttribute(model.EntityName, model.EntityId, model.Key, storeId); if (attr == null) @@ -1050,7 +1103,7 @@ public ActionResult GenericAttributeAdd(GenericAttributeModel model, GridCommand [GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributeUpdate(GenericAttributeModel model, GridCommand command) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); model.Key = model.Key.TrimSafe(); @@ -1063,7 +1116,7 @@ public ActionResult GenericAttributeUpdate(GenericAttributeModel model, GridComm return Content(modelStateErrorMessages.FirstOrDefault()); } - var storeId = _services.StoreContext.CurrentStore.Id; + var storeId = _commonServices.StoreContext.CurrentStore.Id; var attr = _genericAttributeService.GetAttributeById(model.Id); // if the key changed, ensure it isn't being used by another attribute @@ -1089,7 +1142,7 @@ public ActionResult GenericAttributeUpdate(GenericAttributeModel model, GridComm [GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributeDelete(int id, GridCommand command) { - if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); var attr = _genericAttributeService.GetAttributeById(id); From d300433196e3adc89f314d14c8b791124e0101f9 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 24 Jun 2015 16:33:04 +0200 Subject: [PATCH 0175/1256] The discount tab should be hidden for bundles with activated per-item-pricing option --- .../Views/Product/_CreateOrUpdate.BundleItems.cshtml | 4 +++- .../Administration/Views/Product/_CreateOrUpdate.cshtml | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.BundleItems.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.BundleItems.cshtml index f750912c51..edab6a805b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.BundleItems.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.BundleItems.cshtml @@ -150,7 +150,9 @@ }); $(document).on('change', '#@Html.FieldIdFor(model => model.BundlePerItemPricing)', function () { - $('#TierPriceContainer').toggle(!$(this).is(':checked')); + var isChecked = $(this).is(':checked'); + $('#TierPriceContainer').toggle(!isChecked); + $('a[href=#tab-discounts]').parent().toggle(!isChecked); }); $(document).on('change', '#@Html.FieldIdFor(model => model.BundlePerItemShoppingCart)', function () { diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.cshtml index 90abd97a81..4f5763b2db 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.cshtml @@ -64,6 +64,8 @@ } x.Add().Text(T("Admin.Catalog.Products.Discounts").Text) + .Name("tab-discounts") + .Visible(!(Model.ProductTypeId == (int)ProductType.BundledProduct && Model.BundlePerItemPricing)) .Icon("fa fa-signal fa-lg fa-flip-horizontal fa-fw") .LinkHtmlAttributes(new { data_tab_name = "Discounts" }) .Action("LoadEditTab", "Product", new { id = Model.Id, tabName = "Discounts" }) From f25e03d48ab6d454ee1c2bfd7a40fc8d5d8ea1b4 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 23 Jun 2015 22:31:12 +0200 Subject: [PATCH 0176/1256] Minor fixes in readme.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9652a45276..39784f16b0 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ SmartStore.NET is a free, open source, full-featured e-commerce solution for com **SmartStore.NET includes all essential features to create multilingual and multi-currency stores** targeting desktop or mobile devices and enabling SEO optimized rich product catalogs with support for an unlimited number of products and categories, variants, bundles, datasheets, ESD, discounts, coupons and many more. -A comprehensive set of tools for CRM & CMS, sales, marketing, payment & shipping handling among others makes SmartStore.NET a powerful all-in-one solution fulfilling all your needs... totally FREE! +A comprehensive set of tools for CRM & CMS, sales, marketing, payment & shipping handling, etc. makes SmartStore.NET a powerful all-in-one solution fulfilling all your needs... totally FREE! -**SmartStore.NET delivers a beautiful and configurable shop frontend out-of-the-box** built with a design approach on the highest level, including components like `Twitter Bootstrap`, `Less CSS` and others. The innovative ShopBar, a powerful layered navigation, reviews & ratings, an optimized checkout process... they all provide a perfect shopping experience to your buyers. +**SmartStore.NET delivers a beautiful and configurable shop front-end out-of-the-box**, built with a design approach on the highest level, including components like `Twitter Bootstrap`, `Less CSS` and others. The innovative ShopBar, a powerful layered navigation, reviews & ratings, an optimized checkout process... they all provide a perfect shopping experience for your buyers. The state-of-the-art architecture of SmartStore.NET - with `ASP.NET 4.5` + `MVC 5`, `Entity Framework 6` and Domain Driven Design approach - makes it easy to extend, extremely flexible and essentially fun to work with ;-) @@ -26,7 +26,7 @@ The state-of-the-art architecture of SmartStore.NET - with `ASP.NET 4.5` + `MVC * State of the art architecture thanks to `ASP.NET 4.5`, `ASP.NET MVC 5`, `Entity Framework 6` and Domain Driven Design * Easy to extend and extremely flexible thanks to modular design * (NEW) A powerful theming engine lets you create themes & skins with minimum effort thanks to theme inheritance -* Consistent and sophisticated use of modern components such as `jQuery`, `Twitter Bootstrap`, `LESS` & more in the frontend and backend. +* Consistent and sophisticated use of modern components such as `jQuery`, `Twitter Bootstrap`, `LESS` & more in the front and back end. * Easy shop management thanks to modern and clean UI * Out of the box shop design on the highest level * Revolutionary Shopbar for the best shopping experience From 9cef73e9fe6fcbf2d4e26a54659dfbd3af5d20c7 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 23 Jun 2015 23:00:45 +0200 Subject: [PATCH 0177/1256] Updated GMC taxonomy files --- .../Files/taxonomy.de-DE.txt | 5163 +++++++--------- .../Files/taxonomy.en-US.txt | 5400 +++++++---------- 2 files changed, 4516 insertions(+), 6047 deletions(-) diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/Files/taxonomy.de-DE.txt b/src/Plugins/SmartStore.GoogleMerchantCenter/Files/taxonomy.de-DE.txt index c21aaa3e62..6be270d3aa 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/Files/taxonomy.de-DE.txt +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/Files/taxonomy.de-DE.txt @@ -1,13 +1,13 @@ Baby & Kleinkind -Baby & Kleinkind > Baby baden -Baby & Kleinkind > Baby baden > Babybadewannen -Baby & Kleinkind > Baby baden > Shampoo-Schutzschilder -Baby & Kleinkind > Babygesundheit -Baby & Kleinkind > Babygesundheit > Baby-Gesundheits- & Pflege-Sets -Baby & Kleinkind > Babygesundheit > Nasensauger -Baby & Kleinkind > Babygesundheit > Reinigungstücher für Schnuller -Baby & Kleinkind > Babygesundheit > Schnuller & Beißringe -Baby & Kleinkind > Babygesundheit > Schnullerclips & -ketten +Baby & Kleinkind > Baby Badebedarf +Baby & Kleinkind > Baby Badebedarf > Babybadewannen +Baby & Kleinkind > Baby Badebedarf > Shampoo-Schutzschilder +Baby & Kleinkind > Baby Gesundheitsbedarf +Baby & Kleinkind > Baby Gesundheitsbedarf > Baby-Gesundheits- & Pflegesets +Baby & Kleinkind > Baby Gesundheitsbedarf > Nasensauger +Baby & Kleinkind > Baby Gesundheitsbedarf > Reinigungstücher für Schnuller +Baby & Kleinkind > Baby Gesundheitsbedarf > Schnuller & Beißringe +Baby & Kleinkind > Baby Gesundheitsbedarf > Schnullerclips & -ketten Baby & Kleinkind > Babysicherheit Baby & Kleinkind > Babysicherheit > Baby- & Haustierschutzgitter Baby & Kleinkind > Babysicherheit > Baby-Schutzleisten @@ -17,28 +17,30 @@ Baby & Kleinkind > Babysicherheit > Babysicherungen & Schutzvorrichtungen Baby & Kleinkind > Babysicherheit > Zubehör für Baby- & Haustierschutzgitter Baby & Kleinkind > Babyspielwaren Baby & Kleinkind > Babyspielwaren > ABC-Lernspielzeuge -Baby & Kleinkind > Babyspielwaren > Baby-Activity-Spielzeug +Baby & Kleinkind > Babyspielwaren > Baby-Aktiv-Spielzeug Baby & Kleinkind > Babyspielwaren > Baby-Mobile-Zubehör Baby & Kleinkind > Babyspielwaren > Baby-Mobiles Baby & Kleinkind > Babyspielwaren > Babylauflernhilfen Baby & Kleinkind > Babyspielwaren > Babyrasseln Baby & Kleinkind > Babyspielwaren > Babyschaukeln & Türhopser Baby & Kleinkind > Babyspielwaren > Babywippen -Baby & Kleinkind > Babyspielwaren > Lauf- & Spielgitter -Baby & Kleinkind > Babyspielwaren > Schnuller und Beruhigung +Baby & Kleinkind > Babyspielwaren > Lauf- & Spielgitterreinigungst +Baby & Kleinkind > Babyspielwaren > Schnuller & Beruhigung Baby & Kleinkind > Babyspielwaren > Sortier-, Stapel- & Steckspielzeug Baby & Kleinkind > Babyspielwaren > Spiel- & Krabbeldecken Baby & Kleinkind > Babyspielwaren > Zieh- & Schiebespielzeug Baby & Kleinkind > Babytransport Baby & Kleinkind > Babytransport > Baby- & Kleinkindautositze -Baby & Kleinkind > Babytransport > Babytragen +Baby & Kleinkind > Babytransport > Babyträger Baby & Kleinkind > Babytransport > Kinderwagen Baby & Kleinkind > Babytransportzubehör Baby & Kleinkind > Babytransportzubehör > Einkaufswagen- & Hochstuhlbezüge +Baby & Kleinkind > Babytransportzubehör > Fußsäcke Baby & Kleinkind > Babytransportzubehör > Zubehör für Baby- & Kleinkindautositze -Baby & Kleinkind > Babytransportzubehör > Zubehör für Babytragen +Baby & Kleinkind > Babytransportzubehör > Zubehör für Babyträger Baby & Kleinkind > Babytransportzubehör > Zubehör für Kinderwagen -Baby & Kleinkind > Geschenksets für Babys und Kleinkinder +Baby & Kleinkind > Geschenksets für Babys +Baby & Kleinkind > Puckdecken Baby & Kleinkind > Stillen & Füttern Baby & Kleinkind > Stillen & Füttern > Baby-Spucktücher Baby & Kleinkind > Stillen & Füttern > Babyflaschen @@ -47,17 +49,19 @@ Baby & Kleinkind > Stillen & Füttern > Flaschenwärmer & Sterilisatoren Baby & Kleinkind > Stillen & Füttern > Lerntassen Baby & Kleinkind > Stillen & Füttern > Lätzchen Baby & Kleinkind > Stillen & Füttern > Milchpumpen +Baby & Kleinkind > Stillen & Füttern > Milchpumpenzubehör Baby & Kleinkind > Stillen & Füttern > Muttermilchbehälter Baby & Kleinkind > Stillen & Füttern > Nahrung für Babys & Kleinkinder Baby & Kleinkind > Stillen & Füttern > Nahrung für Babys & Kleinkinder > Baby-Snacks -Baby & Kleinkind > Stillen & Füttern > Nahrung für Babys & Kleinkinder > Babymüsli +Baby & Kleinkind > Stillen & Füttern > Nahrung für Babys & Kleinkinder > Babygetreide Baby & Kleinkind > Stillen & Füttern > Nahrung für Babys & Kleinkinder > Babynahrung Baby & Kleinkind > Stillen & Füttern > Nahrung für Babys & Kleinkinder > Babysäfte +Baby & Kleinkind > Stillen & Füttern > Nahrung für Babys & Kleinkinder > Getränke und Milchmischgetränke Baby & Kleinkind > Stillen & Füttern > Nahrung für Babys & Kleinkinder > Milchnahrung Baby & Kleinkind > Stillen & Füttern > Sauger für Babyflaschen -Baby & Kleinkind > Stillen & Füttern > Stilleinlagen -Baby & Kleinkind > Stillen & Füttern > Stillhütchen +Baby & Kleinkind > Stillen & Füttern > Stillhütchen & -einlagen Baby & Kleinkind > Stillen & Füttern > Stillkissen +Baby & Kleinkind > Stillen & Füttern > Stillkissenbezüge Baby & Kleinkind > Stillen & Füttern > Stilltücher Baby & Kleinkind > Töpfchentraining Baby & Kleinkind > Töpfchentraining > Töpfchen @@ -67,6 +71,7 @@ Baby & Kleinkind > Wickelbedarf > Baby-Reinigungstücher Baby & Kleinkind > Wickelbedarf > Behandlung von Windeldermatitis Baby & Kleinkind > Wickelbedarf > Behälter & Warmhalter für Baby-Reinigungstücher Baby & Kleinkind > Wickelbedarf > Wickelauflagen +Baby & Kleinkind > Wickelbedarf > Wickelauflagen & Bezüge Baby & Kleinkind > Wickelbedarf > Windel-Organizer Baby & Kleinkind > Wickelbedarf > Windelbeutel Baby & Kleinkind > Wickelbedarf > Windeleimer @@ -74,19 +79,17 @@ Baby & Kleinkind > Wickelbedarf > Windeleimerzubehör Baby & Kleinkind > Wickelbedarf > Windeleinlagen Baby & Kleinkind > Wickelbedarf > Windeln Baby & Kleinkind > Wickelbedarf > Windelsets -Baby & Kleinkind > Wickeldecken Bekleidung & Accessoires Bekleidung & Accessoires > Bekleidung Bekleidung & Accessoires > Bekleidung > Anzüge -Bekleidung & Accessoires > Bekleidung > Anzüge > Hosenanzüge +Bekleidung & Accessoires > Bekleidung > Anzüge > Anzüge & Hosenanzüge Bekleidung & Accessoires > Bekleidung > Anzüge > Kostüme Bekleidung & Accessoires > Bekleidung > Anzüge > Smokings -Bekleidung & Accessoires > Bekleidung > Anzüge > Westen & Sakkos Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Baby- & Kleinkind-Kombis Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Baby- & Kleinkind-Oberbekleidung Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Baby- & Kleinkindsocken -Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Baby-Bodies +Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Baby-Bodys Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Baby-Schlafkleidung & -Schlafsäcke Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Babyüberhosen Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Bademode für Babys & Kleinkinder @@ -95,14 +98,6 @@ Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Kleinkindu Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Oberteile für Babys & Kleinkinder Bekleidung & Accessoires > Bekleidung > Baby- & Kleinkindbekleidung > Unterteile für Babys & Kleinkinder Bekleidung & Accessoires > Bekleidung > Bademode -Bekleidung & Accessoires > Bekleidung > Bademode > Badeshorts -Bekleidung & Accessoires > Bekleidung > Bademode > Badeslips -Bekleidung & Accessoires > Bekleidung > Bademode > Bikini Oberteile -Bekleidung & Accessoires > Bekleidung > Bademode > Bikini Unterteile -Bekleidung & Accessoires > Bekleidung > Bademode > Bikinis -Bekleidung & Accessoires > Bekleidung > Bademode > Einteiler-Badeanzüge -Bekleidung & Accessoires > Bekleidung > Bademode > Strandkleider -Bekleidung & Accessoires > Bekleidung > Bademode > Tankinis Bekleidung & Accessoires > Bekleidung > Brautmoden Bekleidung & Accessoires > Bekleidung > Brautmoden > Brautjungfernkleider Bekleidung & Accessoires > Bekleidung > Brautmoden > Brautkleider @@ -111,19 +106,7 @@ Bekleidung & Accessoires > Bekleidung > Einteiler > Latzhosen Bekleidung & Accessoires > Bekleidung > Einteiler > Overalls Bekleidung & Accessoires > Bekleidung > Einteiler > Turn- & Gymnastikanzüge Bekleidung & Accessoires > Bekleidung > Hosen -Bekleidung & Accessoires > Bekleidung > Hosen > Anzughosen -Bekleidung & Accessoires > Bekleidung > Hosen > Cargo-Hosen -Bekleidung & Accessoires > Bekleidung > Hosen > Cordhosen -Bekleidung & Accessoires > Bekleidung > Hosen > Jeans -Bekleidung & Accessoires > Bekleidung > Hosen > Khakihosen -Bekleidung & Accessoires > Bekleidung > Hosen > Leder- & Wildlederhosen -Bekleidung & Accessoires > Bekleidung > Hosen > Leggings -Bekleidung & Accessoires > Bekleidung > Hosen > Leinenhosen Bekleidung & Accessoires > Bekleidung > Kleider -Bekleidung & Accessoires > Bekleidung > Kleider > Abend- & Ballkleider -Bekleidung & Accessoires > Bekleidung > Kleider > Alltagskleider -Bekleidung & Accessoires > Bekleidung > Kleider > Cocktail- & Partykleider -Bekleidung & Accessoires > Bekleidung > Kleider > Kleines Schwarzes Bekleidung & Accessoires > Bekleidung > Kombinationen Bekleidung & Accessoires > Bekleidung > Nachtwäsche & Loungewear Bekleidung & Accessoires > Bekleidung > Nachtwäsche & Loungewear > Bademäntel @@ -132,28 +115,16 @@ Bekleidung & Accessoires > Bekleidung > Nachtwäsche & Loungewear > Nachthemden Bekleidung & Accessoires > Bekleidung > Nachtwäsche & Loungewear > Schlafanzüge Bekleidung & Accessoires > Bekleidung > Röcke Bekleidung & Accessoires > Bekleidung > Shirts & Tops -Bekleidung & Accessoires > Bekleidung > Shirts & Tops > Fantrikots -Bekleidung & Accessoires > Bekleidung > Shirts & Tops > Hemden & Blusen -Bekleidung & Accessoires > Bekleidung > Shirts & Tops > Leibchen -Bekleidung & Accessoires > Bekleidung > Shirts & Tops > Poloshirts -Bekleidung & Accessoires > Bekleidung > Shirts & Tops > Sweater & Strickjacken -Bekleidung & Accessoires > Bekleidung > Shirts & Tops > Sweatshirts -Bekleidung & Accessoires > Bekleidung > Shirts & Tops > T-Shirts Bekleidung & Accessoires > Bekleidung > Shorts -Bekleidung & Accessoires > Bekleidung > Shorts > Bermudashorts -Bekleidung & Accessoires > Bekleidung > Shorts > Cargo-Shorts -Bekleidung & Accessoires > Bekleidung > Shorts > Hot Pants Bekleidung & Accessoires > Bekleidung > Skorts Bekleidung & Accessoires > Bekleidung > Sportbekleidung Bekleidung & Accessoires > Bekleidung > Sportbekleidung > American Football-Hosen Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Boxshorts -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Gymnastik- & Ballettanzüge Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Jagdbekleidung Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Jagdbekleidung > Ghillie-Anzüge +Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Jagdbekleidung > Jagd- & Angelwesten Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Jagdbekleidung > Jagd- & taktische Hosen -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Jagdbekleidung > Jagd- & taktische Westen Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Kampfsporthosen -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Lange Unterhosen Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Motorradbekleidung Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Motorradbekleidung > Motorrad-Kombis Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Motorradbekleidung > Motorradhosen @@ -165,43 +136,17 @@ Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Radsport-Funktionsbekl Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Radsport-Funktionsbekleidung > Fahrradtrikots Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Radsport-Funktionsbekleidung > Fahrradträgerhosen Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Radsport-Funktionsbekleidung > Radsport-Zeitfahranzüge -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Saunaanzüge -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Schneehosen und - anzüge -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sport-Tanktops -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sporthosen -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sporthosen (kurz) -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sportjacken -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sportjacken > Windbreakers -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sportkleider -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sportröcke -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sportshirts -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sportunterkleidung -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sportunterkleidung > Kompressionshose (kurz) -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sportunterkleidung > Sport-BHs -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sportunterkleidung > Sportunterwäsche -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Sportunterkleidung > Suspensorien -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Tanzkleidung -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Tanzkleidung > Tanz-Leggings -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Tanzkleidung > Tanz-Oberteile -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Tanzkleidung > Tanzhosen -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Tanzkleidung > Tanzkleider -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Tanzkleidung > Tanzröcke -Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Trainingsanzüge +Bekleidung & Accessoires > Bekleidung > Sportbekleidung > Tanzkleider, Tanzröcke und Tanzkostüme Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Dirndl Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Hakama-Hosen Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Kimono-Oberbekleidung -Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Kimono-Oberbekleidung > Haori-Jacken -Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Kimono-Oberbekleidung > Kimono-Mäntel Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Kimonos -Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Kimonos > Furisode-Kimonos -Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Kimonos > Hochzeitskimonos -Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Kimonos > Informelle Kimonos -Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Kimonos > Iromuji-Kimonos -Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Kimonos > Komon-Kimonos -Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Kimonos > Tomesode- & Houmongi-Kimonos Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Religiöse Festkleidung +Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Religiöse Festkleidung > Tauf- & Kommunionskleider +Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Saris Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Trachten Lederhosen +Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Traditionelle japanische formelle Kleidung Bekleidung & Accessoires > Bekleidung > Traditionelle & Festkleidung > Yukata Bekleidung & Accessoires > Bekleidung > Uniformen Bekleidung & Accessoires > Bekleidung > Uniformen > Arbeitshosen @@ -222,62 +167,45 @@ Bekleidung & Accessoires > Bekleidung > Uniformen > Sportuniformen > Ringerunifo Bekleidung & Accessoires > Bekleidung > Uniformen > Sportuniformen > Schiedsrichteruniformen Bekleidung & Accessoires > Bekleidung > Uniformen > Sportuniformen > Softballuniformen Bekleidung & Accessoires > Bekleidung > Uniformen > Uniformen für das Restaurantgewerbe -Bekleidung & Accessoires > Bekleidung > Uniformen > Uniformen für das Restaurantgewerbe > Hosen für Köche -Bekleidung & Accessoires > Bekleidung > Uniformen > Uniformen für das Restaurantgewerbe > Hüte für Köche +Bekleidung & Accessoires > Bekleidung > Uniformen > Uniformen für das Restaurantgewerbe > Kochhosen Bekleidung & Accessoires > Bekleidung > Uniformen > Uniformen für das Restaurantgewerbe > Kochjacken +Bekleidung & Accessoires > Bekleidung > Uniformen > Uniformen für das Restaurantgewerbe > Kochmützen Bekleidung & Accessoires > Bekleidung > Uniformen > Ärztekittel Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > BH-Zubehör Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > BH-Zubehör > BH-Einlagen Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > BH-Zubehör > BH-Träger & -Erweiterungen Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > BH-Zubehör > BH-Träger-Pads -Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > BH-Zubehör > Brustaufkleber & -Concealer +Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > BH-Zubehör > Brustaufkleber Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Büstenhalter -Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Büstenhalter > Still-BHs Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Dessous Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Dessous-Accessoires Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Dessous-Accessoires > Strumpfbänder Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Dessous-Accessoires > Strumpfhalter -Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Hochzeitsdessous +Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Lange Unterhosen Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Petticoats & Rüschenhöschen Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Shapewear Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Socken Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Strumpfhosen +Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Suspensorien Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Unterhemden Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Unterhosen Bekleidung & Accessoires > Bekleidung > Unterwäsche & Socken > Unterwäsche Bekleidung & Accessoires > Bekleidung > Überbekleidung Bekleidung & Accessoires > Bekleidung > Überbekleidung > Chaps Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Anoraks -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Boleros -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Capes & Ponchos -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > College Jacken -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Daunenjacken -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Fleecejacken -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Jeansjacken -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Leder- & Wildlederjacken -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Overcoats -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Pelzmäntel -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Sakkos -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Trenchcoats -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Mäntel & Jacken > Tweedjacken -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Regenbekleidung -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Regenbekleidung > Regenanzüge -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Regenbekleidung > Regenhosen -Bekleidung & Accessoires > Bekleidung > Überbekleidung > Regenbekleidung > Regenmäntel +Bekleidung & Accessoires > Bekleidung > Überbekleidung > Regenanzüge +Bekleidung & Accessoires > Bekleidung > Überbekleidung > Regenhosen +Bekleidung & Accessoires > Bekleidung > Überbekleidung > Schneehosen und - anzüge Bekleidung & Accessoires > Bekleidung > Überbekleidung > Westen Bekleidung & Accessoires > Bekleidungsaccessoires Bekleidung & Accessoires > Bekleidungsaccessoires > Accessoires für traditionelle Kleidung -Bekleidung & Accessoires > Bekleidungsaccessoires > Accessoires für traditionelle Kleidung > Kimono-Unterkleidung -Bekleidung & Accessoires > Bekleidungsaccessoires > Accessoires für traditionelle Kleidung > Obi-Accessoires Bekleidung & Accessoires > Bekleidungsaccessoires > Accessoires für traditionelle Kleidung > Obis Bekleidung & Accessoires > Bekleidungsaccessoires > Accessoires für traditionelle Kleidung > Tabi-Socken Bekleidung & Accessoires > Bekleidungsaccessoires > Ansteckbuttons -Bekleidung & Accessoires > Bekleidungsaccessoires > Arm- & Beinstulpen -Bekleidung & Accessoires > Bekleidungsaccessoires > Arm- & Beinstulpen > Armstulpen -Bekleidung & Accessoires > Bekleidungsaccessoires > Arm- & Beinstulpen > Beinstulpen +Bekleidung & Accessoires > Bekleidungsaccessoires > Armstulpen Bekleidung & Accessoires > Bekleidungsaccessoires > Bandanas & Stofftücher +Bekleidung & Accessoires > Bekleidungsaccessoires > Beinstulpen Bekleidung & Accessoires > Bekleidungsaccessoires > Braut-Accessoires Bekleidung & Accessoires > Bekleidungsaccessoires > Braut-Accessoires > Brautschleier Bekleidung & Accessoires > Bekleidungsaccessoires > Einstecktücher @@ -286,34 +214,23 @@ Bekleidung & Accessoires > Bekleidungsaccessoires > Gürtel Bekleidung & Accessoires > Bekleidungsaccessoires > Gürtelschnallen Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Diademe +Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Duttkissen Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Haargabeln Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Haargummis -Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Haarklammern +Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Haarklammern, -nadeln & -clips Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Haarkränze Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Haarkämme -Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Haarnadeln & -clips Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Haarnetze Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Haarverlängerungen +Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Perücken +Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Perücken-Accessoires +Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Perücken-Accessoires > Perückenkleber +Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Perücken-Accessoires > Perückennetze Bekleidung & Accessoires > Bekleidungsaccessoires > Haaraccessoires > Stirnbänder Bekleidung & Accessoires > Bekleidungsaccessoires > Halswärmer Bekleidung & Accessoires > Bekleidungsaccessoires > Handschuhe & Fausthandschuhe -Bekleidung & Accessoires > Bekleidungsaccessoires > Handschuhe & Fausthandschuhe > Abendhandschuhe -Bekleidung & Accessoires > Bekleidungsaccessoires > Handschuhe & Fausthandschuhe > Fausthandschuhe -Bekleidung & Accessoires > Bekleidungsaccessoires > Handschuhe & Fausthandschuhe > Handschuhe -Bekleidung & Accessoires > Bekleidungsaccessoires > Handschuhe & Fausthandschuhe > Ski- & Snowboardhandschuhe Bekleidung & Accessoires > Bekleidungsaccessoires > Hosenträger Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Barette -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Cowboyhüte -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Filzhüte -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Kappen -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Kappen > Ballonmützen -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Kappen > Baseballmützen -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Melonen (Hut) -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Mützen -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Schirmhüte -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Sonnenhüte -Bekleidung & Accessoires > Bekleidungsaccessoires > Hüte > Sonnenvisiere Bekleidung & Accessoires > Bekleidungsaccessoires > Knopfnieten Bekleidung & Accessoires > Bekleidungsaccessoires > Kopfbekleidung & -tücher Bekleidung & Accessoires > Bekleidungsaccessoires > Kopfbekleidung & -tücher > Fascinators @@ -321,18 +238,15 @@ Bekleidung & Accessoires > Bekleidungsaccessoires > Kopfbekleidung & -tücher > Bekleidung & Accessoires > Bekleidungsaccessoires > Kopfbekleidung & -tücher > Turbane Bekleidung & Accessoires > Bekleidungsaccessoires > Kragenstäbchen Bekleidung & Accessoires > Bekleidungsaccessoires > Krawatten -Bekleidung & Accessoires > Bekleidungsaccessoires > Krawatten > Ascotkrawatte -Bekleidung & Accessoires > Bekleidungsaccessoires > Krawatten > Bolotie -Bekleidung & Accessoires > Bekleidungsaccessoires > Krawatten > Fliegen -Bekleidung & Accessoires > Bekleidungsaccessoires > Krawatten > Schlipse Bekleidung & Accessoires > Bekleidungsaccessoires > Krawattennadeln Bekleidung & Accessoires > Bekleidungsaccessoires > Leis Bekleidung & Accessoires > Bekleidungsaccessoires > Manschettenknöpfe Bekleidung & Accessoires > Bekleidungsaccessoires > Muffe Bekleidung & Accessoires > Bekleidungsaccessoires > Ohrenschützer Bekleidung & Accessoires > Bekleidungsaccessoires > Schals & Halstücher -Bekleidung & Accessoires > Bekleidungsaccessoires > Schleier +Bekleidung & Accessoires > Bekleidungsaccessoires > Schwangerschaftsgürtel & Bauchstützen Bekleidung & Accessoires > Bekleidungsaccessoires > Schweißbänder +Bekleidung & Accessoires > Bekleidungsaccessoires > Schärpen Bekleidung & Accessoires > Bekleidungsaccessoires > Sonnenbrillen Bekleidung & Accessoires > Bekleidungsaccessoires > Sturmhauben Bekleidung & Accessoires > Bekleidungsaccessoires > Zubehör für Baby- & Kleinkindbekleidung @@ -349,36 +263,25 @@ Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis > Ausweistaschen Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis > Geldbeutel & Geldklammern Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis > Handtaschen -Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis > Handtaschen > Clutches & Taschen für besondere Anlässe -Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis > Handtaschen > Henkeltaschen -Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis > Handtaschen > Hobo-Handtaschen -Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis > Handtaschen > Schultertaschen -Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis > Handtaschen > Tragetaschen -Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis > Handtaschen > Umhängetaschen Bekleidung & Accessoires > Handtaschen, Geldbörsen & Etuis > Visitenkartenetuis Bekleidung & Accessoires > Kostüme & Accessoires -Bekleidung & Accessoires > Kostüme & Accessoires > Accessoires für Perücken -Bekleidung & Accessoires > Kostüme & Accessoires > Accessoires für Perücken > Kappen für Perücken -Bekleidung & Accessoires > Kostüme & Accessoires > Accessoires für Perücken > Kleber für Perücken Bekleidung & Accessoires > Kostüme & Accessoires > Kostümaccessoires Bekleidung & Accessoires > Kostüme & Accessoires > Kostümaccessoires > Glatzen -Bekleidung & Accessoires > Kostüme & Accessoires > Kostümaccessoires > Kostümaccessoire-Sets +Bekleidung & Accessoires > Kostüme & Accessoires > Kostümaccessoires > Kostüm-Accessoire-Sets +Bekleidung & Accessoires > Kostüme & Accessoires > Kostümaccessoires > Kostüm-Handschuhe Bekleidung & Accessoires > Kostüme & Accessoires > Kostümaccessoires > Kostümhüte Bekleidung & Accessoires > Kostüme & Accessoires > Kostümaccessoires > Plastikschmuck +Bekleidung & Accessoires > Kostüme & Accessoires > Kostümaccessoires > Spezial-Schminkeffekte +Bekleidung & Accessoires > Kostüme & Accessoires > Kostümaccessoires > Tabakwarenimitate Bekleidung & Accessoires > Kostüme & Accessoires > Kostümaccessoires > Umhänge für Kostüme Bekleidung & Accessoires > Kostüme & Accessoires > Kostüme & Verkleidungen Bekleidung & Accessoires > Kostüme & Accessoires > Kostümschuhe Bekleidung & Accessoires > Kostüme & Accessoires > Masken -Bekleidung & Accessoires > Kostüme & Accessoires > Perücken Bekleidung & Accessoires > Schmuck -Bekleidung & Accessoires > Schmuck > Armbanduhren -Bekleidung & Accessoires > Schmuck > Armbanduhren > Analoguhren -Bekleidung & Accessoires > Schmuck > Armbanduhren > Digitaluhren +Bekleidung & Accessoires > Schmuck > Armbanduhren & Taschenuhren Bekleidung & Accessoires > Schmuck > Armbänder -Bekleidung & Accessoires > Schmuck > Broschen & Anstecknadeln +Bekleidung & Accessoires > Schmuck > Broschen und Anstecknadeln Bekleidung & Accessoires > Schmuck > Charms & Anhänger -Bekleidung & Accessoires > Schmuck > Edelsteine -Bekleidung & Accessoires > Schmuck > Edelsteine > Diamanten Bekleidung & Accessoires > Schmuck > Fußkettchen Bekleidung & Accessoires > Schmuck > Halsketten Bekleidung & Accessoires > Schmuck > Körperschmuck @@ -396,72 +299,6 @@ Bekleidung & Accessoires > Schuh-Accessoires > Sporen Bekleidung & Accessoires > Schuh-Accessoires > Stiefelsocken Bekleidung & Accessoires > Schuh-Accessoires > Überschuhe Bekleidung & Accessoires > Schuhe -Bekleidung & Accessoires > Schuhe > Abendschuhe & Anzugschuhe -Bekleidung & Accessoires > Schuhe > Abendschuhe & Anzugschuhe > Brautschuhe -Bekleidung & Accessoires > Schuhe > Abendschuhe & Anzugschuhe > Pumps -Bekleidung & Accessoires > Schuhe > Abendschuhe & Anzugschuhe > Pumps > Klassische Pumps -Bekleidung & Accessoires > Schuhe > Abendschuhe & Anzugschuhe > Pumps > Spectator-Pumps -Bekleidung & Accessoires > Schuhe > Abendschuhe & Anzugschuhe > Pumps > d'Orsay Pumps -Bekleidung & Accessoires > Schuhe > Abendschuhe & Anzugschuhe > Schnürschuhe -Bekleidung & Accessoires > Schuhe > Clogs & Pantoletten -Bekleidung & Accessoires > Schuhe > Espadrilles -Bekleidung & Accessoires > Schuhe > Flache Schuhe -Bekleidung & Accessoires > Schuhe > Hausschuhe -Bekleidung & Accessoires > Schuhe > Loafers -Bekleidung & Accessoires > Schuhe > Mokassins -Bekleidung & Accessoires > Schuhe > Outdoor Schuhe -Bekleidung & Accessoires > Schuhe > Outdoor Schuhe > Angel- & Jagdschuhe -Bekleidung & Accessoires > Schuhe > Outdoor Schuhe > Gartenschuhe -Bekleidung & Accessoires > Schuhe > Outdoor Schuhe > Kletterschuhe -Bekleidung & Accessoires > Schuhe > Outdoor Schuhe > Leistungsruderschuhe -Bekleidung & Accessoires > Schuhe > Outdoor Schuhe > Wanderschuhe -Bekleidung & Accessoires > Schuhe > Outdoor Schuhe > Wassersportschuhe -Bekleidung & Accessoires > Schuhe > Sandalen -Bekleidung & Accessoires > Schuhe > Sandalen > Flipflops -Bekleidung & Accessoires > Schuhe > Sandalen > Outdoor Sandalen/vorne geschlossen -Bekleidung & Accessoires > Schuhe > Sandalen > Schlupfsandalen -Bekleidung & Accessoires > Schuhe > Schuhe für Babys & Kleinkinder -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sneakers -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sneakers > Fitness-Schuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sneakers > Laufschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sneakers > Sneakers & Freizeitschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sneakers > Walking-Schuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Ballet- & Tanzschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Basketball-Schuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Bowlingschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Boxschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Cheerleading-Schuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Fahrradschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Gewichtheberschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Golfschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Hallenfussballschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Hallenschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Hallenschuhe > Badmintonschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Hallenschuhe > Handballschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Hallenschuhe > Volleyball-Schuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Ringerschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Skateboard-Schuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Tennis-Schuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Sportschuhe > Tischtennis-Schuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Stollen- & Nockenschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Stollen- & Nockenschuhe > American Football-Schuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Stollen- & Nockenschuhe > Baseball- & Softballschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Stollen- & Nockenschuhe > Fußballschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Stollen- & Nockenschuhe > Lacrosse-Stollenschuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Stollen- & Nockenschuhe > Rugby-Schuhe -Bekleidung & Accessoires > Schuhe > Sportschuhe & Sneakers > Stollen- & Nockenschuhe > Spikes -Bekleidung & Accessoires > Schuhe > Stiefel -Bekleidung & Accessoires > Schuhe > Stiefel > Arbeits- & Sicherheitsstiefel -Bekleidung & Accessoires > Schuhe > Stiefel > Gefütterte Stiefel -Bekleidung & Accessoires > Schuhe > Stiefel > Gummistiefel -Bekleidung & Accessoires > Schuhe > Stiefel > Motorradstiefel -Bekleidung & Accessoires > Schuhe > Stiefel > Reitstiefel -Bekleidung & Accessoires > Schuhe > Stiefel > Schneestiefel -Bekleidung & Accessoires > Schuhe > Stiefel > Stiefeletten -Bekleidung & Accessoires > Schuhe > Stiefel > Western-Stiefel -Bekleidung & Accessoires > Schuhe > Stiefel > Wüsten- & Chukka-Boots Bürobedarf Bürobedarf > Ablage & Organisation Bürobedarf > Ablage & Organisation > Adressbücher @@ -477,24 +314,16 @@ Bürobedarf > Ablage & Organisation > Bindesysteme > Aktenordnerzubehör > Regis Bürobedarf > Ablage & Organisation > Bindesysteme > Bindegeräte Bürobedarf > Ablage & Organisation > Bindesysteme > Binderücken Bürobedarf > Ablage & Organisation > CD-/DVD-Ordnungssysteme -Bürobedarf > Ablage & Organisation > CD-/DVD-Ordnungssysteme > CD- & DVD-Verpackungen -Bürobedarf > Ablage & Organisation > CD-/DVD-Ordnungssysteme > CD/DVD-Hüllen -Bürobedarf > Ablage & Organisation > CD-/DVD-Ordnungssysteme > CD/DVD-Taschen & -Sonnenblendentaschen Bürobedarf > Ablage & Organisation > Federmappen Bürobedarf > Ablage & Organisation > Geldkassetten Bürobedarf > Ablage & Organisation > Kalender, Organizer & Zeitplaner Bürobedarf > Ablage & Organisation > Karteikästen Bürobedarf > Ablage & Organisation > Kartenhüllen -Bürobedarf > Ablage & Organisation > Laminieren -Bürobedarf > Ablage & Organisation > Laminieren > Laminierfolie, Schutzhüllen -Bürobedarf > Ablage & Organisation > Laminieren > Laminiergeräte Bürobedarf > Ablage & Organisation > Postkartenorganizer Bürobedarf > Ablage & Organisation > Postsortiersysteme Bürobedarf > Ablage & Organisation > Register- & Hängemappen Bürobedarf > Ablage & Organisation > Rezeptkästen Bürobedarf > Ablage & Organisation > Schreibtischorganizer -Bürobedarf > Ablage & Organisation > Schreibtischorganizer > Ablagekästen -Bürobedarf > Ablage & Organisation > Staufächer und -schränke Bürobedarf > Ablage & Organisation > Visitenkarten-Ständer Bürobedarf > Ablage & Organisation > Visitenkartenbücher Bürobedarf > Bücherzubehör @@ -504,21 +333,22 @@ Bürobedarf > Bücherzubehör > Leselampen Bürobedarf > Bücherzubehör > Lesezeichen Bürobedarf > Büroarbeitsmittel Bürobedarf > Büroarbeitsmittel > Bleistiftspitzer +Bürobedarf > Büroarbeitsmittel > Brieföffner +Bürobedarf > Büroarbeitsmittel > Bürostempel Bürobedarf > Büroarbeitsmittel > Heftgeräte Bürobedarf > Büroarbeitsmittel > Heftklammernzieher +Bürobedarf > Büroarbeitsmittel > Klebebandabroller Bürobedarf > Büroarbeitsmittel > Klemmbretter -Bürobedarf > Büroarbeitsmittel > Lineale Bürobedarf > Büroarbeitsmittel > Lupen -Bürobedarf > Büroarbeitsmittel > Scheren Bürobedarf > Büroarbeitsmittel > Schreibgeräte Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Füller & Bleistifte Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Füller & Bleistifte > Bleistifte Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Füller & Bleistifte > Bleistifte > Schreibbleistifte Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Füller & Bleistifte > Bleistifte > Zeichenbleistifte & Buntstifte Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Füller & Bleistifte > Füller- & Bleistift-Sets -Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Füller & Bleistifte > Multifunktions-Schreibgeräte Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Füller & Bleistifte > Schreibstifte, Kugelschreiber & Füller Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Markierstifte & Textmarker +Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Multifunktions-Schreibgeräte Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Pastellkreiden Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Tafelkreide Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Wachsmalstifte @@ -526,11 +356,7 @@ Bürobedarf > Büroarbeitsmittel > Schreibgeräte > Zeichenkohle Bürobedarf > Büroarbeitsmittel > Schreibwerkzeugzubehör Bürobedarf > Büroarbeitsmittel > Schreibwerkzeugzubehör > Bleistiftminen Bürobedarf > Büroarbeitsmittel > Schreibwerkzeugzubehör > Füllertinte & -patronen -Bürobedarf > Büroarbeitsmittel > Schreibwerkzeugzubehör > Kugelschreiberminen Bürobedarf > Büroarbeitsmittel > Schreibwerkzeugzubehör > Marker-Nachfülltinte -Bürobedarf > Büroarbeitsmittel > Stempel -Bürobedarf > Büroarbeitsmittel > Stempel > Bürostempel -Bürobedarf > Büroarbeitsmittel > Stempel > Motivstempel Bürobedarf > Büroarbeitsmittel > Tischglocken Bürobedarf > Bürogeräte Bürobedarf > Bürogeräte > Aktenvernichter @@ -538,9 +364,11 @@ Bürobedarf > Bürogeräte > Diktiergeräte & Geräte zur Transkription Bürobedarf > Bürogeräte > Elektronische Wörterbücher & Übersetzungsgeräte Bürobedarf > Bürogeräte > Etikettendrucker Bürobedarf > Bürogeräte > Frankiermaschinen +Bürobedarf > Bürogeräte > Laminiergeräte Bürobedarf > Bürogeräte > Schreibmaschinen Bürobedarf > Bürogeräte > Stempeluhren Bürobedarf > Bürogeräte > Taschenrechner +Bürobedarf > Bürogeräte > Taschenrechner-Zubehör Bürobedarf > Büromatten & Stuhlunterlagen Bürobedarf > Büromatten & Stuhlunterlagen > Arbeitsplatzmatten Bürobedarf > Büromatten & Stuhlunterlagen > Büromatten @@ -552,20 +380,14 @@ Bürobedarf > Bürowagen > Medienwagen Bürobedarf > Bürowagen > Mehrzweckwagen Bürobedarf > Bürowagen > Postwagen Bürobedarf > Impulsschweißgeräte +Bürobedarf > Laptophalter Bürobedarf > Namensschilder Bürobedarf > Papierbearbeitung -Bürobedarf > Papierbearbeitung > Bastelmesser Bürobedarf > Papierbearbeitung > Blattwender Bürobedarf > Papierbearbeitung > Briefbeschwerer Bürobedarf > Papierbearbeitung > Locher -Bürobedarf > Papierbearbeitung > Locher > Bürolocher -Bürobedarf > Papierbearbeitung > Locher > Dekolocher Bürobedarf > Papierbearbeitung > Papierfalzmaschinen Bürobedarf > Papierbearbeitung > Papierrüttler -Bürobedarf > Papierbearbeitung > Papierschneider -Bürobedarf > Papierbearbeitung > Papierschneiderzubehör -Bürobedarf > Papierbearbeitung > Papierschneiderzubehör > Papierschneidetische -Bürobedarf > Papierbearbeitung > Schneidematten Bürobedarf > Papierbearbeitung > Schreibunterlagen Bürobedarf > Präsentationsbedarf Bürobedarf > Präsentationsbedarf > Ausstellungstafeln @@ -573,8 +395,8 @@ Bürobedarf > Präsentationsbedarf > Ausstellungstafeln > Hartschaumstoffplatten Bürobedarf > Präsentationsbedarf > Ausstellungstafeln > Pinnwände Bürobedarf > Präsentationsbedarf > Ausstellungstafeln > Plakatkartons Bürobedarf > Präsentationsbedarf > Ausstellungstafeln > Trägerplatten -Bürobedarf > Präsentationsbedarf > Ausstellungstafeln > Zubehör für Ausstellungstafeln -Bürobedarf > Präsentationsbedarf > Ausstellungstafeln > Zubehör für Ausstellungstafeln > Dekorative Elemente für Ausstellungstafeln +Bürobedarf > Präsentationsbedarf > Ausstellungstafeln > Zubehör für Anschlagbretter +Bürobedarf > Präsentationsbedarf > Ausstellungstafeln > Zubehör für Anschlagbretter > Dekorative Elemente für Anschlagbretter Bürobedarf > Präsentationsbedarf > Dokumentenkameras Bürobedarf > Präsentationsbedarf > Flipchart-Blöcke Bürobedarf > Präsentationsbedarf > Flipcharts @@ -584,8 +406,10 @@ Bürobedarf > Präsentationsbedarf > Lesepulte Bürobedarf > Präsentationsbedarf > Präsentationsfernbedienungen Bürobedarf > Präsentationsbedarf > Schreibtafeln Bürobedarf > Präsentationsbedarf > Whiteboards +Bürobedarf > Schreibtischunterlagen Bürobedarf > Schreibwaren Bürobedarf > Schreibwaren > Büroklammern & Papierklammern +Bürobedarf > Schreibwaren > Büroklebeband Bürobedarf > Schreibwaren > Etiketten & Anhängerschilder Bürobedarf > Schreibwaren > Etiketten & Anhängerschilder > Adressaufkleber Bürobedarf > Schreibwaren > Etiketten & Anhängerschilder > Klebebänder für Etikettiergeräte @@ -595,18 +419,15 @@ Bürobedarf > Schreibwaren > Etiketten & Anhängerschilder > Versandanhänger Bürobedarf > Schreibwaren > Etiketten & Anhängerschilder > Versandaufkleber & -etiketten Bürobedarf > Schreibwaren > Gummibänder Bürobedarf > Schreibwaren > Heftklammern -Bürobedarf > Schreibwaren > Klebstoffe -Bürobedarf > Schreibwaren > Klebstoffe > Büroklebeband -Bürobedarf > Schreibwaren > Korrektur -Bürobedarf > Schreibwaren > Korrektur > Korrekturflüssigkeiten, Korrekturstifte & Korrekturbänder -Bürobedarf > Schreibwaren > Korrektur > Radiergummis +Bürobedarf > Schreibwaren > Klebepads +Bürobedarf > Schreibwaren > Korrekturflüssigkeiten, Korrekturstifte & Korrekturbänder +Bürobedarf > Schreibwaren > Laminierfolie & Schutzhüllen Bürobedarf > Schreibwaren > Musterklammern Bürobedarf > Schreibwaren > Papierprodukte Bürobedarf > Schreibwaren > Papierprodukte > Blanko-Ausweise Bürobedarf > Schreibwaren > Papierprodukte > Briefpapier Bürobedarf > Schreibwaren > Papierprodukte > Briefumschläge Bürobedarf > Schreibwaren > Papierprodukte > Drucker- & Kopierpapier -Bürobedarf > Schreibwaren > Papierprodukte > Drucker- & Kopierpapier > Fotodruckerpapier Bürobedarf > Schreibwaren > Papierprodukte > Feinkarton Bürobedarf > Schreibwaren > Papierprodukte > Geschäftsformulare & -belege Bürobedarf > Schreibwaren > Papierprodukte > Haftnotizen @@ -617,15 +438,13 @@ Bürobedarf > Schreibwaren > Papierprodukte > Papier für Hefter Bürobedarf > Schreibwaren > Papierprodukte > Postkarten Bürobedarf > Schreibwaren > Papierprodukte > Scheckformulare Bürobedarf > Schreibwaren > Papierprodukte > Visitenkarten +Bürobedarf > Schreibwaren > Radiergummis Bürobedarf > Schreibwaren > Reißzwecken & Pins -Bürobedarf > Schreibwaren > Stempelkissen & Tinten Bürobedarf > Versandbedarf -Bürobedarf > Versandbedarf > Briefwaagen Bürobedarf > Versandbedarf > Packband +Bürobedarf > Versandbedarf > Umzugs- & Versandkartons Bürobedarf > Versandbedarf > Verpackungsmaterialien -Bürobedarf > Versandbedarf > Versandschachteln Elektronik -Elektronik > 3D-Drucker Elektronik > Audio Elektronik > Audio > Audiokomponenten Elektronik > Audio > Audiokomponenten > AV-Receiver @@ -638,13 +457,9 @@ Elektronik > Audio > Audiokomponenten > Audioverstärker > Kopfhörerverstärker Elektronik > Audio > Audiokomponenten > Audioverstärker > Stereoverstärker Elektronik > Audio > Audiokomponenten > Channel Strips Elektronik > Audio > Audiokomponenten > DI-Boxen -Elektronik > Audio > Audiokomponenten > Kopfhörer +Elektronik > Audio > Audiokomponenten > Kopfhörer & Headsets Elektronik > Audio > Audiokomponenten > Lautsprecher -Elektronik > Audio > Audiokomponenten > Lautsprecher > Computerlautsprecher -Elektronik > Audio > Audiokomponenten > Lautsprecher > Studiomonitore -Elektronik > Audio > Audiokomponenten > Lautsprecher > Subwoofer Elektronik > Audio > Audiokomponenten > Mikrofone -Elektronik > Audio > Audiokomponenten > Mikrofone > Videokamera-Mikrofone Elektronik > Audio > Audiokomponenten > Signalprozessoren Elektronik > Audio > Audiokomponenten > Signalprozessoren > Effektprozessoren Elektronik > Audio > Audiokomponenten > Signalprozessoren > Equalizer @@ -653,6 +468,7 @@ Elektronik > Audio > Audiokomponenten > Signalprozessoren > Mikrofonvorverstärk Elektronik > Audio > Audiokomponenten > Signalprozessoren > Noise Gates & Kompressoren Elektronik > Audio > Audiokomponenten > Signalprozessoren > Phono-Vorverstärker Elektronik > Audio > Audiokomponenten > Signalprozessoren > Steuerungssysteme für PA-Anlagen +Elektronik > Audio > Audiokomponenten > Studio-Aufnahmesets Elektronik > Audio > Audioplayer & -rekorder Elektronik > Audio > Audioplayer & -rekorder > CD-Player & -Rekorder Elektronik > Audio > Audioplayer & -rekorder > Diktiergeräte @@ -665,262 +481,227 @@ Elektronik > Audio > Audioplayer & -rekorder > MP3-Player Elektronik > Audio > Audioplayer & -rekorder > Mehrspurrekorder Elektronik > Audio > Audioplayer & -rekorder > MiniDisc-Player Elektronik > Audio > Audioplayer & -rekorder > Plattenspieler -Elektronik > Audio > Audioplayer & -rekorder > Plattenspieler > DJ-Plattenspieler Elektronik > Audio > Audioplayer & -rekorder > Radios -Elektronik > Audio > Audioplayer & -rekorder > Radios > Satellitenradios -Elektronik > Audio > Audioplayer & -rekorder > Radios > WLAN-Radios Elektronik > Audio > Audioplayer & -rekorder > Stereoanlagen +Elektronik > Audio > Audioplayer & -rekorder > Tonbandgeräte Elektronik > Audio > Audiozubehör -Elektronik > Audio > Audiozubehör > Kopfhörerzubehör -Elektronik > Audio > Audiozubehör > Kopfhörerzubehör > In-Ear-Ohrhörer Polster -Elektronik > Audio > Audiozubehör > Kopfhörerzubehör > Kopfhörer-Polster +Elektronik > Audio > Audiozubehör > Audio- & Video-Receiver-Zubehör +Elektronik > Audio > Audiozubehör > Kopfhörer- & Headset-Zubehör +Elektronik > Audio > Audiozubehör > Kopfhörer- & Headset-Zubehör > Kopfhörer- & In-Ear-Ohrhörer-Polster Elektronik > Audio > Audiozubehör > Lautsprecherzubehör -Elektronik > Audio > Audiozubehör > Lautsprecherzubehör > Bespannstoff für Lautsprecher +Elektronik > Audio > Audiozubehör > Lautsprecherzubehör > Bass-Shaker +Elektronik > Audio > Audiozubehör > Lautsprecherzubehör > Lautsprecherkomponenten & -sets Elektronik > Audio > Audiozubehör > Lautsprecherzubehör > Lautsprecherständer +Elektronik > Audio > Audiozubehör > Lautsprecherzubehör > Lautsprechertaschen, -abdeckungen & -cases Elektronik > Audio > Audiozubehör > Lautsprecherzubehör > Taschen für Lautsprecherständer +Elektronik > Audio > Audiozubehör > Mikrofonständer Elektronik > Audio > Audiozubehör > Mikrofonzubehör -Elektronik > Audio > Audiozubehör > Mikrofonzubehör > Mikrofon-Windschutz -Elektronik > Audio > Audiozubehör > Mikrofonzubehör > Mikrofonständer Elektronik > Audio > Audiozubehör > Plattenspielerzubehör -Elektronik > Audio > Audiozubehör > Plattenspielerzubehör > Plattenspieler-Tonabnehmer & -Nadeln Elektronik > Audio > Audiozubehör > Satellitenradio-Zubehör Elektronik > Audio > Audiozubehör > Zubehör für Karaoke-Systeme Elektronik > Audio > Audiozubehör > Zubehör für Karaoke-Systeme > Karaoke-Speicherchips Elektronik > Audio > Audiozubehör > Zubehör für MP3-Player Elektronik > Audio > Audiozubehör > Zubehör für MP3-Player > MP3-Player-Taschen -Elektronik > Audio > Audiozubehör > Zubehör für MP3-Player > Zubehör für MP3-Player & Mobiltelefone +Elektronik > Audio > Audiozubehör > Zubehör für MP3-Player > Zubehörsets für MP3-Player & Mobiltelefone Elektronik > Audio > Beschallungsanlagen Elektronik > Audio > Bühnenausstattung Elektronik > Audio > Bühnenausstattung > Drahtlossender Elektronik > Audio > DJ- & Spezialaudiogeräte Elektronik > Audio > DJ- & Spezialaudiogeräte > DJ CD-Player Elektronik > Audio > DJ- & Spezialaudiogeräte > DJ Systeme -Elektronik > Audio > DJ- & Spezialaudiogeräte > Zubehör für DJ-Anlagen +Elektronik > Audio > Megafone Elektronik > Computer Elektronik > Computer > Barebone-Computer -Elektronik > Computer > Computerkomponenten -Elektronik > Computer > Computerkomponenten > Ausgabegeräte -Elektronik > Computer > Computerkomponenten > Blade-Server-Gehäuse -Elektronik > Computer > Computerkomponenten > Computer-Starter-Kits -Elektronik > Computer > Computerkomponenten > Computernetzteile -Elektronik > Computer > Computerkomponenten > Computerregale & -Befestigungssysteme -Elektronik > Computer > Computerkomponenten > Eingabegeräte -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Computer Mäuse & Trackballs -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Computertastaturen -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Digitale Stifte -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Fingerabdruck-Lesegeräte -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Gamecontroller -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Grafiktabletts -Elektronik > Computer > Computerkomponenten > Eingabegeräte > KVM-Switches -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Smartcard-Leser -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Speicherkartenlesegerät -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Strichcode-Scanner -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Tastatur- & Maussets -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Touchpads -Elektronik > Computer > Computerkomponenten > Eingabegeräte > Ziffernblöcke -Elektronik > Computer > Computerkomponenten > I/O-Karten -Elektronik > Computer > Computerkomponenten > I/O-Karten > FireWire-Karten -Elektronik > Computer > Computerkomponenten > I/O-Karten > Grafikkarten -Elektronik > Computer > Computerkomponenten > I/O-Karten > Parallele Karten -Elektronik > Computer > Computerkomponenten > I/O-Karten > Serielle Karten -Elektronik > Computer > Computerkomponenten > I/O-Karten > Soundkarten -Elektronik > Computer > Computerkomponenten > I/O-Karten > TV-Karten und -Adapter -Elektronik > Computer > Computerkomponenten > I/O-Karten > USB-Karten -Elektronik > Computer > Computerkomponenten > Kühlung von Computersystemen -Elektronik > Computer > Computerkomponenten > Laptopteile -Elektronik > Computer > Computerkomponenten > Laptopteile > Laptop-Ersatzbildschirme -Elektronik > Computer > Computerkomponenten > Laptopteile > Laptop-Ersatzkabel -Elektronik > Computer > Computerkomponenten > Laptopteile > Laptop-Ersatztastaturen -Elektronik > Computer > Computerkomponenten > Laptopteile > Laptop-Scharniere -Elektronik > Computer > Computerkomponenten > Laptopteile > Laptopgehäuse -Elektronik > Computer > Computerkomponenten > Motherboards -Elektronik > Computer > Computerkomponenten > PC-Gehäuse -Elektronik > Computer > Computerkomponenten > Prozessoren -Elektronik > Computer > Computerkomponenten > Speichergeräte -Elektronik > Computer > Computerkomponenten > Speichergeräte > Bandlaufwerke -Elektronik > Computer > Computerkomponenten > Speichergeräte > Datenspeicher-Duplizierer -Elektronik > Computer > Computerkomponenten > Speichergeräte > Datenspeicher-Duplizierer > CD-/DVD-Brenner -Elektronik > Computer > Computerkomponenten > Speichergeräte > Datenspeicher-Duplizierer > Festplatten-Duplizierer -Elektronik > Computer > Computerkomponenten > Speichergeräte > Datenspeicher-Duplizierer > USB-Laufwerk-Duplizierer -Elektronik > Computer > Computerkomponenten > Speichergeräte > Disk-Arrays -Elektronik > Computer > Computerkomponenten > Speichergeräte > Diskettenlaufwerke -Elektronik > Computer > Computerkomponenten > Speichergeräte > Festplatten -Elektronik > Computer > Computerkomponenten > Speichergeräte > Festplatten > Solid-State-Laufwerke -Elektronik > Computer > Computerkomponenten > Speichergeräte > Festplatten > XBox 360 Festplatten -Elektronik > Computer > Computerkomponenten > Speichergeräte > Netzwerkspeichersysteme -Elektronik > Computer > Computerkomponenten > Speichergeräte > Netzwerkspeichersysteme > NAS-Server -Elektronik > Computer > Computerkomponenten > Speichergeräte > Netzwerkspeichersysteme > Speichernetzwerke -Elektronik > Computer > Computerkomponenten > Speichergeräte > Optische Laufwerke -Elektronik > Computer > Computerkomponenten > Speichergeräte > Optische Laufwerke > CD-Laufwerke -Elektronik > Computer > Computerkomponenten > Speichergeräte > Optische Laufwerke > DVD-Laufwerke -Elektronik > Computer > Computerkomponenten > Speichergeräte > Optische Laufwerke > MO-Disketten -Elektronik > Computer > Computerkomponenten > Speichergeräte > Speicherlaufwerkzubehör -Elektronik > Computer > Computerkomponenten > Speichergeräte > Speicherlaufwerkzubehör > Externe Festplatten -Elektronik > Computer > Computerkomponenten > Speichergeräte > Speicherlaufwerkzubehör > Festplatten-Caddies -Elektronik > Computer > Computerkomponenten > Speichergeräte > Speicherlaufwerkzubehör > Festplatten-Dockingstationen -Elektronik > Computer > Computerkomponenten > Speichergeräte > Speicherlaufwerkzubehör > Festplatten-Transporttaschen -Elektronik > Computer > Computerkomponenten > Speichergeräte > Speicherlaufwerkzubehör > Festplattenhalterungen -Elektronik > Computer > Computerkomponenten > Speichergeräte > USB-Massenspeicher -Elektronik > Computer > Computerkomponenten > USB- & FireWire-Hubs -Elektronik > Computer > Computerkomponenten > Zubehör für Eingabegeräte -Elektronik > Computer > Computerkomponenten > Zubehör für Eingabegeräte > Grafiktablett-Zubehör -Elektronik > Computer > Computerkomponenten > Zubehör für Eingabegeräte > Halterung für Strichcodeleser -Elektronik > Computer > Computerkomponenten > Zubehör für Eingabegeräte > Zubehör für Gamecontroller -Elektronik > Computer > Computerkomponenten > Zubehör für Eingabegeräte > Zubehör für Gamecontroller > Joysticks & Tasten Elektronik > Computer > Computerserver -Elektronik > Computer > Computerzubehör -Elektronik > Computer > Computerzubehör > Ersatzspitzen für Stylus Pens -Elektronik > Computer > Computerzubehör > Keyboard- und Mausauflagen -Elektronik > Computer > Computerzubehör > Laptopzubehör -Elektronik > Computer > Computerzubehör > Laptopzubehör > Laptop-Dockingstationen -Elektronik > Computer > Computerzubehör > Monitorständer -Elektronik > Computer > Computerzubehör > Mousepads -Elektronik > Computer > Computerzubehör > Stylus Pens -Elektronik > Computer > Computerzubehör > Tablet-Computer-Zubehör -Elektronik > Computer > Computerzubehör > Tablet-Computer-Zubehör > Tablet-Computer-Ersatzteile -Elektronik > Computer > Computerzubehör > Tablet-Computer-Zubehör > Tablet-Computer-Ersatzteile > Digitalisierer -Elektronik > Computer > Computerzubehör > Tablet-Computer-Zubehör > Tablet-PC-Halter -Elektronik > Computer > Computerzubehör > Tastatur- & Maus-Handballenauflage -Elektronik > Computer > Computerzubehör > Zubehör für E-Book-Reader & Handheld-Computer -Elektronik > Computer > Computerzubehör > Zubehör für E-Book-Reader & Handheld-Computer > PDA-Zubehör -Elektronik > Computer > Computerzubehör > Zubehör für E-Book-Reader & Handheld-Computer > PDA-Zubehör > PDA-Taschen -Elektronik > Computer > Computerzubehör > Zubehör für E-Book-Reader & Handheld-Computer > Zubehör für E-Book-Reader -Elektronik > Computer > Computerzubehör > Zubehör für E-Book-Reader & Handheld-Computer > Zubehör für E-Book-Reader > E-Book-Reader-Taschen +Elektronik > Computer > Datenbrillen Elektronik > Computer > Desktop-Computer Elektronik > Computer > E-Book-Reader & Handheld-Computer -Elektronik > Computer > E-Book-Reader & Handheld-Computer > Datenerfassungsterminals +Elektronik > Computer > E-Book-Reader & Handheld-Computer > Datenerfassungsgeräte Elektronik > Computer > E-Book-Reader & Handheld-Computer > E-Book-Reader Elektronik > Computer > E-Book-Reader & Handheld-Computer > PDAs Elektronik > Computer > Interaktive Kioske Elektronik > Computer > Laptops -Elektronik > Computer > Laptops > Netbooks +Elektronik > Computer > Multitouch-Tischcomputer Elektronik > Computer > Tablet-PCs +Elektronik > Computer > Thin Clients & Zero Clients Elektronik > Drucken, Kopieren, Scannen & Faxen -Elektronik > Drucken, Kopieren, Scannen & Faxen > Drucker & Kopierer -Elektronik > Drucken, Kopieren, Scannen & Faxen > Drucker & Kopierer > Drucker -Elektronik > Drucken, Kopieren, Scannen & Faxen > Drucker & Kopierer > Drucker > Fotodrucker -Elektronik > Drucken, Kopieren, Scannen & Faxen > Drucker & Kopierer > Drucker > Laserdrucker -Elektronik > Drucken, Kopieren, Scannen & Faxen > Drucker & Kopierer > Drucker > Matrixdrucker -Elektronik > Drucken, Kopieren, Scannen & Faxen > Drucker & Kopierer > Drucker > Tintenstrahldrucker -Elektronik > Drucken, Kopieren, Scannen & Faxen > Drucker & Kopierer > Kopierer -Elektronik > Drucken, Kopieren, Scannen & Faxen > Faxgeräte +Elektronik > Drucken, Kopieren, Scannen & Faxen > 3D-Drucker +Elektronik > Drucken, Kopieren, Scannen & Faxen > 3D-Drucker-Zubehör +Elektronik > Drucken, Kopieren, Scannen & Faxen > Drucker, Kopierer & Faxgeräte Elektronik > Drucken, Kopieren, Scannen & Faxen > Scanner -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Drucker-Duplexeinheiten -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Drucker-Papierfächer -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Drucker-Verbrauchsmaterial -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Drucker-Verbrauchsmaterial > Drucker-Farbbänder -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Drucker-Verbrauchsmaterial > Druckerfilter -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Drucker-Verbrauchsmaterial > Druckköpfe -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Drucker-Verbrauchsmaterial > Toner & Tintenpatronen -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Drucker-Verbrauchsmaterial > Toner- & Inkjet-Kartuschen -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Drucker-Verbrauchsmaterial > Toner- & Inkjet-Kartuschen > Druckertrommelsets -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Drucker-Verbrauchsmaterial > Toner- & Inkjet-Kartuschen > Ölwalzen -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Druckerspeicher -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Druckertische -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Druckerzubehör > Druckerwartungssets -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Kopiererzubehör -Elektronik > Drucker-, Kopierer-, Scanner- & Faxzubehör > Scannerzubehör +Elektronik > Drucken, Kopieren, Scannen & Faxen > Scannerzubehör +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Drucker-Duplexeinheiten +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Drucker-Verbrauchsmaterial +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Drucker-Verbrauchsmaterial > Drucker-Farbbänder +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Drucker-Verbrauchsmaterial > Druckerfilter +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Drucker-Verbrauchsmaterial > Druckertrommeln & Sets +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Drucker-Verbrauchsmaterial > Druckerwartungssets +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Drucker-Verbrauchsmaterial > Druckköpfe +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Drucker-Verbrauchsmaterial > Toner & Tintenpatronen +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Drucker-Verbrauchsmaterial > Toner- & Inkjet-Kartuschen +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Druckerspeicher +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Druckertische +Elektronik > Drucken, Kopieren, Scannen & Faxen > Zubehör für Drucker, Kopierer & Faxgeräte > Ersatzteile für Drucker, Kopierer & Faxgeräte Elektronik > Elektrische Instrumente Seefahrt +Elektronik > Elektrische Instrumente Seefahrt > Audio- und Videoemfpänger Elektronik > Elektrische Instrumente Seefahrt > Fischfinder +Elektronik > Elektrische Instrumente Seefahrt > Marine-Lautsprecher Elektronik > Elektrische Instrumente Seefahrt > Schiffsradar Elektronik > Elektrische Instrumente Seefahrt > Seefunkgeräte Elektronik > Elektrische Instrumente Seefahrt > Seekartenplotter & GPS -Elektronik > Elektromotoren -Elektronik > Elektronische Bauelemente -Elektronik > Elektronische Bauelemente > Decoder & Encoder für Schaltkreise -Elektronik > Elektronische Bauelemente > Elektronische Filter -Elektronik > Elektronische Bauelemente > Halbleiter -Elektronik > Elektronische Bauelemente > Halbleiter > Dioden -Elektronik > Elektronische Bauelemente > Halbleiter > Integrierte Schaltkreise & Chips -Elektronik > Elektronische Bauelemente > Halbleiter > Integrierte Schaltkreise & Chips > Operationsverstärker -Elektronik > Elektronische Bauelemente > Halbleiter > Integrierte Schaltkreise & Chips > Spannungsregler (ICs) -Elektronik > Elektronische Bauelemente > Halbleiter > Mikrocontroller -Elektronik > Elektronische Bauelemente > Halbleiter > Transistoren -Elektronik > Elektronische Bauelemente > Leiterplatten -Elektronik > Elektronische Bauelemente > Leiterplatten > Entwicklungsboard -Elektronik > Elektronische Bauelemente > Optoelektronik -Elektronik > Elektronische Bauelemente > Optoelektronik > Laserdioden -Elektronik > Elektronische Bauelemente > Passive elektronische Bauelemente -Elektronik > Elektronische Bauelemente > Passive elektronische Bauelemente > Induktoren -Elektronik > Elektronische Bauelemente > Passive elektronische Bauelemente > Kondensatoren -Elektronik > Elektronische Bauelemente > Passive elektronische Bauelemente > Oszillatoren -Elektronik > Elektronische Bauelemente > Passive elektronische Bauelemente > Widerstände -Elektronik > Elektronische Bauelemente > Passive elektronische Bauelemente > Widerstände > Potentiometer -Elektronik > Elektronische Bauelemente > Platinenentwicklung -Elektronik > Elektronische Bauelemente > Platinenentwicklung > Steckplatinen +Elektronik > Elektronische Leiterplatten & Bauteile +Elektronik > Elektronische Leiterplatten & Bauteile > Decoder & Encoder für Schaltkreise +Elektronik > Elektronische Leiterplatten & Bauteile > Elektronische Filter +Elektronik > Elektronische Leiterplatten & Bauteile > Halbleiter +Elektronik > Elektronische Leiterplatten & Bauteile > Halbleiter > Dioden +Elektronik > Elektronische Leiterplatten & Bauteile > Halbleiter > Integrierte Schaltkreise & Chips +Elektronik > Elektronische Leiterplatten & Bauteile > Halbleiter > Mikrocontroller +Elektronik > Elektronische Leiterplatten & Bauteile > Halbleiter > Transistoren +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Computer-Leiterplatten +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Computer-Leiterplatten > Computer-Inverterplatine +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Computer-Leiterplatten > Festplatten-Leiterplatten +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Computer-Leiterplatten > Motherboards +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Entwicklungsboard +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Kamera-Leiterplatten +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Leiterplatten für Drucker, Kopierer & Faxgeräte +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Leiterplatten für Fernsehgeräte +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Leiterplatten für Fitnessgeräte +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Leiterplatten für Haushaltsgeräte +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Leiterplatten für Pools und Spas +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplatten > Leiterplatten für Scanner +Elektronik > Elektronische Leiterplatten & Bauteile > Leiterplattenzubehör +Elektronik > Elektronische Leiterplatten & Bauteile > Passive elektronische Bauelemente +Elektronik > Elektronische Leiterplatten & Bauteile > Passive elektronische Bauelemente > Induktoren +Elektronik > Elektronische Leiterplatten & Bauteile > Passive elektronische Bauelemente > Kondensatoren +Elektronik > Elektronische Leiterplatten & Bauteile > Passive elektronische Bauelemente > Oszillatoren +Elektronik > Elektronische Leiterplatten & Bauteile > Passive elektronische Bauelemente > Widerstände +Elektronik > Elektronische Leiterplatten & Bauteile > Platinenentwicklung +Elektronik > Elektronische Leiterplatten & Bauteile > Platinenentwicklung > Steckplatinen Elektronik > Elektronisches Zubehör Elektronik > Elektronisches Zubehör > Adapter Elektronik > Elektronisches Zubehör > Adapter > Audio/Video-Adapter Elektronik > Elektronisches Zubehör > Adapter > Speicheradapter -Elektronik > Elektronisches Zubehör > Adapter > Storage Adapter Elektronik > Elektronisches Zubehör > Adapter > USB-Adapter Elektronik > Elektronisches Zubehör > Antennen -Elektronik > Elektronisches Zubehör > Antennen > Funkantennen -Elektronik > Elektronisches Zubehör > Antennen > Kommunikationsantennen -Elektronik > Elektronisches Zubehör > Antennen > TV-Antennen Elektronik > Elektronisches Zubehör > Antennenzubehör Elektronik > Elektronisches Zubehör > Antennenzubehör > Antennenhalterungen & -befestigungen Elektronik > Elektronisches Zubehör > Antennenzubehör > Dreheinrichtungen Elektronik > Elektronisches Zubehör > Antennenzubehör > Satelliten-LNBs +Elektronik > Elektronisches Zubehör > Audio- und Video-Splitter & -Switches +Elektronik > Elektronisches Zubehör > Audio- und Video-Splitter & -Switches > DVI-Splitter und -Switches +Elektronik > Elektronisches Zubehör > Audio- und Video-Splitter & -Switches > HDMI-Splitter & -Switches +Elektronik > Elektronisches Zubehör > Audio- und Video-Splitter & -Switches > VGA-Splitter und -Switches +Elektronik > Elektronisches Zubehör > Computerkomponenten +Elektronik > Elektronisches Zubehör > Computerkomponenten > Blade-Server-Gehäuse +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computer-Backplates & I/O Shields +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computer-Kühlkomponenten +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computer-Starter-Kits +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computer-Steckkarten +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computer-Steckkarten > Computer-Steckkarten & -Adapter +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computer-Steckkarten > Grafikkarten & Videoadapter +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computer-Steckkarten > Riser-Karten +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computer-Steckkarten > Soundkarten +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computer-Steckkarten > TV-Karten und -Adapter +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computernetzteile +Elektronik > Elektronisches Zubehör > Computerkomponenten > Computerregale & -Befestigungssysteme +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Computer Mäuse & Trackballs +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Digitale Stifte +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Eingabegeräte zur Gestensteuerung +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Elektronische Kartenlesegeräte +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Fingerabdruck-Lesegeräte +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Gamecontroller +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Grafiktabletts +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > KVM-Switches +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Speicherkartenlesegerät +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Strichcode-Scanner +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Tastaturen +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Touchpads +Elektronik > Elektronisches Zubehör > Computerkomponenten > Eingabegeräte > Ziffernblöcke +Elektronik > Elektronisches Zubehör > Computerkomponenten > Ersatzteile für E-Book-Reader +Elektronik > Elektronisches Zubehör > Computerkomponenten > Ersatzteile für E-Book-Reader > Ersatzbildschirme für E-Book-Reader +Elektronik > Elektronisches Zubehör > Computerkomponenten > Laptopteile +Elektronik > Elektronisches Zubehör > Computerkomponenten > Laptopteile > Laptop-Bildschirmdigitalisierer +Elektronik > Elektronisches Zubehör > Computerkomponenten > Laptopteile > Laptop-Ersatzbildschirme +Elektronik > Elektronisches Zubehör > Computerkomponenten > Laptopteile > Laptop-Ersatzkabel +Elektronik > Elektronisches Zubehör > Computerkomponenten > Laptopteile > Laptop-Ersatzlautsprecher +Elektronik > Elektronisches Zubehör > Computerkomponenten > Laptopteile > Laptop-Ersatztastaturen +Elektronik > Elektronisches Zubehör > Computerkomponenten > Laptopteile > Laptop-Scharniere +Elektronik > Elektronisches Zubehör > Computerkomponenten > Laptopteile > Laptopgehäuse +Elektronik > Elektronisches Zubehör > Computerkomponenten > PC-Gehäuse +Elektronik > Elektronisches Zubehör > Computerkomponenten > Prozessoren +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Bandlaufwerke +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Datenspeicher-Duplizierer +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Datenspeicher-Duplizierer > CD-/DVD-Brenner +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Datenspeicher-Duplizierer > Festplatten-Duplizierer +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Datenspeicher-Duplizierer > USB-Laufwerk-Duplizierer +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Disk-Arrays +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Diskettenlaufwerke +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Festplatten +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Festplattenzubehör +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Festplattenzubehör > Festplatten-Dockingstationen +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Festplattenzubehör > Festplatten-Transporttaschen +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Festplattenzubehör > Festplattengehäuse & -steckplätze +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Netzwerkspeichersysteme +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > Optische Laufwerke +Elektronik > Elektronisches Zubehör > Computerkomponenten > Speichergeräte > USB-Massenspeicher +Elektronik > Elektronisches Zubehör > Computerkomponenten > Tablet-PC-Ersatzteile +Elektronik > Elektronisches Zubehör > Computerkomponenten > Tablet-PC-Ersatzteile > Tablet-Bildschirme und Bildschirm-Digitizer +Elektronik > Elektronisches Zubehör > Computerkomponenten > Tablet-PC-Ersatzteile > Tablet-Ersatzlautsprecher +Elektronik > Elektronisches Zubehör > Computerkomponenten > Tablet-PC-Ersatzteile > Tablet-Gehäuse & -Rahmen +Elektronik > Elektronisches Zubehör > Computerkomponenten > USB- & FireWire-Hubs +Elektronik > Elektronisches Zubehör > Computerkomponenten > Zubehör für Eingabegeräte +Elektronik > Elektronisches Zubehör > Computerkomponenten > Zubehör für Eingabegeräte > Halterung für Strichcodeleser +Elektronik > Elektronisches Zubehör > Computerkomponenten > Zubehör für Eingabegeräte > Mäuse und Trackball-Zubehör +Elektronik > Elektronisches Zubehör > Computerkomponenten > Zubehör für Eingabegeräte > Tastaturtasten & -kappen +Elektronik > Elektronisches Zubehör > Computerkomponenten > Zubehör für Eingabegeräte > Zubehör für Gamecontroller +Elektronik > Elektronisches Zubehör > Computerzubehör +Elektronik > Elektronisches Zubehör > Computerzubehör > Computer-Monitorständer +Elektronik > Elektronisches Zubehör > Computerzubehör > Computer-Schutzhüllen +Elektronik > Elektronisches Zubehör > Computerzubehör > Computerzubehör-Sets +Elektronik > Elektronisches Zubehör > Computerzubehör > Ersatzspitzen für Stylus Pens +Elektronik > Elektronisches Zubehör > Computerzubehör > Laptop-Dockingstationen +Elektronik > Elektronisches Zubehör > Computerzubehör > Mousepads +Elektronik > Elektronisches Zubehör > Computerzubehör > Stylus Pens +Elektronik > Elektronisches Zubehör > Computerzubehör > Ständer für Tablet-PCs +Elektronik > Elektronisches Zubehör > Computerzubehör > Tastatur- & Maus-Handballenauflage +Elektronik > Elektronisches Zubehör > Computerzubehör > Tastaturablagen +Elektronik > Elektronisches Zubehör > Computerzubehör > Zubehör für E-Book-Reader & Handheld-Computer +Elektronik > Elektronisches Zubehör > Computerzubehör > Zubehör für E-Book-Reader & Handheld-Computer > PDA-Zubehör +Elektronik > Elektronisches Zubehör > Computerzubehör > Zubehör für E-Book-Reader & Handheld-Computer > PDA-Zubehör > PDA-Taschen +Elektronik > Elektronisches Zubehör > Computerzubehör > Zubehör für E-Book-Reader & Handheld-Computer > Zubehör für E-Book-Reader +Elektronik > Elektronisches Zubehör > Computerzubehör > Zubehör für E-Book-Reader & Handheld-Computer > Zubehör für E-Book-Reader > E-Book-Reader-Taschen +Elektronik > Elektronisches Zubehör > Drei- und Einbeinstative für Mobiltelefone und Tablets Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge > Blickschutzfilter Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge > Display-Schutzfolien Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge > Elektronik-Sticker & -Aufkleber -Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge > Elektronik-Sticker & -Aufkleber > Aufkleber für Spielkonsolen -Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge > Elektronik-Sticker & -Aufkleber > Handy-Aufkleber -Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge > Elektronik-Sticker & -Aufkleber > Laptop-Sticker & -Aufkleber -Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge > Elektronik-Sticker & -Aufkleber > MP3-Player-Sticker & -Aufkleber -Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge > Elektronik-Sticker & -Aufkleber > Sticker für Computertastaturen -Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge > Elektronik-Sticker & -Aufkleber > Tablet-Computer-Sticker & -Aufkleber Elektronik > Elektronisches Zubehör > Elektronik-Folien & -Überzüge > Tastaturschutz Elektronik > Elektronisches Zubehör > Elektronikreiniger -Elektronik > Elektronisches Zubehör > Elektronikreiniger > Audio- & Videoreiniger -Elektronik > Elektronisches Zubehör > Elektronikreiniger > Bildschirmreiniger -Elektronik > Elektronisches Zubehör > Elektronikreiniger > Kamerareiniger Elektronik > Elektronisches Zubehör > Fernbedienungen Elektronik > Elektronisches Zubehör > Kabel Elektronik > Elektronisches Zubehör > Kabel > Audio- & Videokabel -Elektronik > Elektronisches Zubehör > Kabel > Audio- & Videokabel > DVI-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Audio- & Videokabel > HDMI-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Audio- & Videokabel > Lautsprecherkabel -Elektronik > Elektronisches Zubehör > Kabel > Audio- & Videokabel > SCART-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Cinch-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Datenübertragungskabel -Elektronik > Elektronisches Zubehör > Kabel > Datenübertragungskabel > Firewire-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Datenübertragungskabel > USB-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Datenübertragungskabel > iOS-Kabel +Elektronik > Elektronisches Zubehör > Kabel > Datenübertragungs- & Speicherkabel Elektronik > Elektronisches Zubehör > Kabel > KVM-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Koaxialkabel Elektronik > Elektronisches Zubehör > Kabel > Netzwerkkabel -Elektronik > Elektronisches Zubehör > Kabel > Netzwerkkabel > Ethernet-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Netzwerkkabel > Serial-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Optische Kabel -Elektronik > Elektronisches Zubehör > Kabel > Speicherkabel -Elektronik > Elektronisches Zubehör > Kabel > Speicherkabel > IDE-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Speicherkabel > SAS-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Speicherkabel > SATA-Kabel -Elektronik > Elektronisches Zubehör > Kabel > Speicherkabel > SCSI-Kabel Elektronik > Elektronisches Zubehör > Kabel > System- & Netzkabel Elektronik > Elektronisches Zubehör > Kabel > Telefonkabel Elektronik > Elektronisches Zubehör > Kabel-Management Elektronik > Elektronisches Zubehör > Kabel-Management > Aderhülsen & Kabelmuffen Elektronik > Elektronisches Zubehör > Kabel-Management > Kabelbinder +Elektronik > Elektronisches Zubehör > Kabel-Management > Kabelbinderpistolen +Elektronik > Elektronisches Zubehör > Kabel-Management > Kabelmarkierungen Elektronik > Elektronisches Zubehör > Kabel-Management > Kabelschellen Elektronik > Elektronisches Zubehör > Kabel-Management > Kabelträger Elektronik > Elektronisches Zubehör > Kabel-Management > Schalttafeln -Elektronik > Elektronisches Zubehör > Leere Medien -Elektronik > Elektronisches Zubehör > Leere Medien > Blu-ray Rohlinge -Elektronik > Elektronisches Zubehör > Leere Medien > CD Rohlinge -Elektronik > Elektronisches Zubehör > Leere Medien > Computerbänder -Elektronik > Elektronisches Zubehör > Leere Medien > Computerdisks -Elektronik > Elektronisches Zubehör > Leere Medien > Computerdisks > Disketten -Elektronik > Elektronisches Zubehör > Leere Medien > DVD Rohlinge -Elektronik > Elektronisches Zubehör > Leere Medien > MiniDiscs -Elektronik > Elektronisches Zubehör > Leere Medien > Unbespielte Kassetten -Elektronik > Elektronisches Zubehör > Leere Medien > Unbespielte Kassetten > Mikrokassetten -Elektronik > Elektronisches Zubehör > Leere Medien > Unbespielte Videokassetten +Elektronik > Elektronisches Zubehör > Leermedien +Elektronik > Elektronisches Zubehör > Signalstörer +Elektronik > Elektronisches Zubehör > Signalstörer > GPS-Störsender +Elektronik > Elektronisches Zubehör > Signalstörer > Mobiltelefon-Störsender +Elektronik > Elektronisches Zubehör > Signalstörer > Radarstörer Elektronik > Elektronisches Zubehör > Signalverstärker Elektronik > Elektronisches Zubehör > Speicher Elektronik > Elektronisches Zubehör > Speicher > Cache-Speicher @@ -934,45 +715,34 @@ Elektronik > Elektronisches Zubehör > Speicherkartenzubehör > Speicherkartenet Elektronik > Elektronisches Zubehör > Stromversorgung Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Akkus & Batterien für schnurlose Telefone -Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Batterien für E-Book-Lesegeräte -Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Batterien für Tablet-Computer +Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Akkus für Tablet-Computer +Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Batterien für E-Book-Reader +Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Batterien für Videospielkonsolen & Game-Controller Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Handy-Akkus Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Kameraakkus & -batterien Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Laptopakkus +Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > MP3-Player-Batterien Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Mehrzweckbatterien Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > PDA-Batterien Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > USV-Batterien Elektronik > Elektronisches Zubehör > Stromversorgung > Akkus & Batterien > Videokameraakkus & -batterien Elektronik > Elektronisches Zubehör > Stromversorgung > Batteriezubehör Elektronik > Elektronisches Zubehör > Stromversorgung > Batteriezubehör > Akkuladegeräte für Kameras +Elektronik > Elektronisches Zubehör > Stromversorgung > Batteriezubehör > Batteriehalter Elektronik > Elektronisches Zubehör > Stromversorgung > Batteriezubehör > Batterieladegeräte +Elektronik > Elektronisches Zubehör > Stromversorgung > Batteriezubehör > Laderegler +Elektronik > Elektronisches Zubehör > Stromversorgung > Batteriezubehör > Universal-Batterieprüfgeräte Elektronik > Elektronisches Zubehör > Stromversorgung > Brennstoffzellen -Elektronik > Elektronisches Zubehör > Stromversorgung > Ladegeräte -Elektronik > Elektronisches Zubehör > Stromversorgung > Ladegeräte > E-Book-Reader Ladegeräte -Elektronik > Elektronisches Zubehör > Stromversorgung > Ladegeräte > MP3-Player-Ladegeräte -Elektronik > Elektronisches Zubehör > Stromversorgung > Ladegeräte > Mobiltelefonladegeräte -Elektronik > Elektronisches Zubehör > Stromversorgung > Ladegeräte > PDA-Ladegeräte -Elektronik > Elektronisches Zubehör > Stromversorgung > Ladegeräte > Solar-Ladegeräte -Elektronik > Elektronisches Zubehör > Stromversorgung > Ladegeräte > Tablet-Computer-Ladegeräte +Elektronik > Elektronisches Zubehör > Stromversorgung > Gehäuse für Stromversorgungsgeräte Elektronik > Elektronisches Zubehör > Stromversorgung > Leistungsregler -Elektronik > Elektronisches Zubehör > Stromversorgung > Netzadapter -Elektronik > Elektronisches Zubehör > Stromversorgung > Netzadapter > Laptop-Netzadapter -Elektronik > Elektronisches Zubehör > Stromversorgung > Netzadapter > Reiseadapter -Elektronik > Elektronisches Zubehör > Stromversorgung > Netzadapter > Schaltnetzteile -Elektronik > Elektronisches Zubehör > Stromversorgung > Netzadapter > Wechselrichter -Elektronik > Elektronisches Zubehör > Stromversorgung > Netzteilzubehör -Elektronik > Elektronisches Zubehör > Stromversorgung > Power-Injektoren & -Splitter -Elektronik > Elektronisches Zubehör > Stromversorgung > Spannungsstabilisator -Elektronik > Elektronisches Zubehör > Stromversorgung > Spannungswandler +Elektronik > Elektronisches Zubehör > Stromversorgung > Netzteil- & Ladegerätezubehör +Elektronik > Elektronisches Zubehör > Stromversorgung > Netzteile & Ladegeräte +Elektronik > Elektronisches Zubehör > Stromversorgung > Reiseadapter Elektronik > Elektronisches Zubehör > Stromversorgung > Steckdosenleisten & Überspannungsschutz -Elektronik > Elektronisches Zubehör > Stromversorgung > Stromkasten -Elektronik > Elektronisches Zubehör > Stromversorgung > Unterbrechungsfreie Stromversorgung -Elektronik > Elektronisches Zubehör > Stromversorgung > Zubehör für Unterbrechungsfreie Stromversorgung +Elektronik > Elektronisches Zubehör > Stromversorgung > USV +Elektronik > Elektronisches Zubehör > Stromversorgung > Zubehör für USV Elektronik > Elektronisches Zubehör > Stromversorgung > Überspannungsschutzgeräte -Elektronik > GPS -Elektronik > GPS > Auto-GPS-Systeme -Elektronik > GPS > Flugnavigation -Elektronik > GPS > Sport-GPS-Geräte +Elektronik > GPS-Navigationssysteme Elektronik > GPS-Tracker Elektronik > GPS-Zubehör Elektronik > GPS-Zubehör > GPS-Halterungen @@ -980,30 +750,26 @@ Elektronik > GPS-Zubehör > GPS-Taschen Elektronik > Geräte zur Mauterhebung Elektronik > Kommunikationsgeräte Elektronik > Kommunikationsgeräte > Anrufbeantworter -Elektronik > Kommunikationsgeräte > Anrufbeantworter > Telefonwarteschleifensysteme Elektronik > Kommunikationsgeräte > Anruferkennung Elektronik > Kommunikationsgeräte > Funkgeräte Elektronik > Kommunikationsgeräte > Funkgeräte > CB-Funkgeräte Elektronik > Kommunikationsgeräte > Funkgeräte > Funkscanner Elektronik > Kommunikationsgeräte > Funkgeräte > Funksprechgeräte Elektronik > Kommunikationsgeräte > Funkzubehör -Elektronik > Kommunikationsgeräte > Headsets Elektronik > Kommunikationsgeräte > Pager Elektronik > Kommunikationsgeräte > Sprechanlagen Elektronik > Kommunikationsgeräte > Sprechanlagen-Zubehör Elektronik > Kommunikationsgeräte > Telefone Elektronik > Kommunikationsgeräte > Telefone > Konferenztelefone Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefone -Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefone > Handyuhren -Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefone > Multifunktionstelefone -Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefone > Smartphones Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefonzubehör +Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefonzubehör > Auswurfhilfen für SIM-Karten Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefonzubehör > Ersatzteile für Mobiltelefone -Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefonzubehör > Ersatzteile für Mobiltelefone > Digitalisierer für Mobiltelefone -Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefonzubehör > Handy-SIM-Karten +Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefonzubehör > Handy-Prepaid- & -SIM-Karten Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefonzubehör > Handycharms & -anhänger Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefonzubehör > Mobiltelefonhalterungen & -ständer Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefonzubehör > Mobiltelefontaschen +Elektronik > Kommunikationsgeräte > Telefone > Mobiltelefonzubehör > Zubehör für Mobiltelefon-Kameras Elektronik > Kommunikationsgeräte > Telefone > Satellitentelefone Elektronik > Kommunikationsgeräte > Telefone > Schnurlostelefone Elektronik > Kommunikationsgeräte > Telefone > Schnurtelefone @@ -1011,26 +777,16 @@ Elektronik > Kommunikationsgeräte > Telefone > Telefonzubehör Elektronik > Kommunikationsgeräte > Telefone > Telefonzubehör > Telefonkarten Elektronik > Kommunikationsgeräte > Videokonferenzsysteme Elektronik > Komponenten -Elektronik > Komponenten > Automatisierungskomponenten -Elektronik > Komponenten > Automatisierungskomponenten > Antriebssysteme mit variabler Frequenz & einstellbarer Drehzahl -Elektronik > Komponenten > Automatisierungskomponenten > Speicherprogrammierbare Steuerungen Elektronik > Komponenten > Beschleunigungssensoren Elektronik > Komponenten > Modulatoren -Elektronik > Komponenten > Modulatoren > HF-Modulatoren Elektronik > Komponenten > Splitter -Elektronik > Komponenten > Splitter > HF-Splitter -Elektronik > Komponenten > Splitter > UHF-Splitter -Elektronik > Komponenten > Transformatoren -Elektronik > Komponenten > Transformatoren > Baluns -Elektronik > Komponenten > Verbinder -Elektronik > Komponenten > Verbinder > Keystone-Module -Elektronik > Komponenten > Verbinder > RCA-Klinkenstecker +Elektronik > Komponenten > Steckverbinder Elektronik > Komponenten > Wandler +Elektronik > Komponenten > Wandler > Audiowandler Elektronik > Komponenten > Wandler > Signalwandler Elektronik > Netzwerktechnik Elektronik > Netzwerktechnik > Bridges & Router Elektronik > Netzwerktechnik > Bridges & Router > Netzwerk-Bridges -Elektronik > Netzwerktechnik > Bridges & Router > Netzwerk-Bridges > WLAN-Bridges Elektronik > Netzwerktechnik > Bridges & Router > VoIP-Gateways & -Router Elektronik > Netzwerktechnik > Bridges & Router > Wireless Access Points Elektronik > Netzwerktechnik > Bridges & Router > Wireless Router @@ -1040,12 +796,13 @@ Elektronik > Netzwerktechnik > Konzentratoren & Multiplexer Elektronik > Netzwerktechnik > Modems Elektronik > Netzwerktechnik > Modemzubehör Elektronik > Netzwerktechnik > Netzwerkkarten -Elektronik > Netzwerktechnik > Netzwerkkarten > Xbox 360-Netzwerkkarten Elektronik > Netzwerktechnik > Netzwerksicherheitssysteme & Firewalls -Elektronik > Netzwerktechnik > Powerline-Netzwerkadapter +Elektronik > Netzwerktechnik > PoE-Adapter Elektronik > Netzwerktechnik > Repeater & Sende/-Empfangsgeräte -Elektronik > Plug & Play-TV-Spiele +Elektronik > Radargeschwindigkeitsmesser +Elektronik > Radarwarner Elektronik > Spielautomatenbedarf +Elektronik > Spielautomatenbedarf > Basketballspiele Elektronik > Spielautomatenbedarf > Flipper Elektronik > Spielautomatenbedarf > Flipper-Zubehör Elektronik > Spielautomatenbedarf > Skee-Ball-Maschinen @@ -1054,10 +811,6 @@ Elektronik > Spielautomatenbedarf > Zubehör für Spielautomaten Elektronik > Video Elektronik > Video > Computermonitore Elektronik > Video > Fernseher -Elektronik > Video > Fernseher > Flachbildschirmfernseher -Elektronik > Video > Fernseher > Projektions-TV-Geräte -Elektronik > Video > Fernseher > Röhrenfernsehgeräte -Elektronik > Video > Fernseher > Tragbare TV-Geräte Elektronik > Video > Projektoren Elektronik > Video > Projektoren > Diaprojektoren Elektronik > Video > Projektoren > Multimedia-Projektoren @@ -1069,15 +822,12 @@ Elektronik > Video > Video-Multiplexer Elektronik > Video > Videoabspielgeräte & -rekorder Elektronik > Video > Videoabspielgeräte & -rekorder > DVD- & Blu-ray-Player Elektronik > Video > Videoabspielgeräte & -rekorder > DVD-Rekorder -Elektronik > Video > Videoabspielgeräte & -rekorder > DVD-Rekorder > Blu-ray-Rekorder -Elektronik > Video > Videoabspielgeräte & -rekorder > DVD-Rekorder > HD-DVD-Rekorder Elektronik > Video > Videoabspielgeräte & -rekorder > Digitale Videorekorder -Elektronik > Video > Videoabspielgeräte & -rekorder > Home-Mediaplayer +Elektronik > Video > Videoabspielgeräte & -rekorder > Netzwerk-Mediaplayer Elektronik > Video > Videoabspielgeräte & -rekorder > Videorekorder Elektronik > Video > Videobearbeitungshardware & Videoproduktionsausrüstung Elektronik > Video > Videoserver Elektronik > Video > Videotransmitter -Elektronik > Video > Videotransmitter > Videosender Elektronik > Video > Videozubehör Elektronik > Video > Videozubehör > 3D-Brillen Elektronik > Video > Videozubehör > Computerbildschirmzubehör @@ -1093,374 +843,204 @@ Elektronik > Video > Videozubehör > TV-Zubehör Elektronik > Video > Videozubehör > TV-Zubehör > Ersatzlampen für Fernseher Elektronik > Video > Videozubehör > TV-Zubehör > TV- & Monitorhalterungen Elektronik > Video > Videozubehör > TV-Zubehör > TV-Konverter & Receiver +Elektronik > Video > Videozubehör > TV-Zubehör > TV-Lautsprecher Elektronik > Videospielkonsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Dreamcast-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > GameCube-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Jaguar-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Neo Geo-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Nintendo 64-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Nintendo Entertainment System-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > PC Engine-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > PlayStation 2-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > PlayStation 3-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > PlayStation-Originalkonsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Sega Genesis-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Sega Master System-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Super Nintendo-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Wii U -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Wii-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Xbox 360-Konsolen -Elektronik > Videospielkonsolen > Heim-Spielkonsolen > Xbox-Originalkonsolen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > Atari Lynx-Konsolen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > Game Gear-Konsolen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > Gameboy-Konsolen (alle) -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > Gameboy-Konsolen (alle) > Game Boy Advance-Konsolen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > Gameboy-Konsolen (alle) > Gameboy-Konsolen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > LeapFrog -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > N-Gage-Konsolen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > Neo Geo Pocket-Konsolen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > Nintendo 3DS -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > Nintendo DS-Konsolen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > PlayStation Portable-Konsolen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > PlayStation Vita -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > Retrogen -Elektronik > Videospielkonsolen > Tragbare Spielkonsolen > WonderSwan Elektronik > Zubehör für Videospielkonsolen Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Dreamcast-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > GameCube-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Jaguar-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Neo Geo-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Nintendo 64-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Nintendo Entertainment System-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > PC Engine-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > PlayStation-Zubehör (alle) -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > PlayStation-Zubehör (alle) > PlayStation 2-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > PlayStation-Zubehör (alle) > PlayStation 3-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > PlayStation-Zubehör (alle) > PlayStation-Originalzubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Sega Genesis-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Sega Master System-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Super Nintendo-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Wii U-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Wii-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Xbox-Zubehör (komplett) -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Xbox-Zubehör (komplett) > Xbox 360-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für Spielkonsolen > Xbox-Zubehör (komplett) > Xbox-Originalzubehör Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > Atari Lynx-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > Game Gear-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > Gameboy-Zubehör (komplett) -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > Gameboy-Zubehör (komplett) > Game Boy Advance-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > Gameboy-Zubehör (komplett) > Game Boy-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > N-Gage-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > Neo Geo Pocket-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > Nintendo 3DS-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > Nintendo DS-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > PlayStation Vita-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > Playstation Portable-Zubehör -Elektronik > Zubehör für Videospielkonsolen > Zubehör für mobile Spielkonsolen > WonderSwan-Zubehör Fahrzeuge & Teile +Fahrzeuge & Teile > Fahrzeuge +Fahrzeuge & Teile > Fahrzeuge > Kraftfahrzeuge +Fahrzeuge & Teile > Fahrzeuge > Kraftfahrzeuge > Autos, LKWs & Lieferwagen +Fahrzeuge & Teile > Fahrzeuge > Kraftfahrzeuge > Gelände- & Allradfahrzeuge +Fahrzeuge & Teile > Fahrzeuge > Kraftfahrzeuge > Gelände- & Allradfahrzeuge > Go-Karts +Fahrzeuge & Teile > Fahrzeuge > Kraftfahrzeuge > Gelände- & Allradfahrzeuge > Quads +Fahrzeuge & Teile > Fahrzeuge > Kraftfahrzeuge > Golfwagen +Fahrzeuge & Teile > Fahrzeuge > Kraftfahrzeuge > Motorräder & -roller +Fahrzeuge & Teile > Fahrzeuge > Kraftfahrzeuge > Schneemobile +Fahrzeuge & Teile > Fahrzeuge > Kraftfahrzeuge > Wohnmobile +Fahrzeuge & Teile > Fahrzeuge > Luftfahrzeuge +Fahrzeuge & Teile > Fahrzeuge > Wasserfahrzeuge +Fahrzeuge & Teile > Fahrzeuge > Wasserfahrzeuge > Jetski +Fahrzeuge & Teile > Fahrzeuge > Wasserfahrzeuge > Motorboote +Fahrzeuge & Teile > Fahrzeuge > Wasserfahrzeuge > Segelboote +Fahrzeuge & Teile > Fahrzeuge > Wasserfahrzeuge > Yachten Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi > Adapterkassetten -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi > Auto-Hifi-CD-Wechsler -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi > Auto-Hifi-Empfänger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi > Auto-Hifi-Empfänger > Car-Hifi-Satellitenradios -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi > Auto-Hifi-Endstufen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi > Auto-Hifi-Equalizer & -Frequenzweichen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi > Auto-Hifi-Kassettenspieler -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi > Auto-Hifi-Lautsprecher -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi > Auto-Hifi-Subwoofer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi > Freisprechanlagen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi- & -Videokabel -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Hifi-Überspannungsschutz -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Multimedia -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Multimedia > Auto-DVD-Player -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Auto-Hifi & -Multimedia > Auto-Multimedia > Auto-Monitore +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > ATV- & UTV-Schutzausrüstung +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > ATV- & UTV-Schutzausrüstung > ATV- & UTV-Griffpolster +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Auto-Alarmanlagen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Fernbediente schlüssellose Systeme +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Kfz-Türschlösser +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Kfz-Türschlösser > Kfz-Türschlosssicherungen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Kfz-Türschlösser > Türknöpfe +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Kfz-Türschlösser > Türschlösser & Schließsysteme +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Kupplungsschlösser +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Lenkradschlösser +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Motorrad-Schlösser & -Alarmanlagen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Radkrallen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Wegfahrsperren +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Auto-Alarmanlagen & Schließsysteme > Zubehör für Auto-Alarmanlagen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung > Airbagteile +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung > Fensternetze +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung > Gurtpolster +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung > Gurtschlösser +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung > Kfz-Warnflaggen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung > Sicherheitsgurtbänder +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung > Sicherheitsgurte +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung > Unterlegkeile +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung > Warnleuchten +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Kfz-Sicherheitsausrüstung > Überrollkäfige & -bügel +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung > Motorrad-Genickschutz +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung > Motorrad-Handprotektoren +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung > Motorrad-Nierengurte +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung > Motorrad: Brust- und Rückenprotektoren +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung > Motorrad: Ellbogen- und Handgelenkschützer +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung > Motorrad: Knie- & Schienbeinschützer +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung > Motorradbrillen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung > Motorradhandschuhe +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung > Motorradhelme +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Fahrzeugsicherheit > Motorrad-Schutzausrüstung > Motorradhelmersatzteile & -zubehör Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Flugzeugteile & -Zubehör -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Abschlepphaken für Kfz -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Einstiegsleisten -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Ersatzteile für Pkw-Anhänger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Fahrzeugkühlergrills -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Fußrasten für Motorräder -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Hardtops -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Karosseriebausätze -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kennzeichen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Anhängerkupplung -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Diffusoren -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträger > Autogepäckträger für Angelruten -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträger > Autogepäckträger für Kanus & Kajaks -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträger > Autogepäckträger für Motorräder & Motorroller -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträger > Autogepäckträger für Skier & Snowboards -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträger > Autogepäckträger für Surfbretter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträger > Autogewehrhalter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträger > Fahrradträger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträger > Gepäckträger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträger > Grundgestelle für Autogepäckträger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträgerzubehör -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträgerzubehör > Fahrradträgerzubehör -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträgerzubehör > Fahrradträgerzubehör > Adapter für Fahrradgabelhalter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträgerzubehör > Fahrradträgerzubehör > Befestigungsriemen für Fahrräder -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Gepäckträgerzubehör > Fahrradträgerzubehör > Fahrradrahmenhalter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Ladenetze -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Türen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Kfz-Warnflaggen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Ladeflächen für Pickups -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Ladeflächenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Ladeflächenteile > Gestänge für Lkw-Betten -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Motorradkotflügel -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Motorradlenker- & Griffe -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Motorradsitze -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Motorradverkleidungen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Schalthebel für Motorräder -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Schiebedächer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Spoiler -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Stoßstangen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Stoßstangenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Teile für Kfz-Türen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Verdecke -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Winden -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Außenteile > Windenzubehör -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Armaturenbrett-Zubehör -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Autofußmatten -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Autositzauflagen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Autositze -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Dachhimmel -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Elektrisch verstellbare Sitze -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Elektrische Kfz-Sicherungen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Fahrzeugteppiche -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Getränkehalter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Kfz-Armstützen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Kfz-Rückenlehnen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Sonnenblenden -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Innenausstattung > Zigarettenanzünderstecker -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme > Autoalarmanlagen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme > Autokameras -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme > Fernbediente schlüssellose Systeme -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme > Freilaufnaben -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme > Kindersicherungen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme > Lenkradschlösser -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme > Motorrad-Schlösser & -Alarmanlagen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme > Wegfahrsperren -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme > Zentralverriegelungen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Schließsysteme > Zubehör für Auto-Alarmanlagen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Sicherheitsausrüstung -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Sicherheitsausrüstung > Einparkhilfen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik > A/V-Player & im Armaturenbrett integrierte Systeme für Autos +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik > Audioverstärker für Autos +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik > Equalizer & Frequenzweichen für Autos +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik > Freisprechanlagen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik > Halterungen für Kfz-Videomonitore +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik > Kassettenadapter +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik > Kassettenspieler für Autos +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik > Lautsprecher für Autos +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik > Parkkameras für Autos +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Elektronik > Subwoofer für Autos Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Achsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Antriebswellen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Antriebswellenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Differentiale -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Getriebe -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Getrieberäder -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Getriebeteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Kipphebel -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Kipphebelteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Kipphebelteile > Ventildeckel -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Kugellager -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Kupplungsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Pleuelstangen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Antriebsteile > Verteilergetriebeteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Aufhängungsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Aufhängungsteile > Stoßdämpfer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Brems- & Kupplungshebel +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Abschleppzubehör +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Aufhängungsteile für Autos +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Bodenbeläge & Polster +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Getriebe- & Antriebsteile Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Auspuff -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Auspuff > Abgasrückführungsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Auspuff > Auspuffe & Auspuffteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Auspuff > Auspuffkrümmer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Auspuff > Auspufftöpfe & Teile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Auspuff > Katalysatoren -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Auspuff > Sauerstoffsensoren & Teile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Batterien -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Batterien > Hybridbatterien Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung > Kfz-Fahrtrichtungsanzeiger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung > Kfz-Glühbirnen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung > Kfz-Innenbeleuchtung -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung > Kfz-Nebelscheinwerfer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung > Kfz-Rück- & Bremslichter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung > Kfz-Rückfahrlichter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung > Kfz-Scheinwerfer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung > Kfz-Seitenleuchten -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung > Kfz-Standlichter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Beleuchtung > Scheinwerferabdeckungen für Fahrzeuge Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Bremsen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Bremsen > Bremsenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Bremsen > Feststellbremsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Bremsen > Teile für Kfz-Handbremsen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Keilriemen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Elektroniksysteme +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Innenausstattung Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Klimatisierung -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Klimatisierung > Kfz-Enteisungszubehör -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Klimatisierung > Kfz-Gebläseteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Klimatisierung > Kfz-Heizungsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Klimatisierung > Kfz-Klimaanlageteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Klimatisierung > Kfz-Temperaturregler +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motoren Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Anlasser -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Anlasserteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Generatorenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Heizsysteme -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Heizsystemteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Kolben -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Kolbenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Kolbenteile > Kfz-Kolbenbolzen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Kolbenteile > Kfz-Kolbenringe -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Kompressorteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Kurbelwellen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Kurbelwellenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Lichtmaschinen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Lichtmaschinenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Motordichtsätze -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Motorsteuerungsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Motorsteuerungsteile > Steuerketten -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Nockenwellen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Nockenwellenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Schwungräder & -Schwungradteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Vakuumpumpenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Verdichter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Verdichterteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Vergaser -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Vergaserteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Zylinderköpfe & -teile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Zündungsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Zündungsteile > Kfz-Verteilerteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Zündungsteile > Teile für Hochspannungskondensatorzündungen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Zündungsteile > Zündkerzen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Motorteile > Kfz-Zündungsteile > Zündspulen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Felgen & Reifen für Kfz Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Felgen & Reifen für Kfz > Autofelgen & -räder Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Felgen & Reifen für Kfz > Felgen & Räder für ATV & UTV -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Felgen & Reifen für Kfz > Felgen & Räder für ATV & UTV > Felgen & Räder für Quads/ATVs -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Felgen & Reifen für Kfz > Felgen & Räder für ATV & UTV > Felgen & Räder für UTV-Fahrzeuge Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Felgen & Reifen für Kfz > Motorradfelgen & -räder Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Kfz-Radteile Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Kfz-Reifen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Kfz-Reifen > Autoreifen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Kfz-Reifen > Motorradreifen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Kfz-Reifen > Reifen für ATV & UTV -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Kfz-Reifen > Reifen für ATV & UTV > ATV-Reifen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Kfz-Reifen > Reifen für ATV & UTV > Reifen für UTV-Fahrzeuge Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Kfz-Reifenzubehör -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Räder > Kfz-Reifenzubehör > Schneeketten +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Sensoren & -Messinstrumente +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Sitze Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Spiegel -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Spiegel > Anhänger- & Wohnwagenspiegel -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Spiegel > Fahrzeug-Außenspiegel -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Spiegel > Kfz-Rückspiegel -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Ventile & -teile +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kfz-Steuerelemente Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen > Benzinpumpen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen > Einspritzdüsen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen > Einspritzteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen > Kraftstoffleitungen & Teile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen > Kraftstoffpumpenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen > Kraftstoffsiebe & -filter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen > Lachgaseinspritzsysteme -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen > Luftmassenmesser -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen > Treibstofftanks -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Kraftstoffanlagen > Treibstofftankteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Lenkungsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Lenkungsteile > Achsschenkelbolzen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Lenkungsteile > Lenkradkontrolltasten -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Lenkungsteile > Lenkradkontrolltasten > Frontscheinwerferregelungselemente -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Lenkungsteile > Lenkradkontrolltasten > Kfz-Lichtdimmer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Lenkungsteile > Lenkradkontrolltasten > Tempomat-Teile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Lenkungsteile > Lenkradkontrolltasten > Wischergeschwindigkeitssteuerung -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Lenkungsteile > Lenkräder -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Lenkungsteile > Servolenkungsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Luftansaugungsteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Luftansaugungsteile > Kfz-Luftpumpen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Luftansaugungsteile > Kompressorenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Luftansaugungsteile > Luftfilter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Luftansaugungsteile > Luftverteiler -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Pedale für Kfz -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Scheibenwischer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Teile für Kfz-Batterien +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Rahmen- & Karosserieteile Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Teile für Kfz-Fenster -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Teile für Kfz-Fenster > Fenster- & Windschutzscheibenglas -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Teile für Kfz-Fenster > Teile für elektrische Fensterheber -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Ölkreislauf -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Ölkreislauf > Ölfilter -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Ölkreislauf > Ölpumpen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Ölkreislauf > Ölpumpenteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Ölkreislauf > Ölwannen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Teile > Teile für Kfz-Ölkreislauf Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Aufladegeräte für Fahrzeugbatterien Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugdiagnosegeräte +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Fahrzeug-Hardtops +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Fahrzeugabdeckplanen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Fahrzeugabdeckplanen > Bootsabdeckplanen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Fahrzeugabdeckplanen > Golfcart-Abdeckplanen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Fahrzeugabdeckplanen > Kfz-Abdeckplanen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Fahrzeugabdeckplanen > Motorradabdeckplanen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Fahrzeugabdeckplanen > Unterstände & Abdeckungen für Wohnmobile +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Fahrzeugverdecke +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Golfcart-Gehäuse +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Ladeflächenabdeckungen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugabdeckungen > Windschutzscheiben-Abdeckungen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeuglack +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeuglack > Bremssattellack +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeuglack > Rahmen- & Karosserielack Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung > Autowaschbürsten Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung > Autowaschmittel +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung > Einspritzanlagenreinigungs-Sets Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung > Fahrzeug-Glasreiniger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung > Fahrzeug-Polsterreiniger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung > Fahrzeug-Sprühreiniger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung > Fahrzeug-Teppichreiniger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung > Reifenreinigungs- & Glanzmittel +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung > Kfz-Teppich- & Polsterreiniger Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreinigung > Wachse, Polituren & Schutzmittel für Fahrzeuge +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge > Aufladegeräte für Fahrzeugbatterien +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge > Fahrzeugbatterie-Prüfgeräte +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge > Fahrzeugdiagnosegeräte +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge > Karosseriedichtmasse +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge > Kfz-Bremsreparatur-Sets +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge > Kfz-Starthilfen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge > Kfz-Überbrückungskabel +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge > Werkzeuge für Kupplungsausrichtung & -ausbau +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge > Werkzeuge für Reifenreparatur & -wechsel +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Fahrzeugreparatur- & Spezialwerkzeuge > Windschutzscheibenreparatursets Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Antennenbälle +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Abdeckungen für Anhängerkupplungen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Autofolien -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Autoscheibenfolien -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Autositzbezüge +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Fahrzeug-Außendesigns +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Fahrzeug-Dekosets Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Fahrzeug-Embleme +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Kennzeichen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Kennzeichenhalterungen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Kennzeichenrahmen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Kfz-Antennenbälle +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Kfz-Armaturenbrett-Zubehör Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Kfz-Aufkleber Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Kfz-Fahnen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Kfz-Kennzeichenabdeckungen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Kfz-Lufterfrischer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Magneten -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Rückenlehnentaschen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Lenkradbezüge +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Magnete +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Rückspiegel-Deko +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Schalthebelverkleidung +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Dekor > Schaltknäufe Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Benzin- & Ölzusätze Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Bremsflüssigkeit -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Flüssigkeit für Servolenkungen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Flüssigkeit für hydraulische Kupplungen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Frostschutzmittel Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Getriebeöl Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Kfz-Schmierstoffe Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Kühlsystemadditive -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Motorenöl Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Motorreiniger +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Motoröl +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Servolenkflüssigkeit Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Tankreiniger Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kfz-Flüssigkeiten > Wischwasser -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Reifenbedarf -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Reifenbedarf > Radkappen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Reifenbedarf > Radventilkappen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Reifenbedarf > Reifenabdeckungen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Reifenbedarf > Reifendrucksensoren & -messer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Reifenbedarf > Reifenstifte -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Starthilfe -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Windschutzscheibenreparatursets -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Überbrückungskabel -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Überwachungstechnik -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Überwachungstechnik > Benzinuhren -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Überwachungstechnik > Geschwindigkeitsanzeiger -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Überwachungstechnik > Kfz-Bordcomputer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Überwachungstechnik > Kilometerzähler -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Überwachungstechnik > Motorsteuergerätteile -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Überwachungstechnik > Tachometer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung > Motorrad-Genickschutz -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung > Motorrad-Nierengurte -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung > Motorrad: Brust- und Rückenprotektoren -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung > Motorrad: Ellbogen- und Handgelenkschützer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung > Motorrad: Knie- & Schienbeinschützer -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung > Motorradbrillen -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung > Motorradhandschuhe -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung > Motorradhelme -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung > Motorradhelmersatzteile & -zubehör -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorrad-Schutzausrüstung > Motorradhelmersatzteile & -zubehör > Motorradhelm-Visiere -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Motorradzubehör > Motorradtaschen & -koffer +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Kfz-Wartung & -Pflege > Kraftstoffkanister +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Boxen & Sortiersysteme für Ladeflächen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Bügel & Haken für Kopfstützen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Anhänger +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Anhänger > Bootsanhänger +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Anhänger > Kleinanhänger & Transportanhänger +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Anhänger > Pferde- & Viehanhänger +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Anhänger > Wohnwagen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträger +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträger > Autogepäckträger für Angelruten +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträger > Autogepäckträger für Kanus & Kajaks +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträger > Autogepäckträger für Motorräder & Motorroller +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträger > Autogepäckträger für Skier & Snowboards +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträger > Autogepäckträger für Surfbretter +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträger > Autogewehrhalter +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträger > Fahrradträger +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträger > Gepäckträger +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträger > Grundgestelle für Autogepäckträger +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträgerzubehör +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträgerzubehör > Fahrradträgerzubehör +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Gepäckträgerzubehör > Ski- & Snowboardträger-Zubehör +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Kfz-Ladenetze +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Laderampen +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Motorradtaschen & -koffer +Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Stauraum- & Transportsysteme > Utensilientaschen fürs Auto Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zubehör Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zubehör > Anlegen & Ankern Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zubehör > Anlegen & Ankern > Anker @@ -1493,7 +1073,6 @@ Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zube Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zubehör > Wasserfahrzeugmotorteile > Wasserfahrzeugpropeller Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zubehör > Wasserfahrzeugmotorteile > Wasserfahrzeugvergaser & Teile Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zubehör > Wasserfahrzeugpflege -Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zubehör > Wasserfahrzeugpflege > Wasserfahrzeugabdeckungen Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zubehör > Wasserfahrzeugpflege > Wasserfahrzeugpolituren Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zubehör > Wasserfahrzeugpflege > Wasserfahrzeugreiniger Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zubehör > Wasserfahrzeugsteuerung @@ -1502,7 +1081,6 @@ Fahrzeuge & Teile > Fahrzeugersatzteile & -zubehör > Wasserfahrzeugteile & Zube Für Erwachsene Für Erwachsene > Erotik Für Erwachsene > Erotik > Erotikbücher -Für Erwachsene > Erotik > Erotikbücher > Erotik-Comics Für Erwachsene > Erotik > Erotische DVDs & Videos Für Erwachsene > Erotik > Erotische Kleidung Für Erwachsene > Erotik > Erotische Lebensmittel & Esswaren @@ -1510,71 +1088,101 @@ Für Erwachsene > Erotik > Erotische Spiele Für Erwachsene > Erotik > Erotische Zeitschriften Für Erwachsene > Erotik > Pole Dance-Tanzstangenkits Für Erwachsene > Erotik > Sexspielzeug +Für Erwachsene > Waffen +Für Erwachsene > Waffen > Elektroschockpistolen & Taser-Waffen +Für Erwachsene > Waffen > Fechtwaffen +Für Erwachsene > Waffen > Hieb- und Stichwaffen +Für Erwachsene > Waffen > Kampfmesser +Für Erwachsene > Waffen > Nunchakus +Für Erwachsene > Waffen > Peitschen +Für Erwachsene > Waffen > Schlagringe +Für Erwachsene > Waffen > Schlagstockwaffen +Für Erwachsene > Waffen > Schusswaffen +Für Erwachsene > Waffen > Schusswaffenzubehör +Für Erwachsene > Waffen > Schusswaffenzubehör > Material & Ausrüstung zum Nachladen von Schusswaffen +Für Erwachsene > Waffen > Schusswaffenzubehör > Material & Ausrüstung zum Nachladen von Schusswaffen > Ladepressen +Für Erwachsene > Waffen > Schusswaffenzubehör > Munition +Für Erwachsene > Waffen > Schusswaffenzubehör > Munitionskisten & -halter +Für Erwachsene > Waffen > Schusswaffenzubehör > Picatinny-Schienen +Für Erwachsene > Waffen > Schusswaffenzubehör > Pistolentaschen +Für Erwachsene > Waffen > Schusswaffenzubehör > Schusswaffengriffe +Für Erwachsene > Waffen > Schusswaffenzubehör > Schusswaffengurte +Für Erwachsene > Waffen > Schusswaffenzubehör > Schusswaffenreinigung +Für Erwachsene > Waffen > Schusswaffenzubehör > Schusswaffenreinigung > Schusswaffen-Reinigungsmittel +Für Erwachsene > Waffen > Schusswaffenzubehör > Schusswaffenreinigung > Schusswaffen-Reinigungspatches +Für Erwachsene > Waffen > Schusswaffenzubehör > Schusswaffenreinigung > Schusswaffen-Reinigungstücher +Für Erwachsene > Waffen > Schusswaffenzubehör > Waffenkoffer und -taschen +Für Erwachsene > Waffen > Schusswaffenzubehör > Waffenleuchten +Für Erwachsene > Waffen > Speerwaffen +Für Erwachsene > Waffen > Tränengas & Pfefferspray +Für Erwachsene > Waffen > Wurfsterne Gesundheit & Schönheit Gesundheit & Schönheit > Gesundheitspflege Gesundheit & Schönheit > Gesundheitspflege > Akupunktur Gesundheit & Schönheit > Gesundheitspflege > Akupunktur > Akupunkturmodelle Gesundheit & Schönheit > Gesundheitspflege > Akupunktur > Akupunkturnadeln -Gesundheit & Schönheit > Gesundheitspflege > Arthritisbehandlung +Gesundheit & Schönheit > Gesundheitspflege > Amputationsstrümpfe Gesundheit & Schönheit > Gesundheitspflege > Beatmungsmedizin +Gesundheit & Schönheit > Gesundheitspflege > Beatmungsmedizin > CPAP-Geräte +Gesundheit & Schönheit > Gesundheitspflege > Beatmungsmedizin > CPAP-Masken +Gesundheit & Schönheit > Gesundheitspflege > Beatmungsmedizin > Dampfinhalatoren Gesundheit & Schönheit > Gesundheitspflege > Beatmungsmedizin > Inhalatoren +Gesundheit & Schönheit > Gesundheitspflege > Beatmungsmedizin > Sauerstoffbehälter Gesundheit & Schönheit > Gesundheitspflege > Behälter für Verhütungsmittel Gesundheit & Schönheit > Gesundheitspflege > Bettpfannen -Gesundheit & Schönheit > Gesundheitspflege > Blutgruppentests -Gesundheit & Schönheit > Gesundheitspflege > CPAP-Ausrüstung -Gesundheit & Schönheit > Gesundheitspflege > CPAP-Ausrüstung > CPAP-Geräte -Gesundheit & Schönheit > Gesundheitspflege > CPAP-Ausrüstung > CPAP-Masken -Gesundheit & Schönheit > Gesundheitspflege > Diabetikerbedarf -Gesundheit & Schönheit > Gesundheitspflege > Drogentests +Gesundheit & Schönheit > Gesundheitspflege > Ergo- & Physiotherapeutische Hilfsmittel +Gesundheit & Schönheit > Gesundheitspflege > Ergo- & Physiotherapeutische Hilfsmittel > Elektrische Muskelstimulatoren +Gesundheit & Schönheit > Gesundheitspflege > Ergo- & Physiotherapeutische Hilfsmittel > Therapieschaukeln Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Antiseptika & Reinigung Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Augenwaschbedarf -Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Behandlung von Ausschlägen Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Erste-Hilfe-Koffer Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Medizinisches Klebeband & Verbandsmaterial Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Schutzhüllen für Gipsverbände Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Warm & Kalt Therapie Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Warm & Kalt Therapie > Eisanwendungen +Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Warm & Kalt Therapie > Wärmecremes Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Warm & Kalt Therapie > Wärmflaschen & Heizkissen -Gesundheit & Schönheit > Gesundheitspflege > Erste Hilfe > Wärmecremes Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung -Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung > Diätpräparate Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung > Energie-Gel & -Nahrung -Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung > Ergänzung zur künstlichen Ernährung +Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung > Flüssignahrung zur künstlichen Ernährung Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung > Mahlzeitenersatz-Getränke -Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung > Proteinpulver Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung > Pürierte Lebensmittel Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung > Sportriegel -Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung > Traditionelle chinesische Tonika Gesundheit & Schönheit > Gesundheitspflege > Fitness & Ernährung > Vitamine & Nahrungsergänzungsmittel -Gesundheit & Schönheit > Gesundheitspflege > HIV-Tests Gesundheit & Schönheit > Gesundheitspflege > Hausnotrufgeräte -Gesundheit & Schönheit > Gesundheitspflege > Hörgeräte Gesundheit & Schönheit > Gesundheitspflege > Hörhilfen Gesundheit & Schönheit > Gesundheitspflege > Inkontinenzartikel +Gesundheit & Schönheit > Gesundheitspflege > Kondome +Gesundheit & Schönheit > Gesundheitspflege > Kontaktgels & -lotionen +Gesundheit & Schönheit > Gesundheitspflege > Lichttherapielampen +Gesundheit & Schönheit > Gesundheitspflege > Medikamente & Arzneimittel Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte +Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Aktivitätsmonitore Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Alkoholmessgeräte Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Blutdruckmessgeräte Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Blutzuckermessgeräte Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Cholesterinmessgeräte Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Fieberthermometer -Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Fruchtbarkeitscomputer -Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Herzfrequenzmessgeräte +Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Fruchtbarkeitsmonitore & Ovulationstests Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Körperfettanalyse Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Personenwaagen Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Pränatale Herzfrequenzmesser Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Pulsoximeter -Gesundheit & Schönheit > Gesundheitspflege > Medizinische Messgeräte > Schrittzähler +Gesundheit & Schönheit > Gesundheitspflege > Medizinische Tests +Gesundheit & Schönheit > Gesundheitspflege > Medizinische Tests > Allergietest-Sets +Gesundheit & Schönheit > Gesundheitspflege > Medizinische Tests > Blutgruppentests +Gesundheit & Schönheit > Gesundheitspflege > Medizinische Tests > Drogentests +Gesundheit & Schönheit > Gesundheitspflege > Medizinische Tests > HIV-Tests +Gesundheit & Schönheit > Gesundheitspflege > Medizinische Tests > Harnwegsinfektionstests +Gesundheit & Schönheit > Gesundheitspflege > Medizinische Tests > Schwangerschaftstests Gesundheit & Schönheit > Gesundheitspflege > Medizinisches Gleitgel Gesundheit & Schönheit > Gesundheitspflege > Notfall-Armband -Gesundheit & Schönheit > Gesundheitspflege > Orthopädische Hilfsmittel -Gesundheit & Schönheit > Gesundheitspflege > Orthopädische Hilfsmittel > Handtrainer -Gesundheit & Schönheit > Gesundheitspflege > Rauchabgewöhnung -Gesundheit & Schönheit > Gesundheitspflege > Schwangerschaftstests +Gesundheit & Schönheit > Gesundheitspflege > Pillendosen +Gesundheit & Schönheit > Gesundheitspflege > Probenbehälter Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Behindertengerechte Möbel & Vorrichtungen Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Behindertengerechte Möbel & Vorrichtungen > Duschbänke & -sitze -Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Behindertenzubehör Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Gehhilfen Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Gehhilfen > Gehstöcke Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Gehhilfen > Krücken @@ -1583,58 +1191,59 @@ Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Ge Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Zubehör & Bedarf zur Barrierefreiheit Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Zubehör & Bedarf zur Barrierefreiheit > Elektromobile Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Zubehör & Bedarf zur Barrierefreiheit > Rollstühle -Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Zubehör & Bedarf zur Barrierefreiheit > Rollstühle > Elektrorollstühle -Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Zubehör & Bedarf zur Barrierefreiheit > Rollstühle > Standardrollstühle Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Zubehör & Bedarf zur Barrierefreiheit > Treppenlifte +Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Zubehör & Bedarf zur Barrierefreiheit > Umlagerungsbretter & -tücher +Gesundheit & Schönheit > Gesundheitspflege > Senioren- & Behindertenbedarf > Zubehör für Behindertengerechte Möbel & Vorrichtungen +Gesundheit & Schönheit > Gesundheitspflege > Spermizide Gesundheit & Schönheit > Gesundheitspflege > Stützen & Bandagen -Gesundheit & Schönheit > Gesundheitspflege > Verhütungsmittel -Gesundheit & Schönheit > Gesundheitspflege > Verhütungsmittel > Kondome -Gesundheit & Schönheit > Gesundheitspflege > Verhütungsmittel > Spermizide Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte > Blutzuckermessung Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte > Blutzuckermessung > Blutzucker-Kontrolllösung Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte > Blutzuckermessung > Blutzuckerteststreifen Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte > Blutzuckermessung > Stechhilfen -Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte > Verhütungscomputerzubehör +Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte > Zubehör für Aktivitätsmonitore Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte > Zubehör für Badezimmerwaagen Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte > Zubehör für Blutdrucküberwachungsgeräte Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte > Zubehör für Blutdrucküberwachungsgeräte > Blutdruckmanschetten -Gesundheit & Schönheit > Gesundheitspflege > Zubehör für biometrische Messgeräte > Zubehör für Herzfrequenzmesser Gesundheit & Schönheit > Körperpflege Gesundheit & Schönheit > Körperpflege > Augenpflege Gesundheit & Schönheit > Körperpflege > Augenpflege > Augentropfen Gesundheit & Schönheit > Körperpflege > Augenpflege > Brillen Gesundheit & Schönheit > Körperpflege > Augenpflege > Brillengläser Gesundheit & Schönheit > Körperpflege > Augenpflege > Brillenzubehör -Gesundheit & Schönheit > Körperpflege > Augenpflege > Brillenzubehör > Brillenetuis & -ständer +Gesundheit & Schönheit > Körperpflege > Augenpflege > Brillenzubehör > Brillenbänder & -ketten +Gesundheit & Schönheit > Körperpflege > Augenpflege > Brillenzubehör > Brillenetuis & -halter +Gesundheit & Schönheit > Körperpflege > Augenpflege > Brillenzubehör > Kontaktlinsenreiniger Gesundheit & Schönheit > Körperpflege > Augenpflege > Kontaktlinsen Gesundheit & Schönheit > Körperpflege > Augenpflege > Kontaktlinsenpflege +Gesundheit & Schönheit > Körperpflege > Augenpflege > Kontaktlinsenpflege > Kontaktlinsen-Pflegesets Gesundheit & Schönheit > Körperpflege > Augenpflege > Kontaktlinsenpflege > Kontaktlinsenbehälter Gesundheit & Schönheit > Körperpflege > Augenpflege > Kontaktlinsenpflege > Kontaktlinsenpflegemittel -Gesundheit & Schönheit > Körperpflege > Augenpflege > Kontaktlinsenpflege > Pflegekits für Kontaktlinsen Gesundheit & Schönheit > Körperpflege > Augenpflege > Sonnenbrillengläser Gesundheit & Schönheit > Körperpflege > Damenhygieneartikel Gesundheit & Schönheit > Körperpflege > Damenhygieneartikel > Damen-Deodorant -Gesundheit & Schönheit > Körperpflege > Damenhygieneartikel > Intim-Waschlotionen +Gesundheit & Schönheit > Körperpflege > Damenhygieneartikel > Intim-Waschlotionen für Frauen +Gesundheit & Schönheit > Körperpflege > Damenhygieneartikel > Menstruationstassen Gesundheit & Schönheit > Körperpflege > Damenhygieneartikel > Slipeinlagen & Binden Gesundheit & Schönheit > Körperpflege > Damenhygieneartikel > Tampons Gesundheit & Schönheit > Körperpflege > Deodorants & Antitranspirante Gesundheit & Schönheit > Körperpflege > Einlaufsets & -zubehör Gesundheit & Schönheit > Körperpflege > Fußpflege -Gesundheit & Schönheit > Körperpflege > Fußpflege > Antipilzmittel +Gesundheit & Schönheit > Körperpflege > Fußpflege > Ballenpflege Gesundheit & Schönheit > Körperpflege > Fußpflege > Einlegesohlen & Einlagen Gesundheit & Schönheit > Körperpflege > Fußpflege > Fußgeruchskiller Gesundheit & Schönheit > Körperpflege > Fußpflege > Hühneraugen- & Hornhautprodukte -Gesundheit & Schönheit > Körperpflege > Fußpflege > Zehenpflege Gesundheit & Schönheit > Körperpflege > Fußpflege > Zehenspreizer Gesundheit & Schönheit > Körperpflege > Gleitmittel Gesundheit & Schönheit > Körperpflege > Haarkosmetik Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haar-Decoloration Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haarfärbemittel +Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haarpflege-Sets Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haarscheren Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haarstyling-Geräte Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haarstyling-Geräte > Haarglätter Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haarstyling-Geräte > Haartrockner +Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haarstyling-Geräte > Hairstyling-Sets Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haarstyling-Geräte > Kämme & Bürsten Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haarstyling-Geräte > Lockenstäbe Gesundheit & Schönheit > Körperpflege > Haarkosmetik > Haarstyling-Geräte > Lockenwickler @@ -1654,7 +1263,7 @@ Gesundheit & Schönheit > Körperpflege > Kosmetika > Badeartikel Gesundheit & Schönheit > Körperpflege > Kosmetika > Badeartikel > Bade- & Naturschwämme Gesundheit & Schönheit > Körperpflege > Kosmetika > Badeartikel > Badebürsten Gesundheit & Schönheit > Körperpflege > Kosmetika > Badeartikel > Duschhauben -Gesundheit & Schönheit > Körperpflege > Kosmetika > Badeartikel > Feuchttücher +Gesundheit & Schönheit > Körperpflege > Kosmetika > Badeartikel > Feuchttücher für Erwachsene Gesundheit & Schönheit > Körperpflege > Kosmetika > Badeartikel > Flüssigseifen Gesundheit & Schönheit > Körperpflege > Kosmetika > Badeartikel > Handdesinfektionsmittel Gesundheit & Schönheit > Körperpflege > Kosmetika > Badeartikel > Schaumbäder & Badesalze @@ -1668,64 +1277,68 @@ Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Aknebehandlun Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Anti-Aging-Hautpflegeprodukte Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Bräunungsprodukte Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Bräunungsprodukte > Selbstbräuner -Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Bräunungsprodukte > Selbstbräuner & Selbstbräuner-Entferner Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Bräunungsprodukte > Sonnenöle & -lotionen -Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Gesichtsmasken Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Gesichtspeeling Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Gesichtsreiniger -Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Gesichtsreinigungscremes +Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Gesichtsreinigersets Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Insektenschutzmittel +Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Komprimierte Gesichtsmasken Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Körperpuder Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Körperöle Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Lippenpflege Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Lotion & Feuchtigkeitscremes -Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Lotion & Feuchtigkeitscremes > Feuchtigkeitsspendende Gesichtscremes -Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Lotion & Feuchtigkeitscremes > Fußlotion -Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Lotion & Feuchtigkeitscremes > Handlotionen -Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Lotion & Feuchtigkeitscremes > Körperlotion Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Make-up-Entferner Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Porenreinigungspflaster Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Reinigungswasser & Adstringentien Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Sonnencreme Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Vaseline +Gesundheit & Schönheit > Körperpflege > Kosmetika > Hautpflege > Warzenentferner Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Hautpflegeutensilien +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Hautpflegeutensilien > Applikatoren für Lotionen und Sonnenschutzcremes Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Hautpflegeutensilien > Bimssteine Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Hautpflegeutensilien > Fußfeilen Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Hautpflegeutensilien > Gesichtsbürsten Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Hautpflegeutensilien > Gesichtssaunas Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Hautpflegeutensilien > Hautpflegeroller +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Hautpflegeutensilien > Hautreinigungs-Bürstenköpfe Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Hautpflegeutensilien > Mitesser-Entferner Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör -Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Applikatoren für künstliche Wimpern Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Augenbrauenschablonen Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Ersatzkissen für Wimpernzangen -Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Kleber für doppelte Augenlider -Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Kleber für künstliche Wimpern Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Make-up-Pinsel Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Make-up-Schwämme Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Make-up-Spiegel +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Nachfüllbare Make-up-Paletten & -Koffer Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Pudertücher +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Schlupflid-Kleber & -Klebestreifen Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Wimpernformer +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Zubehör für künstliche Wimpern +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Zubehör für künstliche Wimpern > Applikatoren für künstliche Wimpern +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Zubehör für künstliche Wimpern > Entferner für künstliche Wimpern +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Make-up Zubehör > Zubehör für künstliche Wimpern > Kleber für künstliche Wimpern Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Finger- & Zehenspreizer Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Maniküre-Sets Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Nagelfeilen & Sandblattfeilen Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Nagelfräser Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Nagelhautscheren Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Nagelhautschieber Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Nagelknipser +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Nagelpiercing-Zubehör Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Nagelpolierer Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Nageltrockner -Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Maniküre & Pediküre > Zehenspreizer für Pediküre -Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetik-Zubehör > Pinzetten +Gesundheit & Schönheit > Körperpflege > Kosmetika > Kosmetiksets Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up -Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen-Make-up -Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen-Make-up > Augenbrauenstifte -Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen-Make-up > Behandlungen für Wimpernwachstum -Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen-Make-up > Kajalstifte -Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen-Make-up > Künstliche Wimpern -Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen-Make-up > Lidschatten -Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen-Make-up > Mascara +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen > Augenbrauen Make-up +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen > Eyeliner & Kajal +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen > Künstliche Wimpern +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen > Lidschatten +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen > Lidschatten-Grundierung +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen > Mascara +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen > Mascara-Grundierung +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Augen > Wimpern- & Augenbrauenbehandlung Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Kostüm- & Bühnen-Make-up Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Körper-Make-up Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Körper-Make-up > Bodypainting-Farbe @@ -1735,9 +1348,10 @@ Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Lippen > Lipglos Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Lippen > Lipliner Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Lippen > Lippen- & Wangentönung Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Lippen > Lippenstift -Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Makeup-Sets +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Lippen > Lippenstift-Grundierung Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Spray zum Fixieren von Make-up Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Teint +Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Teint > Gesichtsgrundierung Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Teint > Grundierungen & Concealer Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Teint > Highlighter & Luminizer Gesundheit & Schönheit > Körperpflege > Kosmetika > Make-up > Teint > Puder @@ -1748,24 +1362,30 @@ Gesundheit & Schönheit > Körperpflege > Kosmetika > Nagelpflege > Künstliche Gesundheit & Schönheit > Körperpflege > Kosmetika > Nagelpflege > Nagelhautcremes & -Lotionen Gesundheit & Schönheit > Körperpflege > Kosmetika > Nagelpflege > Nagelkleber Gesundheit & Schönheit > Körperpflege > Kosmetika > Nagelpflege > Nagelkunst-Zubehör +Gesundheit & Schönheit > Körperpflege > Kosmetika > Nagelpflege > Nagellack-Überlacke und -Trockensprays Gesundheit & Schönheit > Körperpflege > Kosmetika > Nagelpflege > Nagellacke Gesundheit & Schönheit > Körperpflege > Kosmetika > Nagelpflege > Nagellackentferner Gesundheit & Schönheit > Körperpflege > Kosmetika > Nagelpflege > Nagellackverdünner Gesundheit & Schönheit > Körperpflege > Kosmetika > Reiniger für Kosmetikwerkzeuge Gesundheit & Schönheit > Körperpflege > Massage & Entspannung +Gesundheit & Schönheit > Körperpflege > Massage & Entspannung > Augenkissen Gesundheit & Schönheit > Körperpflege > Massage & Entspannung > Massagegeräte +Gesundheit & Schönheit > Körperpflege > Massage & Entspannung > Massagestein-Wärmer +Gesundheit & Schönheit > Körperpflege > Massage & Entspannung > Massagesteine Gesundheit & Schönheit > Körperpflege > Massage & Entspannung > Massagestühle Gesundheit & Schönheit > Körperpflege > Massage & Entspannung > Massagetische Gesundheit & Schönheit > Körperpflege > Massage & Entspannung > Massageöle +Gesundheit & Schönheit > Körperpflege > Massage & Entspannung > Rückenkratzer Gesundheit & Schönheit > Körperpflege > Mundpflege +Gesundheit & Schönheit > Körperpflege > Mundpflege > Aufbissschienen Gesundheit & Schönheit > Körperpflege > Mundpflege > Ersatzdüsen für Mundduschen Gesundheit & Schönheit > Körperpflege > Mundpflege > Gebissreiniger Gesundheit & Schönheit > Körperpflege > Mundpflege > Interdentalreiniger -Gesundheit & Schönheit > Körperpflege > Mundpflege > Mittel gegen Zahnschmerzen Gesundheit & Schönheit > Körperpflege > Mundpflege > Mundduschen -Gesundheit & Schönheit > Körperpflege > Mundpflege > Mundschutz Gesundheit & Schönheit > Körperpflege > Mundpflege > Mundspray Gesundheit & Schönheit > Körperpflege > Mundpflege > Mundwasser +Gesundheit & Schönheit > Körperpflege > Mundpflege > Reparatursets für Zahnprothesen +Gesundheit & Schönheit > Körperpflege > Mundpflege > Spangen-, Gebiss- & Aufbissschienendosen Gesundheit & Schönheit > Körperpflege > Mundpflege > Zahnaufhellung Gesundheit & Schönheit > Körperpflege > Mundpflege > Zahnbürsten Gesundheit & Schönheit > Körperpflege > Mundpflege > Zahnbürstenzubehör @@ -1786,27 +1406,32 @@ Gesundheit & Schönheit > Körperpflege > Ohrenpflege > Ohrenstöpsel Gesundheit & Schönheit > Körperpflege > Ohrenpflege > Ohrentrockner Gesundheit & Schönheit > Körperpflege > Ohrenpflege > Ohrentropfen Gesundheit & Schönheit > Körperpflege > Ohrenpflege > Ohrkerzen +Gesundheit & Schönheit > Körperpflege > Ohrenpflege > Ohrlöffel Gesundheit & Schönheit > Körperpflege > Ohrenpflege > Ohrspritzen Gesundheit & Schönheit > Körperpflege > Ohrenpflege > Ohrstöpselspender +Gesundheit & Schönheit > Körperpflege > Pinzetten Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Alaunstifte +Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Elektrorasierer Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Haar- & Bartschneider +Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Haaraufheller Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Haarentfernung Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Haarentfernung > Elektrolysegeräte Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Haarentfernung > Enthaarungsmittel +Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Haarentfernung > Enthaarungswachs-Wärmer Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Haarentfernung > Epilatoren Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Haarentfernung > Laserhaarentfernung -Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Haarentfernung > Waxing-Kits -Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Rasierapparate +Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Haarentfernung > Waxing-Sets & Zubehör Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Rasiercreme Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Rasierer & Rasierklingen Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Rasierpinsel +Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Rasierschalen Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Rasiersets Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Rasierwasser Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Zubehör für Haarschneidegeräte & Trimmer Gesundheit & Schönheit > Körperpflege > Rasieren & Trimmen > Zubehör für elektrische Rasierer -Gesundheit & Schönheit > Körperpflege > Rückenpflege -Gesundheit & Schönheit > Körperpflege > Rückenpflege > Stützkissen für Rücken- & Lendenbereich +Gesundheit & Schönheit > Körperpflege > Rückengesundheit +Gesundheit & Schönheit > Körperpflege > Rückengesundheit > Stützkissen für Rücken- & Lendenbereich Gesundheit & Schönheit > Körperpflege > Schlafhilfen Gesundheit & Schönheit > Körperpflege > Schlafhilfen > Hilfsmittel gegen Schnarchen und Schlaf-Apnoe Gesundheit & Schönheit > Körperpflege > Schlafhilfen > Reisekissen @@ -1814,12 +1439,14 @@ Gesundheit & Schönheit > Körperpflege > Schlafhilfen > Schlafmasken Gesundheit & Schönheit > Körperpflege > Schlafhilfen > Soundmaschinen Gesundheit & Schönheit > Körperpflege > Sonnenbänke Gesundheit & Schönheit > Körperpflege > Tanningzelt -Gesundheit & Schönheit > Körperpflege > Warzenentferner Gesundheit & Schönheit > Körperpflege > Wattebällchen Gesundheit & Schönheit > Körperpflege > Wattestäbchen Gesundheit & Schönheit > Schmuckreinigung & -pflege -Gesundheit & Schönheit > Schmuckreinigung & -pflege > Schmuckreiniger +Gesundheit & Schönheit > Schmuckreinigung & -pflege > Dampfstrahlreiniger für Schmuck +Gesundheit & Schönheit > Schmuckreinigung & -pflege > Hilfsmittel zur Schmuckreinigung +Gesundheit & Schönheit > Schmuckreinigung & -pflege > Lösungen und Poliermittel zur Schmuckreinigung Gesundheit & Schönheit > Schmuckreinigung & -pflege > Schmuckständer & -kästen +Gesundheit & Schönheit > Schmuckreinigung & -pflege > Uhrreparatursätze Heim & Garten Heim & Garten > Badzubehör Heim & Garten > Badzubehör > Badematten & Badteppiche @@ -1828,74 +1455,71 @@ Heim & Garten > Badzubehör > Badewannenkissen Heim & Garten > Badzubehör > Badezimmer-Zubehörsets Heim & Garten > Badzubehör > Badzubehörhalterungen Heim & Garten > Badzubehör > Duschvorhangringe +Heim & Garten > Badzubehör > Duschvorhangstangen Heim & Garten > Badzubehör > Duschvorhänge Heim & Garten > Badzubehör > Garderobenhaken +Heim & Garten > Badzubehör > Haltegriffe Heim & Garten > Badzubehör > Handtuchhalter Heim & Garten > Badzubehör > Händetrockner Heim & Garten > Badzubehör > Kosmetiktuchhalter Heim & Garten > Badzubehör > Medizinschränke Heim & Garten > Badzubehör > Seifen- & Lotionsspender Heim & Garten > Badzubehör > Seifenablagen -Heim & Garten > Badzubehör > Toilettenbürsten +Heim & Garten > Badzubehör > Toilettenbürsten & -halter Heim & Garten > Badzubehör > Toilettenbürstenköpfe Heim & Garten > Badzubehör > Toilettenpapierhalter Heim & Garten > Badzubehör > Zahnbürstenhalter Heim & Garten > Badzubehör > Zubehör für Händetrockner Heim & Garten > Beleuchtung -Heim & Garten > Beleuchtung > Außenbeleuchtung -Heim & Garten > Beleuchtung > Außenbeleuchtung > Gartenlaternen & -fackeln -Heim & Garten > Beleuchtung > Außenbeleuchtung > Gartenstrahler -Heim & Garten > Beleuchtung > Außenbeleuchtung > Terrassenbeleuchtung -Heim & Garten > Beleuchtung > Außenbeleuchtung > Wegbeleuchtung Heim & Garten > Beleuchtung > Bilderbeleuchtung -Heim & Garten > Beleuchtung > Flutlichter +Heim & Garten > Beleuchtung > Bodeneinbauleuchten +Heim & Garten > Beleuchtung > Flutlichter & Punktstrahler Heim & Garten > Beleuchtung > Lampen -Heim & Garten > Beleuchtung > Lampen > Standleuchten -Heim & Garten > Beleuchtung > Lampen > Tischlampen Heim & Garten > Beleuchtung > Leuchten Heim & Garten > Beleuchtung > Leuchten > Deckenleuchten Heim & Garten > Beleuchtung > Leuchten > Kronleuchter Heim & Garten > Beleuchtung > Leuchten > Unterbauleuchten Heim & Garten > Beleuchtung > Leuchten > Wandleuchten, Wandbeleuchtung -Heim & Garten > Beleuchtung > Leuchten > Wandleuchten, Wandbeleuchtung > Wandleuchten Heim & Garten > Beleuchtung > Leuchtmittel Heim & Garten > Beleuchtung > Leuchtmittel > Glühlampen Heim & Garten > Beleuchtung > Leuchtmittel > Kompaktleuchtstofflampen Heim & Garten > Beleuchtung > Leuchtmittel > LED-Leuchtmittel Heim & Garten > Beleuchtung > Leuchtmittel > Leuchtstoffröhren -Heim & Garten > Beleuchtung > Lichtschienen -Heim & Garten > Beleuchtung > Lichtschienen > Leuchten für Lichtschienensysteme -Heim & Garten > Beleuchtung > Lichtschienen > Schienen für Lichtschienensysteme -Heim & Garten > Beleuchtung > Lichtschienen > Zubehör für Lichtschienensysteme +Heim & Garten > Beleuchtung > Lichtschienensysteme +Heim & Garten > Beleuchtung > Lichtschienensysteme > Leuchten für Lichtschienensysteme +Heim & Garten > Beleuchtung > Lichtschienensysteme > Schienen für Lichtschienensysteme +Heim & Garten > Beleuchtung > Lichtschienensysteme > Zubehör für Lichtschienensysteme Heim & Garten > Beleuchtung > Lichtschläuche & Lichterketten -Heim & Garten > Beleuchtung > Nachtlichter +Heim & Garten > Beleuchtung > Nachtlichter & indirekte Beleuchtung Heim & Garten > Beleuchtung > Notbeleuchtung +Heim & Garten > Beleuchtung > Schwimmende Lichter +Heim & Garten > Beleuchtung > Tiki-Fackeln & Öllampen +Heim & Garten > Beleuchtung > Wegbeleuchtung Heim & Garten > Beleuchtungszubehör Heim & Garten > Beleuchtungszubehör > Beleuchtungszeitschaltuhren +Heim & Garten > Beleuchtungszubehör > Brennstoff für Öllampen Heim & Garten > Beleuchtungszubehör > Lampenschirme Heim & Garten > Beleuchtungszubehör > Laternenhalterungen Heim & Garten > Beleuchtungszubehör > Laternensockel Heim & Garten > Bett- und Haushaltswäsche Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche +Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Baldachine & Betthimmel Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Bettbezüge -Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Bettdecken Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Bettlaken Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Bettvolants Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Decken -Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Decken > Heizdecken -Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Decken > Überwürfe -Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Kissen- & Zierkissenbezüge +Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Kissenbezüge Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Kopfkissen -Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Kopfkissen > Seitenschläferkissen Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Matratzenschoner Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Matratzenschoner > Matratzenauflagen Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Matratzenschoner > Matratzenbezüge Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Schlafunterlagen -Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Steppdecken +Heim & Garten > Bett- und Haushaltswäsche > Bettwäsche > Steppdecken & Quilts Heim & Garten > Bett- und Haushaltswäsche > Handtücher Heim & Garten > Bett- und Haushaltswäsche > Handtücher > Badhandtücher & Waschlappen Heim & Garten > Bett- und Haushaltswäsche > Handtücher > Geschirrtücher Heim & Garten > Bett- und Haushaltswäsche > Handtücher > Strandtücher +Heim & Garten > Bett- und Haushaltswäsche > Küchentuchsets Heim & Garten > Bett- und Haushaltswäsche > Tischwäsche Heim & Garten > Bett- und Haushaltswäsche > Tischwäsche > Stoffservietten Heim & Garten > Bett- und Haushaltswäsche > Tischwäsche > Tischläufer @@ -1903,52 +1527,47 @@ Heim & Garten > Bett- und Haushaltswäsche > Tischwäsche > Tischsets Heim & Garten > Bett- und Haushaltswäsche > Tischwäsche > Tischtücher Heim & Garten > Bett- und Haushaltswäsche > Tischwäsche > Tischvorhänge Heim & Garten > Bett- und Haushaltswäsche > Tischwäsche > Zierdecken -Heim & Garten > Bett- und Haushaltswäsche > Tischwäschezubehör -Heim & Garten > Bett- und Haushaltswäsche > Tischwäschezubehör > Klemmen & Gewichte für Tischdecken Heim & Garten > Dekoration Heim & Garten > Dekoration > Bilderrahmen -Heim & Garten > Dekoration > Bilderrahmen > Digitale Bilderrahmen -Heim & Garten > Dekoration > Bilderrahmen > Posterrahmen Heim & Garten > Dekoration > Briefkasten-Zubehör -Heim & Garten > Dekoration > Briefkasten-Zubehör > Briefkasten-Befestigungsbügel Heim & Garten > Dekoration > Briefkasten-Zubehör > Briefkasten-Standanlagen Heim & Garten > Dekoration > Briefkasten-Zubehör > Briefkastenanlagen -Heim & Garten > Dekoration > Briefkasten-Zubehör > Briefkastenaufsätze Heim & Garten > Dekoration > Briefkasten-Zubehör > Briefkastenfahnen +Heim & Garten > Dekoration > Briefkasten-Zubehör > Briefkastengehäuse Heim & Garten > Dekoration > Briefkasten-Zubehör > Briefkastentüren Heim & Garten > Dekoration > Briefkästen Heim & Garten > Dekoration > Briefschlitze Heim & Garten > Dekoration > Brunnen & Teiche -Heim & Garten > Dekoration > Brunnen & Teiche > Brunnen -Heim & Garten > Dekoration > Brunnen & Teiche > Brunnen > Außenbrunnen -Heim & Garten > Dekoration > Brunnen & Teiche > Brunnen > Zimmerbrunnen +Heim & Garten > Dekoration > Brunnen & Teiche > Brunnen & Wasserfälle Heim & Garten > Dekoration > Brunnen & Teiche > Brunnen- & Teichzubehör Heim & Garten > Dekoration > Brunnen & Teiche > Teiche Heim & Garten > Dekoration > Buchstützen +Heim & Garten > Dekoration > Deko-Aufkleber Heim & Garten > Dekoration > Dekorative Flaschen Heim & Garten > Dekoration > Dekorative Gefäße -Heim & Garten > Dekoration > Dekorative Klingeln Heim & Garten > Dekoration > Dekorteller -Heim & Garten > Dekoration > Dufttarts Heim & Garten > Dekoration > Ecosphere-Kugeln Heim & Garten > Dekoration > Fensterdrapierung Heim & Garten > Dekoration > Fensterdrapierung > Buntglasscheiben Heim & Garten > Dekoration > Fensterdrapierung > Fensterfolie Heim & Garten > Dekoration > Fensterdrapierung > Fliegengitter Heim & Garten > Dekoration > Fensterdrapierung > Jalousien & Rollos -Heim & Garten > Dekoration > Fensterdrapierung > Volants +Heim & Garten > Dekoration > Fensterdrapierung > Querbehänge Heim & Garten > Dekoration > Fensterdrapierung > Vorhänge & Gardinen Heim & Garten > Dekoration > Fensterschmuckmagnete Heim & Garten > Dekoration > Festtags-Dekoartikel Heim & Garten > Dekoration > Festtags-Dekoartikel > Adventskalender Heim & Garten > Dekoration > Festtags-Dekoartikel > Haken für Weihnachtssocken Heim & Garten > Dekoration > Festtags-Dekoartikel > Krippen +Heim & Garten > Dekoration > Festtags-Dekoartikel > Modellbaudörfer & -zubehör mit saisonalem Bezug +Heim & Garten > Dekoration > Festtags-Dekoartikel > Ostereier-Färbe-Sets +Heim & Garten > Dekoration > Festtags-Dekoartikel > Traditionelle Japanische Puppen Heim & Garten > Dekoration > Festtags-Dekoartikel > Weihnachtsbaumdecken Heim & Garten > Dekoration > Festtags-Dekoartikel > Weihnachtsbaumschmuck Heim & Garten > Dekoration > Festtags-Dekoartikel > Weihnachtsbaumständer -Heim & Garten > Dekoration > Festtags-Dekoartikel > Weihnachtsschmuck-Aufbewahrung +Heim & Garten > Dekoration > Festtags-Dekoartikel > Weihnachtsschmuck-Aufhänger Heim & Garten > Dekoration > Festtags-Dekoartikel > Weihnachtsschmuck-Displays -Heim & Garten > Dekoration > Festtags-Dekoartikel > Weihnachtssocken +Heim & Garten > Dekoration > Festtags-Dekoartikel > Weihnachtsstrümpfe Heim & Garten > Dekoration > Figuren zur Dekoration Heim & Garten > Dekoration > Flaggen & Windsäcke Heim & Garten > Dekoration > Flammenlose Kerzen @@ -1959,38 +1578,40 @@ Heim & Garten > Dekoration > Futterspender > Vogelfutterspender Heim & Garten > Dekoration > Fußmatten Heim & Garten > Dekoration > Garderoben Heim & Garten > Dekoration > Garten- & Trittsteine -Heim & Garten > Dekoration > Gartenschmuck -Heim & Garten > Dekoration > Gartenschmuck > Gartenkugeln -Heim & Garten > Dekoration > Gartenskulpturen +Heim & Garten > Dekoration > Gartendeko Heim & Garten > Dekoration > Glasfensterbilder Heim & Garten > Dekoration > Globen Heim & Garten > Dekoration > Hausnummern & Buchstaben Heim & Garten > Dekoration > Hausnummernschilder -Heim & Garten > Dekoration > Kerzen -Heim & Garten > Dekoration > Kerzen > Chanukkah-Kerzen -Heim & Garten > Dekoration > Kerzen > Hochzeitskerzen -Heim & Garten > Dekoration > Kerzenständer -Heim & Garten > Dekoration > Kerzenständer > Chanukkia +Heim & Garten > Dekoration > Kartonschablonen +Heim & Garten > Dekoration > Kindermesslatten Heim & Garten > Dekoration > Kreuzblumen Heim & Garten > Dekoration > Kränze & Girlanden +Heim & Garten > Dekoration > Kunst +Heim & Garten > Dekoration > Kunst > Figuren, Skulpturen & Statuen +Heim & Garten > Dekoration > Kunst > Poster & Bildende Kunst +Heim & Garten > Dekoration > Kunst > Wandteppiche Heim & Garten > Dekoration > Körbe Heim & Garten > Dekoration > Kühlschrankmagnete Heim & Garten > Dekoration > Künstliche Pflanzen -Heim & Garten > Dekoration > Künstliche Pflanzen > Kunstfloristik -Heim & Garten > Dekoration > Künstliche Pflanzen > Künstliche Blumen -Heim & Garten > Dekoration > Künstliche Pflanzen > Künstliche Bäume -Heim & Garten > Dekoration > Künstliche Pflanzen > Künstliche Formschnittpflanzen Heim & Garten > Dekoration > Lebensmittel-Attrappen Heim & Garten > Dekoration > Niederschlags-Messgeräte Heim & Garten > Dekoration > Quadratische Sitzkissen +Heim & Garten > Dekoration > Raumduft-Zubehör +Heim & Garten > Dekoration > Raumduft-Zubehör > Kerzenlöscher +Heim & Garten > Dekoration > Raumduft-Zubehör > Kerzenständer +Heim & Garten > Dekoration > Raumduft-Zubehör > Räuchermittelhalter +Heim & Garten > Dekoration > Raumduft-Zubehör > Wachs- & Ölwärmer Heim & Garten > Dekoration > Raumdüfte +Heim & Garten > Dekoration > Raumdüfte > Duftwachs Heim & Garten > Dekoration > Raumdüfte > Duftöle +Heim & Garten > Dekoration > Raumdüfte > Kerzen Heim & Garten > Dekoration > Raumdüfte > Lufterfrischer Heim & Garten > Dekoration > Raumdüfte > Potpourri Heim & Garten > Dekoration > Raumdüfte > Räuchermittel -Heim & Garten > Dekoration > Raumdüfte > Räuchermittelhalter Heim & Garten > Dekoration > Regenketten Heim & Garten > Dekoration > Rückenstützkissen +Heim & Garten > Dekoration > Sanduhren Heim & Garten > Dekoration > Schalen Heim & Garten > Dekoration > Schaukästen Heim & Garten > Dekoration > Schneekugeln @@ -2003,35 +1624,36 @@ Heim & Garten > Dekoration > Spaßschilder Heim & Garten > Dekoration > Spiegel Heim & Garten > Dekoration > Spieluhren Heim & Garten > Dekoration > Tabletts -Heim & Garten > Dekoration > Tafeln +Heim & Garten > Dekoration > Tapeten Heim & Garten > Dekoration > Teppiche -Heim & Garten > Dekoration > Teppiche > Heizteppiche -Heim & Garten > Dekoration > Tiki-Fackeln & Öllampen Heim & Garten > Dekoration > Traumfänger Heim & Garten > Dekoration > Trockenblumen Heim & Garten > Dekoration > Truhen +Heim & Garten > Dekoration > Uhrbauteile Heim & Garten > Dekoration > Uhren Heim & Garten > Dekoration > Uhren > Standuhren Heim & Garten > Dekoration > Uhren > Tisch- und Regaluhren Heim & Garten > Dekoration > Uhren > Wanduhren -Heim & Garten > Dekoration > Uhren > Wanduhren > Kuckucksuhren Heim & Garten > Dekoration > Uhren > Wecker -Heim & Garten > Dekoration > Uhren > Wecker > Radiowecker -Heim & Garten > Dekoration > Uhren > Wecker > Reisewecker Heim & Garten > Dekoration > Vasen -Heim & Garten > Dekoration > Vogelhäuschen +Heim & Garten > Dekoration > Vasenfüller & Streudeko +Heim & Garten > Dekoration > Vogel- und Tierhäuschen +Heim & Garten > Dekoration > Vogel- und Tierhäuschen > Fledermaushäuschen +Heim & Garten > Dekoration > Vogel- und Tierhäuschen > Schmetterlingshäuschen +Heim & Garten > Dekoration > Vogel- und Tierhäuschen > Vogelhäuschen +Heim & Garten > Dekoration > Vogelhaus-Zubehör Heim & Garten > Dekoration > Vogeltränken -Heim & Garten > Dekoration > Wachs- & Ölwärmer -Heim & Garten > Dekoration > Wandapplikationen -Heim & Garten > Dekoration > Wandregale & Simse Heim & Garten > Dekoration > Wetterfahnen & Dachdekoration Heim & Garten > Dekoration > Windräder Heim & Garten > Dekoration > Windspiele +Heim & Garten > Dekoration > Zierglocken Heim & Garten > Dekoration > Zierkissen -Heim & Garten > Dekoration > Zubehör für Fahnen und Windsäcke -Heim & Garten > Dekoration > Zubehör für Fahnen und Windsäcke > Beleuchtung für Fahnen- und Windsackstangen -Heim & Garten > Dekoration > Zubehör für Fahnen und Windsäcke > Stangen für Fahnen und Windsäcke -Heim & Garten > Dekoration > Zubehör für Vogelhäuschen +Heim & Garten > Dekoration > Ziertafeln +Heim & Garten > Dekoration > Zubehör für Fahnen & Windsäcke +Heim & Garten > Dekoration > Zubehör für Fahnen & Windsäcke > Befestigungsvorrichtungen & -sets für Fahnen- & Windsackstangen +Heim & Garten > Dekoration > Zubehör für Fahnen & Windsäcke > Beleuchtung für Fahnen- & Windsackstangen +Heim & Garten > Dekoration > Zubehör für Fahnen & Windsäcke > Stangen für Fahnen & Windsäcke +Heim & Garten > Dekoration > Zubehör für Futterspender Heim & Garten > Dekoration > Zubehör zur Fensterdekoration Heim & Garten > Dekoration > Zubehör zur Fensterdekoration > Ersatzteile für Vorhänge & Jalousien Heim & Garten > Dekoration > Zubehör zur Fensterdekoration > Gardinen- & Vorhangringe @@ -2039,30 +1661,30 @@ Heim & Garten > Dekoration > Zubehör zur Fensterdekoration > Gardinen- & Vorhan Heim & Garten > Dekoration > Zubehör zur Fensterdekoration > Gardinenhalter & -quasten Heim & Garten > Feuer- & Gasschutz Heim & Garten > Feuer- & Gasschutz > Feuerlöscher -Heim & Garten > Feuer- & Gasschutz > Feuerlöschkästen Heim & Garten > Feuer- & Gasschutz > Feuermelder Heim & Garten > Feuer- & Gasschutz > Feuermelder-Steuerungen Heim & Garten > Feuer- & Gasschutz > Hitzemelder -Heim & Garten > Feuer- & Gasschutz > Kohlenmonoxiddetektoren -Heim & Garten > Feuer- & Gasschutz > Radondetektoren -Heim & Garten > Feuer- & Gasschutz > Rauchmelder +Heim & Garten > Feuer- & Gasschutz > Kästen & Halterungen für Feuerlöscher +Heim & Garten > Feuer- & Gasschutz > Rauch- & Kohlenmonoxidmelder Heim & Garten > Feuer- & Gasschutz > Sprinkleranlagen +Heim & Garten > Feuer- & Gasschutz > Wassermelder Heim & Garten > Haushaltsbedarf Heim & Garten > Haushaltsbedarf > Abfallbehälter +Heim & Garten > Haushaltsbedarf > Abfallbehälter > Müllcontainer Heim & Garten > Haushaltsbedarf > Abfallbehälter > Mülltonnen & Abfalleimer Heim & Garten > Haushaltsbedarf > Abfallbehälter > Recycling-Behälter Heim & Garten > Haushaltsbedarf > Abfallbehälter > Sondermüllbehälter Heim & Garten > Haushaltsbedarf > Abfallbehälterzubehör -Heim & Garten > Haushaltsbedarf > Abfallbehälterzubehör > Abfallbehälter-Auszugsrahmen +Heim & Garten > Haushaltsbedarf > Abfallbehälterzubehör > Abfallbehälter-Verkleidungen Heim & Garten > Haushaltsbedarf > Abfallbehälterzubehör > Abfallbehälterdeckel Heim & Garten > Haushaltsbedarf > Abfallbehälterzubehör > Abfallbehälterrollen Heim & Garten > Haushaltsbedarf > Abfallbehälterzubehör > Abfallbehälterwagen +Heim & Garten > Haushaltsbedarf > Abfallbehälterzubehör > Beschriftungen & Etiketten für Abfallbehälter Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme -Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Aufbewahrung & Ordnungssysteme für Geschenkpapier Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Aufbewahrungsbehälter Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Aufbewahrungsbeutel Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Aufbewahrungshaken & Regale -Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Aufbewahrungshaken & Regale > Kleiderständer +Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Aufbewahrungshaken & Regale > Bügelbrettaufhänger und -ablagen Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Aufbewahrungshaken & Regale > Mehrzweckhaken Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Aufbewahrungshaken & Regale > Schirmständer Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Fotoaufbewahrung @@ -2070,24 +1692,24 @@ Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Fotoaufbewahr Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Fotoaufbewahrung > Fotoboxen Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Haushalts-Ordnungshelfer Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleider- & Wandschrankaufbewahrung +Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleider- & Wandschrankaufbewahrung > Herrendiener Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleider- & Wandschrankaufbewahrung > Hutschachteln Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleider- & Wandschrankaufbewahrung > Kleiderbügel +Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleider- & Wandschrankaufbewahrung > Kleiderständer +Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleider- & Wandschrankaufbewahrung > Ladestationen Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleider- & Wandschrankaufbewahrung > Schuhregale & -schränke -Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleinaufbewahrung / sonstige Aufbewahrung -Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleinaufbewahrung / sonstige Aufbewahrung > Herrendiener -Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleinaufbewahrung / sonstige Aufbewahrung > Kommoden-Organizer -Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Kleinaufbewahrung / sonstige Aufbewahrung > Ladestationen -Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Pillendosen +Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Schubladeneinsätze Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Schubladensysteme Heim & Garten > Haushaltsbedarf > Aufbewahrung & Ordnungssysteme > Tischbesteckkommoden Heim & Garten > Haushaltsbedarf > Auskleidung für Schubladen & Regale +Heim & Garten > Haushaltsbedarf > Fußbodenschutzfolien & -läufer +Heim & Garten > Haushaltsbedarf > Garagenmatten Heim & Garten > Haushaltsbedarf > Haushaltsthermometer Heim & Garten > Haushaltsbedarf > Hygienepapiere Heim & Garten > Haushaltsbedarf > Hygienepapiere > Küchenrollen & Papierhandtücher Heim & Garten > Haushaltsbedarf > Hygienepapiere > Papierservietten Heim & Garten > Haushaltsbedarf > Hygienepapiere > Papiertaschentücher Heim & Garten > Haushaltsbedarf > Hygienepapiere > Toilettenpapier -Heim & Garten > Haushaltsbedarf > Luftentfeuchter Heim & Garten > Haushaltsbedarf > Möbelgleiter Heim & Garten > Haushaltsbedarf > Müllbeutel Heim & Garten > Haushaltsbedarf > Müllpressezubehör @@ -2095,22 +1717,23 @@ Heim & Garten > Haushaltsbedarf > Reinigungsutensilien Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Abzieher Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Besen Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Besen- & Bodenwischerstiele +Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Besenköpfe +Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Bodenwischeraufsätze Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Eimer Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Ersatz-Wischmops Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Gewebe- & Polsterschutz Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Allzweckreiniger -Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Backofenreiniger +Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Backofen- & Grillreiniger +Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Bodenreiniger Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Edelstahlreiniger & -polituren +Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Entkalkungsmittel Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Geschirrspülmittel & -seifen Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Glas- & Oberflächenreiniger Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Haushaltsdesinfektion Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Klarspüler -Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Lederpflege- & Färbemittel Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Möbelreiniger & -Politur -Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Reiniger für Hartholzböden Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Spülmaschinenreiniger -Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Steinreiniger Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Teppichreiniger Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Textil- & Polsterreiniger Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Tiergeruchs- & Fleckenentferner @@ -2119,8 +1742,8 @@ Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Wan Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Haushaltsreiniger > Waschmaschinenreiniger Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Kehrschaufeln Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Reinigungshandschuhe +Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Reinigungstücher Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Scheuerbürsten -Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Scheuerbürsten > Bürsten für Babyflaschen Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Schwämme & Topfreiniger Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Staubwedel & -Tücher Heim & Garten > Haushaltsbedarf > Reinigungsutensilien > Staubwedel-Ersatzköpfe @@ -2145,18 +1768,22 @@ Heim & Garten > Haushaltsbedarf > Schädlingsbekämpfung > Insektenschutz Heim & Garten > Haushaltsbedarf > Schädlingsbekämpfung > Insektenschutz > Mittel gegen Haushaltsinsekten Heim & Garten > Haushaltsbedarf > Schädlingsbekämpfung > Insektenschutz > Tierabwehr Heim & Garten > Haushaltsbedarf > Schädlingsbekämpfung > Schädlingsbekämpfungsmittel +Heim & Garten > Haushaltsbedarf > Stufenteppiche Heim & Garten > Haushaltsbedarf > Teppichunterlagen +Heim & Garten > Haushaltsbedarf > Trocknungsmittel Heim & Garten > Haushaltsbedarf > Wäschepflege Heim & Garten > Haushaltsbedarf > Wäschepflege > Bleichmittel Heim & Garten > Haushaltsbedarf > Wäschepflege > Bügelbretter Heim & Garten > Haushaltsbedarf > Wäschepflege > Bügelbrettunterlagen & -bezüge +Heim & Garten > Haushaltsbedarf > Wäschepflege > Bügeleisenhalter +Heim & Garten > Haushaltsbedarf > Wäschepflege > Ersatzteile für Bügeleisen Heim & Garten > Haushaltsbedarf > Wäschepflege > Fleckenentferner für Stoffe Heim & Garten > Haushaltsbedarf > Wäschepflege > Fusselrasierer Heim & Garten > Haushaltsbedarf > Wäschepflege > Fusselrollen Heim & Garten > Haushaltsbedarf > Wäschepflege > Mittel gegen Falten & statische Aufladung Heim & Garten > Haushaltsbedarf > Wäschepflege > Schweißabsorbierungspads Heim & Garten > Haushaltsbedarf > Wäschepflege > Textilerfrischer -Heim & Garten > Haushaltsbedarf > Wäschepflege > Trockenreinigungsbedarf +Heim & Garten > Haushaltsbedarf > Wäschepflege > Trockenreinigungssets Heim & Garten > Haushaltsbedarf > Wäschepflege > Waschbälle Heim & Garten > Haushaltsbedarf > Wäschepflege > Waschpulver Heim & Garten > Haushaltsbedarf > Wäschepflege > Weichspüler & Trocknertücher @@ -2166,39 +1793,36 @@ Heim & Garten > Haushaltsbedarf > Wäschepflege > Wäscheständer Heim & Garten > Haushaltsbedarf > Wäschepflege > Wäschestärke Heim & Garten > Haushaltsbedarf > Wäschepflege > Wäschesäcke & Waschkörbe Heim & Garten > Haushaltsgeräte +Heim & Garten > Haushaltsgeräte > Boden- & Teppichtrockner Heim & Garten > Haushaltsgeräte > Bohner- & Poliermaschinen Heim & Garten > Haushaltsgeräte > Dampf-Tapetenlöser Heim & Garten > Haushaltsgeräte > Futontrockner -Heim & Garten > Haushaltsgeräte > Garagenparksensoren +Heim & Garten > Haushaltsgeräte > Garagentorantrieb Heim & Garten > Haushaltsgeräte > Garagentoröffner -Heim & Garten > Haushaltsgeräte > Garagenöffner -Heim & Garten > Haushaltsgeräte > Heim- & Gebäudeautomatisierung Heim & Garten > Haushaltsgeräte > Heißwasserboiler -Heim & Garten > Haushaltsgeräte > Heißwasserboiler > Tauchsieder Heim & Garten > Haushaltsgeräte > Klimatisierung Heim & Garten > Haushaltsgeräte > Klimatisierung > Fog-Anlagen für den Außenbereich Heim & Garten > Haushaltsgeräte > Klimatisierung > Kanalheizer Heim & Garten > Haushaltsgeräte > Klimatisierung > Klimaanlagen -Heim & Garten > Haushaltsgeräte > Klimatisierung > Kotatsu Heim & Garten > Haushaltsgeräte > Klimatisierung > Luftbefeuchter +Heim & Garten > Haushaltsgeräte > Klimatisierung > Luftentfeuchter Heim & Garten > Haushaltsgeräte > Klimatisierung > Luftreiniger Heim & Garten > Haushaltsgeräte > Klimatisierung > Radiatoren Heim & Garten > Haushaltsgeräte > Klimatisierung > Raumheizgeräte -Heim & Garten > Haushaltsgeräte > Klimatisierung > Raumtrocknungsgeräte Heim & Garten > Haushaltsgeräte > Klimatisierung > Terrassenstrahler Heim & Garten > Haushaltsgeräte > Klimatisierung > Ventilatoren Heim & Garten > Haushaltsgeräte > Klimatisierung > Ventilatoren > Deckenventilatoren Heim & Garten > Haushaltsgeräte > Klimatisierung > Ventilatoren > Handventilatoren Heim & Garten > Haushaltsgeräte > Klimatisierung > Ventilatoren > Lüftungsventilatoren Heim & Garten > Haushaltsgeräte > Klimatisierung > Ventilatoren > Tisch- & Standventilatoren +Heim & Garten > Haushaltsgeräte > Klimatisierung > Ventilatoren > Wandventilatoren Heim & Garten > Haushaltsgeräte > Klimatisierung > Verdunstungskühler Heim & Garten > Haushaltsgeräte > Klimatisierung > Öfen & Kessel -Heim & Garten > Haushaltsgeräte > Nähmaschinen -Heim & Garten > Haushaltsgeräte > Nähmaschinen > Overlock-Nähmaschinen Heim & Garten > Haushaltsgeräte > Staubsauger Heim & Garten > Haushaltsgeräte > Teppich- & Dampfreinigungsgeräte +Heim & Garten > Haushaltsgeräte > Ultraschallreiniger Heim & Garten > Haushaltsgeräte > Waschen & Trocknen -Heim & Garten > Haushaltsgeräte > Waschen & Trocknen > Bügeleisen +Heim & Garten > Haushaltsgeräte > Waschen & Trocknen > Bügeleisen & -systeme Heim & Garten > Haushaltsgeräte > Waschen & Trocknen > Dampfglätter für Bekleidung Heim & Garten > Haushaltsgeräte > Waschen & Trocknen > Dampfpressen Heim & Garten > Haushaltsgeräte > Waschen & Trocknen > Waschmaschinen @@ -2207,13 +1831,13 @@ Heim & Garten > Haushaltsgeräte > Waschen & Trocknen > Wäschetrockner Heim & Garten > Haushaltsgeräte-Zubehör Heim & Garten > Haushaltsgeräte-Zubehör > Boiler-Zubehör Heim & Garten > Haushaltsgeräte-Zubehör > Boiler-Zubehör > Abgasrohre +Heim & Garten > Haushaltsgeräte-Zubehör > Boiler-Zubehör > Ausgleichsgefäß für Warmwasserbereiter Heim & Garten > Haushaltsgeräte-Zubehör > Boiler-Zubehör > Boiler Heim & Garten > Haushaltsgeräte-Zubehör > Boiler-Zubehör > Boilerwannen Heim & Garten > Haushaltsgeräte-Zubehör > Boiler-Zubehör > Heizelemente Heim & Garten > Haushaltsgeräte-Zubehör > Boiler-Zubehör > Heizungslüftung Heim & Garten > Haushaltsgeräte-Zubehör > Boiler-Zubehör > Opferanoden Heim & Garten > Haushaltsgeräte-Zubehör > Entfeuchterzubehör -Heim & Garten > Haushaltsgeräte-Zubehör > Entfeuchterzubehör > Entfeuchterfilter Heim & Garten > Haushaltsgeräte-Zubehör > Heizkessel- & Boilerzubehör Heim & Garten > Haushaltsgeräte-Zubehör > Heizkörperzubehör Heim & Garten > Haushaltsgeräte-Zubehör > Heizkörperzubehör > Heizkörperreflexionsfolie @@ -2226,63 +1850,51 @@ Heim & Garten > Haushaltsgeräte-Zubehör > Luftbefeuchter-Zubehör Heim & Garten > Haushaltsgeräte-Zubehör > Luftbefeuchter-Zubehör > Luftbefeuchterfilter Heim & Garten > Haushaltsgeräte-Zubehör > Luftreinigerzubehör Heim & Garten > Haushaltsgeräte-Zubehör > Luftreinigerzubehör > Luftreinigerfilter -Heim & Garten > Haushaltsgeräte-Zubehör > Nähmaschinenzubehör -Heim & Garten > Haushaltsgeräte-Zubehör > Nähmaschinenzubehör > Nähmaschinenfüße -Heim & Garten > Haushaltsgeräte-Zubehör > Nähmaschinenzubehör > Nähmaschinengehäuse & -abdeckungen -Heim & Garten > Haushaltsgeräte-Zubehör > Nähmaschinenzubehör > Nähmaschinennadeln -Heim & Garten > Haushaltsgeräte-Zubehör > Nähmaschinenzubehör > Spulen & Spulenhalter Heim & Garten > Haushaltsgeräte-Zubehör > Staubsaugerzubehör -Heim & Garten > Haushaltsgeräte-Zubehör > Staubsaugerzubehör > Staubsauger-Antriebsriemen -Heim & Garten > Haushaltsgeräte-Zubehör > Staubsaugerzubehör > Staubsaugeraufsätze -Heim & Garten > Haushaltsgeräte-Zubehör > Staubsaugerzubehör > Staubsaugerbeutel -Heim & Garten > Haushaltsgeräte-Zubehör > Staubsaugerzubehör > Staubsaugerfilter -Heim & Garten > Haushaltsgeräte-Zubehör > Staubsaugerzubehör > Staubsaugerschläuche -Heim & Garten > Haushaltsgeräte-Zubehör > Teppich- und Dampfreinigerzubehör +Heim & Garten > Haushaltsgeräte-Zubehör > Teppich- & Dampfreinigerzubehör Heim & Garten > Haushaltsgeräte-Zubehör > Ventilatorenzubehör Heim & Garten > Haushaltsgeräte-Zubehör > Wasch-Zubehör Heim & Garten > Haushaltsgeräte-Zubehör > Wasch-Zubehör > Bügeleisenzubehör -Heim & Garten > Haushaltsgeräte-Zubehör > Wasch-Zubehör > Waschmaschinenzubehör -Heim & Garten > Haushaltsgeräte-Zubehör > Wasch-Zubehör > Waschmaschinenzubehör > Sockel für Waschmaschinen & Trockner -Heim & Garten > Haushaltsgeräte-Zubehör > Wasch-Zubehör > Waschmaschinenzubehör > Waschmaschinenschläuche -Heim & Garten > Haushaltsgeräte-Zubehör > Wasch-Zubehör > Waschmaschinenzubehör > Waschmaschinenventile Heim & Garten > Haushaltsgeräte-Zubehör > Wasch-Zubehör > Zubehör für Dampfmaschinen Heim & Garten > Haushaltsgeräte-Zubehör > Wasch-Zubehör > Zubehör für Dampfpressen -Heim & Garten > Haushaltsgeräte-Zubehör > Wasch-Zubehör > Zubehör für Wäschetrockner +Heim & Garten > Haushaltsgeräte-Zubehör > Wasch-Zubehör > Zubehör für Waschmaschinen und Wäschetrockner Heim & Garten > Haussicherheit Heim & Garten > Haussicherheit > Bewegungsmelder Heim & Garten > Haussicherheit > Hausalarmsysteme +Heim & Garten > Haussicherheit > Safe-Zubehör Heim & Garten > Haussicherheit > Safes & Tresore Heim & Garten > Haussicherheit > Sensoren für Sicherheitssysteme Heim & Garten > Haussicherheit > Sicherheitsleuchten -Heim & Garten > Haussicherheit > Tracking-Geräte +Heim & Garten > Haussicherheit > Sicherheitsspiegel Heim & Garten > Haussicherheit > Überwachungskamera-Attrappen Heim & Garten > Haussicherheit > Überwachungsmonitore & -rekorder Heim & Garten > Holzöfen Heim & Garten > Kamine -Heim & Garten > Kamine > Außenkamine -Heim & Garten > Kamine > Innenkamine Heim & Garten > Küche & Esszimmer Heim & Garten > Küche & Esszimmer > Bar-Utensilien Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Absinth-Fontänen Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Bierzapfhähne +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Cocktail- & Barzubehörsets +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Cocktailshaker & Zubehör +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Cocktailshaker & Zubehör > Bar-Eispickel +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Cocktailshaker & Zubehör > Barsiebe +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Cocktailshaker & Zubehör > Cocktailshaker +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Cocktailshaker & Zubehör > Cocktailstößel +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Cocktailshaker & Zubehör > Flaschenöffner Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Dekanter -Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Eiskübel Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Flaschenstöpsel & -verschlüsse +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Flaschenverschlüsse Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Folienschneider -Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Getränkeshaker & Zubehör -Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Getränkeshaker & Zubehör > Bar-Eispickel -Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Getränkeshaker & Zubehör > Cocktailshaker -Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Getränkeshaker & Zubehör > Flaschenöffner -Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Getränkeshaker & Zubehör > Getränkezubehörsets +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Getränkewannen & -kühler Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Glasuntersetzer & Bierdeckel Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Korkenzieher +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Kühlsteine & -Sticks für Getränke Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Untersetzerhalter Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Weindekantierer +Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Weinflaschenhalter Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Weinglasanhänger -Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Weinkübel & -kühler -Heim & Garten > Küche & Esszimmer > Bar-Utensilien > Whisky-Steine Heim & Garten > Küche & Esszimmer > Essens- & Getränkebehälter -Heim & Garten > Küche & Esszimmer > Essens- & Getränkebehälter > Brotdosen & Tragetaschen +Heim & Garten > Küche & Esszimmer > Essens- & Getränkebehälter > Brotdosen & -taschen Heim & Garten > Küche & Esszimmer > Essens- & Getränkebehälter > Feldflaschen Heim & Garten > Küche & Esszimmer > Essens- & Getränkebehälter > Flachmänner Heim & Garten > Küche & Esszimmer > Essens- & Getränkebehälter > Getränkedeckel @@ -2298,6 +1910,7 @@ Heim & Garten > Küche & Esszimmer > Essens- & Getränkebehälter > Wasserflasch Heim & Garten > Küche & Esszimmer > Essens- & Getränkebehälter > Weinflaschentaschen Heim & Garten > Küche & Esszimmer > Essensaufbewahrung Heim & Garten > Küche & Esszimmer > Essensaufbewahrung - Zubehör +Heim & Garten > Küche & Esszimmer > Essensaufbewahrung - Zubehör > Etiketten für Lebensmittel und Getränke Heim & Garten > Küche & Esszimmer > Essensaufbewahrung - Zubehör > Sauerstoffabsorber Heim & Garten > Küche & Esszimmer > Essensaufbewahrung - Zubehör > Spender für Frischhaltefolie Heim & Garten > Küche & Esszimmer > Essensaufbewahrung - Zubehör > Verschlussstreifen & Verschlussclips @@ -2305,7 +1918,7 @@ Heim & Garten > Küche & Esszimmer > Essensaufbewahrung > Brotkästen & -taschen Heim & Garten > Küche & Esszimmer > Essensaufbewahrung > Frischhaltebeutel Heim & Garten > Küche & Esszimmer > Essensaufbewahrung > Honiggläser Heim & Garten > Küche & Esszimmer > Essensaufbewahrung > Kecksdosen & -behälter -Heim & Garten > Küche & Esszimmer > Essensaufbewahrung > Lebensmittelabdeckhauben +Heim & Garten > Küche & Esszimmer > Essensaufbewahrung > Lebensmittel-Abdeckhauben Heim & Garten > Küche & Esszimmer > Essensaufbewahrung > Lebensmittelbehälter Heim & Garten > Küche & Esszimmer > Essensaufbewahrung > Lebensmittelverpackungsmaterial Heim & Garten > Küche & Esszimmer > Essensaufbewahrung > Lebensmittelverpackungsmaterial > Alufolien @@ -2323,15 +1936,13 @@ Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backformen > Br Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backformen > Grillbleche mit Fettpfannen Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backformen > Kuchen- & Quichebackformen Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backformen > Kuchenbackformen -Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backformen > Muffin- & Cupcakebackformen +Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backformen > Muffin- & Gebäckformen Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backformen > Pizzableche Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backformen > Pizzasteine -Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backformen > Spezialbackformen Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backzubehör Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backzubehör > Backgewichte Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backzubehör > Backmatten & -formen Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backzubehör > Brätereinsätze -Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Backzubehör > Papierbackförmchen Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr & Backformen (Kombisets) Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Auflaufformen & Kasserollen @@ -2344,12 +1955,11 @@ Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Sautépfannen Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Schmortöpfe Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Schnellkochtöpfe -Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Schnellkochtöpfe > Elektrische Schnellkochtöpfe Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Stiel- & Bratpfannen Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Stieltöpfe Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Suppentöpfe -Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Tajines -Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Wasserbadtopf +Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Tajines & Tonkochtöpfe +Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Wasserbadtöpfe Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Wasserkessel Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirr > Woks Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirrzubehör @@ -2360,92 +1970,78 @@ Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirrzub Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirrzubehör > Wokzubehör Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirrzubehör > Wokzubehör > Wokbürsten Heim & Garten > Küche & Esszimmer > Kochgeschirr & Backformen > Kochgeschirrzubehör > Wokzubehör > Wokringe +Heim & Garten > Küche & Esszimmer > Küchenblöcke & Pantryküchen Heim & Garten > Küche & Esszimmer > Küchengeräte Heim & Garten > Küche & Esszimmer > Küchengeräte > Abfallzerkleinerer Heim & Garten > Küche & Esszimmer > Küchengeräte > Abzugshauben -Heim & Garten > Küche & Esszimmer > Küchengeräte > Allesschneider -Heim & Garten > Küche & Esszimmer > Küchengeräte > Allesschneider > Aufschnittmaschine +Heim & Garten > Küche & Esszimmer > Küchengeräte > Aufschnittmaschine Heim & Garten > Küche & Esszimmer > Küchengeräte > Außengrills -Heim & Garten > Küche & Esszimmer > Küchengeräte > Außengrills > Gasgrills -Heim & Garten > Küche & Esszimmer > Küchengeräte > Außengrills > Holzkohlegrills Heim & Garten > Küche & Esszimmer > Küchengeräte > Backöfen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Backöfen > Durchlauföfen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Backöfen > Etagenöfen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Backöfen > Wandöfen Heim & Garten > Küche & Esszimmer > Küchengeräte > Brotbackautomaten Heim & Garten > Küche & Esszimmer > Küchengeräte > Campingkocher -Heim & Garten > Küche & Esszimmer > Küchengeräte > Crêpe-Geräte Heim & Garten > Küche & Esszimmer > Küchengeräte > Dörrautomaten -Heim & Garten > Küche & Esszimmer > Küchengeräte > Eis-Shaver +Heim & Garten > Küche & Esszimmer > Küchengeräte > Eis-Crusher & Eis-Shaver Heim & Garten > Küche & Esszimmer > Küchengeräte > Eismaschinen Heim & Garten > Küche & Esszimmer > Küchengeräte > Elektrische Pfannen & Woks Heim & Garten > Küche & Esszimmer > Küchengeräte > Elektrogrills & -bratplatten -Heim & Garten > Küche & Esszimmer > Küchengeräte > Elektrogrills & -bratplatten > Elektrische Grillpfannen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Elektrogrills & -bratplatten > Elektrogrills Heim & Garten > Küche & Esszimmer > Küchengeräte > Entsafter -Heim & Garten > Küche & Esszimmer > Küchengeräte > Entsafter > Handentsafter -Heim & Garten > Küche & Esszimmer > Küchengeräte > Fonduesets +Heim & Garten > Küche & Esszimmer > Küchengeräte > Fonduetöpfe & -Sets Heim & Garten > Küche & Esszimmer > Küchengeräte > Fritteusen Heim & Garten > Küche & Esszimmer > Küchengeräte > Gasgrillplatten Heim & Garten > Küche & Esszimmer > Küchengeräte > Gefrierschränke & -truhen Heim & Garten > Küche & Esszimmer > Küchengeräte > Geschirrspüler Heim & Garten > Küche & Esszimmer > Küchengeräte > Getränkewärmer +Heim & Garten > Küche & Esszimmer > Küchengeräte > Grillöfen & Mini-Backöfen Heim & Garten > Küche & Esszimmer > Küchengeräte > Heißgetränkebereiter Heim & Garten > Küche & Esszimmer > Küchengeräte > Joghurtmaschinen Heim & Garten > Küche & Esszimmer > Küchengeräte > Kaffee- & Espressomaschinen Heim & Garten > Küche & Esszimmer > Küchengeräte > Kaffee- & Espressomaschinen > Espressokannen Heim & Garten > Küche & Esszimmer > Küchengeräte > Kaffee- & Espressomaschinen > Espressomaschinen Heim & Garten > Küche & Esszimmer > Küchengeräte > Kaffee- & Espressomaschinen > Filterkaffeemaschinen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Kaffee- & Espressomaschinen > French Presses Heim & Garten > Küche & Esszimmer > Küchengeräte > Kaffee- & Espressomaschinen > Perkolatoren & Kaffeebrüher +Heim & Garten > Küche & Esszimmer > Küchengeräte > Kaffee- & Espressomaschinen > Pressstempelkannen Heim & Garten > Küche & Esszimmer > Küchengeräte > Kaffee- & Espressomaschinen > Vakuumbereiter Heim & Garten > Küche & Esszimmer > Küchengeräte > Kochfelder Heim & Garten > Küche & Esszimmer > Küchengeräte > Kochplatten Heim & Garten > Küche & Esszimmer > Küchengeräte > Kochtöpfe & Dampfkochtöpfe Heim & Garten > Küche & Esszimmer > Küchengeräte > Kochtöpfe & Dampfkochtöpfe > Dampfgarer Heim & Garten > Küche & Esszimmer > Küchengeräte > Kochtöpfe & Dampfkochtöpfe > Eierkocher -Heim & Garten > Küche & Esszimmer > Küchengeräte > Kochtöpfe & Dampfkochtöpfe > Langsamkocher Heim & Garten > Küche & Esszimmer > Küchengeräte > Kochtöpfe & Dampfkochtöpfe > Reiskocher +Heim & Garten > Küche & Esszimmer > Küchengeräte > Kochtöpfe & Dampfkochtöpfe > Schongarer Heim & Garten > Küche & Esszimmer > Küchengeräte > Kochtöpfe & Dampfkochtöpfe > Thermokocher Heim & Garten > Küche & Esszimmer > Küchengeräte > Kochtöpfe & Dampfkochtöpfe > Öfen zum Vakuumgaren Heim & Garten > Küche & Esszimmer > Küchengeräte > Küchenherde Heim & Garten > Küche & Esszimmer > Küchengeräte > Kühlschränke Heim & Garten > Küche & Esszimmer > Küchengeräte > Lebensmittel-Räucheröfen Heim & Garten > Küche & Esszimmer > Küchengeräte > Lebensmittelmühlen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Lebensmittelmühlen > Fleischwölfe -Heim & Garten > Küche & Esszimmer > Küchengeräte > Lebensmittelmühlen > Getreidemühlen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Lebensmittelmühlen > Gewürzmühlen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Lebensmittelmühlen > Kaffeemühlen Heim & Garten > Küche & Esszimmer > Küchengeräte > Messerschärfer Heim & Garten > Küche & Esszimmer > Küchengeräte > Mikrowellenherde Heim & Garten > Küche & Esszimmer > Küchengeräte > Milchaufschäumer +Heim & Garten > Küche & Esszimmer > Küchengeräte > Mixer & Pürierstäbe Heim & Garten > Küche & Esszimmer > Küchengeräte > Mochi-Maschinen Heim & Garten > Küche & Esszimmer > Küchengeräte > Müllpressen Heim & Garten > Küche & Esszimmer > Küchengeräte > Nudelmaschinen Heim & Garten > Küche & Esszimmer > Küchengeräte > Popcornmaschinen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Roaster Ovens & Mini-Backöfen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Rühr- & Küchenmaschinen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Rührgeräte -Heim & Garten > Küche & Esszimmer > Küchengeräte > Shlushmaschinen +Heim & Garten > Küche & Esszimmer > Küchengeräte > Slush-Eis-Maschinen Heim & Garten > Küche & Esszimmer > Küchengeräte > Sojamilchbereiter Heim & Garten > Küche & Esszimmer > Küchengeräte > Speiseeismaschinen Heim & Garten > Küche & Esszimmer > Küchengeräte > Speisewärmer +Heim & Garten > Küche & Esszimmer > Küchengeräte > Speisewärmer > Buffetwärmer +Heim & Garten > Küche & Esszimmer > Küchengeräte > Speisewärmer > Reiswärmer Heim & Garten > Küche & Esszimmer > Küchengeräte > Speisewärmer > Speisewärmelampen -Heim & Garten > Küche & Esszimmer > Küchengeräte > Speisewärmer > Warmhaltebehälter Heim & Garten > Küche & Esszimmer > Küchengeräte > Speisewärmer > Warmhaltetische -Heim & Garten > Küche & Esszimmer > Küchengeräte > Standmixer & Pürierstäbe Heim & Garten > Küche & Esszimmer > Küchengeräte > Teekocher Heim & Garten > Küche & Esszimmer > Küchengeräte > Temperiermaschinen für Schokolade Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Brezelbackautomat Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Donutmaker +Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Mini- & Toastöfen Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Muffin- & Cupcake-Maker Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Pizzaöfen Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Pizzelle-Eisen Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Quesadilla- & Tortilla-Maker Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Sandwichtoaster Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Toaster -Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Toastöfen Heim & Garten > Küche & Esszimmer > Küchengeräte > Toaster & Grills > Waffeleisen Heim & Garten > Küche & Esszimmer > Küchengeräte > Trinkwasserspender Heim & Garten > Küche & Esszimmer > Küchengeräte > Vakuumierer @@ -2461,7 +2057,6 @@ Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Allespicker & Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Ausstechförmchen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Backpinsel Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Backschaufeln -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Bonbon- & Pralinenformen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Bratenspritzen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Bratschläuche Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Dampfgarbeutel @@ -2480,25 +2075,25 @@ Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Fleischklopfe Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Fleischpistolen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Geschirrständer & Abtropfflächen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Getränkespender +Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Gewürzmühlen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Kartoffelpressen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Keksmaschine Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Kellen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Knoblauchpressen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Kochthermometer -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Kuchenverzierungsbedarf +Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Kuchen-Dekorationsbedarf Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Kurzzeitmesser & Eieruhren Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenformen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenmesser Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Aufbewahrungssysteme für Getränkepads Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Besteckkästen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Gewürzregale & -ständer Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Halter für Küchenutensilien Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Konservenregal -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Küchenkarusselle Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Küchenrollenhalter & -spender Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Küchenschranksysteme Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Messerblöcke & -halter +Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Organizer für Küchenutensilien Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Serviettenhalter & -spender Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Topfregale Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenorganizer > Trinkgefäßhalter @@ -2511,14 +2106,11 @@ Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenschabe Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenschaber > Teigspatel Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenscheren Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenschneidegeräte -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenschneidegeräte > Brotschneidemaschinen -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenschneidegeräte > Eierschneider -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenschneidegeräte > Gemüsehobel -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenschneidegeräte > Käsehobel -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenthermometer +Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenthermometer-Zubehör +Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchentrichter Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenutensilien-Sets -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenwaagen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Küchenzangen +Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Lebensmittelschablonen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Löffelablagen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Mehlsiebe Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Messbecher & Dosierlöffel @@ -2532,6 +2124,7 @@ Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Portionierer Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Portionierer > Eiscremeportionierer Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Portionierer > Eisportionierer Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Portionierer > Kugelausstecher +Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Portionierer > Popcorn- & Pommesschaufeln Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Reiben Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Rührschüsseln Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Salatschleudern @@ -2539,8 +2132,7 @@ Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Saucenspender Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Schaumlöffel Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Schneebesen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Schneidebretter -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Schneidemaschinen für Lebensmittel -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Schäler +Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Schäler & Entkerner Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Schürzen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Spezialbesteck & Nussknacker Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Spezialbesteck & Nussknacker > Hummer- & Krebszangen @@ -2549,7 +2141,6 @@ Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Spezialbestec Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Spülbeckenkörbe Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Spülbeckenmatten Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Stampfer -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Stieleisformen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Sushi-Matten Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Teesiebe Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Teigmischer @@ -2561,9 +2152,8 @@ Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Teigräder Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Teigtücher Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Topfhandschuhe & Topflappen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Tortenheber -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Würfelschneider & Zerkleinerungsgeräte Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Ziseliermesser -Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Zitruspressen +Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Zubehör für Gewürzmühlen Heim & Garten > Küche & Esszimmer > Küchenhelfer & -utensilien > Zuckerspender Heim & Garten > Küche & Esszimmer > Tafelgeschirr Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Geschirr @@ -2572,6 +2162,7 @@ Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Geschirr > Schüsseln Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Geschirr > Teller Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Kaffee- & Teekannen Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Kaffee- & Teeservices +Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Klemmen & Gewichte für Tischdecken Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Salz- & Pfefferstreuer Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Servierbesteck Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Servierbesteck > Bowlenschüsseluntersatz @@ -2593,145 +2184,115 @@ Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Tischbestecke Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Tischbestecke > Besteck-Sets Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Tischbestecke > Essstäbchen Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Tischbestecke > Essstäbchenzubehör -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Tischbestecke > Essstäbchenzubehör > Essstäbchenaufsätze -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Tischbestecke > Essstäbchenzubehör > Essstäbchenbank Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Tischbestecke > Gabeln Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Tischbestecke > Löffel Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Tischbestecke > Tafelmesser Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Topfuntersetzer Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Biergläser -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Biergläser > Krüge & Bierhumpen -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Biergläser > Pilsgläser -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Biergläser > Pint-Gläser Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Kaffee- & Teebecher Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Kaffee- und Teetassen -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Kaffee- und Teetassen > Kaffeetassen -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Kaffee- und Teetassen > Teetassen Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Kaffee- und Teeuntertassen Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Schnapsgläser Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Stielgläser -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Stielgläser > Kognakschwenker -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Stielgläser > Margarita-Gläser -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Stielgläser > Martini-Gläser -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Stielgläser > Sektgläser -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Stielgläser > Weingläser Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Trinkbehältersets Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Trinkgläser -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Trinkgläser > Highball-Gläser -Heim & Garten > Küche & Esszimmer > Tafelgeschirr > Trinkgefäße > Trinkgläser > Tumbler Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör > Anzündkamine Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör > Außengrillabdeckungen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör > Außengrillroste & -auflagen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör > Außengrillspieße & -körbe -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör > Grillbrenner +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör > Ersatzteile für Außengrills Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör > Grillbretter Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör > Grillwagen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör > Holzkohle Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Außengrillzubehör > Räucherchips & -Pellets -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Backofenzubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Backofenzubehör > Backofeninnenverkleidungen -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Backofenzubehör > Backofenschutz -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Backofenzubehör > Ofenroste +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Dunstabzugshauben-Zubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Dörrautomatenzubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Dörrautomatenzubehör > Dörrautomatenbleche Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Dörrautomatenzubehör > Dörrautomatentabletts -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Eis-Shaver-Zubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Entsafterzubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Fonduesetzubehör +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Fonduesetzubehör > Chafing Dish- & Fonduebrennpasten Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Fonduesetzubehör > Fonduegabeln Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Fonduesetzubehör > Fonduetopfständer Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Fritteusenzubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Fritteusenzubehör > Fritteusenkörbe -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Gasherdzubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Gasherdzubehör > Gasherdaufsätze -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Herdzubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Herdzubehör > Herdabdeckungen -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Herdzubehör > Herdauffangwannen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Küchenabfallzerkleinerer-Zubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Kühlschrankzubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Mikrowellenzubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Mikrowellenzubehör > Mikrowellen Trim-Kits -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Mikrowellenzubehör > Mikrowellen-Schublade -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Mixerzubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Mixerzubehör > Mixbecher -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Mixerzubehör > Mixerdeckel Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Nudelmaschinenzubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Rührgerätezubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Rührgerätezubehör > Knethaken für Rührgeräte -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Rührgerätezubehör > Rührbesen für Rührgeräte -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Rührgerätezubehör > Rührgeräteaufsätze -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Rührgerätezubehör > Rührgeräteaufsätze > Entsafteraufsätze -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Rührgerätezubehör > Rührgeräteaufsätze > Fleischwolfaufsätze -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Rührgerätezubehör > Rührgeräteaufsätze > Nudelmaschinenaufsätze -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Rührgerätezubehör > Schüsseln für Rührgeräte Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Speiseeismaschinenzubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Speiseeismaschinenzubehör > Gefrierschüsseln für Speiseeismaschinen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Spülmaschinenzubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Spülmaschinenzubehör > Spülmaschineneinsätze für Gläser Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Toasterzubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Vakuumiererzubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Vakuumiererzubehör > Vakuumierer-Beutel Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Wasserspenderzubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Wasserspenderzubehör > Flaschen für Wasserspender -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zerkleinererzubehör +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Weinkühlschrank-Zubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Brotbackautomaten Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Campingöfen +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Eis-Crusher & Eis-Shaver Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Eismaschinen -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Gefriertruhen +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Gefrierschränke +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Herdplatten, Backöfen und Küchenherde Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Joghurtmaschinen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Aufschäumer -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Espressokocherteile +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Ersatzteile für Espresso- & Kaffeemaschinen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Kaffeefilter Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Kaffeefilterkörbe Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Kaffeekannen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Kaffeekannenwarmhalter +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Kaffeemühlen +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Kaffeemühlenzubehör Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Siebträger Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Kaffee- & Espressomaschinen > Wasserfilter für Kaffeemaschinen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Lebensmittelmühlen -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Lebensmittelmühlen > Fleischwolfzubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Lebensmittelmühlen > Kaffeemühlenzubehör -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Lebensmittelmühlen > Zubehör für Gewürzmühlen +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Mixer & Pürierstäbe Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Popcornmaschinen +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Trinkwassersprudler +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Waffeleisen Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Warmhaltetheken Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Warmhaltetheken > Behälter für Warmhaltetheken Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Warmhaltetheken > Deckel für Warmhaltebehälter +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Wasserkocher Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für Zuckerwattemaschinen -Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für elektrische Töpfe & Woks +Heim & Garten > Küche & Esszimmer > Zubehör für Küchengeräte > Zubehör für elektrische Pfannen & Woks Heim & Garten > Notfallvorsorge Heim & Garten > Notfallvorsorge > Erdbebenmelder Heim & Garten > Notfallvorsorge > Möbelanker +Heim & Garten > Notfallvorsorge > Notfalldecken Heim & Garten > Notfallvorsorge > Notfallwerkzeuge Heim & Garten > Notfallvorsorge > Notvorräte Heim & Garten > Pflanzen Heim & Garten > Pflanzen > Blumen Heim & Garten > Pflanzen > Bäume Heim & Garten > Pflanzen > Grünpflanzen, Büsche & Sträucher -Heim & Garten > Pflanzen > Grünpflanzen, Büsche & Sträucher > Gartenpflanzen -Heim & Garten > Pflanzen > Grünpflanzen, Büsche & Sträucher > Zimmerpflanzen +Heim & Garten > Pflanzen > Pflanzen- & Kräuteranbausets Heim & Garten > Pflanzen > Saatgut Heim & Garten > Pflanzen > Wasserpflanzen Heim & Garten > Pool & Spa Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Badeinseln & Schwimmliegen -Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Badeinseln & Schwimmliegen > Baby-Luftmatratzen & Baby-Schwimmringe Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Badespielzeug +Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Chlorgeneratoren für Pools und Whirlpools Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Mechanische & Chemische Poolreiniger Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Pool- & Whirlpool-Filter -Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Poolabdeckungen +Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Poolabdeckungen & -unterlagen Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Poolbürsten -Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Poolleitern +Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Poolfolien +Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Poolleitern, -treppen & -rampen Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Poolreinigungsgeräte Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Poolskimmer -Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Poolsysteme Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Schläuche für Poolreiniger -Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Schwimmflügel +Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Sonnendecks Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Sprungbretter Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Swimmingpoolheizungen +Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Wartungssets für Pools & Whirlpools Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Wasserrutschen +Heim & Garten > Pool & Spa > Pool- & Whirlpool-Zubehör > Zubehör für Poolabdeckungen Heim & Garten > Pool & Spa > Pools Heim & Garten > Pool & Spa > Saunen Heim & Garten > Pool & Spa > Spa-Becken @@ -2741,12 +2302,12 @@ Heim & Garten > Rasen & Garten > Bewässerungssysteme > Gartenschlauchsprühköp Heim & Garten > Rasen & Garten > Bewässerungssysteme > Gartenschlauchzubehör & -ventile Heim & Garten > Rasen & Garten > Bewässerungssysteme > Gartenschläuche Heim & Garten > Rasen & Garten > Bewässerungssysteme > Gießkannen -Heim & Garten > Rasen & Garten > Bewässerungssysteme > Sprinkler & Köpfe -Heim & Garten > Rasen & Garten > Bewässerungssysteme > Sprinkler & Köpfe > Sprinkler -Heim & Garten > Rasen & Garten > Bewässerungssysteme > Sprinkler & Köpfe > Sprinklerköpfe +Heim & Garten > Rasen & Garten > Bewässerungssysteme > Sprinkler & -köpfe Heim & Garten > Rasen & Garten > Bewässerungssysteme > Sprinklersysteme Heim & Garten > Rasen & Garten > Bewässerungssysteme > Sprinklersysteme > Sprinklerventile Heim & Garten > Rasen & Garten > Bewässerungssysteme > Sprinklersysteme > Steuerelemente für Sprinkleranlagen +Heim & Garten > Rasen & Garten > Bewässerungssysteme > Wasserspender für Pflanzen +Heim & Garten > Rasen & Garten > Bewässerungssysteme > Zubehör für Gießkannen Heim & Garten > Rasen & Garten > Garten & Balkon Heim & Garten > Rasen & Garten > Garten & Balkon > Gartenhäuschen & Gartenbauten Heim & Garten > Rasen & Garten > Garten & Balkon > Gartenhäuschen & Gartenbauten > Bögen, Gitter, Laubengänge & Pergolen @@ -2758,43 +2319,42 @@ Heim & Garten > Rasen & Garten > Garten & Balkon > Gartenhäuschen & Gartenbaute Heim & Garten > Rasen & Garten > Garten & Balkon > Gartenhäuschen & Gartenbauten > Pavillon-Zubehör > Seitenwand-Sets für Pavillons Heim & Garten > Rasen & Garten > Garten & Balkon > Gartenhäuschen & Gartenbauten > Pavillon-Zubehör > Stangen für Sonnendächer Heim & Garten > Rasen & Garten > Garten & Balkon > Gartenhäuschen & Gartenbauten > Pavillons & Gartenlauben -Heim & Garten > Rasen & Garten > Garten & Balkon > Gartenhäuschen & Gartenbauten > Schuppen & Lagerung +Heim & Garten > Rasen & Garten > Garten & Balkon > Gartenhäuschen & Gartenbauten > Schuppen, Garagen & Carports Heim & Garten > Rasen & Garten > Garten & Balkon > Hollywoodschaukeln Heim & Garten > Rasen & Garten > Garten & Balkon > Hängematten Heim & Garten > Rasen & Garten > Garten & Balkon > Hängemattenzubehör +Heim & Garten > Rasen & Garten > Garten & Balkon > Markisen +Heim & Garten > Rasen & Garten > Garten & Balkon > Markisen-Zubehör Heim & Garten > Rasen & Garten > Garten & Balkon > Outdoor-Decken Heim & Garten > Rasen & Garten > Garten & Balkon > Outdoor-Decken > Picknickdecken Heim & Garten > Rasen & Garten > Garten & Balkon > Outdoor-Decken > Poncholiner Heim & Garten > Rasen & Garten > Garten & Balkon > Outdoor-Decken > Strandmatten -Heim & Garten > Rasen & Garten > Garten & Balkon > Sonnenschirm- und Markisenzubehör -Heim & Garten > Rasen & Garten > Garten & Balkon > Sonnenschirm- und Markisenzubehör > Beleuchtung für Sonnenschirme -Heim & Garten > Rasen & Garten > Garten & Balkon > Sonnenschirm- und Markisenzubehör > Sonnenschirmschutzhüllen -Heim & Garten > Rasen & Garten > Garten & Balkon > Sonnenschirm- und Markisenzubehör > Sonnenschirmstoff -Heim & Garten > Rasen & Garten > Garten & Balkon > Sonnenschirm- und Markisenzubehör > Sonnenschirmständer Heim & Garten > Rasen & Garten > Garten & Balkon > Sonnenschirme +Heim & Garten > Rasen & Garten > Garten & Balkon > Zubehör für Hollywoodschaukeln +Heim & Garten > Rasen & Garten > Garten & Balkon > Zubehör für Sonnenschirme +Heim & Garten > Rasen & Garten > Garten & Balkon > Zubehör für Sonnenschirme > Sonnenschirmabdeckungen +Heim & Garten > Rasen & Garten > Garten & Balkon > Zubehör für Sonnenschirme > Sonnenschirmbeleuchtung +Heim & Garten > Rasen & Garten > Garten & Balkon > Zubehör für Sonnenschirme > Sonnenschirmschutzhüllen +Heim & Garten > Rasen & Garten > Garten & Balkon > Zubehör für Sonnenschirme > Sonnenschirmstoff +Heim & Garten > Rasen & Garten > Garten & Balkon > Zubehör für Sonnenschirme > Sonnenschirmständer Heim & Garten > Rasen & Garten > Gartenbau +Heim & Garten > Rasen & Garten > Gartenbau > Blumenkäfige & Zubehör Heim & Garten > Rasen & Garten > Gartenbau > Blumentöpfe & Pflanzgefäße Heim & Garten > Rasen & Garten > Gartenbau > Dünger +Heim & Garten > Rasen & Garten > Gartenbau > Gartentopfuntersetzer und Trays Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Astsägen Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Baumscheren -Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Gartenbauutensilien -Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Gartenbauutensilien > Gartenhacken -Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Gartensicheln +Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Gartensicheln & Macheten Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Geräte zum Pflanzen von Knollen -Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Hacken & Spitzhacken -Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Haumesser -Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Macheten Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Mistgabeln Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Pflanzkellen +Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Pflanzwerkzeuge Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Rasen- & Gartenspritzgeräte -Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Rasenkantentrimmer -Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Rasenlüfter +Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Rasenwalzen Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Rechen Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Schaufeln & Spaten Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Schubkarren -Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Schubkarrenteile -Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Strahlstöcke Heim & Garten > Rasen & Garten > Gartenbau > Gartenwerkzeuge > Streugeräte Heim & Garten > Rasen & Garten > Gartenbau > Gewächshäuser Heim & Garten > Rasen & Garten > Gartenbau > Herbizide @@ -2804,28 +2364,34 @@ Heim & Garten > Rasen & Garten > Gartenbau > Kompostieren > Komposter Heim & Garten > Rasen & Garten > Gartenbau > Kompostieren > Kompostlüfter Heim & Garten > Rasen & Garten > Gartenbau > Krankheitsbekämpfung Heim & Garten > Rasen & Garten > Gartenbau > Mulch +Heim & Garten > Rasen & Garten > Gartenbau > Pflanzeinsätze für Blumentöpfe und -kübel Heim & Garten > Rasen & Garten > Gartenbau > Pflanzenständer -Heim & Garten > Rasen & Garten > Gartenbau > Pflanzenstützen -Heim & Garten > Rasen & Garten > Gartenbau > Pflanzenstützstäbe & -gitter Heim & Garten > Rasen & Garten > Gartenbau > Regenfässer Heim & Garten > Rasen & Garten > Gartenbau > Sand & Gartenerde Heim & Garten > Rasen & Garten > Gartenbau > Unkrautvlies Heim & Garten > Rasen & Garten > Gartenbau > Unkrautvlies-Zubehör Heim & Garten > Rasen & Garten > Gartenbau > Unkrautvlies-Zubehör > Erdanker & -nägel -Heim & Garten > Rasen & Garten > Gartenbau > Unkrautvlies-Zubehör > Unkrautvlies - Gewebeband +Heim & Garten > Rasen & Garten > Gartenbau > Unkrautvlies-Zubehör > Garten - Gewebeband Heim & Garten > Rasen & Garten > Gartenbau > Zubehör für Gartenarbeit Heim & Garten > Rasen & Garten > Gartenbau > Zubehör für Gartenarbeit > Gartentaschen -Heim & Garten > Rasen & Garten > Gartenbau > Zubehör für Gartenarbeit > Kniekissen +Heim & Garten > Rasen & Garten > Gartenbau > Zubehör für Gartenarbeit > Rollsitze, Sitzhilfen & Kniekissen für Gartenarbeit Heim & Garten > Rasen & Garten > Gartenbau > Zubehör für Gartenarbeit > Umtopftische +Heim & Garten > Rasen & Garten > Gartenbau > Zubehör für Gartengeräte +Heim & Garten > Rasen & Garten > Gartenbau > Zubehör für Gartengeräte > Aufsätze für Gartengeräte +Heim & Garten > Rasen & Garten > Gartenbau > Zubehör für Gartengeräte > Griffe für Gartengeräte +Heim & Garten > Rasen & Garten > Gartenbau > Zubehör für Gartengeräte > Schubkarrenteile Heim & Garten > Rasen & Garten > Gartenmaschinen +Heim & Garten > Rasen & Garten > Gartenmaschinen > Basiseinheiten für elektrische Gartengeräte Heim & Garten > Rasen & Garten > Gartenmaschinen > Bodenbearbeitungsmaschinen Heim & Garten > Rasen & Garten > Gartenmaschinen > Elektrische Heckenscheren -Heim & Garten > Rasen & Garten > Gartenmaschinen > Elektrische Kombi-Ausstattung -Heim & Garten > Rasen & Garten > Gartenmaschinen > Elektrische Kombi-Gartenmaschinen +Heim & Garten > Rasen & Garten > Gartenmaschinen > Elektrische Kombi-Gartenmaschinen-Sets Heim & Garten > Rasen & Garten > Gartenmaschinen > Hochdruckreiniger +Heim & Garten > Rasen & Garten > Gartenmaschinen > Kehrmaschine Heim & Garten > Rasen & Garten > Gartenmaschinen > Kettensägen Heim & Garten > Rasen & Garten > Gartenmaschinen > Laubbläser Heim & Garten > Rasen & Garten > Gartenmaschinen > Laubsauger +Heim & Garten > Rasen & Garten > Gartenmaschinen > Rasenkantentrimmer +Heim & Garten > Rasen & Garten > Gartenmaschinen > Rasenlüfter und Vertikutierer Heim & Garten > Rasen & Garten > Gartenmaschinen > Rasenmäher Heim & Garten > Rasen & Garten > Gartenmaschinen > Rasenmäher > Aufsitzrasenmäher Heim & Garten > Rasen & Garten > Gartenmaschinen > Rasenmäher > Handrasenmäher @@ -2835,382 +2401,358 @@ Heim & Garten > Rasen & Garten > Gartenmaschinen > Rasentrimmer & Freischneider Heim & Garten > Rasen & Garten > Gartenmaschinen > Schneefräsen Heim & Garten > Rasen & Garten > Gartenmaschinen > Traktoren Heim & Garten > Rasen & Garten > Schnee- und Eisbeseitigung -Heim & Garten > Rasen & Garten > Schnee- und Eisbeseitigung > Eiskratzer +Heim & Garten > Rasen & Garten > Schnee- und Eisbeseitigung > Eiskratzer & Schneebesen Heim & Garten > Rasen & Garten > Schnee- und Eisbeseitigung > Schneeschaufeln Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Aufsätze für elektrische Kombi-Gartenmaschinen +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Aufsätze für elektrische Kombi-Gartenmaschinen > Fräsen- und Grubber-Aufsätze +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Aufsätze für elektrische Kombi-Gartenmaschinen > Heckenscheren-Aufsätze +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Aufsätze für elektrische Kombi-Gartenmaschinen > Laubbläser-Aufsätze +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Aufsätze für elektrische Kombi-Gartenmaschinen > Rasentrimmer-Aufsätze +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Aufsätze für elektrische Kombi-Gartenmaschinen > Stangensägen-Aufsätze +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Aufsätze für elektrische Kombi-Gartenmaschinen > Unkrauttrimmer-Aufsätze Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Batterien für elektrische Kombi-Gartenmaschinen -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Batterien für elektrische Kombi-Gartenmaschinen > Batterien für Heckenschneider -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Batterien für elektrische Kombi-Gartenmaschinen > Batterien für Unkrauttrimmer -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Batterien für elektrische Kombi-Gartenmaschinen > Rasenmäherbatterien Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Heckenscheren-Zubehör -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Heckenscheren-Zubehör > Heckenscheren-Aufsätze Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Hochdruckreiniger-Zubehör Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Kettensägenzubehör Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Kettensägenzubehör > Kettensägenketten Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Kettensägenzubehör > Kettensägenschwerter Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Laubbläser-Zubehör -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Laubbläser-Zubehör > Laubbläser-Erweiterungen +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Laubbläser-Zubehör > Laubbläser-Rohre +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Grasauffangbehälter +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Mulchkits für Rasenmäher +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Mulchstopfen für Rasenmäher +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Rasenkehrmaschinen +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Rasenmäher-Antriebsrollen +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Rasenmäher-Keilriemen +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Rasenmäher-Reifen +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Rasenmäher-Reifenschläuche +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Rasenmäher-Riemenscheiben +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Rasenmäher-Räder +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Rasenmäherabdeckungen +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Rasenmähermesser +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasenmäher-Zubehör > Wiesenmäher-Zusatzteile Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasentrimmer-Zubehör -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Rasentrimmer-Zubehör > Rasentrimmer-Aufsätze Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Schneefräsenzubehör Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Traktorteile & Zubehör +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Traktorteile & Zubehör > Traktorreifen +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Traktorteile & Zubehör > Traktorräder Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Unkrauttrimmer-Zubehör -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Unkrauttrimmer-Zubehör > Abdeckungen für Unkrauttrimmer-Kabelrollen -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Unkrauttrimmer-Zubehör > Messer & Kabelrollen für Unkrauttrimmer -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Unkrauttrimmer-Zubehör > Unkrauttrimmer-Aufsätze -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher > Grasauffangbehälter -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher > Rasenkehrmaschinen -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher > Rasenmäher-Keilriemen -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher > Rasenmäher-Reifen -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher > Rasenmäher-Riemenscheiben -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher > Rasenmäher-Räder -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher > Rasenmäher-Zusatzteile -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher > Rasenmäherabdeckungen -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher > Rasenmähermesser -Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Zubehör für Rasenmäher > Wiesenmäher-Zusatzteile +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Unkrauttrimmer-Zubehör > Abdeckungen für Rasentrimmer-Kabelrollen +Heim & Garten > Rasen & Garten > Zubehör für Gartenmaschinen > Unkrauttrimmer-Zubehör > Messer & Kabelrollen für Rasentrimmer Heim & Garten > Rauchzubehör Heim & Garten > Rauchzubehör > Aschenbecher -Heim & Garten > Rauchzubehör > Feuerzeuge Heim & Garten > Rauchzubehör > Humidore Heim & Garten > Rauchzubehör > Humidorzubehör -Heim & Garten > Rauchzubehör > Streichhölzer +Heim & Garten > Rauchzubehör > Zigarettenhalter Heim & Garten > Rauchzubehör > Zigarettenkisten Heim & Garten > Rauchzubehör > Zigarrenkisten -Heim & Garten > Rauchzubehör > Zigarrenschneider +Heim & Garten > Rauchzubehör > Zigarrenschneider & -locher Heim & Garten > Schutzhüllen für Sonnenschirme Heim & Garten > Sonnen- & Regenschirme Heim & Garten > Zubehör für Kamine & Holzöfen Heim & Garten > Zubehör für Kamine & Holzöfen > Blasebälge +Heim & Garten > Zubehör für Kamine & Holzöfen > Feuerböcke Heim & Garten > Zubehör für Kamine & Holzöfen > Feuerholz & Brennstoffe Heim & Garten > Zubehör für Kamine & Holzöfen > Feuerholz-Aufbewahrung Heim & Garten > Zubehör für Kamine & Holzöfen > Holzofenventilatoren & -gebläse Heim & Garten > Zubehör für Kamine & Holzöfen > Kamin- & Holzofenroste Heim & Garten > Zubehör für Kamine & Holzöfen > Kaminbodenplatten -Heim & Garten > Zubehör für Kamine & Holzöfen > Kaminböcke Heim & Garten > Zubehör für Kamine & Holzöfen > Kamingitter Heim & Garten > Zubehör für Kamine & Holzöfen > Kaminreflektoren Heim & Garten > Zubehör für Kamine & Holzöfen > Kaminwerkzeug Heim & Garten > Zubehör für Kamine & Holzöfen > Zubehör für Feuerholz-Aufbewahrung Heimwerkerbedarf +Heimwerkerbedarf > Baumaterial +Heimwerkerbedarf > Baumaterial > Chemikalien +Heimwerkerbedarf > Baumaterial > Chemikalien > Abflussreiniger +Heimwerkerbedarf > Baumaterial > Chemikalien > Ammonium +Heimwerkerbedarf > Baumaterial > Chemikalien > Anzünderflüssigkeit +Heimwerkerbedarf > Baumaterial > Chemikalien > Beton- & Mauerreiniger +Heimwerkerbedarf > Baumaterial > Chemikalien > Enteiser +Heimwerkerbedarf > Baumaterial > Chemikalien > Holzterrassen- & -zaunreiniger +Heimwerkerbedarf > Baumaterial > Chemikalien > Kaminreiniger +Heimwerkerbedarf > Baumaterial > Chemikalien > Kältespray für Elektronik +Heimwerkerbedarf > Baumaterial > Chemikalien > Reiniger für Abwassertanks & Senkgruben +Heimwerkerbedarf > Baumaterial > Chemikalien > Säureneutralisierer +Heimwerkerbedarf > Baumaterial > Klebebänder +Heimwerkerbedarf > Baumaterial > Kraftklebstoffe & -leime +Heimwerkerbedarf > Baumaterial > Lösungsmittel, Abbeizmittel & Verdünner +Heimwerkerbedarf > Baumaterial > Lötmetall & Flussmittel +Heimwerkerbedarf > Baumaterial > Malermaterial +Heimwerkerbedarf > Baumaterial > Malermaterial > Farbe +Heimwerkerbedarf > Baumaterial > Malermaterial > Farbenbindemittel +Heimwerkerbedarf > Baumaterial > Malermaterial > Farbstoffe +Heimwerkerbedarf > Baumaterial > Malermaterial > Grundierungen +Heimwerkerbedarf > Baumaterial > Malermaterial > Lacke & Beschichtungen +Heimwerkerbedarf > Baumaterial > Maurermaterial +Heimwerkerbedarf > Baumaterial > Maurermaterial > Mauersteine & Betonblöcke +Heimwerkerbedarf > Baumaterial > Maurermaterial > Mörtel +Heimwerkerbedarf > Baumaterial > Maurermaterial > Zement, Mörtel & Beton +Heimwerkerbedarf > Baumaterial > Primer für Rohrverbindungen +Heimwerkerbedarf > Baumaterial > Schmiermittel +Heimwerkerbedarf > Baumaterial > Schutzbeschichtungen & Dichtmittel +Heimwerkerbedarf > Baumaterial > Wandausbesserungsmaterial & Gips Heimwerkerbedarf > Baumaterialien Heimwerkerbedarf > Baumaterialien > Arbeitsplatten -Heimwerkerbedarf > Baumaterialien > Arbeitsplatten > Granitarbeitsplatten -Heimwerkerbedarf > Baumaterialien > Arbeitsplatten > Hartholzarbeitsplatten -Heimwerkerbedarf > Baumaterialien > Arbeitsplatten > Keramik- & Porzellanarbeitsplatten -Heimwerkerbedarf > Baumaterialien > Arbeitsplatten > Kunststoffbeschichtete Arbeitsplatten -Heimwerkerbedarf > Baumaterialien > Arbeitsplatten > Marmorarbeitsplatten -Heimwerkerbedarf > Baumaterialien > Arbeitsplatten > Schichtstoffarbeitsplatten Heimwerkerbedarf > Baumaterialien > Bauholz +Heimwerkerbedarf > Baumaterialien > Bedachung +Heimwerkerbedarf > Baumaterialien > Bedachung > Dachrinnen +Heimwerkerbedarf > Baumaterialien > Bedachung > Dachschindeln & -pfannen +Heimwerkerbedarf > Baumaterialien > Bedachung > Kehlbleche +Heimwerkerbedarf > Baumaterialien > Bedachung > Zubehör für Dachrinnen +Heimwerkerbedarf > Baumaterialien > Betonstahl & -gitter Heimwerkerbedarf > Baumaterialien > Fenster +Heimwerkerbedarf > Baumaterialien > Fensterbauteile +Heimwerkerbedarf > Baumaterialien > Fensterbauteile > Fensterhebel +Heimwerkerbedarf > Baumaterialien > Fensterbauteile > Fensterrahmen Heimwerkerbedarf > Baumaterialien > Fensterläden -Heimwerkerbedarf > Baumaterialien > Fliesen -Heimwerkerbedarf > Baumaterialien > Fliesen > Fliesenböden -Heimwerkerbedarf > Baumaterialien > Fliesen > Geflieste Arbeitsplatten -Heimwerkerbedarf > Baumaterialien > Fußböden -Heimwerkerbedarf > Baumaterialien > Fußböden > Granitböden -Heimwerkerbedarf > Baumaterialien > Fußböden > Hartholzböden -Heimwerkerbedarf > Baumaterialien > Fußböden > Kautschukbeläge -Heimwerkerbedarf > Baumaterialien > Fußböden > Keramik- & Porzellanböden -Heimwerkerbedarf > Baumaterialien > Fußböden > Künstlicher Torf -Heimwerkerbedarf > Baumaterialien > Fußböden > Laminatböden -Heimwerkerbedarf > Baumaterialien > Fußböden > Marmorböden -Heimwerkerbedarf > Baumaterialien > Fußböden > Vinylböden +Heimwerkerbedarf > Baumaterialien > Fußböden & Teppichböden +Heimwerkerbedarf > Baumaterialien > Gipskartonplatten Heimwerkerbedarf > Baumaterialien > Glas +Heimwerkerbedarf > Baumaterialien > Handläufe und Geländersysteme +Heimwerkerbedarf > Baumaterialien > Hausverkleidung +Heimwerkerbedarf > Baumaterialien > Isolierung Heimwerkerbedarf > Baumaterialien > Leisten Heimwerkerbedarf > Baumaterialien > Luken -Heimwerkerbedarf > Baumaterialien > Mauersteine, Steine & Beton Heimwerkerbedarf > Baumaterialien > Schalldämpfende Materialien -Heimwerkerbedarf > Baumaterialien > Teppichböden Heimwerkerbedarf > Baumaterialien > Treppen +Heimwerkerbedarf > Baumaterialien > Türbeschläge & -klingeln +Heimwerkerbedarf > Baumaterialien > Türbeschläge & -klingeln > Schlossfallen +Heimwerkerbedarf > Baumaterialien > Türbeschläge & -klingeln > Schlüssellochverzierungen für Türen +Heimwerkerbedarf > Baumaterialien > Türbeschläge & -klingeln > Türdruckplatten +Heimwerkerbedarf > Baumaterialien > Türbeschläge & -klingeln > Türklingeln +Heimwerkerbedarf > Baumaterialien > Türbeschläge & -klingeln > Türklopfer +Heimwerkerbedarf > Baumaterialien > Türbeschläge & -klingeln > Türknäufe & -klinken +Heimwerkerbedarf > Baumaterialien > Türbeschläge & -klingeln > Türrahmen +Heimwerkerbedarf > Baumaterialien > Türbeschläge & -klingeln > Türschließer +Heimwerkerbedarf > Baumaterialien > Türbeschläge & -klingeln > Türstopper Heimwerkerbedarf > Baumaterialien > Türen Heimwerkerbedarf > Baumaterialien > Türen > Garagentore Heimwerkerbedarf > Baumaterialien > Türen > Haustüren -Heimwerkerbedarf > Baumaterialien > Türen > Haustüren > Fliegengittertüren -Heimwerkerbedarf > Baumaterialien > Türen > Sonstige Türen -Heimwerkerbedarf > Baumaterialien > Türen > Sonstige Türen > Haustiertüren +Heimwerkerbedarf > Baumaterialien > Wand- & Deckenfliesen Heimwerkerbedarf > Baumaterialien > Wandverkleidung +Heimwerkerbedarf > Baumaterialien > Zugluftstopper, Fenster- & Türdichtungen Heimwerkerbedarf > Bauzubehör Heimwerkerbedarf > Bauzubehör > Abdeckfolien +Heimwerkerbedarf > Bauzubehör > Befestigungselemente +Heimwerkerbedarf > Bauzubehör > Befestigungselemente > Dübel +Heimwerkerbedarf > Bauzubehör > Befestigungselemente > Gewindestangen +Heimwerkerbedarf > Bauzubehör > Befestigungselemente > Nieten +Heimwerkerbedarf > Bauzubehör > Befestigungselemente > Nägel +Heimwerkerbedarf > Bauzubehör > Befestigungselemente > Schrauben +Heimwerkerbedarf > Bauzubehör > Befestigungselemente > Schrauben & Muttern +Heimwerkerbedarf > Bauzubehör > Befestigungselemente > Schraubverbinder +Heimwerkerbedarf > Bauzubehör > Befestigungselemente > Unterlegscheiben Heimwerkerbedarf > Bauzubehör > Betonformen -Heimwerkerbedarf > Bauzubehör > Bindegarne -Heimwerkerbedarf > Bauzubehör > Draht -Heimwerkerbedarf > Bauzubehör > Dübel +Heimwerkerbedarf > Bauzubehör > Bodenspieße +Heimwerkerbedarf > Bauzubehör > Federn Heimwerkerbedarf > Bauzubehör > Filter & Siebe -Heimwerkerbedarf > Bauzubehör > Flaschenzüge Heimwerkerbedarf > Bauzubehör > Gasschläuche +Heimwerkerbedarf > Bauzubehör > Haken, Schnallen & Verschlüsse +Heimwerkerbedarf > Bauzubehör > Haken, Schnallen & Verschlüsse > Gear Tie-Universalkabelbinder +Heimwerkerbedarf > Bauzubehör > Haken, Schnallen & Verschlüsse > Kettenverbinder & -glieder +Heimwerkerbedarf > Bauzubehör > Haken, Schnallen & Verschlüsse > Lasthaken, Trageklemmen & Schäkel +Heimwerkerbedarf > Bauzubehör > Haken, Schnallen & Verschlüsse > Schnallen- & Steckschnallen Heimwerkerbedarf > Bauzubehör > Halterungen -Heimwerkerbedarf > Bauzubehör > Holzdübel & -stäbe -Heimwerkerbedarf > Bauzubehör > Holzplättchen -Heimwerkerbedarf > Bauzubehör > Ketten -Heimwerkerbedarf > Bauzubehör > Klebebänder -Heimwerkerbedarf > Bauzubehör > Klebebänder > Abdeckband -Heimwerkerbedarf > Bauzubehör > Klebebänder > Folienklebeband -Heimwerkerbedarf > Bauzubehör > Klebebänder > Gafferband -Heimwerkerbedarf > Bauzubehör > Klebebänder > Gewebeband -Heimwerkerbedarf > Bauzubehör > Klebebänder > Heizungsband -Heimwerkerbedarf > Bauzubehör > Klebebänder > Isolierband -Heimwerkerbedarf > Bauzubehör > Klebebänder > Klebe- & Gitterband für Gipskartonplatten -Heimwerkerbedarf > Bauzubehör > Klebebänder > Kupferband -Heimwerkerbedarf > Bauzubehör > Klebebänder > Teflonband -Heimwerkerbedarf > Bauzubehör > Luftdurchlässe & Abzugsrohre +Heimwerkerbedarf > Bauzubehör > Ketten, Drähte & Seile +Heimwerkerbedarf > Bauzubehör > Ketten, Drähte & Seile > Bindegarne +Heimwerkerbedarf > Bauzubehör > Ketten, Drähte & Seile > Draht +Heimwerkerbedarf > Bauzubehör > Ketten, Drähte & Seile > Ketten +Heimwerkerbedarf > Bauzubehör > Ketten, Drähte & Seile > Seile +Heimwerkerbedarf > Bauzubehör > Ketten, Drähte & Seile > Spanngummis +Heimwerkerbedarf > Bauzubehör > Ketten, Drähte & Seile > Spanngurte +Heimwerkerbedarf > Bauzubehör > Ketten, Drähte & Seile > Zugschalterketten und -kordeln +Heimwerkerbedarf > Bauzubehör > Laufrollen Heimwerkerbedarf > Bauzubehör > Luftschläuche -Heimwerkerbedarf > Bauzubehör > Lötmetall & Flussmittel -Heimwerkerbedarf > Bauzubehör > Nieten -Heimwerkerbedarf > Bauzubehör > Nägel +Heimwerkerbedarf > Bauzubehör > Metallgussformen Heimwerkerbedarf > Bauzubehör > Planen -Heimwerkerbedarf > Bauzubehör > Riegel +Heimwerkerbedarf > Bauzubehör > Richtstützen Heimwerkerbedarf > Bauzubehör > Scharniere -Heimwerkerbedarf > Bauzubehör > Schmiermittel Heimwerkerbedarf > Bauzubehör > Schmierschläuche Heimwerkerbedarf > Bauzubehör > Schrankbauteile +Heimwerkerbedarf > Bauzubehör > Schrankbauteile > Schlüssellochverzierungen für Schränke Heimwerkerbedarf > Bauzubehör > Schrankbauteile > Schrankbeschläge Heimwerkerbedarf > Bauzubehör > Schrankbauteile > Schrankknäufe & -griffe Heimwerkerbedarf > Bauzubehör > Schrankbauteile > Schrankscharniere -Heimwerkerbedarf > Bauzubehör > Schrankbauteile > Schrankschlösser Heimwerkerbedarf > Bauzubehör > Schrankbauteile > Schranktüren -Heimwerkerbedarf > Bauzubehör > Schrauben -Heimwerkerbedarf > Bauzubehör > Schrauben & Muttern -Heimwerkerbedarf > Bauzubehör > Schrauben > Gipskartonschrauben -Heimwerkerbedarf > Bauzubehör > Schrauben > Holzschrauben -Heimwerkerbedarf > Bauzubehör > Schrauben > Metallschrauben -Heimwerkerbedarf > Bauzubehör > Schraubverbinder -Heimwerkerbedarf > Bauzubehör > Seile -Heimwerkerbedarf > Bauzubehör > Spanngummis -Heimwerkerbedarf > Bauzubehör > Spanngurte +Heimwerkerbedarf > Bauzubehör > Schubladenschienen Heimwerkerbedarf > Bauzubehör > Spulen -Heimwerkerbedarf > Bauzubehör > Steuerungen -Heimwerkerbedarf > Bauzubehör > Steuerungen > Heizungs- & Klimaanlagen Steuerungen -Heimwerkerbedarf > Bauzubehör > Steuerungen > Schalt- & Bedienungstafeln -Heimwerkerbedarf > Bauzubehör > Steuerungen > Thermostate -Heimwerkerbedarf > Bauzubehör > Türbeschläge & -klingeln -Heimwerkerbedarf > Bauzubehör > Türbeschläge & -klingeln > Schlossfallen -Heimwerkerbedarf > Bauzubehör > Türbeschläge & -klingeln > Türklingeln -Heimwerkerbedarf > Bauzubehör > Türbeschläge & -klingeln > Türklopfer -Heimwerkerbedarf > Bauzubehör > Türbeschläge & -klingeln > Türknäufe & -klinken -Heimwerkerbedarf > Bauzubehör > Türbeschläge & -klingeln > Türschließer -Heimwerkerbedarf > Bauzubehör > Türbeschläge & -klingeln > Türstopper -Heimwerkerbedarf > Bauzubehör > Unterlegscheiben +Heimwerkerbedarf > Bauzubehör > Standfüße für Pfosten +Heimwerkerbedarf > Bauzubehör > Transport- und Schallschutzabdeckungen Heimwerkerbedarf > Bauzubehör > Warnklebeband Heimwerkerbedarf > Bauzubehör > Werkzeugaufbewahrung & Ordnungssysteme Heimwerkerbedarf > Bauzubehör > Werkzeugaufbewahrung & Ordnungssysteme > Dienst- & Werkzeuggürtel +Heimwerkerbedarf > Bauzubehör > Werkzeugaufbewahrung & Ordnungssysteme > Einsätze zur Werkzeugaufbewahrung Heimwerkerbedarf > Bauzubehör > Werkzeugaufbewahrung & Ordnungssysteme > Gartenschlauchhalterungen Heimwerkerbedarf > Bauzubehör > Werkzeugaufbewahrung & Ordnungssysteme > Werkbänke Heimwerkerbedarf > Bauzubehör > Werkzeugaufbewahrung & Ordnungssysteme > Werkzeugetuis Heimwerkerbedarf > Bauzubehör > Werkzeugaufbewahrung & Ordnungssysteme > Werkzeugkästen Heimwerkerbedarf > Bauzubehör > Werkzeugaufbewahrung & Ordnungssysteme > Werkzeugschränke Heimwerkerbedarf > Bauzubehör > Werkzeugaufbewahrung & Ordnungssysteme > Werkzeugtaschen -Heimwerkerbedarf > Bauzubehör > Zugschalterketten und -kordeln -Heimwerkerbedarf > Bedachung -Heimwerkerbedarf > Bedachung > Dachrinnen -Heimwerkerbedarf > Bedachung > Kehlbleche -Heimwerkerbedarf > Bedachung > Zubehör für Dachrinnen -Heimwerkerbedarf > Chemikalien -Heimwerkerbedarf > Chemikalien > Abflussreiniger -Heimwerkerbedarf > Chemikalien > Ammonium -Heimwerkerbedarf > Chemikalien > Beton- & Mauerreiniger -Heimwerkerbedarf > Chemikalien > Enteiser -Heimwerkerbedarf > Chemikalien > Holzterrassen- & -zaunreiniger -Heimwerkerbedarf > Chemikalien > Kaminreiniger -Heimwerkerbedarf > Chemikalien > Reiniger für Abwassertanks & Senkgruben -Heimwerkerbedarf > Chemikalien > Säureneutralisierer -Heimwerkerbedarf > Elektrikbedarf -Heimwerkerbedarf > Elektrikbedarf > Anschlussdosen & Halterungen -Heimwerkerbedarf > Elektrikbedarf > Drahtbindemaschinen -Heimwerkerbedarf > Elektrikbedarf > Drahtspulen -Heimwerkerbedarf > Elektrikbedarf > Elektronische Leitungen -Heimwerkerbedarf > Elektrikbedarf > Elektroschalter -Heimwerkerbedarf > Elektrikbedarf > Elektroschalter > Lichtschalter -Heimwerkerbedarf > Elektrikbedarf > Laderegler -Heimwerkerbedarf > Elektrikbedarf > Relais -Heimwerkerbedarf > Elektrikbedarf > Schrumpfschläuche -Heimwerkerbedarf > Elektrikbedarf > Steckdosen -Heimwerkerbedarf > Elektrikbedarf > Steckdosenabdeckungen -Heimwerkerbedarf > Elektrikbedarf > Verlängerungskabel -Heimwerkerbedarf > Elektrikbedarf > Verlängerungskabelzubehör -Heimwerkerbedarf > Elektrikbedarf > Verlängerungskabelzubehör > Kabeltrommeln für Verlängerungskabel -Heimwerkerbedarf > Elektrikbedarf > Verlängerungskabelzubehör > Verlängerungskabelstecker -Heimwerkerbedarf > Elektrikbedarf > Verteilerkästen -Heimwerkerbedarf > Elektrikbedarf > Vorschaltgeräte & Starter -Heimwerkerbedarf > Elektrikbedarf > Wandplatten -Heimwerkerbedarf > Elektrikbedarf > Zeitschaltuhren -Heimwerkerbedarf > Elektrikbedarf > Überbrückungsschalter -Heimwerkerbedarf > Erneuerbare Energie -Heimwerkerbedarf > Erneuerbare Energie > Solarenergie -Heimwerkerbedarf > Erneuerbare Energie > Solarenergie > Solarenergie-Kits -Heimwerkerbedarf > Erneuerbare Energie > Solarenergie > Solarpaneele -Heimwerkerbedarf > Erneuerbare Energie > Windkraft -Heimwerkerbedarf > Erneuerbare Energie > Windkraft > Windturbinen -Heimwerkerbedarf > Generatoren +Heimwerkerbedarf > Bauzubehör > Zylinderstifte & Dübelstangen +Heimwerkerbedarf > Brennstoffbehälter & -tanks +Heimwerkerbedarf > Elektrobedarf +Heimwerkerbedarf > Elektrobedarf > Anker, Rotoren und Statoren +Heimwerkerbedarf > Elektrobedarf > Anschlussdosen & Halterungen +Heimwerkerbedarf > Elektrobedarf > Drahtbindemaschinen +Heimwerkerbedarf > Elektrobedarf > Elektrische Leitungen +Heimwerkerbedarf > Elektrobedarf > Elektromotoren +Heimwerkerbedarf > Elektrobedarf > Elektroschalter +Heimwerkerbedarf > Elektrobedarf > Elektroschalter > Lichtschalter +Heimwerkerbedarf > Elektrobedarf > Elektroschalter > Spezielle elektrische Schalter +Heimwerkerbedarf > Elektrobedarf > Generatoren +Heimwerkerbedarf > Elektrobedarf > Gerätestecker +Heimwerkerbedarf > Elektrobedarf > Heim- & Gebäudeautomatisierung +Heimwerkerbedarf > Elektrobedarf > Kabelanschlüsse & Steckverbinder +Heimwerkerbedarf > Elektrobedarf > Kohlebürsten +Heimwerkerbedarf > Elektrobedarf > Leitungen & Gehäuse +Heimwerkerbedarf > Elektrobedarf > Leitungen & Gehäuse > Kabelkanäle +Heimwerkerbedarf > Elektrobedarf > Leitungen & Gehäuse > Schrumpfschläuche +Heimwerkerbedarf > Elektrobedarf > Schaltnetzteile +Heimwerkerbedarf > Elektrobedarf > Solarenergie-Kits +Heimwerkerbedarf > Elektrobedarf > Solarpaneele +Heimwerkerbedarf > Elektrobedarf > Spannungswandler & -regler +Heimwerkerbedarf > Elektrobedarf > Steckdosen +Heimwerkerbedarf > Elektrobedarf > Steckdosen-Zeitschaltuhren & -Sensoren +Heimwerkerbedarf > Elektrobedarf > Steckdosenabdeckungen +Heimwerkerbedarf > Elektrobedarf > Telefon- & Internetbuchsen +Heimwerkerbedarf > Elektrobedarf > Verlängerungskabel +Heimwerkerbedarf > Elektrobedarf > Verlängerungskabelzubehör +Heimwerkerbedarf > Elektrobedarf > Verteilerkästen +Heimwerkerbedarf > Elektrobedarf > Vorschaltgeräte & Starter +Heimwerkerbedarf > Elektrobedarf > Wandplatten +Heimwerkerbedarf > Elektrobedarf > Wechselrichter +Heimwerkerbedarf > Elektrobedarf > Zubehör für Generatoren Heimwerkerbedarf > Hauseinzäunung +Heimwerkerbedarf > Hauseinzäunung > Absperrungen +Heimwerkerbedarf > Hauseinzäunung > Beeteinfassungen Heimwerkerbedarf > Hauseinzäunung > Tore +Heimwerkerbedarf > Hauseinzäunung > Zaunfelder +Heimwerkerbedarf > Hauseinzäunung > Zaungitter Heimwerkerbedarf > Hauseinzäunung > Zaunlatten -Heimwerkerbedarf > Hauseinzäunung > Zaunpfosten -Heimwerkerbedarf > Hauseinzäunung > Zäune -Heimwerkerbedarf > Hauseinzäunung > Zäune > Drahtzaun -Heimwerkerbedarf > Hauseinzäunung > Zäune > Drahtzaun > Maschendraht -Heimwerkerbedarf > Hauseinzäunung > Zäune > Drahtzaun > Stacheldraht -Heimwerkerbedarf > Isolierung -Heimwerkerbedarf > Isolierung > Fenster- & Türisolierung -Heimwerkerbedarf > Isolierung > Gebäudeisolierung -Heimwerkerbedarf > Isolierung > Rohrisolierung -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Beschichtungen -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Dichtungsmittel -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Fugendichtmittel -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Fugenmassen -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Leime -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Leime > Glitzerkleber -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Leime > Gummikleber -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Leime > Heißklebesticks -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Leime > Holzleim -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Leime > Klebestifte -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Leime > Sekundenkleber -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Leime > Weißleim -Heimwerkerbedarf > Leime, Beschichtungen & Dichtungsmittel > Zement -Heimwerkerbedarf > Möbelbau -Heimwerkerbedarf > Sanitärinstallationen -Heimwerkerbedarf > Sanitärinstallationen > Abflusszubehör -Heimwerkerbedarf > Sanitärinstallationen > Abflusszubehör > Abflussauskleidung bzw. -Abdichtung -Heimwerkerbedarf > Sanitärinstallationen > Abflusszubehör > Abflussgitter -Heimwerkerbedarf > Sanitärinstallationen > Abflusszubehör > Abflussreinigungswerkzeug -Heimwerkerbedarf > Sanitärinstallationen > Abflusszubehör > Kanal- & Abflussstäbe -Heimwerkerbedarf > Sanitärinstallationen > Abflusszubehör > Sanitärabläufe -Heimwerkerbedarf > Sanitärinstallationen > Brunnenbedarf -Heimwerkerbedarf > Sanitärinstallationen > Druckminderer -Heimwerkerbedarf > Sanitärinstallationen > Düsen -Heimwerkerbedarf > Sanitärinstallationen > Installationsrohre -Heimwerkerbedarf > Sanitärinstallationen > Installationsrohre > Rohrnippel -Heimwerkerbedarf > Sanitärinstallationen > Installationsrohre > Stahlrohre -Heimwerkerbedarf > Sanitärinstallationen > Installationsrohre > Steckverbindungsrohre -Heimwerkerbedarf > Sanitärinstallationen > Kraftstoffleitungen & Zubehör -Heimwerkerbedarf > Sanitärinstallationen > Kugelhähne & Verschlüsse -Heimwerkerbedarf > Sanitärinstallationen > Pumpen -Heimwerkerbedarf > Sanitärinstallationen > Reparatursätze -Heimwerkerbedarf > Sanitärinstallationen > Reparatursätze > Rohr-Reparatursätze -Heimwerkerbedarf > Sanitärinstallationen > Rohrreiniger -Heimwerkerbedarf > Sanitärinstallationen > Rohrverbindungsstücke -Heimwerkerbedarf > Sanitärinstallationen > Rohrverbindungsstücke > Flansche -Heimwerkerbedarf > Sanitärinstallationen > Rohrverbindungsstücke > Rohranschlüsse & Reduzierstücke -Heimwerkerbedarf > Sanitärinstallationen > Rohrverbindungsstücke > Rohrkappen & -verschlüsse -Heimwerkerbedarf > Sanitärinstallationen > Rohrverbindungsstücke > Rohrschellen -Heimwerkerbedarf > Sanitärinstallationen > Rohrverbindungsstücke > Rohrverbinder -Heimwerkerbedarf > Sanitärinstallationen > Rohrverbindungsstücke > Sanitärdichtungen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärarmaturen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärarmaturen > Gashähne -Heimwerkerbedarf > Sanitärinstallationen > Sanitärarmaturen > Schlauchhähne -Heimwerkerbedarf > Sanitärinstallationen > Sanitärarmaturen > Wasserhähne -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Badarmaturen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Badarmaturen > Wasserhähne zum Vorspülen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Badewannen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Brauseeckventile -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Duschgriffe -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Duschkabinen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Duschkabinen & -türen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Duschköpfe -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Duschpaneele -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Duschschläuche -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Duschvorhangstangen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Duschwannen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Duschwände -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Stangenhalterungen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschen > Wasserfilter für Duschen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Halterungsplatten -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten & Bidets -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten & Bidets > Bidets -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten & Bidets > Toiletten -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten & Bidets > Urinale -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten- und Bidetzubehör -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten- und Bidetzubehör > Spülkastenabdeckungen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten- und Bidetzubehör > Spülkästen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten- und Bidetzubehör > Toilettendeckel -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten- und Bidetzubehör > Toilettensitze -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten- und Bidetzubehör > Toilettenverkleidung -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten- und Bidetzubehör > WC-Papiersitze -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten- und Bidetzubehör > WC-Spülkastengriffe -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Waschbecken & Spülen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Waschbecken & Spülen > Badezimmerwaschbecken -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Waschbecken & Spülen > Küchenspülen & Spülbecken -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Waschbecken- & Spülenzubehör -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Waschbecken- & Spülenzubehör > Waschbeckenfüße -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Zubehör für Armaturen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Zubehör für Badewannen -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Zubehör für Badewannen > Badewanneneinläufe -Heimwerkerbedarf > Sanitärinstallationen > Sanitärkeramik & Armaturen > Zubehör für Badewannen > Badewannenverkleidungen -Heimwerkerbedarf > Sanitärinstallationen > Schläuche -Heimwerkerbedarf > Sanitärinstallationen > Siphons & Siebe -Heimwerkerbedarf > Sanitärinstallationen > Siphons & Siebe > Ablaufgarnituren für Badewannen -Heimwerkerbedarf > Sanitärinstallationen > Siphons & Siebe > Ablaufgarnituren für Duschen -Heimwerkerbedarf > Sanitärinstallationen > Siphons & Siebe > Flaschensiphons -Heimwerkerbedarf > Sanitärinstallationen > Sperrventile -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Wasserdestillationsgeräte -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Wasserenthärter -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Wasserenthärtungszubehör -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Wasserenthärtungszubehör > Salz zur Wasserenthärtung -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Wasserleitungsfilter -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Wasserleitungsfilter > Wasserfilter für Kühlschränke -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Wasserspender -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Wasserspender > Trinkbrunnen -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Wasserspender > Wasserkühler -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Zubehör für Wasserfilter -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Zubehör für Wasserfilter > Wasserfiltergehäuse -Heimwerkerbedarf > Sanitärinstallationen > Trinkwasserspender & Filter > Zubehör für Wasserfilter > Wasserfilterkartuschen -Heimwerkerbedarf > Sanitärinstallationen > Ventile -Heimwerkerbedarf > Sanitärinstallationen > Ventile > Kugelhähne -Heimwerkerbedarf > Sanitärinstallationen > Wasserschaltuhren -Heimwerkerbedarf > Sanitärinstallationen > Wasserstandsregler -Heimwerkerbedarf > Sanitärinstallationen > Wärmefühler -Heimwerkerbedarf > Schlösser & Schlossereibedarf -Heimwerkerbedarf > Schlösser & Schlossereibedarf > Kartenschließsysteme -Heimwerkerbedarf > Schlösser & Schlossereibedarf > Riegelschlösser -Heimwerkerbedarf > Schlösser & Schlossereibedarf > Taschenschiebetür-Schlösser -Heimwerkerbedarf > Schlösser & Schlossereibedarf > Vorhängeschlösser -Heimwerkerbedarf > Schlösser & Schlossereibedarf > Zylinderschlösser -Heimwerkerbedarf > Schlüsselrohlinge -Heimwerkerbedarf > Taschenlampen +Heimwerkerbedarf > Hauseinzäunung > Zaunpfosten & -querlatten +Heimwerkerbedarf > Hauseinzäunung > Zubehör für Zäune & Gartentore +Heimwerkerbedarf > Heizen, Belüftung & Klimaanlagen +Heimwerkerbedarf > Heizen, Belüftung & Klimaanlagen > Filtertrockner +Heimwerkerbedarf > Heizen, Belüftung & Klimaanlagen > Luftdurchlässe & Abzugsrohre +Heimwerkerbedarf > Heizen, Belüftung & Klimaanlagen > Luftkanäle +Heimwerkerbedarf > Heizen, Belüftung & Klimaanlagen > Steuerungen +Heimwerkerbedarf > Heizen, Belüftung & Klimaanlagen > Steuerungen > Feuchtigkeitsregler +Heimwerkerbedarf > Heizen, Belüftung & Klimaanlagen > Steuerungen > Schalt- & Bedienungstafeln +Heimwerkerbedarf > Heizen, Belüftung & Klimaanlagen > Steuerungen > Thermostate +Heimwerkerbedarf > Kleinmotoren +Heimwerkerbedarf > Küchen- und Sanitärinstallationen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Brunnenbedarf +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Installationsrohre +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen > Dichtungen & O-Ringe +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen > Druckminderer +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen > Düsen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen > In der Wand verbaute Trägerleisten +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen > Rohranschlüsse & Reduzierstücke +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen > Rohrflansche +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen > Rohrkappen & -verschlüsse +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen > Rohrschellen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen > Rohrverbinder +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Rohrverbindungsstücke & -halterungen > Ventile +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitär-Reparatursätze +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Armaturen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Badewannen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Badezimmerausstattungen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Duschkabinen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten & Bidets +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten & Bidets > Bidets +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten & Bidets > Toiletten +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Toiletten & Bidets > Urinale +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Waschbecken & Spülen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Waschbecken & Spülen > Badezimmerwaschbecken +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Sanitärkeramik & Armaturen > Waschbecken & Spülen > Küchenspülen & Spülbecken +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Schläuche & Leitungen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter > Salz zur Wasserenthärtung +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter > Wasserdestillationsgeräte +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter > Wasserenthärter +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter > Wasserleitungsfilter +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter > Wasserspender +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter > Wasserspender > Trinkbrunnen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter > Wasserspender > Wasserkühler +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter > Zubehör für Wasserfilter +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter > Zubehör für Wasserfilter > Wasserfiltergehäuse +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Trinkwasserspender & Filter > Zubehör für Wasserfilter > Wasserfilterkartuschen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Wasserschaltuhren +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Wasserstandsregler +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Abflusskomponenten +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Abflusskomponenten > Abflussauskleidung bzw. -Abdichtung +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Abflusskomponenten > Abflussgitter +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Abflusskomponenten > Abflussreinigungswerkzeug +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Abflusskomponenten > Abflussstöpsel & -filter +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Abflusskomponenten > Geruchsverschlüsse +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Abflusskomponenten > Kanal- & Abflussstäbe +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Abflusskomponenten > Sanitärabläufe +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Abflüsse +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Duscharmaturen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Duscharmaturen > Badewannen- & Duschdüsen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Duscharmaturen > Duscharme & Verbindungsteile +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Duscharmaturen > Duschkabinen & -türen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Duscharmaturen > Duschköpfe +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Duscharmaturen > Duschpaneele +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Duscharmaturen > Duschwannen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Duscharmaturen > Duschwände +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Duscharmaturen > Elektrische & Powerduschen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Duscharmaturen > Wasserfilter für Duschen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Halterungsplatten +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Toiletten- und Bidetzubehör +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Toiletten- und Bidetzubehör > Bidet-Hähne & -Sprüher +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Toiletten- und Bidetzubehör > Kugelhähne & Verschlüsse +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Toiletten- und Bidetzubehör > Spülkastenabdeckungen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Toiletten- und Bidetzubehör > Spülkästen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Toiletten- und Bidetzubehör > Toilettendeckel +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Toiletten- und Bidetzubehör > Toilettensitze +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Toiletten- und Bidetzubehör > Toilettenverkleidung +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Toiletten- und Bidetzubehör > WC-Papiersitze +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Toiletten- und Bidetzubehör > WC-Spülkastengriffe +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Waschbecken- & Spülenzubehör +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Waschbecken- & Spülenzubehör > Waschbeckenfüße +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Zubehör für Armaturen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Zubehör für Armaturen > Armaturen-Griffe +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Zubehör für Armaturen > Strahlregler +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Zubehör für Badewannen +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Zubehör für Badewannen > Badewanneneinläufe +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Zubehör für Badewannen > Badewannenunterbau & -füße +Heimwerkerbedarf > Küchen- und Sanitärinstallationen > Zubehör für sanitäre Anlagen > Zubehör für Badewannen > Badewannenverkleidungen +Heimwerkerbedarf > Metallpumpen +Heimwerkerbedarf > Metallpumpen > Bewässerungs-, Sprinkler- und Boosterpumpen +Heimwerkerbedarf > Metallpumpen > Brunnenpumpen und -systeme +Heimwerkerbedarf > Metallpumpen > Haushaltsgerätepumpen +Heimwerkerbedarf > Metallpumpen > Pool-, Brunnen- und Teichpumpen +Heimwerkerbedarf > Metallpumpen > Pumpen zur Entwässerung und Wasserleitung +Heimwerkerbedarf > Metallpumpen > Sickergruben-, Abwasser- und Abflusspumpen +Heimwerkerbedarf > Schlösser & Schlüssel +Heimwerkerbedarf > Schlösser & Schlüssel > Kartenschließsysteme +Heimwerkerbedarf > Schlösser & Schlüssel > Schlösser & Riegel +Heimwerkerbedarf > Schlösser & Schlüssel > Schlüsselkappen +Heimwerkerbedarf > Schlösser & Schlüssel > Schlüsselrohlinge Heimwerkerbedarf > Vorratsbehälter -Heimwerkerbedarf > Vorratsbehälter > Nahrungsmittelbehälter -Heimwerkerbedarf > Vorratsbehälter > Wassertanks -Heimwerkerbedarf > Vorratsbehälter > Öltanks -Heimwerkerbedarf > Wandfarben & Tapeten -Heimwerkerbedarf > Wandfarben & Tapeten > Abbeizmittel -Heimwerkerbedarf > Wandfarben & Tapeten > Anstrichfarben -Heimwerkerbedarf > Wandfarben & Tapeten > Farbe -Heimwerkerbedarf > Wandfarben & Tapeten > Farbenbindemittel -Heimwerkerbedarf > Wandfarben & Tapeten > Farbstoffe -Heimwerkerbedarf > Wandfarben & Tapeten > Grundierungen -Heimwerkerbedarf > Wandfarben & Tapeten > Lacke -Heimwerkerbedarf > Wandfarben & Tapeten > Lösungsmittel -Heimwerkerbedarf > Wandfarben & Tapeten > Tapeten -Heimwerkerbedarf > Werkstatthocker Heimwerkerbedarf > Werkzeuge -Heimwerkerbedarf > Werkzeuge > Ahlen Heimwerkerbedarf > Werkzeuge > Ambosse Heimwerkerbedarf > Werkzeuge > Arbeitslampen -Heimwerkerbedarf > Werkzeuge > Arbeitslampen > Stirnlampen Heimwerkerbedarf > Werkzeuge > Arbeitsscheinwerfer -Heimwerkerbedarf > Werkzeuge > Aufzüge & Hebeeinrichtungen -Heimwerkerbedarf > Werkzeuge > Aufzüge & Hebeeinrichtungen > Bauaufzüge -Heimwerkerbedarf > Werkzeuge > Aufzüge & Hebeeinrichtungen > Hubwagen -Heimwerkerbedarf > Werkzeuge > Aufzüge & Hebeeinrichtungen > Kettenzüge -Heimwerkerbedarf > Werkzeuge > Aufzüge & Hebeeinrichtungen > Pneumatische Hebevorrichtungen -Heimwerkerbedarf > Werkzeuge > Aufzüge & Hebeeinrichtungen > Seilzüge -Heimwerkerbedarf > Werkzeuge > Aufzüge & Hebeeinrichtungen > Wagenheber Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge > Betonmischer Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge > Fugenkellen Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge > Fugenschwamm Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge > Glättkellen Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge > Glättmaschinen -Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge > Kantenwerkzeug +Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge > Kanten- & Schneidwerkzeuge Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge > Maurerkellen Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge > Maurerschnüre Heimwerkerbedarf > Werkzeuge > Bauwerkzeuge > Maurerwerkzeuge Heimwerkerbedarf > Werkzeuge > Betonbesen -Heimwerkerbedarf > Werkzeuge > Biegewerkzeuge +Heimwerkerbedarf > Werkzeuge > Biegewerkzeuge für Rohre & Stangen Heimwerkerbedarf > Werkzeuge > Bodenverdichter Heimwerkerbedarf > Werkzeuge > Bohrmaschinen Heimwerkerbedarf > Werkzeuge > Bohrmaschinen > Druckluftbohrer @@ -3219,75 +2761,56 @@ Heimwerkerbedarf > Werkzeuge > Bohrmaschinen > Schneckenbohrer Heimwerkerbedarf > Werkzeuge > Bohrmaschinen > Stemmmaschinen Heimwerkerbedarf > Werkzeuge > Bohrmaschinen > Ständerbohrmaschinen Heimwerkerbedarf > Werkzeuge > Brecheisen -Heimwerkerbedarf > Werkzeuge > Bürsten -Heimwerkerbedarf > Werkzeuge > Bürsten > Airbrushpistolen -Heimwerkerbedarf > Werkzeuge > Bürsten > Kaminbürste -Heimwerkerbedarf > Werkzeuge > Bürsten > Malerpinsel -Heimwerkerbedarf > Werkzeuge > Bürsten > Rohrbürsten Heimwerkerbedarf > Werkzeuge > Drehmaschinen -Heimwerkerbedarf > Werkzeuge > Druckluftpistolen Heimwerkerbedarf > Werkzeuge > Einziehhilfen Heimwerkerbedarf > Werkzeuge > Elektrohobel Heimwerkerbedarf > Werkzeuge > Entgrater -Heimwerkerbedarf > Werkzeuge > Fettpistolen -Heimwerkerbedarf > Werkzeuge > Formeinsätze +Heimwerkerbedarf > Werkzeuge > Fettpressen +Heimwerkerbedarf > Werkzeuge > Feuerzeuge & Streichhölzer +Heimwerkerbedarf > Werkzeuge > Gewindebohrer Heimwerkerbedarf > Werkzeuge > Gewindeschneidmaschinen Heimwerkerbedarf > Werkzeuge > Glühbirnenwechsler Heimwerkerbedarf > Werkzeuge > Griffe +Heimwerkerbedarf > Werkzeuge > Hacken & Spitzhacken +Heimwerkerbedarf > Werkzeuge > Handmischmaschinen Heimwerkerbedarf > Werkzeuge > Handwerkzeuge für Drähte und Kabel -Heimwerkerbedarf > Werkzeuge > Handwerkzeuge für Drähte und Kabel > Abisolierzangen -Heimwerkerbedarf > Werkzeuge > Handwerkzeuge für Drähte und Kabel > Drahtschneider -Heimwerkerbedarf > Werkzeuge > Handwerkzeuge für Drähte und Kabel > Kabelklemmzangen -Heimwerkerbedarf > Werkzeuge > Handwerkzeuge für Drähte und Kabel > Kabelschneider -Heimwerkerbedarf > Werkzeuge > Handwerkzeuge für Drähte und Kabel > Seitenschneider Heimwerkerbedarf > Werkzeuge > Heißluftpistole Heimwerkerbedarf > Werkzeuge > Hobel Heimwerkerbedarf > Werkzeuge > Holzspalter -Heimwerkerbedarf > Werkzeuge > Hämmern -Heimwerkerbedarf > Werkzeuge > Hämmern > Drucklufthammer -Heimwerkerbedarf > Werkzeuge > Hämmern > Elektrohammer -Heimwerkerbedarf > Werkzeuge > Hämmern > Hammer -Heimwerkerbedarf > Werkzeuge > Hämmern > Hammer > Holzhammer & Gummihammer -Heimwerkerbedarf > Werkzeuge > Hämmern > Hammer > Vorschlaghammer -Heimwerkerbedarf > Werkzeuge > Hämmern > Presslufthammer -Heimwerkerbedarf > Werkzeuge > Industriescheren +Heimwerkerbedarf > Werkzeuge > Hämmer +Heimwerkerbedarf > Werkzeuge > Hämmer > Manuelle Hämmer +Heimwerkerbedarf > Werkzeuge > Hämmer > Maschinenbetriebene Hämmer Heimwerkerbedarf > Werkzeuge > Industrievibratoren +Heimwerkerbedarf > Werkzeuge > Kaminbürste Heimwerkerbedarf > Werkzeuge > Kittmesser & -spachtel -Heimwerkerbedarf > Werkzeuge > Klebepistolen Heimwerkerbedarf > Werkzeuge > Kompressoren -Heimwerkerbedarf > Werkzeuge > Kompressoren > Gaskompressoren -Heimwerkerbedarf > Werkzeuge > Kompressoren > Luftkompressoren Heimwerkerbedarf > Werkzeuge > Kontrollspiegel Heimwerkerbedarf > Werkzeuge > Lasthebemagnete Heimwerkerbedarf > Werkzeuge > Leitern & Gerüste Heimwerkerbedarf > Werkzeuge > Leitern & Gerüste > Arbeitsplattformen Heimwerkerbedarf > Werkzeuge > Leitern & Gerüste > Gerüste Heimwerkerbedarf > Werkzeuge > Leitern & Gerüste > Leitern -Heimwerkerbedarf > Werkzeuge > Leitern & Gerüste > Leitern > Aluminiumleitern -Heimwerkerbedarf > Werkzeuge > Leitern & Gerüste > Leitern > Holzleitern Heimwerkerbedarf > Werkzeuge > Leitern & Gerüste > Leiterwagen Heimwerkerbedarf > Werkzeuge > Leitern & Gerüste > Tritthocker -Heimwerkerbedarf > Werkzeuge > Locheisen +Heimwerkerbedarf > Werkzeuge > Locheisen & Ahlen Heimwerkerbedarf > Werkzeuge > Lochschaufeln Heimwerkerbedarf > Werkzeuge > Lötkolben Heimwerkerbedarf > Werkzeuge > Malerwerkzeug +Heimwerkerbedarf > Werkzeuge > Malerwerkzeug > Airbrushpistolen Heimwerkerbedarf > Werkzeuge > Malerwerkzeug > Farbrollen -Heimwerkerbedarf > Werkzeuge > Malerwerkzeug > Farbschaber +Heimwerkerbedarf > Werkzeuge > Malerwerkzeug > Farbrüttler +Heimwerkerbedarf > Werkzeuge > Malerwerkzeug > Farbsiebe Heimwerkerbedarf > Werkzeuge > Malerwerkzeug > Farbspritzpistolen Heimwerkerbedarf > Werkzeuge > Malerwerkzeug > Farbwannen Heimwerkerbedarf > Werkzeuge > Malerwerkzeug > Kantenmaler +Heimwerkerbedarf > Werkzeuge > Malerwerkzeug > Malerpinsel Heimwerkerbedarf > Werkzeuge > Malerwerkzeug > Malschwämme Heimwerkerbedarf > Werkzeuge > Markierwerkzeuge -Heimwerkerbedarf > Werkzeuge > Markierwerkzeuge > Markiereisen -Heimwerkerbedarf > Werkzeuge > Markierwerkzeuge > Markiermesser -Heimwerkerbedarf > Werkzeuge > Markierwerkzeuge > Schlagschnüre -Heimwerkerbedarf > Werkzeuge > Markierwerkzeuge > Zimmermannsbleistifte Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Balkensucher Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Barometer -Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Diagnostische Wärmekamera -Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Drucksensoren & Wandler Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Durchflussmesser +Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Elektrische Prüfgeräte Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Entfernungsmesser Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Feuchtigkeitsmesser Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Gasdetektoren @@ -3295,43 +2818,39 @@ Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Geigerzähler Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Haarlineale Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Hygrometer Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Höhenmesser -Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Kabelprüfgeräte -Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Kabelsuchgeräte +Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Infrarotthermometer Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Kluppen Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Lautstärkemesser -Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Lecksucher Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Maßbänder Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Messerführungen Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Messinstrumente Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Messräder Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Messschieber -Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Metallsuchgeräte & Spannungsdetektoren -Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Multimeter Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Raumluftmessgeräte Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Richtwaagen Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Richtwaagen > Laser-Wasserwaagen Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Richtwaagen > Schaugläser Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Richtwaagen > Wasserwaagen -Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Rohrsuchgeräte Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Schwingungsmesser Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Seismographen Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Sonden & Suchgeräte Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Stahlbewehrungssucher Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Stangenzirkel Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Theodolite -Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Thermometer -Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Thermometer > Infrarotthermometer +Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Thermoelemente & -säulen +Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Transducer & Messumformer Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > UV-Lichtmesser Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Waagen Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Wetterstationen +Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Windgeschwindigkeitsmesser Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Winkel Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Winkelmesser +Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Wärmekameras Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > Zollstöcke Heimwerkerbedarf > Werkzeuge > Messwerkzeuge & Messwertgeber > pH-Meter Heimwerkerbedarf > Werkzeuge > Multifunktionales Elektrowerkzeug Heimwerkerbedarf > Werkzeuge > Mühlen Heimwerkerbedarf > Werkzeuge > Müll- & Papierkrallen -Heimwerkerbedarf > Werkzeuge > Müll- & Papierkrallen > Greifzangen Heimwerkerbedarf > Werkzeuge > Nageleisen Heimwerkerbedarf > Werkzeuge > Nagler & Tacker Heimwerkerbedarf > Werkzeuge > Nietwerkzeuge @@ -3339,6 +2858,8 @@ Heimwerkerbedarf > Werkzeuge > Nietwerkzeuge > Nietpistolen Heimwerkerbedarf > Werkzeuge > Nietwerkzeuge > Nietzangen Heimwerkerbedarf > Werkzeuge > Oberfräsen Heimwerkerbedarf > Werkzeuge > Reibahlen +Heimwerkerbedarf > Werkzeuge > Rohrbürsten +Heimwerkerbedarf > Werkzeuge > Rohrreiniger Heimwerkerbedarf > Werkzeuge > Rollwagen & Sackkarren Heimwerkerbedarf > Werkzeuge > Sandstrahler Heimwerkerbedarf > Werkzeuge > Saugglocken @@ -3352,87 +2873,80 @@ Heimwerkerbedarf > Werkzeuge > Schneidegeräte > Bolzenschneider Heimwerkerbedarf > Werkzeuge > Schneidegeräte > Cutter Heimwerkerbedarf > Werkzeuge > Schneidegeräte > Fliesen-, Ziegel- & Schindelschneider Heimwerkerbedarf > Werkzeuge > Schneidegeräte > Glasschneider -Heimwerkerbedarf > Werkzeuge > Schneidegeräte > Nibbelmaschinen +Heimwerkerbedarf > Werkzeuge > Schneidegeräte > Metallscheren & Nibbelmaschinen Heimwerkerbedarf > Werkzeuge > Schneidegeräte > Rohrschneider -Heimwerkerbedarf > Werkzeuge > Schneidegeräte > Zwickzange -Heimwerkerbedarf > Werkzeuge > Schnitzwerkzeuge -Heimwerkerbedarf > Werkzeuge > Schnitzwerkzeuge > Hohleisen -Heimwerkerbedarf > Werkzeuge > Schnitzwerkzeuge > Hohlmeißel -Heimwerkerbedarf > Werkzeuge > Schnitzwerkzeuge > Holzschnitzmesser -Heimwerkerbedarf > Werkzeuge > Schnitzwerkzeuge > Meißel +Heimwerkerbedarf > Werkzeuge > Schneidegeräte > Zwickzangen +Heimwerkerbedarf > Werkzeuge > Schnitzwerkzeuge & Hohlmeißel Heimwerkerbedarf > Werkzeuge > Schraubendreher -Heimwerkerbedarf > Werkzeuge > Schraubendreher > Elektrische Schraubenzieher -Heimwerkerbedarf > Werkzeuge > Schraubendreher > Handschraubenzieher Heimwerkerbedarf > Werkzeuge > Schraubenschlüssel -Heimwerkerbedarf > Werkzeuge > Schraubenschlüssel > Innensechskantschlüssel -Heimwerkerbedarf > Werkzeuge > Schraubenschlüssel > Knarren -Heimwerkerbedarf > Werkzeuge > Schweißwerkzeuge +Heimwerkerbedarf > Werkzeuge > Schraubzwingen & -stöcke +Heimwerkerbedarf > Werkzeuge > Schweißwerkzeuge & Plasmaschneider Heimwerkerbedarf > Werkzeuge > Schwingschleifer Heimwerkerbedarf > Werkzeuge > Schärfgeräte -Heimwerkerbedarf > Werkzeuge > Schärfgeräte > Schleifsteine -Heimwerkerbedarf > Werkzeuge > Schärfgeräte > Schärfgeräte für Kettensägen Heimwerkerbedarf > Werkzeuge > Steckschlüssel Heimwerkerbedarf > Werkzeuge > Stemmwerkzeuge -Heimwerkerbedarf > Werkzeuge > Stemmwerkzeuge > Fugenpistolen -Heimwerkerbedarf > Werkzeuge > Stemmwerkzeuge > Kalfateisen -Heimwerkerbedarf > Werkzeuge > Stemmwerkzeuge > Kalfathammer Heimwerkerbedarf > Werkzeuge > Stoßmaschinen Heimwerkerbedarf > Werkzeuge > Sägeböcke Heimwerkerbedarf > Werkzeuge > Sägen Heimwerkerbedarf > Werkzeuge > Sägen > Bandsägen -Heimwerkerbedarf > Werkzeuge > Sägen > Bügelsägen Heimwerkerbedarf > Werkzeuge > Sägen > Dekupiersägen Heimwerkerbedarf > Werkzeuge > Sägen > Fliesensägen Heimwerkerbedarf > Werkzeuge > Sägen > Gehrungssägen Heimwerkerbedarf > Werkzeuge > Sägen > Handkreissägen Heimwerkerbedarf > Werkzeuge > Sägen > Handsägen +Heimwerkerbedarf > Werkzeuge > Sägen > Plattensägen Heimwerkerbedarf > Werkzeuge > Sägen > Stichsägen Heimwerkerbedarf > Werkzeuge > Sägen > Säbelsägen Heimwerkerbedarf > Werkzeuge > Sägen > Tischkreissägen Heimwerkerbedarf > Werkzeuge > Sägen > Trennsägen +Heimwerkerbedarf > Werkzeuge > Taschenlampen & Stirnlampen Heimwerkerbedarf > Werkzeuge > Tischlerbänke Heimwerkerbedarf > Werkzeuge > Wasseranschluss-Nachschleifwerkzeuge Heimwerkerbedarf > Werkzeuge > Werkzeugfeilen Heimwerkerbedarf > Werkzeuge > Werkzeugmesser -Heimwerkerbedarf > Werkzeuge > Werkzeugmesser > Rigipsmesser Heimwerkerbedarf > Werkzeuge > Werkzeugschlüssel -Heimwerkerbedarf > Werkzeuge > Werkzeugschlüssel > Absperrhahn Schlüssel -Heimwerkerbedarf > Werkzeuge > Werkzeugschlüssel > Heizkörperschlüssel -Heimwerkerbedarf > Werkzeuge > Werkzeugschlüssel > Schachtdeckelheber Heimwerkerbedarf > Werkzeuge > Werkzeugsets Heimwerkerbedarf > Werkzeuge > Werkzeugsets > Elektrowerkzeug-Combo-Sets Heimwerkerbedarf > Werkzeuge > Werkzeugsets > Handwerkzeugsets -Heimwerkerbedarf > Werkzeuge > Werkzeugspanner -Heimwerkerbedarf > Werkzeuge > Werkzeugspanner > Schraubzwingen Heimwerkerbedarf > Werkzeuge > Zangen Heimwerkerbedarf > Werkzeuge > Äxte Heimwerkerbedarf > Werkzeuge > Ölfilterabfluss Heimwerkerbedarf > Werkzeugzubehör -Heimwerkerbedarf > Werkzeugzubehör > Airbrushzubehör Heimwerkerbedarf > Werkzeugzubehör > Anstreichzubehör +Heimwerkerbedarf > Werkzeugzubehör > Anstreichzubehör > Airbrushzubehör Heimwerkerbedarf > Werkzeugzubehör > Anstreichzubehör > Anstreichrollenzubehör +Heimwerkerbedarf > Werkzeugzubehör > Anstreichzubehör > Pinselreiniger Heimwerkerbedarf > Werkzeugzubehör > Axtzubehör +Heimwerkerbedarf > Werkzeugzubehör > Axtzubehör > Axtgriffe Heimwerkerbedarf > Werkzeugzubehör > Axtzubehör > Axtköpfe Heimwerkerbedarf > Werkzeugzubehör > Bohrzubehör -Heimwerkerbedarf > Werkzeugzubehör > Bohrzubehör > Bohrer +Heimwerkerbedarf > Werkzeugzubehör > Bohrzubehör > Bohrer & Bits Heimwerkerbedarf > Werkzeugzubehör > Bohrzubehör > Bohrerschleifgeräte Heimwerkerbedarf > Werkzeugzubehör > Bohrzubehör > Bohrerverlängerungen +Heimwerkerbedarf > Werkzeugzubehör > Bohrzubehör > Bohrfutter +Heimwerkerbedarf > Werkzeugzubehör > Bohrzubehör > Bohrständer & -führungen Heimwerkerbedarf > Werkzeugzubehör > Bohrzubehör > Lochsägen Heimwerkerbedarf > Werkzeugzubehör > Drehmaschinenzubehör Heimwerkerbedarf > Werkzeugzubehör > Elektrowerkzeug-Akkus Heimwerkerbedarf > Werkzeugzubehör > Hammerzubehör Heimwerkerbedarf > Werkzeugzubehör > Hammerzubehör > Drucklufthammerzubehör -Heimwerkerbedarf > Werkzeugzubehör > Hammerzubehör > Hammerkeile Heimwerkerbedarf > Werkzeugzubehör > Hammerzubehör > Hammerköpfe +Heimwerkerbedarf > Werkzeugzubehör > Hammerzubehör > Hammerstiele +Heimwerkerbedarf > Werkzeugzubehör > Keile für Werkzeuggriffe +Heimwerkerbedarf > Werkzeugzubehör > Keilwerkzeuge Heimwerkerbedarf > Werkzeugzubehör > Klammern Heimwerkerbedarf > Werkzeugzubehör > Ladegeräte für Elektrowerkzeuge Heimwerkerbedarf > Werkzeugzubehör > Magnetisierer & Entmagnetisierer -Heimwerkerbedarf > Werkzeugzubehör > Sandstrahlerzubehör -Heimwerkerbedarf > Werkzeugzubehör > Sandstrahlerzubehör > Sandstrahlkabinen +Heimwerkerbedarf > Werkzeugzubehör > Mischwerkzeuge +Heimwerkerbedarf > Werkzeugzubehör > Sandstrahler-Zubehör +Heimwerkerbedarf > Werkzeugzubehör > Sandstrahler-Zubehör > Sandstrahlkabinen +Heimwerkerbedarf > Werkzeugzubehör > Schleifmaschinenzubehör +Heimwerkerbedarf > Werkzeugzubehör > Schleifmaschinenzubehör > Schleifscheiben & -stifte Heimwerkerbedarf > Werkzeugzubehör > Schleifzubehör Heimwerkerbedarf > Werkzeugzubehör > Schleifzubehör > Schleifpapier & Schleifschwämme -Heimwerkerbedarf > Werkzeugzubehör > Schraubendreherzubehör -Heimwerkerbedarf > Werkzeugzubehör > Schraubendreherzubehör > Schraubendrehereinsätze +Heimwerkerbedarf > Werkzeugzubehör > Schneidwerkzeug-Zubehör +Heimwerkerbedarf > Werkzeugzubehör > Schneidwerkzeug-Zubehör > Nibbelmaschinenstempel +Heimwerkerbedarf > Werkzeugzubehör > Schweißzubehör Heimwerkerbedarf > Werkzeugzubehör > Spannvorrichtungen Heimwerkerbedarf > Werkzeugzubehör > Steckschlüsseleinsätze Heimwerkerbedarf > Werkzeugzubehör > Sägenzubehör @@ -3441,24 +2955,22 @@ Heimwerkerbedarf > Werkzeugzubehör > Sägenzubehör > Handkreissägen-Zubehör Heimwerkerbedarf > Werkzeugzubehör > Sägenzubehör > Kreissägenzubehör Heimwerkerbedarf > Werkzeugzubehör > Sägenzubehör > Laubsägenzubehör Heimwerkerbedarf > Werkzeugzubehör > Sägenzubehör > Tischsägenzubehör -Heimwerkerbedarf > Werkzeugzubehör > Werkzeuggriffe -Heimwerkerbedarf > Werkzeugzubehör > Werkzeuggriffe > Axtgriffe -Heimwerkerbedarf > Werkzeugzubehör > Werkzeuggriffe > Hammerstiele Heimwerkerbedarf > Werkzeugzubehör > Werkzeugklingen & -blätter +Heimwerkerbedarf > Werkzeugzubehör > Werkzeugklingen & -blätter > Cutter-, Schaber- & Spachtelklingen Heimwerkerbedarf > Werkzeugzubehör > Werkzeugklingen & -blätter > Sägeblätter -Heimwerkerbedarf > Werkzeugzubehör > Werkzeugklingen & -blätter > Teppichmesserklingen +Heimwerkerbedarf > Werkzeugzubehör > Werkzeugsicherungen Heimwerkerbedarf > Werkzeugzubehör > Werkzeugständer Heimwerkerbedarf > Werkzeugzubehör > Werkzeugständer > Sägeständer -Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Generatoren -Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Generatoren > Generator-Ersatzteile -Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Generatoren > Generatorabdeckungen +Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Hacken & Pickel +Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Hacken & Pickel > Griffe für Hacken & Pickel Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Lötkolben Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Lötkolben > Lötkolbenspitzen Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Lötkolben > Lötkolbenständer Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Messwerkzeuge & Messwertgeber Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Messwerkzeuge & Messwertgeber > Multimeter-Zubehör Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Messwerkzeuge & Messwertgeber > Zubehör für Gasdetektoren -Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Messwerkzeuge & Messwertgeber > Zubehör für Metallsuchgeräte & Spannungsdetektoren +Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Messwerkzeuge & Messwertgeber > Zubehör für Messskalen +Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Messwerkzeuge & Messwertgeber > Zubehör für Spannungsmesser Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Oberfräsen Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Oberfräsen > Oberfräsenteile Heimwerkerbedarf > Werkzeugzubehör > Zubehör für Oberfräsen > Oberfräsentische @@ -3470,16 +2982,17 @@ Kameras & Optik > Fotografie Kameras & Optik > Fotografie > Aufbewahrung für Negative & Kontaktbögen Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Belichtungsmesser -Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Blitzdiffusoren -Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Blitzdiffusoren > Kamera-Blitzdiffusoren -Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Blitzreflektoren -Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Hintergründe -Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Lichtfilter & Filterfolien Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Lichtsteuerung -Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Softboxen -Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Studioausstattung +Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Lichtsteuerung > Blitzdiffusoren +Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Lichtsteuerung > Blitzreflektoren +Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Lichtsteuerung > Lichtfilter & Filterfolien +Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Lichtsteuerung > Softboxen +Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Studio-Halterungen +Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Studiohintergründe Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Studioscheinwerfer & -blitzgeräte Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Zubehör für Belichtungsmesser +Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Zubehör für Studiobeleuchtung & Blitzgeräte +Kameras & Optik > Fotografie > Beleuchtung & Studiobedarf > Zubehör für Studioständer & -halterungen Kameras & Optik > Fotografie > Dunkelkammer Kameras & Optik > Fotografie > Dunkelkammer > Ausrüstung, Entwicklung & Verarbeitung Kameras & Optik > Fotografie > Dunkelkammer > Ausrüstung, Entwicklung & Verarbeitung > Dunkelkammerbecken @@ -3489,11 +3002,6 @@ Kameras & Optik > Fotografie > Dunkelkammer > Ausrüstung, Entwicklung & Verarbe Kameras & Optik > Fotografie > Dunkelkammer > Ausrüstung, Entwicklung & Verarbeitung > Retuschierbedarf & -zubehör Kameras & Optik > Fotografie > Dunkelkammer > Dunkelkammerleuchten Kameras & Optik > Fotografie > Dunkelkammer > Fotochemikalien -Kameras & Optik > Fotografie > Dunkelkammer > Fotochemikalien > Farbfotokits -Kameras & Optik > Fotografie > Dunkelkammer > Fotochemikalien > Fixierer -Kameras & Optik > Fotografie > Dunkelkammer > Fotochemikalien > Fotoentwickler -Kameras & Optik > Fotografie > Dunkelkammer > Fotochemikalien > Fototoner -Kameras & Optik > Fotografie > Dunkelkammer > Fotochemikalien > Stoppbäder Kameras & Optik > Fotografie > Dunkelkammer > Fotopapier Kameras & Optik > Fotografie > Dunkelkammer > Vergrößerungszubehör Kameras & Optik > Fotografie > Dunkelkammer > Vergrößerungszubehör > Dunkelkammer-Timer @@ -3501,259 +3009,259 @@ Kameras & Optik > Fotografie > Dunkelkammer > Vergrößerungszubehör > Dunkelka Kameras & Optik > Fotografie > Dunkelkammer > Vergrößerungszubehör > Fokussierhilfen Kameras & Optik > Fotografie > Dunkelkammer > Vergrößerungszubehör > Fotovergrößerer Kameras & Optik > Fotografie > Dunkelkammer > Vergrößerungszubehör > Lichtmesser +Kameras & Optik > Fotografie > Passepartouts & Aufziehmaterialien Kameras & Optik > Kamera- & Optisches Zubehör -Kameras & Optik > Kamera- & Optisches Zubehör > Kamera- & Optische Linsen -Kameras & Optik > Kamera- & Optisches Zubehör > Kamera- & Optische Linsen > Kameraobjektive -Kameras & Optik > Kamera- & Optisches Zubehör > Kamera- & Optische Linsen > Objektive für Überwachungskameras -Kameras & Optik > Kamera- & Optisches Zubehör > Kamera- & Optische Linsen > Videokamera-Objektive +Kameras & Optik > Kamera- & Optisches Zubehör > Kamera- & Video-Objektive +Kameras & Optik > Kamera- & Optisches Zubehör > Kamera- & Video-Objektive > Kameraobjektive +Kameras & Optik > Kamera- & Optisches Zubehör > Kamera- & Video-Objektive > Objektive für Überwachungskameras +Kameras & Optik > Kamera- & Optisches Zubehör > Kamera- & Video-Objektive > Videokamera-Objektive +Kameras & Optik > Kamera- & Optisches Zubehör > Kamera-Ersatzkabel Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör & Zubehör für optische Linsen -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör & Zubehör für optische Linsen > Objektiv- & Filteradapter -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör & Zubehör für optische Linsen > Objektivabdeckungen -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör & Zubehör für optische Linsen > Objektivfilter -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör & Zubehör für optische Linsen > Objektivfilter > Makrofilter -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör & Zubehör für optische Linsen > Objektivtaschen -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör & Zubehör für optische Linsen > Streulichtblenden -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör & Zubehör für optische Linsen > Telekonverter +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Bildsensoren Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Blitzhaltesysteme -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Fototasche -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Fototasche > Kamerataschen -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Fototasche > Videokamerataschen +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Digitale Rückteile +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Ersatzbildschirme & -Displays +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Ersatzgehäuseteile & -klappen +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Ersatztasten & -knöpfe +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Fokusvorrichtungen für Kameras Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kamera-Blitzgeräte Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kamera-Blitzlichtzubehör Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kamera-Fernbedienungen +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kameraausrüstungen Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kamerafilme -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kameragriffe Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kameragurte -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kamerahalterungen -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Unterwasser-Kamerahüllen -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Unterwasser-Kamerahüllen > Unterwassergehäuse für Kameras -Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Unterwasser-Kamerahüllen > Unterwassergehäuse für Videokameras +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kamerahaltegriffe +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kameramonitore +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kamerastabilisatoren und -stützen +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kamerataschen & -koffer +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Kamerazubehör-Sets +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Schalldämmung & Sound Blimps für Kameras +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Sonnenschutz für Kameras & Sucheraufsätze +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Unterwassergehäuse für Kameras und Videokameras Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Videokameraleuchten +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Zoomkomponenten für Objektive +Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Zubehör für Unterwasserkameragehäuse Kameras & Optik > Kamera- & Optisches Zubehör > Kamerazubehör > Überwachungskamera-Zubehör Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör > Fernglas- & Fernrohrzubehör -Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör > Optisches Zubehör für Nachtsichtsysteme Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör > Taschen & Koffer für optische Instrumente Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör > Wärmebildzubehör -Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör > Zubehör für Messsucher +Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör > Zubehör für Entferungsmesser Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör > Zubehör für Spektive -Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör > Zubehör für Spektive > Spektivokulare Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör > Zubehör für Teleskope Kameras & Optik > Kamera- & Optisches Zubehör > Optisches Zubehör > Zubehör für Zielfernrohre Kameras & Optik > Kamera- & Optisches Zubehör > Stative +Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Kameraobjektive +Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Kameraobjektive > Objektiv- & Filteradapter +Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Kameraobjektive > Objektivabdeckungen +Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Kameraobjektive > Objektivfilter +Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Kameraobjektive > Objektivkonverter +Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Kameraobjektive > Objektivtaschen +Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Kameraobjektive > Streulichtblenden Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Stative Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Stative > Schellen & Halterungen für Stative Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Stative > Stativaufbewahrung +Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Stative > Stativgriffe Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Stative > Stativköpfe +Kameras & Optik > Kamera- & Optisches Zubehör > Zubehör für Stative > Stativspinnen Kameras & Optik > Kameras Kameras & Optik > Kameras > Analogkameras -Kameras & Optik > Kameras > Analogkameras > Sofortbildkameras +Kameras & Optik > Kameras > Boroskope Kameras & Optik > Kameras > Digitalkameras -Kameras & Optik > Kameras > Digitalkameras > Digitale Kompaktkameras -Kameras & Optik > Kameras > Digitalkameras > Digitale Spiegelreflexkameras -Kameras & Optik > Kameras > Digitalkameras > Spiegellose Systemkameras Kameras & Optik > Kameras > Einwegkameras Kameras & Optik > Kameras > Videokameras Kameras & Optik > Kameras > Webcams Kameras & Optik > Kameras > Wildkameras Kameras & Optik > Kameras > Überwachungskameras -Kameras & Optik > Kameras > Überwachungskameras > Versteckte Kameras Kameras & Optik > Optische Geräte Kameras & Optik > Optische Geräte > Ferngläser -Kameras & Optik > Optische Geräte > Ferngläser > Operngläser Kameras & Optik > Optische Geräte > Fernrohre Kameras & Optik > Optische Geräte > Fernrohre > Spektive Kameras & Optik > Optische Geräte > Fernrohre > Teleskope +Kameras & Optik > Optische Geräte > Fernrohre > Waffenspektive & Zielfernrohre Kameras & Optik > Optische Geräte > Monokulare Kameras & Optik > Optische Geräte > Optische Entfernungsmesser Kunst & Unterhaltung +Kunst & Unterhaltung > Eintrittskarten Kunst & Unterhaltung > Hobby & Kunst -Kunst & Unterhaltung > Hobby & Kunst > Bildende Kunst -Kunst & Unterhaltung > Hobby & Kunst > Bildende Kunst > Figuren, Skulpturen & Statuen -Kunst & Unterhaltung > Hobby & Kunst > Bildende Kunst > Fotografien -Kunst & Unterhaltung > Hobby & Kunst > Bildende Kunst > Fotografien > Stock-Fotografie -Kunst & Unterhaltung > Hobby & Kunst > Bildende Kunst > Gemälde -Kunst & Unterhaltung > Hobby & Kunst > Bildende Kunst > Kartonschablonen -Kunst & Unterhaltung > Hobby & Kunst > Bildende Kunst > Mixed-Media-Kunst -Kunst & Unterhaltung > Hobby & Kunst > Bildende Kunst > Poster & Nachdrucke -Kunst & Unterhaltung > Hobby & Kunst > Bildende Kunst > Zeichnungen & Illustrationen +Kunst & Unterhaltung > Hobby & Kunst > Jonglieren Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Aufbewahrungsmöglichkeiten für Handwerk & Hobby -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Aufbewahrungsmöglichkeiten für Handwerk & Hobby > Behälter für Strick- & Häkelnadeln -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Aufbewahrungsmöglichkeiten für Handwerk & Hobby > Nähkörbe -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Aufbewahrungsmöglichkeiten für Handwerk & Hobby > Ordnungsboxen für Garn -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Bastelmagnete -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Bier & Wein selbst herstellen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Bier & Wein selbst herstellen > Bierbrauen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Bier & Wein selbst herstellen > Weinherstellung -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Blumenstecken -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Blumenstecken > Blumenklebeband -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Blumenstecken > Vasenfüller & Streudeko -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Dekorative Aufkleber -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Druckgrafik -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Druckgrafik > Siebdruck -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Druckgrafik > Siebdruck > Handroller -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Druckgrafik > Siebdruck > Siebdruck-Rakel -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Formen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Glashandwerk -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Glitzer -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Holzbearbeitung -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > JoJos aus Stoff -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Jonglieren -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kerzen- & Seifenherstellung -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kerzen- & Seifenherstellung > Dochtaufhänger -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kerzen- & Seifenherstellung > Dochte -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kränze und Gebinde -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kränze und Gebinde > Rahmen zur Kranzbindung -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Lederhandwerk -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Leinwände & Keilrahmen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Leuchtkästen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Magnetband -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Modellbau -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Modellbau > Modellbausätze -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Modellbau > Modelleisenbahn & Eisenbahnsets -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Modellbau > Modelleisenbahnzubehör -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Modellbau > Modellraketen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Moosgummi & Styropor -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Mosaike -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Mosaike > Mosaikbausätze -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Fasernweberei-Muster -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Fasernweberei-Muster > Kreuzstich- und Stickmuster -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Fasernweberei-Muster > Nähmuster -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Fasernweberei-Muster > Strick- & Häkelmuster -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Filzen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Filzen > Filzformen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Filzen > Filznadeln -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Filzen > Filzpolster & -matten -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Faden- & Garnführer -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Faden- & Garnspulen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Faden- & Garnwickler -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Fadenabschneider -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Fingerhüte -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Flicksets -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Herstellungs-Sets für Jo-Jos -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Herstellungs-Sets für Pompons & Schleifen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Kardierer -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Maschenmarkierer & -zähler -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Nadeleinfädler -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Nadelkissen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Nahttrenner -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Nähnadeln -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Schablonen für Stoff-Zuschneidemaschinen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Schneiderpuppen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Sicherheitsnadeln -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Spanndrähte -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Spannmatten -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Stecknadeln -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Stoff-Zuschneidemaschinen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Stoffscheren -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Textilkleber -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Textilkleber > Schmucksteinkleber -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Textilkleber > Textilklebeband -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Textilkunst-Messgeräte -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Textilkunst-Rahmen, -Reifen & -Spannvorrichtungen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Textilmarker -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Geräte & Zubehör für Textilkunst > Webmaschinen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Gobelinstickerei -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Gobelinstickerei > Gobelinstickerei-Sets -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Gobelinstickerei > Leinwand für Gobelinstickerei -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Häkeln -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Häkeln > Häkelgarne -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Häkeln > Häkelnadeln -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Kreuzstich -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Quilten -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Spinnen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Spinnen > Handspindeln -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Spinnen > Spinnräder -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Spinnen > Spinnzubehör -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Spitze & Borten -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Stricken -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Stricken > Stricknadeln -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Aufnäher -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Druckknöpfe -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Elastikbund -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Füllmaterial -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Garne -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Klettverschlüsse -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Knöpfe -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Plastiksegeltuch -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Reißverschlüsse -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Rohwolle -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Stoffe -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Textilaufnäher- und aufbügler -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Textilfarben -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Textilfärbemittel -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Vlieseline -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Textilkunst-Verbrauchsmaterialien > Zwirn -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Weben -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Weben > Haken für Locker-Hooking -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Weben > Webschlagkämme -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Nähen, Häkeln, Stricken & Sticken > Weben > Webschützen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Pailletten -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papier -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papier > Aquarellpapier -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papier > Bastelpapier -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papier > Origami-Papier -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papier > Pauspapier -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papier > Pergament -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papier > Skizzenblöcke -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papier > Tonpapier & Karton -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papier > Transferpapier -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papierkunst -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papierkunst > Kartenbastelsets -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papierkunst > Prägen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papierkunst > Prägen > Prägemappen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papierkunst > Prägen > Prägemaschinen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papierkunst > Prägen > Prägepuder -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papierkunst > Prägen > Prägestempel -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papierkunst > Prägen > Prägestifte -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papierkunst > Prägen > Werkzeuge zum Prägen mit Hitze -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Papierkunst > Rill- und Perforiergeräte für Papier -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Pfeifenreiniger -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Schablonenkunst -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Schablonenkunst > Schablonen & Matrizen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Schablonenkunst > Schablonendruckmaschinen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Schmuckherstellung -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Schmuckherstellung > Perlen -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Schmuckherstellung > Schmuck- & Perlenband -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Schmuckherstellung > Schmuck- & Perlendraht -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Schmuckherstellung > Schmuck-Basisteile -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Scrapbooking -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Sets für die Räucherwerkherstellung -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Stempeln -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Stempeln > Lederstempel & Sets -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Stempeln > Metallstempel & Sets -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Strass -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Töpferei & Bildhauerei -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Töpferei & Bildhauerei > Modellierton & Modelliermasse -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Uhrreparatursätze -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Vordrucke -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Vorlagen für Perlenarbeiten -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zauberbedarf -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zeichnen & Malerei -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zeichnen & Malerei > Künstlerpinsel -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zeichnen & Malerei > Malerei -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zeichnen & Malerei > Malerei > Farbpaletten -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zeichnen & Malerei > Malerei > Künstlerfarben -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zeichnen & Malerei > Malerei > Malgründe -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zeichnen & Malerei > Malerei > Palettenmesser -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zeichnen & Malerei > Skizzieren -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zeichnen & Malerei > Skizzieren > Zeichenzirkel -Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zeichnen & Malerei > Zeichen- & Malsets +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Aufbewahrung für Kunst- & Bastelmaterial +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Aufbewahrung für Kunst- & Bastelmaterial > Arbeitssets für Näh- und Textilkunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Aufbewahrung für Kunst- & Bastelmaterial > Aufbewahrung für Fäden & Garne +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Aufbewahrung für Kunst- & Bastelmaterial > Aufbewahrung für Näh-, Strick- & Häkelnadeln +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Basteldraht +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Basteldraht > Blumendraht +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Basteldraht > Pfeifenreiniger +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Basteldraht > Schmuck- & Perlendraht +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelfarben, -tinten & -lacke +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelfarben, -tinten & -lacke > Fixative +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelfarben, -tinten & -lacke > Färbemittel für Kunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelfarben, -tinten & -lacke > Keramik- & Tonglasuren +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelfarben, -tinten & -lacke > Kunst- & Bastelfarben +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelfarben, -tinten & -lacke > Malgründe +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelfarben, -tinten & -lacke > Stempelkissen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelfarben, -tinten & -lacke > Tinte für Kunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelklebstoffe & -magnete +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelklebstoffe & -magnete > Aufbügelbänder +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelklebstoffe & -magnete > Bastel- & Büroklebstoff +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelklebstoffe & -magnete > Bastelmagnete +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelklebstoffe & -magnete > Blumenklebeband +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelklebstoffe & -magnete > Deko-Klebeband +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelwerkstoffe +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelwerkstoffe > Garne +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelwerkstoffe > Rohwolle +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelwerkstoffe > Schmuck- & Perlenband +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Bastelwerkstoffe > Zwirn +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Befestigungen & Verschlüsse +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Befestigungen & Verschlüsse > Klettverschlüsse +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Befestigungen & Verschlüsse > Knöpfe +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Befestigungen & Verschlüsse > Reißverschlussziehgriffe +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Befestigungen & Verschlüsse > Reißverschlüsse +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Befestigungen & Verschlüsse > Schnallen & Haken +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Befestigungen & Verschlüsse > Ösen & Tüllen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Dochte +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Dochthalter +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Formen & Rohlinge für Kunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Formen & Rohlinge für Kunstarbeiten > Holz & Formen für Kunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Formen & Rohlinge für Kunstarbeiten > Kranz- & Gesteckunterlagen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Formen & Rohlinge für Kunstarbeiten > Moosgummi & Styropor +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Formen & Rohlinge für Kunstarbeiten > Pappmaschee-Formen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Füllmaterial +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Füllmaterial > Füllgranulate +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Füllmaterial > Kissenformen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Füllmaterial > Wattierung & Füllung +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Leder & Vinyl +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Papier für Kunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Papier für Kunstarbeiten > Bastelfolie +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Papier für Kunstarbeiten > Bastelpapier +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Papier für Kunstarbeiten > Kartenkarton & Scrapbooking-Papier +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Papier für Kunstarbeiten > Origami-Papier +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Papier für Kunstarbeiten > Pergament +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Papier für Kunstarbeiten > Transferpapier +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Papier für Kunstarbeiten > Zeichen- & Malpapier +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Prägepuder +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Rohes Kerzenwachs +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Textilien +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Textilien > Bastelleinwände +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Textilien > Bastelleinwände > Leinwände & Keilrahmen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Textilien > Bastelleinwände > Plastiksegeltuch +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Textilien > Bastelleinwände > Stickleinwände +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Textilien > Bedruckbare Gewebe +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Textilien > Stoffe +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Textilien > Vlieseline +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Töpferei & Bildhauerei +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Töpferei & Bildhauerei > Engoben +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Töpferei & Bildhauerei > Gipsgewebe +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Töpferei & Bildhauerei > Modellierton & Modelliermasse +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Töpferei & Bildhauerei > Pappmaschee-Mischungen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Aufnäher +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Bänder & Einfassungen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Deko-Federn +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Dekorative Aufkleber +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Edelsteine +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Elastikbund +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Pailletten & Glitzer +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Perlen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Schleifen & Rosetten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Schmuck-Basisteile +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Strass & Deko-Elemente +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelmaterialien > Verzierungen & Trimmungen > Textilaufnäher & -aufbügler +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelsets +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelsets > Bastelsets +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelsets > Flicksets +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelsets > Kerzenherstellungssets +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelsets > Mosaikbausätze +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelsets > Schmuckherstellungssets +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelsets > Scrapbooking- & Stempelsets +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelsets > Sets für die Räucherwerkherstellung +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelsets > Sticksets +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelsets > Zeichen- & Malsets +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Dekorationswerkzeuge für Kunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Farbmischwerkzeuge +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Farbmischwerkzeuge > Farbpaletten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Farbmischwerkzeuge > Palettenmesser +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Filzpolster & -matten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Fingerhüte +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Klebepistolen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Leuchtkästen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Maschinen für Textilarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Maschinen für Textilarbeiten > Filznadeln & -maschinen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Maschinen für Textilarbeiten > Handwebstühle +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Maschinen für Textilarbeiten > Mechanische Webstühle +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Maschinen für Textilarbeiten > Nähmaschinen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Maschinen für Textilarbeiten > Spinnräder +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten > Handroller +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten > Holzbrennwerkzeuge +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten > Künstlerpinsel +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten > Maschenmarkierer & -zähler +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten > Motivstempel +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten > Schablonen & Matrizen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten > Schablonendruckmaschinen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten > Siebdruck-Rakel +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten > Textilkunst-Messgeräte +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Mess- & Markierwerkzeuge für Kunstarbeiten > Zeichenzirkel +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Näh-, Strick- & Häkelnadeln +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Näh-, Strick- & Häkelnadeln > Häkelnadeln +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Näh-, Strick- & Häkelnadeln > Knüpfhaken +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Näh-, Strick- & Häkelnadeln > Nähmaschinennadeln +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Näh-, Strick- & Häkelnadeln > Nähnadeln +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Näh-, Strick- & Häkelnadeln > Stricknadeln +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Rahmen, Reifen & Spannvorrichtungen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Schneidematten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Schneiderpuppen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Sicherheitsnadeln +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Spanndrähte +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Spannmatten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Stanz- & Prägewerkzeuge für Kunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Stanz- & Prägewerkzeuge für Kunstarbeiten > Bastel- & Büroscheren +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Stanz- & Prägewerkzeuge für Kunstarbeiten > Bastelmesser +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Stanz- & Prägewerkzeuge für Kunstarbeiten > Fadenabschneider +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Stanz- & Prägewerkzeuge für Kunstarbeiten > Heißluftgeräte +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Stanz- & Prägewerkzeuge für Kunstarbeiten > Nahttrenner +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Stanz- & Prägewerkzeuge für Kunstarbeiten > Prägestifte +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Stanz- & Prägewerkzeuge für Kunstarbeiten > Rill- & Perforiergeräte für Papier +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Stanz- & Prägewerkzeuge für Kunstarbeiten > Stanzer & Präger für Kunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Stecknadeln +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Werkzeuge für die Faden- & Garnverarbeitung +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Werkzeuge für die Faden- & Garnverarbeitung > Faden- & Garnführer +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Werkzeuge für die Faden- & Garnverarbeitung > Faden- & Garnspulen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Werkzeuge für die Faden- & Garnverarbeitung > Faden- & Garnwickler +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Werkzeuge für die Faden- & Garnverarbeitung > Handspindeln +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Werkzeuge für die Faden- & Garnverarbeitung > Kardierer +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Werkzeuge für die Faden- & Garnverarbeitung > Nadeleinfädler +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Werkzeuge für die Faden- & Garnverarbeitung > Webschlagkämme +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Kunst- & Bastelwerkzeuge > Werkzeuge für die Faden- & Garnverarbeitung > Webschützen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Muster & Formen für Kunstarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Muster & Formen für Kunstarbeiten > Filzformen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Muster & Formen für Kunstarbeiten > Gießformen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Muster & Formen für Kunstarbeiten > Nähmuster +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Muster & Formen für Kunstarbeiten > Stick-, Strick- & Häkelmuster +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Muster & Formen für Kunstarbeiten > Vorlagen für Perlenarbeiten +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zubehör für Kunst- & Bastelwerkzeuge +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zubehör für Kunst- & Bastelwerkzeuge > Ersatzteile für Nähmaschinen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zubehör für Kunst- & Bastelwerkzeuge > Klingen für Bastelmesser +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zubehör für Kunst- & Bastelwerkzeuge > Nähmaschinenfüße +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zubehör für Kunst- & Bastelwerkzeuge > Nähmaschinengehäuse & -abdeckungen +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zubehör für Kunst- & Bastelwerkzeuge > Spinnzubehör +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zubehör für Kunst- & Bastelwerkzeuge > Stempelblöcke +Kunst & Unterhaltung > Hobby & Kunst > Kunsthandwerk & Hobby > Zubehör für Kunst- & Bastelwerkzeuge > Verlängerungstische für Nähmaschinen +Kunst & Unterhaltung > Hobby & Kunst > Modellbau +Kunst & Unterhaltung > Hobby & Kunst > Modellbau > Modellbausätze +Kunst & Unterhaltung > Hobby & Kunst > Modellbau > Modelleisenbahn & Eisenbahnsets +Kunst & Unterhaltung > Hobby & Kunst > Modellbau > Modelleisenbahnzubehör +Kunst & Unterhaltung > Hobby & Kunst > Modellbau > Modellraketen Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Akkordeons & Konzertinas Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Alt- & Baritonhörner Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Euphonien -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Flügelhörner -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Kornette -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Mellophone Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Posaunen -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Sousaphone -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Trompeten +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Trompeten & Kornetts Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Tubas Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Blechblasinstrumente > Waldhörner Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Dudelsäcke @@ -3767,15 +3275,14 @@ Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Blockflöten Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Fagotte Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Flöten -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Flöten > Schwegelpfeifen Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Kinderflöten Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Klarinetten +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Längsflöten & Panflöten Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Maultrommeln Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Melodicas Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Mundharmonikas Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Oboen Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Okarinas -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Panflöten Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Saxophone Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Holzblasinstrumente > Zugpfeife Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Klaviere @@ -3783,9 +3290,6 @@ Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Saiteninstrumente Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Saiteninstrumente > Bratschen Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Saiteninstrumente > Cellos Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Saiteninstrumente > Gitarren -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Saiteninstrumente > Gitarren > Akustikgitarren -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Saiteninstrumente > Gitarren > Bassgitarren -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Saiteninstrumente > Gitarren > Elektrische Gitarren Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Saiteninstrumente > Harfen Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Saiteninstrumente > Kontrabässe Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Saiteninstrumente > Violinen @@ -3797,22 +3301,21 @@ Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Gl Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Gongs Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Finger- & Handzimbeln -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Handglocken Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Handschellen & -glocken +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Handtrommeln +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Handtrommeln > Beckentrommeln +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Handtrommeln > Bongos +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Handtrommeln > Cajons +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Handtrommeln > Congas +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Handtrommeln > Rahmentrommeln +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Handtrommeln > Sprechtrommeln +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Handtrommeln > Tablas Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Holzblöcke -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Kasagnetten +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Kastagnetten Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Kuhglocken Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Rasseln -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Scraper +Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Scraper & Schnarren Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Tamburine -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Tamburins -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Tamburins > Beckentrommel -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Tamburins > Bongos -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Tamburins > Cajons -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Tamburins > Congas -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Tamburins > Sprechtrommeln -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Tamburins > Tablas -Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Tamburins > Tympanons Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Triangeln Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Handperkussionsinstrumente > Vibraslaps Kunst & Unterhaltung > Hobby & Kunst > Musikinstrumente > Schlaginstrumente > Hi-Hats @@ -3828,13 +3331,11 @@ Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Modellbau-Zubehör Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Münzen & Währungen Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Retro-Werbung Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammelkarten -Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammelkarten > Sport-Sammelkarten -Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammelkarten > Sport-Sammelkarten > American Football-Sammelkarten -Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammelkarten > Sport-Sammelkarten > Baseball-Sammelkarten -Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammelkarten > Sport-Sammelkarten > Basketball-Sammelkarten -Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammelkarten > Sport-Sammelkarten > Fußball-Sammelkarten -Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammelkarten > Sport-Sammelkarten > Hockey-Sammelkarten -Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammelkarten > Sport-Sammelkarten > Rennsport-Sammelkarten +Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammlerwaffen +Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammlerwaffen > Dekowaffen +Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammlerwaffen > Sammlermesser +Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammlerwaffen > Schwerter +Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sammlerwaffen > Schwertständer & Schwerthalter Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sport-Fanartikel Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sport-Fanartikel > American Football-Fanartikel @@ -3848,84 +3349,78 @@ Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sp Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sportartikel mit Autogramm > American Football-Artikel mit Autogramm Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sportartikel mit Autogramm > Baseball- & Softballartikel mit Autogramm Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sportartikel mit Autogramm > Basketballartikel mit Autogramm +Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sportartikel mit Autogramm > Boxartikel mit Autogramm Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sportartikel mit Autogramm > Fußballartikel mit Autogramm Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sportartikel mit Autogramm > Hockeyartikel mit Autogramm Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sportartikel mit Autogramm > Rennsportartikel mit Autogramm Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Sport-Sammelobjekte > Sportartikel mit Autogramm > Tennisartikel mit Autogramm Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Steine & Fossilien Kunst & Unterhaltung > Hobby & Kunst > Sammlerstücke > Stempelsiegel +Kunst & Unterhaltung > Hobby & Kunst > Zauberbedarf +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Bier- & Weinherstellung +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Bier- & Weinherstellung > Abfüllflaschen +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Bier- & Weinherstellung > Brauzutaten +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Bier- & Weinherstellung > Sets zum Selbstherstellen von Bier & Wein +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Bier- & Weinherstellung > Weinherstellung Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Keyboardzubehör Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Keyboardzubehör > Keyboardständer Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Keyboardzubehör > Keyboardtaschen Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Keyboardzubehör > Sustain-Pedale -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Klavierzubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Klavierzubehör > Klavierbänke +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Klavierbänke & Musikerhocker +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Marschgabeln und Notenhalter +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Metronome Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Notenständer Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Dämpfer für Schlagzeug & Becken -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Elektronische Schlagzeugmodule +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Module für elektronische Schlagzeuge Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Schlagzeug-Hardware Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Schlagzeug-Hardware > Beater Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Schlagzeug-Hardware > Fußmaschinen Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Schlagzeug-Hardware > Schlagzeughalterungen Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Schlagzeugfelle -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Schlagzeughocker Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Schlagzeugkoffer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Schlagzeugstockzubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Schlagzeugstockzubehör > Taschen für Schlagzeugstöcke +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Sticks & Besen Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Stimmschlüssel Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Ständer für Perkussionsinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Trommelschlägel -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Trommelstöcke Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Zubehör für Handperkussionsinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Zubehör für Handperkussionsinstrumente > Ständer für Handperkussionsinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Zubehör für Handperkussionsinstrumente > Taschen für Handperkussionsinstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Zubehör für Sticks & Besen +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Schlagzeugzubehör > Zubehör für Sticks & Besen > Taschen für Sticks & Besen Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Stimmgeräte Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Ständer für Musikinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Ständer für Musikinstrumente > Beleuchtung für Instrumentenständer Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Ständer für Musikinstrumente > Notenklemmen Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Ständer für Musikinstrumente > Taschen für Instrumentenständer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Ständer für Verstärker +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Taktstöcke Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Verstärker für Musikinstrumente -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Verstärkergehäuse +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Verstärkerzubehör +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Verstärkerzubehör > Ständer für Verstärker +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Verstärkerzubehör > Verstärker-Fußschalter +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Verstärkerzubehör > Verstärkerabdeckungen +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Verstärkerzubehör > Verstärkergehäuse +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Verstärkerzubehör > Verstärkerknöpfe +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Verstärkerzubehör > Verstärkerröhren Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Aufhängungen & Ständer für Blechinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Blechblasinstrumentenpflege &-reinigung -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Blechblasinstrumentenpflege &-reinigung > Bürsten, Reinigungsspiralen & Putzstöcke für Blechblasinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Blechblasinstrumentenpflege &-reinigung > Klappenöl für Blechblasinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Blechblasinstrumentenpflege &-reinigung > Pflegesets für Blechblasinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Blechblasinstrumentenpflege &-reinigung > Poliertücher für Blechblasinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Blechblasinstrumentenpflege &-reinigung > Reinigungs- & Desinfektionsmittel für Blechblasinstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Blechblasinstrumentenpflege &-reinigung > Reinigungswerkzeug für Blechblasinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Blechblasinstrumentenpflege &-reinigung > Schutzvorrichtungen für Blechblasinstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Dämpfer für Blechinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Ersatzteile für Blechblasinstrumente -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Euphoniumzubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Euphoniumzubehör > Dämpfer für Euphonien -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Euphoniumzubehör > Euphoniummundstücke -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Euphoniumzubehör > Euphoniumständer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Euphoniumzubehör > Koffer & Transporttaschen für Euphonien -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Posaunenzubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Posaunenzubehör > Dämpfer für Posaunen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Posaunenzubehör > Koffer & Transporttaschen für Posaunen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Posaunenzubehör > Posaunenmarschgabeln -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Posaunenzubehör > Posaunenmundstücke -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Posaunenzubehör > Posaunenständer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Trompeten- & Hornzubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Trompeten- & Hornzubehör > Dämpfer für Trompeten & Hörner -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Trompeten- & Hornzubehör > Koffer & Transporttaschen für Trompeten -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Trompeten- & Hornzubehör > Trompeten- & Hornmarschgabeln -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Trompeten- & Hornzubehör > Trompeten- & Hornmundstücke -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Trompeten- & Hornzubehör > Trompeten- & Hornständer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Tubazubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Tubazubehör > Dämpfer für Tubas -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Tubazubehör > Koffer & Transporttaschen für Tubas -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Tubazubehör > Tubamundstücke -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Tubazubehör > Tubaständer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Waldhornzubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Waldhornzubehör > Dämpfer für Waldhörner -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Waldhornzubehör > Koffer & Transporttaschen für Waldhörner -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Waldhornzubehör > Waldhornmundstücke -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Waldhornzubehör > Waldhornständer +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Koffer & Gigbags für Blechinstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Blechblasinstrumente > Mundstücke für Blechinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Blockflötenzubehör +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Blockflötenzubehör > Blockflötenkoffer +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Blockflötenzubehör > Blockflötenteile +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Blockflötenzubehör > Pflege- & Reinigungsmittel für Blockflöten Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Blätteretui für Holzblasinstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Fagottblattmesser Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Fagottzubehör @@ -3940,7 +3435,6 @@ Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Fagottzubehör > Koffer & Transporttaschen für Fagotte Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Flötenzubehör Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Flötenzubehör > Flötenhalter & -ständer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Flötenzubehör > Flötenmarschgabeln Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Flötenzubehör > Flötenpflege & -reinigung Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Flötenzubehör > Flötenpflege & -reinigung > Flötenpflegesets Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Flötenzubehör > Flötenpflege & -reinigung > Flötenreinigungsstab @@ -3953,7 +3447,6 @@ Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Klarinettenzubehör > Blattschrauben & Kappen für Klarinetten Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Klarinettenzubehör > Klarinettenblätter Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Klarinettenzubehör > Klarinettenhalter/-ständer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Klarinettenzubehör > Klarinettenmarschgabeln Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Klarinettenzubehör > Klarinettenpflege &-reinigung Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Klarinettenzubehör > Klarinettenpflege &-reinigung > Klarinettenklappenschutz Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Klarinettenzubehör > Klarinettenpflege &-reinigung > Klarinettenpflegesets @@ -3985,7 +3478,6 @@ Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Zubehör für Saxophone > Koffer & Transporttaschen für Saxophone Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Zubehör für Saxophone > Rohrblätter für Saxophone Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Zubehör für Saxophone > Saxophonhalter & -ständer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Zubehör für Saxophone > Saxophonmarschgabeln Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Zubehör für Saxophone > Saxophonpflege &-reinigung Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Zubehör für Saxophone > Saxophonpflege &-reinigung > Saxophonklappenschutz Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Zubehör für Saxophone > Saxophonpflege &-reinigung > Saxophonpflegesets @@ -3996,77 +3488,61 @@ Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Zubehör für Saxophone > Saxophonteile > Mundstücke für Saxophone Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Holzblasinstrumente > Zubehör für Saxophone > Saxophonteile > Saxophonhälse Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Cellozubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Cellozubehör > Cellobögen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Cellozubehör > Cellokoffer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Cellozubehör > Cellosaiten -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Cellozubehör > Dämpfer für Cellos Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarren-Slides Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarrenbefeuchter +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarrengurte Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarrenkoffer & -taschen Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarrenplektren Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarrensaiten -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarrenstimmgeräte +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarrensaitenspanner +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarrenstimmwirbel Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarrenständer +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Gitarrenzubehör & -teile Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Kapodaster -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Stegstifte für Gitarren Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Tonabnehmer für Akustikgitarren Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Gitarrenzubehör > Tonabnehmer für E-Gitarren -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Harfenzubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Harfenzubehör > Harfenkoffer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Harfenzubehör > Harfensaiten -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Kontrabasszubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Kontrabasszubehör > Dämpfer für Kontrabässe -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Kontrabasszubehör > Kontrabassbögen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Kontrabasszubehör > Kontrabasskoffer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Kontrabasszubehör > Kontrabasssaiten Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Saiteninstrumentenpflege &-reinigung Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Saiteninstrumentenpflege &-reinigung > Bogenharz Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Saiteninstrumentenpflege &-reinigung > Politur für Saiteninstrumente Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Saiteninstrumentenpflege &-reinigung > Reinigungstücher für Saiteninstrumente -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violazubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violazubehör > Dämpfer für Violas -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violazubehör > Violabögen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violazubehör > Violakoffer -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violazubehör > Violasaiten -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör > Dämpfer für Violinen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör > Kinnhalter für Violinen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör > Saitenhalter für Violinen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör > Schulterstützen für Violinen & Bratschen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör > Stimmwirbel für Violinen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör > Tonabnehmer für Violinen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör > Violinbögen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör > Violinenkoffer & -taschen -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör > Violinensaiten -Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Violinenzubehör > Violinenstege +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Zubehör für Streichinstrumente & Harfen +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Zubehör für Streichinstrumente & Harfen > Bogenkästen für Streichinstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Zubehör für Streichinstrumente & Harfen > Bögen für Saiteninstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Zubehör für Streichinstrumente & Harfen > Dämpfer für Saiteninstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Zubehör für Streichinstrumente & Harfen > Koffer für Saiteninstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Zubehör für Streichinstrumente & Harfen > Saiten für Saiteninstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Zubehör für Streichinstrumente & Harfen > Ständer für Saiteninstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Zubehör für Streichinstrumente & Harfen > Tonabnehmer für Saiteninstrumente +Kunst & Unterhaltung > Hobby & Kunst > Zubehör für Musikinstrumente > Zubehör für Saiteninstrumente > Zubehör für Streichinstrumente & Harfen > Zubehör & Ersatzteile für Saiteninstrumente Kunst & Unterhaltung > Party & Feiern Kunst & Unterhaltung > Party & Feiern > Partyzubehör Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Antwortkarten -Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Antwortkarten > Antwortkarten für die Hochzeit +Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Aufblasbare Partydeko Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Ballon-Sets Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Banner Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Briefsiegel Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Cocktaildekorationen +Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Dekorative Pompons Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Einladungskarten -Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Einladungskarten > Geburtstagseinladungen -Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Einladungskarten > Hochzeitseinladungen Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Eventprogramme +Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Feuerwerkskörper Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Geburtstagskerzen -Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Getränkekühler -Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Kartons & andere Behältnisse für Hochzeitskarten +Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Halter für Karten zu besonderen Anlässen Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Konfetti Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Luftballons -Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Luftschlangen Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Luftschlangenspray Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Partyartikel Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Partyartikel > Kleine Geschenke für Hochzeitsgäste +Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Partygirlanden & -vorhänge Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Partyhüte Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Partyspiele +Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Partyzubehörsets Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Piñatas Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Platzkarten Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Platzkartenhalter +Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Spruchkarten +Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Stuhlbezüge Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Trinkhalme & Rührer Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Trinkspiele Kunst & Unterhaltung > Party & Feiern > Partyzubehör > Trinkspiele > Bierpong @@ -4079,10 +3555,10 @@ Kunst & Unterhaltung > Party & Feiern > Schenken > Befestigungsnadeln für Anste Kunst & Unterhaltung > Party & Feiern > Schenken > Frische Schnittblumen Kunst & Unterhaltung > Party & Feiern > Schenken > Geschenkgutscheine Kunst & Unterhaltung > Party & Feiern > Schenken > Geschenkverpackungen +Kunst & Unterhaltung > Party & Feiern > Schenken > Geschenkverpackungen > Geschenkanhänger Kunst & Unterhaltung > Party & Feiern > Schenken > Geschenkverpackungen > Geschenkboxen & -dosen Kunst & Unterhaltung > Party & Feiern > Schenken > Geschenkverpackungen > Geschenkpapier Kunst & Unterhaltung > Party & Feiern > Schenken > Geschenkverpackungen > Geschenktaschen -Kunst & Unterhaltung > Party & Feiern > Schenken > Geschenkverpackungen > Schleifen & Bänder Kunst & Unterhaltung > Party & Feiern > Schenken > Geschenkverpackungen > Seidenpapier Kunst & Unterhaltung > Party & Feiern > Schenken > Grußkarten Kunst & Unterhaltung > Party & Feiern > Trophäen & Preise @@ -4091,73 +3567,22 @@ Kunst & Unterhaltung > Party & Feiern > Visuelle Effekte > Diskokugeln Kunst & Unterhaltung > Party & Feiern > Visuelle Effekte > Lichteffektbeleuchtung Kunst & Unterhaltung > Party & Feiern > Visuelle Effekte > Lichtmischpulte Kunst & Unterhaltung > Party & Feiern > Visuelle Effekte > Nebelmaschinen +Kunst & Unterhaltung > Party & Feiern > Visuelle Effekte > Ständer für Lichteffektbeleuchtung Medien +Medien > Baupläne für Tischler- und Holzarbeiten Medien > Bücher -Medien > Bücher > Belletristik -Medien > Bücher > Belletristik > Comics -Medien > Bücher > Belletristik > Horrorromane -Medien > Bücher > Belletristik > Kinderbücher -Medien > Bücher > Belletristik > Kriminalromane -Medien > Bücher > Belletristik > Liebesromane -Medien > Bücher > Belletristik > Literatur -Medien > Bücher > Belletristik > Science Fiction- & Fantasy-Romane -Medien > Bücher > Sachliteratur -Medien > Bücher > Sachliteratur > Architekturbücher -Medien > Bücher > Sachliteratur > Biografien -Medien > Bücher > Sachliteratur > Business- & Wirtschaftsbücher -Medien > Bücher > Sachliteratur > Bücher zu Bildung & Erziehung -Medien > Bücher > Sachliteratur > Bücher zu Bildung & Erziehung > Fremdsprachenbücher -Medien > Bücher > Sachliteratur > Bücher zu Bildung & Erziehung > Lernhilfen -Medien > Bücher > Sachliteratur > Bücher zu Handwerk, Hobby & Beschäftigung -Medien > Bücher > Sachliteratur > Bücher zu Körper, Geist & Seele -Medien > Bücher > Sachliteratur > Bücher zum Verkehrswesen -Medien > Bücher > Sachliteratur > Bücher über wahre Kriminalfälle -Medien > Bücher > Sachliteratur > Computerbücher -Medien > Bücher > Sachliteratur > Familienratgeber -Medien > Bücher > Sachliteratur > Fotografiebücher -Medien > Bücher > Sachliteratur > Gartenbücher -Medien > Bücher > Sachliteratur > Geschichtsbücher -Medien > Bücher > Sachliteratur > Gesundheits- & Fitnessbücher -Medien > Bücher > Sachliteratur > Haustierratgeber -Medien > Bücher > Sachliteratur > Heimwerkerbücher -Medien > Bücher > Sachliteratur > Humorvolle Bücher -Medien > Bücher > Sachliteratur > Kochbücher -Medien > Bücher > Sachliteratur > Kunstbücher -Medien > Bücher > Sachliteratur > Literaturwissenschaften -Medien > Bücher > Sachliteratur > Malbücher -Medien > Bücher > Sachliteratur > Mathematikbücher -Medien > Bücher > Sachliteratur > Medizinische Bücher -Medien > Bücher > Sachliteratur > Musikbücher -Medien > Bücher > Sachliteratur > Nachschlagewerke -Medien > Bücher > Sachliteratur > Performance-Kunst-Bücher -Medien > Bücher > Sachliteratur > Philosophiebücher -Medien > Bücher > Sachliteratur > Poesie -Medien > Bücher > Sachliteratur > Politikwissenschaftliche Bücher -Medien > Bücher > Sachliteratur > Psychologiebücher -Medien > Bücher > Sachliteratur > Rechtsbücher -Medien > Bücher > Sachliteratur > Reiseliteratur -Medien > Bücher > Sachliteratur > Religionsbücher -Medien > Bücher > Sachliteratur > Rätselbücher -Medien > Bücher > Sachliteratur > Sachliteratur für Jugendliche -Medien > Bücher > Sachliteratur > Schauspiel -Medien > Bücher > Sachliteratur > Selbsthilfebücher -Medien > Bücher > Sachliteratur > Sozialwissenschaftliche Bücher -Medien > Bücher > Sachliteratur > Spielbücher -Medien > Bücher > Sachliteratur > Sportbücher -Medien > Bücher > Sachliteratur > Sprach- & Linguistikbücher -Medien > Bücher > Sachliteratur > Technologiebücher -Medien > Bücher > Sachliteratur > Tier- & Naturbücher -Medien > Bücher > Sachliteratur > Wissenschaftsbücher Medien > DVDs & Videos -Medien > Musik +Medien > Musik & Tonaufnahmen Medien > Notenblätter Medien > Produkthandbücher & Gebrauchsanleitungen +Medien > Produkthandbücher & Gebrauchsanleitungen > Bürobedarf-Handbücher Medien > Produkthandbücher & Gebrauchsanleitungen > Handbücher für Elektrogeräte Medien > Produkthandbücher & Gebrauchsanleitungen > Handbücher für Elektrowerkzeuge Medien > Produkthandbücher & Gebrauchsanleitungen > Handbücher für Haushaltsgeräte Medien > Produkthandbücher & Gebrauchsanleitungen > Handbücher für Küchengeräte -Medien > Produkthandbücher & Gebrauchsanleitungen > Handbücher für Modelle und Spielzeuge -Medien > Produkthandbücher & Gebrauchsanleitungen > KFZ-Handbücher +Medien > Produkthandbücher & Gebrauchsanleitungen > Handbücher für Modellbau und Spielzeuge +Medien > Produkthandbücher & Gebrauchsanleitungen > Kamera- & Optikhandbücher +Medien > Produkthandbücher & Gebrauchsanleitungen > Kfz-Handbücher Medien > Produkthandbücher & Gebrauchsanleitungen > Sport- & Freizeithandbücher Medien > Zeitschriften & Zeitungen Möbel @@ -4166,38 +3591,26 @@ Möbel > Baby- & Kleinkindmöbel > Gitter- & Kinderbettzubehör Möbel > Baby- & Kleinkindmöbel > Gitter- & Kinderbettzubehör > Bettnestchen & Randschutz für Gitterbetten Möbel > Baby- & Kleinkindmöbel > Gitter- & Kinderbettzubehör > Umbausätze für Gitterbetten Möbel > Baby- & Kleinkindmöbel > Gitterbetten & Kleinkinderbetten -Möbel > Baby- & Kleinkindmöbel > Hochstühle und Sitzerhöhungen -Möbel > Baby- & Kleinkindmöbel > Möbelgarnituren für Babies und Kleinkinder -Möbel > Baby- & Kleinkindmöbel > Spielmöbel +Möbel > Baby- & Kleinkindmöbel > Hochstühle & Sitzerhöhungen +Möbel > Baby- & Kleinkindmöbel > Möbelgarnituren für Babies & Kleinkinder Möbel > Baby- & Kleinkindmöbel > Wickeltische Möbel > Baby- & Kleinkindmöbel > Wiegen & Stubenwagen Möbel > Baby- & Kleinkindmöbel > Wiegen- & Stubenwagenzubehör -Möbel > Baby- & Kleinkindmöbel > Wiegen- & Stubenwagenzubehör > Untergestelle für Wiegen Möbel > Baby- & Kleinkindmöbel > Zubehör für Hochstühle und Sitzerhöhungen Möbel > Betten & Zubehör -Möbel > Betten & Zubehör > Betten -Möbel > Betten & Zubehör > Betten > Ausziehbetten -Möbel > Betten & Zubehör > Betten > Etagenbetten -Möbel > Betten & Zubehör > Betten > Schlafcouch -Möbel > Betten & Zubehör > Betten > Schrankbetten -Möbel > Betten & Zubehör > Bettrahmen -Möbel > Betten & Zubehör > Bettzubehör -Möbel > Betten & Zubehör > Bettzubehör > Wasserbettzubehör +Möbel > Betten & Zubehör > Bett- & Bettrahmenzubehör +Möbel > Betten & Zubehör > Betten & Bettgestelle Möbel > Betten & Zubehör > Kopf- & Fußenden Möbel > Betten & Zubehör > Matratzen -Möbel > Betten & Zubehör > Matratzen > Wasserbetten Möbel > Betten & Zubehör > Matratzen-Untergestelle Möbel > Büromöbel Möbel > Büromöbel > Arbeitsplätze im Großraumbüro Möbel > Büromöbel > Arbeitstische Möbel > Büromöbel > Arbeitstische > Konferenztische Möbel > Büromöbel > Arbeitstische > Verstellbare Zeichentische -Möbel > Büromöbel > Bürostuhl-Zubehör -Möbel > Büromöbel > Bürostühle -Möbel > Büromöbel > Bürostühle > Kniestühle +Möbel > Büromöbel > Büro- & Schreibtischstühle +Möbel > Büromöbel > Büromöbelgarnituren Möbel > Büromöbel > Schreibtische -Möbel > Büromöbel > Sekretäre -Möbel > Büromöbel > Zubehör für Arbeitsplätze im Großraumbüro Möbel > Futonauflagen Möbel > Futonrahmen Möbel > Futons @@ -4208,6 +3621,7 @@ Möbel > Gartenmöbel > Gartenhocker Möbel > Gartenmöbel > Gartenmöbelgarnituren Möbel > Gartenmöbel > Gartensitzmöbel Möbel > Gartenmöbel > Gartensitzmöbel > Gartenbänke +Möbel > Gartenmöbel > Gartensitzmöbel > Gartensofaelemente Möbel > Gartenmöbel > Gartensitzmöbel > Gartensofas Möbel > Gartenmöbel > Gartensitzmöbel > Gartenstühle Möbel > Gartenmöbel > Gartensitzmöbel > Sonnenliegen @@ -4217,33 +3631,33 @@ Möbel > Gartenmöbelzubehör > Abdeckungen für Gartenmöbel Möbel > Kücheninseln & Küchenwagen Möbel > Kücheninseln & Küchenwagen > Kücheninseln Möbel > Kücheninseln & Küchenwagen > Küchenwagen +Möbel > Möbel für Unterhaltungselektronik Möbel > Möbelgarnituren +Möbel > Möbelgarnituren > Badezimmergarnituren Möbel > Möbelgarnituren > Küchen- & Esszimmergarnituren Möbel > Möbelgarnituren > Schlafzimmergarnituren Möbel > Möbelgarnituren > Wohnzimmergarnituren Möbel > Polsterhocker -Möbel > Polsterhocker > Fußhocker -Möbel > Polsterhocker > Hocker mit Stauraum -Möbel > Polsterhocker > Konvertierbare Hocker Möbel > Raumteiler Möbel > Raumteilerzubehör Möbel > Regalsysteme Möbel > Regalsysteme > Bücherregale & Bücherschränke +Möbel > Regalsysteme > Wandregale & Simse Möbel > Regalzubehör Möbel > Regalzubehör > Ersatzregale Möbel > Schränke Möbel > Schränke > Aktenschränke -Möbel > Schränke > Anrichten Möbel > Schränke > Aufbewahrungstruhen Möbel > Schränke > Aufbewahrungstruhen > Aussteuertruhen Möbel > Schränke > Aufbewahrungstruhen > Spielzeugtruhen Möbel > Schränke > Buffets & Sideboards +Möbel > Schränke > Bügelcenter +Möbel > Schränke > Büroschränke Möbel > Schränke > Geschirrschränke Möbel > Schränke > Kleiderschränke Möbel > Schränke > Kommoden +Möbel > Schränke > Küchenschränke Möbel > Schränke > Mediaaufbewahrung -Möbel > Schränke > Mediaaufbewahrung > Mediaschränke -Möbel > Schränke > Mediaaufbewahrung > TV- & Mediamöbel Möbel > Schränke > Spirituosenschränke Möbel > Schränke > Wasch- und Schminktische Möbel > Schränke > Wasch- und Schminktische > Badezimmerwaschtische @@ -4255,15 +3669,15 @@ Möbel > Sitzbänke > Küchen- & Eckbänke Möbel > Sitzbänke > Schminktischhocker Möbel > Sitzbänke > Truhen- & Flurbänke Möbel > Sofa-Zubehör +Möbel > Sofa-Zubehör > Anbausofas Möbel > Sofa-Zubehör > Sitzverstärkung für Stühle & Sofas Möbel > Sofas -Möbel > Sofas > Loveseats -Möbel > Sofas > Modulsofas -Möbel > Sofas > Schlafsofas Möbel > Stuhlzubehör +Möbel > Stuhlzubehör > Ersatzteile für Hängesessel Möbel > Stühle -Möbel > Stühle > Barhocker +Möbel > Stühle > Bodenstühle Möbel > Stühle > Elektrische Massagesessel +Möbel > Stühle > Hocker & Barhocker Möbel > Stühle > Hängesessel Möbel > Stühle > Klappstühle & Holzhocker Möbel > Stühle > Küchen- und Esszimmerstühle @@ -4271,17 +3685,13 @@ Möbel > Stühle > Liegemöbel Möbel > Stühle > Multimediasessel Möbel > Stühle > Schaukelstühle Möbel > Stühle > Sessel -Möbel > Stühle > Sessel > Armsessel -Möbel > Stühle > Sessel > Recliner-Sessel -Möbel > Stühle > Sessel > Schlafsessel Möbel > Stühle > Sessel ohne Armlehnen Möbel > Stühle > Sitzsäcke -Möbel > TV- & HiFi-Möbel Möbel > Tische Möbel > Tische > Kinderspieltische Möbel > Tische > Klapptische +Möbel > Tische > Kotatsu Möbel > Tische > Küchen- & Esszimmertische -Möbel > Tische > Küchen- & Esszimmertische > Bartische & Stehtische Möbel > Tische > Nachttische Möbel > Tische > Nähmaschinentische Möbel > Tische > Poker- & Spieltische @@ -4292,85 +3702,55 @@ Möbel > Tische > Ziertische > Konsolentische Möbel > Tischzubehör Möbel > Tischzubehör > Tischbeine Möbel > Tischzubehör > Tischplatten +Möbel > Zubehör für Büromöbel +Möbel > Zubehör für Büromöbel > Bürostuhl-Zubehör +Möbel > Zubehör für Büromöbel > Schreibtischteile & -zubehör +Möbel > Zubehör für Büromöbel > Zubehör für Arbeitsplätze im Großraumbüro Nahrungsmittel, Getränke & Tabak Nahrungsmittel, Getränke & Tabak > Getränke -Nahrungsmittel, Getränke & Tabak > Getränke > Alkopops -Nahrungsmittel, Getränke & Tabak > Getränke > Bier -Nahrungsmittel, Getränke & Tabak > Getränke > Bier > Alkoholfreies Bier +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Alkopops +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Bier +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Cidre +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Cocktail-Bitter +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Cocktail-Premix +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Liköre & Spirituosen +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Liköre & Spirituosen > Absinth +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Liköre & Spirituosen > Gin +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Liköre & Spirituosen > Liköre +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Liköre & Spirituosen > Rum +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Liköre & Spirituosen > Shochu & Soju +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Liköre & Spirituosen > Tequila +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Liköre & Spirituosen > Weinbrand +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Liköre & Spirituosen > Whiskey +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Liköre & Spirituosen > Wodka +Nahrungsmittel, Getränke & Tabak > Getränke > Alkoholische Getränke > Wein Nahrungsmittel, Getränke & Tabak > Getränke > Buttermilch -Nahrungsmittel, Getränke & Tabak > Getränke > Cidre -Nahrungsmittel, Getränke & Tabak > Getränke > Cocktail-Premix Nahrungsmittel, Getränke & Tabak > Getränke > Eierlikör Nahrungsmittel, Getränke & Tabak > Getränke > Essighaltige Getränke Nahrungsmittel, Getränke & Tabak > Getränke > Getränke mit Fruchtgeschmack +Nahrungsmittel, Getränke & Tabak > Getränke > Getränkepulver Nahrungsmittel, Getränke & Tabak > Getränke > Kaffee -Nahrungsmittel, Getränke & Tabak > Getränke > Kaffee > Gemahlener & ungemahlener Kaffee -Nahrungsmittel, Getränke & Tabak > Getränke > Kaffee > Instantkaffee -Nahrungsmittel, Getränke & Tabak > Getränke > Kaffee > Kaffeegetränke in Flaschen -Nahrungsmittel, Getränke & Tabak > Getränke > Kaffee > Kaffeekapseln Nahrungsmittel, Getränke & Tabak > Getränke > Kakao -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Gin -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Liköre -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Rum -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Schnäpse -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Tequila -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Weinbrand -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Weinbrand > Cognac -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Whiskey -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Whiskey > Amerikanischer Whiskey -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Whiskey > Irischer Whiskey -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Whiskey > Schottischer Whisky -Nahrungsmittel, Getränke & Tabak > Getränke > Liköre & Spirituosen > Wodka Nahrungsmittel, Getränke & Tabak > Getränke > Limonaden -Nahrungsmittel, Getränke & Tabak > Getränke > Magenbitter Nahrungsmittel, Getränke & Tabak > Getränke > Milch -Nahrungsmittel, Getränke & Tabak > Getränke > Milch > Trockenmilch -Nahrungsmittel, Getränke & Tabak > Getränke > Mischgetränke Nahrungsmittel, Getränke & Tabak > Getränke > Nicht-tierische Milch -Nahrungsmittel, Getränke & Tabak > Getränke > Nicht-tierische Milch > Hafermilch -Nahrungsmittel, Getränke & Tabak > Getränke > Nicht-tierische Milch > Hanfmilch -Nahrungsmittel, Getränke & Tabak > Getränke > Nicht-tierische Milch > Kokosmilch -Nahrungsmittel, Getränke & Tabak > Getränke > Nicht-tierische Milch > Mandelmilch -Nahrungsmittel, Getränke & Tabak > Getränke > Nicht-tierische Milch > Reismilch -Nahrungsmittel, Getränke & Tabak > Getränke > Nicht-tierische Milch > Sojamilch Nahrungsmittel, Getränke & Tabak > Getränke > Saft Nahrungsmittel, Getränke & Tabak > Getränke > Sportgetränke & Energy Drinks Nahrungsmittel, Getränke & Tabak > Getränke > Tees & Aufgüsse -Nahrungsmittel, Getränke & Tabak > Getränke > Tees & Aufgüsse > Teebeutel & Lose Teeblätter -Nahrungsmittel, Getränke & Tabak > Getränke > Tees & Aufgüsse > Teegetränke in Flaschen -Nahrungsmittel, Getränke & Tabak > Getränke > Tees & Aufgüsse > Teepulver Nahrungsmittel, Getränke & Tabak > Getränke > Wasser -Nahrungsmittel, Getränke & Tabak > Getränke > Wasser > Aromatisiertes Wasser -Nahrungsmittel, Getränke & Tabak > Getränke > Wasser > Mineralwasser -Nahrungsmittel, Getränke & Tabak > Getränke > Wasser > Tonic Water -Nahrungsmittel, Getränke & Tabak > Getränke > Wasser > Wasser in Flaschen -Nahrungsmittel, Getränke & Tabak > Getränke > Wein -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Alkoholfreie Weine -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Blush-Roséwein -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Dessertwein -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Dessertwein > Portwein -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Dessertwein > Sherry -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Dessertwein > Wermut -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Met -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Reiswein -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Roséwein -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Rotwein -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Sangria -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Sekt -Nahrungsmittel, Getränke & Tabak > Getränke > Wein > Weißwein Nahrungsmittel, Getränke & Tabak > Lebensmittel Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Backwaren-Mischungen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Bagels Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Brot & Brötchen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Coffee Cake Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Cupcakes -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Dessert-Platten Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Donuts Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Eistüten Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Feingebäck -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Fudge +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Karamell-Fudge Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Kuchen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Kuchen zum Kaffee Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Muffins Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Pasteten & Torten Nahrungsmittel, Getränke & Tabak > Lebensmittel > Backwaren > Plätzchen @@ -4383,26 +3763,14 @@ Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Frisc Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Gemüsedip Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Guacamole Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Hummus -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Käseaufstrich +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Käse-Dips & -aufstriche Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Marmeladen & Gelees Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Nussbutter -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Nussbutter > Erdnussbutter -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Nussbutter > Haselnussbutter -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Nussbutter > Mandelbutter Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Salsa-Saucen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Dips & Brotaufstriche > Tapenade Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Fertigvorspeisen & -beilagen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Fertigvorspeisen & -beilagen > Feinkost-Sandwiches -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Fertigvorspeisen & -beilagen > Fertigbeilagen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Fertigvorspeisen & -beilagen > Fertighauptgerichte -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Fertigvorspeisen & -beilagen > Frühstückssandwiches -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Fertigvorspeisen & -beilagen > Pizza -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Fertigvorspeisen & -beilagen > Waffeln, Pfannkuchen & French Toast -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Hors d'Oeuvre-Tabletts -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Pfannengerichte -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Sushi -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Tiefkühlgerichte +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Fertige Mahlzeiten und Hauptgerichte +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fertiggerichte > Fertige Vorspeisen und Beilagen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fleisch, Fisch, Meeresfrüchte & Eier Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fleisch, Fisch, Meeresfrüchte & Eier > Eier Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fleisch, Fisch, Meeresfrüchte & Eier > Fisch & Meeresfrüchte @@ -4411,40 +3779,25 @@ Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fleisch, Fisch, Meeresfrücht Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fleisch, Fisch, Meeresfrüchte & Eier > Fleisch Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fleisch, Fisch, Meeresfrüchte & Eier > Fleisch > Fleisch- & Wurstwaren Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fleisch, Fisch, Meeresfrüchte & Eier > Fleisch > Fleischkonserven -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fleisch, Fisch, Meeresfrüchte & Eier > Fleisch > Frikadellen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fleisch, Fisch, Meeresfrüchte & Eier > Fleisch > Frisches & Tiefgefrorenes Fleisch -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Fleisch, Fisch, Meeresfrüchte & Eier > Fleisch > Würstchen & Hotdogs Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backaromen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backaromen > Mandelextrakt -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backaromen > Vanilleextrakt Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backfett & Schmalz Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backmischungen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backmischungen > Backmischungen für Brot & Muffins -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backmischungen > Backmischungen für Brot & Muffins > Backmischungen für Muffins -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backmischungen > Backmischungen für Brot & Muffins > Brotmischungen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backmischungen > Backmischungen für Kuchen und Brownies -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backmischungen > Backmischungen für Waffeln und Pfannkuchen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backmischungen > Brezel-Backmischungen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backmischungen > Brotpudding-Backmischungen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backmischungen > Plätzchenmischungen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backmischungen für Waffeln und Pfannkuchen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backpulver Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backsoda +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Backwaren-Deko-Sets Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Blockschokoloade Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Bohnenpasten & -saucen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Dosen- und Trockenmilch Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Essbare Backdekoration -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Essbare Backdekoration > Essbare Backwaren-Deko -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Essbare Backdekoration > Farbzucker -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Essbare Backdekoration > Streusel -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Essbare Backdekoration > Zuckerperlen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Fertigbackmischungen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Essig +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Gemahlene Getreideprodukte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Geschmacksneutrale Gelatine -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Gezuckerte Kondensmilch Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Hefe Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Kochwein -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Kokosraspeln -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Kuchenfüllung -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Künstliche Süßstoffe +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Kuchen- & Pastetenfüllungen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Lebensmittelfarben Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Maissirup Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Maisstärke @@ -4454,29 +3807,16 @@ Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Melasse Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Paniermehl Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Raspeln, Flocken & Tröpfchen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Chili-Öl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Erdnussöl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Hanföl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Kochspray -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Kokosöl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Maisöl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Olivenöl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Pflanzenöl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Rapsöl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Reisöl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Sesamöl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Sojabohnenöl -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Speiseöle > Walnussöl Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Starterkulturen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Stärkemehl & Paniermischungen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Tapiokaperlen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Teig Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Teig > Brot- & Gebäckteig -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Teig > Brot- & Gebäckteig > Pizzateig Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Teig > Pastetenteig -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Teig > Plätzchen- und Brownieteig +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Teig > Plätzchen- & Brownieteig Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Tomatenmark -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Ungesüßte Kondensmilch -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Zucker +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Zitronen- und Limettensaft +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Zucker & Süßstoffe Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Zuckerguss & Glasur Nahrungsmittel, Getränke & Tabak > Lebensmittel > Koch- & Backzutaten > Zuckerwatte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Körner, Reis & Getreide @@ -4487,7 +3827,6 @@ Nahrungsmittel, Getränke & Tabak > Lebensmittel > Körner, Reis & Getreide > Fr Nahrungsmittel, Getränke & Tabak > Lebensmittel > Körner, Reis & Getreide > Gerste Nahrungsmittel, Getränke & Tabak > Lebensmittel > Körner, Reis & Getreide > Haferflocken, Grütze & Grieß Nahrungsmittel, Getränke & Tabak > Lebensmittel > Körner, Reis & Getreide > Hirse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Körner, Reis & Getreide > Maismehl Nahrungsmittel, Getränke & Tabak > Lebensmittel > Körner, Reis & Getreide > Quinoa Nahrungsmittel, Getränke & Tabak > Lebensmittel > Körner, Reis & Getreide > Reis Nahrungsmittel, Getränke & Tabak > Lebensmittel > Körner, Reis & Getreide > Roggen @@ -4496,96 +3835,72 @@ Nahrungsmittel, Getränke & Tabak > Lebensmittel > Milchprodukte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Milchprodukte > Butter & Margarine Nahrungsmittel, Getränke & Tabak > Lebensmittel > Milchprodukte > Hüttenkäse Nahrungsmittel, Getränke & Tabak > Lebensmittel > Milchprodukte > Joghurt +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Milchprodukte > Kaffeeweißer Nahrungsmittel, Getränke & Tabak > Lebensmittel > Milchprodukte > Käse Nahrungsmittel, Getränke & Tabak > Lebensmittel > Milchprodukte > Sahne Nahrungsmittel, Getränke & Tabak > Lebensmittel > Milchprodukte > Sauerrahm Nahrungsmittel, Getränke & Tabak > Lebensmittel > Milchprodukte > Schlagsahne Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Brotnüsse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Cashewnüsse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Dika-Nüsse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Erdnüsse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Esskastanien -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Gemischte Nüsse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Geröstete Sojabohnen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Haselnüsse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Kolanüsse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Kürbiskerne -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Macadamia-Nüsse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Mamoncillo -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Mandeln -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Nüsse mit Schokoladenüberzug -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Paradiesnüsse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Paranuss -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Pekanuss -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Pinienkerne -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Pistazien -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Sesamkörner -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Sonnenblumenkerne -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Nüsse & Samen > Walnüsse Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Dosenbohnen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Dosenfrüchte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Alfalfasprossen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Arakachas Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Artischocken Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Auberginen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Choi Sum +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Gartensalat +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Grünkohl +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Mangold +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Pak Choi +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Rauke +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Rübenblätter +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Salatmischungen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Spinat +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Wasserspinat +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Wegwarte +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blattgemüse > Yu Choy Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Blumenkohl Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Bohnen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Bohnensprossen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Borretsch Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Brokkoli Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Chinesischer Brokkoli -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Choi Sum Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Erbsen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Farnspitzen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Fenchelknollen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Flaschenkürbis -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Gartenkürbis -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Gartensalat +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Gemüsemischungen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Gobo-Wurzel -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Grünkohl Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Gurken Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Ingwer Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Kaktusblätter Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Kartoffeln -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Kichererbsen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Knoblauch Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Kohl Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Kohlrabi -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Kohlrüben +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Kürbisse Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Lotoswurzel Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Mais -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Mangold Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Maniok Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Möhren Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Okra -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Pak Choi -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Palmkohl Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Paprikaschoten Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Pastinaken Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Petersilienwurzeln Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Pilze Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Porree Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Radieschen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Rauke Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Rettich Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Rhabarber Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Rosenkohl Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Rutenkohl Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Rüben -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Rübenblätter -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Salatmischungen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Schalotten Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Sellerie Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Sellerieknollen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Spanische Artischocken Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Spargel -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Speisekürbisse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Spinat -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Steckrüben +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Sprossen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Steckrüben & Kohlrüben Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Süßkartoffeln Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Tamarillos Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Tannias @@ -4594,21 +3909,13 @@ Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & T Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Topinambur Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Wasserkastanien Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Wasserkresse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Wasserspinat -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Wegwarte -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Wegwarte > Chicorée -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Wegwarte > Krausblättrige Endivien -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Wegwarte > Radicchio -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Wegwarte > Winterendivie Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Weizengras Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Yambohnen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Yams -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Yu Choy Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Zuckerrohr Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Gemüse > Zwiebeln Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Ananas -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Aprikosen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Atemoyas Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Avocados Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Bananen @@ -4622,94 +3929,61 @@ Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & T Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Datteln Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Feigen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Granatäpfel -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Grapefruits Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Große Sapoten Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Guaven Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Homli-Früchte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Kaktusfeigen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Kirschen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Kiwis Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Kokosnüsse -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Korinthen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Kumquats -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Limequats -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Limetten Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Longan Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Loquats Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Lychees -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Madroaa-Früchte -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Mandarinen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Mangos +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Madrono-Früchte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Mangostanfrüchte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Melonen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Melonen > Bittermelonen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Melonen > Horngurken -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Nektarinen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Orangen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Obstmischungen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Papayas Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Passionsfrüchte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Persimonen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Pfirsiche -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Pflaumen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Physalis Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Pitahayas -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Plumcots Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Quitten Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Rambutans Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Sapoten Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Stachelannonen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Steinfrüchte +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Steinfrüchte > Aprikosen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Steinfrüchte > Kirschen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Steinfrüchte > Mangos +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Steinfrüchte > Pfirsiche & Nektarinen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Steinfrüchte > Pflaumen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Steinfrüchte > Plumcots Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Sternfrüchte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Tamarinden -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Tangelos Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Trauben Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Zimtäpfel -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Zitronen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Zitrusfrüchte +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Zitrusfrüchte > Grapefruits +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Zitrusfrüchte > Kumquats +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Zitrusfrüchte > Limequats +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Zitrusfrüchte > Limetten +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Zitrusfrüchte > Orangen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Zitrusfrüchte > Tangelos +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Zitrusfrüchte > Zitronen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Frisches & Tiefgefrorenes Obst > Äpfel Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Fruchtsoßen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Fruchtsoßen > Apfelsoße -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Fruchtsoßen > Preiselbeersoße Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Gemüsekonserven Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Getrocknete Bohnen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Getrocknete Früchte -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Getrocknetes Gemüse +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Obstkonserven +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Obst & Gemüse > Trockengemüse Nahrungsmittel, Getränke & Tabak > Lebensmittel > Pasta & Nudeln +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Schokofrüchte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Suppen & Brühen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Suppen & Brühen > Brühwürfel -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Suppen & Brühen > Dosensuppen & -brühen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Suppen & Brühen > Fertigsuppen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Kaugummi -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Bonbons -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Candy Corn -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Dauerlutscher -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Frucht- & Weingummi -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Fruchtgummis -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Früchte mit Schokoladenüberzug -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Geleebohnen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Karamellbonbons -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Kaubonbons -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Lakritze -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Marshmallow-Bonbons -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Minzbonbons -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Nougat -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Peanut Butter Cups -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Peppermint-Patties -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Pralinen-Sortiments -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Schokoladenriegel & Miniriegel -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Schokoladentrüffel -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Schokoriegel -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Süßigkeiten mit Krokant -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Süßwaren aus Karamell -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Taffy -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Kaugummi > Süßigkeiten & Schokolade > Zuckerstangen +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Süßigkeiten & Schokolade Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tiefkühl-Desserts & -Neuheiten -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tiefkühl-Desserts & -Neuheiten > Eishörnchen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tiefkühl-Desserts & -Neuheiten > Frozen Yogurt -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tiefkühl-Desserts & -Neuheiten > Fruchteis -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tiefkühl-Desserts & -Neuheiten > Gefrorene Desserts ohne Milchanteil -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tiefkühl-Desserts & -Neuheiten > Sorbet -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tiefkühl-Desserts & -Neuheiten > Speiseeis +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tiefkühl-Desserts & -Neuheiten > Eissnacks +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tiefkühl-Desserts & -Neuheiten > Speiseeis und gefrorener Joghurt Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tiefkühl-Desserts & -Neuheiten > Stieleis Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tofu- & Soja-Produkte Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tofu- & Soja-Produkte > Fleischalternativen @@ -4720,25 +3994,12 @@ Nahrungsmittel, Getränke & Tabak > Lebensmittel > Tofu- & Soja-Produkte > Tofu Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Brezeln Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Chips -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Chips > Bagel-Chips -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Chips > Kartoffelchips -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Chips > Mais- & Tortilla-Chips -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Chips > Pita-Chips Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Croûtons Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Dessertküchlein Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Fruchtsnacks Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Getreide- & Müsliriegel Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Grissini Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Kräcker -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Kräcker > Austerncracker -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Kräcker > Crackermischungen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Kräcker > Einfache Cracker -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Kräcker > Fladenbrotcracker -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Kräcker > Graham-Cracker -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Kräcker > Käsecracker -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Kräcker > Matzecracker -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Kräcker > Salzcracker -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Kräcker > Sandwich-Cracker Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Käse-Flips Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Popcorn Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Pudding & Gelatine-Snacks @@ -4749,106 +4010,71 @@ Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Schwein Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Sesamsticks Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Studentenfutter Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Trockenfleisch -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Trockenfleisch > Beef Jerky -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Trockenfleisch > Pork Jerky -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Vorspeisen & Snacks > Trockenfleisch > Turkey Jerky Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Anis -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Basilikum -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Bocksbart -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Bohnenkraut -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Chilipulver -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Dill -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Estragon -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Fenchelblätter -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Knoblauchpulver -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Koriander -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Kreuzkümmel -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Loorbeerblätter -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Majoran -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Minze -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Oregano -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Paprikapulver -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Petersilie -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Rosmarin -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Salbei -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Sauerampfer -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Schnittlauch -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Thymian -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Vanilleschoten -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Zimt -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Zitronengras -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Kräuter & Gewürze > Zwiebelpulver Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Mononatriumglutamat Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Pfeffer Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Salz -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzen & Verfeinern > Würzmischungen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Barbecue-Sauce Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Bratensoße Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Chilisauce -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Chutney Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Cocktailsaucen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Currysauce Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Dessertsaucen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Dessertsaucen > Aufschlagmittel Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Dessertsaucen > Eissaucen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Dessertsaucen > Fruchttopping -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Essig +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Eingelegtes Obst und Gemüse Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Fischsauce Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Honig -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Kaffeeweißer Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Ketchup -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Marinaden +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Marinaden und Grillsoßen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Mayonnaise Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Meerrettichsaucen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Oliven & Kapern Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Pastasoßen -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Pickles & Relishes Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Pizzasoße Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Salatdressing Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Sataysauce Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Sauce tartare Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Senf Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Sirup -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Sirup > Agavensirup -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Sirup > Ahornsirup -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Sirup > Aromatisierter Sirup -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Sirup > Sirup für Schneeballeis Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Sojasauce -Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Steaksauce +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Süßsaure Soßen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Tahini +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Weiße Soßen und Rahmsoßen Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Worcestershiresauce +Nahrungsmittel, Getränke & Tabak > Lebensmittel > Würzmittel & Saucen > Würzsoße und Chutney Nahrungsmittel, Getränke & Tabak > Tabakprodukte Nahrungsmittel, Getränke & Tabak > Tabakprodukte > Kautabak -Nahrungsmittel, Getränke & Tabak > Tabakprodukte > Rauchlose Zigaretten +Nahrungsmittel, Getränke & Tabak > Tabakprodukte > Pfeifen Nahrungsmittel, Getränke & Tabak > Tabakprodukte > Tabak +Nahrungsmittel, Getränke & Tabak > Tabakprodukte > Vaporizer & Rauchlose Zigaretten Nahrungsmittel, Getränke & Tabak > Tabakprodukte > Zigaretten Nahrungsmittel, Getränke & Tabak > Tabakprodukte > Zigarren Religion & Feierlichkeiten Religion & Feierlichkeiten > Artikel für Gedenkzeremonien Religion & Feierlichkeiten > Artikel für Gedenkzeremonien > Urnen Religion & Feierlichkeiten > Artikel für Hochzeitszeremonien +Religion & Feierlichkeiten > Artikel für Hochzeitszeremonien > Hochzeitsläufer Religion & Feierlichkeiten > Artikel für Hochzeitszeremonien > Körbe für Blumenmädchen Religion & Feierlichkeiten > Artikel für Hochzeitszeremonien > Ringkissen Religion & Feierlichkeiten > Religiöse Artikel Religion & Feierlichkeiten > Religiöse Artikel > Altare +Religion & Feierlichkeiten > Religiöse Artikel > Gebetskarten Religion & Feierlichkeiten > Religiöse Artikel > Gebetsketten Religion & Feierlichkeiten > Religiöse Artikel > Religiöse Schleier +Religion & Feierlichkeiten > Religiöse Artikel > Tarotkarten Software Software > Computersoftware Software > Computersoftware > Antiviren- & Sicherheitssoftware Software > Computersoftware > Betriebssysteme Software > Computersoftware > Büroanwendungssoftware Software > Computersoftware > Compiler & Programmierungstools -Software > Computersoftware > Computer-Dienstprogramme & -Wartung +Software > Computersoftware > Computerdienstprogramme & -wartung +Software > Computersoftware > GPS-Karten & -Software Software > Computersoftware > Handheld- & PDA-Software Software > Computersoftware > Lernsoftware Software > Computersoftware > Netzwerksoftware -Software > Computersoftware > Referenzsoftware -Software > Computersoftware > Referenzsoftware > GPS-Karten & -Software -Software > Computersoftware > Referenzsoftware > Wörterbuch- & Übersetzungssoftware Software > Computersoftware > Software für Multimedia & Design Software > Computersoftware > Software für Multimedia & Design > Animationsbearbeitungssoftware Software > Computersoftware > Software für Multimedia & Design > Graphic-Design-Software @@ -4863,58 +4089,20 @@ Software > Computersoftware > Software für Multimedia & Design > Web-Design-Sof Software > Computersoftware > Steuer- & Buchhaltungssoftware Software > Computersoftware > Unternehmens- & Produktivitätssoftware Software > Computersoftware > Wiederherstellungsdatenträger +Software > Computersoftware > Wörterbuch- & Übersetzungssoftware Software > Digital-Content-Software -Software > Digital-Content-Software > Clipart Software > Digital-Content-Software > Computer-Icons Software > Digital-Content-Software > Desktop-Hintergrundbilder +Software > Digital-Content-Software > Digitales Bildmaterial Software > Digital-Content-Software > Dokumentvorlagen Software > Digital-Content-Software > Fonts +Software > Digital-Content-Software > Stock-Fotografie & Videoclips Software > Digital-Content-Software > Virtuelles Geld Software > PC- & Videospiele -Software > PC- & Videospiele > Atari 2600-Spiele -Software > PC- & Videospiele > Atari 5200-Spiele -Software > PC- & Videospiele > Atari Lynx-Spiele -Software > PC- & Videospiele > ColecoVision-Spiele -Software > PC- & Videospiele > Computerspiele -Software > PC- & Videospiele > Computerspiele > Mac-Spiele -Software > PC- & Videospiele > Computerspiele > PC-Spiele -Software > PC- & Videospiele > Dreamcast-Spiele -Software > PC- & Videospiele > Game Boy-Spiele (gesamt) -Software > PC- & Videospiele > Game Boy-Spiele (gesamt) > Game Boy Advance-Spiele -Software > PC- & Videospiele > Game Boy-Spiele (gesamt) > Gameboy-Spiele -Software > PC- & Videospiele > Game Gear-Spiele -Software > PC- & Videospiele > GameCube-Spiele -Software > PC- & Videospiele > Intellivision-Spiele -Software > PC- & Videospiele > Jaguar-Spiele -Software > PC- & Videospiele > LeapFrog-Spiele -Software > PC- & Videospiele > N-Gage-Spiele -Software > PC- & Videospiele > Neo Geo Pocket-Spiele -Software > PC- & Videospiele > Neo Geo-Spiele -Software > PC- & Videospiele > Nintendo 64-Spiele -Software > PC- & Videospiele > Nintendo DS-Spiele -Software > PC- & Videospiele > Nintendo Entertainment System-Spiele -Software > PC- & Videospiele > PC Engine-Spiele -Software > PC- & Videospiele > PlayStation Portable-Spiele -Software > PC- & Videospiele > PlayStation Vita-Spiele -Software > PC- & Videospiele > PlayStation-Spiele (gesamt) -Software > PC- & Videospiele > PlayStation-Spiele (gesamt) > PlayStation (Original)-Spiele -Software > PC- & Videospiele > PlayStation-Spiele (gesamt) > PlayStation 2-Spiele -Software > PC- & Videospiele > PlayStation-Spiele (gesamt) > PlayStation 3-Spiele -Software > PC- & Videospiele > Sega Genesis-Spiele -Software > PC- & Videospiele > Sega Master System-Spiele -Software > PC- & Videospiele > Super Nintendo-Spiele -Software > PC- & Videospiele > Wii U-Spiele -Software > PC- & Videospiele > Wii-Spiele -Software > PC- & Videospiele > Xbox-Spiele (gesamt) -Software > PC- & Videospiele > Xbox-Spiele (gesamt) > Xbox (Original)-Spiele -Software > PC- & Videospiele > Xbox-Spiele (gesamt) > Xbox 360-Spiele Spielzeuge & Spiele Spielzeuge & Spiele > Puzzles & Geduldspiele Spielzeuge & Spiele > Puzzles & Geduldspiele > Holzsteckpuzzle Spielzeuge & Spiele > Puzzles & Geduldspiele > Mechanische Geduldspiele -Spielzeuge & Spiele > Puzzles & Geduldspiele > Mechanische Geduldspiele > Entwirrspiele -Spielzeuge & Spiele > Puzzles & Geduldspiele > Mechanische Geduldspiele > Geschicklichkeitsspiele -Spielzeuge & Spiele > Puzzles & Geduldspiele > Mechanische Geduldspiele > Zusammensetzspiele Spielzeuge & Spiele > Puzzles & Geduldspiele > Puzzle-Zubehör Spielzeuge & Spiele > Puzzles & Geduldspiele > Puzzles Spielzeuge & Spiele > Spiel-Timer @@ -4923,40 +4111,33 @@ Spielzeuge & Spiele > Spiele > Battle Tops Spielzeuge & Spiele > Spiele > Bingo-Spiele Spielzeuge & Spiele > Spiele > Blackjack- & Würfelspiel-Sets Spielzeuge & Spiele > Spiele > Brettspiele -Spielzeuge & Spiele > Spiele > Brettspiele > Backgammon-Spiele -Spielzeuge & Spiele > Spiele > Brettspiele > Damespiele -Spielzeuge & Spiele > Spiele > Brettspiele > Parcheesi -Spielzeuge & Spiele > Spiele > Brettspiele > Schachspiele +Spielzeuge & Spiele > Spiele > Geschicklichkeitsspiele +Spielzeuge & Spiele > Spiele > Glücksspielautomaten Spielzeuge & Spiele > Spiele > Kampfkreiselzubehör Spielzeuge & Spiele > Spiele > Kartenspiele -Spielzeuge & Spiele > Spiele > Kartenspiele > Sammelkartenspiele -Spielzeuge & Spiele > Spiele > Kartenspiele > Traditionelle Spielkarten Spielzeuge & Spiele > Spiele > Kartenspielzubehör Spielzeuge & Spiele > Spiele > Legespiele -Spielzeuge & Spiele > Spiele > Legespiele > Dominospiele -Spielzeuge & Spiele > Spiele > Legespiele > Mah-Jongg Spielzeuge & Spiele > Spiele > Pokerchip-Zubehör Spielzeuge & Spiele > Spiele > Pokerchip-Zubehör > Behälter für Pokerchips Spielzeuge & Spiele > Spiele > Pokerchips & -sets -Spielzeuge & Spiele > Spiele > Rouletterad & Zubehör -Spielzeuge & Spiele > Spiele > Stapelspiele +Spielzeuge & Spiele > Spiele > Rouletteräder & -zubehör Spielzeuge & Spiele > Spiele > Tragbare elektronische Spiele Spielzeuge & Spiele > Spiele > Würfelsets & -spiele -Spielzeuge & Spiele > Spiele > Würfelsets & -spiele > Würfel & Würfelsets -Spielzeuge & Spiele > Spiele > Würfelsets & -spiele > Würfelspiele Spielzeuge & Spiele > Spielzeug für draußen Spielzeuge & Spiele > Spielzeug für draußen > Hüpfburg-Zubehör Spielzeuge & Spiele > Spielzeug für draußen > Hüpfburgen Spielzeuge & Spiele > Spielzeug für draußen > Rutschen Spielzeuge & Spiele > Spielzeug für draußen > Sandkästen -Spielzeuge & Spiele > Spielzeug für draußen > Schaukeln & Rutschen +Spielzeuge & Spiele > Spielzeug für draußen > Schaukeln Spielzeuge & Spiele > Spielzeug für draußen > Schaukeln & Spielplatzgeräte -Spielzeuge & Spiele > Spielzeug für draußen > Spielfallschirme Spielzeuge & Spiele > Spielzeug für draußen > Spielhäuser Spielzeuge & Spiele > Spielzeug für draußen > Spielzelte & -tunnel +Spielzeuge & Spiele > Spielzeug für draußen > Springstöcke +Spielzeuge & Spiele > Spielzeug für draußen > Stelzen +Spielzeuge & Spiele > Spielzeug für draußen > Trampoline +Spielzeuge & Spiele > Spielzeug für draußen > Trampolinzubehör Spielzeuge & Spiele > Spielzeug für draußen > Wasserspielgeräte -Spielzeuge & Spiele > Spielzeug für draußen > Wasserspielgeräte > Wasserparks -Spielzeuge & Spiele > Spielzeug für draußen > Wasserspielgeräte > Wasserrutschen für den Garten +Spielzeuge & Spiele > Spielzeug für draußen > Wasserspielgeräte > Planschbecken und Wasserrutschen Spielzeuge & Spiele > Spielzeug für draußen > Wasserspielgeräte > Wassersprenger für Kinder Spielzeuge & Spiele > Spielzeug für draußen > Wasserspielgeräte > Wassertische Spielzeuge & Spiele > Spielzeug für draußen > Wippen @@ -4972,10 +4153,9 @@ Spielzeuge & Spiele > Spielzeuge > Bausteine & Bauspielzeug > Schaumstoffbaustei Spielzeuge & Spiele > Spielzeuge > Bausteine & Bauspielzeug > Steckbausteine Spielzeuge & Spiele > Spielzeuge > Bällebad-Zubehör Spielzeuge & Spiele > Spielzeuge > Bällebad-Zubehör > Bälle für Bällebad +Spielzeuge & Spiele > Spielzeuge > Bällebäder Spielzeuge & Spiele > Spielzeuge > Bürospielzeug Spielzeuge & Spiele > Spielzeuge > Bürospielzeug > Magnetspielzeug -Spielzeuge & Spiele > Spielzeuge > Elektronisches Spielzeug -Spielzeuge & Spiele > Spielzeuge > Elektronisches Spielzeug > Roboter Spielzeuge & Spiele > Spielzeuge > Fahr, Wipp- & Schaukelspielzeug Spielzeuge & Spiele > Spielzeuge > Fahr, Wipp- & Schaukelspielzeug > Elektrische Kinderfahrzeuge Spielzeuge & Spiele > Spielzeuge > Fahr, Wipp- & Schaukelspielzeug > Hand- & Bollerwagen @@ -4985,8 +4165,6 @@ Spielzeuge & Spiele > Spielzeuge > Fahr, Wipp- & Schaukelspielzeug > Wipp- & Sch Spielzeuge & Spiele > Spielzeuge > Ferngesteuertes Spielzeug Spielzeuge & Spiele > Spielzeuge > Ferngesteuertes Spielzeug > Ferngesteuerte Autos Spielzeuge & Spiele > Spielzeuge > Ferngesteuertes Spielzeug > Ferngesteuerte Boote -Spielzeuge & Spiele > Spielzeuge > Ferngesteuertes Spielzeug > Ferngesteuerte Boote > Ferngesteuerte U-Boote -Spielzeuge & Spiele > Spielzeuge > Ferngesteuertes Spielzeug > Ferngesteuerte Figuren Spielzeuge & Spiele > Spielzeuge > Ferngesteuertes Spielzeug > Ferngesteuerte Flugzeuge Spielzeuge & Spiele > Spielzeuge > Ferngesteuertes Spielzeug > Ferngesteuerte Hubschrauber Spielzeuge & Spiele > Spielzeuge > Ferngesteuertes Spielzeug > Ferngesteuerte Motorräder @@ -4999,7 +4177,7 @@ Spielzeuge & Spiele > Spielzeuge > Fliegendes Spielzeug > Luft- & Wasserraketen Spielzeuge & Spiele > Spielzeuge > Fliegendes Spielzeug > Spielzeug-Fallschirme Spielzeuge & Spiele > Spielzeuge > Fliegendes Spielzeug > Spielzeug-Segelflugzeuge Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug -Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug > Ball- und Becherspiele +Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug > Ball- & Becherspiele Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug > Flummis Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug > Hampelmänner Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug > Jo-Jos @@ -5011,22 +4189,23 @@ Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug > Seifenblasen-Spielze Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug > Spiele mit Bändern Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug > Springspirale Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug > Teile und Zubehör für Jo-Jos -Spielzeuge & Spiele > Spielzeuge > Interaktives Spielzeug > Teile und Zubehör für Jo-Jos > JoJo-Handschuhe Spielzeuge & Spiele > Spielzeuge > Kinder-Rollenspiele Spielzeuge & Spiele > Spielzeuge > Kinder-Rollenspiele > Berufespielzeug & Rollenspiele +Spielzeuge & Spiele > Spielzeuge > Kinder-Rollenspiele > Einkaufsladen Spielzeuge & Spiele > Spielzeuge > Kinder-Rollenspiele > Elektronisches Rollenspielzeug Spielzeuge & Spiele > Spielzeuge > Kinder-Rollenspiele > Gartengeräte für Kinder Spielzeuge & Spiele > Spielzeuge > Kinder-Rollenspiele > Haushaltsspielzeug Spielzeuge & Spiele > Spielzeuge > Kinder-Rollenspiele > Spielgeld & Banken Spielzeuge & Spiele > Spielzeuge > Kinder-Rollenspiele > Spielwerkzeug Spielzeuge & Spiele > Spielzeuge > Kinder-Rollenspiele > Spielzeugküchen & Spielzeuglebensmittel -Spielzeuge & Spiele > Spielzeuge > Kugelbäder Spielzeuge & Spiele > Spielzeuge > Lernspielzeug Spielzeuge & Spiele > Spielzeuge > Lernspielzeug > Ameisenfarmen +Spielzeuge & Spiele > Spielzeuge > Lernspielzeug > Astronomisches Spielzeug und astronomische Modelle Spielzeuge & Spiele > Spielzeuge > Lernspielzeug > Insektensammlung +Spielzeuge & Spiele > Spielzeuge > Lernspielzeug > Lernkarten Spielzeuge & Spiele > Spielzeuge > Lernspielzeug > Lesespiele Spielzeuge & Spiele > Spielzeuge > Lernspielzeug > Schieberechner -Spielzeuge & Spiele > Spielzeuge > Lernspielzeug > Wissenschafts-Sets +Spielzeuge & Spiele > Spielzeuge > Lernspielzeug > Wissenschaftssets Spielzeuge & Spiele > Spielzeuge > Musikspielzeuge Spielzeuge & Spiele > Spielzeuge > Musikspielzeuge > Spielzeuginstrumente Spielzeuge & Spiele > Spielzeuge > Optische Spielzeuge @@ -5034,11 +4213,6 @@ Spielzeuge & Spiele > Spielzeuge > Optische Spielzeuge > Kaleidoskope Spielzeuge & Spiele > Spielzeuge > Optische Spielzeuge > Prismen Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Action- & Spielzeugfiguren -Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Action- & Spielzeugfiguren > Action-Figuren -Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Action- & Spielzeugfiguren > Spielzeugsoldaten -Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Action- & Spielzeugfiguren > Tierfiguren -Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Action- & Spielzeugfiguren > Tierfiguren > Dinosaurierfiguren -Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Action- & Spielzeugfiguren > Tierfiguren > Pferde- & Ponyfiguren Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Marionetten Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Papier- & Magnetpuppen Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Puppen @@ -5050,13 +4224,11 @@ Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Wackelfiguren Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Zubehör für Puppen & Actionfiguren Spielzeuge & Spiele > Spielzeuge > Puppen, Spielkombinationen & Spielzeugfiguren > Zubehör für Puppen & Puppentheater +Spielzeuge & Spiele > Spielzeuge > Roboter Spielzeuge & Spiele > Spielzeuge > Spielfahrzeug-Zubehör -Spielzeuge & Spiele > Spielzeuge > Spielfahrzeug-Zubehör > Kinderfahrzeugteile & Zubehör -Spielzeuge & Spiele > Spielzeuge > Spielfahrzeug-Zubehör > Zubehör für Schiebefahrzeuge mit Pedalen -Spielzeuge & Spiele > Spielzeuge > Spielfahrzeug-Zubehör > Zubehör für elektrisches Spielfahrzeug -Spielzeuge & Spiele > Spielzeuge > Spielfahrzeug-Zubehör > Zubehör für elektrisches Spielfahrzeug > Ladegeräte für elektrisches Spielfahrzeug +Spielzeuge & Spiele > Spielzeuge > Spielzeug-Geschenkkörbe Spielzeuge & Spiele > Spielzeuge > Spielzeuge zum Malen & Zeichnen -Spielzeuge & Spiele > Spielzeuge > Spielzeuge zum Malen & Zeichnen > Bastelsets +Spielzeuge & Spiele > Spielzeuge > Spielzeuge zum Malen & Zeichnen > Spielteig & Knetmasse Spielzeuge & Spiele > Spielzeuge > Spielzeuge zum Malen & Zeichnen > Zeichentafeln Spielzeuge & Spiele > Spielzeuge > Spielzeugfahrzeuge Spielzeuge & Spiele > Spielzeuge > Spielzeugfahrzeuge > Rennbahnen @@ -5069,249 +4241,533 @@ Spielzeuge & Spiele > Spielzeuge > Spielzeugfahrzeuge > Spielzeugmotorräder Spielzeuge & Spiele > Spielzeuge > Spielzeugfahrzeuge > Spielzeugraumschiffe Spielzeuge & Spiele > Spielzeuge > Spielzeugfahrzeuge > Züge & Eisenbahnsets Spielzeuge & Spiele > Spielzeuge > Spielzeugwaffen -Spielzeuge & Spiele > Spielzeuge > Spielzeugwaffen > Wasserpistolen +Spielzeuge & Spiele > Spielzeuge > Spielzeugwaffenzubehör +Spielzeuge & Spiele > Spielzeuge > Sportspielzeug-Zubehör +Spielzeuge & Spiele > Spielzeuge > Sportspielzeug-Zubehör > Fitnessspielzeug-Zubehör +Spielzeuge & Spiele > Spielzeuge > Sportspielzeug-Zubehör > Fitnessspielzeug-Zubehör > Hula-Hoop-Zubehör Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge -Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > American Football für Kinder -Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > American Football für Kinder > Fußbälle aus Schaumstoff +Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Angelspielzeug Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Baseball für Kinder Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Basketball für Kinder Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Bowling für Kinder Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Bumerangs +Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Fingerboards & Fingerboard-Sets Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Fitness-Spielzeug Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Fitness-Spielzeug > Hula-Hoop-Reifen Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Footbags Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Frisbees +Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Fußball für Kinder Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Golf für Kinder Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Hockey für Kinder +Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Kinderspielbälle +Spielzeuge & Spiele > Spielzeuge > Sportspielzeuge > Spielzeugschläger Spielzeuge & Spiele > Spielzeuge > Strand- & Sandspielzeug -Spielzeuge & Spiele > Spielzeuge > Strand- & Sandspielzeug > Sandeimer -Spielzeuge & Spiele > Spielzeuge > Strand- & Sandspielzeug > Strandbälle +Spielzeuge & Spiele > Spielzeuge > Zubehör für Flugspielzeug +Spielzeuge & Spiele > Spielzeuge > Zubehör für Flugspielzeug > Zubehör für Drachen +Spielzeuge & Spiele > Spielzeuge > Zubehör für Flugspielzeug > Zubehör für Drachen > Wickelspulen für Drachen Spielzeuge & Spiele > Spielzeuge > Zubehör für Spielzeugfahrzeuge Spielzeuge & Spiele > Spielzeuge > Zubehör für Spielzeugfahrzeuge > Autorennbahn-Zubehör Spielzeuge & Spiele > Spielzeuge > Zubehör für Spielzeugfahrzeuge > Zubehör für Spielzeugeisenbahn Spielzeuge & Spiele > Spielzeuge > Zubehör für ferngesteuerte Fahrzeuge -Spielzeuge & Spiele > Spielzeuge > Zubehör für fliegendes Spielzeug -Spielzeuge & Spiele > Spielzeuge > Zubehör für fliegendes Spielzeug > Zubehör für Drachen -Spielzeuge & Spiele > Spielzeuge > Zubehör für fliegendes Spielzeug > Zubehör für Drachen > Wickelspulen für Drachen Sportartikel -Sportartikel > Kampfsport -Sportartikel > Kampfsport > Box- & Trainingssackzubehör -Sportartikel > Kampfsport > Boxen -Sportartikel > Kampfsport > Boxen > Boxhandschuhe -Sportartikel > Kampfsport > Boxen > Boxringe -Sportartikel > Kampfsport > Boxen > Boxringelemente -Sportartikel > Kampfsport > Boxen > Boxsackzubehör -Sportartikel > Kampfsport > Boxschutzbekleidung -Sportartikel > Kampfsport > Boxsäcke -Sportartikel > Kampfsport > Fechten -Sportartikel > Kampfsport > Fechten > Fechtschutzbekleidung -Sportartikel > Kampfsport > Fechten > Fechtschutzbekleidung > Fechthandschuhe -Sportartikel > Kampfsport > Fechten > Fechtschutzbekleidung > Fechtmasken -Sportartikel > Kampfsport > Kampfkunst -Sportartikel > Kampfsport > Kampfkunst > Kampfsportgürtel -Sportartikel > Kampfsport > Ringen -Sportartikel > Kampfsport > Ringen > Ringermatten -Sportartikel > Kampfsport > Ringen > Schutzbekleidung für Ringer -Sportartikel > Kampfsport > Training-Dummys -Sportartikel > Luftsport -Sportartikel > Luftsport > Drachenfliegen -Sportartikel > Luftsport > Drachenfliegen > Hängegleiter -Sportartikel > Luftsport > Fallschirme -Sportartikel > Luftsport > Fluganzüge -Sportartikel > Mannschaftssportarten -Sportartikel > Mannschaftssportarten > American Football -Sportartikel > Mannschaftssportarten > American Football > American Football-Handschuhe -Sportartikel > Mannschaftssportarten > American Football > American Football-Kicking Tees -Sportartikel > Mannschaftssportarten > American Football > American Football-Schutzbekleidung -Sportartikel > Mannschaftssportarten > American Football > American Football-Schutzbekleidung > American Football-Girdle Shorts -Sportartikel > Mannschaftssportarten > American Football > American Football-Schutzbekleidung > American Football-Helme -Sportartikel > Mannschaftssportarten > American Football > American Football-Schutzbekleidung > American Football-Helmzubehör -Sportartikel > Mannschaftssportarten > American Football > American Football-Schutzbekleidung > American Football-Helmzubehör > American Football-Facemasks -Sportartikel > Mannschaftssportarten > American Football > American Football-Schutzbekleidung > American Football-Helmzubehör > American Football-Helmpolster -Sportartikel > Mannschaftssportarten > American Football > American Football-Schutzbekleidung > American Football-Helmzubehör > American Football-Helmvisiere -Sportartikel > Mannschaftssportarten > American Football > American Football-Schutzbekleidung > American Football-Helmzubehör > American Football-Kinnriemen -Sportartikel > Mannschaftssportarten > American Football > American Football-Schutzbekleidung > American Football-Nackenschutz -Sportartikel > Mannschaftssportarten > American Football > American Football-Schutzbekleidung > American Football-Schulterpads -Sportartikel > Mannschaftssportarten > American Football > American Football-Torstangen -Sportartikel > Mannschaftssportarten > American Football > American Football-Trainingsausrüstung -Sportartikel > Mannschaftssportarten > American Football > Football-Bälle -Sportartikel > Mannschaftssportarten > Ballpumpen -Sportartikel > Mannschaftssportarten > Balltaschen -Sportartikel > Mannschaftssportarten > Baseball -Sportartikel > Mannschaftssportarten > Baseball > Baseball- & Softballhandschuhe -Sportartikel > Mannschaftssportarten > Baseball > Baseball- & Softballhandschuhe > Baseballhandschuhe -Sportartikel > Mannschaftssportarten > Baseball > Baseball- & Softballhandschuhe > Softballhandschuhe -Sportartikel > Mannschaftssportarten > Baseball > Baseball-Bases -Sportartikel > Mannschaftssportarten > Baseball > Baseball-Bälle -Sportartikel > Mannschaftssportarten > Baseball > Baseball-Schutzbekleidung -Sportartikel > Mannschaftssportarten > Baseball > Baseball-Schutzbekleidung > Baseballhelme -Sportartikel > Mannschaftssportarten > Baseball > Baseballnetze -Sportartikel > Mannschaftssportarten > Baseball > Baseballschläger -Sportartikel > Mannschaftssportarten > Baseball > Schlaghandschuhe -Sportartikel > Mannschaftssportarten > Baseball > Wurfmaschinen -Sportartikel > Mannschaftssportarten > Basketball -Sportartikel > Mannschaftssportarten > Basketball > Basketballkorbteile & -zubehör -Sportartikel > Mannschaftssportarten > Basketball > Basketballkorbteile & -zubehör > Basketball-Korbbretter -Sportartikel > Mannschaftssportarten > Basketball > Basketballkorbteile & -zubehör > Basketballnetze -Sportartikel > Mannschaftssportarten > Basketball > Basketballkorbteile & -zubehör > Basketballpfosten -Sportartikel > Mannschaftssportarten > Basketball > Basketballkorbteile & -zubehör > Basketballringe -Sportartikel > Mannschaftssportarten > Basketball > Basketballkorbteile & -zubehör > Schutzverkleidung für Basketballkorb -Sportartikel > Mannschaftssportarten > Basketball > Basketballkörbe -Sportartikel > Mannschaftssportarten > Basketball > Basketbälle -Sportartikel > Mannschaftssportarten > Beachvolleyball -Sportartikel > Mannschaftssportarten > Beachvolleyball > Beachvolleyball-Bälle -Sportartikel > Mannschaftssportarten > Beachvolleyball > Beachvolleyball-Netze -Sportartikel > Mannschaftssportarten > Broomball -Sportartikel > Mannschaftssportarten > Broomball > Broomballschläger -Sportartikel > Mannschaftssportarten > Cheerleading -Sportartikel > Mannschaftssportarten > Cheerleading > Cheerleading-Megaphone -Sportartikel > Mannschaftssportarten > Cheerleading > Pom-Poms -Sportartikel > Mannschaftssportarten > Cricket -Sportartikel > Mannschaftssportarten > Cricket > Cricketbälle -Sportartikel > Mannschaftssportarten > Cricket > Crickethandschuhe -Sportartikel > Mannschaftssportarten > Cricket > Crickethelme -Sportartikel > Mannschaftssportarten > Cricket > Cricketschläger -Sportartikel > Mannschaftssportarten > Curling -Sportartikel > Mannschaftssportarten > Feldhockey -Sportartikel > Mannschaftssportarten > Feldhockey > Feldhockeybälle -Sportartikel > Mannschaftssportarten > Feldhockey > Feldhockeyhandschuhe -Sportartikel > Mannschaftssportarten > Feldhockey > Feldhockeyschläger -Sportartikel > Mannschaftssportarten > Feldhockey > Feldhockeytore -Sportartikel > Mannschaftssportarten > Fußball -Sportartikel > Mannschaftssportarten > Fußball > Eckfahnen -Sportartikel > Mannschaftssportarten > Fußball > Fußball-Kapitänsbinden -Sportartikel > Mannschaftssportarten > Fußball > Fußballschienbeinschützer -Sportartikel > Mannschaftssportarten > Fußball > Fußballtore & -netze -Sportartikel > Mannschaftssportarten > Fußball > Fußbälle -Sportartikel > Mannschaftssportarten > Fußball > Fußbälle > Futsal-Bälle -Sportartikel > Mannschaftssportarten > Fußball > Torwarthandschuhe -Sportartikel > Mannschaftssportarten > Fußball > Zubehör für Fußballtore -Sportartikel > Mannschaftssportarten > Handball -Sportartikel > Mannschaftssportarten > Hockey -Sportartikel > Mannschaftssportarten > Hockey > Hockey-Schutzausrüstung -Sportartikel > Mannschaftssportarten > Hockey > Hockey-Schutzausrüstung > Hockey-Körperpolster -Sportartikel > Mannschaftssportarten > Hockey > Hockey-Schutzausrüstung > Hockeyhandschuhe -Sportartikel > Mannschaftssportarten > Hockey > Hockey-Schutzausrüstung > Hockeyhandschuhe > Eishockeyhandschuhe -Sportartikel > Mannschaftssportarten > Hockey > Hockey-Schutzausrüstung > Hockeyhelme -Sportartikel > Mannschaftssportarten > Hockey > Hockey-Schutzausrüstung > Hockeyhelme > Eishockeyhelme -Sportartikel > Mannschaftssportarten > Hockey > Hockey-Schutzausrüstung > Hockeyhosen -Sportartikel > Mannschaftssportarten > Hockey > Hockeybälle & Pucks -Sportartikel > Mannschaftssportarten > Hockey > Hockeybälle & Pucks > Hockeypucks -Sportartikel > Mannschaftssportarten > Hockey > Hockeybälle & Pucks > Rollhockeybälle -Sportartikel > Mannschaftssportarten > Hockey > Hockeyschlitten -Sportartikel > Mannschaftssportarten > Hockey > Hockeyschläger -Sportartikel > Mannschaftssportarten > Hockey > Hockeyschläger > Eishockeyschläger -Sportartikel > Mannschaftssportarten > Hockey > Hockeyschläger > Hockeyschlager für Street- und Rollhockey -Sportartikel > Mannschaftssportarten > Hockey > Hockeyschlägerpflege -Sportartikel > Mannschaftssportarten > Hockey > Hockeyschlägerteile -Sportartikel > Mannschaftssportarten > Hockey > Hockeyschlägerteile > Hockeyschlägerkellen -Sportartikel > Mannschaftssportarten > Hockey > Hockeyschlägerteile > Hockeyschlägerschäfte -Sportartikel > Mannschaftssportarten > Hockey > Hockeytore -Sportartikel > Mannschaftssportarten > Hockey > Hockeytore > Eishockeytore -Sportartikel > Mannschaftssportarten > Lacrosse -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Bälle -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schläger -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schlägerteile -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schlägerteile > Lacrosse-Schlägerköpfe -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schlägerteile > Lacrosse-Schlägernetze & Strings -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schlägerteile > Lacrosse-Schlägerschäfte -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schutzbekleidung -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schutzbekleidung > Lacrosse-Armschutz -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schutzbekleidung > Lacrosse-Augenschutz -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schutzbekleidung > Lacrosse-Handschuhe -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schutzbekleidung > Lacrosse-Helme -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Schutzbekleidung > Lacrosse-Schulterschutz -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Tore -Sportartikel > Mannschaftssportarten > Lacrosse > Lacrosse-Trainingsausrüstung -Sportartikel > Mannschaftssportarten > Rounders -Sportartikel > Mannschaftssportarten > Rounders > Rounders-Handschuhe -Sportartikel > Mannschaftssportarten > Rounders > Rounders-Schläger -Sportartikel > Mannschaftssportarten > Rugby -Sportartikel > Mannschaftssportarten > Rugby > Rugby-Bälle -Sportartikel > Mannschaftssportarten > Rugby > Rugby-Handschuhe -Sportartikel > Mannschaftssportarten > Rugby > Rugby-Helme -Sportartikel > Mannschaftssportarten > Rugby > Rugby-Tore -Sportartikel > Mannschaftssportarten > Rugby > Rugby-Trainingsausrüstung -Sportartikel > Mannschaftssportarten > Schiedsrichterausrüstung -Sportartikel > Mannschaftssportarten > Schiedsrichterausrüstung > Linienrichterfahnen -Sportartikel > Mannschaftssportarten > Schiedsrichterausrüstung > Schiedsrichterpfeifen -Sportartikel > Mannschaftssportarten > Schiedsrichterausrüstung > Strafkarten -Sportartikel > Mannschaftssportarten > Softball -Sportartikel > Mannschaftssportarten > Softball > Softball-Bälle -Sportartikel > Mannschaftssportarten > Softball > Softball-Schutzbekleidung -Sportartikel > Mannschaftssportarten > Softball > Softballschläger -Sportartikel > Mannschaftssportarten > Volleyball -Sportartikel > Mannschaftssportarten > Volleyball > Volleyball-Bälle -Sportartikel > Mannschaftssportarten > Volleyball > Volleyballnetze -Sportartikel > Mannschaftssportarten > Volleyball > Volleyballtaschen -Sportartikel > Mannschaftssportarten > Zubehör zum Aufpumpen von Bällen -Sportartikel > Mannschaftssportarten > Zubehör zum Aufpumpen von Bällen > Ballpumpenaufsätze +Sportartikel > Athletik +Sportartikel > Athletik > Allgemeine Sportartikel +Sportartikel > Athletik > Allgemeine Sportartikel > Ablagen & Transportwagen für Gymnastikmatten +Sportartikel > Athletik > Allgemeine Sportartikel > Ballpumpen +Sportartikel > Athletik > Allgemeine Sportartikel > Ballpumpenzubehör +Sportartikel > Athletik > Allgemeine Sportartikel > Ballpumpenzubehör > Ballpumpenaufsätze +Sportartikel > Athletik > Allgemeine Sportartikel > Balltaschen & -wagen +Sportartikel > Athletik > Allgemeine Sportartikel > Chalk +Sportartikel > Athletik > Allgemeine Sportartikel > Gymnastikmatten +Sportartikel > Athletik > Allgemeine Sportartikel > Leitern & Hürden für Geschwindigkeits- & Koordinationstraining +Sportartikel > Athletik > Allgemeine Sportartikel > Markierungshütchen +Sportartikel > Athletik > Allgemeine Sportartikel > Masken für Höhentraining +Sportartikel > Athletik > Allgemeine Sportartikel > Megaphone für Sportveranstaltungen +Sportartikel > Athletik > Allgemeine Sportartikel > Sport-Mundschutz +Sportartikel > Athletik > Allgemeine Sportartikel > Stadionsitze und Polster +Sportartikel > Athletik > Allgemeine Sportartikel > Suspensorien für Athleten +Sportartikel > Athletik > Allgemeine Sportartikel > Übungsnetze +Sportartikel > Athletik > American Football +Sportartikel > Athletik > American Football > American Football-Handschuhe +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung > American Football-Girdle Shorts +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung > American Football-Helme +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung > American Football-Helmzubehör +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung > American Football-Helmzubehör > American Football-Facemasks +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung > American Football-Helmzubehör > American Football-Helmpolster +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung > American Football-Helmzubehör > American Football-Helmvisiere +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung > American Football-Helmzubehör > American Football-Kinnriemen +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung > American Football-Nackenschutz +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung > American Football-Schulterpads +Sportartikel > Athletik > American Football > American Football-Schutzbekleidung > Schutz-Shirts und -Hemden +Sportartikel > Athletik > American Football > American Football-Torstangen +Sportartikel > Athletik > American Football > American Football-Trainingsausrüstung +Sportartikel > Athletik > American Football > American Football-Trainingsausrüstung > Dummys & Schlitten +Sportartikel > Athletik > American Football > Football-Bälle +Sportartikel > Athletik > American Football > Kicking Tees & Halter für Fußbälle +Sportartikel > Athletik > Baseball & Softball +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softball-Bases +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softball-Schlaghandschuhe +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softball-Schutzkleidung +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softball-Schutzkleidung > Ausrüstung für Fänger +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softball-Schutzkleidung > Baseball- & Softball-Brustpanzer +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softball-Schutzkleidung > Baseball- & Softball-Knie- & Schienbeinschoner +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softball-Schutzkleidung > Baseball- & Softballhelme +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softball-Schutzkleidung > Schutzhelme für Fänger +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softball-Wurfhügel +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softball-Wurfmale +Sportartikel > Athletik > Baseball & Softball > Baseball- & Softballhandschuhe +Sportartikel > Athletik > Baseball & Softball > Baseball-Bälle +Sportartikel > Athletik > Baseball & Softball > Baseballschläger +Sportartikel > Athletik > Baseball & Softball > Softball-Bälle +Sportartikel > Athletik > Baseball & Softball > Softballschläger +Sportartikel > Athletik > Baseball & Softball > Wurfmaschinen +Sportartikel > Athletik > Basketball +Sportartikel > Athletik > Basketball > Basketball-Trainingshilfen +Sportartikel > Athletik > Basketball > Basketballkorbteile & -zubehör +Sportartikel > Athletik > Basketball > Basketballkorbteile & -zubehör > Basketball-Korbbretter +Sportartikel > Athletik > Basketball > Basketballkorbteile & -zubehör > Basketballnetze +Sportartikel > Athletik > Basketball > Basketballkorbteile & -zubehör > Basketballringe +Sportartikel > Athletik > Basketball > Basketballkorbteile & -zubehör > Basketballständer +Sportartikel > Athletik > Basketball > Basketballkorbteile & -zubehör > Schutzverkleidung für Basketballkörbe +Sportartikel > Athletik > Basketball > Basketballkörbe +Sportartikel > Athletik > Basketball > Basketbälle +Sportartikel > Athletik > Boxen & Kampfsport +Sportartikel > Athletik > Boxen & Kampfsport > Boxringe +Sportartikel > Athletik > Boxen & Kampfsport > Boxringelemente +Sportartikel > Athletik > Boxen & Kampfsport > Boxschutzbekleidung +Sportartikel > Athletik > Boxen & Kampfsport > Boxschutzbekleidung > Armschutz +Sportartikel > Athletik > Boxen & Kampfsport > Boxschutzbekleidung > Boxhandschuhe +Sportartikel > Athletik > Boxen & Kampfsport > Boxschutzbekleidung > Handbandagen +Sportartikel > Athletik > Boxen & Kampfsport > Boxschutzbekleidung > Kopfschutz +Sportartikel > Athletik > Boxen & Kampfsport > Boxschutzbekleidung > Körperschutz +Sportartikel > Athletik > Boxen & Kampfsport > Boxschutzbekleidung > Schienbeinschoner +Sportartikel > Athletik > Boxen & Kampfsport > Kampfsportgürtel +Sportartikel > Athletik > Boxen & Kampfsport > Kampfsportwaffen +Sportartikel > Athletik > Boxen & Kampfsport > Trainingsausrüstung für Boxen & Kampfsport +Sportartikel > Athletik > Boxen & Kampfsport > Trainingsausrüstung für Boxen & Kampfsport > Box- & Trainingssackzubehör +Sportartikel > Athletik > Boxen & Kampfsport > Trainingsausrüstung für Boxen & Kampfsport > Box- & Trainingssäcke +Sportartikel > Athletik > Boxen & Kampfsport > Trainingsausrüstung für Boxen & Kampfsport > Boxpratzen +Sportartikel > Athletik > Boxen & Kampfsport > Trainingsausrüstung für Boxen & Kampfsport > Schlagpolster +Sportartikel > Athletik > Boxen & Kampfsport > Trainingsausrüstung für Boxen & Kampfsport > Training-Dummys +Sportartikel > Athletik > Broomball-Ausrüstung +Sportartikel > Athletik > Cheerleading +Sportartikel > Athletik > Cheerleading > Cheerleader-Pompons +Sportartikel > Athletik > Cricket +Sportartikel > Athletik > Cricket > Cricket-Aussrüstungssets +Sportartikel > Athletik > Cricket > Cricket-Schutzkleidung +Sportartikel > Athletik > Cricket > Cricket-Schutzkleidung > Cricket-Beinschutz +Sportartikel > Athletik > Cricket > Cricket-Schutzkleidung > Crickethandschuhe +Sportartikel > Athletik > Cricket > Cricket-Schutzkleidung > Crickethelme +Sportartikel > Athletik > Cricket > Cricketbälle +Sportartikel > Athletik > Cricket > Cricketschläger +Sportartikel > Athletik > Cricket > Cricketschläger-Zubehör +Sportartikel > Athletik > Cricket > Cricketschläger-Zubehör > Cricketschläger-Griffe +Sportartikel > Athletik > Cricket > Cricketstäbe +Sportartikel > Athletik > Eiskunstlauf & Hockey +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockey-Schutzausrüstung +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockey-Schutzausrüstung > Ausrüstungssets für Torwarte +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockey-Schutzausrüstung > Eishockeyhosenträger und -gürtel +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockey-Schutzausrüstung > Hockey-Ellenbogenschutz +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockey-Schutzausrüstung > Hockey-Schienbeinschoner & -Beinschutz +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockey-Schutzausrüstung > Hockey-Schulterpolster & -Brustpolster +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockey-Schutzausrüstung > Hockeyhandschuhe +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockey-Schutzausrüstung > Hockeyhelme +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockey-Schutzausrüstung > Hockeyhosen +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockeybälle & Pucks +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockeyschlitten +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockeyschläger +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockeyschlägerpflege +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockeyschlägerteile +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockeyschlägerteile > Hockey-Schlägerschäfte +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockeyschlägerteile > Hockeyschlägerkellen +Sportartikel > Athletik > Eiskunstlauf & Hockey > Hockeytore +Sportartikel > Athletik > Eiskunstlauf & Hockey > Schlittschuhe +Sportartikel > Athletik > Eiskunstlauf & Hockey > Schlittschuhzubehör +Sportartikel > Athletik > Eiskunstlauf & Hockey > Schlittschuhzubehör > Eiskunstlaufstiefel +Sportartikel > Athletik > Eiskunstlauf & Hockey > Schlittschuhzubehör > Kufenschoner +Sportartikel > Athletik > Eiskunstlauf & Hockey > Schlittschuhzubehör > Schlittschuhkufen +Sportartikel > Athletik > Eiskunstlauf & Hockey > Schlittschuhzubehör > Schlittschuhschleifer +Sportartikel > Athletik > Eiskunstlauf & Hockey > Schlittschuhzubehör > Schnürhilfen +Sportartikel > Athletik > Fechten +Sportartikel > Athletik > Fechten > Fechtschutzbekleidung +Sportartikel > Athletik > Fechten > Fechtschutzbekleidung > Fechthandschuhe +Sportartikel > Athletik > Fechten > Fechtschutzbekleidung > Fechtjacken & -E-Westen +Sportartikel > Athletik > Fechten > Fechtschutzbekleidung > Fechtmasken +Sportartikel > Athletik > Fechten > Sportfechtwaffen +Sportartikel > Athletik > Feldhockey & Lacrosse +Sportartikel > Athletik > Feldhockey & Lacrosse > Feldhockey- & Lacrosse-Schutzkleidung +Sportartikel > Athletik > Feldhockey & Lacrosse > Feldhockey- & Lacrosse-Schutzkleidung > Feldhockey- & Lacrosse-Handschuhe +Sportartikel > Athletik > Feldhockey & Lacrosse > Feldhockey- & Lacrosse-Schutzkleidung > Feldhockey- & Lacrosse-Pads +Sportartikel > Athletik > Feldhockey & Lacrosse > Feldhockey- & Lacrosse-Schutzkleidung > Hockey- & Lacrosse-Helme +Sportartikel > Athletik > Feldhockey & Lacrosse > Feldhockey- & Lacrosse-Schutzkleidung > Masken & Schutzbrillen +Sportartikel > Athletik > Feldhockey & Lacrosse > Feldhockeybälle +Sportartikel > Athletik > Feldhockey & Lacrosse > Feldhockeyschläger +Sportartikel > Athletik > Feldhockey & Lacrosse > Feldhockeytore +Sportartikel > Athletik > Feldhockey & Lacrosse > Lacrosse-Ausrüstungen +Sportartikel > Athletik > Feldhockey & Lacrosse > Lacrosse-Bälle +Sportartikel > Athletik > Feldhockey & Lacrosse > Lacrosse-Schläger +Sportartikel > Athletik > Feldhockey & Lacrosse > Lacrosse-Schlägerteile +Sportartikel > Athletik > Feldhockey & Lacrosse > Lacrosse-Schlägerteile > Lacrosse-Schlägerköpfe +Sportartikel > Athletik > Feldhockey & Lacrosse > Lacrosse-Schlägerteile > Lacrosse-Schlägernetze & Strings +Sportartikel > Athletik > Feldhockey & Lacrosse > Lacrosse-Schlägerteile > Lacrosse-Schlägerschäfte +Sportartikel > Athletik > Feldhockey & Lacrosse > Lacrosse-Tore +Sportartikel > Athletik > Feldhockey & Lacrosse > Lacrosse-Trainingszubehör +Sportartikel > Athletik > Fußball +Sportartikel > Athletik > Fußball > Eckfahnen +Sportartikel > Athletik > Fußball > Fußball-Schutzkleidung +Sportartikel > Athletik > Fußball > Fußball-Schutzkleidung > Fußballschienbeinschützer +Sportartikel > Athletik > Fußball > Fußballtore & -netze +Sportartikel > Athletik > Fußball > Fußbälle +Sportartikel > Athletik > Fußball > Torwarthandschuhe +Sportartikel > Athletik > Fußball > Zubehör für Fußballtore +Sportartikel > Athletik > Handball +Sportartikel > Athletik > Handball > Handbälle +Sportartikel > Athletik > Leichtathletik +Sportartikel > Athletik > Leichtathletik > Diskusscheiben +Sportartikel > Athletik > Leichtathletik > Hochsprunglatten +Sportartikel > Athletik > Leichtathletik > Hochsprungmatten +Sportartikel > Athletik > Leichtathletik > Hürden +Sportartikel > Athletik > Leichtathletik > Kugelstoß-Kugeln +Sportartikel > Athletik > Leichtathletik > Speere +Sportartikel > Athletik > Leichtathletik > Stabhochsprungmatten +Sportartikel > Athletik > Leichtathletik > Stabhochsprungstäbe +Sportartikel > Athletik > Leichtathletik > Staffelstäbe +Sportartikel > Athletik > Leichtathletik > Startblöcke +Sportartikel > Athletik > Leichtathletik > Startpistolen +Sportartikel > Athletik > Leichtathletik > Wurfhämmer +Sportartikel > Athletik > Racquetball & Squash +Sportartikel > Athletik > Racquetball & Squash > Racquetball- & Squash-Bälle +Sportartikel > Athletik > Racquetball & Squash > Racquetball-Schläger +Sportartikel > Athletik > Racquetball & Squash > Squash- & Racquetball-Handschuhe +Sportartikel > Athletik > Racquetball & Squash > Squash- & Racquetball-Schutzbrillen +Sportartikel > Athletik > Racquetball & Squash > Squashschläger +Sportartikel > Athletik > Ringen +Sportartikel > Athletik > Ringen > Schutzbekleidung für Ringer +Sportartikel > Athletik > Ringen > Schutzbekleidung für Ringer > Ringer-Kniepolster +Sportartikel > Athletik > Ringen > Schutzbekleidung für Ringer > Ringer-Kopfschutz +Sportartikel > Athletik > Rounders +Sportartikel > Athletik > Rounders > Rounders-Handschuhe +Sportartikel > Athletik > Rounders > Rounders-Schläger +Sportartikel > Athletik > Rugby +Sportartikel > Athletik > Rugby > Rugby-Bälle +Sportartikel > Athletik > Rugby > Rugby-Handschuhe +Sportartikel > Athletik > Rugby > Rugby-Schutzkleidung +Sportartikel > Athletik > Rugby > Rugby-Schutzkleidung > Rugby-Helme +Sportartikel > Athletik > Rugby > Rugby-Tore +Sportartikel > Athletik > Rugby > Rugby-Trainingsausrüstung +Sportartikel > Athletik > Tanzen +Sportartikel > Athletik > Tanzen > Ballettstangen +Sportartikel > Athletik > Tennis +Sportartikel > Athletik > Tennis > Tennisballdosen +Sportartikel > Athletik > Tennis > Tennisballkörbe & -wagen +Sportartikel > Athletik > Tennis > Tennisballwurfmaschinen +Sportartikel > Athletik > Tennis > Tennisbälle +Sportartikel > Athletik > Tennis > Tennisnetze +Sportartikel > Athletik > Tennis > Tennisschläger +Sportartikel > Athletik > Tennis > Tennisschlägerzubehör +Sportartikel > Athletik > Tennis > Tennisschlägerzubehör > Griffbänder +Sportartikel > Athletik > Tennis > Tennisschlägerzubehör > Schlägerdämpfer +Sportartikel > Athletik > Tennis > Tennisschlägerzubehör > Tennissaiten +Sportartikel > Athletik > Tennis > Tennisschlägerzubehör > Tennistaschen +Sportartikel > Athletik > Tennis > Tennisschlägerzubehör > Ösenbänder für Tennisschläger +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Anzeigetafeln +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Begrenzungsmarkierungen für Spielfelder +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Handzähler +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Kapitänsbinden +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Linienrichterfahnen +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Pitch Counter +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Schiedsrichter- & Trainerpfeifen +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Schiedsrichter-Münzen +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Schiedsrichtermappen +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Schiedsrichterstände & -stühle +Sportartikel > Athletik > Trainer- & Schiedsrichterausrüstung > Strafkarten & -flaggen +Sportartikel > Athletik > Turnen +Sportartikel > Athletik > Turnen > Pauschenpferde +Sportartikel > Athletik > Turnen > Schutzausrüstung +Sportartikel > Athletik > Turnen > Schutzausrüstung > Turner-Handbandagen +Sportartikel > Athletik > Turnen > Sprungpferde +Sportartikel > Athletik > Turnen > Turnringe +Sportartikel > Athletik > Turnen > Turnsprungbretter +Sportartikel > Athletik > Turnen > Turnstangen & Schwebebalken +Sportartikel > Athletik > Volleyball +Sportartikel > Athletik > Volleyball > Volleyball-Schutzkleidung +Sportartikel > Athletik > Volleyball > Volleyball-Schutzkleidung > Volleyball-Knieschoner +Sportartikel > Athletik > Volleyball > Volleyball-Trainingshilfen +Sportartikel > Athletik > Volleyball > Volleyballnetze +Sportartikel > Athletik > Volleyball > Volleybälle +Sportartikel > Athletik > Wallyball-Ausrüstung +Sportartikel > Athletik > Wasserball +Sportartikel > Athletik > Wasserball > Wasserballkappen +Sportartikel > Athletik > Wasserball > Wasserballtore +Sportartikel > Athletik > Wasserball > Wasserbälle +Sportartikel > Fitness +Sportartikel > Fitness > Balancetrainer +Sportartikel > Fitness > Bauchtrainer +Sportartikel > Fitness > Cardio +Sportartikel > Fitness > Cardio > Cardiogeräte +Sportartikel > Fitness > Cardio > Cardiogeräte > Crosstrainer +Sportartikel > Fitness > Cardio > Cardiogeräte > Heimtrainer +Sportartikel > Fitness > Cardio > Cardiogeräte > Laufbänder +Sportartikel > Fitness > Cardio > Cardiogeräte > Rudergeräte +Sportartikel > Fitness > Cardio > Cardiogeräte > Stepper +Sportartikel > Fitness > Cardio > Springseile +Sportartikel > Fitness > Cardio > Zubehör für Cardiogeräte +Sportartikel > Fitness > Cardio > Zubehör für Cardiogeräte > Crosstrainer-Zubehör +Sportartikel > Fitness > Cardio > Zubehör für Cardiogeräte > Heimtrainer-Zubehör +Sportartikel > Fitness > Cardio > Zubehör für Cardiogeräte > Laufbandzubehör +Sportartikel > Fitness > Cardio > Zubehör für Cardiogeräte > Rudergerät-Zubehör +Sportartikel > Fitness > Cardio > Zubehör für Cardiogeräte > Stepper-Zubehör +Sportartikel > Fitness > Fitnessbänder +Sportartikel > Fitness > Fitnessgeräte-Sets +Sportartikel > Fitness > Gewichtheben +Sportartikel > Fitness > Gewichtheben > Gewichthebergürtel +Sportartikel > Fitness > Gewichtheben > Gewichtheberhandschuhe & Handgelenkschoner +Sportartikel > Fitness > Gewichtheben > Hanteln +Sportartikel > Fitness > Gewichtheben > Hantelzubehör +Sportartikel > Fitness > Gewichtheben > Hantelzubehör > Hantelstangen +Sportartikel > Fitness > Gewichtheben > Hantelzubehör > Hantelstangen-Feststellringe +Sportartikel > Fitness > Gewichtheben > Hantelzubehör > Hantelständer +Sportartikel > Fitness > Gewichtheben > Krafttrainingsgeräte +Sportartikel > Fitness > Gewichtheben > Zubehör für Krafttrainingsgeräte +Sportartikel > Fitness > Gewichtswesten & -manschetten +Sportartikel > Fitness > Gymnastikbälle +Sportartikel > Fitness > Handtrainer +Sportartikel > Fitness > Inversionstische +Sportartikel > Fitness > Keilmatten +Sportartikel > Fitness > Klimmzugstangen +Sportartikel > Fitness > Matten für Heimtrainer +Sportartikel > Fitness > Medizinbälle +Sportartikel > Fitness > Power Tower +Sportartikel > Fitness > Reaktionsbälle +Sportartikel > Fitness > Schaumroller +Sportartikel > Fitness > Schaumroller-Zubehör +Sportartikel > Fitness > Schaumroller-Zubehör > Aufbewahrungstaschen für Schaumroller +Sportartikel > Fitness > Sicherheitslichter & -reflektoren für Sport +Sportartikel > Fitness > Steppbretter +Sportartikel > Fitness > Stoppuhren +Sportartikel > Fitness > Suspension Trainer +Sportartikel > Fitness > Trainings- & Bremsschirme +Sportartikel > Fitness > Trainingsbänke +Sportartikel > Fitness > Vibrationstrainer +Sportartikel > Fitness > Yoga & Pilates +Sportartikel > Fitness > Yoga & Pilates > Beutel für Yogamatten +Sportartikel > Fitness > Yoga & Pilates > Pilates-Geräte +Sportartikel > Fitness > Yoga & Pilates > Yoga- & Pilatesblöcke +Sportartikel > Fitness > Yoga & Pilates > Yoga- & Pilatesmatten +Sportartikel > Fitness > Yoga & Pilates > Yoga- & Pilatestücher +Sportartikel > Indoor - Aktivitäten +Sportartikel > Indoor - Aktivitäten > Air-Hockey +Sportartikel > Indoor - Aktivitäten > Air-Hockey > Air-Hockey-Ausrüstung +Sportartikel > Indoor - Aktivitäten > Air-Hockey > Air-Hockey-Tische +Sportartikel > Indoor - Aktivitäten > Air-Hockey > Air-Hockey-Tischzubehör +Sportartikel > Indoor - Aktivitäten > Billard +Sportartikel > Indoor - Aktivitäten > Billard > Billarddreiecke +Sportartikel > Indoor - Aktivitäten > Billard > Billardhandschuhe +Sportartikel > Indoor - Aktivitäten > Billard > Billardkugeln +Sportartikel > Indoor - Aktivitäten > Billard > Billardqueues & Queuebrücken +Sportartikel > Indoor - Aktivitäten > Billard > Billardtisch-Beleuchtung +Sportartikel > Indoor - Aktivitäten > Billard > Billardtisch-Teile & Zubehör +Sportartikel > Indoor - Aktivitäten > Billard > Billardtisch-Teile & Zubehör > Ballfangtaschen +Sportartikel > Indoor - Aktivitäten > Billard > Billardtisch-Teile & Zubehör > Billardtisch-Bürsten +Sportartikel > Indoor - Aktivitäten > Billard > Billardtisch-Teile & Zubehör > Billardtücher +Sportartikel > Indoor - Aktivitäten > Billard > Billardtisch-Teile & Zubehör > Billiardtischabdeckungen +Sportartikel > Indoor - Aktivitäten > Billard > Billardtische +Sportartikel > Indoor - Aktivitäten > Billard > Queuezubehör +Sportartikel > Indoor - Aktivitäten > Billard > Queuezubehör > Billiardkoffer +Sportartikel > Indoor - Aktivitäten > Billard > Queuezubehör > Billiardkreide +Sportartikel > Indoor - Aktivitäten > Billard > Queuezubehör > Queueständer +Sportartikel > Indoor - Aktivitäten > Bowling +Sportartikel > Indoor - Aktivitäten > Bowling > Bowling-Handgelenkstützen +Sportartikel > Indoor - Aktivitäten > Bowling > Bowlinghandschuhe +Sportartikel > Indoor - Aktivitäten > Bowling > Bowlingkegel +Sportartikel > Indoor - Aktivitäten > Bowling > Bowlingkugeln +Sportartikel > Indoor - Aktivitäten > Bowling > Bowlingtaschen +Sportartikel > Indoor - Aktivitäten > Dartspiele +Sportartikel > Indoor - Aktivitäten > Dartspiele > Dart-Rückwände +Sportartikel > Indoor - Aktivitäten > Dartspiele > Dartpfeile +Sportartikel > Indoor - Aktivitäten > Dartspiele > Dartscheiben +Sportartikel > Indoor - Aktivitäten > Dartspiele > Dartteile +Sportartikel > Indoor - Aktivitäten > Dartspiele > Dartteile > Dartflights +Sportartikel > Indoor - Aktivitäten > Dartspiele > Dartteile > Dartschäfte +Sportartikel > Indoor - Aktivitäten > Dartspiele > Dartteile > Dartspitzen +Sportartikel > Indoor - Aktivitäten > Jakkolo +Sportartikel > Indoor - Aktivitäten > Jakkolo > Jakkolo-Pulver +Sportartikel > Indoor - Aktivitäten > Jakkolo > Jakkolo-Spielsteine +Sportartikel > Indoor - Aktivitäten > Jakkolo > Shuffleboard-Tische +Sportartikel > Indoor - Aktivitäten > Multispieltische +Sportartikel > Indoor - Aktivitäten > Tischfußball +Sportartikel > Indoor - Aktivitäten > Tischfußball > Tischfußball-Bälle +Sportartikel > Indoor - Aktivitäten > Tischfußball > Tischfußball-Tische +Sportartikel > Indoor - Aktivitäten > Tischfußball > Zubehör für Tischfußballtische +Sportartikel > Indoor - Aktivitäten > Tischtennis +Sportartikel > Indoor - Aktivitäten > Tischtennis > Tischtennis-Roboter +Sportartikel > Indoor - Aktivitäten > Tischtennis > Tischtennisbälle +Sportartikel > Indoor - Aktivitäten > Tischtennis > Tischtennisnetze und -pfosten +Sportartikel > Indoor - Aktivitäten > Tischtennis > Tischtennisplatten +Sportartikel > Indoor - Aktivitäten > Tischtennis > Tischtennisschläger & -sets +Sportartikel > Indoor - Aktivitäten > Tischtennis > Zubehör für Tischtennis-Roboter +Sportartikel > Indoor - Aktivitäten > Tischtennis > Zubehör für Tischtennisschläger Sportartikel > Outdoor-Aktivitäten Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen -Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelblei -Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelhaken +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelgeräte +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelgeräte > Angelblei +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelgeräte > Angelhaken +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelgeräte > Karabiner & Wirbel +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelgeräte > Kunstköder +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelgeräte > Schwimmer Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelkästen & Angeltaschen Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelleinen & -wirbel Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelrollen +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelrollen-Zubehör +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelrollen-Zubehör > Ersatzspulen +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelrollen-Zubehör > Schmierstoffe +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelrollen-Zubehör > Taschen & Behälter Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelruten +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelruten-Zubehör +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelruten-Zubehör > Angelrutenhalter und -ständer +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Angelruten-Zubehör > Taschen & Behälter für Angelruten +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Bissanzeiger Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Fallen für den Angelsport Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Fischernetze Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Gaffs Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Harpunen für den Angelsport -Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Karabiner und Drehringe für den Angelsport -Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Kunstköder -Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Kunstköder > Kunstfliegen Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Köderbefestigung Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Köderbefestigung > Angelschnur Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Köderbefestigung > Pop-Up-Kugeln Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Köderbehälter Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Lebendköder -Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Schwimmer Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Wathosen für Angler & Jäger -Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Werkzeug zum Entfernen des Angelhakens -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Camping-Töpfe & -Geschirr -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Campinghilfsmittel -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Campinghilfsmittel > Messer & Klingen -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Campinghilfsmittel > Messer & Klingen > Jagdmesser -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Campinghilfsmittel > Multifunktionswerkzeuge & -messer -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Campingleuchten & -laternen -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Campingmöbel -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Campingmöbel > Feldbetten -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Campingmöbel > Luftmatratzen -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Campingmöbel > Luftmatratzenzubehör -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Gefriergetrocknete Lebensmittel -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Isomatten -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Jugendherbergs-Schlafsack -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Kompressionssäcke -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Mobile Toiletten -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Moskitonetze -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Navigationskompasse -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Notfalldecken -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Schlafsäcke -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Steigeisen -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Taschenwärmer -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Tragbare Wasserfilter & Wasserreiniger -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Trekkingstöcke -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Urinellas & Tragbare Urinale -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Zelte -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Zeltzubehör -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Zeltzubehör > Vorzelte -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Zeltzubehör > Zeltstangen & -Heringe -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Zeltzubehör > Zeltunterlagen -Sportartikel > Outdoor-Aktivitäten > Camping & Wandern & Rucksacktouren > Zubehör für Trekkingstöcke -Sportartikel > Outdoor-Aktivitäten > Discgolf -Sportartikel > Outdoor-Aktivitäten > Discgolf > Discgolf-Fangkörbe -Sportartikel > Outdoor-Aktivitäten > Discgolf > Discgolf-Scheiben -Sportartikel > Outdoor-Aktivitäten > Discgolf > Discgolf-Taschen -Sportartikel > Outdoor-Aktivitäten > Geocaching -Sportartikel > Outdoor-Aktivitäten > Geocaching > Cachebehälter -Sportartikel > Outdoor-Aktivitäten > Geocaching > Geocaching-Logbücher -Sportartikel > Outdoor-Aktivitäten > Geocaching > Geocaching-Trackables +Sportartikel > Outdoor-Aktivitäten > Angeln & Fischen > Werkzeuge zum Entfernen des Angelhakens +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Ablagen für Wasserfahrzeuge +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Ablagen für Wasserfahrzeuge > Halterungen für Boards +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Ablagen für Wasserfahrzeuge > Halterungen für Boote +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung > Neoprenanzugteile +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung > Neoprenanzugteile > Kappen, Handschuhe & Stiefel für Neoprenanzüge +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung > Neoprenanzugteile > Neopren-Oberteile +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung > Neoprenanzugteile > Neopren-Unterteile +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung > Neoprenanzüge +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung > Rashguards & Schwimmshirts +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung > Rettungswesten +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung > Schwimmwestenzubehör +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung > Trockenanzüge +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Boots- & Wassersportkleidung > Wassersporthelme +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport > Handschuhe für den Bootssport +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport > Kajaks +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport > Kajakzubehör +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport > Kanus +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport > Kanuzubehör +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport > Paddel & Ruder +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport > Paddelriemen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport > Rafts +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport > Ruderboote +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Bootssport > Tretboote +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Kitesurfen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Kitesurfen > Kiteboard-Taschen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Kitesurfen > Kiteboards +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Kitesurfen > Kiteboardteile +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Kitesurfen > Kitesurfing-Kites +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Kitesurfen > Trapeze für Kite- & Windsurfen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Badekappen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Gegenstromanlagen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Handpaddel +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Nasenklammern +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Pull Buoys +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Schwimmbretter +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Schwimmbrillen & -masken +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Schwimmflossen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Schwimmflossen > Monoflossen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Schwimmflossen > Trainingsflossen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Schwimmflügel +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Schwimmgewichte +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Schwimmgürtel +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Schwimmhandschuhe +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Schwimmen > Zubehör für Schwimmbrillen & -masken +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Handschuhe für seilgebundene Wassersportarten +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Kneeboarding +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Kneeboarding > Kneeboards +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Tubes & Towables +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Wakeboarding +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Wakeboarding > Kiteboard- & Wakeboard-Bindungen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Wakeboarding > Wakeboard-Ersatzteile +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Wakeboarding > Wakeboards +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Wasserski +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Wasserski > Hydrofoils +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Wasserski > Wasserski-Bindungen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Wasserski > Wasserskier +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Wasserski > Wasserskikoffer & -taschen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Seilgebundene Wassersportarten > Zugseile für Wassersport +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen > Bodyboards +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen > Fußleinen für Surfbretter +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen > Handschuhe für Surfer +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen > Paddelboards +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen > Skimboards +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen > Surfboard-Taschen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen > Surfboard-Wachs +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen > Surfbretter +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen > Surfbrettfinnen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Surfen > Surfpads +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Tauchen & Schnorcheln +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Tauchen & Schnorcheln > Atemregler +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Tauchen & Schnorcheln > Bleigürtel +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Tauchen & Schnorcheln > Schnorchel +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Tauchen & Schnorcheln > Tarierwesten +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Tauchen & Schnorcheln > Tauch- & Schnorchelausrüstung +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Tauchen & Schnorcheln > Tauch- & Schnorchelflossen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Tauchen & Schnorcheln > Tauch- & Schnorchelmasken +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Tauchen & Schnorcheln > Tauchcomputer +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Tauchen & Schnorcheln > Tauchermesser & -scheren +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Windsurfen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Windsurfen > Windsurfboard-Ausrüstung +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Windsurfen > Windsurfboard-Ausrüstung > Windsurf-Finnen +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Windsurfen > Windsurfboard-Ausrüstung > Windsurfmasten +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Windsurfen > Windsurfbretter +Sportartikel > Outdoor-Aktivitäten > Boot- & Wassersport > Windsurfen > Windsurfsegel +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Camping-Töpfe & -Geschirr +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Campinghilfsmittel +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Campinghilfsmittel > Jagdmesser +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Campinghilfsmittel > Multifunktionswerkzeuge & -messer +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Campingleuchten & -laternen +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Campingmöbel +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Campingmöbel > Feldbetten +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Campingmöbel > Luftbetten +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Campingmöbel > Zubehör für Luftmatratzen & Schlafunterlagen +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Innenschlafsack +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Isomatten +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Kompressionssäcke +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Mobile Toiletten & Duschen +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Mobile Toiletten & Duschen > Mobile Duschen & Sichtschutz +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Mobile Toiletten & Duschen > Mobile Toiletten & Urinale +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Moskitonetze & Fliegengitter +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Navigationskompasse +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Schlafsäcke +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Taschenwärmer +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Tragbare Wasserfilter & Wasserreiniger +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Trekkingstöcke +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Windschutz +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Zelte +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Zeltzubehör +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Zeltzubehör > Innenzelte +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Zeltzubehör > Vorzelte +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Zeltzubehör > Zeltstangen & -Heringe +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Zeltzubehör > Zeltunterlagen +Sportartikel > Outdoor-Aktivitäten > Camping & Wandern > Zubehör für Trekkingstöcke +Sportartikel > Outdoor-Aktivitäten > Drachenfliegen & Fallschirmspringen +Sportartikel > Outdoor-Aktivitäten > Drachenfliegen & Fallschirmspringen > Fallschirme +Sportartikel > Outdoor-Aktivitäten > Drachenfliegen & Fallschirmspringen > Fluganzüge +Sportartikel > Outdoor-Aktivitäten > Drachenfliegen & Fallschirmspringen > Hängegleiter Sportartikel > Outdoor-Aktivitäten > Golf -Sportartikel > Outdoor-Aktivitäten > Golf > Golf-Sets Sportartikel > Outdoor-Aktivitäten > Golf > Golf-Tees Sportartikel > Outdoor-Aktivitäten > Golf > Golf-Trainingshilfen +Sportartikel > Outdoor-Aktivitäten > Golf > Golf-Zubehörsets Sportartikel > Outdoor-Aktivitäten > Golf > Golfballmarkierungen Sportartikel > Outdoor-Aktivitäten > Golf > Golfbälle Sportartikel > Outdoor-Aktivitäten > Golf > Golffahnen @@ -5321,97 +4777,127 @@ Sportartikel > Outdoor-Aktivitäten > Golf > Golfschläger Sportartikel > Outdoor-Aktivitäten > Golf > Golfschläger-Teile & Zubehör Sportartikel > Outdoor-Aktivitäten > Golf > Golfschläger-Teile & Zubehör > Golfschläger-Schutzhüllen Sportartikel > Outdoor-Aktivitäten > Golf > Golfschläger-Teile & Zubehör > Golfschlägergriffe +Sportartikel > Outdoor-Aktivitäten > Golf > Golfschläger-Teile & Zubehör > Golfschlägerschäfte Sportartikel > Outdoor-Aktivitäten > Golf > Golftaschen Sportartikel > Outdoor-Aktivitäten > Golf > Golftaschenzubehör Sportartikel > Outdoor-Aktivitäten > Golf > Golftaschenzubehör > Golftaschenhüllen Sportartikel > Outdoor-Aktivitäten > Golf > Golftaschenzubehör > Golftaschentrolleys Sportartikel > Outdoor-Aktivitäten > Golf > Pitchgabeln -Sportartikel > Outdoor-Aktivitäten > Jagen -Sportartikel > Outdoor-Aktivitäten > Jagen > Hochsitze -Sportartikel > Outdoor-Aktivitäten > Jagen > Jagdansitze & Tarnung -Sportartikel > Outdoor-Aktivitäten > Jagen > Jagdhund-Ausrüstung -Sportartikel > Outdoor-Aktivitäten > Jagen > Jagdköder -Sportartikel > Outdoor-Aktivitäten > Jagen > Jagdzelte -Sportartikel > Outdoor-Aktivitäten > Jagen > Lockinstrumente -Sportartikel > Outdoor-Aktivitäten > Jagen > Lockmittel für Wild -Sportartikel > Outdoor-Aktivitäten > Jagen > Tierfallen -Sportartikel > Outdoor-Aktivitäten > Jagen > Wildfutterautomaten +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Armschutz für Bogenschützen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Bogen- & Armbrustteile & -zubehör +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Bögen & Armbrüste +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Bögen & Armbrüste > Armbrüste +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Bögen & Armbrüste > Compoundbögen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Bögen & Armbrüste > Langbögen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Handschuhe & Auslöser +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Köcher +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Pfeile +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Pfeilelemente & Zubehör +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Pfeilelemente & Zubehör > Jagdspitzen & Feldspitzen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Pfeilelemente & Zubehör > Nocken +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Pfeilelemente & Zubehör > Steuerfedern +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Bogenschießen > Zielscheiben für Bogenschießen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Hochsitze +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Jagdansitze & Tarnung +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Jagdhund-Ausrüstung +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Jagdverstärker +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Lockmittel für Wild +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Lockmittel für Wild > Geruchstarnung & Lockdüfte +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Lockmittel für Wild > Jagdköder +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Lockmittel für Wild > Köder, Futter & Mineralien +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Lockmittel für Wild > Lockinstrumente +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Tierfallen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Jagen > Wildfutterautomaten +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball > Ersatzteile & Zubehör für Paintball-Gewehre +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball > Ersatzteile & Zubehör für Paintball-Gewehre > Paintball-Drop-Forwards +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball > Ersatzteile & Zubehör für Paintball-Gewehre > Paintball-Gewehrläufe +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball > Ersatzteile & Zubehör für Paintball-Gewehre > Paintball-Hopper +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball > Ersatzteile & Zubehör für Paintball-Gewehre > Paintball-Pressluftflaschen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball > Paintball-Battlepacks +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball > Paintball-Granaten +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball > Paintball-Granatwerfer +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball > Paintball-Markierer +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball > Paintballs +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball- & Airsoft-Schutzkleidung +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball- & Airsoft-Schutzkleidung > Paintball- & Airsoft-Handschuhe +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball- & Airsoft-Schutzkleidung > Paintball- & Airsoft-Schutzbrillen & Masken +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball- & Airsoft-Schutzkleidung > Paintball- & Airsoft-Schutzpolster +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Paintball- & Airsoft-Schutzkleidung > Paintball- & Airsoft-Westen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Softair +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Softair > Softairkugeln +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Softair > Softairwaffen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Softair > Softairwaffen-Teile & -Zubehör +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Paintball & Airsoft > Softair > Softairwaffen-Teile & -Zubehör > Batterien für Softairwaffen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Schießsportzubehör +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Schießsportzubehör > Stative & Zweibeinständer +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Schießsportzubehör > Stützen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Schießsportzubehör > Zielscheiben +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Schutzkleidung für Jagd- und Schießsport +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Schutzkleidung für Jagd- und Schießsport > Handschuhe für Jagd- und Schießsport +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Schutzkleidung für Jagd- und Schießsport > Jacken für Jagd- und Schießsport +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Tontaubenschießen +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Tontaubenschießen > Tontauben +Sportartikel > Outdoor-Aktivitäten > Jagen und Schießen > Tontaubenschießen > Tontauben-Wurfmaschinen Sportartikel > Outdoor-Aktivitäten > Kitebuggying +Sportartikel > Outdoor-Aktivitäten > Kitebuggying > Kitebuggy-Zubehör Sportartikel > Outdoor-Aktivitäten > Kitebuggying > Kitebuggys -Sportartikel > Outdoor-Aktivitäten > Kitebuggying-Zubehör Sportartikel > Outdoor-Aktivitäten > Klettern -Sportartikel > Outdoor-Aktivitäten > Klettern > Eisklettern -Sportartikel > Outdoor-Aktivitäten > Klettern > Eisklettern > Eiskletterausrüstung -Sportartikel > Outdoor-Aktivitäten > Klettern > Eisklettern > Eisschrauben -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Bouldermatten -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Chalk -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Chalkbags -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Expresssets -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Gurtbänder -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Karabiner -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Klettergurte -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Kletterhelme -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Kletterschutzausrüstung -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Kletterseile -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Kletterwandgriffe -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Seilsäcke -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Sicherungsgeräte -Sportartikel > Outdoor-Aktivitäten > Klettern > Felsklettern & Indoor-Klettern > Steigklemmen & Abseilausrüstung -Sportartikel > Outdoor-Aktivitäten > Laufsport -Sportartikel > Outdoor-Aktivitäten > Leichtathletik -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Diskusscheiben -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Hochsprunglatten -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Hochsprungmatten -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Hürden -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Kugelstoß-Kugeln -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Speere -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Stabhochsprungmatten -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Stabhochsprungstäbe -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Staffelstäbe -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Startpistolen -Sportartikel > Outdoor-Aktivitäten > Leichtathletik > Wurfhämmer -Sportartikel > Outdoor-Aktivitäten > Motorsport -Sportartikel > Outdoor-Aktivitäten > Motorsport > Rennsport +Sportartikel > Outdoor-Aktivitäten > Klettern > Bouldermatten +Sportartikel > Outdoor-Aktivitäten > Klettern > Chalkbags +Sportartikel > Outdoor-Aktivitäten > Klettern > Eiskletterausrüstung +Sportartikel > Outdoor-Aktivitäten > Klettern > Eisschrauben +Sportartikel > Outdoor-Aktivitäten > Klettern > Expresssets +Sportartikel > Outdoor-Aktivitäten > Klettern > Gurtbänder +Sportartikel > Outdoor-Aktivitäten > Klettern > Karabiner +Sportartikel > Outdoor-Aktivitäten > Klettern > Kletterbekleidung & -zubehör +Sportartikel > Outdoor-Aktivitäten > Klettern > Kletterbekleidung & -zubehör > Kletterhandschuhe +Sportartikel > Outdoor-Aktivitäten > Klettern > Kletterbekleidung & -zubehör > Kletterhelme +Sportartikel > Outdoor-Aktivitäten > Klettern > Kletterbekleidung & -zubehör > Steigeisen +Sportartikel > Outdoor-Aktivitäten > Klettern > Klettergurte +Sportartikel > Outdoor-Aktivitäten > Klettern > Kletterschutzausrüstung +Sportartikel > Outdoor-Aktivitäten > Klettern > Kletterseile +Sportartikel > Outdoor-Aktivitäten > Klettern > Kletterwandgriffe +Sportartikel > Outdoor-Aktivitäten > Klettern > Seilsäcke +Sportartikel > Outdoor-Aktivitäten > Klettern > Sicherungsgeräte +Sportartikel > Outdoor-Aktivitäten > Klettern > Steigklemmen & Abseilausrüstung Sportartikel > Outdoor-Aktivitäten > Radsport Sportartikel > Outdoor-Aktivitäten > Radsport > Dreiradzubehör Sportartikel > Outdoor-Aktivitäten > Radsport > Dreiräder -Sportartikel > Outdoor-Aktivitäten > Radsport > Dreiräder > Liegedreiräder Sportartikel > Outdoor-Aktivitäten > Radsport > Einradzubehör Sportartikel > Outdoor-Aktivitäten > Radsport > Einräder -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradausrüstung -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradausrüstung > Cleat-Zubehör -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradausrüstung > Cleat-Zubehör > Cleat-Platten -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradausrüstung > Cleat-Zubehör > Cleat-Schrauben -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradausrüstung > Cleat-Zubehör > Cleat-Schutzhüllen -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradausrüstung > Fahrradhandschuhe -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradausrüstung > Fahrradhelme -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradausrüstung > Fahrradhelmschutz -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradausrüstung > Fahrradüberschuhe -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradausrüstung > Schuhplatten Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrrad-Groupsets Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradbremsenteile Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradbremsenteile > Bremsen-Sets Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradbremsenteile > Bremshebel Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradbremsenteile > Bremsrotoren Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradbremsenteile > Bremssättel Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradgabeln -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradgriffe & Lenkergriffbänder +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradkabel +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradkabelgehäuse Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradlenkerverlängerungen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradlenkervorbau -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradlenkkopfteile -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradlenkkopfteile > Fahrradlenkkopf-Abstandsringe -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradlenkkopfteile > Fahrradlenkkopf-Halterungen +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradlenkkopf-Teile +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradlenkkopf-Teile > Fahrradlenkkopf-Abstandsringe +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradlenkkopf-Teile > Fahrradlenkkopf-Halterungen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradlenkköpfe Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradlenkstangen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradrahmen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradreifen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradräder Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradräderzubehör +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradräderzubehör > Fahrradachsen & -spanner Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradräderzubehör > Fahrradfelgen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradräderzubehör > Fahrradfußrasten Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradräderzubehör > Fahrradnaben +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradräderzubehör > Fahrradnabenteile Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradräderzubehör > Fahrradspeichen +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradräderzubehör > Felgenbänder Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradräderzubehör > Speichennippel Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradsattelstützen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradsattelstützenklemmen @@ -5425,10 +4911,23 @@ Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradschalt Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradschaltungsteile > Fahrradschalthebel Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradschaltungsteile > Tretlagergehäuse Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradschläuche +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradständer Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Fahrradsättel Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Kleinere Fahrradzubehörteile -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Kleinere Fahrradzubehörteile > Fahrradhalterungen -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Kleinere Fahrradzubehörteile > Fahrradklemmstücke +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Reifenventiladapter +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Reifenventile +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbauteile > Reifenventilkappen +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör > Fahrrad-Schutzpolster +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör > Fahrradhandschuhe +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör > Fahrradhelme +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör > Fahrradhelmteile und -zubehör +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör > Fahrradüberschuhe +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör > Schuhplatten +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör > Schuhplatten-Zubehör +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör > Schuhplatten-Zubehör > Schuhplatten-Klemmen & -Keile +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör > Schuhplatten-Zubehör > Schuhplatten-Schrauben +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradbekleidung & Zubehör > Schuhplatten-Zubehör > Schuhplatten-Schutzhüllen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Dämpferpumpen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrrad-Fußriemen @@ -5438,493 +4937,222 @@ Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradcomput Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradgepäckträger Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradklingeln & -hupen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradkörbe -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradlichter & -reflektoren Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradpumpen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradsattelbezüge & -polster Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradschlösser Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradschutzbleche -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradspeichenreflektoren +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradspeichen-Reflektoren Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradspiegel Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradständer & Fahrradparksysteme Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradtaschen Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradtaschen & -koffer -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradwerkzeug, Reinigungsmittel & Schmiermittel -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradwerkzeug, Reinigungsmittel & Schmiermittel > Fahrradschmiermittel -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradwerkzeug, Reinigungsmittel & Schmiermittel > Fahrradspeichen-Spannschlüssel +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Fahrradwerkzeug Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Flaschenhalter für Fahrradrahmen +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Flicken & Reparatur-Sets +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Griffe und Dekor für Fahrradlenker Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Kinderfahrradsitze Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Stützräder Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Surfbretthalterungen für Fahrräder Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Trainingsrollen +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Umrüstsatz für E-Bikes Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Zubehör für Fahrradcomputer +Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrradzubehör > Zubehör für Fahrradkindersitze Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrräder -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrräder > Cruiser -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrräder > Elektrofahrräder -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrräder > Liegeräder -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrräder > Mountainbikes -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrräder > Rennräder -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrräder > Trekkingräder -Sportartikel > Outdoor-Aktivitäten > Radsport > Fahrräder > Triathlonräder -Sportartikel > Outdoor-Aktivitäten > Rasenspiele -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Bean Bag -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Boccia -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Hufeisenwerfen -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Krocket -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Leitergolf -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Rasen-Dart -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Rasenbowling -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Rasenbowling > Rasenbowling-Kugeln -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Rasenbowling > Rasenbowling-Zielkugeln -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Ringwurfspiel -Sportartikel > Outdoor-Aktivitäten > Rasenspiele > Washer Pitching -Sportartikel > Outdoor-Aktivitäten > Reflektierende Fitnessbekleidung -Sportartikel > Outdoor-Aktivitäten > Reflektierende Fitnessbekleidung > Reflektierende Gürtel Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör -Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Hufglocken & Gamaschen -Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Hufglocken & Gamaschen > Hufglocken -Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Hufglocken & Gamaschen > Pferdegamaschen Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf > Abreitdecken & Weidedecken +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf > Fliegenmasken +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf > Hufglocken & Gamaschen Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf > Leckerli für Pferde Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf > Pferdefutter Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf > Pferdehaarpflege +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf > Pferdehaarpflege > Kämme, Bürsten & Striegel Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf > Pferdehaarpflege > Pferdeschermaschinen Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf > Vitamine & Futterergänzungsmittel für Pferde +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Pferdebedarf > Wurmkur für Pferde Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Reitausrüstung -Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Reitausrüstung > Gerten +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Reitausrüstung > Gerten & Peitschen Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Reitausrüstung > Reithandschuhe Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Reitausrüstung > Reithelme Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Reitausrüstung > Reithosen Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Sattel- & Zaumzeug +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Sattel- & Zaumzeug > Halfter Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Sattel- & Zaumzeug > Pferdegeschirr +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Sattel- & Zaumzeug > Pferdeleinen Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Sattel- & Zaumzeug > Sattelgurte +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Sattel- & Zaumzeug > Steigbügel Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Sattel- & Zaumzeug > Sättel Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Sattel- & Zaumzeug > Trensen Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Sattel- & Zaumzeug > Zaumzeug Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Sattel- & Zaumzeug > Zügel -Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Zubehör für Pferdesattel & -zaumzeug -Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Zubehör für Pferdesattel & -zaumzeug > Sattelauflagen +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Zubehör für Sattel & Zaumzeug +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Zubehör für Sattel & Zaumzeug > Sattel- & Zaumzeugbehälter +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Zubehör für Sattel & Zaumzeug > Sattelzubehör +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Zubehör für Sattel & Zaumzeug > Sattelzubehör > Sattelauflagen +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Zubehör für Sattel & Zaumzeug > Sattelzubehör > Sattelbezüge und -hüllen +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Zubehör für Sattel & Zaumzeug > Sattelzubehör > Sattelpolster & -decken +Sportartikel > Outdoor-Aktivitäten > Reitsportzubehör > Zubehör für Sattel & Zaumzeug > Sattelzubehör > Satteltaschen Sportartikel > Outdoor-Aktivitäten > Roller -Sportartikel > Outdoor-Aktivitäten > Roller > Motorroller -Sportartikel > Outdoor-Aktivitäten > Roller > Tretroller -Sportartikel > Outdoor-Aktivitäten > Schießspiele -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Battlepacks -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Gewehrteile -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Gewehrteile > Paintball-Gewehrläufe -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Gewehrteile > Paintball-Hopper -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Granaten -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Granatwerfer -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Markierer -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Pressluftflaschen -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Schutzausrüstung -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Schutzausrüstung > Paintball-Handschuhe -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Schutzausrüstung > Paintball-Protektoren -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Schutzausrüstung > Paintball-Schutzbrillen & -Masken -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintball-Schutzausrüstung > Paintball-Westen -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Paintball > Paintballs -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Softair -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Softair > Softair-Schutzausrüstung -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Softair > Softairkugeln -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Softair > Softairwaffen -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Softair > Softairwaffen-Teile & -Zubehör -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Softair > Softairwaffen-Teile & -Zubehör > Batterien für Softairwaffen -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Tontaubenschießen -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Tontaubenschießen > Tontauben -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Tontaubenschießen > Tontauben-Wurfmaschinen -Sportartikel > Outdoor-Aktivitäten > Schießspiele > Zielscheiben -Sportartikel > Outdoor-Aktivitäten > Schutzkleidung für Jagd- und Schießsport -Sportartikel > Outdoor-Aktivitäten > Schutzkleidung für Jagd- und Schießsport > Handschuhe für Jagd- und Schießsport -Sportartikel > Outdoor-Aktivitäten > Schutzkleidung für Jagd- und Schießsport > Jacken für Jagd- und Schießsport -Sportartikel > Outdoor-Aktivitäten > Shuffleboard -Sportartikel > Outdoor-Aktivitäten > Shuffleboard > Shuffleboard-Cues -Sportartikel > Outdoor-Aktivitäten > Shuffleboard > Shuffleboard-Disks Sportartikel > Outdoor-Aktivitäten > Skateboarding Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skate-Rails Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skate-Rampen -Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboard-Schutzausrüstung -Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboard-Schutzausrüstung > Handschuhe für Skateboarder -Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboard-Schutzausrüstung > Skateboard-Helme -Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboard-Schutzausrüstung > Skateboard-Protektoren Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboard-Teile Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboard-Teile > Skateboard-Achsen Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboard-Teile > Skateboard-Decks -Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboard-Teile > Skateboard-Kugellager +Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboard-Teile > Skateboard-Kleinteile Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboard-Teile > Skateboard-Rollen +Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboarding-Schutzausrüstung +Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboarding-Schutzausrüstung > Skate-Helme +Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboarding-Schutzausrüstung > Skateboarding-Handschuhe +Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboarding-Schutzausrüstung > Skateboarding-Protektoren Sportartikel > Outdoor-Aktivitäten > Skateboarding > Skateboards Sportartikel > Outdoor-Aktivitäten > Skaten -Sportartikel > Outdoor-Aktivitäten > Skaten > Eiskunstlaufstiefel Sportartikel > Outdoor-Aktivitäten > Skaten > Inline-Skates -Sportartikel > Outdoor-Aktivitäten > Skaten > Kufenschoner +Sportartikel > Outdoor-Aktivitäten > Skaten > Inlineskate-Teile Sportartikel > Outdoor-Aktivitäten > Skaten > Rollerskates -Sportartikel > Outdoor-Aktivitäten > Skaten > Schlittschuhe -Sportartikel > Outdoor-Aktivitäten > Skaten > Schlittschuhe > Eishockeyschlittschuhe -Sportartikel > Outdoor-Aktivitäten > Skaten > Schlittschuhe > Eiskunstlaufschuhe -Sportartikel > Outdoor-Aktivitäten > Skaten > Schlittschuhkufen -Sportartikel > Outdoor-Aktivitäten > Skaten > Schlittschuhschleifer -Sportartikel > Outdoor-Aktivitäten > Skaten > Schnürhilfen -Sportartikel > Outdoor-Aktivitäten > Skaten > Skate-Helme & -Protektoren -Sportartikel > Outdoor-Aktivitäten > Skaten > Skate-Zubehörteile -Sportartikel > Outdoor-Aktivitäten > Stadionsitze und Polster -Sportartikel > Outdoor-Aktivitäten > Tetherball +Sportartikel > Outdoor-Aktivitäten > Skaten > Rollschuh-Teile +Sportartikel > Outdoor-Aktivitäten > Skaten > Rollskis +Sportartikel > Outdoor-Aktivitäten > Skaten > Schutzausrüstung für Skater +Sportartikel > Outdoor-Aktivitäten > Skaten > Schutzausrüstung für Skater > Rollschuh-Polster +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Badminton +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Badminton > Badmintonnetze +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Badminton > Badmintonschläger & -sets +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Badminton > Federball +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Bälle für Paddle-Tennis +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Discgolf +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Discgolf > Discgolf-Fangkörbe +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Discgolf > Discgolf-Taschen +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Paddletennis +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Paddletennis > Paddletennis-Bälle +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Paddletennis > Paddletennis-Schläger +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Pickleball +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Pickleball > Pickleball-Bälle +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Pickleball > Pickleball-Schläger +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Rasenspiele +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Shuffleboard +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Shuffleboard > Shuffleboard-Cues +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Shuffleboard > Shuffleboard-Disks +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Tetherball +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Tetherball > Tetherball-Bälle +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Tetherball > Tetherball-Sets +Sportartikel > Outdoor-Aktivitäten > Spiele im Freien > Tetherball > Tetherball-Stangen Sportartikel > Outdoor-Aktivitäten > Trinksystem-Zubehör Sportartikel > Outdoor-Aktivitäten > Trinksystemrucksäcke & -taschen -Sportartikel > Sportarten & Spiele für drinnen -Sportartikel > Sportarten & Spiele für drinnen > Air-Hockey -Sportartikel > Sportarten & Spiele für drinnen > Air-Hockey > Air-Hockey-Pucks -Sportartikel > Sportarten & Spiele für drinnen > Air-Hockey > Air-Hockey-Schläger -Sportartikel > Sportarten & Spiele für drinnen > Air-Hockey > Air-Hockey-Tische -Sportartikel > Sportarten & Spiele für drinnen > Air-Hockey > Air-Hockey-Tischzubehör -Sportartikel > Sportarten & Spiele für drinnen > Billard -Sportartikel > Sportarten & Spiele für drinnen > Billard > Billarddreiecke -Sportartikel > Sportarten & Spiele für drinnen > Billard > Billardhandschuhe -Sportartikel > Sportarten & Spiele für drinnen > Billard > Billardkugeln -Sportartikel > Sportarten & Spiele für drinnen > Billard > Billardqueues & Queuebrücken -Sportartikel > Sportarten & Spiele für drinnen > Billard > Billardtisch-Beleuchtung -Sportartikel > Sportarten & Spiele für drinnen > Billard > Billardtisch-Teile & Zubehör -Sportartikel > Sportarten & Spiele für drinnen > Billard > Billardtisch-Teile & Zubehör > Ballfangtaschen -Sportartikel > Sportarten & Spiele für drinnen > Billard > Billardtisch-Teile & Zubehör > Billardtisch-Bürsten -Sportartikel > Sportarten & Spiele für drinnen > Billard > Billardtisch-Teile & Zubehör > Billardtücher -Sportartikel > Sportarten & Spiele für drinnen > Billard > Billardtische -Sportartikel > Sportarten & Spiele für drinnen > Billard > Queuezubehör -Sportartikel > Sportarten & Spiele für drinnen > Billard > Queuezubehör > Queueständer -Sportartikel > Sportarten & Spiele für drinnen > Bowling -Sportartikel > Sportarten & Spiele für drinnen > Bowling > Bowling-Handgelenkstützen -Sportartikel > Sportarten & Spiele für drinnen > Bowling > Bowlinghandschuhe -Sportartikel > Sportarten & Spiele für drinnen > Bowling > Bowlingkegel -Sportartikel > Sportarten & Spiele für drinnen > Bowling > Bowlingkugeln -Sportartikel > Sportarten & Spiele für drinnen > Bowling > Bowlingtaschen -Sportartikel > Sportarten & Spiele für drinnen > Darts -Sportartikel > Sportarten & Spiele für drinnen > Darts > Dart-Rückwände -Sportartikel > Sportarten & Spiele für drinnen > Darts > Dartpfeile & -Sets -Sportartikel > Sportarten & Spiele für drinnen > Darts > Dartscheiben -Sportartikel > Sportarten & Spiele für drinnen > Darts > Dartteile -Sportartikel > Sportarten & Spiele für drinnen > Darts > Dartteile > Dartflights -Sportartikel > Sportarten & Spiele für drinnen > Darts > Dartteile > Dartschäfte -Sportartikel > Sportarten & Spiele für drinnen > Darts > Dartteile > Dartspitzen -Sportartikel > Sportarten & Spiele für drinnen > Jakkolo -Sportartikel > Sportarten & Spiele für drinnen > Jakkolo > Jakkolo-Pulver -Sportartikel > Sportarten & Spiele für drinnen > Jakkolo > Jakkolo-Spielsteine -Sportartikel > Sportarten & Spiele für drinnen > Jakkolo > Shuffleboard-Tische -Sportartikel > Sportarten & Spiele für drinnen > Multispieltische -Sportartikel > Sportarten & Spiele für drinnen > Tischfußball -Sportartikel > Sportarten & Spiele für drinnen > Tischfußball > Tischfußball-Bälle -Sportartikel > Sportarten & Spiele für drinnen > Tischfußball > Tischfußball-Tische -Sportartikel > Sportarten & Spiele für drinnen > Tischfußball > Zubehör für Tischfußballtische -Sportartikel > Sportarten & Spiele für drinnen > Tischtennis -Sportartikel > Sportarten & Spiele für drinnen > Tischtennis > Tischtennis-Roboter -Sportartikel > Sportarten & Spiele für drinnen > Tischtennis > Tischtennisbälle -Sportartikel > Sportarten & Spiele für drinnen > Tischtennis > Tischtennisnetze und -pfosten -Sportartikel > Sportarten & Spiele für drinnen > Tischtennis > Tischtennisplatten -Sportartikel > Sportarten & Spiele für drinnen > Tischtennis > Tischtennisschläger -Sportartikel > Sportarten & Spiele für drinnen > Tischtennis > Zubehör für Tischtennis-Roboter -Sportartikel > Sportarten & Spiele für drinnen > Tischtennis > Zubehör für Tischtennisschläger -Sportartikel > Sportarten mit Schläger -Sportartikel > Sportarten mit Schläger > Badminton -Sportartikel > Sportarten mit Schläger > Badminton > Badmintonnetze -Sportartikel > Sportarten mit Schläger > Badminton > Badmintonschläger -Sportartikel > Sportarten mit Schläger > Badminton > Federbälle -Sportartikel > Sportarten mit Schläger > Bälle für Paddle-Tennis -Sportartikel > Sportarten mit Schläger > Paddle-Tennis -Sportartikel > Sportarten mit Schläger > Pickleball -Sportartikel > Sportarten mit Schläger > Platform-Tennis -Sportartikel > Sportarten mit Schläger > Racquetball -Sportartikel > Sportarten mit Schläger > Racquetball > Racquetball-Bälle -Sportartikel > Sportarten mit Schläger > Racquetball > Racquetball-Schläger -Sportartikel > Sportarten mit Schläger > Racquetball > Racquetball-Schutzausrüstung -Sportartikel > Sportarten mit Schläger > Racquetball > Racquetball-Schutzausrüstung > Squash- & Racquetball-Schutzbrillen -Sportartikel > Sportarten mit Schläger > Squash -Sportartikel > Sportarten mit Schläger > Squash > Squash-Bälle -Sportartikel > Sportarten mit Schläger > Squash > Squash-Schläger -Sportartikel > Sportarten mit Schläger > Squash > Squash-Schutzausrüstung -Sportartikel > Sportarten mit Schläger > Tennis -Sportartikel > Sportarten mit Schläger > Tennis > Tennisballdosen -Sportartikel > Sportarten mit Schläger > Tennis > Tennisballkörbe -Sportartikel > Sportarten mit Schläger > Tennis > Tennisballwurfmaschinen -Sportartikel > Sportarten mit Schläger > Tennis > Tennisbälle -Sportartikel > Sportarten mit Schläger > Tennis > Tennisnetze -Sportartikel > Sportarten mit Schläger > Tennis > Tennisschläger -Sportartikel > Sportarten mit Schläger > Tennis > Tennisschlägerzubehör -Sportartikel > Sportarten mit Schläger > Tennis > Tennisschlägerzubehör > Griffbänder -Sportartikel > Sportarten mit Schläger > Tennis > Tennisschlägerzubehör > Tennissaiten -Sportartikel > Sportarten mit Schläger > Tennis > Tennisschlägerzubehör > Tennistaschen -Sportartikel > Sportarten mit Schläger > Tennis > Tennisschlägerzubehör > Vibrationsdämpfer -Sportartikel > Sportarten mit Schläger > Tennis > Tennisschlägerzubehör > Ösenbänder für Tennisschläger -Sportartikel > Sportübungen & Fitness -Sportartikel > Sportübungen & Fitness > Bauchtrainer -Sportartikel > Sportübungen & Fitness > Fitnessbänder -Sportartikel > Sportübungen & Fitness > Gewichthebergürtel -Sportartikel > Sportübungen & Fitness > Gewichtheberhandschuhe & Handgelenkschoner -Sportartikel > Sportübungen & Fitness > Gewichtswesten & -manschetten -Sportartikel > Sportübungen & Fitness > Gymnastikbälle -Sportartikel > Sportübungen & Fitness > Gymnastikmatten -Sportartikel > Sportübungen & Fitness > Gymnastikmatten > Matten für Heimtrainer -Sportartikel > Sportübungen & Fitness > Hantelbänke -Sportartikel > Sportübungen & Fitness > Hanteln -Sportartikel > Sportübungen & Fitness > Hantelstangen -Sportartikel > Sportübungen & Fitness > Hantelzubehör -Sportartikel > Sportübungen & Fitness > Kardiogeräte -Sportartikel > Sportübungen & Fitness > Kardiogeräte > Crosstrainer -Sportartikel > Sportübungen & Fitness > Kardiogeräte > Heimtrainer -Sportartikel > Sportübungen & Fitness > Kardiogeräte > Laufbänder -Sportartikel > Sportübungen & Fitness > Kardiogeräte > Rudergeräte -Sportartikel > Sportübungen & Fitness > Kardiogeräte > Stepper -Sportartikel > Sportübungen & Fitness > Krafttrainingsgeräte -Sportartikel > Sportübungen & Fitness > Medizinbälle -Sportartikel > Sportübungen & Fitness > Reaction Balls -Sportartikel > Sportübungen & Fitness > Schaumroller -Sportartikel > Sportübungen & Fitness > Schaumroller-Zubehör -Sportartikel > Sportübungen & Fitness > Schaumroller-Zubehör > Aufbewahrungstaschen für Schaumroller -Sportartikel > Sportübungen & Fitness > Springseile -Sportartikel > Sportübungen & Fitness > Stoppuhren -Sportartikel > Sportübungen & Fitness > Yoga & Pilates -Sportartikel > Sportübungen & Fitness > Yoga & Pilates > Beutel für Yogamatten -Sportartikel > Sportübungen & Fitness > Yoga & Pilates > Pilates-Geräte -Sportartikel > Sportübungen & Fitness > Yoga & Pilates > Yoga- & Pilatesblöcke -Sportartikel > Sportübungen & Fitness > Yoga & Pilates > Yoga- & Pilatesmatten -Sportartikel > Sportübungen & Fitness > Yoga- & Pilateszubehör -Sportartikel > Sportübungen & Fitness > Yoga- & Pilateszubehör > Yoga- & Pilatestücher -Sportartikel > Sportübungen & Fitness > Zubehör für Kardiogeräte -Sportartikel > Sportübungen & Fitness > Zubehör für Krafttrainingsgeräte -Sportartikel > Springen -Sportartikel > Springen > Bungee-Jumping -Sportartikel > Springen > Springstöcke -Sportartikel > Springen > Sprungstelzen -Sportartikel > Springen > Trampoline -Sportartikel > Springen > Trampolinzubehör -Sportartikel > Springen > Trampolinzubehör > Trampolin-Sicherheitspolster -Sportartikel > Springen > Trampolinzubehör > Trampolin-Verankerungssets -Sportartikel > Springen > Trampolinzubehör > Trampolinfedern -Sportartikel > Springen > Trampolinzubehör > Trampolinleitern -Sportartikel > Springen > Trampolinzubehör > Trampolinnetze -Sportartikel > Springen > Trampolinzubehör > Trampolinsprungtücher -Sportartikel > Tanzen -Sportartikel > Tanzen > Ballettstangen -Sportartikel > Turnen -Sportartikel > Turnen > Schutzausrüstung -Sportartikel > Turnen > Schwebebalken -Sportartikel > Turnen > Sprungpferde -Sportartikel > Turnen > Turnmatten -Sportartikel > Turnen > Turnpferde -Sportartikel > Turnen > Turnringe -Sportartikel > Turnen > Turnsprungbretter -Sportartikel > Turnen > Turnstangen -Sportartikel > Wassersport -Sportartikel > Wassersport > Ablagen für Wasserfahrzeuge -Sportartikel > Wassersport > Bootssport -Sportartikel > Wassersport > Bootssport > Handschuhe für den Bootssport -Sportartikel > Wassersport > Bootssport > Kajaksport -Sportartikel > Wassersport > Bootssport > Kajaksport > Kajak-Zubehör -Sportartikel > Wassersport > Bootssport > Kajaksport > Kajak-Zubehör > Spritzdecken -Sportartikel > Wassersport > Bootssport > Kajaksport > Kajaks -Sportartikel > Wassersport > Bootssport > Kanusport -Sportartikel > Wassersport > Bootssport > Kanusport > Kanu-Zubehör -Sportartikel > Wassersport > Bootssport > Kanusport > Kanus -Sportartikel > Wassersport > Bootssport > Raftingboote -Sportartikel > Wassersport > Bootssport > Rudern -Sportartikel > Wassersport > Bootssport > Rudern > Ruderboote -Sportartikel > Wassersport > Bootssport > Rudern > Sitzauflagen -Sportartikel > Wassersport > Bootssport > Segel- & Yachtsport -Sportartikel > Wassersport > Bootssport > Tretboote -Sportartikel > Wassersport > Kitesurfen -Sportartikel > Wassersport > Kitesurfen > Kiteboard-Taschen -Sportartikel > Wassersport > Kitesurfen > Kiteboards -Sportartikel > Wassersport > Kitesurfen > Kiteboardteile -Sportartikel > Wassersport > Kitesurfen > Kitesurfing-Kites -Sportartikel > Wassersport > Kitesurfen > Kitesurfing-Trapeze -Sportartikel > Wassersport > Neoprenanzüge -Sportartikel > Wassersport > Neoprenanzüge > Neopren-Oberteile -Sportartikel > Wassersport > Neoprenanzüge > Neopren-Unterteile -Sportartikel > Wassersport > Neoprenanzüge > Zubehör für Neoprenanzüge -Sportartikel > Wassersport > Paddel & Ruder -Sportartikel > Wassersport > Rafting -Sportartikel > Wassersport > Rafting > Raftinghelme -Sportartikel > Wassersport > Rafting > Rafts -Sportartikel > Wassersport > Rettungswesten -Sportartikel > Wassersport > Schwimmen -Sportartikel > Wassersport > Schwimmen > Badekappen -Sportartikel > Wassersport > Schwimmen > Gegenstromanlagen -Sportartikel > Wassersport > Schwimmen > Handpaddel -Sportartikel > Wassersport > Schwimmen > Nasenklammern -Sportartikel > Wassersport > Schwimmen > Pull Buoys -Sportartikel > Wassersport > Schwimmen > Schwimmbretter -Sportartikel > Wassersport > Schwimmen > Schwimmbrillen & -masken -Sportartikel > Wassersport > Schwimmen > Schwimmflossen -Sportartikel > Wassersport > Schwimmen > Schwimmflossen > Monoflossen -Sportartikel > Wassersport > Schwimmen > Schwimmflossen > Trainingsflossen -Sportartikel > Wassersport > Schwimmen > Schwimmgewichte -Sportartikel > Wassersport > Schwimmen > Schwimmgürtel -Sportartikel > Wassersport > Schwimmen > Schwimmhandschuhe -Sportartikel > Wassersport > Schwimmen > Zubehör für Schwimmbrillen & -masken -Sportartikel > Wassersport > Schwimmwestenzubehör -Sportartikel > Wassersport > Seilgebundene Wassersportarten -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Handschuhe für Wassersport mit Zugseil -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Kneeboarding -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Kneeboarding > Kneeboards -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Parasailing -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Tubes & Towables -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Wakeboarding -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Wakeboarding > Wakeboard-Bindungen -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Wakeboarding > Wakeboards -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Wasserski -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Wasserski > Hydrofoils -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Wasserski > Wasserski-Bindungen -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Wasserski > Wasserski-Koffer & -Taschen -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Wasserski > Wasserskier -Sportartikel > Wassersport > Seilgebundene Wassersportarten > Zugseile -Sportartikel > Wassersport > Surfen -Sportartikel > Wassersport > Surfen > Bodyboards -Sportartikel > Wassersport > Surfen > Fußschlaufen & Trapeztampen -Sportartikel > Wassersport > Surfen > Handschuhe für Surfer -Sportartikel > Wassersport > Surfen > Paddelboards -Sportartikel > Wassersport > Surfen > Skimboards -Sportartikel > Wassersport > Surfen > Surfboard-Taschen -Sportartikel > Wassersport > Surfen > Surfboard-Wachs -Sportartikel > Wassersport > Surfen > Surfbretter -Sportartikel > Wassersport > Surfen > Surfbrettfinnen -Sportartikel > Wassersport > Surfen > Surfpads -Sportartikel > Wassersport > Tauchen & Schnorcheln -Sportartikel > Wassersport > Tauchen & Schnorcheln > Atemregler -Sportartikel > Wassersport > Tauchen & Schnorcheln > Bleigürtel -Sportartikel > Wassersport > Tauchen & Schnorcheln > Handschuhe für Taucher & Schnorchler -Sportartikel > Wassersport > Tauchen & Schnorcheln > Schnorchel -Sportartikel > Wassersport > Tauchen & Schnorcheln > Tarierwesten -Sportartikel > Wassersport > Tauchen & Schnorcheln > Tauch- & Schnorchelflossen -Sportartikel > Wassersport > Tauchen & Schnorcheln > Tauch- & Schnorchelmasken -Sportartikel > Wassersport > Tauchen & Schnorcheln > Tauchcomputer -Sportartikel > Wassersport > Tauchen & Schnorcheln > Tauchermesser & -scheren -Sportartikel > Wassersport > Tauchen & Schnorcheln > Trockenanzüge -Sportartikel > Wassersport > Tubing -Sportartikel > Wassersport > UV-Schutz-Shirts -Sportartikel > Wassersport > Wasserball -Sportartikel > Wassersport > Wasserball > Wasserballkappen -Sportartikel > Wassersport > Wasserball > Wasserballtore -Sportartikel > Wassersport > Wasserball > Wasserbälle -Sportartikel > Wassersport > Windsurfen -Sportartikel > Wassersport > Windsurfen > Windsurf-Ausrüstung -Sportartikel > Wassersport > Windsurfen > Windsurf-Ausrüstung > Windsurf-Finnen -Sportartikel > Wassersport > Windsurfen > Windsurf-Ausrüstung > Windsurfmasten -Sportartikel > Wassersport > Windsurfen > Windsurf-Ausrüstung > Windsurfsegel -Sportartikel > Wassersport > Windsurfen > Windsurfbretter -Sportartikel > Wintersport -Sportartikel > Wintersport > Bobs -Sportartikel > Wintersport > Rodeln -Sportartikel > Wintersport > Schlitten -Sportartikel > Wintersport > Schlitten > Rodelschlitten -Sportartikel > Wintersport > Schlitten > Rodelschlitten > Rennschlitten -Sportartikel > Wintersport > Schlitten > Rodelschlitten > Schneerutscher -Sportartikel > Wintersport > Schlitten > Rodelschlitten > Toboggans -Sportartikel > Wintersport > Schlitten > Rodelschläuche -Sportartikel > Wintersport > Schneemobilsport -Sportartikel > Wintersport > Schneeschuhe & Zubehör -Sportartikel > Wintersport > Schneeschuhe & Zubehör > Schneeschuhbinder -Sportartikel > Wintersport > Schneeschuhe & Zubehör > Schneeschuhe -Sportartikel > Wintersport > Skisport -Sportartikel > Wintersport > Skisport > Ski- & Snowboard-Brillen -Sportartikel > Wintersport > Skisport > Ski- & Snowboard-Brillengläser -Sportartikel > Wintersport > Skisport > Ski- & Snowboardhelme -Sportartikel > Wintersport > Skisport > Skibindungen -Sportartikel > Wintersport > Skisport > Skibindungen > Skibindungen Alpin -Sportartikel > Wintersport > Skisport > Skibindungen > Skibindungen Langlauf -Sportartikel > Wintersport > Skisport > Skier -Sportartikel > Wintersport > Skisport > Skier > Alpinskier -Sportartikel > Wintersport > Skisport > Skier > Langlaufskier -Sportartikel > Wintersport > Skisport > Skier- & Snowboard-Ablagen -Sportartikel > Wintersport > Skisport > Skier- & Snowboard-Taschen -Sportartikel > Wintersport > Skisport > Skier- & Snowboard-Taschen > Skitaschen -Sportartikel > Wintersport > Skisport > Skier- & Snowboard-Taschen > Snowboardtaschen -Sportartikel > Wintersport > Skisport > Skischuhe -Sportartikel > Wintersport > Skisport > Skischuhe > Skischuhe Alpin -Sportartikel > Wintersport > Skisport > Skischuhe > Skischuhe Langlauf -Sportartikel > Wintersport > Skisport > Skistöcke -Sportartikel > Wintersport > Snowboarden -Sportartikel > Wintersport > Snowboarden > Snowboard-Bindungen -Sportartikel > Wintersport > Snowboarden > Snowboards -Sportartikel > Wintersport > Snowboarden > Snowboardstiefel -Sportartikel > Wintersport > Snowboarden > Zubehör Snowboard-Bindungen +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Lawinenschutz +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Lawinenschutz > Lawinenairbags +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Lawinenschutz > Lawinensonden +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Rodelschlitten +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Schneeschuhe & Zubehör +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Schneeschuhe & Zubehör > Schneeschuh-Bindungen +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Schneeschuhe & Zubehör > Schneeschuhe +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Ersatzteile für Skibindungen +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Ski- & Snowboard-Ablagen +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Ski- & Snowboard-Brillen +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Ski- & Snowboard-Brillenzubehör +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Ski- & Snowboard-Brillenzubehör > Ski- & Snowboard-Brillengläser +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Ski- & Snowboard-Leinen +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Ski- & Snowboard-Taschen +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Ski- & Snowboard-Wachs +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Ski- & Snowboardhelme +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Skibindungen +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Skier +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Skier > Alpinskier +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Skier > Langlaufskier +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Skischuhe +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Skistöcke +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Snowboard-Bindungen +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Snowboards +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Snowboardstiefel +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Tuningwerkzeuge für Skis & Snowboards +Sportartikel > Outdoor-Aktivitäten > Wintersport & -Aktivitäten > Skisport & Snowboarden > Zubehör Snowboard-Bindungen Taschen & Gepäck +Taschen & Gepäck > Aktentaschen Taschen & Gepäck > Bauchtaschen -Taschen & Gepäck > Business-Taschen -Taschen & Gepäck > Business-Taschen > Aktentaschen -Taschen & Gepäck > Business-Taschen > Kleidertaschen -Taschen & Gepäck > Business-Taschen > Taschen & Etuis für elektronische Geräte -Taschen & Gepäck > Business-Taschen > Taschen & Etuis für elektronische Geräte > Computerschutzhüllen -Taschen & Gepäck > Business-Taschen > Taschen & Etuis für elektronische Geräte > Laptoptaschen & -Etuis -Taschen & Gepäck > Business-Taschen > Taschen & Etuis für elektronische Geräte > Taschen & Etuis für Tablets Taschen & Gepäck > Einkaufstaschen Taschen & Gepäck > Gepäckzubehör +Taschen & Gepäck > Gepäckzubehör > Folien & Einsätze für Trockenboxen Taschen & Gepäck > Gepäckzubehör > Gepäck-Organizer Taschen & Gepäck > Gepäckzubehör > Gepäckanhänger +Taschen & Gepäck > Gepäckzubehör > Kofferablagen Taschen & Gepäck > Gepäckzubehör > Koffergurte Taschen & Gepäck > Gepäckzubehör > Reisebehälter Taschen & Gepäck > Gepäckzubehör > Reisedokumententaschen +Taschen & Gepäck > Gepäckzubehör > Rucksack-Schutzhüllen +Taschen & Gepäck > Kleidertaschen Taschen & Gepäck > Koffer -Taschen & Gepäck > Koffer > Handgepäck Taschen & Gepäck > Kosmetikkoffer Taschen & Gepäck > Kulturtaschen Taschen & Gepäck > Kurier- & Schultertaschen -Taschen & Gepäck > Rucksackzubehör -Taschen & Gepäck > Rucksackzubehör > Rucksack-Schutzhüllen Taschen & Gepäck > Rucksäcke Taschen & Gepäck > Seesäcke +Taschen & Gepäck > Trockenboxen Taschen & Gepäck > Wickeltaschen Tiere & Tierbedarf Tiere & Tierbedarf > Haustierbedarf +Tiere & Tierbedarf > Haustierbedarf > Agility-Ausrüstung Tiere & Tierbedarf > Haustierbedarf > Aquaristik Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Aquarien Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Aquariumbeleuchtung Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Aquariumdekoration -Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Aquariumdekoration > Künstliche Aquariumpflanzen Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Aquariumfilter -Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Aquariumpumpen Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Aquariumständer +Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Ausströmersteine & Diffusoren für Aquarien Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Bodengrund für Aquarien Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Fischfutter Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Fischfutterautomaten -Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Heizvorrichtungen für Aquarien +Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Fischnetze für Aquarien +Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Schläuche & Rohre für Aquarien & Teiche +Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Temperaturregler für Aquarien Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Wasseraufbereitungsgeräte Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Wasserpflanzendünger -Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Wasserpumpen für Aquarien +Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Zubehör für Aquariumreinigung Tiere & Tierbedarf > Haustierbedarf > Aquaristik > Überlaufkästen Tiere & Tierbedarf > Haustierbedarf > Augentropfen für Haustiere Tiere & Tierbedarf > Haustierbedarf > Begrenzungssysteme -Tiere & Tierbedarf > Haustierbedarf > Bodenschutz & Unterlagen Tiere & Tierbedarf > Haustierbedarf > Bügel für Haustierbekleidung +Tiere & Tierbedarf > Haustierbedarf > Entsorgungssysteme & -werkzeug für Tierkot Tiere & Tierbedarf > Haustierbedarf > Erkennungsmarken +Tiere & Tierbedarf > Haustierbedarf > Erste-Hilfe-Koffer für Haustiere Tiere & Tierbedarf > Haustierbedarf > Fitnessmonitor für Haustiere Tiere & Tierbedarf > Haustierbedarf > Fitnessmonitor für Haustiere > Glukosemessgeräte für Haustiere Tiere & Tierbedarf > Haustierbedarf > Fitnessmonitor für Haustiere > Schrittzähler für Haustiere Tiere & Tierbedarf > Haustierbedarf > Fitnessmonitor für Haustiere > Thermometer für Haustiere -Tiere & Tierbedarf > Haustierbedarf > Fitnessmonitor für Haustiere > Tierwaagen Tiere & Tierbedarf > Haustierbedarf > Floh- & Zeckenschutzmittel -Tiere & Tierbedarf > Haustierbedarf > Floh- & Zeckenschutzmittel > Mittel gegen Hundeflöhe/-zecken -Tiere & Tierbedarf > Haustierbedarf > Floh- & Zeckenschutzmittel > Mittel gegen Katzenflöhe/-zecken -Tiere & Tierbedarf > Haustierbedarf > Futternäpfe, Futter- & Wasserspender -Tiere & Tierbedarf > Haustierbedarf > Futternäpfe, Futter- & Wasserspender > Futternäpfe, Futter- & Wasserspender für Kleintiere -Tiere & Tierbedarf > Haustierbedarf > Futternäpfe, Futter- & Wasserspender > Hundeschüsseln, Futter- & Wasserspender -Tiere & Tierbedarf > Haustierbedarf > Futternäpfe, Futter- & Wasserspender > Katzenschüsseln, Futter- & Wasserspender +Tiere & Tierbedarf > Haustierbedarf > Futter- & Wasserspender Tiere & Tierbedarf > Haustierbedarf > Glocken & Anhänger Tiere & Tierbedarf > Haustierbedarf > Halsbänder & Geschirre -Tiere & Tierbedarf > Haustierbedarf > Halsbänder & Geschirre > Hundehalsbänder & Hundegeschirre -Tiere & Tierbedarf > Haustierbedarf > Halsbänder & Geschirre > Katzenhalsbänder & Katzengeschirre Tiere & Tierbedarf > Haustierbedarf > Haustierpflegeartikel +Tiere & Tierbedarf > Haustierbedarf > Haustierpflegeartikel > Düfte & Deosprays für Haustiere +Tiere & Tierbedarf > Haustierbedarf > Haustierpflegeartikel > Feuchttücher für Haustiere +Tiere & Tierbedarf > Haustierbedarf > Haustierpflegeartikel > Haartrockner für Haustiere Tiere & Tierbedarf > Haustierbedarf > Haustierpflegeartikel > Kämme & Bürsten zur Fellpflege Tiere & Tierbedarf > Haustierbedarf > Haustierpflegeartikel > Nagellack für Haustiere Tiere & Tierbedarf > Haustierbedarf > Haustierpflegeartikel > Nagelpflege für Haustiere Tiere & Tierbedarf > Haustierbedarf > Haustierpflegeartikel > Shampoos & Spülungen zur Fellpflege Tiere & Tierbedarf > Haustierbedarf > Haustierpflegeartikel > Tierhaarschneider -Tiere & Tierbedarf > Haustierbedarf > Haustiersportbedarf +Tiere & Tierbedarf > Haustierbedarf > Haustiertüren +Tiere & Tierbedarf > Haustierbedarf > Hilfsmittel für Tierausbildung +Tiere & Tierbedarf > Haustierbedarf > Hilfsmittel für Tierausbildung > Bodenschutz & Unterlagen +Tiere & Tierbedarf > Haustierbedarf > Hilfsmittel für Tierausbildung > Clicker & Belohnungsspielzeug für Tierausbildung +Tiere & Tierbedarf > Haustierbedarf > Hilfsmittel für Tierausbildung > Pad-Unterlagen für Tierausbildung +Tiere & Tierbedarf > Haustierbedarf > Hilfsmittel für Tierausbildung > Sprays & Lösungen für Tierausbildung Tiere & Tierbedarf > Haustierbedarf > Hundebedarf +Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Einlagen für Hundewindeln Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Hundebekleidung Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Hundebetten Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Hundefutter Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Hundehütten +Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Hundelaufbänder Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Hundespielzeug Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Hundewindeln Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Hundezwinger & -ausläufe Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Leckerbissen für Hunde Tiere & Tierbedarf > Haustierbedarf > Hundebedarf > Zubehör für Hundezwinger & -ausläufe Tiere & Tierbedarf > Haustierbedarf > Katzenbedarf +Tiere & Tierbedarf > Haustierbedarf > Katzenbedarf > Einlagen für Katzentoilette Tiere & Tierbedarf > Haustierbedarf > Katzenbedarf > Katzenbekleidung Tiere & Tierbedarf > Haustierbedarf > Katzenbedarf > Katzenbetten Tiere & Tierbedarf > Haustierbedarf > Katzenbedarf > Katzenfutter @@ -5934,23 +5162,20 @@ Tiere & Tierbedarf > Haustierbedarf > Katzenbedarf > Katzenstreu Tiere & Tierbedarf > Haustierbedarf > Katzenbedarf > Katzentoiletten Tiere & Tierbedarf > Haustierbedarf > Katzenbedarf > Leckerbissen für Katzen Tiere & Tierbedarf > Haustierbedarf > Katzenbedarf > Vorleger für Katzentoiletten +Tiere & Tierbedarf > Haustierbedarf > Katzenbedarf > Zubehör für Katzenmöbel Tiere & Tierbedarf > Haustierbedarf > Kleintierzubehör Tiere & Tierbedarf > Haustierbedarf > Kleintierzubehör > Decken & Streu für Kleintiere Tiere & Tierbedarf > Haustierbedarf > Kleintierzubehör > Futter für Kleintiere Tiere & Tierbedarf > Haustierbedarf > Kleintierzubehör > Lebensräume & Gehege für Kleintiere Tiere & Tierbedarf > Haustierbedarf > Kleintierzubehör > Leckerli für Kleintiere Tiere & Tierbedarf > Haustierbedarf > Kleintierzubehör > Zubehör für Lebensräume von Kleintieren +Tiere & Tierbedarf > Haustierbedarf > Kotbeutel Tiere & Tierbedarf > Haustierbedarf > Leinen -Tiere & Tierbedarf > Haustierbedarf > Leinen > Hundeleinen -Tiere & Tierbedarf > Haustierbedarf > Leinen > Katzenleinen -Tiere & Tierbedarf > Haustierbedarf > Lockmittel für Haustiere Tiere & Tierbedarf > Haustierbedarf > Maulkörbe Tiere & Tierbedarf > Haustierbedarf > Medizinische Halsbänder für Haustiere Tiere & Tierbedarf > Haustierbedarf > Medizinisches Klebeband & Verbandsmaterial für Haustiere Tiere & Tierbedarf > Haustierbedarf > Mundpflege für Haustiere -Tiere & Tierbedarf > Haustierbedarf > Mundpflege für Haustiere > Mundspray für Haustiere -Tiere & Tierbedarf > Haustierbedarf > Mundpflege für Haustiere > Zahnbürsten für Haustiere -Tiere & Tierbedarf > Haustierbedarf > Mundpflege für Haustiere > Zahnpasta für Haustiere +Tiere & Tierbedarf > Haustierbedarf > Napfständer Tiere & Tierbedarf > Haustierbedarf > Napfunterlagen Tiere & Tierbedarf > Haustierbedarf > Pet-Stroller Tiere & Tierbedarf > Haustierbedarf > Reptilien- & Amphibienbedarf @@ -5960,14 +5185,13 @@ Tiere & Tierbedarf > Haustierbedarf > Reptilien- & Amphibienbedarf > Reptilien- Tiere & Tierbedarf > Haustierbedarf > Reptilien- & Amphibienbedarf > Terrarien Tiere & Tierbedarf > Haustierbedarf > Reptilien- & Amphibienbedarf > Zubehör für Terrarien Tiere & Tierbedarf > Haustierbedarf > Sonnenschutz für Haustiere +Tiere & Tierbedarf > Haustierbedarf > Spender & Halterungen für Kotbeutel Tiere & Tierbedarf > Haustierbedarf > Spielgehege für Haustiere Tiere & Tierbedarf > Haustierbedarf > Tierfutterbehälter Tiere & Tierbedarf > Haustierbedarf > Tierfutterportionierer Tiere & Tierbedarf > Haustierbedarf > Tiermedikamente -Tiere & Tierbedarf > Haustierbedarf > Transportboxen und -taschen für Haustiere -Tiere & Tierbedarf > Haustierbedarf > Transportboxen und -taschen für Haustiere > Tragetaschen für Kleintiere -Tiere & Tierbedarf > Haustierbedarf > Transportboxen und -taschen für Haustiere > Transportboxen und -taschen für Hunde -Tiere & Tierbedarf > Haustierbedarf > Transportboxen und -taschen für Haustiere > Transportboxen und -taschen für Katzen +Tiere & Tierbedarf > Haustierbedarf > Transportboxen & -taschen +Tiere & Tierbedarf > Haustierbedarf > Trennvorrichtungen für den Haustiertransport Tiere & Tierbedarf > Haustierbedarf > Treppen & Rampen für Haustiere Tiere & Tierbedarf > Haustierbedarf > Verlängerungsleinen Tiere & Tierbedarf > Haustierbedarf > Vitamine & Nahrungsergänzungsmittel für Haustiere @@ -5977,29 +5201,44 @@ Tiere & Tierbedarf > Haustierbedarf > Vogelbedarf > Spielvorrichtungen für Vög Tiere & Tierbedarf > Haustierbedarf > Vogelbedarf > Vogelfutter Tiere & Tierbedarf > Haustierbedarf > Vogelbedarf > Vogelkäfige & -ständer Tiere & Tierbedarf > Haustierbedarf > Vogelbedarf > Vogelkäfigzubehör -Tiere & Tierbedarf > Haustierbedarf > Vogelbedarf > Vogelkäfigzubehör > Futter- und Wasserspender für Vogelkäfige +Tiere & Tierbedarf > Haustierbedarf > Vogelbedarf > Vogelkäfigzubehör > Futter- & Wasserspender für Vogelkäfige +Tiere & Tierbedarf > Haustierbedarf > Vogelbedarf > Vogelkäfigzubehör > Vogelbäder für Vogelkäfige Tiere & Tierbedarf > Haustierbedarf > Vogelbedarf > Vogelleitern & -sitzstangen Tiere & Tierbedarf > Haustierbedarf > Vogelbedarf > Vogelspielzeug +Tiere & Tierbedarf > Haustierbedarf > Wärmekissen für Haustiere +Tiere & Tierbedarf > Haustierbedarf > Zubehör für Haustier-Heizkissen +Tiere & Tierbedarf > Haustierbedarf > Zubehör für Haustierbetten +Tiere & Tierbedarf > Haustierbedarf > Zubehör für Haustierklappen +Tiere & Tierbedarf > Haustierbedarf > Zubehör für Haustiertragetaschen und -boxen Tiere & Tierbedarf > Lebende Tiere Wirtschaft & Industrie Wirtschaft & Industrie > Arbeitsschutzausrüstung Wirtschaft & Industrie > Arbeitsschutzausrüstung > Chemikalienschutzanzüge -Wirtschaft & Industrie > Arbeitsschutzausrüstung > Feuerschutzkleidung -Wirtschaft & Industrie > Arbeitsschutzausrüstung > Feuerwehr-Atemschutzmasken -Wirtschaft & Industrie > Arbeitsschutzausrüstung > Gasmasken +Wirtschaft & Industrie > Arbeitsschutzausrüstung > Gasmasken- & Atemschutzmaskenzubehör Wirtschaft & Industrie > Arbeitsschutzausrüstung > Halteseile +Wirtschaft & Industrie > Arbeitsschutzausrüstung > Knieschoner Wirtschaft & Industrie > Arbeitsschutzausrüstung > Kugelsichere Westen Wirtschaft & Industrie > Arbeitsschutzausrüstung > Schutzbrillen Wirtschaft & Industrie > Arbeitsschutzausrüstung > Schutzhandschuhe Wirtschaft & Industrie > Arbeitsschutzausrüstung > Schutzhelme +Wirtschaft & Industrie > Arbeitsschutzausrüstung > Schutzmasken +Wirtschaft & Industrie > Arbeitsschutzausrüstung > Schutzmasken > Feuerwehr-Atemschutzmasken +Wirtschaft & Industrie > Arbeitsschutzausrüstung > Schutzmasken > Gas- & Atemschutzmasken +Wirtschaft & Industrie > Arbeitsschutzausrüstung > Schutzmasken > Medizinische Masken +Wirtschaft & Industrie > Arbeitsschutzausrüstung > Schutzmasken > Staubmasken +Wirtschaft & Industrie > Arbeitsschutzausrüstung > Schweißhelme Wirtschaft & Industrie > Arbeitsschutzausrüstung > Sicherheitsschürzen -Wirtschaft & Industrie > Arbeitsschutzausrüstung > Signalkleidung -Wirtschaft & Industrie > Arbeitsschutzausrüstung > Staubmasken +Wirtschaft & Industrie > Arbeitsschutzausrüstung > Sicherungsgurte Wirtschaft & Industrie > Aufbewahrungszubehör für industrielle Zwecke +Wirtschaft & Industrie > Automatisierungskomponenten +Wirtschaft & Industrie > Automatisierungskomponenten > Antriebssysteme mit variabler Frequenz & einstellbarer Drehzahl +Wirtschaft & Industrie > Automatisierungskomponenten > Speicherprogrammierbare Steuerungen Wirtschaft & Industrie > Baugewerbe +Wirtschaft & Industrie > Baugewerbe > Verkehrskegel Wirtschaft & Industrie > Baugewerbe > Vermessung Wirtschaft & Industrie > Bergbau & Steinbruch Wirtschaft & Industrie > Beschilderung +Wirtschaft & Industrie > Beschilderung > Digitale Schilder Wirtschaft & Industrie > Beschilderung > Einzelhandelsschilder Wirtschaft & Industrie > Beschilderung > Elektronische Schilder Wirtschaft & Industrie > Beschilderung > Elektronische Schilder > LED-Schilder @@ -6015,19 +5254,21 @@ Wirtschaft & Industrie > Beschilderung > Warnschilder Wirtschaft & Industrie > Beschilderung > Wegweiser Wirtschaft & Industrie > Beschilderung > Öffnungszeiten-Schilder Wirtschaft & Industrie > Einzelhandel +Wirtschaft & Industrie > Einzelhandel > Einkaufstüten aus Papier & Plastik Wirtschaft & Industrie > Einzelhandel > Geldhandhabung Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Geldscheinprüfgeräte Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Geldtaschen Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Geldwechsler Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Geldzählmaschinen für Münzen und Scheine +Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Ladenkassen & POS-Terminals Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Münzrollenpapier & Geldscheinbanderolen -Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Registrierkassen & Kassenzubehör -Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Registrierkassen & Kassenzubehör > Kassenschubladen -Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Registrierkassen & Kassenzubehör > Kreditkartenleser -Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Registrierkassen & Kassenzubehör > Unterschriftenpads -Wirtschaft & Industrie > Einzelhandel > Plastiktüten +Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Zubehör für Ladenkassen & POS-Terminals +Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Zubehör für Ladenkassen & POS-Terminals > Kassenschubladen +Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Zubehör für Ladenkassen & POS-Terminals > Kreditkartenterminals +Wirtschaft & Industrie > Einzelhandel > Geldhandhabung > Zubehör für Ladenkassen & POS-Terminals > Unterschriftenpads Wirtschaft & Industrie > Einzelhandel > Preisauszeichnungsgeräte Wirtschaft & Industrie > Einzelhandel > Präsentationsständer für Bekleidung +Wirtschaft & Industrie > Einzelhandel > Schaufensterdeko & -puppen Wirtschaft & Industrie > Einzelhandel > Schaufensterpuppen Wirtschaft & Industrie > Einzelhandel > Schaufensterpuppenteile Wirtschaft & Industrie > Einzelhandel > Vitrinen @@ -6036,63 +5277,77 @@ Wirtschaft & Industrie > Finanzwesen & Versicherung Wirtschaft & Industrie > Finanzwesen & Versicherung > Bullion Wirtschaft & Industrie > Forst- & Holzwirtschaft Wirtschaft & Industrie > Friseur- & Kosmetikgewerbe -Wirtschaft & Industrie > Friseur- & Kosmetikgewerbe > Pediküresessel +Wirtschaft & Industrie > Friseur- & Kosmetikgewerbe > Friseurumhänge & Halskrausen +Wirtschaft & Industrie > Friseur- & Kosmetikgewerbe > Pedikürestuhl Wirtschaft & Industrie > Friseur- & Kosmetikgewerbe > Salonstühle Wirtschaft & Industrie > Gewerbliche Lagerung Wirtschaft & Industrie > Gewerbliche Lagerung > Frachtcontainer Wirtschaft & Industrie > Gewerbliche Lagerung > Industrieregale Wirtschaft & Industrie > Gewerbliche Lagerung > Industrieschränke +Wirtschaft & Industrie > Gewerbliche Lagerung > Zäune, Einfriedungen & Türen Wirtschaft & Industrie > Herstellung Wirtschaft & Industrie > Hotels & Gaststätten Wirtschaft & Industrie > Landwirtschaft Wirtschaft & Industrie > Landwirtschaft > Viehhaltung -Wirtschaft & Industrie > Landwirtschaft > Viehhaltung > Hühnerställe +Wirtschaft & Industrie > Landwirtschaft > Viehhaltung > Brutapparate +Wirtschaft & Industrie > Landwirtschaft > Viehhaltung > Viehfutter Wirtschaft & Industrie > Landwirtschaft > Viehhaltung > Viehfutterspender +Wirtschaft & Industrie > Landwirtschaft > Viehhaltung > Viehhalfter Wirtschaft & Industrie > Materialbeförderung +Wirtschaft & Industrie > Materialbeförderung > Aufzüge & Hebeeinrichtungen +Wirtschaft & Industrie > Materialbeförderung > Aufzüge & Hebeeinrichtungen > Flaschenzüge & Rollen +Wirtschaft & Industrie > Materialbeförderung > Aufzüge & Hebeeinrichtungen > Hebezüge, Kräne & Laufkatzen +Wirtschaft & Industrie > Materialbeförderung > Aufzüge & Hebeeinrichtungen > Hubwagen +Wirtschaft & Industrie > Materialbeförderung > Aufzüge & Hebeeinrichtungen > Personenaufzüge +Wirtschaft & Industrie > Materialbeförderung > Aufzüge & Hebeeinrichtungen > Seilwinden Wirtschaft & Industrie > Materialbeförderung > Förderanlagen -Wirtschaft & Industrie > Materialbeförderung > Gabelstapler +Wirtschaft & Industrie > Materialbeförderung > Paletten & Ladeflächen Wirtschaft & Industrie > Medizinischer Bereich Wirtschaft & Industrie > Medizinischer Bereich > Krankenhaus-Vorhänge Wirtschaft & Industrie > Medizinischer Bereich > Krankenhausbekleidung Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Bettwäsche Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Automatisierte externe Defibrillatoren -Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Medizinische Zangen +Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Medizinische Hebegürtel Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Otoskope & Ophthalmoskope Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Patientenlifter Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Reflexhämmer -Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Skalpelle Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Stethoskope +Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Tragen Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Vitaldatenmonitore Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Geräte > Zubehör für Vitaldatenmonitore +Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Instrumente +Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Instrumente > Chirurgische Nadeln und Fäden +Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Instrumente > Medizinische Zangen +Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Instrumente > Skalpelle +Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Instrumente > Skalpellklingen Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Chiropraktische Tische Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Krankenhaus- und Pflegebetten Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Medikamentenaufbewahrung -Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Medikamentenaufbewahrung > Betäubungsmittelschränke Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Medizinische Wagen Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Medizinische Wagen > Infusionsständer & -wagen Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Medizinische Wagen > Reanimationswagen Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > OP-Tische -Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Untersuchungsstühle -Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Untersuchungsstühle > Gynäkologische Stühle -Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Untersuchungsstühle > Optometrische Stühle -Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Untersuchungsstühle > Zahnarztstühle +Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Möbel > Untersuchungsstühle & -tische Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Schulungsgeräte Wirtschaft & Industrie > Medizinischer Bereich > Medizinische Schulungsgeräte > HLW-Puppen Wirtschaft & Industrie > Medizinischer Bereich > Medizinischer Bedarf Wirtschaft & Industrie > Medizinischer Bereich > Medizinischer Bedarf > Einweghandschuhe Wirtschaft & Industrie > Medizinischer Bereich > Medizinischer Bedarf > Fingerlinge -Wirtschaft & Industrie > Medizinischer Bereich > Medizinischer Bedarf > Medizinische Masken -Wirtschaft & Industrie > Medizinischer Bereich > Medizinischer Bedarf > Zungenspatel +Wirtschaft & Industrie > Medizinischer Bereich > Medizinischer Bedarf > Mundspatel +Wirtschaft & Industrie > Medizinischer Bereich > Medizinischer Bedarf > Nadeln & Spritzen +Wirtschaft & Industrie > Medizinischer Bereich > Medizinischer Bedarf > Stomazubehör Wirtschaft & Industrie > Medizinischer Bereich > OP-Bekleidung Wirtschaft & Industrie > Medizinischer Bereich > OP-Hauben Wirtschaft & Industrie > Medizinischer Bereich > OP-Kittel Wirtschaft & Industrie > Nahrungsmittelservice +Wirtschaft & Industrie > Nahrungsmittelservice > Auslagenschutz Wirtschaft & Industrie > Nahrungsmittelservice > Backwarenbehälter Wirtschaft & Industrie > Nahrungsmittelservice > Einweg-Serviergeschirr Wirtschaft & Industrie > Nahrungsmittelservice > Einweg-Serviergeschirr > Einwegtabletts Wirtschaft & Industrie > Nahrungsmittelservice > Einwegbehälter +Wirtschaft & Industrie > Nahrungsmittelservice > Einwegdeckel Wirtschaft & Industrie > Nahrungsmittelservice > Einweggeschirr Wirtschaft & Industrie > Nahrungsmittelservice > Einweggeschirr > Einwegbecher Wirtschaft & Industrie > Nahrungsmittelservice > Einweggeschirr > Einwegbesteck @@ -6101,10 +5356,10 @@ Wirtschaft & Industrie > Nahrungsmittelservice > Einweggeschirr > Einwegteller Wirtschaft & Industrie > Nahrungsmittelservice > Eisbehälter Wirtschaft & Industrie > Nahrungsmittelservice > Gemüseschleudern Wirtschaft & Industrie > Nahrungsmittelservice > Hot-Dog-Grills -Wirtschaft & Industrie > Nahrungsmittelservice > Kippbare Industrietöpfe +Wirtschaft & Industrie > Nahrungsmittelservice > Kippbare Industriepfannen Wirtschaft & Industrie > Nahrungsmittelservice > Lebensmittelkörbe +Wirtschaft & Industrie > Nahrungsmittelservice > Scheck- & Kartenetuis Wirtschaft & Industrie > Nahrungsmittelservice > Servierwagen -Wirtschaft & Industrie > Nahrungsmittelservice > Spender für Einmalbesteck Wirtschaft & Industrie > Nahrungsmittelservice > Spülwannen Wirtschaft & Industrie > Nahrungsmittelservice > Takeaway-Behälter Wirtschaft & Industrie > Nahrungsmittelservice > Teller- & Speisenwärmer @@ -6117,15 +5372,12 @@ Wirtschaft & Industrie > Piercing & Tätowieren > Tätowierbedarf > Tattoo-Abdec Wirtschaft & Industrie > Piercing & Tätowieren > Tätowierbedarf > Tätowierfarben Wirtschaft & Industrie > Piercing & Tätowieren > Tätowierbedarf > Tätowiermaschinen Wirtschaft & Industrie > Piercing & Tätowieren > Tätowierbedarf > Tätowiernadeln +Wirtschaft & Industrie > Reinigungswagen Wirtschaft & Industrie > Schwermaschinen Wirtschaft & Industrie > Schwermaschinen > Häcksler -Wirtschaft & Industrie > Sicherheitssektor -Wirtschaft & Industrie > Sicherheitssektor > Metalldetektoren -Wirtschaft & Industrie > Sicherheitssektor > Schellen -Wirtschaft & Industrie > Sicherheitssektor > Schellen > Fußgelenkschellen -Wirtschaft & Industrie > Sicherheitssektor > Schellen > Fußschellen -Wirtschaft & Industrie > Sicherheitssektor > Schellen > Handschellen -Wirtschaft & Industrie > Sicherheitssektor > Schlagstöcke +Wirtschaft & Industrie > Strafverfolgung +Wirtschaft & Industrie > Strafverfolgung > Metalldetektoren +Wirtschaft & Industrie > Strafverfolgung > Schellen Wirtschaft & Industrie > Werbung & Marketing Wirtschaft & Industrie > Werbung & Marketing > Broschüren Wirtschaft & Industrie > Werbung & Marketing > Messestand-Displays @@ -6134,8 +5386,11 @@ Wirtschaft & Industrie > Wissenschaft & Labor Wirtschaft & Industrie > Wissenschaft & Labor > Biochemikalien Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Autoklaven +Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Gefriertrockenmaschinen +Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Labor-Gefrierschränke Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Labor-Heizplatten Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Labormixer +Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Labortrichter Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Laboröfen Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Mikroskope Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Mikroskopzubehör @@ -6146,7 +5401,6 @@ Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Mikroskopzube Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Mikroskopzubehör > Objektträger Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Mikrotome Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Spektrometer -Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Spektrometer > Spektralfotometer Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Trockeneismaschinen Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Zentrifugen Wirtschaft & Industrie > Wissenschaft & Labor > Laborausstattung > Zubehör für Spektrometer @@ -6160,9 +5414,14 @@ Wirtschaft & Industrie > Wissenschaft & Labor > Laborbedarf > Reagenzglasstände Wirtschaft & Industrie > Wissenschaft & Labor > Laborbedarf > Reagenzgläser Wirtschaft & Industrie > Wissenschaft & Labor > Laborbedarf > Spritzflaschen Wirtschaft & Industrie > Wissenschaft & Labor > Laborchemikalien +Wirtschaft & Industrie > Wissenschaft & Labor > Laborproben Wirtschaft & Industrie > Wissenschaft & Labor > Sezierinstrumente Wirtschaft & Industrie > Zahnmedizin +Wirtschaft & Industrie > Zahnmedizin > Prophy-Paste Wirtschaft & Industrie > Zahnmedizin > Zahnmedizinische Instrumente -Wirtschaft & Industrie > Zahnmedizin > Zahnmedizinische Instrumente > Zahnmedizinische Ausstattung -Wirtschaft & Industrie > Zahnmedizin > Zahnmedizinische Instrumente > Zahnmedizinische Spiegel -Wirtschaft & Industrie > Zahnmedizin > Zahnzement +Wirtschaft & Industrie > Zahnmedizin > Zahnmedizinische Instrumente > Dappengläser +Wirtschaft & Industrie > Zahnmedizin > Zahnmedizinische Instrumente > Dentalspiegel +Wirtschaft & Industrie > Zahnmedizin > Zahnmedizinische Instrumente > Prophy-Kelche +Wirtschaft & Industrie > Zahnmedizin > Zahnmedizinische Instrumente > Prophy-Köpfe +Wirtschaft & Industrie > Zahnmedizin > Zahnmedizinische Instrumente > Zahnmedizinische Instrumentensets +Wirtschaft & Industrie > Zahnmedizin > Zahnzement \ No newline at end of file diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/Files/taxonomy.en-US.txt b/src/Plugins/SmartStore.GoogleMerchantCenter/Files/taxonomy.en-US.txt index f7004f5fca..671672c564 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/Files/taxonomy.en-US.txt +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/Files/taxonomy.en-US.txt @@ -1,9 +1,9 @@ - -Animals & Pet Supplies +Animals & Pet Supplies Animals & Pet Supplies > Live Animals Animals & Pet Supplies > Pet Supplies Animals & Pet Supplies > Pet Supplies > Bird Supplies Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Cage Accessories +Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Cage Accessories > Bird Cage Bird Baths Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Cage Accessories > Bird Cage Food & Water Dishes Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Cages & Stands Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Food @@ -16,7 +16,9 @@ Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Apparel Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Beds Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Food Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Furniture +Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Furniture Accessories Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Litter +Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Litter Box Liners Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Litter Box Mats Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Litter Boxes Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Toys @@ -25,23 +27,26 @@ Animals & Pet Supplies > Pet Supplies > Dog Supplies Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Apparel Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Beds Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Diaper Pads & Liners +Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Diapers Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Food Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Houses Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Kennel & Run Accessories Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Kennels & Runs Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Toys +Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Treadmills Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Treats Animals & Pet Supplies > Pet Supplies > Fish Supplies -Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Air Pumps +Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium & Pond Tubing +Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Air Stones & Diffusers +Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Cleaning Supplies Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Decor -Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Decor > Artificial Aquarium Plants Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Filters +Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Fish Nets Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Gravel & Substrates -Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Heating Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Lighting Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Overflow Boxes Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Stands -Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Water Pumps +Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Temperature Controllers Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Water Treatments Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquariums Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquatic Plant Fertilizers @@ -49,57 +54,58 @@ Animals & Pet Supplies > Pet Supplies > Fish Supplies > Fish Feeders Animals & Pet Supplies > Pet Supplies > Fish Supplies > Fish Food Animals & Pet Supplies > Pet Supplies > Pet Agility Equipment Animals & Pet Supplies > Pet Supplies > Pet Apparel Hangers -Animals & Pet Supplies > Pet Supplies > Pet Attractant +Animals & Pet Supplies > Pet Supplies > Pet Bed Accessories Animals & Pet Supplies > Pet Supplies > Pet Bells & Charms Animals & Pet Supplies > Pet Supplies > Pet Biometric Monitors Animals & Pet Supplies > Pet Supplies > Pet Biometric Monitors > Pet Glucose Meters Animals & Pet Supplies > Pet Supplies > Pet Biometric Monitors > Pet Pedometers -Animals & Pet Supplies > Pet Supplies > Pet Biometric Monitors > Pet Scales Animals & Pet Supplies > Pet Supplies > Pet Biometric Monitors > Pet Thermometers Animals & Pet Supplies > Pet Supplies > Pet Bowl Mats +Animals & Pet Supplies > Pet Supplies > Pet Bowl Stands Animals & Pet Supplies > Pet Supplies > Pet Bowls, Feeders & Waterers -Animals & Pet Supplies > Pet Supplies > Pet Bowls, Feeders & Waterers > Cat Bowls, Feeders & Waterers -Animals & Pet Supplies > Pet Supplies > Pet Bowls, Feeders & Waterers > Dog Bowls, Feeders & Waterers -Animals & Pet Supplies > Pet Supplies > Pet Bowls, Feeders & Waterers > Small Animal Bowls, Feeders & Waterers +Animals & Pet Supplies > Pet Supplies > Pet Carrier & Crate Accessories Animals & Pet Supplies > Pet Supplies > Pet Carriers & Crates -Animals & Pet Supplies > Pet Supplies > Pet Carriers & Crates > Cat Carriers & Crates -Animals & Pet Supplies > Pet Supplies > Pet Carriers & Crates > Dog Carriers & Crates -Animals & Pet Supplies > Pet Supplies > Pet Carriers & Crates > Small Animal Carriers Animals & Pet Supplies > Pet Supplies > Pet Collars & Harnesses -Animals & Pet Supplies > Pet Supplies > Pet Collars & Harnesses > Cat Collars & Harnesses -Animals & Pet Supplies > Pet Supplies > Pet Collars & Harnesses > Dog Collars & Harnesses Animals & Pet Supplies > Pet Supplies > Pet Containment Systems +Animals & Pet Supplies > Pet Supplies > Pet Door Accessories +Animals & Pet Supplies > Pet Supplies > Pet Doors Animals & Pet Supplies > Pet Supplies > Pet Eye Drops & Lubricants +Animals & Pet Supplies > Pet Supplies > Pet First Aid & Emergency Kits Animals & Pet Supplies > Pet Supplies > Pet Flea & Tick Control -Animals & Pet Supplies > Pet Supplies > Pet Flea & Tick Control > Cat Flea & Tick Control -Animals & Pet Supplies > Pet Supplies > Pet Flea & Tick Control > Dog Flea & Tick Control Animals & Pet Supplies > Pet Supplies > Pet Food Containers Animals & Pet Supplies > Pet Supplies > Pet Food Scoops Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Combs & Brushes +Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Fragrances & Deodorizing Sprays Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Hair Clippers & Trimmers +Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Hair Dryers Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Nail Polish Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Nail Tools Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Shampoo & Conditioner +Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Wipes +Animals & Pet Supplies > Pet Supplies > Pet Heating Pad Accessories +Animals & Pet Supplies > Pet Supplies > Pet Heating Pads Animals & Pet Supplies > Pet Supplies > Pet ID Tags Animals & Pet Supplies > Pet Supplies > Pet Leash Extensions Animals & Pet Supplies > Pet Supplies > Pet Leashes -Animals & Pet Supplies > Pet Supplies > Pet Leashes > Cat Leashes -Animals & Pet Supplies > Pet Supplies > Pet Leashes > Dog Leashes Animals & Pet Supplies > Pet Supplies > Pet Medical Collars Animals & Pet Supplies > Pet Supplies > Pet Medical Tape & Bandages Animals & Pet Supplies > Pet Supplies > Pet Medicine Animals & Pet Supplies > Pet Supplies > Pet Muzzles -Animals & Pet Supplies > Pet Supplies > Pet Oral Care -Animals & Pet Supplies > Pet Supplies > Pet Oral Care > Pet Breath Spray -Animals & Pet Supplies > Pet Supplies > Pet Oral Care > Pet Toothbrushes -Animals & Pet Supplies > Pet Supplies > Pet Oral Care > Pet Toothpaste +Animals & Pet Supplies > Pet Supplies > Pet Oral Care Supplies Animals & Pet Supplies > Pet Supplies > Pet Playpens Animals & Pet Supplies > Pet Supplies > Pet Steps & Ramps Animals & Pet Supplies > Pet Supplies > Pet Strollers Animals & Pet Supplies > Pet Supplies > Pet Sunscreen -Animals & Pet Supplies > Pet Supplies > Pet Training Pads +Animals & Pet Supplies > Pet Supplies > Pet Training Aids +Animals & Pet Supplies > Pet Supplies > Pet Training Aids > Pet Training Clickers & Treat Dispensers +Animals & Pet Supplies > Pet Supplies > Pet Training Aids > Pet Training Pad Holders +Animals & Pet Supplies > Pet Supplies > Pet Training Aids > Pet Training Pads +Animals & Pet Supplies > Pet Supplies > Pet Training Aids > Pet Training Sprays & Solutions Animals & Pet Supplies > Pet Supplies > Pet Vitamins & Supplements +Animals & Pet Supplies > Pet Supplies > Pet Waste Bag Dispensers & Holders +Animals & Pet Supplies > Pet Supplies > Pet Waste Bags +Animals & Pet Supplies > Pet Supplies > Pet Waste Disposal Systems & Tools Animals & Pet Supplies > Pet Supplies > Reptile & Amphibian Supplies Animals & Pet Supplies > Pet Supplies > Reptile & Amphibian Supplies > Reptile & Amphibian Food Animals & Pet Supplies > Pet Supplies > Reptile & Amphibian Supplies > Reptile & Amphibian Habitat Accessories @@ -112,68 +118,42 @@ Animals & Pet Supplies > Pet Supplies > Small Animal Supplies > Small Animal Foo Animals & Pet Supplies > Pet Supplies > Small Animal Supplies > Small Animal Habitat Accessories Animals & Pet Supplies > Pet Supplies > Small Animal Supplies > Small Animal Habitats & Cages Animals & Pet Supplies > Pet Supplies > Small Animal Supplies > Small Animal Treats +Animals & Pet Supplies > Pet Supplies > Vehicle Pet Barriers Apparel & Accessories Apparel & Accessories > Clothing Apparel & Accessories > Clothing > Activewear -Apparel & Accessories > Clothing > Activewear > Active Dresses -Apparel & Accessories > Clothing > Activewear > Active Jackets -Apparel & Accessories > Clothing > Activewear > Active Jackets > Windbreakers -Apparel & Accessories > Clothing > Activewear > Active Leotards -Apparel & Accessories > Clothing > Activewear > Active Pants -Apparel & Accessories > Clothing > Activewear > Active Shirts -Apparel & Accessories > Clothing > Activewear > Active Shorts -Apparel & Accessories > Clothing > Activewear > Active Skirts -Apparel & Accessories > Clothing > Activewear > Active Tanks -Apparel & Accessories > Clothing > Activewear > Active Undergarments -Apparel & Accessories > Clothing > Activewear > Active Undergarments > Active Underwear -Apparel & Accessories > Clothing > Activewear > Active Undergarments > Compression Undergarment Shorts -Apparel & Accessories > Clothing > Activewear > Active Undergarments > Jock Straps -Apparel & Accessories > Clothing > Activewear > Active Undergarments > Sports Bras -Apparel & Accessories > Clothing > Activewear > Activewear Sets Apparel & Accessories > Clothing > Activewear > Bicycle Activewear Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Bibs Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Jerseys -Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Shorts +Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Shorts & Briefs Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Skinsuits Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Tights Apparel & Accessories > Clothing > Activewear > Boxing Shorts -Apparel & Accessories > Clothing > Activewear > Dancewear -Apparel & Accessories > Clothing > Activewear > Dancewear > Dance Dresses -Apparel & Accessories > Clothing > Activewear > Dancewear > Dance Pants -Apparel & Accessories > Clothing > Activewear > Dancewear > Dance Skirts -Apparel & Accessories > Clothing > Activewear > Dancewear > Dance Tights -Apparel & Accessories > Clothing > Activewear > Dancewear > Dance Tops +Apparel & Accessories > Clothing > Activewear > Dance Dresses, Skirts & Costumes Apparel & Accessories > Clothing > Activewear > Football Pants Apparel & Accessories > Clothing > Activewear > Hunting Clothing Apparel & Accessories > Clothing > Activewear > Hunting Clothing > Ghillie Suits +Apparel & Accessories > Clothing > Activewear > Hunting Clothing > Hunting & Fishing Vests Apparel & Accessories > Clothing > Activewear > Hunting Clothing > Hunting & Tactical Pants -Apparel & Accessories > Clothing > Activewear > Hunting Clothing > Hunting & Tactical Vests -Apparel & Accessories > Clothing > Activewear > Long Johns Apparel & Accessories > Clothing > Activewear > Martial Arts Shorts Apparel & Accessories > Clothing > Activewear > Motorcycle Protective Clothing Apparel & Accessories > Clothing > Activewear > Motorcycle Protective Clothing > Motorcycle Jackets Apparel & Accessories > Clothing > Activewear > Motorcycle Protective Clothing > Motorcycle Pants Apparel & Accessories > Clothing > Activewear > Motorcycle Protective Clothing > Motorcycle Suits Apparel & Accessories > Clothing > Activewear > Paintball Clothing -Apparel & Accessories > Clothing > Activewear > Sauna Suits -Apparel & Accessories > Clothing > Activewear > Snow Pants & Suits Apparel & Accessories > Clothing > Baby & Toddler Clothing Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Bottoms Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Diaper Covers Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Dresses Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Outerwear Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Outfits +Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Sleepwear Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Socks & Tights Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Swimwear Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Tops -Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby Onesies -Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby Sleepwear & Swaddlers +Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby One-Pieces Apparel & Accessories > Clothing > Baby & Toddler Clothing > Toddler Underwear Apparel & Accessories > Clothing > Dresses -Apparel & Accessories > Clothing > Dresses > Cocktail Dresses -Apparel & Accessories > Clothing > Dresses > Day Dresses -Apparel & Accessories > Clothing > Dresses > Formal Gowns -Apparel & Accessories > Clothing > Dresses > Little Black Dresses Apparel & Accessories > Clothing > One-Pieces Apparel & Accessories > Clothing > One-Pieces > Jumpsuits & Rompers Apparel & Accessories > Clothing > One-Pieces > Leotards & Unitards @@ -181,46 +161,14 @@ Apparel & Accessories > Clothing > One-Pieces > Overalls Apparel & Accessories > Clothing > Outerwear Apparel & Accessories > Clothing > Outerwear > Chaps Apparel & Accessories > Clothing > Outerwear > Coats & Jackets -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Anorak Jackets -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Blazers -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Boleros -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Capes & Ponchos -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Denim Jackets -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Down & Snow Jackets -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Fleece Jackets -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Fur Coats -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Leather & Suede Jackets -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Overcoats -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Trench Coats -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Tweed Jackets -Apparel & Accessories > Clothing > Outerwear > Coats & Jackets > Varsity Jackets -Apparel & Accessories > Clothing > Outerwear > Rain Gear -Apparel & Accessories > Clothing > Outerwear > Rain Gear > Rain Pants -Apparel & Accessories > Clothing > Outerwear > Rain Gear > Rain Suits -Apparel & Accessories > Clothing > Outerwear > Rain Gear > Raincoats +Apparel & Accessories > Clothing > Outerwear > Rain Pants +Apparel & Accessories > Clothing > Outerwear > Rain Suits +Apparel & Accessories > Clothing > Outerwear > Snow Pants & Suits Apparel & Accessories > Clothing > Outerwear > Vests Apparel & Accessories > Clothing > Outfit Sets Apparel & Accessories > Clothing > Pants -Apparel & Accessories > Clothing > Pants > Cargo Pants -Apparel & Accessories > Clothing > Pants > Corduroy & Velvet Pants -Apparel & Accessories > Clothing > Pants > Dress Pants -Apparel & Accessories > Clothing > Pants > Jeans -Apparel & Accessories > Clothing > Pants > Khaki & Chino Pants -Apparel & Accessories > Clothing > Pants > Leather & Suede Pants -Apparel & Accessories > Clothing > Pants > Leggings -Apparel & Accessories > Clothing > Pants > Linen Pants Apparel & Accessories > Clothing > Shirts & Tops -Apparel & Accessories > Clothing > Shirts & Tops > Camisoles & Tank Tops -Apparel & Accessories > Clothing > Shirts & Tops > Polo Shirts -Apparel & Accessories > Clothing > Shirts & Tops > Shirts & Blouses -Apparel & Accessories > Clothing > Shirts & Tops > Sports Fan Jerseys -Apparel & Accessories > Clothing > Shirts & Tops > Sweaters & Cardigans -Apparel & Accessories > Clothing > Shirts & Tops > Sweatshirts -Apparel & Accessories > Clothing > Shirts & Tops > T-Shirts Apparel & Accessories > Clothing > Shorts -Apparel & Accessories > Clothing > Shorts > Bermuda Shorts -Apparel & Accessories > Clothing > Shorts > Cargo Shorts -Apparel & Accessories > Clothing > Shorts > Short Shorts Apparel & Accessories > Clothing > Skirts Apparel & Accessories > Clothing > Skorts Apparel & Accessories > Clothing > Sleepwear & Loungewear @@ -231,31 +179,17 @@ Apparel & Accessories > Clothing > Sleepwear & Loungewear > Robes Apparel & Accessories > Clothing > Suits Apparel & Accessories > Clothing > Suits > Pant Suits Apparel & Accessories > Clothing > Suits > Skirt Suits -Apparel & Accessories > Clothing > Suits > Suit Separates Apparel & Accessories > Clothing > Suits > Tuxedos Apparel & Accessories > Clothing > Swimwear -Apparel & Accessories > Clothing > Swimwear > Bikinis -Apparel & Accessories > Clothing > Swimwear > Cover-Ups -Apparel & Accessories > Clothing > Swimwear > One-Piece Swimsuits -Apparel & Accessories > Clothing > Swimwear > Swim Briefs -Apparel & Accessories > Clothing > Swimwear > Swim Shorts -Apparel & Accessories > Clothing > Swimwear > Swimsuit Bottoms -Apparel & Accessories > Clothing > Swimwear > Swimsuit Tops -Apparel & Accessories > Clothing > Swimwear > Tankinis & Extra Coverage Swimwear Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Dirndls Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Hakama Trousers +Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Japanese Black Formal Wear Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimono Outerwear -Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimono Outerwear > Haori Jackets -Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimono Outerwear > Kimono Coats Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimonos -Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimonos > Bridal Kimonos -Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimonos > Casual Kimonos -Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimonos > Furisode Kimonos -Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimonos > Iromuji Kimonos -Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimonos > Komon Kimonos -Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimonos > Tomesode & Houmongi Kimonos Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Religious Ceremonial Clothing +Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Religious Ceremonial Clothing > Baptism & Communion Dresses +Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Saris & Lehengas Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Traditional Leather Pants Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Yukata Apparel & Accessories > Clothing > Underwear & Socks @@ -265,13 +199,13 @@ Apparel & Accessories > Clothing > Underwear & Socks > Bra Accessories > Bra Str Apparel & Accessories > Clothing > Underwear & Socks > Bra Accessories > Breast Enhancing Inserts Apparel & Accessories > Clothing > Underwear & Socks > Bra Accessories > Breast Petals & Concealers Apparel & Accessories > Clothing > Underwear & Socks > Bras -Apparel & Accessories > Clothing > Underwear & Socks > Bras > Nursing Bras -Apparel & Accessories > Clothing > Underwear & Socks > Bridal Intimates Apparel & Accessories > Clothing > Underwear & Socks > Hosiery +Apparel & Accessories > Clothing > Underwear & Socks > Jock Straps Apparel & Accessories > Clothing > Underwear & Socks > Lingerie Apparel & Accessories > Clothing > Underwear & Socks > Lingerie Accessories Apparel & Accessories > Clothing > Underwear & Socks > Lingerie Accessories > Garter Belts Apparel & Accessories > Clothing > Underwear & Socks > Lingerie Accessories > Garters +Apparel & Accessories > Clothing > Underwear & Socks > Long Johns Apparel & Accessories > Clothing > Underwear & Socks > Petticoats & Pettipants Apparel & Accessories > Clothing > Underwear & Socks > Shapewear Apparel & Accessories > Clothing > Underwear & Socks > Socks @@ -305,9 +239,7 @@ Apparel & Accessories > Clothing > Wedding & Bridal Party Dresses Apparel & Accessories > Clothing > Wedding & Bridal Party Dresses > Bridal Party Dresses Apparel & Accessories > Clothing > Wedding & Bridal Party Dresses > Wedding Dresses Apparel & Accessories > Clothing Accessories -Apparel & Accessories > Clothing Accessories > Arm & Leg Warmers -Apparel & Accessories > Clothing Accessories > Arm & Leg Warmers > Arm Warmers -Apparel & Accessories > Clothing Accessories > Arm & Leg Warmers > Leg Warmers +Apparel & Accessories > Clothing Accessories > Arm Warmers & Sleeves Apparel & Accessories > Clothing Accessories > Baby & Toddler Clothing Accessories Apparel & Accessories > Clothing Accessories > Baby & Toddler Clothing Accessories > Baby & Toddler Belts Apparel & Accessories > Clothing Accessories > Baby & Toddler Clothing Accessories > Baby & Toddler Gloves & Mittens @@ -322,75 +254,59 @@ Apparel & Accessories > Clothing Accessories > Bridal Accessories > Bridal Veils Apparel & Accessories > Clothing Accessories > Button Studs Apparel & Accessories > Clothing Accessories > Collar Stays Apparel & Accessories > Clothing Accessories > Cufflinks +Apparel & Accessories > Clothing Accessories > Decorative Fans Apparel & Accessories > Clothing Accessories > Earmuffs -Apparel & Accessories > Clothing Accessories > Folding Fans Apparel & Accessories > Clothing Accessories > Gloves & Mittens -Apparel & Accessories > Clothing Accessories > Gloves & Mittens > Formal Gloves -Apparel & Accessories > Clothing Accessories > Gloves & Mittens > Gloves -Apparel & Accessories > Clothing Accessories > Gloves & Mittens > Mittens -Apparel & Accessories > Clothing Accessories > Gloves & Mittens > Ski & Snowboard Gloves Apparel & Accessories > Clothing Accessories > Hair Accessories -Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Claws +Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Bun & Volume Shapers Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Combs Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Extensions Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Forks & Sticks Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Nets -Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Pins & Clips +Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Pins, Claws & Clips Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Wreaths Apparel & Accessories > Clothing Accessories > Hair Accessories > Headbands Apparel & Accessories > Clothing Accessories > Hair Accessories > Ponytail Holders Apparel & Accessories > Clothing Accessories > Hair Accessories > Tiaras +Apparel & Accessories > Clothing Accessories > Hair Accessories > Wig Accessories +Apparel & Accessories > Clothing Accessories > Hair Accessories > Wig Accessories > Wig Caps +Apparel & Accessories > Clothing Accessories > Hair Accessories > Wig Accessories > Wig Glue & Tape +Apparel & Accessories > Clothing Accessories > Hair Accessories > Wigs Apparel & Accessories > Clothing Accessories > Hand Muffs Apparel & Accessories > Clothing Accessories > Handkerchiefs Apparel & Accessories > Clothing Accessories > Hats -Apparel & Accessories > Clothing Accessories > Hats > Beanies -Apparel & Accessories > Clothing Accessories > Hats > Berets -Apparel & Accessories > Clothing Accessories > Hats > Bowler & Derby Hats -Apparel & Accessories > Clothing Accessories > Hats > Caps -Apparel & Accessories > Clothing Accessories > Hats > Caps > Baseball Caps -Apparel & Accessories > Clothing Accessories > Hats > Caps > Newsboy Caps -Apparel & Accessories > Clothing Accessories > Hats > Cowboys Hats -Apparel & Accessories > Clothing Accessories > Hats > Fedoras -Apparel & Accessories > Clothing Accessories > Hats > Sun Hats -Apparel & Accessories > Clothing Accessories > Hats > Umbrella Hats -Apparel & Accessories > Clothing Accessories > Hats > Visors Apparel & Accessories > Clothing Accessories > Headwear Apparel & Accessories > Clothing Accessories > Headwear > Fascinators Apparel & Accessories > Clothing Accessories > Headwear > Headdresses Apparel & Accessories > Clothing Accessories > Headwear > Turbans +Apparel & Accessories > Clothing Accessories > Leg Warmers Apparel & Accessories > Clothing Accessories > Leis +Apparel & Accessories > Clothing Accessories > Maternity Belts & Support Bands Apparel & Accessories > Clothing Accessories > Neck Gaiters Apparel & Accessories > Clothing Accessories > Neckties -Apparel & Accessories > Clothing Accessories > Neckties > Ascot Ties -Apparel & Accessories > Clothing Accessories > Neckties > Bolo Ties -Apparel & Accessories > Clothing Accessories > Neckties > Bow Ties -Apparel & Accessories > Clothing Accessories > Neckties > Ties Apparel & Accessories > Clothing Accessories > Pinback Buttons +Apparel & Accessories > Clothing Accessories > Sashes Apparel & Accessories > Clothing Accessories > Scarves & Shawls Apparel & Accessories > Clothing Accessories > Sunglasses Apparel & Accessories > Clothing Accessories > Suspenders Apparel & Accessories > Clothing Accessories > Tie Clips Apparel & Accessories > Clothing Accessories > Traditional Clothing Accessories -Apparel & Accessories > Clothing Accessories > Traditional Clothing Accessories > Kimono Underclothes -Apparel & Accessories > Clothing Accessories > Traditional Clothing Accessories > Obi Accessories Apparel & Accessories > Clothing Accessories > Traditional Clothing Accessories > Obis Apparel & Accessories > Clothing Accessories > Traditional Clothing Accessories > Tabi Socks -Apparel & Accessories > Clothing Accessories > Veils Apparel & Accessories > Clothing Accessories > Wristbands Apparel & Accessories > Costumes & Accessories Apparel & Accessories > Costumes & Accessories > Costume Accessories Apparel & Accessories > Costumes & Accessories > Costume Accessories > Bald Caps Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Accessory Sets Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Capes +Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Gloves Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Hats +Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Special Effects +Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Tobacco Products Apparel & Accessories > Costumes & Accessories > Costume Accessories > Pretend Jewelry Apparel & Accessories > Costumes & Accessories > Costume Shoes Apparel & Accessories > Costumes & Accessories > Costumes Apparel & Accessories > Costumes & Accessories > Masks -Apparel & Accessories > Costumes & Accessories > Wig Accessories -Apparel & Accessories > Costumes & Accessories > Wig Accessories > Wig Caps -Apparel & Accessories > Costumes & Accessories > Wig Accessories > Wig Glue -Apparel & Accessories > Costumes & Accessories > Wigs Apparel & Accessories > Handbag & Wallet Accessories Apparel & Accessories > Handbag & Wallet Accessories > Checkbook Covers Apparel & Accessories > Handbag & Wallet Accessories > Keychains @@ -400,13 +316,6 @@ Apparel & Accessories > Handbags, Wallets & Cases Apparel & Accessories > Handbags, Wallets & Cases > Badge & Pass Holders Apparel & Accessories > Handbags, Wallets & Cases > Business Card Cases Apparel & Accessories > Handbags, Wallets & Cases > Handbags -Apparel & Accessories > Handbags, Wallets & Cases > Handbags > Clutches & Special Occasion Bags -Apparel & Accessories > Handbags, Wallets & Cases > Handbags > Cross-Body Handbags -Apparel & Accessories > Handbags, Wallets & Cases > Handbags > Hobo Handbags -Apparel & Accessories > Handbags, Wallets & Cases > Handbags > Satchels -Apparel & Accessories > Handbags, Wallets & Cases > Handbags > Shoulder Bags -Apparel & Accessories > Handbags, Wallets & Cases > Handbags > Tote Handbags -Apparel & Accessories > Handbags, Wallets & Cases > Handbags > Wristlets Apparel & Accessories > Handbags, Wallets & Cases > Wallets & Money Clips Apparel & Accessories > Jewelry Apparel & Accessories > Jewelry > Anklets @@ -416,8 +325,6 @@ Apparel & Accessories > Jewelry > Brooches & Lapel Pins Apparel & Accessories > Jewelry > Charms & Pendants Apparel & Accessories > Jewelry > Earrings Apparel & Accessories > Jewelry > Jewelry Sets -Apparel & Accessories > Jewelry > Loose Stones -Apparel & Accessories > Jewelry > Loose Stones > Diamonds Apparel & Accessories > Jewelry > Necklaces Apparel & Accessories > Jewelry > Rings Apparel & Accessories > Jewelry > Watch Accessories @@ -425,8 +332,6 @@ Apparel & Accessories > Jewelry > Watch Accessories > Watch Bands Apparel & Accessories > Jewelry > Watch Accessories > Watch Stickers & Decals Apparel & Accessories > Jewelry > Watch Accessories > Watch Winders Apparel & Accessories > Jewelry > Watches -Apparel & Accessories > Jewelry > Watches > Analog Watches -Apparel & Accessories > Jewelry > Watches > Digital Watches Apparel & Accessories > Shoe Accessories Apparel & Accessories > Shoe Accessories > Boot Liners Apparel & Accessories > Shoe Accessories > Gaiters @@ -434,87 +339,180 @@ Apparel & Accessories > Shoe Accessories > Shoe Covers Apparel & Accessories > Shoe Accessories > Shoelaces Apparel & Accessories > Shoe Accessories > Spurs Apparel & Accessories > Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Ballet & Dance Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Basketball Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Bowling Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Boxing Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Cheerleading Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Cycling Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Golf Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Indoor Court Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Indoor Court Shoes > Badminton Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Indoor Court Shoes > Handball Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Indoor Court Shoes > Volleyball Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Indoor Soccer Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Skateboarding Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Table Tennis Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Tennis Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Weightlifting Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Athletic Shoes > Wrestling Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Cleats -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Cleats > Baseball & Softball Cleats -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Cleats > Football Cleats -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Cleats > Lacrosse Cleats -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Cleats > Rugby Boots -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Cleats > Soccer Cleats -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Cleats > Track Spikes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Sneakers -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Sneakers > Cross Training Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Sneakers > Fashion Sneakers -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Sneakers > Running Shoes -Apparel & Accessories > Shoes > Athletic Shoes & Sneakers > Sneakers > Walking Shoes -Apparel & Accessories > Shoes > Baby & Toddler Shoes -Apparel & Accessories > Shoes > Boots -Apparel & Accessories > Shoes > Boots > Cowboy Boots -Apparel & Accessories > Shoes > Boots > Desert & Chukka Boots -Apparel & Accessories > Shoes > Boots > Dress Boots -Apparel & Accessories > Shoes > Boots > Motorcycle Boots -Apparel & Accessories > Shoes > Boots > Rain Boots -Apparel & Accessories > Shoes > Boots > Riding Boots -Apparel & Accessories > Shoes > Boots > Shearling & Fur Trimmed Boots -Apparel & Accessories > Shoes > Boots > Snow Boots -Apparel & Accessories > Shoes > Boots > Work & Safety Boots -Apparel & Accessories > Shoes > Clogs & Mules -Apparel & Accessories > Shoes > Dress Shoes -Apparel & Accessories > Shoes > Dress Shoes > Formal Shoes -Apparel & Accessories > Shoes > Dress Shoes > Oxford Shoes -Apparel & Accessories > Shoes > Dress Shoes > Pumps -Apparel & Accessories > Shoes > Dress Shoes > Pumps > Basic Pumps -Apparel & Accessories > Shoes > Dress Shoes > Pumps > D'orsay & Two-Piece Pumps -Apparel & Accessories > Shoes > Dress Shoes > Pumps > Spectator Pumps -Apparel & Accessories > Shoes > Espadrilles -Apparel & Accessories > Shoes > Flats -Apparel & Accessories > Shoes > Loafers & Slip-Ons -Apparel & Accessories > Shoes > Moccasins -Apparel & Accessories > Shoes > Outdoor Shoes -Apparel & Accessories > Shoes > Outdoor Shoes > Climbing Shoes -Apparel & Accessories > Shoes > Outdoor Shoes > Fishing & Hunting Shoes -Apparel & Accessories > Shoes > Outdoor Shoes > Gardening Shoes -Apparel & Accessories > Shoes > Outdoor Shoes > Hiking Boots & Shoes -Apparel & Accessories > Shoes > Outdoor Shoes > Performance Boating Shoes -Apparel & Accessories > Shoes > Outdoor Shoes > Water Shoes -Apparel & Accessories > Shoes > Sandals -Apparel & Accessories > Shoes > Sandals > Fisherman Sandals -Apparel & Accessories > Shoes > Sandals > Slide Sandals -Apparel & Accessories > Shoes > Sandals > Thongs & Flip-Flops -Apparel & Accessories > Shoes > Slippers Arts & Entertainment +Arts & Entertainment > Event Tickets Arts & Entertainment > Hobbies & Creative Arts -Arts & Entertainment > Hobbies & Creative Arts > Artwork -Arts & Entertainment > Hobbies & Creative Arts > Artwork > Cardboard Cutouts -Arts & Entertainment > Hobbies & Creative Arts > Artwork > Drawings & Illustrations -Arts & Entertainment > Hobbies & Creative Arts > Artwork > Mixed Media Art -Arts & Entertainment > Hobbies & Creative Arts > Artwork > Paintings -Arts & Entertainment > Hobbies & Creative Arts > Artwork > Photographs -Arts & Entertainment > Hobbies & Creative Arts > Artwork > Photographs > Stock Photographs -Arts & Entertainment > Hobbies & Creative Arts > Artwork > Posters -Arts & Entertainment > Hobbies & Creative Arts > Artwork > Sculptures & Statues +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Candle Making Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Drawing & Painting Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Fabric Repair Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Incense Making Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Jewelry Making Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Mosaic Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Needlecraft Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Scrapbooking & Stamping Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Toy Craft Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Cardstock & Scrapbooking Paper +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Construction Paper +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Craft Foil +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Drawing & Painting Paper +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Origami Paper +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Transfer Paper +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Vellum Paper +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Buttons & Snaps +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Clasps & Hooks +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Eyelets & Grommets +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Hook and Loop Fasteners +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Zipper Pulls +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Zippers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Art & Craft Paint +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Art Fixatives +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Art Ink +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Ceramic & Pottery Glazes +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Craft Dyes +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Ink Pads +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Paint Mediums +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Shapes & Bases +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Shapes & Bases > Craft Foam & Styrofoam +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Shapes & Bases > Craft Wood & Shapes +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Shapes & Bases > Papier Mache Shapes +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Shapes & Bases > Wreath & Floral Frames +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets > Craft & Office Glue +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets > Craft Magnets +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets > Decorative Tape +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets > Floral Tape +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets > Fusible Tape +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Fibers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Fibers > Jewelry & Beading Cord +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Fibers > Thread & Floss +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Fibers > Unspun Fiber +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Fibers > Yarn +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Wire +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Wire > Craft Pipe Cleaners +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Wire > Floral Wire +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Wire > Jewelry & Beading Wire +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Appliques & Patches +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Beads +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Bows & Yo-Yos +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Decorative Stickers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Elastic +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Feathers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Jewelry Findings +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Loose Stones +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Rhinestones & Flatbacks +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Ribbons & Trim +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Sequins & Glitter +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Sew-in Labels +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embossing Powder +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Filling & Padding Material +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Filling & Padding Material > Batting & Stuffing +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Filling & Padding Material > Filling Pellets +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Filling & Padding Material > Pillow Forms +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Leather & Vinyl +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials > Clay & Modeling Dough +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials > Papier Mache Mixes +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials > Plaster Gauze +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials > Pottery Slips +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Raw Candle Wax +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Crafting Canvas +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Crafting Canvas > Needlecraft Canvas +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Crafting Canvas > Painting Canvas +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Crafting Canvas > Plastic Canvas +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Fabric +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Interfacing +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Printable Fabric +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Wick Tabs +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Wicks +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Craft Knife Blades +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Craft Machine Cases & Covers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Sewing Machine Extension Tables +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Sewing Machine Feet +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Sewing Machine Replacement Parts +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Spinning Wheel Accessories +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Stamp Blocks +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Blocking Mats +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Blocking Wires +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Color Mixing Tools +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Color Mixing Tools > Palette Knives +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Color Mixing Tools > Palettes +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Craft & Office Scissors +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Craft Cutters & Embossers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Craft Knives +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Craft Scoring Tools +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Embossing Heat Tools +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Embossing Pens & Styluses +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Seam Rippers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Thread & Yarn Cutters +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Decoration Makers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Art Brushes +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Brayer Rollers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Decorative Stamps +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Drafting Compasses +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Screen Printing Squeegees +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Stencil Machines +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Stencils & Die Cuts +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Stitch Markers & Counters +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Textile Art Gauges & Rulers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Wood Burning Tools +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Cutting Mats +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Dress Forms +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Felting Pads & Mats +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Frames, Hoops & Stretchers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Glue Guns +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Light Boxes +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks > Crochet Hooks +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks > Hand-Sewing Needles +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks > Knitting Needles +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks > Latch & Locker Hooks +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks > Sewing Machine Needles +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Safety Pins +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Straight Pins +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines > Felting Needles & Machines +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines > Hand Looms +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines > Mechanical Looms +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines > Sewing Machines +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines > Spinning Wheels +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thimbles & Sewing Palms +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Fiber Cards & Brushes +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Hand Spindles +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Needle Threaders +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Thread & Yarn Guides +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Thread & Yarn Spools +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Thread, Yarn & Bobbin Winders +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Weaving Beaters +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Weaving Shuttles +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Craft Organization +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Craft Organization > Needle, Pin & Hook Organizers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Craft Organization > Sewing Baskets & Kits +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Craft Organization > Thread & Yarn Organizers +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds > Beading Patterns +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds > Craft Molds +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds > Felting Molds +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds > Needlecraft Patterns +Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds > Sewing Patterns Arts & Entertainment > Hobbies & Creative Arts > Collectibles Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Autographs Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Coins & Currency +Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Trading Cards Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Weapons +Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Weapons > Collectible Guns Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Weapons > Collectible Knives Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Weapons > Collectible Swords Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Weapons > Sword Stands & Displays @@ -528,6 +526,7 @@ Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectib Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Auto Racing Autographed Paraphernalia Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Baseball & Softball Autographed Paraphernalia Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Basketball Autographed Paraphernalia +Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Boxing Autographed Paraphernalia Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Football Autographed Paraphernalia Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Hockey Autographed Paraphernalia Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Soccer Autographed Paraphernalia @@ -540,381 +539,182 @@ Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectib Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories > Hockey Fan Accessories Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories > Soccer Fan Accessories Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories > Tennis Fan Accessories -Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Trading Cards -Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Trading Cards > Sports Trading Cards -Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Trading Cards > Sports Trading Cards > Auto Racing Trading Cards -Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Trading Cards > Sports Trading Cards > Baseball Trading Cards -Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Trading Cards > Sports Trading Cards > Basketball Trading Cards -Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Trading Cards > Sports Trading Cards > Football Trading Cards -Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Trading Cards > Sports Trading Cards > Hockey Trading Cards -Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Trading Cards > Sports Trading Cards > Soccer Trading Cards Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Vintage Advertisements -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Art Paper -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Art Paper > Construction Paper -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Art Paper > Origami Paper -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Art Paper > Scratchboard Paper -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Art Paper > Sketch Pads -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Art Paper > Tracing Paper -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Art Paper > Transfer Paper -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Art Paper > Vellum -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Art Paper > Watercolor Paper -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Beading Patterns -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Candle & Soap Making -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Candle & Soap Making > Wick Tabs -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Candle & Soap Making > Wicks -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Canvas & Boards -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Craft & Hobby Storage -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Craft & Hobby Storage > Knitting Needle & Crochet Hook Cases -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Craft & Hobby Storage > Sewing Organizers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Craft & Hobby Storage > Yarn Organizers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Craft Blanks -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Craft Foam & Styrofoam -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Craft Magnets -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Craft Molds -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Craft Pipe Cleaners -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Decorative Stickers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Drawing & Painting -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Drawing & Painting > Art Brushes -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Drawing & Painting > Drafting -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Drawing & Painting > Drafting > Drafting Compasses -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Drawing & Painting > Drawing & Painting Kits -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Drawing & Painting > Painting -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Drawing & Painting > Painting > Art Paint -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Drawing & Painting > Painting > Paint Mediums -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Drawing & Painting > Painting > Palette Knives -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Drawing & Painting > Painting > Palettes -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fabric Yo-Yos -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Crocheting -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Crocheting > Crochet Hooks -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Crocheting > Crochet Thread -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Cross-Stitch & Embroidery -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Felting -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Felting > Felting Molds -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Felting > Felting Needles -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Felting > Felting Pads & Mats -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Fibercraft Patterns -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Fibercraft Patterns > Cross-Stitch & Embroidery Patterns -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Fibercraft Patterns > Knitting & Crocheting Patterns -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Fibercraft Patterns > Sewing Patterns -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Hand Spinning -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Hand Spinning > Hand Spindles -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Hand Spinning > Spinning Wheel Accessories -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Hand Spinning > Spinning Wheels -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Knitting -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Knitting > Knitting Needles -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Lace, Trims & Trimmings -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Needlepoint -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Needlepoint > Needlepoint Canvas -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Needlepoint > Needlepoint Kits -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Quilting -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Elastic -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Fabric -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Fabric Patches -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Hook & Loop Fasteners -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Interfacing -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Plastic Canvas -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Sewing Buttons -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Sewing Labels -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Sewing Snaps -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Stuffing & Filling Material -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Textile Dyes -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Textile Paints -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Thread -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Unspun Fiber -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Yarn -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Materials > Zippers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Blocking Mats -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Blocking Wires -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Bow & Pom-Pom Makers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Dressforms -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Fabric Adhesives -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Fabric Adhesives > Fabric Glue -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Fabric Adhesives > Fusible Fabric Tape -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Fabric Cutter Dies -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Fabric Cutters -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Fabric Marking Tools -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Fabric Repair Kits -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Fabric Scissors & Shears -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Fiber Cards -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Looms -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Needle Threaders -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Pin Cushions -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Safety Pins -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Seam Rippers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Sewing Needles -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Stitch Markers & Counters -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Straight Pins -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Textile Art Frames, Hoops & Stretchers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Textile Art Gauges & Rulers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Thimbles -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Thread & Yarn Cutters -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Thread & Yarn Guides -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Thread & Yarn Spools -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Thread & Yarn Winders -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Textile Art Tools & Accessories > Yo-Yo Makers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Weaving -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Weaving > Locker Hooks -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Weaving > Weaving Beaters -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Fibercraft & Textile Arts > Weaving > Weaving Shuttles -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Flower Arranging -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Flower Arranging > Floral Tape -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Flower Arranging > Vase Fillers & Table Scatters -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Glass Crafts -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Glitter -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Homebrewing -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Homebrewing > Beer Brewing -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Homebrewing > Wine Making -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Incense Making Kits -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Jewelry Making -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Jewelry Making > Beads -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Jewelry Making > Jewelry & Beading Cord -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Jewelry Making > Jewelry & Beading Wire -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Jewelry Making > Jewelry Findings -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Juggling -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Leather Crafts -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Light Boxes -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Magic & Novelties -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Magnetic Tape -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Model Making -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Model Making > Model Rocketry -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Model Making > Model Train Accessories -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Model Making > Model Trains & Train Sets -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Model Making > Scale Model Kits -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Mosaic Making -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Mosaic Making > Mosaic Kits -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Paper Crafts -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Paper Crafts > Card Making Kits -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Paper Crafts > Embossing -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Paper Crafts > Embossing > Embossers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Paper Crafts > Embossing > Embossing Dies -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Paper Crafts > Embossing > Embossing Folders -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Paper Crafts > Embossing > Embossing Heat Tools -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Paper Crafts > Embossing > Embossing Pens -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Paper Crafts > Embossing > Embossing Powder -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Paper Crafts > Paper Creasers & Scorers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Pottery & Sculpting -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Pottery & Sculpting > Modeling Clay & Dough -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Printmaking -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Printmaking > Screen Printing -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Printmaking > Screen Printing > Brayer Rollers -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Printmaking > Screen Printing > Screen Printing Squeegees -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Rhinestones -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Scrapbooking -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Sequins -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Stamping -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Stamping > Leather Stamps & Kits -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Stamping > Metal Stamps & Kits -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Stenciling -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Stenciling > Stencil Machines -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Stenciling > Stencils & Dies -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Watch Repair Kits -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Woodworking -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Wreath Making -Arts & Entertainment > Hobbies & Creative Arts > Crafts & Hobbies > Wreath Making > Wreath Frames -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Brushes, Snakes & Cleaning Rods -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Care Kits -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Cleaners & Sanitizers -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Guards -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Lubricants -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Polishing Cloths -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Brass Instrument Replacement Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Euphonium Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Euphonium Accessories > Euphonium Cases & Gigbags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Euphonium Accessories > Euphonium Mouthpieces -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Euphonium Accessories > Euphonium Mutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Euphonium Accessories > Euphonium Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > French Horn Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > French Horn Accessories > French Horn Cases & Gigbags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > French Horn Accessories > French Horn Mouthpieces -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > French Horn Accessories > French Horn Mutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > French Horn Accessories > French Horn Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trombone Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trombone Accessories > Trombone Cases & Gigbags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trombone Accessories > Trombone Lyres -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trombone Accessories > Trombone Mouthpieces -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trombone Accessories > Trombone Mutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trombone Accessories > Trombone Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trumpet & Cornet Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trumpet & Cornet Accessories > Trumpet & Cornet Cases & Gigbags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trumpet & Cornet Accessories > Trumpet & Cornet Lyres -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trumpet & Cornet Accessories > Trumpet & Cornet Mouthpieces -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trumpet & Cornet Accessories > Trumpet & Cornet Mutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Trumpet & Cornet Accessories > Trumpet & Cornet Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Tuba Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Tuba Accessories > Tuba Cases & Gigbags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Tuba Accessories > Tuba Mouthpieces -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Tuba Accessories > Tuba Mutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Brass Instrument Accessories > Tuba Accessories > Tuba Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Electronic Tuners -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Music Stand Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Music Stand Accessories > Music Stand Bags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Music Stand Accessories > Music Stand Lights -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Music Stand Accessories > Sheet Music Clips -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Music Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Musical Instrument Amplifier Cabinets -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Musical Instrument Amplifier Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Musical Instrument Amplifiers -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Musical Keyboard Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Musical Keyboard Accessories > Musical Keyboard Bags & Cases -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Musical Keyboard Accessories > Musical Keyboard Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Musical Keyboard Accessories > Sustain Pedals -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Cymbal & Drum Cases -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Cymbal & Drum Mutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Drum Heads -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Drum Keys -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Drum Kit Hardware -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Drum Kit Hardware > Bass Drum Beaters -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Drum Kit Hardware > Drum Kit Mounting Hardware -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Drum Kit Hardware > Drum Pedals -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Drum Stick Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Drum Stick Accessories > Drum Stick Bags & Holders -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Drum Sticks -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Drumming Thrones -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Electronic Drum Modules -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Hand Percussion Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Hand Percussion Accessories > Hand Percussion Bags & Cases -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Hand Percussion Accessories > Hand Percussion Stands & Mounts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Percussion Mallets -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Percussion Accessories > Percussion Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Piano Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Piano Accessories > Piano Benches -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Cello Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Cello Accessories > Cello Bows -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Cello Accessories > Cello Cases -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Cello Accessories > Cello Mutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Cello Accessories > Cello Strings -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Acoustic Guitar Pickups -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Capos -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Electric Guitar Pickups -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Guitar Bridge Pins -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Guitar Cases & Gig Bags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Guitar Humidifiers -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Guitar Picks -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Guitar Slides -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Guitar Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Guitar Strings -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Guitar Accessories > Guitar Tuning Machines -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Harp Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Harp Accessories > Harp Cases -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Harp Accessories > Harp Strings -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > String Instrument Care & Cleaning -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > String Instrument Care & Cleaning > Bow Rosin -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > String Instrument Care & Cleaning > String Instrument Cleaning Cloths -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > String Instrument Care & Cleaning > String Instrument Polish -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Upright Bass Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Upright Bass Accessories > Upright Bass Bows -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Upright Bass Accessories > Upright Bass Cases -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Upright Bass Accessories > Upright Bass Mutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Upright Bass Accessories > Upright Bass Strings -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Viola Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Viola Accessories > Viola Bows -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Viola Accessories > Viola Cases -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Viola Accessories > Viola Mutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Viola Accessories > Viola Strings -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories > Violin & Viola Chinrests -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories > Violin & Viola Shoulder Rests -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories > Violin Bows -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories > Violin Bridges -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories > Violin Cases -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories > Violin Mutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories > Violin Pickups -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories > Violin Strings -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories > Violin Tailpieces -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > String Instrument Accessories > Violin Accessories > Violin Tuning Pegs -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Bassoon Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Care & Cleaning -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Care & Cleaning > Bassoon Swabs -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Cases & Gigbags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Parts > Bassoon Bocals -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Parts > Bassoon Small Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Reeds -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Straps & Supports -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning > Clarinet Care Kits -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning > Clarinet Pad Savers -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning > Clarinet Swabs -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Cases & Gigbags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Ligatures & Caps -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Lyres -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Barrels -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Bells -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Mouthpieces -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Small Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Pegs & Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Reeds -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Straps & Supports -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning > Flute Care Kits -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning > Flute Cleaning Rods -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning > Flute Swabs -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Cases & Gigbags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Lyres -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Parts > Flute Headjoints -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Parts > Flute Small Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Pegs & Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Harmonica Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Harmonica Accessories > Harmonica Cases -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Harmonica Accessories > Harmonica Holders -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Care & Cleaning -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Care & Cleaning > Oboe Care Kits -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Care & Cleaning > Oboe Swabs -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Cases & Gigbags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Parts > Oboe Small Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Pegs & Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Reeds -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Straps & Supports -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning > Saxophone Care Kits -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning > Saxophone Pad Savers -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning > Saxophone Swabs -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Cases & Gigbags -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Ligatures & Caps -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Lyres -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts > Saxophone Mouthpieces -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts > Saxophone Necks -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts > Saxophone Small Parts -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Pegs & Stands -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Reeds -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Straps & Supports -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Woodwind Cork Grease -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Woodwind Polishing Cloths -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Woodwind Reed Cases -Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument Accessories > Woodwind Instrument Accessories > Woodwind Reed Knives +Arts & Entertainment > Hobbies & Creative Arts > Homebrewing & Winemaking Supplies +Arts & Entertainment > Hobbies & Creative Arts > Homebrewing & Winemaking Supplies > Beer Brewing Grains & Malts +Arts & Entertainment > Hobbies & Creative Arts > Homebrewing & Winemaking Supplies > Bottling Bottles +Arts & Entertainment > Hobbies & Creative Arts > Homebrewing & Winemaking Supplies > Homebrewing & Winemaking Kits +Arts & Entertainment > Hobbies & Creative Arts > Homebrewing & Winemaking Supplies > Wine Making +Arts & Entertainment > Hobbies & Creative Arts > Juggling +Arts & Entertainment > Hobbies & Creative Arts > Magic & Novelties +Arts & Entertainment > Hobbies & Creative Arts > Model Making +Arts & Entertainment > Hobbies & Creative Arts > Model Making > Model Rocketry +Arts & Entertainment > Hobbies & Creative Arts > Model Making > Model Train Accessories +Arts & Entertainment > Hobbies & Creative Arts > Model Making > Model Trains & Train Sets +Arts & Entertainment > Hobbies & Creative Arts > Model Making > Scale Model Kits +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Care Kits +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Cleaners & Sanitizers +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Cleaning Tools +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Guards +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Lubricants +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Polishing Cloths +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Cases & Gigbags +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Mouthpieces +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Mutes +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Replacement Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Straps & Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Conductor Batons +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Electronic Tuners +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Metronomes +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Benches & Stools +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Lyres & Flip Folders +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Stand Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Stand Accessories > Music Stand Bags +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Stand Accessories > Music Stand Lights +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Stand Accessories > Sheet Music Clips +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Cabinets +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Covers & Cases +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Footswitches +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Knobs +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Tubes +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifiers +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Keyboard Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Keyboard Accessories > Musical Keyboard Bags & Cases +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Keyboard Accessories > Musical Keyboard Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Keyboard Accessories > Sustain Pedals +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Cymbal & Drum Cases +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Cymbal & Drum Mutes +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Heads +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Keys +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Kit Hardware +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Kit Hardware > Bass Drum Beaters +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Kit Hardware > Drum Kit Mounting Hardware +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Kit Hardware > Drum Pedals +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Stick & Brush Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Stick & Brush Accessories > Drum Stick & Brush Bags & Holders +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Sticks & Brushes +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Electronic Drum Modules +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Hand Percussion Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Hand Percussion Accessories > Hand Percussion Bags & Cases +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Hand Percussion Accessories > Hand Percussion Stands & Mounts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Percussion Mallets +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Percussion Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Acoustic Guitar Pickups +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Capos +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Electric Guitar Pickups +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Cases & Gig Bags +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Fittings & Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Humidifiers +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Picks +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Slides +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Straps +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar String Winders +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Strings +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Tuning Pegs +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Bow Cases +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Bows +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Cases +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Fittings & Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Mutes +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Pickups +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Strings +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > String Instrument Care & Cleaning +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > String Instrument Care & Cleaning > Bow Rosin +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > String Instrument Care & Cleaning > String Instrument Cleaning Cloths +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > String Instrument Care & Cleaning > String Instrument Polish +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Care & Cleaning +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Care & Cleaning > Bassoon Swabs +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Cases & Gigbags +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Parts > Bassoon Bocals +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Parts > Bassoon Small Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Reeds +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Straps & Supports +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning > Clarinet Care Kits +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning > Clarinet Pad Savers +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning > Clarinet Swabs +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Cases & Gigbags +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Ligatures & Caps +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Barrels +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Bells +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Mouthpieces +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Small Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Pegs & Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Reeds +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Straps & Supports +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning > Flute Care Kits +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning > Flute Cleaning Rods +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning > Flute Swabs +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Cases & Gigbags +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Parts > Flute Headjoints +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Parts > Flute Small Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Pegs & Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Harmonica Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Harmonica Accessories > Harmonica Cases +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Harmonica Accessories > Harmonica Holders +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Care & Cleaning +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Care & Cleaning > Oboe Care Kits +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Care & Cleaning > Oboe Swabs +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Cases & Gigbags +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Parts > Oboe Small Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Pegs & Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Reeds +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Straps & Supports +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Recorder Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Recorder Accessories > Recorder Care & Cleaning +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Recorder Accessories > Recorder Cases +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Recorder Accessories > Recorder Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning > Saxophone Care Kits +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning > Saxophone Pad Savers +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning > Saxophone Swabs +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Cases & Gigbags +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Ligatures & Caps +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts > Saxophone Mouthpieces +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts > Saxophone Necks +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts > Saxophone Small Parts +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Pegs & Stands +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Reeds +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Straps & Supports +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Woodwind Cork Grease +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Woodwind Polishing Cloths +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Woodwind Reed Cases +Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Woodwind Reed Knives Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Accordions & Concertinas Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Bagpipes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass > Cornets -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass > Euphoniums -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass > Flugel Horns -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass > French Horns -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass > Mellophones -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass > Sousaphones -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass > Trombones -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass > Trumpets -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass > Tubas +Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments +Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > Alto & Baritone Horns +Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > Euphoniums +Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > French Horns +Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > Trombones +Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > Trumpets & Cornets +Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > Tubas Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Electronic Musical Instruments Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Electronic Musical Instruments > Audio Samplers Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Electronic Musical Instruments > MIDI Controllers @@ -930,7 +730,6 @@ Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussio Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Claves & Castanets Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Finger & Hand Cymbals -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Bells Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Bells & Chimes Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Drums Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Drums > Bongos @@ -955,9 +754,6 @@ Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Pianos Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Cellos Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Guitars -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Guitars > Acoustic Guitars -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Guitars > Bass Guitars -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Guitars > Electric Guitars Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Harps Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Upright Basses Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Violas @@ -966,7 +762,6 @@ Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Bassoons Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Clarinets Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Flutes -Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Flutes > Fifes Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Flutophones Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Harmonicas Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Jew's Harps @@ -980,59 +775,62 @@ Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Train Whistles Arts & Entertainment > Party & Celebration Arts & Entertainment > Party & Celebration > Gift Giving -Arts & Entertainment > Party & Celebration > Gift Giving > Corsage & Boutonnière Pins -Arts & Entertainment > Party & Celebration > Gift Giving > Corsages & Boutonnières +Arts & Entertainment > Party & Celebration > Gift Giving > Corsage & Boutonnière Pins +Arts & Entertainment > Party & Celebration > Gift Giving > Corsages & Boutonnières Arts & Entertainment > Party & Celebration > Gift Giving > Fresh Cut Flowers Arts & Entertainment > Party & Celebration > Gift Giving > Gift Cards & Certificates Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping -Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Bows & Ribbons Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Gift Bags Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Gift Boxes & Tins +Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Gift Tags & Labels Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Tissue Paper Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Wrapping Paper Arts & Entertainment > Party & Celebration > Gift Giving > Greeting & Note Cards Arts & Entertainment > Party & Celebration > Party Supplies +Arts & Entertainment > Party & Celebration > Party Supplies > Advice Cards Arts & Entertainment > Party & Celebration > Party Supplies > Balloon Kits Arts & Entertainment > Party & Celebration > Party Supplies > Balloons Arts & Entertainment > Party & Celebration > Party Supplies > Banners -Arts & Entertainment > Party & Celebration > Party Supplies > Beverage Tubs Arts & Entertainment > Party & Celebration > Party Supplies > Birthday Candles +Arts & Entertainment > Party & Celebration > Party Supplies > Chair Sashes Arts & Entertainment > Party & Celebration > Party Supplies > Cocktail Decorations Arts & Entertainment > Party & Celebration > Party Supplies > Confetti +Arts & Entertainment > Party & Celebration > Party Supplies > Decorative Pom-Poms Arts & Entertainment > Party & Celebration > Party Supplies > Drinking Games Arts & Entertainment > Party & Celebration > Party Supplies > Drinking Games > Beer Pong Arts & Entertainment > Party & Celebration > Party Supplies > Drinking Games > Beer Pong > Beer Pong Tables Arts & Entertainment > Party & Celebration > Party Supplies > Drinking Straws & Stirrers Arts & Entertainment > Party & Celebration > Party Supplies > Envelope Seals Arts & Entertainment > Party & Celebration > Party Supplies > Event Programs +Arts & Entertainment > Party & Celebration > Party Supplies > Fireworks & Firecrackers +Arts & Entertainment > Party & Celebration > Party Supplies > Inflatable Party Decorations Arts & Entertainment > Party & Celebration > Party Supplies > Invitations -Arts & Entertainment > Party & Celebration > Party Supplies > Invitations > Birthday Invitations -Arts & Entertainment > Party & Celebration > Party Supplies > Invitations > Wedding Invitations Arts & Entertainment > Party & Celebration > Party Supplies > Noisemakers & Party Blowers Arts & Entertainment > Party & Celebration > Party Supplies > Party Favors Arts & Entertainment > Party & Celebration > Party Supplies > Party Favors > Wedding Favors Arts & Entertainment > Party & Celebration > Party Supplies > Party Games Arts & Entertainment > Party & Celebration > Party Supplies > Party Hats -Arts & Entertainment > Party & Celebration > Party Supplies > Piñatas +Arts & Entertainment > Party & Celebration > Party Supplies > Party Streamers & Curtains +Arts & Entertainment > Party & Celebration > Party Supplies > Party Supply Kits +Arts & Entertainment > Party & Celebration > Party Supplies > Piñatas Arts & Entertainment > Party & Celebration > Party Supplies > Place Card Holders Arts & Entertainment > Party & Celebration > Party Supplies > Place Cards Arts & Entertainment > Party & Celebration > Party Supplies > Response Cards -Arts & Entertainment > Party & Celebration > Party Supplies > Response Cards > Wedding Response Cards Arts & Entertainment > Party & Celebration > Party Supplies > Sparklers +Arts & Entertainment > Party & Celebration > Party Supplies > Special Occasion Card Boxes & Holders Arts & Entertainment > Party & Celebration > Party Supplies > Spray String -Arts & Entertainment > Party & Celebration > Party Supplies > Streamers -Arts & Entertainment > Party & Celebration > Party Supplies > Wedding Card Boxes & Holders Arts & Entertainment > Party & Celebration > Special Effects Arts & Entertainment > Party & Celebration > Special Effects > Disco Balls Arts & Entertainment > Party & Celebration > Special Effects > Fog Machines Arts & Entertainment > Party & Celebration > Special Effects > Special Effects Controllers +Arts & Entertainment > Party & Celebration > Special Effects > Special Effects Light Stands Arts & Entertainment > Party & Celebration > Special Effects > Special Effects Lighting Arts & Entertainment > Party & Celebration > Trophies & Awards Baby & Toddler -Baby & Toddler > Baby & Toddler Gift Sets Baby & Toddler > Baby Bathing Baby & Toddler > Baby Bathing > Baby Bathtubs & Bath Seats Baby & Toddler > Baby Bathing > Shower Visors +Baby & Toddler > Baby Gift Sets Baby & Toddler > Baby Health Baby & Toddler > Baby Health > Baby Health & Grooming Kits Baby & Toddler > Baby Health > Nasal Aspirators @@ -1046,20 +844,20 @@ Baby & Toddler > Baby Safety > Baby Monitors Baby & Toddler > Baby Safety > Baby Safety Harnesses & Leashes Baby & Toddler > Baby Safety > Baby Safety Locks & Guards Baby & Toddler > Baby Safety > Baby Safety Rails -Baby & Toddler > Baby Toys -Baby & Toddler > Baby Toys > Alphabet Toys -Baby & Toddler > Baby Toys > Baby Activity Toys -Baby & Toddler > Baby Toys > Baby Bouncers & Rockers -Baby & Toddler > Baby Toys > Baby Jumpers & Swings -Baby & Toddler > Baby Toys > Baby Mobile Accessories -Baby & Toddler > Baby Toys > Baby Mobiles -Baby & Toddler > Baby Toys > Baby Soothers -Baby & Toddler > Baby Toys > Baby Walkers & Entertainers -Baby & Toddler > Baby Toys > Play Mats & Gyms -Baby & Toddler > Baby Toys > Play Yards -Baby & Toddler > Baby Toys > Push & Pull Toys -Baby & Toddler > Baby Toys > Rattles -Baby & Toddler > Baby Toys > Sorting & Stacking Toys +Baby & Toddler > Baby Toys & Activity Equipment +Baby & Toddler > Baby Toys & Activity Equipment > Alphabet Toys +Baby & Toddler > Baby Toys & Activity Equipment > Baby Activity Toys +Baby & Toddler > Baby Toys & Activity Equipment > Baby Bouncers & Rockers +Baby & Toddler > Baby Toys & Activity Equipment > Baby Jumpers & Swings +Baby & Toddler > Baby Toys & Activity Equipment > Baby Mobile Accessories +Baby & Toddler > Baby Toys & Activity Equipment > Baby Mobiles +Baby & Toddler > Baby Toys & Activity Equipment > Baby Soothers +Baby & Toddler > Baby Toys & Activity Equipment > Baby Walkers & Entertainers +Baby & Toddler > Baby Toys & Activity Equipment > Play Mats & Gyms +Baby & Toddler > Baby Toys & Activity Equipment > Play Yards +Baby & Toddler > Baby Toys & Activity Equipment > Push & Pull Toys +Baby & Toddler > Baby Toys & Activity Equipment > Rattles +Baby & Toddler > Baby Toys & Activity Equipment > Sorting & Stacking Toys Baby & Toddler > Baby Transport Baby & Toddler > Baby Transport > Baby & Toddler Car Seats Baby & Toddler > Baby Transport > Baby Carriers @@ -1068,10 +866,12 @@ Baby & Toddler > Baby Transport Accessories Baby & Toddler > Baby Transport Accessories > Baby & Toddler Car Seat Accessories Baby & Toddler > Baby Transport Accessories > Baby Carrier Accessories Baby & Toddler > Baby Transport Accessories > Baby Stroller Accessories +Baby & Toddler > Baby Transport Accessories > Baby Transport Liners & Sacks Baby & Toddler > Baby Transport Accessories > Shopping Cart & High Chair Covers Baby & Toddler > Diapering Baby & Toddler > Diapering > Baby Wipe Dispensers & Warmers Baby & Toddler > Diapering > Baby Wipes +Baby & Toddler > Diapering > Changing Mat & Tray Covers Baby & Toddler > Diapering > Changing Mats & Trays Baby & Toddler > Diapering > Diaper Kits Baby & Toddler > Diapering > Diaper Liners @@ -1084,27 +884,29 @@ Baby & Toddler > Diapering > Diapers Baby & Toddler > Nursing & Feeding Baby & Toddler > Nursing & Feeding > Baby & Toddler Food Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Cereal +Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Drinks Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Food Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Formula -Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Juice Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Snacks -Baby & Toddler > Nursing & Feeding > Baby Bottle Nipples +Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Toddler Nutrition Drinks & Shakes +Baby & Toddler > Nursing & Feeding > Baby Bottle Nipples & Liners Baby & Toddler > Nursing & Feeding > Baby Bottles Baby & Toddler > Nursing & Feeding > Baby Care Timers Baby & Toddler > Nursing & Feeding > Bibs Baby & Toddler > Nursing & Feeding > Bottle Warmers & Sterilizers Baby & Toddler > Nursing & Feeding > Breast Milk Storage Containers +Baby & Toddler > Nursing & Feeding > Breast Pump Accessories Baby & Toddler > Nursing & Feeding > Breast Pumps Baby & Toddler > Nursing & Feeding > Burp Cloths -Baby & Toddler > Nursing & Feeding > Nipple Shields Baby & Toddler > Nursing & Feeding > Nursing Covers -Baby & Toddler > Nursing & Feeding > Nursing Pads +Baby & Toddler > Nursing & Feeding > Nursing Pads & Shields +Baby & Toddler > Nursing & Feeding > Nursing Pillow Covers Baby & Toddler > Nursing & Feeding > Nursing Pillows Baby & Toddler > Nursing & Feeding > Sippy Cups Baby & Toddler > Potty Training Baby & Toddler > Potty Training > Potty Seats Baby & Toddler > Potty Training > Potty Training Kits -Baby & Toddler > Swaddling Blankets +Baby & Toddler > Swaddling & Receiving Blankets Business & Industrial Business & Industrial > Advertising & Marketing Business & Industrial > Advertising & Marketing > Brochures @@ -1112,23 +914,34 @@ Business & Industrial > Advertising & Marketing > Trade Show Counters Business & Industrial > Advertising & Marketing > Trade Show Displays Business & Industrial > Agriculture Business & Industrial > Agriculture > Animal Husbandry -Business & Industrial > Agriculture > Animal Husbandry > Chicken Coops -Business & Industrial > Agriculture > Animal Husbandry > Livestock Feeders +Business & Industrial > Agriculture > Animal Husbandry > Egg Incubators +Business & Industrial > Agriculture > Animal Husbandry > Livestock Feed +Business & Industrial > Agriculture > Animal Husbandry > Livestock Feeders & Waterers +Business & Industrial > Agriculture > Animal Husbandry > Livestock Halters +Business & Industrial > Automation Control Components +Business & Industrial > Automation Control Components > Programmable Logic Controllers +Business & Industrial > Automation Control Components > Variable Frequency & Adjustable Speed Drives Business & Industrial > Construction Business & Industrial > Construction > Surveying +Business & Industrial > Construction > Traffic Cones & Barrels Business & Industrial > Dentistry Business & Industrial > Dentistry > Dental Cement Business & Industrial > Dentistry > Dental Tools +Business & Industrial > Dentistry > Dental Tools > Dappen Dishes Business & Industrial > Dentistry > Dental Tools > Dental Mirrors Business & Industrial > Dentistry > Dental Tools > Dental Tool Sets +Business & Industrial > Dentistry > Dental Tools > Prophy Cups +Business & Industrial > Dentistry > Dental Tools > Prophy Heads +Business & Industrial > Dentistry > Prophy Paste Business & Industrial > Film & Television Business & Industrial > Finance & Insurance Business & Industrial > Finance & Insurance > Bullion Business & Industrial > Food Service Business & Industrial > Food Service > Bakery Boxes Business & Industrial > Food Service > Bus Tubs +Business & Industrial > Food Service > Check Presenters Business & Industrial > Food Service > Concession Food Containers -Business & Industrial > Food Service > Disposable Cutlery Dispensers +Business & Industrial > Food Service > Disposable Lids Business & Industrial > Food Service > Disposable Serveware Business & Industrial > Food Service > Disposable Serveware > Disposable Serving Trays Business & Industrial > Food Service > Disposable Tableware @@ -1142,11 +955,13 @@ Business & Industrial > Food Service > Food Washers & Dryers Business & Industrial > Food Service > Hot Dog Rollers Business & Industrial > Food Service > Ice Bins Business & Industrial > Food Service > Plate & Dish Warmers +Business & Industrial > Food Service > Sneeze Guards Business & Industrial > Food Service > Take-Out Containers Business & Industrial > Food Service > Tilt Skillets Business & Industrial > Food Service > Vending Machines Business & Industrial > Forestry & Logging Business & Industrial > Hairdressing & Cosmetology +Business & Industrial > Hairdressing & Cosmetology > Hairdressing Capes & Neck Covers Business & Industrial > Hairdressing & Cosmetology > Pedicure Chairs Business & Industrial > Hairdressing & Cosmetology > Salon Chairs Business & Industrial > Heavy Machinery @@ -1156,52 +971,58 @@ Business & Industrial > Industrial Storage Business & Industrial > Industrial Storage > Industrial Cabinets Business & Industrial > Industrial Storage > Industrial Shelving Business & Industrial > Industrial Storage > Shipping Containers +Business & Industrial > Industrial Storage > Wire Partitions, Enclosures & Doors Business & Industrial > Industrial Storage Accessories +Business & Industrial > Janitorial Carts & Caddies Business & Industrial > Law Enforcement -Business & Industrial > Law Enforcement > Batons Business & Industrial > Law Enforcement > Cuffs -Business & Industrial > Law Enforcement > Cuffs > Ankle Cuffs -Business & Industrial > Law Enforcement > Cuffs > Handcuffs -Business & Industrial > Law Enforcement > Cuffs > Leg Cuffs Business & Industrial > Law Enforcement > Metal Detectors Business & Industrial > Manufacturing Business & Industrial > Material Handling Business & Industrial > Material Handling > Conveyors -Business & Industrial > Material Handling > Fork Lifts +Business & Industrial > Material Handling > Lifts & Hoists +Business & Industrial > Material Handling > Lifts & Hoists > Hoists, Cranes & Trolleys +Business & Industrial > Material Handling > Lifts & Hoists > Jacks & Lift Trucks +Business & Industrial > Material Handling > Lifts & Hoists > Personnel Lifts +Business & Industrial > Material Handling > Lifts & Hoists > Pulleys, Blocks & Sheaves +Business & Industrial > Material Handling > Lifts & Hoists > Winches +Business & Industrial > Material Handling > Pallets & Loading Platforms Business & Industrial > Medical Business & Industrial > Medical > Hospital Curtains Business & Industrial > Medical > Hospital Gowns Business & Industrial > Medical > Medical Bedding Business & Industrial > Medical > Medical Equipment Business & Industrial > Medical > Medical Equipment > Automated External Defibrillators -Business & Industrial > Medical > Medical Equipment > Medical Forceps +Business & Industrial > Medical > Medical Equipment > Gait Belts +Business & Industrial > Medical > Medical Equipment > Medical Reflex Hammers & Tuning Forks +Business & Industrial > Medical > Medical Equipment > Medical Stretchers & Gurneys Business & Industrial > Medical > Medical Equipment > Otoscopes & Ophthalmoscopes Business & Industrial > Medical > Medical Equipment > Patient Lifts -Business & Industrial > Medical > Medical Equipment > Reflex Hammers -Business & Industrial > Medical > Medical Equipment > Scalpels Business & Industrial > Medical > Medical Equipment > Stethoscopes Business & Industrial > Medical > Medical Equipment > Vital Signs Monitor Accessories Business & Industrial > Medical > Medical Equipment > Vital Signs Monitors Business & Industrial > Medical > Medical Furniture Business & Industrial > Medical > Medical Furniture > Chiropractic Tables -Business & Industrial > Medical > Medical Furniture > Examination Chairs -Business & Industrial > Medical > Medical Furniture > Examination Chairs > Dental Chairs -Business & Industrial > Medical > Medical Furniture > Examination Chairs > Gynecological Chairs -Business & Industrial > Medical > Medical Furniture > Examination Chairs > Optometry Chairs +Business & Industrial > Medical > Medical Furniture > Examination Chairs & Tables Business & Industrial > Medical > Medical Furniture > Homecare & Hospital Beds Business & Industrial > Medical > Medical Furniture > Medical Cabinets -Business & Industrial > Medical > Medical Furniture > Medical Cabinets > Narcotics Boxes Business & Industrial > Medical > Medical Furniture > Medical Carts Business & Industrial > Medical > Medical Furniture > Medical Carts > Crash Carts Business & Industrial > Medical > Medical Furniture > Medical Carts > IV Poles & Carts Business & Industrial > Medical > Medical Furniture > Surgical Tables +Business & Industrial > Medical > Medical Instruments +Business & Industrial > Medical > Medical Instruments > Medical Forceps +Business & Industrial > Medical > Medical Instruments > Scalpel Blades +Business & Industrial > Medical > Medical Instruments > Scalpels +Business & Industrial > Medical > Medical Instruments > Surgical Needles & Sutures Business & Industrial > Medical > Medical Supplies Business & Industrial > Medical > Medical Supplies > Disposable Gloves Business & Industrial > Medical > Medical Supplies > Finger Cots -Business & Industrial > Medical > Medical Supplies > Medical Masks +Business & Industrial > Medical > Medical Supplies > Medical Needles & Syringes +Business & Industrial > Medical > Medical Supplies > Ostomy Supplies Business & Industrial > Medical > Medical Supplies > Tongue Depressors Business & Industrial > Medical > Medical Teaching Equipment -Business & Industrial > Medical > Medical Teaching Equipment > CPR Mannequins +Business & Industrial > Medical > Medical Teaching Equipment > Medical & Emergency Response Training Mannequins Business & Industrial > Medical > Scrub Caps Business & Industrial > Medical > Scrubs Business & Industrial > Medical > Surgical Gowns @@ -1216,21 +1037,23 @@ Business & Industrial > Piercing & Tattooing > Tattooing Supplies > Tattooing Ma Business & Industrial > Piercing & Tattooing > Tattooing Supplies > Tattooing Needles Business & Industrial > Retail Business & Industrial > Retail > Clothing Display Racks +Business & Industrial > Retail > Display Mannequins Business & Industrial > Retail > Mannequin Parts -Business & Industrial > Retail > Mannequins Business & Industrial > Retail > Money Handling Business & Industrial > Retail > Money Handling > Banknote Verifiers -Business & Industrial > Retail > Money Handling > Cash Registers & POS Equipment -Business & Industrial > Retail > Money Handling > Cash Registers & POS Equipment > Cash Drawers -Business & Industrial > Retail > Money Handling > Cash Registers & POS Equipment > Credit Card Readers -Business & Industrial > Retail > Money Handling > Cash Registers & POS Equipment > Signature Capture Pads +Business & Industrial > Retail > Money Handling > Cash Register & POS Terminal Accessories +Business & Industrial > Retail > Money Handling > Cash Register & POS Terminal Accessories > Cash Drawers & Trays +Business & Industrial > Retail > Money Handling > Cash Register & POS Terminal Accessories > Credit Card Terminals +Business & Industrial > Retail > Money Handling > Cash Register & POS Terminal Accessories > Signature Capture Pads +Business & Industrial > Retail > Money Handling > Cash Registers & POS Terminals Business & Industrial > Retail > Money Handling > Coin & Bill Counters Business & Industrial > Retail > Money Handling > Money Changers Business & Industrial > Retail > Money Handling > Money Deposit Bags Business & Industrial > Retail > Money Handling > Paper Coin Wrappers & Bill Straps -Business & Industrial > Retail > Plastic Bags +Business & Industrial > Retail > Paper & Plastic Shopping Bags Business & Industrial > Retail > Pricing Guns Business & Industrial > Retail > Retail Display Cases +Business & Industrial > Retail > Retail Display Props & Models Business & Industrial > Science & Laboratory Business & Industrial > Science & Laboratory > Biochemicals Business & Industrial > Science & Laboratory > Dissection Kits @@ -1239,7 +1062,10 @@ Business & Industrial > Science & Laboratory > Laboratory Equipment Business & Industrial > Science & Laboratory > Laboratory Equipment > Autoclaves Business & Industrial > Science & Laboratory > Laboratory Equipment > Centrifuges Business & Industrial > Science & Laboratory > Laboratory Equipment > Dry Ice Makers +Business & Industrial > Science & Laboratory > Laboratory Equipment > Freeze-Drying Machines Business & Industrial > Science & Laboratory > Laboratory Equipment > Laboratory Blenders +Business & Industrial > Science & Laboratory > Laboratory Equipment > Laboratory Freezers +Business & Industrial > Science & Laboratory > Laboratory Equipment > Laboratory Funnels Business & Industrial > Science & Laboratory > Laboratory Equipment > Laboratory Hot Plates Business & Industrial > Science & Laboratory > Laboratory Equipment > Laboratory Ovens Business & Industrial > Science & Laboratory > Laboratory Equipment > Microscope Accessories @@ -1252,7 +1078,7 @@ Business & Industrial > Science & Laboratory > Laboratory Equipment > Microscope Business & Industrial > Science & Laboratory > Laboratory Equipment > Microtomes Business & Industrial > Science & Laboratory > Laboratory Equipment > Spectrometer Accessories Business & Industrial > Science & Laboratory > Laboratory Equipment > Spectrometers -Business & Industrial > Science & Laboratory > Laboratory Equipment > Spectrometers > Spectrophotometers +Business & Industrial > Science & Laboratory > Laboratory Specimens Business & Industrial > Science & Laboratory > Laboratory Supplies Business & Industrial > Science & Laboratory > Laboratory Supplies > Beakers Business & Industrial > Science & Laboratory > Laboratory Supplies > Graduated Cylinders @@ -1264,9 +1090,10 @@ Business & Industrial > Science & Laboratory > Laboratory Supplies > Test Tubes Business & Industrial > Science & Laboratory > Laboratory Supplies > Wash Bottles Business & Industrial > Signage Business & Industrial > Signage > Business Hour Signs -Business & Industrial > Signage > Electronic Signs -Business & Industrial > Signage > Electronic Signs > LED Signs -Business & Industrial > Signage > Electronic Signs > Neon Signs +Business & Industrial > Signage > Digital Signs +Business & Industrial > Signage > Electric Signs +Business & Industrial > Signage > Electric Signs > LED Signs +Business & Industrial > Signage > Electric Signs > Neon Signs Business & Industrial > Signage > Emergency & Exit Signs Business & Industrial > Signage > Facility Identification Signs Business & Industrial > Signage > Open & Closed Signs @@ -1279,79 +1106,87 @@ Business & Industrial > Signage > Security Signs Business & Industrial > Signage > Sidewalk & Yard Signs Business & Industrial > Work Safety Protective Gear Business & Industrial > Work Safety Protective Gear > Bullet Proof Vests -Business & Industrial > Work Safety Protective Gear > Dust Masks -Business & Industrial > Work Safety Protective Gear > Fire Repellent Clothing -Business & Industrial > Work Safety Protective Gear > Fireman's Masks -Business & Industrial > Work Safety Protective Gear > Gas Masks & Respirators +Business & Industrial > Work Safety Protective Gear > Gas Mask & Respirator Accessories Business & Industrial > Work Safety Protective Gear > Hardhats Business & Industrial > Work Safety Protective Gear > Hazardous Material Suits -Business & Industrial > Work Safety Protective Gear > High-Visibility Clothing Business & Industrial > Work Safety Protective Gear > Protective Aprons Business & Industrial > Work Safety Protective Gear > Protective Eyewear +Business & Industrial > Work Safety Protective Gear > Protective Masks +Business & Industrial > Work Safety Protective Gear > Protective Masks > Dust Masks +Business & Industrial > Work Safety Protective Gear > Protective Masks > Fireman's Masks +Business & Industrial > Work Safety Protective Gear > Protective Masks > Gas Masks & Respirators +Business & Industrial > Work Safety Protective Gear > Protective Masks > Medical Masks Business & Industrial > Work Safety Protective Gear > Safety Gloves -Business & Industrial > Work Safety Protective Gear > Safety Tethers +Business & Industrial > Work Safety Protective Gear > Safety Knee Pads +Business & Industrial > Work Safety Protective Gear > Welding Helmets +Business & Industrial > Work Safety Protective Gear > Work Safety Harnesses +Business & Industrial > Work Safety Protective Gear > Work Safety Tethers Cameras & Optics Cameras & Optics > Camera & Optic Accessories -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lens Accessories -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lens Accessories > Lens & Filter Adapters -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lens Accessories > Lens Bags -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lens Accessories > Lens Caps -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lens Accessories > Lens Converters -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lens Accessories > Lens Filters -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lens Accessories > Lens Filters > Close-Up Filters -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lens Accessories > Lens Hoods -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lenses -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lenses > Camera Lenses -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lenses > Surveillance Camera Lenses -Cameras & Optics > Camera & Optic Accessories > Camera & Optic Lenses > Video Camera Lenses -Cameras & Optics > Camera & Optic Accessories > Camera Accessories -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Camera Bags -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Camera Bags > Still Camera Bags -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Camera Bags > Video Camera Bags -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Camera Film -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Camera Flash Accessories -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Camera Flashes -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Camera Handles -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Camera Mounts -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Camera Remote Controls -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Camera Straps -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Flash Brackets -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Surveillance Camera Accessories -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Underwater Camera Housings -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Underwater Camera Housings > Underwater Still Camera Housings -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Underwater Camera Housings > Underwater Video Camera Housings -Cameras & Optics > Camera & Optic Accessories > Camera Accessories > Video Camera Lights +Cameras & Optics > Camera & Optic Accessories > Camera & Optic Replacement Cables +Cameras & Optics > Camera & Optic Accessories > Camera & Video Camera Lenses +Cameras & Optics > Camera & Optic Accessories > Camera & Video Camera Lenses > Camera Lenses +Cameras & Optics > Camera & Optic Accessories > Camera & Video Camera Lenses > Surveillance Camera Lenses +Cameras & Optics > Camera & Optic Accessories > Camera & Video Camera Lenses > Video Camera Lenses +Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories +Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens & Filter Adapter Rings +Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens Bags +Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens Caps +Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens Converters +Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens Filters +Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens Hoods +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Accessory Sets +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Bags & Cases +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Body Replacement Panels & Doors +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Digital Backs +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Film +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Flash Accessories +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Flashes +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Focus Devices +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Gears +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Grips +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Image Sensors +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Lens Zoom Units +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Remote Controls +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Replacement Buttons & Knobs +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Replacement Screens & Displays +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Silencers & Sound Blimps +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Stabilizers & Supports +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Straps +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Sun Hoods & Viewfinder Attachments +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Flash Brackets +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > On-Camera Monitors +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Surveillance Camera Accessories +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Underwater Camera Housing Accessories +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Underwater Camera Housings +Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Video Camera Lights Cameras & Optics > Camera & Optic Accessories > Optic Accessories Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Binocular & Monocular Accessories -Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Night Vision Optic Accessories Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Optics Bags & Cases Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Rangefinder Accessories Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Spotting Scope Accessories -Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Spotting Scope Accessories > Scope Eyepieces Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Telescope Accessories Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Thermal Optic Accessories -Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Weapon Scope Accessories +Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Weapon Scope & Sight Accessories Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories > Tripod & Monopod Cases Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories > Tripod & Monopod Heads Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories > Tripod Collars & Mounts +Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories > Tripod Handles +Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories > Tripod Spreaders Cameras & Optics > Camera & Optic Accessories > Tripods & Monopods Cameras & Optics > Cameras +Cameras & Optics > Cameras > Borescopes Cameras & Optics > Cameras > Digital Cameras -Cameras & Optics > Cameras > Digital Cameras > Digital Point & Shoot Cameras -Cameras & Optics > Cameras > Digital Cameras > Digital SLRs -Cameras & Optics > Cameras > Digital Cameras > Mirrorless System Digital Cameras Cameras & Optics > Cameras > Disposable Cameras Cameras & Optics > Cameras > Film Cameras -Cameras & Optics > Cameras > Film Cameras > Instant Cameras Cameras & Optics > Cameras > Surveillance Cameras -Cameras & Optics > Cameras > Surveillance Cameras > Hidden Cameras Cameras & Optics > Cameras > Trail Cameras Cameras & Optics > Cameras > Video Cameras Cameras & Optics > Cameras > Webcams Cameras & Optics > Optics Cameras & Optics > Optics > Binoculars -Cameras & Optics > Optics > Binoculars > Opera Glasses Cameras & Optics > Optics > Monoculars Cameras & Optics > Optics > Rangefinders Cameras & Optics > Optics > Scopes @@ -1373,29 +1208,26 @@ Cameras & Optics > Photography > Darkroom > Enlarging Equipment > Focusing Aids Cameras & Optics > Photography > Darkroom > Enlarging Equipment > Photographic Analyzers Cameras & Optics > Photography > Darkroom > Enlarging Equipment > Photographic Enlargers Cameras & Optics > Photography > Darkroom > Photographic Chemicals -Cameras & Optics > Photography > Darkroom > Photographic Chemicals > Photographic Color Kits -Cameras & Optics > Photography > Darkroom > Photographic Chemicals > Photographic Developer -Cameras & Optics > Photography > Darkroom > Photographic Chemicals > Photographic Fixers -Cameras & Optics > Photography > Darkroom > Photographic Chemicals > Photographic Toners -Cameras & Optics > Photography > Darkroom > Photographic Chemicals > Stop Baths Cameras & Optics > Photography > Darkroom > Photographic Paper Cameras & Optics > Photography > Darkroom > Safelights Cameras & Optics > Photography > Lighting & Studio -Cameras & Optics > Photography > Lighting & Studio > Backgrounds -Cameras & Optics > Photography > Lighting & Studio > Flash Diffusers -Cameras & Optics > Photography > Lighting & Studio > Flash Diffusers > Camera Flash Diffusers -Cameras & Optics > Photography > Lighting & Studio > Flash Reflectors -Cameras & Optics > Photography > Lighting & Studio > Light Controls Cameras & Optics > Photography > Lighting & Studio > Light Meter Accessories Cameras & Optics > Photography > Lighting & Studio > Light Meters -Cameras & Optics > Photography > Lighting & Studio > Lighting Filters & Gels -Cameras & Optics > Photography > Lighting & Studio > Softboxes +Cameras & Optics > Photography > Lighting & Studio > Studio Backgrounds +Cameras & Optics > Photography > Lighting & Studio > Studio Light & Flash Accessories +Cameras & Optics > Photography > Lighting & Studio > Studio Lighting Controls +Cameras & Optics > Photography > Lighting & Studio > Studio Lighting Controls > Flash Diffusers +Cameras & Optics > Photography > Lighting & Studio > Studio Lighting Controls > Flash Reflectors +Cameras & Optics > Photography > Lighting & Studio > Studio Lighting Controls > Lighting Filters & Gobos +Cameras & Optics > Photography > Lighting & Studio > Studio Lighting Controls > Softboxes Cameras & Optics > Photography > Lighting & Studio > Studio Lights & Flashes -Cameras & Optics > Photography > Lighting & Studio > Studio Mountings +Cameras & Optics > Photography > Lighting & Studio > Studio Stand & Mount Accessories +Cameras & Optics > Photography > Lighting & Studio > Studio Stands & Mounts +Cameras & Optics > Photography > Photo Mounting Supplies Cameras & Optics > Photography > Photo Negative & Slide Storage Electronics -Electronics > 3D Printers Electronics > Arcade Equipment +Electronics > Arcade Equipment > Basketball Arcade Games Electronics > Arcade Equipment > Pinball Machine Accessories Electronics > Arcade Equipment > Pinball Machines Electronics > Arcade Equipment > Skee-Ball Machines @@ -1403,24 +1235,24 @@ Electronics > Arcade Equipment > Video Game Arcade Cabinet Accessories Electronics > Arcade Equipment > Video Game Arcade Cabinets Electronics > Audio Electronics > Audio > Audio Accessories -Electronics > Audio > Audio Accessories > Headphone Accessories -Electronics > Audio > Audio Accessories > Headphone Accessories > Headphone Cushions -Electronics > Audio > Audio Accessories > Headphone Accessories > Headphone Ear Tips +Electronics > Audio > Audio Accessories > Audio & Video Receiver Accessories +Electronics > Audio > Audio Accessories > Headphone & Headset Accessories +Electronics > Audio > Audio Accessories > Headphone & Headset Accessories > Headphone Cushions & Tips Electronics > Audio > Audio Accessories > Karaoke System Accessories Electronics > Audio > Audio Accessories > Karaoke System Accessories > Karaoke Chips Electronics > Audio > Audio Accessories > MP3 Player Accessories Electronics > Audio > Audio Accessories > MP3 Player Accessories > MP3 Player & Mobile Phone Accessory Sets Electronics > Audio > Audio Accessories > MP3 Player Accessories > MP3 Player Cases Electronics > Audio > Audio Accessories > Microphone Accessories -Electronics > Audio > Audio Accessories > Microphone Accessories > Microphone Stands -Electronics > Audio > Audio Accessories > Microphone Accessories > Microphone Windscreens +Electronics > Audio > Audio Accessories > Microphone Stands Electronics > Audio > Audio Accessories > Satellite Radio Accessories Electronics > Audio > Audio Accessories > Speaker Accessories -Electronics > Audio > Audio Accessories > Speaker Accessories > Speaker Grill Fabric +Electronics > Audio > Audio Accessories > Speaker Accessories > Speaker Bags, Covers & Cases +Electronics > Audio > Audio Accessories > Speaker Accessories > Speaker Components & Kits Electronics > Audio > Audio Accessories > Speaker Accessories > Speaker Stand Bags -Electronics > Audio > Audio Accessories > Speaker Accessories > Speaker Stands +Electronics > Audio > Audio Accessories > Speaker Accessories > Speaker Stands & Mounts +Electronics > Audio > Audio Accessories > Speaker Accessories > Tactile Transducers Electronics > Audio > Audio Accessories > Turntable Accessories -Electronics > Audio > Audio Accessories > Turntable Accessories > Turntable Cartridges & Needles Electronics > Audio > Audio Components Electronics > Audio > Audio Components > Audio & Video Receivers Electronics > Audio > Audio Components > Audio Amplifiers @@ -1432,21 +1264,18 @@ Electronics > Audio > Audio Components > Audio Transmitters > Bluetooth Transmit Electronics > Audio > Audio Components > Audio Transmitters > FM Transmitters Electronics > Audio > Audio Components > Channel Strips Electronics > Audio > Audio Components > Direct Boxes -Electronics > Audio > Audio Components > Headphones +Electronics > Audio > Audio Components > Headphones & Headsets Electronics > Audio > Audio Components > Microphones -Electronics > Audio > Audio Components > Microphones > Video Camera Microphones Electronics > Audio > Audio Components > Signal Processors Electronics > Audio > Audio Components > Signal Processors > Crossovers Electronics > Audio > Audio Components > Signal Processors > Effects Processors Electronics > Audio > Audio Components > Signal Processors > Equalizers +Electronics > Audio > Audio Components > Signal Processors > Loudspeaker Management Systems Electronics > Audio > Audio Components > Signal Processors > Microphone Preamps Electronics > Audio > Audio Components > Signal Processors > Noise Gates & Compressors Electronics > Audio > Audio Components > Signal Processors > Phono Preamps -Electronics > Audio > Audio Components > Signal Processors > Public Address Management Systems Electronics > Audio > Audio Components > Speakers -Electronics > Audio > Audio Components > Speakers > Computer Speakers -Electronics > Audio > Audio Components > Speakers > Studio Monitors -Electronics > Audio > Audio Components > Speakers > Subwoofers +Electronics > Audio > Audio Components > Studio Recording Bundles Electronics > Audio > Audio Players & Recorders Electronics > Audio > Audio Players & Recorders > Boomboxes Electronics > Audio > Audio Players & Recorders > CD Players & Recorders @@ -1458,51 +1287,54 @@ Electronics > Audio > Audio Players & Recorders > MP3 Players Electronics > Audio > Audio Players & Recorders > MiniDisc Players & Recorders Electronics > Audio > Audio Players & Recorders > Multitrack Recorders Electronics > Audio > Audio Players & Recorders > Radios -Electronics > Audio > Audio Players & Recorders > Radios > Internet Radios -Electronics > Audio > Audio Players & Recorders > Radios > Satellite Radios +Electronics > Audio > Audio Players & Recorders > Reel-to-Reel Tape Players & Recorders Electronics > Audio > Audio Players & Recorders > Stereo Systems Electronics > Audio > Audio Players & Recorders > Turntables & Record Players -Electronics > Audio > Audio Players & Recorders > Turntables & Record Players > DJ Turntables Electronics > Audio > Audio Players & Recorders > Voice Recorders +Electronics > Audio > Bullhorns Electronics > Audio > DJ & Specialty Audio Electronics > Audio > DJ & Specialty Audio > DJ CD Players -Electronics > Audio > DJ & Specialty Audio > DJ Equipment Accessories Electronics > Audio > DJ & Specialty Audio > DJ Systems Electronics > Audio > Public Address Systems Electronics > Audio > Stage Equipment Electronics > Audio > Stage Equipment > Wireless Transmitters -Electronics > Circuit Components -Electronics > Circuit Components > Circuit Decoders & Encoders -Electronics > Circuit Components > Circuit Prototyping -Electronics > Circuit Components > Circuit Prototyping > Breadboards -Electronics > Circuit Components > Electronic Filters -Electronics > Circuit Components > Optoelectronics -Electronics > Circuit Components > Optoelectronics > Laser Diodes -Electronics > Circuit Components > Passive Circuit Components -Electronics > Circuit Components > Passive Circuit Components > Capacitors -Electronics > Circuit Components > Passive Circuit Components > Electronic Oscillators -Electronics > Circuit Components > Passive Circuit Components > Inductors -Electronics > Circuit Components > Passive Circuit Components > Resistors -Electronics > Circuit Components > Passive Circuit Components > Resistors > Potentiometers -Electronics > Circuit Components > Printed Circuit Boards -Electronics > Circuit Components > Printed Circuit Boards > Development Boards -Electronics > Circuit Components > Semiconductors -Electronics > Circuit Components > Semiconductors > Diodes -Electronics > Circuit Components > Semiconductors > Integrated Circuits & Chips -Electronics > Circuit Components > Semiconductors > Integrated Circuits & Chips > Op Amps -Electronics > Circuit Components > Semiconductors > Integrated Circuits & Chips > Voltage Regulator ICs -Electronics > Circuit Components > Semiconductors > Microcontrollers -Electronics > Circuit Components > Semiconductors > Transistors +Electronics > Circuit Boards & Components +Electronics > Circuit Boards & Components > Circuit Board Accessories +Electronics > Circuit Boards & Components > Circuit Decoders & Encoders +Electronics > Circuit Boards & Components > Circuit Prototyping +Electronics > Circuit Boards & Components > Circuit Prototyping > Breadboards +Electronics > Circuit Boards & Components > Electronic Filters +Electronics > Circuit Boards & Components > Passive Circuit Components +Electronics > Circuit Boards & Components > Passive Circuit Components > Capacitors +Electronics > Circuit Boards & Components > Passive Circuit Components > Electronic Oscillators +Electronics > Circuit Boards & Components > Passive Circuit Components > Inductors +Electronics > Circuit Boards & Components > Passive Circuit Components > Resistors +Electronics > Circuit Boards & Components > Printed Circuit Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Camera Circuit Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Computer Circuit Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Computer Circuit Boards > Computer Inverter Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Computer Circuit Boards > Hard Drive Circuit Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Computer Circuit Boards > Motherboards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Development Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Exercise Machine Circuit Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Household Appliance Circuit Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Pool & Spa Circuit Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Printer, Copier, & Fax Machine Circuit Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Scanner Circuit Boards +Electronics > Circuit Boards & Components > Printed Circuit Boards > Television Circuit Boards +Electronics > Circuit Boards & Components > Semiconductors +Electronics > Circuit Boards & Components > Semiconductors > Diodes +Electronics > Circuit Boards & Components > Semiconductors > Integrated Circuits & Chips +Electronics > Circuit Boards & Components > Semiconductors > Microcontrollers +Electronics > Circuit Boards & Components > Semiconductors > Transistors Electronics > Communications Electronics > Communications > Answering Machines -Electronics > Communications > Answering Machines > On Hold Systems Electronics > Communications > Caller IDs Electronics > Communications > Communication Radio Accessories Electronics > Communications > Communication Radios Electronics > Communications > Communication Radios > CB Radios Electronics > Communications > Communication Radios > Radio Scanners Electronics > Communications > Communication Radios > Two-Way Radios -Electronics > Communications > Headsets Electronics > Communications > Intercom Accessories Electronics > Communications > Intercoms Electronics > Communications > Pagers @@ -1511,204 +1343,154 @@ Electronics > Communications > Telephony > Conference Phones Electronics > Communications > Telephony > Corded Phones Electronics > Communications > Telephony > Cordless Phones Electronics > Communications > Telephony > Mobile Phone Accessories +Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Camera Accessories Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Cases Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Charms & Straps +Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Pre-Paid Cards & SIM Cards Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Replacement Parts -Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Replacement Parts > Mobile Phone Digitizers -Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone SIM Cards Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Stands +Electronics > Communications > Telephony > Mobile Phone Accessories > SIM Card Ejection Tools Electronics > Communications > Telephony > Mobile Phones -Electronics > Communications > Telephony > Mobile Phones > Feature Phones -Electronics > Communications > Telephony > Mobile Phones > Smartphones -Electronics > Communications > Telephony > Mobile Phones > Watch Phones Electronics > Communications > Telephony > Satellite Phones Electronics > Communications > Telephony > Telephone Accessories Electronics > Communications > Telephony > Telephone Accessories > Phone Cards Electronics > Communications > Video Conferencing Electronics > Components Electronics > Components > Accelerometers -Electronics > Components > Automation Control Components -Electronics > Components > Automation Control Components > Programmable Logic Controllers -Electronics > Components > Automation Control Components > Variable Frequency & Adjustable Speed Drives -Electronics > Components > Connectors -Electronics > Components > Connectors > Keystone Jacks -Electronics > Components > Connectors > RCA Jacks Electronics > Components > Converters +Electronics > Components > Converters > Audio Converters Electronics > Components > Converters > Scan Converters +Electronics > Components > Electronics Component Connectors Electronics > Components > Modulators -Electronics > Components > Modulators > RF Modulators Electronics > Components > Splitters -Electronics > Components > Splitters > RF Splitters -Electronics > Components > Splitters > UHF Splitters -Electronics > Components > Transformers -Electronics > Components > Transformers > Baluns Electronics > Computers Electronics > Computers > Barebone Computers -Electronics > Computers > Computer Accessories -Electronics > Computers > Computer Accessories > Computer Risers & Stands -Electronics > Computers > Computer Accessories > Handheld Device Accessories -Electronics > Computers > Computer Accessories > Handheld Device Accessories > E-Book Reader Accessories -Electronics > Computers > Computer Accessories > Handheld Device Accessories > E-Book Reader Accessories > E-Book Reader Cases -Electronics > Computers > Computer Accessories > Handheld Device Accessories > PDA Accessories -Electronics > Computers > Computer Accessories > Handheld Device Accessories > PDA Accessories > PDA Cases -Electronics > Computers > Computer Accessories > Keyboard & Mouse Wrist Rests -Electronics > Computers > Computer Accessories > Keyboard Trays & Platforms -Electronics > Computers > Computer Accessories > Laptop Accessories -Electronics > Computers > Computer Accessories > Laptop Accessories > Laptop Docking Stations -Electronics > Computers > Computer Accessories > Mouse Pads -Electronics > Computers > Computer Accessories > Stylus Pen Nibs & Refills -Electronics > Computers > Computer Accessories > Stylus Pens -Electronics > Computers > Computer Accessories > Tablet Computer Accessories -Electronics > Computers > Computer Accessories > Tablet Computer Accessories > Tablet Computer Replacement Parts -Electronics > Computers > Computer Accessories > Tablet Computer Accessories > Tablet Computer Replacement Parts > Tablet Computer Digitizers -Electronics > Computers > Computer Accessories > Tablet Computer Accessories > Tablet Computer Stands -Electronics > Computers > Computer Components -Electronics > Computers > Computer Components > Blade Server Enclosures -Electronics > Computers > Computer Components > Computer Cases -Electronics > Computers > Computer Components > Computer Power Supplies -Electronics > Computers > Computer Components > Computer Processors -Electronics > Computers > Computer Components > Computer Racks & Mounts -Electronics > Computers > Computer Components > Computer Starter Kits -Electronics > Computers > Computer Components > Computer System Cooling -Electronics > Computers > Computer Components > I/O Cards & Adapters -Electronics > Computers > Computer Components > I/O Cards & Adapters > Audio Cards & Adapters -Electronics > Computers > Computer Components > I/O Cards & Adapters > FireWire Cards -Electronics > Computers > Computer Components > I/O Cards & Adapters > Parallel Cards & Adapters -Electronics > Computers > Computer Components > I/O Cards & Adapters > Serial Cards & Adapters -Electronics > Computers > Computer Components > I/O Cards & Adapters > TV Tuner Cards & Adapters -Electronics > Computers > Computer Components > I/O Cards & Adapters > USB Cards -Electronics > Computers > Computer Components > I/O Cards & Adapters > Video Cards & Adapters -Electronics > Computers > Computer Components > Input Device Accessories -Electronics > Computers > Computer Components > Input Device Accessories > Barcode Scanner Stands -Electronics > Computers > Computer Components > Input Device Accessories > Game Controller Accessories -Electronics > Computers > Computer Components > Input Device Accessories > Game Controller Accessories > Game Controller Thumbsticks & Buttons -Electronics > Computers > Computer Components > Input Device Accessories > Graphics Tablet Accessories -Electronics > Computers > Computer Components > Input Devices -Electronics > Computers > Computer Components > Input Devices > Barcode Scanners -Electronics > Computers > Computer Components > Input Devices > Computer Keyboards -Electronics > Computers > Computer Components > Input Devices > Digital Note Taking Pens -Electronics > Computers > Computer Components > Input Devices > Fingerprint Readers -Electronics > Computers > Computer Components > Input Devices > Game Controllers -Electronics > Computers > Computer Components > Input Devices > Graphics Tablets -Electronics > Computers > Computer Components > Input Devices > KVM Switches -Electronics > Computers > Computer Components > Input Devices > Keyboard & Mouse Sets -Electronics > Computers > Computer Components > Input Devices > Memory Card Readers -Electronics > Computers > Computer Components > Input Devices > Mice & Trackballs -Electronics > Computers > Computer Components > Input Devices > Numeric Keypads -Electronics > Computers > Computer Components > Input Devices > Smart Card Readers -Electronics > Computers > Computer Components > Input Devices > Touchpads -Electronics > Computers > Computer Components > Laptop Parts -Electronics > Computers > Computer Components > Laptop Parts > Laptop Hinges -Electronics > Computers > Computer Components > Laptop Parts > Laptop Replacement Cables -Electronics > Computers > Computer Components > Laptop Parts > Laptop Replacement Keyboards -Electronics > Computers > Computer Components > Laptop Parts > Laptop Replacement Screens -Electronics > Computers > Computer Components > Laptop Parts > Laptop Shells -Electronics > Computers > Computer Components > Motherboards -Electronics > Computers > Computer Components > Output Devices -Electronics > Computers > Computer Components > Storage Devices -Electronics > Computers > Computer Components > Storage Devices > Disk Arrays -Electronics > Computers > Computer Components > Storage Devices > Disk Duplicators -Electronics > Computers > Computer Components > Storage Devices > Disk Duplicators > CD/DVD Duplicators -Electronics > Computers > Computer Components > Storage Devices > Disk Duplicators > Hard Drive Duplicators -Electronics > Computers > Computer Components > Storage Devices > Disk Duplicators > USB Drive Duplicators -Electronics > Computers > Computer Components > Storage Devices > Floppy Drives -Electronics > Computers > Computer Components > Storage Devices > Hard Drives -Electronics > Computers > Computer Components > Storage Devices > Hard Drives > Solid State Drives -Electronics > Computers > Computer Components > Storage Devices > Hard Drives > XBox 360 Hard Drives -Electronics > Computers > Computer Components > Storage Devices > Network Storage Systems -Electronics > Computers > Computer Components > Storage Devices > Network Storage Systems > Network Storage Servers -Electronics > Computers > Computer Components > Storage Devices > Network Storage Systems > Storage Area Networks -Electronics > Computers > Computer Components > Storage Devices > Optical Drives -Electronics > Computers > Computer Components > Storage Devices > Optical Drives > CD Drives -Electronics > Computers > Computer Components > Storage Devices > Optical Drives > DVD Drives -Electronics > Computers > Computer Components > Storage Devices > Optical Drives > MO Drives -Electronics > Computers > Computer Components > Storage Devices > Storage Drive Accessories -Electronics > Computers > Computer Components > Storage Devices > Storage Drive Accessories > Hard Drive Caddies -Electronics > Computers > Computer Components > Storage Devices > Storage Drive Accessories > Hard Drive Carrying Cases -Electronics > Computers > Computer Components > Storage Devices > Storage Drive Accessories > Hard Drive Docks -Electronics > Computers > Computer Components > Storage Devices > Storage Drive Accessories > Hard Drive Enclosures -Electronics > Computers > Computer Components > Storage Devices > Storage Drive Accessories > Hard Drive Mounts -Electronics > Computers > Computer Components > Storage Devices > Tape Drives -Electronics > Computers > Computer Components > Storage Devices > USB Flash Drives -Electronics > Computers > Computer Components > USB & FireWire Hubs Electronics > Computers > Computer Servers Electronics > Computers > Desktop Computers Electronics > Computers > Handheld Devices -Electronics > Computers > Handheld Devices > Data Collection Terminals +Electronics > Computers > Handheld Devices > Data Collectors Electronics > Computers > Handheld Devices > E-Book Readers Electronics > Computers > Handheld Devices > PDAs Electronics > Computers > Interactive Kiosks Electronics > Computers > Laptops -Electronics > Computers > Laptops > Netbooks +Electronics > Computers > Smart Glasses Electronics > Computers > Tablet Computers -Electronics > Electrical Motors +Electronics > Computers > Thin & Zero Clients +Electronics > Computers > Touch Table Computers Electronics > Electronics Accessories Electronics > Electronics Accessories > Adapters -Electronics > Electronics Accessories > Adapters > Audio & Video Adapters -Electronics > Electronics Accessories > Adapters > Memory Adapters -Electronics > Electronics Accessories > Adapters > Storage Adapters +Electronics > Electronics Accessories > Adapters > Audio & Video Cable Adapters & Couplers +Electronics > Electronics Accessories > Adapters > Memory Card Adapters Electronics > Electronics Accessories > Adapters > USB Adapters Electronics > Electronics Accessories > Antenna Accessories Electronics > Electronics Accessories > Antenna Accessories > Antenna Mounts & Brackets Electronics > Electronics Accessories > Antenna Accessories > Antenna Rotators Electronics > Electronics Accessories > Antenna Accessories > Satellite LNBs Electronics > Electronics Accessories > Antennas -Electronics > Electronics Accessories > Antennas > Communication Antennas -Electronics > Electronics Accessories > Antennas > Radio Antennas -Electronics > Electronics Accessories > Antennas > TV Antennas +Electronics > Electronics Accessories > Audio & Video Splitters & Switches +Electronics > Electronics Accessories > Audio & Video Splitters & Switches > DVI Splitters & Switches +Electronics > Electronics Accessories > Audio & Video Splitters & Switches > HDMI Splitters & Switches +Electronics > Electronics Accessories > Audio & Video Splitters & Switches > VGA Splitters & Switches Electronics > Electronics Accessories > Blank Media -Electronics > Electronics Accessories > Blank Media > Blank Audio Tapes -Electronics > Electronics Accessories > Blank Media > Blank Audio Tapes > Micro Cassettes -Electronics > Electronics Accessories > Blank Media > Blank Blu-ray Discs -Electronics > Electronics Accessories > Blank Media > Blank CDs -Electronics > Electronics Accessories > Blank Media > Blank DVDs -Electronics > Electronics Accessories > Blank Media > Blank Video Tapes -Electronics > Electronics Accessories > Blank Media > Computer Disks -Electronics > Electronics Accessories > Blank Media > Computer Disks > Floppy Disks -Electronics > Electronics Accessories > Blank Media > Computer Tapes -Electronics > Electronics Accessories > Blank Media > MiniDiscs Electronics > Electronics Accessories > Cable Management Electronics > Electronics Accessories > Cable Management > Cable Clips +Electronics > Electronics Accessories > Cable Management > Cable Tie Guns Electronics > Electronics Accessories > Cable Management > Cable Trays Electronics > Electronics Accessories > Cable Management > Patch Panels +Electronics > Electronics Accessories > Cable Management > Wire & Cable Identification Markers Electronics > Electronics Accessories > Cable Management > Wire & Cable Sleeves Electronics > Electronics Accessories > Cable Management > Wire & Cable Ties Electronics > Electronics Accessories > Cables Electronics > Electronics Accessories > Cables > Audio & Video Cables -Electronics > Electronics Accessories > Cables > Audio & Video Cables > DVI Cables -Electronics > Electronics Accessories > Cables > Audio & Video Cables > HDMI Cables -Electronics > Electronics Accessories > Cables > Audio & Video Cables > SCART Cables -Electronics > Electronics Accessories > Cables > Audio & Video Cables > Speaker Cables -Electronics > Electronics Accessories > Cables > Coaxial Cables -Electronics > Electronics Accessories > Cables > Data Transfer Cables -Electronics > Electronics Accessories > Cables > Data Transfer Cables > FireWire Cables -Electronics > Electronics Accessories > Cables > Data Transfer Cables > USB Cables -Electronics > Electronics Accessories > Cables > Data Transfer Cables > iOS Cables Electronics > Electronics Accessories > Cables > KVM Cables Electronics > Electronics Accessories > Cables > Network Cables -Electronics > Electronics Accessories > Cables > Network Cables > Ethernet Cables -Electronics > Electronics Accessories > Cables > Network Cables > Serial Cables -Electronics > Electronics Accessories > Cables > Optical Cables -Electronics > Electronics Accessories > Cables > RCA Cables -Electronics > Electronics Accessories > Cables > Storage Cables -Electronics > Electronics Accessories > Cables > Storage Cables > IDE Cables -Electronics > Electronics Accessories > Cables > Storage Cables > SAS Cables -Electronics > Electronics Accessories > Cables > Storage Cables > SATA Cables -Electronics > Electronics Accessories > Cables > Storage Cables > SCSI Cables +Electronics > Electronics Accessories > Cables > Storage & Data Transfer Cables Electronics > Electronics Accessories > Cables > System & Power Cables Electronics > Electronics Accessories > Cables > Telephone Cables +Electronics > Electronics Accessories > Computer Accessories +Electronics > Electronics Accessories > Computer Accessories > Computer Accessory Sets +Electronics > Electronics Accessories > Computer Accessories > Computer Covers & Skins +Electronics > Electronics Accessories > Computer Accessories > Computer Risers & Stands +Electronics > Electronics Accessories > Computer Accessories > Handheld Device Accessories +Electronics > Electronics Accessories > Computer Accessories > Handheld Device Accessories > E-Book Reader Accessories +Electronics > Electronics Accessories > Computer Accessories > Handheld Device Accessories > E-Book Reader Accessories > E-Book Reader Cases +Electronics > Electronics Accessories > Computer Accessories > Handheld Device Accessories > PDA Accessories +Electronics > Electronics Accessories > Computer Accessories > Handheld Device Accessories > PDA Accessories > PDA Cases +Electronics > Electronics Accessories > Computer Accessories > Keyboard & Mouse Wrist Rests +Electronics > Electronics Accessories > Computer Accessories > Keyboard Trays & Platforms +Electronics > Electronics Accessories > Computer Accessories > Laptop Docking Stations +Electronics > Electronics Accessories > Computer Accessories > Mouse Pads +Electronics > Electronics Accessories > Computer Accessories > Stylus Pen Nibs & Refills +Electronics > Electronics Accessories > Computer Accessories > Stylus Pens +Electronics > Electronics Accessories > Computer Accessories > Tablet Computer Docks & Stands +Electronics > Electronics Accessories > Computer Components +Electronics > Electronics Accessories > Computer Components > Blade Server Enclosures +Electronics > Electronics Accessories > Computer Components > Computer Backplates & I/O Shields +Electronics > Electronics Accessories > Computer Components > Computer Power Supplies +Electronics > Electronics Accessories > Computer Components > Computer Processors +Electronics > Electronics Accessories > Computer Components > Computer Racks & Mounts +Electronics > Electronics Accessories > Computer Components > Computer Starter Kits +Electronics > Electronics Accessories > Computer Components > Computer System Cooling Parts +Electronics > Electronics Accessories > Computer Components > Desktop Computer & Server Cases +Electronics > Electronics Accessories > Computer Components > E-Book Reader Parts +Electronics > Electronics Accessories > Computer Components > E-Book Reader Parts > E-Book Reader Screens & Screen Digitizers +Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters +Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters > Audio Cards & Adapters +Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters > Computer Interface Cards & Adapters +Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters > Riser Cards +Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters > TV Tuner Cards & Adapters +Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters > Video Cards & Adapters +Electronics > Electronics Accessories > Computer Components > Input Device Accessories +Electronics > Electronics Accessories > Computer Components > Input Device Accessories > Barcode Scanner Stands +Electronics > Electronics Accessories > Computer Components > Input Device Accessories > Game Controller Accessories +Electronics > Electronics Accessories > Computer Components > Input Device Accessories > Keyboard Keys & Caps +Electronics > Electronics Accessories > Computer Components > Input Device Accessories > Mice & Trackball Accessories +Electronics > Electronics Accessories > Computer Components > Input Devices +Electronics > Electronics Accessories > Computer Components > Input Devices > Barcode Scanners +Electronics > Electronics Accessories > Computer Components > Input Devices > Digital Note Taking Pens +Electronics > Electronics Accessories > Computer Components > Input Devices > Electronic Card Readers +Electronics > Electronics Accessories > Computer Components > Input Devices > Fingerprint Readers +Electronics > Electronics Accessories > Computer Components > Input Devices > Game Controllers +Electronics > Electronics Accessories > Computer Components > Input Devices > Gesture Control Input Devices +Electronics > Electronics Accessories > Computer Components > Input Devices > Graphics Tablets +Electronics > Electronics Accessories > Computer Components > Input Devices > KVM Switches +Electronics > Electronics Accessories > Computer Components > Input Devices > Keyboards +Electronics > Electronics Accessories > Computer Components > Input Devices > Memory Card Readers +Electronics > Electronics Accessories > Computer Components > Input Devices > Mice & Trackballs +Electronics > Electronics Accessories > Computer Components > Input Devices > Numeric Keypads +Electronics > Electronics Accessories > Computer Components > Input Devices > Touchpads +Electronics > Electronics Accessories > Computer Components > Laptop Parts +Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Hinges +Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Housings & Trim +Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Replacement Cables +Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Replacement Keyboards +Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Replacement Screens +Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Replacement Speakers +Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Screen Digitizers +Electronics > Electronics Accessories > Computer Components > Storage Devices +Electronics > Electronics Accessories > Computer Components > Storage Devices > Disk Duplicators +Electronics > Electronics Accessories > Computer Components > Storage Devices > Disk Duplicators > CD/DVD Duplicators +Electronics > Electronics Accessories > Computer Components > Storage Devices > Disk Duplicators > Hard Drive Duplicators +Electronics > Electronics Accessories > Computer Components > Storage Devices > Disk Duplicators > USB Drive Duplicators +Electronics > Electronics Accessories > Computer Components > Storage Devices > Floppy Drives +Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drive Accessories +Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drive Accessories > Hard Drive Carrying Cases +Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drive Accessories > Hard Drive Docks +Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drive Accessories > Hard Drive Enclosures & Mounts +Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drive Arrays +Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drives +Electronics > Electronics Accessories > Computer Components > Storage Devices > Network Storage Systems +Electronics > Electronics Accessories > Computer Components > Storage Devices > Optical Drives +Electronics > Electronics Accessories > Computer Components > Storage Devices > Tape Drives +Electronics > Electronics Accessories > Computer Components > Storage Devices > USB Flash Drives +Electronics > Electronics Accessories > Computer Components > Tablet Computer Parts +Electronics > Electronics Accessories > Computer Components > Tablet Computer Parts > Tablet Computer Housings & Trim +Electronics > Electronics Accessories > Computer Components > Tablet Computer Parts > Tablet Computer Replacement Speakers +Electronics > Electronics Accessories > Computer Components > Tablet Computer Parts > Tablet Computer Screens & Screen Digitizers +Electronics > Electronics Accessories > Computer Components > USB & FireWire Hubs Electronics > Electronics Accessories > Electronics Cleaners -Electronics > Electronics Accessories > Electronics Cleaners > Audio & Video Cleaners -Electronics > Electronics Accessories > Electronics Cleaners > Camera Cleaners -Electronics > Electronics Accessories > Electronics Cleaners > Screen Cleaners Electronics > Electronics Accessories > Electronics Films & Shields Electronics > Electronics Accessories > Electronics Films & Shields > Electronics Stickers & Decals -Electronics > Electronics Accessories > Electronics Films & Shields > Electronics Stickers & Decals > Computer Keyboard Stickers -Electronics > Electronics Accessories > Electronics Films & Shields > Electronics Stickers & Decals > Game Console Stickers & Decals -Electronics > Electronics Accessories > Electronics Films & Shields > Electronics Stickers & Decals > Laptop Stickers & Decals -Electronics > Electronics Accessories > Electronics Films & Shields > Electronics Stickers & Decals > MP3 Player Stickers & Decals -Electronics > Electronics Accessories > Electronics Films & Shields > Electronics Stickers & Decals > Mobile Phone Stickers & Decals -Electronics > Electronics Accessories > Electronics Films & Shields > Electronics Stickers & Decals > Tablet Computer Stickers & Decals Electronics > Electronics Accessories > Electronics Films & Shields > Keyboard Protectors Electronics > Electronics Accessories > Electronics Films & Shields > Privacy Filters Electronics > Electronics Accessories > Electronics Films & Shields > Screen Protectors @@ -1721,6 +1503,7 @@ Electronics > Electronics Accessories > Memory > ROM Electronics > Electronics Accessories > Memory > Video Memory Electronics > Electronics Accessories > Memory Accessories Electronics > Electronics Accessories > Memory Accessories > Memory Cases +Electronics > Electronics Accessories > Mobile Phone & Tablet Tripods & Monopods Electronics > Electronics Accessories > Power Electronics > Electronics Accessories > Power > Batteries Electronics > Electronics Accessories > Power > Batteries > Camera Batteries @@ -1728,56 +1511,50 @@ Electronics > Electronics Accessories > Power > Batteries > Cordless Phone Batte Electronics > Electronics Accessories > Power > Batteries > E-Book Reader Batteries Electronics > Electronics Accessories > Power > Batteries > General Purpose Batteries Electronics > Electronics Accessories > Power > Batteries > Laptop Batteries +Electronics > Electronics Accessories > Power > Batteries > MP3 Player Batteries Electronics > Electronics Accessories > Power > Batteries > Mobile Phone Batteries Electronics > Electronics Accessories > Power > Batteries > PDA Batteries Electronics > Electronics Accessories > Power > Batteries > Tablet Computer Batteries Electronics > Electronics Accessories > Power > Batteries > UPS Batteries Electronics > Electronics Accessories > Power > Batteries > Video Camera Batteries +Electronics > Electronics Accessories > Power > Batteries > Video Game Console & Controller Batteries Electronics > Electronics Accessories > Power > Battery Accessories +Electronics > Electronics Accessories > Power > Battery Accessories > Battery Charge Controllers +Electronics > Electronics Accessories > Power > Battery Accessories > Battery Holders Electronics > Electronics Accessories > Power > Battery Accessories > Camera Battery Chargers Electronics > Electronics Accessories > Power > Battery Accessories > General Purpose Battery Chargers -Electronics > Electronics Accessories > Power > Chargers -Electronics > Electronics Accessories > Power > Chargers > E-Book Reader Chargers -Electronics > Electronics Accessories > Power > Chargers > MP3 Player Chargers -Electronics > Electronics Accessories > Power > Chargers > Mobile Phone Chargers -Electronics > Electronics Accessories > Power > Chargers > PDA Chargers -Electronics > Electronics Accessories > Power > Chargers > Solar Chargers -Electronics > Electronics Accessories > Power > Chargers > Tablet Computer Chargers +Electronics > Electronics Accessories > Power > Battery Accessories > General Purpose Battery Testers Electronics > Electronics Accessories > Power > Fuel Cells -Electronics > Electronics Accessories > Power > Power Adapter Accessories -Electronics > Electronics Accessories > Power > Power Adapters -Electronics > Electronics Accessories > Power > Power Adapters > Laptop Power Adapters -Electronics > Electronics Accessories > Power > Power Adapters > Power Converters -Electronics > Electronics Accessories > Power > Power Adapters > Power Inverters -Electronics > Electronics Accessories > Power > Power Adapters > Travel Adapters -Electronics > Electronics Accessories > Power > Power Conditioners +Electronics > Electronics Accessories > Power > Power Adapter & Charger Accessories +Electronics > Electronics Accessories > Power > Power Adapters & Chargers Electronics > Electronics Accessories > Power > Power Control Units -Electronics > Electronics Accessories > Power > Power Enclosures -Electronics > Electronics Accessories > Power > Power Injectors & Splitters Electronics > Electronics Accessories > Power > Power Strips & Surge Suppressors +Electronics > Electronics Accessories > Power > Power Supply Enclosures Electronics > Electronics Accessories > Power > Surge Protection Devices +Electronics > Electronics Accessories > Power > Travel Converters & Adapters Electronics > Electronics Accessories > Power > UPS Electronics > Electronics Accessories > Power > UPS Accessories -Electronics > Electronics Accessories > Power > Voltage Converters Electronics > Electronics Accessories > Remote Controls Electronics > Electronics Accessories > Signal Boosters -Electronics > GPS -Electronics > GPS > Automotive GPS -Electronics > GPS > Aviation GPS -Electronics > GPS > Sport GPS +Electronics > Electronics Accessories > Signal Jammers +Electronics > Electronics Accessories > Signal Jammers > GPS Jammers +Electronics > Electronics Accessories > Signal Jammers > Mobile Phone Jammers +Electronics > Electronics Accessories > Signal Jammers > Radar Jammers Electronics > GPS Accessories Electronics > GPS Accessories > GPS Cases Electronics > GPS Accessories > GPS Mounts -Electronics > GPS Trackers +Electronics > GPS Navigation Systems +Electronics > GPS Tracking Devices Electronics > Marine Electronics Electronics > Marine Electronics > Fish Finders +Electronics > Marine Electronics > Marine Audio & Video Receivers Electronics > Marine Electronics > Marine Chartplotters & GPS Electronics > Marine Electronics > Marine Radar Electronics > Marine Electronics > Marine Radios +Electronics > Marine Electronics > Marine Speakers Electronics > Networking Electronics > Networking > Bridges & Routers Electronics > Networking > Bridges & Routers > Network Bridges -Electronics > Networking > Bridges & Routers > Network Bridges > Wireless Bridges Electronics > Networking > Bridges & Routers > VoIP Gateways & Routers Electronics > Networking > Bridges & Routers > Wireless Access Points Electronics > Networking > Bridges & Routers > Wireless Routers @@ -1786,39 +1563,31 @@ Electronics > Networking > Hubs & Switches Electronics > Networking > Modem Accessories Electronics > Networking > Modems Electronics > Networking > Network Cards & Adapters -Electronics > Networking > Network Cards & Adapters > XBox 360 Network Cards Electronics > Networking > Network Security & Firewall Devices -Electronics > Networking > Power Line Network Adapters +Electronics > Networking > Power Over Ethernet Adapters Electronics > Networking > Print Servers Electronics > Networking > Repeaters & Transceivers -Electronics > Plug & Play TV Games Electronics > Print, Copy, Scan & Fax -Electronics > Print, Copy, Scan & Fax > Fax Machines -Electronics > Print, Copy, Scan & Fax > Printers & Copiers -Electronics > Print, Copy, Scan & Fax > Printers & Copiers > Copiers -Electronics > Print, Copy, Scan & Fax > Printers & Copiers > Printers -Electronics > Print, Copy, Scan & Fax > Printers & Copiers > Printers > Dot Matrix Printers -Electronics > Print, Copy, Scan & Fax > Printers & Copiers > Printers > Inkjet Printers -Electronics > Print, Copy, Scan & Fax > Printers & Copiers > Printers > Laser Printers -Electronics > Print, Copy, Scan & Fax > Printers & Copiers > Printers > Photo Printers +Electronics > Print, Copy, Scan & Fax > 3D Printer Accessories +Electronics > Print, Copy, Scan & Fax > 3D Printers +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Printer Drums & Drum Kits +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Printer Filters +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Printer Maintenance Kits +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Printer Ribbons +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Printheads +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Toner & Inkjet Cartridge Refills +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Toner & Inkjet Cartridges +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Duplexers +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Memory +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Stands +Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer, Copier & Fax Machine Replacement Parts +Electronics > Print, Copy, Scan & Fax > Printers, Copiers & Fax Machines +Electronics > Print, Copy, Scan & Fax > Scanner Accessories Electronics > Print, Copy, Scan & Fax > Scanners -Electronics > Print, Copy, Scan & Fax Accessories -Electronics > Print, Copy, Scan & Fax Accessories > Copier Accessories -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Consumables -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Consumables > Printer Filters -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Consumables > Printer Ribbons -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Consumables > Printheads -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Consumables > Toner & Inkjet Cartridge Refills -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Consumables > Toner & Inkjet Cartridges -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Consumables > Toner & Inkjet Cartridges > Oil Rollers -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Consumables > Toner & Inkjet Cartridges > Printer Drum Kits -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Duplexers -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Maintenance Kits -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Memory -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Stands -Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Printer Trays -Electronics > Print, Copy, Scan & Fax Accessories > Scanner Accessories +Electronics > Radar Detectors +Electronics > Speed Radars Electronics > Toll Collection Devices Electronics > Video Electronics > Video > Computer Monitors @@ -1830,10 +1599,6 @@ Electronics > Video > Satellite & Cable TV Electronics > Video > Satellite & Cable TV > Cable TV Receivers Electronics > Video > Satellite & Cable TV > Satellite Receivers Electronics > Video > Televisions -Electronics > Video > Televisions > CRT Televisions -Electronics > Video > Televisions > Flat Panel Televisions -Electronics > Video > Televisions > Portable Televisions -Electronics > Video > Televisions > Projection Televisions Electronics > Video > Video Accessories Electronics > Video > Video Accessories > 3D Glasses Electronics > Video > Video Accessories > Computer Monitor Accessories @@ -1845,158 +1610,58 @@ Electronics > Video > Video Accessories > Projector Accessories > Projection Scr Electronics > Video > Video Accessories > Projector Accessories > Projector Mounts Electronics > Video > Video Accessories > Projector Accessories > Projector Replacement Lamps Electronics > Video > Video Accessories > Rewinders -Electronics > Video > Video Accessories > Television Accessories -Electronics > Video > Video Accessories > Television Accessories > TV & Monitor Mounts -Electronics > Video > Video Accessories > Television Accessories > TV Replacement Lamps -Electronics > Video > Video Accessories > Television Accessories > TV Scan Converters +Electronics > Video > Video Accessories > Television Parts & Accessories +Electronics > Video > Video Accessories > Television Parts & Accessories > TV & Monitor Mounts +Electronics > Video > Video Accessories > Television Parts & Accessories > TV Converter Boxes +Electronics > Video > Video Accessories > Television Parts & Accessories > TV Replacement Lamps +Electronics > Video > Video Accessories > Television Parts & Accessories > TV Replacement Speakers Electronics > Video > Video Editing Hardware & Production Equipment Electronics > Video > Video Multiplexers Electronics > Video > Video Players & Recorders Electronics > Video > Video Players & Recorders > DVD & Blu-ray Players Electronics > Video > Video Players & Recorders > DVD Recorders -Electronics > Video > Video Players & Recorders > DVD Recorders > Blu-Ray Recorders -Electronics > Video > Video Players & Recorders > DVD Recorders > HD-DVD Recorders Electronics > Video > Video Players & Recorders > Digital Video Recorders -Electronics > Video > Video Players & Recorders > Home Media Players +Electronics > Video > Video Players & Recorders > Streaming & Home Media Players Electronics > Video > Video Players & Recorders > VCRs Electronics > Video > Video Servers Electronics > Video > Video Transmitters -Electronics > Video > Video Transmitters > Video Senders Electronics > Video Game Console Accessories Electronics > Video Game Console Accessories > Home Game Console Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > All PlayStation Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > All PlayStation Accessories > PlayStation (original) Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > All PlayStation Accessories > PlayStation 2 Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > All PlayStation Accessories > PlayStation 3 Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > All XBox Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > All XBox Accessories > XBox (original) Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > All XBox Accessories > XBox 360 Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Dreamcast Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > GameCube Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Jaguar Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Neo Geo Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Nintendo 64 Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Nintendo Entertainment System Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Sega Genesis Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Sega Master System Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Super Nintendo Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Turbografx 16 Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Wii Accessories -Electronics > Video Game Console Accessories > Home Game Console Accessories > Wii U Accessories Electronics > Video Game Console Accessories > Portable Game Console Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > All Game Boy Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > All Game Boy Accessories > Game Boy Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > All Game Boy Accessories > Game Boy Advance Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > Atari Lynx Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > Game Gear Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > N-Gage Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > Neo Geo Pocket Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > Nintendo 3DS Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > Nintendo DS Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > PlayStation Portable Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > PlayStation Vita Accessories -Electronics > Video Game Console Accessories > Portable Game Console Accessories > WonderSwan Accessories Electronics > Video Game Consoles -Electronics > Video Game Consoles > Home Game Consoles -Electronics > Video Game Consoles > Home Game Consoles > Dreamcast Consoles -Electronics > Video Game Consoles > Home Game Consoles > GameCube Consoles -Electronics > Video Game Consoles > Home Game Consoles > Jaguar Consoles -Electronics > Video Game Consoles > Home Game Consoles > Neo Geo Consoles -Electronics > Video Game Consoles > Home Game Consoles > Nintendo 64 Consoles -Electronics > Video Game Consoles > Home Game Consoles > Nintendo Entertainment System Consoles -Electronics > Video Game Consoles > Home Game Consoles > PlayStation (original) Consoles -Electronics > Video Game Consoles > Home Game Consoles > PlayStation 2 Consoles -Electronics > Video Game Consoles > Home Game Consoles > PlayStation 3 Consoles -Electronics > Video Game Consoles > Home Game Consoles > Sega Genesis Consoles -Electronics > Video Game Consoles > Home Game Consoles > Sega Master System Consoles -Electronics > Video Game Consoles > Home Game Consoles > Super Nintendo Consoles -Electronics > Video Game Consoles > Home Game Consoles > Turbografx 16 Consoles -Electronics > Video Game Consoles > Home Game Consoles > Wii Consoles -Electronics > Video Game Consoles > Home Game Consoles > Wii U Consoles -Electronics > Video Game Consoles > Home Game Consoles > XBox (original) Consoles -Electronics > Video Game Consoles > Home Game Consoles > XBox 360 Consoles -Electronics > Video Game Consoles > Portable Game Consoles -Electronics > Video Game Consoles > Portable Game Consoles > All Game Boy Consoles -Electronics > Video Game Consoles > Portable Game Consoles > All Game Boy Consoles > Game Boy Advance Consoles -Electronics > Video Game Consoles > Portable Game Consoles > All Game Boy Consoles > Game Boy Consoles -Electronics > Video Game Consoles > Portable Game Consoles > Atari Lynx Consoles -Electronics > Video Game Consoles > Portable Game Consoles > Game Gear Consoles -Electronics > Video Game Consoles > Portable Game Consoles > LeapFrog Consoles -Electronics > Video Game Consoles > Portable Game Consoles > N-Gage Consoles -Electronics > Video Game Consoles > Portable Game Consoles > Neo Geo Pocket Consoles -Electronics > Video Game Consoles > Portable Game Consoles > Nintendo 3DS -Electronics > Video Game Consoles > Portable Game Consoles > Nintendo DS Consoles -Electronics > Video Game Consoles > Portable Game Consoles > PlayStation Portable Consoles -Electronics > Video Game Consoles > Portable Game Consoles > PlayStation Vita -Electronics > Video Game Consoles > Portable Game Consoles > Retrogen -Electronics > Video Game Consoles > Portable Game Consoles > WonderSwan Food, Beverages & Tobacco Food, Beverages & Tobacco > Beverages -Food, Beverages & Tobacco > Beverages > Beer -Food, Beverages & Tobacco > Beverages > Beer > Non-Alcoholic Beer -Food, Beverages & Tobacco > Beverages > Bitters +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Beer +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Bitters +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Cocktail Mixes +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Flavored Alcoholic Beverages +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Hard Cider +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Absinthe +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Brandy +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Gin +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Liqueurs +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Rum +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Shochu & Soju +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Tequila +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Vodka +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Whiskey +Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Wine Food, Beverages & Tobacco > Beverages > Buttermilk -Food, Beverages & Tobacco > Beverages > Cocktail Mixes Food, Beverages & Tobacco > Beverages > Coffee -Food, Beverages & Tobacco > Beverages > Coffee > Bottled Coffee Drinks -Food, Beverages & Tobacco > Beverages > Coffee > Coffee Pods -Food, Beverages & Tobacco > Beverages > Coffee > Ground & Whole Bean Coffee -Food, Beverages & Tobacco > Beverages > Coffee > Instant Coffee Food, Beverages & Tobacco > Beverages > Eggnog -Food, Beverages & Tobacco > Beverages > Flavored Malt Beverages Food, Beverages & Tobacco > Beverages > Fruit Flavored Drinks -Food, Beverages & Tobacco > Beverages > Hard Cider Food, Beverages & Tobacco > Beverages > Hot Chocolate Food, Beverages & Tobacco > Beverages > Juice -Food, Beverages & Tobacco > Beverages > Liquor & Spirits -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Brandy -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Brandy > Cognac -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Gin -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Liqueurs -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Rum -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Schnapps -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Tequila -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Vodka -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Whiskey -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Whiskey > American Whiskey -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Whiskey > Irish Whiskey -Food, Beverages & Tobacco > Beverages > Liquor & Spirits > Whiskey > Scotch Whiskey Food, Beverages & Tobacco > Beverages > Milk -Food, Beverages & Tobacco > Beverages > Milk > Powdered Milk Food, Beverages & Tobacco > Beverages > Non-Dairy Milk -Food, Beverages & Tobacco > Beverages > Non-Dairy Milk > Almond Milk -Food, Beverages & Tobacco > Beverages > Non-Dairy Milk > Coconut Milk -Food, Beverages & Tobacco > Beverages > Non-Dairy Milk > Hemp Milk -Food, Beverages & Tobacco > Beverages > Non-Dairy Milk > Oat Milk -Food, Beverages & Tobacco > Beverages > Non-Dairy Milk > Rice Milk -Food, Beverages & Tobacco > Beverages > Non-Dairy Milk > Soy Milk Food, Beverages & Tobacco > Beverages > Powdered Beverage Mixes Food, Beverages & Tobacco > Beverages > Soda Food, Beverages & Tobacco > Beverages > Sports & Energy Drinks Food, Beverages & Tobacco > Beverages > Tea & Infusions -Food, Beverages & Tobacco > Beverages > Tea & Infusions > Bottled Tea Drinks -Food, Beverages & Tobacco > Beverages > Tea & Infusions > Powdered Tea -Food, Beverages & Tobacco > Beverages > Tea & Infusions > Tea Bags & Loose Tea Leaves Food, Beverages & Tobacco > Beverages > Vinegar Drinks Food, Beverages & Tobacco > Beverages > Water -Food, Beverages & Tobacco > Beverages > Water > Bottled Water -Food, Beverages & Tobacco > Beverages > Water > Carbonated Water -Food, Beverages & Tobacco > Beverages > Water > Flavored Water -Food, Beverages & Tobacco > Beverages > Water > Tonic Water -Food, Beverages & Tobacco > Beverages > Wine -Food, Beverages & Tobacco > Beverages > Wine > Blush Wine -Food, Beverages & Tobacco > Beverages > Wine > Dessert Wine -Food, Beverages & Tobacco > Beverages > Wine > Dessert Wine > Port -Food, Beverages & Tobacco > Beverages > Wine > Dessert Wine > Sherry -Food, Beverages & Tobacco > Beverages > Wine > Dessert Wine > Vermouth -Food, Beverages & Tobacco > Beverages > Wine > Mead -Food, Beverages & Tobacco > Beverages > Wine > Non-Alcoholic Wine -Food, Beverages & Tobacco > Beverages > Wine > Red Wine -Food, Beverages & Tobacco > Beverages > Wine > Rice Wine -Food, Beverages & Tobacco > Beverages > Wine > Rosé Wine -Food, Beverages & Tobacco > Beverages > Wine > Sangria -Food, Beverages & Tobacco > Beverages > Wine > Sparkling Wine -Food, Beverages & Tobacco > Beverages > Wine > White Wine Food, Beverages & Tobacco > Food Items Food, Beverages & Tobacco > Food Items > Bakery Food, Beverages & Tobacco > Food Items > Bakery > Bagels @@ -2014,136 +1679,80 @@ Food, Beverages & Tobacco > Food Items > Bakery > Pastries & Scones Food, Beverages & Tobacco > Food Items > Bakery > Pies & Tarts Food, Beverages & Tobacco > Food Items > Bakery > Taco Shells & Tostadas Food, Beverages & Tobacco > Food Items > Bakery > Tortillas & Wraps -Food, Beverages & Tobacco > Food Items > Candy & Gum -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Candy Bars & Pieces -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Candy Brittle -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Candy Canes -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Candy Corn -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Caramels -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Chocolate Assortments -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Chocolate Bars -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Chocolate Covered Fruit -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Chocolate Truffles -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Fruit Chews -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Gumdrops -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Gummy Candies -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Hard Candies -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Jelly Beans -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Licorice -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Lollipops & Suckers -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Marshmallow Candies -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Mints -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Nougat -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Peanut Butter Cups -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Peppermint Patties -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Taffy -Food, Beverages & Tobacco > Food Items > Candy & Gum > Candy & Chocolate > Toffee -Food, Beverages & Tobacco > Food Items > Candy & Gum > Chewing Gum +Food, Beverages & Tobacco > Food Items > Candied & Chocolate Covered Fruit +Food, Beverages & Tobacco > Food Items > Candy & Chocolate Food, Beverages & Tobacco > Food Items > Condiments & Sauces -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Barbecue Sauce -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Chutney Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Cocktail Sauce -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Coffee Creamer Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Curry Sauce Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Dessert Toppings Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Dessert Toppings > Fruit Toppings Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Dessert Toppings > Ice Cream Syrup -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Dessert Toppings > Whipped Topping Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Fish Sauce Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Gravy Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Honey Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Horseradish Sauce Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Hot Sauce Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Ketchup -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Marinade +Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Marinades & Grilling Sauces Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Mayonnaise Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Mustard Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Olives & Capers Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Pasta Sauce -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Pickles & Relishes +Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Pickled Fruits & Vegetables Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Pizza Sauce +Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Relish & Chutney Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Salad Dressing Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Satay Sauce Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Soy Sauce -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Steak Sauce +Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Sweet and Sour Sauces Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Syrup -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Syrup > Agave Syrup -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Syrup > Flavored Syrup -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Syrup > Pancake & Maple Syrup -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Syrup > Snow Cone Syrup Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Tahini Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Tartar Sauce -Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Vinegar +Food, Beverages & Tobacco > Food Items > Condiments & Sauces > White & Cream Sauces Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Worcestershire Sauce Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Artificial Sweeteners Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Chips Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Chocolate -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Extracts -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Extracts > Almond Extract -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Extracts > Vanilla Extract -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Kits +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Flavors & Extracts Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Mixes -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Mixes > Bread & Muffin Mixes -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Mixes > Bread & Muffin Mixes > Bread Mixes -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Mixes > Bread & Muffin Mixes > Muffin Mixes -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Mixes > Bread Pudding Mixes -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Mixes > Cake & Brownie Mixes -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Mixes > Cookie Mixes -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Mixes > Pretzel Mixes -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Mixes > Waffle & Pancake Mixes Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Powder Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Soda Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Batter & Coating Mixes Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Bean Paste Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Bread Crumbs -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Condensed Milk -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Canola Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Chili Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Coconut Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Cooking Spray -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Corn Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Hemp Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Olive Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Peanut Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Rice Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Sesame Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Soybean Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Vegetable Oil -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oil > Walnut Oil +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Canned & Dry Milk +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cookie Decorating Kits +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oils Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Starch Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Wine Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Corn Syrup Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Dough Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Dough > Bread & Pastry Dough -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Dough > Bread & Pastry Dough > Pizza Dough Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Dough > Cookie & Brownie Dough Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Dough > Pie Crusts Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Edible Baking Decorations -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Edible Baking Decorations > Colored Sugar -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Edible Baking Decorations > Edible Baking Decoration Kits -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Edible Baking Decorations > Sprinkles -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Edible Baking Decorations > Sugar Pearls -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Evaporated Milk Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Floss Sugar Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Flour Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Food Coloring Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Frosting & Icing +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Lemon & Lime Juice Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Marshmallows +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Meal Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Molasses -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Pie Fillings +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Pie & Pastry Fillings Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Shortening & Lard -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Shredded Coconut Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Starter Cultures -Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Sugar +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Sugar & Sweeteners +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Tapioca Pearls Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Tomato Paste Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Unflavored Gelatin +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Vinegar +Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Waffle & Pancake Mixes Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Yeast Food, Beverages & Tobacco > Food Items > Dairy Products Food, Beverages & Tobacco > Food Items > Dairy Products > Butter & Margarine Food, Beverages & Tobacco > Food Items > Dairy Products > Cheese +Food, Beverages & Tobacco > Food Items > Dairy Products > Coffee Creamer Food, Beverages & Tobacco > Food Items > Dairy Products > Cottage Cheese Food, Beverages & Tobacco > Food Items > Dairy Products > Cream Food, Beverages & Tobacco > Food Items > Dairy Products > Sour Cream @@ -2151,37 +1760,29 @@ Food, Beverages & Tobacco > Food Items > Dairy Products > Whipped Cream Food, Beverages & Tobacco > Food Items > Dairy Products > Yogurt Food, Beverages & Tobacco > Food Items > Dips & Spreads Food, Beverages & Tobacco > Food Items > Dips & Spreads > Apple Butter -Food, Beverages & Tobacco > Food Items > Dips & Spreads > Cheese Spread +Food, Beverages & Tobacco > Food Items > Dips & Spreads > Cheese Dips & Spreads Food, Beverages & Tobacco > Food Items > Dips & Spreads > Cream Cheese Food, Beverages & Tobacco > Food Items > Dips & Spreads > Guacamole Food, Beverages & Tobacco > Food Items > Dips & Spreads > Hummus Food, Beverages & Tobacco > Food Items > Dips & Spreads > Jams & Jellies Food, Beverages & Tobacco > Food Items > Dips & Spreads > Nut Butters -Food, Beverages & Tobacco > Food Items > Dips & Spreads > Nut Butters > Almond Butter -Food, Beverages & Tobacco > Food Items > Dips & Spreads > Nut Butters > Hazelnut Butter -Food, Beverages & Tobacco > Food Items > Dips & Spreads > Nut Butters > Peanut Butter Food, Beverages & Tobacco > Food Items > Dips & Spreads > Salsa Food, Beverages & Tobacco > Food Items > Dips & Spreads > Tapenade Food, Beverages & Tobacco > Food Items > Dips & Spreads > Vegetable Dip Food, Beverages & Tobacco > Food Items > Food Gift Baskets Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties -Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Frozen Yogurt -Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Ice Cream -Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Nondairy Frozen Desserts -Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Popsicles -Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Sherbet -Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Sorbet -Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Sundae Cones +Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Ice Cream & Frozen Yogurt +Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Ice Cream Novelties +Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Ice Pops Food, Beverages & Tobacco > Food Items > Fruits & Vegetables +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Canned & Jarred Fruits Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Canned & Jarred Vegetables Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Canned & Prepared Beans -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Canned Fruits Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Dried Fruits Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Dried Vegetables Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Dry Beans Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Apples -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Apricots Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Atemoyas Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Avocados Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Babacos @@ -2190,43 +1791,37 @@ Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fr Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Breadfruit Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Cactus Pears Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Cherimoyas -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Cherries +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Grapefruits +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Kumquats +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Lemons +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Limequats +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Limes +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Oranges +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Tangelos Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Coconuts -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Currants Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Dates Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Feijoas Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Figs -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Grapefruits +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Fruit Mixes Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Grapes Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Guavas -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Homli Fruits -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Kiwifruit -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Kumquats -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Lemons -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Limequats -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Limes +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Homely Fruits +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Kiwis Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Longan Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Loquats Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Lychees -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Madroño +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Madroño Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Mamey -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Mangoes Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Mangosteens Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Melons -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Melons > Bitter Melons -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Melons > Kiwanos -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Nectarines -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Oranges Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Papayas Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Passion Fruit -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Peaches Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Pears Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Persimmons Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Physalis Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Pineapples Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Pitahayas -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Plumcots -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Plums Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Pomegranates Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Quince Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Rambutans @@ -2234,21 +1829,21 @@ Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fr Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Sapote Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Soursops Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Starfruits +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Apricots +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Cherries +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Mangoes +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Peaches & Nectarines +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Plumcots +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Plums Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Sugar Apples Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Tamarindo -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Tangelos -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Tangerines Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Alfafa Sprouts Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Arracachas Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Artichokes -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Arugula Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Asparagus -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Bean Sprouts Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Beans -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Beet Greens Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Beets -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Bok Choy Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Borage Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Broccoli Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Brussel Sprouts @@ -2259,14 +1854,6 @@ Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Ve Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Cauliflower Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Celery Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Celery Roots -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Chard -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Chick Peas -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Chicory -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Chicory > Belgian Endives -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Chicory > Endives -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Chicory > Escarole -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Chicory > Radicchio -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Choy Sum Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Corn Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Cucumbers Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Eggplants @@ -2277,56 +1864,57 @@ Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Ve Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Garlic Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Ginger Root Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Gobo Root -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Gourds Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Arugula +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Beet Greens +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Bok Choy +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Chard +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Chicory +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Choy Sum +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Kale +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Lettuce +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > On Choy +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Salad Mixes +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Spinach +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Yu Choy Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Horseradish Root Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Jicama -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Kale Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Kohlrabi Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Leeks -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Lettuce Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Lotus Roots Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Malangas Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Mushrooms Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Okra -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > On Choy Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Onions Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Parsley Roots Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Parsnips Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Peas Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Peppers Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Potatoes -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Pumpkins Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Radishes Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Rhubarb -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Rutabagas -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Salad Mixes Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Shallots -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Spinach -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Squashes +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Sprouts +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Squashes & Gourds Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Sugar Cane Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Sunchokes Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Sweet Potatoes Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Tamarillos Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Taro Root Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Tomatoes -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Turnips -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Tuscan Cabbage +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Turnips & Rutabagas +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Vegetable Mixes Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Water Chestnuts Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Watercress Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Wheatgrass -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Yu Choy +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Yams Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Yuca Root -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Ñame -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fruit Sauce -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fruit Sauce > Apple Sauce -Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fruit Sauce > Cranberry Sauce +Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fruit Sauces Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Amaranth Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Barley Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Buckwheat Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Cereal & Granola -Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Cornmeal Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Couscous Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Millet Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Oats, Grits & Hot Cereal @@ -2340,104 +1928,28 @@ Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Meat Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Meat > Canned Meats Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Meat > Fresh & Frozen Meats Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Meat > Lunch & Deli Meats -Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Meat > Meat Patties -Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Meat > Sausages & Hot Dogs Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Seafood Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Seafood > Canned Seafood Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Seafood > Fresh & Frozen Seafood Food, Beverages & Tobacco > Food Items > Nuts & Seeds -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Almonds -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Brazil Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Cashews -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Chestnuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Chocolate Covered Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Hazelnuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Kola Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Macadamia Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Mamoncillo Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Maya Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Mixed Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Ogbono Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Paradise Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Peanuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Pecans -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Pine Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Pistachios -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Pumpkin Seeds -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Sesame Seeds -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Soy Nuts -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Sunflower Seeds -Food, Beverages & Tobacco > Food Items > Nuts & Seeds > Walnuts Food, Beverages & Tobacco > Food Items > Pasta & Noodles Food, Beverages & Tobacco > Food Items > Prepared Foods -Food, Beverages & Tobacco > Food Items > Prepared Foods > Appetizers & Hors d'Oeuvres -Food, Beverages & Tobacco > Food Items > Prepared Foods > Frozen Dinners -Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Entrées & Sides -Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Entrées & Sides > Breakfast Sandwiches -Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Entrées & Sides > Pizza -Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Entrées & Sides > Prepared Entrées -Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Entrées & Sides > Prepared Sandwiches -Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Entrées & Sides > Prepared Side Dishes -Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Entrées & Sides > Waffles, Pancakes & French Toast -Food, Beverages & Tobacco > Food Items > Prepared Foods > Skillet Dinners -Food, Beverages & Tobacco > Food Items > Prepared Foods > Sushi +Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Appetizers & Side Dishes +Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Meals & Entrées Food, Beverages & Tobacco > Food Items > Seasonings & Spices Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Anise -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Basil -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Bay Leaves -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Chili Powder -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Chives -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Cilantro -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Cinnamon -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Cumin -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Dill -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Fennel Seeds -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Garlic Powder -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Lemon Grass -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Marjoram -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Mint -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Onion Powder -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Oregano -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Paprika -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Parsley -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Rosemary -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Sage -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Salsify -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Savory -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Sorrel -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Tarragon -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Thyme -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices > Vanilla Beans Food, Beverages & Tobacco > Food Items > Seasonings & Spices > MSG Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Pepper Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Salt -Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Seasoning & Spice Blends Food, Beverages & Tobacco > Food Items > Snack Foods Food, Beverages & Tobacco > Food Items > Snack Foods > Breadsticks Food, Beverages & Tobacco > Food Items > Snack Foods > Cereal & Granola Bars Food, Beverages & Tobacco > Food Items > Snack Foods > Cheese Puffs Food, Beverages & Tobacco > Food Items > Snack Foods > Chips -Food, Beverages & Tobacco > Food Items > Snack Foods > Chips > Bagel Chips -Food, Beverages & Tobacco > Food Items > Snack Foods > Chips > Corn & Tortilla Chips -Food, Beverages & Tobacco > Food Items > Snack Foods > Chips > Pita Chips -Food, Beverages & Tobacco > Food Items > Snack Foods > Chips > Potato Chips Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers -Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers > Cheese Crackers -Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers > Cracker Assortments -Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers > Flatbread Crackers -Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers > Graham Crackers -Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers > Matzo Crackers -Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers > Oyster Crackers -Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers > Saltine Crackers -Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers > Sandwich Crackers -Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers > Water Crackers Food, Beverages & Tobacco > Food Items > Snack Foods > Croutons Food, Beverages & Tobacco > Food Items > Snack Foods > Fruit Snacks Food, Beverages & Tobacco > Food Items > Snack Foods > Jerky -Food, Beverages & Tobacco > Food Items > Snack Foods > Jerky > Beef Jerky -Food, Beverages & Tobacco > Food Items > Snack Foods > Jerky > Pork Jerky -Food, Beverages & Tobacco > Food Items > Snack Foods > Jerky > Turkey Jerky Food, Beverages & Tobacco > Food Items > Snack Foods > Popcorn Food, Beverages & Tobacco > Food Items > Snack Foods > Pork Rinds Food, Beverages & Tobacco > Food Items > Snack Foods > Pretzels @@ -2449,9 +1961,6 @@ Food, Beverages & Tobacco > Food Items > Snack Foods > Snack Cakes Food, Beverages & Tobacco > Food Items > Snack Foods > Sticky Rice Cakes Food, Beverages & Tobacco > Food Items > Snack Foods > Trail & Snack Mixes Food, Beverages & Tobacco > Food Items > Soups & Broths -Food, Beverages & Tobacco > Food Items > Soups & Broths > Bouillon Cubes -Food, Beverages & Tobacco > Food Items > Soups & Broths > Canned Soups & Broths -Food, Beverages & Tobacco > Food Items > Soups & Broths > Dried Soups Food, Beverages & Tobacco > Food Items > Tofu, Soy & Vegetarian Products Food, Beverages & Tobacco > Food Items > Tofu, Soy & Vegetarian Products > Cheese Alternatives Food, Beverages & Tobacco > Food Items > Tofu, Soy & Vegetarian Products > Meat Alternatives @@ -2462,13 +1971,13 @@ Food, Beverages & Tobacco > Tobacco Products Food, Beverages & Tobacco > Tobacco Products > Chewing Tobacco Food, Beverages & Tobacco > Tobacco Products > Cigarettes Food, Beverages & Tobacco > Tobacco Products > Cigars -Food, Beverages & Tobacco > Tobacco Products > Electronic Cigarettes Food, Beverages & Tobacco > Tobacco Products > Loose Tobacco +Food, Beverages & Tobacco > Tobacco Products > Smoking Pipes +Food, Beverages & Tobacco > Tobacco Products > Vaporizers & Electronic Cigarettes Furniture Furniture > Baby & Toddler Furniture Furniture > Baby & Toddler Furniture > Baby & Toddler Furniture Sets Furniture > Baby & Toddler Furniture > Bassinet & Cradle Accessories -Furniture > Baby & Toddler Furniture > Bassinet & Cradle Accessories > Bassinet Stands Furniture > Baby & Toddler Furniture > Bassinets & Cradles Furniture > Baby & Toddler Furniture > Changing Tables Furniture > Baby & Toddler Furniture > Crib & Toddler Bed Accessories @@ -2476,21 +1985,13 @@ Furniture > Baby & Toddler Furniture > Crib & Toddler Bed Accessories > Crib Bum Furniture > Baby & Toddler Furniture > Crib & Toddler Bed Accessories > Crib Conversion Kits Furniture > Baby & Toddler Furniture > Cribs & Toddler Beds Furniture > Baby & Toddler Furniture > High Chair & Booster Seat Accessories -Furniture > Baby & Toddler Furniture > High Chairs & Boosters -Furniture > Baby & Toddler Furniture > Playroom Furniture +Furniture > Baby & Toddler Furniture > High Chairs & Booster Seats Furniture > Beds & Accessories -Furniture > Beds & Accessories > Bed Accessories -Furniture > Beds & Accessories > Bed Accessories > Waterbed Accessories -Furniture > Beds & Accessories > Bed Frames -Furniture > Beds & Accessories > Beds -Furniture > Beds & Accessories > Beds > Bunk Beds -Furniture > Beds & Accessories > Beds > Day Beds -Furniture > Beds & Accessories > Beds > Murphy Beds -Furniture > Beds & Accessories > Beds > Trundle Beds +Furniture > Beds & Accessories > Bed & Bed Frame Accessories +Furniture > Beds & Accessories > Beds & Bed Frames Furniture > Beds & Accessories > Headboards & Footboards Furniture > Beds & Accessories > Mattress Foundations Furniture > Beds & Accessories > Mattresses -Furniture > Beds & Accessories > Mattresses > Waterbeds Furniture > Benches Furniture > Benches > Kitchen & Dining Benches Furniture > Benches > Storage & Entryway Benches @@ -2501,11 +2002,11 @@ Furniture > Cabinets & Storage > Buffets & Sideboards Furniture > Cabinets & Storage > China Cabinets & Hutches Furniture > Cabinets & Storage > Dressers Furniture > Cabinets & Storage > File Cabinets +Furniture > Cabinets & Storage > Ironing Centers +Furniture > Cabinets & Storage > Kitchen Cabinets Furniture > Cabinets & Storage > Magazine Racks -Furniture > Cabinets & Storage > Media Storage -Furniture > Cabinets & Storage > Media Storage > Media Cabinets -Furniture > Cabinets & Storage > Media Storage > Media Racks & Towers -Furniture > Cabinets & Storage > Pantries +Furniture > Cabinets & Storage > Media Storage Cabinets & Racks +Furniture > Cabinets & Storage > Storage Cabinets & Lockers Furniture > Cabinets & Storage > Storage Chests Furniture > Cabinets & Storage > Storage Chests > Hope Chests Furniture > Cabinets & Storage > Storage Chests > Toy Chests @@ -2518,23 +2019,23 @@ Furniture > Carts & Islands Furniture > Carts & Islands > Kitchen & Dining Carts Furniture > Carts & Islands > Kitchen Islands Furniture > Chair Accessories +Furniture > Chair Accessories > Hanging Chair Replacement Parts Furniture > Chairs Furniture > Chairs > Arm Chairs, Recliners & Sleeper Chairs -Furniture > Chairs > Arm Chairs, Recliners & Sleeper Chairs > Arm Chairs -Furniture > Chairs > Arm Chairs, Recliners & Sleeper Chairs > Recliners -Furniture > Chairs > Arm Chairs, Recliners & Sleeper Chairs > Sleeper Chairs -Furniture > Chairs > Bar Stools Furniture > Chairs > Bean Bag Chairs Furniture > Chairs > Chaises Furniture > Chairs > Electric Massaging Chairs +Furniture > Chairs > Floor Chairs Furniture > Chairs > Folding Chairs & Stools Furniture > Chairs > Gaming Chairs Furniture > Chairs > Hanging Chairs Furniture > Chairs > Kitchen & Dining Room Chairs Furniture > Chairs > Rocking Chairs Furniture > Chairs > Slipper Chairs +Furniture > Chairs > Table & Bar Stools Furniture > Entertainment Centers & TV Stands Furniture > Furniture Sets +Furniture > Furniture Sets > Bathroom Furniture Sets Furniture > Furniture Sets > Bedroom Furniture Sets Furniture > Furniture Sets > Kitchen & Dining Furniture Sets Furniture > Furniture Sets > Living Room Furniture Sets @@ -2542,20 +2043,18 @@ Furniture > Futon Frames Furniture > Futon Pads Furniture > Futons Furniture > Office Furniture -Furniture > Office Furniture > Desk Hutches Furniture > Office Furniture > Desks -Furniture > Office Furniture > Office Chair Accessories Furniture > Office Furniture > Office Chairs -Furniture > Office Furniture > Office Chairs > Kneeling Chairs +Furniture > Office Furniture > Office Furniture Sets Furniture > Office Furniture > Workspace Tables Furniture > Office Furniture > Workspace Tables > Art & Drafting Tables Furniture > Office Furniture > Workspace Tables > Conference Room Tables -Furniture > Office Furniture > Workstation & Cubicle Accessories Furniture > Office Furniture > Workstations & Cubicles +Furniture > Office Furniture Accessories +Furniture > Office Furniture Accessories > Desk Parts & Accessories +Furniture > Office Furniture Accessories > Office Chair Accessories +Furniture > Office Furniture Accessories > Workstation & Cubicle Accessories Furniture > Ottomans -Furniture > Ottomans > Convertible Ottomans -Furniture > Ottomans > Glider Ottomans -Furniture > Ottomans > Storage Ottomans Furniture > Outdoor Furniture Furniture > Outdoor Furniture > Outdoor Beds Furniture > Outdoor Furniture > Outdoor Furniture Sets @@ -2563,6 +2062,7 @@ Furniture > Outdoor Furniture > Outdoor Ottomans Furniture > Outdoor Furniture > Outdoor Seating Furniture > Outdoor Furniture > Outdoor Seating > Outdoor Benches Furniture > Outdoor Furniture > Outdoor Seating > Outdoor Chairs +Furniture > Outdoor Furniture > Outdoor Seating > Outdoor Sectional Sofa Units Furniture > Outdoor Furniture > Outdoor Seating > Outdoor Sofas Furniture > Outdoor Furniture > Outdoor Seating > Sunloungers Furniture > Outdoor Furniture > Outdoor Storage Boxes @@ -2573,14 +2073,13 @@ Furniture > Room Divider Accessories Furniture > Room Dividers Furniture > Shelving Furniture > Shelving > Bookcases & Standing Shelves +Furniture > Shelving > Wall Shelves & Ledges Furniture > Shelving Accessories Furniture > Shelving Accessories > Replacement Shelves Furniture > Sofa Accessories Furniture > Sofa Accessories > Chair & Sofa Supports +Furniture > Sofa Accessories > Sectional Sofa Units Furniture > Sofas -Furniture > Sofas > Loveseats -Furniture > Sofas > Sectional Sofas -Furniture > Sofas > Sofabeds Furniture > Table Accessories Furniture > Table Accessories > Table Legs Furniture > Table Accessories > Table Tops @@ -2592,276 +2091,238 @@ Furniture > Tables > Accent Tables > Sofa Tables Furniture > Tables > Activity Tables Furniture > Tables > Folding Tables Furniture > Tables > Kitchen & Dining Room Tables -Furniture > Tables > Kitchen & Dining Room Tables > Hightop Tables +Furniture > Tables > Kotatsu Furniture > Tables > Nightstands Furniture > Tables > Poker & Game Tables Furniture > Tables > Sewing Machine Tables Hardware -Hardware > Adhesives, Coatings & Sealants -Hardware > Adhesives, Coatings & Sealants > Caulk -Hardware > Adhesives, Coatings & Sealants > Cements -Hardware > Adhesives, Coatings & Sealants > Coatings -Hardware > Adhesives, Coatings & Sealants > Glues -Hardware > Adhesives, Coatings & Sealants > Glues > Glitter Glue -Hardware > Adhesives, Coatings & Sealants > Glues > Glue Gun Sticks -Hardware > Adhesives, Coatings & Sealants > Glues > Glue Sticks -Hardware > Adhesives, Coatings & Sealants > Glues > Rubber Cement -Hardware > Adhesives, Coatings & Sealants > Glues > Super Glue -Hardware > Adhesives, Coatings & Sealants > Glues > White Glue -Hardware > Adhesives, Coatings & Sealants > Glues > Wood Glue -Hardware > Adhesives, Coatings & Sealants > Joint Compounds -Hardware > Adhesives, Coatings & Sealants > Sealants +Hardware > Building Consumables +Hardware > Building Consumables > Chemicals +Hardware > Building Consumables > Chemicals > Acid Neutralizers +Hardware > Building Consumables > Chemicals > Ammonia +Hardware > Building Consumables > Chemicals > Chimney Cleaners +Hardware > Building Consumables > Chemicals > Concrete & Masonry Cleaners +Hardware > Building Consumables > Chemicals > De-icers +Hardware > Building Consumables > Chemicals > Deck & Fence Cleaners +Hardware > Building Consumables > Chemicals > Drain Cleaners +Hardware > Building Consumables > Chemicals > Electrical Freeze Sprays +Hardware > Building Consumables > Chemicals > Lighter Fluid +Hardware > Building Consumables > Chemicals > Septic Tank & Cesspool Treatments +Hardware > Building Consumables > Hardware Glue & Adhesives +Hardware > Building Consumables > Hardware Tape +Hardware > Building Consumables > Lubricants +Hardware > Building Consumables > Masonry Consumables +Hardware > Building Consumables > Masonry Consumables > Bricks & Concrete Blocks +Hardware > Building Consumables > Masonry Consumables > Cement, Mortar & Concrete Mixes +Hardware > Building Consumables > Masonry Consumables > Grout +Hardware > Building Consumables > Painting Consumables +Hardware > Building Consumables > Painting Consumables > Paint +Hardware > Building Consumables > Painting Consumables > Paint Binders +Hardware > Building Consumables > Painting Consumables > Primers +Hardware > Building Consumables > Painting Consumables > Stains +Hardware > Building Consumables > Painting Consumables > Varnishes & Finishes +Hardware > Building Consumables > Plumbing Primer +Hardware > Building Consumables > Protective Coatings & Sealants +Hardware > Building Consumables > Solder & Flux +Hardware > Building Consumables > Solvents, Strippers & Thinners +Hardware > Building Consumables > Wall Patching Compounds & Plaster Hardware > Building Materials -Hardware > Building Materials > Bricks, Stones & Concrete -Hardware > Building Materials > Carpets Hardware > Building Materials > Countertops -Hardware > Building Materials > Countertops > Ceramic & Porcelain Countertops -Hardware > Building Materials > Countertops > Granite Countertops -Hardware > Building Materials > Countertops > Hardwood Countertops -Hardware > Building Materials > Countertops > Laminate Countertops -Hardware > Building Materials > Countertops > Marble Countertops -Hardware > Building Materials > Countertops > Vinyl Countertops +Hardware > Building Materials > Door Hardware +Hardware > Building Materials > Door Hardware > Door Bells & Chimes +Hardware > Building Materials > Door Hardware > Door Closers +Hardware > Building Materials > Door Hardware > Door Frames +Hardware > Building Materials > Door Hardware > Door Keyhole Escutcheons +Hardware > Building Materials > Door Hardware > Door Knobs & Handles +Hardware > Building Materials > Door Hardware > Door Knockers +Hardware > Building Materials > Door Hardware > Door Push Plates +Hardware > Building Materials > Door Hardware > Door Stops +Hardware > Building Materials > Door Hardware > Door Strikes Hardware > Building Materials > Doors Hardware > Building Materials > Doors > Garage Doors Hardware > Building Materials > Doors > Home Doors -Hardware > Building Materials > Doors > Home Doors > Screen Doors -Hardware > Building Materials > Doors > Utility Doors -Hardware > Building Materials > Doors > Utility Doors > Pet Doors -Hardware > Building Materials > Flooring -Hardware > Building Materials > Flooring > Artificial Turf -Hardware > Building Materials > Flooring > Ceramic & Porcelain Flooring -Hardware > Building Materials > Flooring > Granite Flooring -Hardware > Building Materials > Flooring > Hardwood Flooring -Hardware > Building Materials > Flooring > Laminate Flooring -Hardware > Building Materials > Flooring > Marble Flooring -Hardware > Building Materials > Flooring > Rubber Flooring -Hardware > Building Materials > Flooring > Vinyl Flooring +Hardware > Building Materials > Drywall +Hardware > Building Materials > Flooring & Carpet Hardware > Building Materials > Glass +Hardware > Building Materials > Handrails & Railing Systems Hardware > Building Materials > Hatches -Hardware > Building Materials > Lumber +Hardware > Building Materials > Insulation +Hardware > Building Materials > Lumber & Sheet Stock Hardware > Building Materials > Molding +Hardware > Building Materials > Rebar & Remesh +Hardware > Building Materials > Roofing +Hardware > Building Materials > Roofing > Gutter Accessories +Hardware > Building Materials > Roofing > Gutters +Hardware > Building Materials > Roofing > Roof Flashings +Hardware > Building Materials > Roofing > Roofing Shingles & Tiles Hardware > Building Materials > Shutters -Hardware > Building Materials > Sound Dampening Materials +Hardware > Building Materials > Siding +Hardware > Building Materials > Sound Dampening Panels & Foam Hardware > Building Materials > Staircases -Hardware > Building Materials > Tile -Hardware > Building Materials > Tile > Tile Countertops -Hardware > Building Materials > Tile > Tile Flooring +Hardware > Building Materials > Wall & Ceiling Tile Hardware > Building Materials > Wall Paneling +Hardware > Building Materials > Weather Stripping & Weatherization Supplies +Hardware > Building Materials > Window Hardware +Hardware > Building Materials > Window Hardware > Window Cranks +Hardware > Building Materials > Window Hardware > Window Frames Hardware > Building Materials > Windows -Hardware > Cabinetry -Hardware > Chemicals -Hardware > Chemicals > Acid Neutralizers -Hardware > Chemicals > Ammonia -Hardware > Chemicals > Chimney Cleaners -Hardware > Chemicals > Concrete & Masonry Cleaners -Hardware > Chemicals > De-icers -Hardware > Chemicals > Deck & Fence Cleaners -Hardware > Chemicals > Drain Cleaners -Hardware > Chemicals > Septic Tank & Cesspool Cleaners -Hardware > Electrical Supplies -Hardware > Electrical Supplies > Ballasts & Starters -Hardware > Electrical Supplies > Bypass Switches -Hardware > Electrical Supplies > Charge Controllers -Hardware > Electrical Supplies > Circuit Breaker Panels -Hardware > Electrical Supplies > Electrical Plug Caps -Hardware > Electrical Supplies > Electrical Switches -Hardware > Electrical Supplies > Electrical Switches > Light Switches -Hardware > Electrical Supplies > Electrical Timers -Hardware > Electrical Supplies > Electrical Wires -Hardware > Electrical Supplies > Extension Cord Accessories -Hardware > Electrical Supplies > Extension Cord Accessories > Extension Cord Connectors -Hardware > Electrical Supplies > Extension Cord Accessories > Extension Cord Reels & Winders -Hardware > Electrical Supplies > Extension Cords -Hardware > Electrical Supplies > Heat-Shrink Tubing -Hardware > Electrical Supplies > Mount Boxes & Brackets -Hardware > Electrical Supplies > Relays -Hardware > Electrical Supplies > Wall Plates -Hardware > Electrical Supplies > Wall Sockets -Hardware > Electrical Supplies > Wire Binding Spools -Hardware > Electrical Supplies > Wire Caps & Nuts -Hardware > Generators +Hardware > Fencing & Barriers +Hardware > Fencing & Barriers > Fence & Gate Accessories +Hardware > Fencing & Barriers > Fence Panels +Hardware > Fencing & Barriers > Fence Pickets +Hardware > Fencing & Barriers > Fence Posts & Rails +Hardware > Fencing & Barriers > Garden Borders & Edging +Hardware > Fencing & Barriers > Gates +Hardware > Fencing & Barriers > Lattice +Hardware > Fencing & Barriers > Safety & Crowd Control Barriers +Hardware > Fuel Containers & Tanks Hardware > Hardware Accessories -Hardware > Hardware Accessories > Brackets -Hardware > Hardware Accessories > Bungee Cords +Hardware > Hardware Accessories > Brackets & Reinforcement Braces Hardware > Hardware Accessories > Cabinet Hardware +Hardware > Hardware Accessories > Cabinet Hardware > Cabinet & Furniture Keyhole Escutcheons Hardware > Hardware Accessories > Cabinet Hardware > Cabinet Backplates Hardware > Hardware Accessories > Cabinet Hardware > Cabinet Catches Hardware > Hardware Accessories > Cabinet Hardware > Cabinet Doors Hardware > Hardware Accessories > Cabinet Hardware > Cabinet Knobs & Handles -Hardware > Hardware Accessories > Cabinet Hardware > Cabinet Locks -Hardware > Hardware Accessories > Chains +Hardware > Hardware Accessories > Casters +Hardware > Hardware Accessories > Chain, Wire & Rope +Hardware > Hardware Accessories > Chain, Wire & Rope > Bungee Cords +Hardware > Hardware Accessories > Chain, Wire & Rope > Chains +Hardware > Hardware Accessories > Chain, Wire & Rope > Pull Chains +Hardware > Hardware Accessories > Chain, Wire & Rope > Ropes & Hardware Cable +Hardware > Hardware Accessories > Chain, Wire & Rope > Tie Down Straps +Hardware > Hardware Accessories > Chain, Wire & Rope > Twine +Hardware > Hardware Accessories > Chain, Wire & Rope > Utility Wire Hardware > Hardware Accessories > Coils Hardware > Hardware Accessories > Concrete Molds -Hardware > Hardware Accessories > Controls -Hardware > Hardware Accessories > Controls > Control Panels -Hardware > Hardware Accessories > Controls > HVAC Controls -Hardware > Hardware Accessories > Controls > Thermostats -Hardware > Hardware Accessories > Door Hardware -Hardware > Hardware Accessories > Door Hardware > Door Bells & Chimes -Hardware > Hardware Accessories > Door Hardware > Door Closers -Hardware > Hardware Accessories > Door Hardware > Door Knobs & Handles -Hardware > Hardware Accessories > Door Hardware > Door Knockers -Hardware > Hardware Accessories > Door Hardware > Door Stops -Hardware > Hardware Accessories > Door Hardware > Door Strikes Hardware > Hardware Accessories > Dowel Pins & Rods +Hardware > Hardware Accessories > Drawer Slides Hardware > Hardware Accessories > Drop Cloths -Hardware > Hardware Accessories > Drywall Anchors Hardware > Hardware Accessories > Filters & Screens Hardware > Hardware Accessories > Flagging & Caution Tape Hardware > Hardware Accessories > Gas Hoses -Hardware > Hardware Accessories > Hardware Tape -Hardware > Hardware Accessories > Hardware Tape > Copper Tape -Hardware > Hardware Accessories > Hardware Tape > Drywall Tape -Hardware > Hardware Accessories > Hardware Tape > Duct Tape -Hardware > Hardware Accessories > Hardware Tape > Electrical Tape -Hardware > Hardware Accessories > Hardware Tape > Foil Tape -Hardware > Hardware Accessories > Hardware Tape > Gaffers Tape -Hardware > Hardware Accessories > Hardware Tape > Heat Tape -Hardware > Hardware Accessories > Hardware Tape > Masking Tape -Hardware > Hardware Accessories > Hardware Tape > Teflon Tape +Hardware > Hardware Accessories > Ground Spikes +Hardware > Hardware Accessories > Hardware Fasteners +Hardware > Hardware Accessories > Hardware Fasteners > Drywall Anchors +Hardware > Hardware Accessories > Hardware Fasteners > Nails +Hardware > Hardware Accessories > Hardware Fasteners > Nuts & Bolts +Hardware > Hardware Accessories > Hardware Fasteners > Rivets +Hardware > Hardware Accessories > Hardware Fasteners > Screw Posts +Hardware > Hardware Accessories > Hardware Fasteners > Screws +Hardware > Hardware Accessories > Hardware Fasteners > Threaded Rods +Hardware > Hardware Accessories > Hardware Fasteners > Washers Hardware > Hardware Accessories > Hinges -Hardware > Hardware Accessories > Latches -Hardware > Hardware Accessories > Lubricants +Hardware > Hardware Accessories > Hooks, Buckles & Fasteners +Hardware > Hardware Accessories > Hooks, Buckles & Fasteners > Chain Connectors & Links +Hardware > Hardware Accessories > Hooks, Buckles & Fasteners > Gear Ties +Hardware > Hardware Accessories > Hooks, Buckles & Fasteners > Lifting Hooks, Clamps & Shackles +Hardware > Hardware Accessories > Hooks, Buckles & Fasteners > Utility Buckles Hardware > Hardware Accessories > Lubrication Hoses -Hardware > Hardware Accessories > Nails -Hardware > Hardware Accessories > Nuts & Bolts +Hardware > Hardware Accessories > Metal Casting Molds +Hardware > Hardware Accessories > Moving & Soundproofing Blankets & Covers Hardware > Hardware Accessories > Pneumatic Hoses -Hardware > Hardware Accessories > Pull Chains -Hardware > Hardware Accessories > Pulleys -Hardware > Hardware Accessories > Rivets -Hardware > Hardware Accessories > Rope -Hardware > Hardware Accessories > Screw Posts -Hardware > Hardware Accessories > Screws -Hardware > Hardware Accessories > Screws > Drywall Screws -Hardware > Hardware Accessories > Screws > Metal Screws -Hardware > Hardware Accessories > Screws > Wood Screws -Hardware > Hardware Accessories > Solder & Flux +Hardware > Hardware Accessories > Post Base Plates +Hardware > Hardware Accessories > Springs Hardware > Hardware Accessories > Tarps -Hardware > Hardware Accessories > Tie Down Straps Hardware > Hardware Accessories > Tool Storage & Organization Hardware > Hardware Accessories > Tool Storage & Organization > Garden Hose Storage -Hardware > Hardware Accessories > Tool Storage & Organization > Tool & Duty Belts +Hardware > Hardware Accessories > Tool Storage & Organization > Tool & Equipment Belts Hardware > Hardware Accessories > Tool Storage & Organization > Tool Bags Hardware > Hardware Accessories > Tool Storage & Organization > Tool Boxes Hardware > Hardware Accessories > Tool Storage & Organization > Tool Cabinets & Chests +Hardware > Hardware Accessories > Tool Storage & Organization > Tool Organizer Liners & Inserts Hardware > Hardware Accessories > Tool Storage & Organization > Tool Sheaths Hardware > Hardware Accessories > Tool Storage & Organization > Work Benches -Hardware > Hardware Accessories > Twine -Hardware > Hardware Accessories > Utility Wire -Hardware > Hardware Accessories > Vents & Flues -Hardware > Hardware Accessories > Washers -Hardware > Hardware Accessories > Wood Biscuits -Hardware > Hardware Torches -Hardware > Home Fencing -Hardware > Home Fencing > Fence Pickets -Hardware > Home Fencing > Fences -Hardware > Home Fencing > Fences > Wire Fencing -Hardware > Home Fencing > Fences > Wire Fencing > Barbed & Razor Wire -Hardware > Home Fencing > Fences > Wire Fencing > Chain Link Fencing -Hardware > Home Fencing > Fencing Posts -Hardware > Home Fencing > Gates -Hardware > Insulation -Hardware > Insulation > Building Insulation -Hardware > Insulation > Pipe Insulation -Hardware > Insulation > Window & Door Insulation -Hardware > Key Blanks -Hardware > Locks & Locksmithing -Hardware > Locks & Locksmithing > Cylinder Locks -Hardware > Locks & Locksmithing > Deadbolt Locks -Hardware > Locks & Locksmithing > Key Card Entry Systems -Hardware > Locks & Locksmithing > Padlocks -Hardware > Locks & Locksmithing > Pocket Door Locks -Hardware > Painting & Wall Covering Supplies -Hardware > Painting & Wall Covering Supplies > Finishes -Hardware > Painting & Wall Covering Supplies > Paint -Hardware > Painting & Wall Covering Supplies > Paint Binders -Hardware > Painting & Wall Covering Supplies > Paint Strippers -Hardware > Painting & Wall Covering Supplies > Primers -Hardware > Painting & Wall Covering Supplies > Solvents -Hardware > Painting & Wall Covering Supplies > Stains -Hardware > Painting & Wall Covering Supplies > Varnishes -Hardware > Painting & Wall Covering Supplies > Wallpaper +Hardware > Hardware Accessories > Wall Jacks & Braces +Hardware > Hardware Pumps +Hardware > Hardware Pumps > Home Appliance Pumps +Hardware > Hardware Pumps > Pool, Fountain & Pond Pumps +Hardware > Hardware Pumps > Sprinkler, Booster & Irrigation System Pumps +Hardware > Hardware Pumps > Sump, Sewage & Effluent Pumps +Hardware > Hardware Pumps > Utility Pumps +Hardware > Hardware Pumps > Well Pumps & Systems +Hardware > Heating, Ventilation & Air Conditioning +Hardware > Heating, Ventilation & Air Conditioning > Air & Filter Dryers +Hardware > Heating, Ventilation & Air Conditioning > Air Ducts +Hardware > Heating, Ventilation & Air Conditioning > HVAC Controls +Hardware > Heating, Ventilation & Air Conditioning > HVAC Controls > Control Panels +Hardware > Heating, Ventilation & Air Conditioning > HVAC Controls > Humidistats +Hardware > Heating, Ventilation & Air Conditioning > HVAC Controls > Thermostats +Hardware > Heating, Ventilation & Air Conditioning > Vents & Flues +Hardware > Locks & Keys +Hardware > Locks & Keys > Key Blanks +Hardware > Locks & Keys > Key Caps +Hardware > Locks & Keys > Key Card Entry Systems +Hardware > Locks & Keys > Locks & Latches Hardware > Plumbing -Hardware > Plumbing > Ballcocks & Flappers -Hardware > Plumbing > Drain Accessories -Hardware > Plumbing > Drain Accessories > Drain Frames -Hardware > Plumbing > Drain Accessories > Drain Liners -Hardware > Plumbing > Drain Accessories > Drain Openers -Hardware > Plumbing > Drain Accessories > Drain Rods -Hardware > Plumbing > Drain Accessories > Plumbing Wastes -Hardware > Plumbing > Fuel Lines & Accessories -Hardware > Plumbing > Hoses -Hardware > Plumbing > Nozzles -Hardware > Plumbing > Plumbing Fittings -Hardware > Plumbing > Plumbing Fittings > Flanges -Hardware > Plumbing > Plumbing Fittings > Pipe Adaptors & Bushings -Hardware > Plumbing > Plumbing Fittings > Pipe Caps & Plugs -Hardware > Plumbing > Plumbing Fittings > Pipe Clamps -Hardware > Plumbing > Plumbing Fittings > Pipe Connectors -Hardware > Plumbing > Plumbing Fittings > Plumbing Gaskets +Hardware > Plumbing > Plumbing Fittings & Supports +Hardware > Plumbing > Plumbing Fittings & Supports > Gaskets & O-Rings +Hardware > Plumbing > Plumbing Fittings & Supports > In-Wall Carriers & Mounting Frames +Hardware > Plumbing > Plumbing Fittings & Supports > Nozzles +Hardware > Plumbing > Plumbing Fittings & Supports > Pipe Adapters & Bushings +Hardware > Plumbing > Plumbing Fittings & Supports > Pipe Caps & Plugs +Hardware > Plumbing > Plumbing Fittings & Supports > Pipe Connectors +Hardware > Plumbing > Plumbing Fittings & Supports > Plumbing Flanges +Hardware > Plumbing > Plumbing Fittings & Supports > Plumbing Pipe Clamps +Hardware > Plumbing > Plumbing Fittings & Supports > Plumbing Regulators +Hardware > Plumbing > Plumbing Fittings & Supports > Plumbing Valves +Hardware > Plumbing > Plumbing Fixture Hardware & Parts +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Bathtub Accessories +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Bathtub Accessories > Bathtub Bases & Feet +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Bathtub Accessories > Bathtub Skirts +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Bathtub Accessories > Bathtub Spouts +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Drain Covers & Strainers +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Drain Frames +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Drain Liners +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Drain Openers +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Drain Rods +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Plumbing Traps +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Plumbing Wastes +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drains +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Faucet Accessories +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Faucet Accessories > Faucet Aerators +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Faucet Accessories > Faucet Handles & Controls +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Fixture Plates +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Bathtub & Shower Jets +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Electric & Power Showers +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Arms & Connectors +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Bases +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Columns +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Doors & Enclosures +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Heads +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Walls & Surrounds +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Water Filters +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Sink Accessories +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Sink Accessories > Sink Legs +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Ballcocks & Flappers +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Bidet Faucets & Sprayers +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet & Bidet Seats +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Seat Covers +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Seat Lid Covers +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Tank Covers +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Tank Levers +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Tanks +Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Trim Hardware > Plumbing > Plumbing Fixtures -Hardware > Plumbing > Plumbing Fixtures > Bathtub Accessories -Hardware > Plumbing > Plumbing Fixtures > Bathtub Accessories > Bathtub Skirts -Hardware > Plumbing > Plumbing Fixtures > Bathtub Accessories > Bathtub Spouts +Hardware > Plumbing > Plumbing Fixtures > Bathroom Suites Hardware > Plumbing > Plumbing Fixtures > Bathtubs -Hardware > Plumbing > Plumbing Fixtures > Faucet Accessories Hardware > Plumbing > Plumbing Fixtures > Faucets -Hardware > Plumbing > Plumbing Fixtures > Faucets > Pre-Rinse Faucets -Hardware > Plumbing > Plumbing Fixtures > Fixture Plates -Hardware > Plumbing > Plumbing Fixtures > Shower -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Arm Diverters -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Arm Mounts -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Bars -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Bases -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Columns -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Doors & Enclosures -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Heads -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Hoses -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Rods -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Stalls & Kits -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Walls & Surrounds -Hardware > Plumbing > Plumbing Fixtures > Shower > Shower Water Filters -Hardware > Plumbing > Plumbing Fixtures > Sink Accessories -Hardware > Plumbing > Plumbing Fixtures > Sink Accessories > Sink Legs +Hardware > Plumbing > Plumbing Fixtures > Shower Stalls & Kits Hardware > Plumbing > Plumbing Fixtures > Sinks Hardware > Plumbing > Plumbing Fixtures > Sinks > Bathroom Sinks Hardware > Plumbing > Plumbing Fixtures > Sinks > Kitchen & Utility Sinks -Hardware > Plumbing > Plumbing Fixtures > Toilet & Bidet Accessories -Hardware > Plumbing > Plumbing Fixtures > Toilet & Bidet Accessories > Toilet & Bidet Seats -Hardware > Plumbing > Plumbing Fixtures > Toilet & Bidet Accessories > Toilet Seat Covers -Hardware > Plumbing > Plumbing Fixtures > Toilet & Bidet Accessories > Toilet Seat Lid Covers -Hardware > Plumbing > Plumbing Fixtures > Toilet & Bidet Accessories > Toilet Tank Covers -Hardware > Plumbing > Plumbing Fixtures > Toilet & Bidet Accessories > Toilet Tank Levers -Hardware > Plumbing > Plumbing Fixtures > Toilet & Bidet Accessories > Toilet Tanks -Hardware > Plumbing > Plumbing Fixtures > Toilet & Bidet Accessories > Toilet Trim Hardware > Plumbing > Plumbing Fixtures > Toilets & Bidets Hardware > Plumbing > Plumbing Fixtures > Toilets & Bidets > Bidets Hardware > Plumbing > Plumbing Fixtures > Toilets & Bidets > Toilets Hardware > Plumbing > Plumbing Fixtures > Toilets & Bidets > Urinals +Hardware > Plumbing > Plumbing Hoses & Supply Lines Hardware > Plumbing > Plumbing Pipes -Hardware > Plumbing > Plumbing Pipes > Piping Nipples -Hardware > Plumbing > Plumbing Pipes > Push-Fit Pipes -Hardware > Plumbing > Plumbing Pipes > Steel Pipes -Hardware > Plumbing > Plumbing Pumps -Hardware > Plumbing > Plumbing Regulators -Hardware > Plumbing > Plumbing Stoppers -Hardware > Plumbing > Plumbing Taps -Hardware > Plumbing > Plumbing Taps > Gas Taps -Hardware > Plumbing > Plumbing Taps > Hose Bibbs -Hardware > Plumbing > Plumbing Taps > Water Taps -Hardware > Plumbing > Plumbing Valves -Hardware > Plumbing > Plumbing Valves > Ball Valves -Hardware > Plumbing > Repair Kits -Hardware > Plumbing > Repair Kits > Tube Repair Kits -Hardware > Plumbing > Thermocouples -Hardware > Plumbing > Traps & Strainers -Hardware > Plumbing > Traps & Strainers > Bath Traps -Hardware > Plumbing > Traps & Strainers > Bottle Traps -Hardware > Plumbing > Traps & Strainers > Shower Traps -Hardware > Plumbing > Tube Cleaners +Hardware > Plumbing > Plumbing Repair Kits Hardware > Plumbing > Water Dispensing & Filtration Hardware > Plumbing > Water Dispensing & Filtration > In-Line Water Filters -Hardware > Plumbing > Water Dispensing & Filtration > In-Line Water Filters > Refrigerator Water Filters Hardware > Plumbing > Water Dispensing & Filtration > Water Dispensers Hardware > Plumbing > Water Dispensing & Filtration > Water Dispensers > Drinking Fountains Hardware > Plumbing > Water Dispensing & Filtration > Water Dispensers > Water Chillers @@ -2869,61 +2330,88 @@ Hardware > Plumbing > Water Dispensing & Filtration > Water Distillers Hardware > Plumbing > Water Dispensing & Filtration > Water Filtration Accessories Hardware > Plumbing > Water Dispensing & Filtration > Water Filtration Accessories > Water Filter Cartridges Hardware > Plumbing > Water Dispensing & Filtration > Water Filtration Accessories > Water Filter Housings -Hardware > Plumbing > Water Dispensing & Filtration > Water Softener Accessories -Hardware > Plumbing > Water Dispensing & Filtration > Water Softener Accessories > Water Softener Salt +Hardware > Plumbing > Water Dispensing & Filtration > Water Softener Salt Hardware > Plumbing > Water Dispensing & Filtration > Water Softeners Hardware > Plumbing > Water Levelers Hardware > Plumbing > Water Timers Hardware > Plumbing > Well Supplies -Hardware > Renewable Energy -Hardware > Renewable Energy > Solar Energy -Hardware > Renewable Energy > Solar Energy > Solar Energy Kits -Hardware > Renewable Energy > Solar Energy > Solar Panels -Hardware > Renewable Energy > Wind Power -Hardware > Renewable Energy > Wind Power > Wind Turbines -Hardware > Roofing -Hardware > Roofing > Gutter Accessories -Hardware > Roofing > Gutters -Hardware > Roofing > Roof Flashings -Hardware > Shop Stools +Hardware > Power & Electrical Supplies +Hardware > Power & Electrical Supplies > Armatures, Rotors & Stators +Hardware > Power & Electrical Supplies > Ballasts & Starters +Hardware > Power & Electrical Supplies > Carbon Brushes +Hardware > Power & Electrical Supplies > Circuit Breaker Panels +Hardware > Power & Electrical Supplies > Conduit & Housings +Hardware > Power & Electrical Supplies > Conduit & Housings > Electrical Conduit +Hardware > Power & Electrical Supplies > Conduit & Housings > Heat-Shrink Tubing +Hardware > Power & Electrical Supplies > Electrical Motors +Hardware > Power & Electrical Supplies > Electrical Mount Boxes & Brackets +Hardware > Power & Electrical Supplies > Electrical Plug Caps +Hardware > Power & Electrical Supplies > Electrical Switches +Hardware > Power & Electrical Supplies > Electrical Switches > Light Switches +Hardware > Power & Electrical Supplies > Electrical Switches > Specialty Electrical Switches & Relays +Hardware > Power & Electrical Supplies > Electrical Wires & Cable +Hardware > Power & Electrical Supplies > Extension Cord Accessories +Hardware > Power & Electrical Supplies > Extension Cords +Hardware > Power & Electrical Supplies > Generator Accessories +Hardware > Power & Electrical Supplies > Generators +Hardware > Power & Electrical Supplies > Home Automation Kits +Hardware > Power & Electrical Supplies > Phone & Data Jacks +Hardware > Power & Electrical Supplies > Power Converters +Hardware > Power & Electrical Supplies > Power Inlets +Hardware > Power & Electrical Supplies > Power Inverters +Hardware > Power & Electrical Supplies > Power Outlets & Sockets +Hardware > Power & Electrical Supplies > Solar Energy Kits +Hardware > Power & Electrical Supplies > Solar Panels +Hardware > Power & Electrical Supplies > Voltage Transformers & Regulators +Hardware > Power & Electrical Supplies > Wall Plates & Covers +Hardware > Power & Electrical Supplies > Wall Socket Controls & Sensors +Hardware > Power & Electrical Supplies > Wire Caps & Nuts +Hardware > Power & Electrical Supplies > Wire Terminals & Connectors +Hardware > Small Engines Hardware > Storage Tanks -Hardware > Storage Tanks > Food Tanks -Hardware > Storage Tanks > Oil Tanks -Hardware > Storage Tanks > Water Tanks Hardware > Tool Accessories -Hardware > Tool Accessories > Air Brush Accessories +Hardware > Tool Accessories > Abrasive Blaster Accessories +Hardware > Tool Accessories > Abrasive Blaster Accessories > Sandblasting Cabinets Hardware > Tool Accessories > Axe Accessories +Hardware > Tool Accessories > Axe Accessories > Axe Handles Hardware > Tool Accessories > Axe Accessories > Axe Heads -Hardware > Tool Accessories > Drill Accessories -Hardware > Tool Accessories > Drill Accessories > Drill Bit Extensions -Hardware > Tool Accessories > Drill Accessories > Drill Bit Sharpeners -Hardware > Tool Accessories > Drill Accessories > Drill Bits -Hardware > Tool Accessories > Drill Accessories > Hole Saws +Hardware > Tool Accessories > Cutter Accessories +Hardware > Tool Accessories > Cutter Accessories > Nibbler Dies +Hardware > Tool Accessories > Drill & Screwdriver Accessories +Hardware > Tool Accessories > Drill & Screwdriver Accessories > Drill & Screwdriver Bits +Hardware > Tool Accessories > Drill & Screwdriver Accessories > Drill Bit Extensions +Hardware > Tool Accessories > Drill & Screwdriver Accessories > Drill Bit Sharpeners +Hardware > Tool Accessories > Drill & Screwdriver Accessories > Drill Chucks +Hardware > Tool Accessories > Drill & Screwdriver Accessories > Drill Stands & Guides +Hardware > Tool Accessories > Drill & Screwdriver Accessories > Hole Saws Hardware > Tool Accessories > Driver Accessories Hardware > Tool Accessories > Flashlight Accessories -Hardware > Tool Accessories > Generator Accessories -Hardware > Tool Accessories > Generator Accessories > Generator Covers -Hardware > Tool Accessories > Generator Accessories > Generator Replacement Parts +Hardware > Tool Accessories > Grinder Accessories +Hardware > Tool Accessories > Grinder Accessories > Grinding Wheels & Points Hardware > Tool Accessories > Hammer Accessories Hardware > Tool Accessories > Hammer Accessories > Air Hammer Accessories +Hardware > Tool Accessories > Hammer Accessories > Hammer Handles Hardware > Tool Accessories > Hammer Accessories > Hammer Heads -Hardware > Tool Accessories > Hammer Accessories > Hammer Wedges Hardware > Tool Accessories > Industrial Staples Hardware > Tool Accessories > Jigs Hardware > Tool Accessories > Magnetizers & Demagnetizers +Hardware > Tool Accessories > Mattock & Pickaxe Accessories +Hardware > Tool Accessories > Mattock & Pickaxe Accessories > Mattock & Pickaxe Handles Hardware > Tool Accessories > Measuring Tool & Sensor Accessories +Hardware > Tool Accessories > Measuring Tool & Sensor Accessories > Electrical Testing Tool Accessories Hardware > Tool Accessories > Measuring Tool & Sensor Accessories > Gas Detector Accessories -Hardware > Tool Accessories > Measuring Tool & Sensor Accessories > Metal & Voltage Detector Accessories +Hardware > Tool Accessories > Measuring Tool & Sensor Accessories > Measuring Scale Accessories Hardware > Tool Accessories > Measuring Tool & Sensor Accessories > Multimeter Accessories +Hardware > Tool Accessories > Mixing Tool Paddles Hardware > Tool Accessories > Paint Tool Accessories +Hardware > Tool Accessories > Paint Tool Accessories > Airbrush Accessories +Hardware > Tool Accessories > Paint Tool Accessories > Paint Brush Cleaning Solutions Hardware > Tool Accessories > Paint Tool Accessories > Paint Roller Accessories Hardware > Tool Accessories > Power Tool Batteries Hardware > Tool Accessories > Power Tool Chargers Hardware > Tool Accessories > Router Accessories Hardware > Tool Accessories > Router Accessories > Router Bits Hardware > Tool Accessories > Router Accessories > Router Tables -Hardware > Tool Accessories > Sandblasting Accessories -Hardware > Tool Accessories > Sandblasting Accessories > Sandblasting Cabinets Hardware > Tool Accessories > Sanding Accessories Hardware > Tool Accessories > Sanding Accessories > Sandpaper & Sanding Sponges Hardware > Tool Accessories > Saw Accessories @@ -2932,60 +2420,42 @@ Hardware > Tool Accessories > Saw Accessories > Handheld Circular Saw Accessorie Hardware > Tool Accessories > Saw Accessories > Jigsaw Accessories Hardware > Tool Accessories > Saw Accessories > Miter Saw Accessories Hardware > Tool Accessories > Saw Accessories > Table Saw Accessories -Hardware > Tool Accessories > Screwdriver Accessories -Hardware > Tool Accessories > Screwdriver Accessories > Screwdriver Tips Hardware > Tool Accessories > Shaper Accessories Hardware > Tool Accessories > Shaper Accessories > Shaper Cutters Hardware > Tool Accessories > Soldering Iron Accessories Hardware > Tool Accessories > Soldering Iron Accessories > Soldering Iron Stands Hardware > Tool Accessories > Soldering Iron Accessories > Soldering Iron Tips Hardware > Tool Accessories > Tool Blades +Hardware > Tool Accessories > Tool Blades > Cutter & Scraper Blades Hardware > Tool Accessories > Tool Blades > Saw Blades -Hardware > Tool Accessories > Tool Blades > Utility Knife Blades -Hardware > Tool Accessories > Tool Handles -Hardware > Tool Accessories > Tool Handles > Axe Handles -Hardware > Tool Accessories > Tool Handles > Hammer Handles +Hardware > Tool Accessories > Tool Handle Wedges +Hardware > Tool Accessories > Tool Safety Tethers Hardware > Tool Accessories > Tool Sockets Hardware > Tool Accessories > Tool Stands Hardware > Tool Accessories > Tool Stands > Saw Stands +Hardware > Tool Accessories > Wedge Tools +Hardware > Tool Accessories > Welding Accessories Hardware > Tools +Hardware > Tools > Abrasive Blasters Hardware > Tools > Anvils -Hardware > Tools > Awls Hardware > Tools > Axes -Hardware > Tools > Benders -Hardware > Tools > Blowguns -Hardware > Tools > Brushes -Hardware > Tools > Brushes > Airbrushes -Hardware > Tools > Brushes > Chimney Brushes -Hardware > Tools > Brushes > Paint Brushes -Hardware > Tools > Brushes > Pipe Brushes Hardware > Tools > Carpentry Jointers -Hardware > Tools > Carving Tools -Hardware > Tools > Carving Tools > Carving Spoons -Hardware > Tools > Carving Tools > Chisels -Hardware > Tools > Carving Tools > Gouges -Hardware > Tools > Carving Tools > Wood Carving Knives +Hardware > Tools > Carving Chisels & Gouges Hardware > Tools > Caulking Tools -Hardware > Tools > Caulking Tools > Caulking Guns -Hardware > Tools > Caulking Tools > Caulking Irons -Hardware > Tools > Caulking Tools > Caulking Mallets +Hardware > Tools > Chimney Brushes Hardware > Tools > Compactors Hardware > Tools > Compressors -Hardware > Tools > Compressors > Air Compressors -Hardware > Tools > Compressors > Gas Compressors Hardware > Tools > Concrete Brooms -Hardware > Tools > Crowbars Hardware > Tools > Cutters Hardware > Tools > Cutters > Bolt Cutters Hardware > Tools > Cutters > Glass Cutters -Hardware > Tools > Cutters > Nibblers +Hardware > Tools > Cutters > Handheld Metal Shears & Nibblers Hardware > Tools > Cutters > Nippers Hardware > Tools > Cutters > Pipe Cutters Hardware > Tools > Cutters > Rebar Cutters Hardware > Tools > Cutters > Tile & Shingle Cutters Hardware > Tools > Cutters > Utility Knives Hardware > Tools > Deburrers -Hardware > Tools > Die Sets Hardware > Tools > Dollies & Hand Trucks Hardware > Tools > Drills Hardware > Tools > Drills > Augers @@ -2994,90 +2464,70 @@ Hardware > Tools > Drills > Handheld Power Drills Hardware > Tools > Drills > Mortisers Hardware > Tools > Drills > Pneumatic Drills Hardware > Tools > Electrician Fish Tape -Hardware > Tools > Flashlights -Hardware > Tools > Flashlights > Headlamps -Hardware > Tools > Glue Guns +Hardware > Tools > Flashlights & Headlamps Hardware > Tools > Grease Guns Hardware > Tools > Grinders Hardware > Tools > Grips -Hardware > Tools > Hammering -Hardware > Tools > Hammering > Air Hammers -Hardware > Tools > Hammering > Automatic Hammers -Hardware > Tools > Hammering > Hammers -Hardware > Tools > Hammering > Hammers > Mallets -Hardware > Tools > Hammering > Hammers > Sledgehammers -Hardware > Tools > Hammering > Jackhammers -Hardware > Tools > Hardware Shears +Hardware > Tools > Hammers +Hardware > Tools > Hammers > Manual Hammers +Hardware > Tools > Hammers > Powered Hammers +Hardware > Tools > Handheld Power Mixers +Hardware > Tools > Hardware Torches Hardware > Tools > Heat Guns -Hardware > Tools > Hoisting -Hardware > Tools > Hoisting > Air Casters -Hardware > Tools > Hoisting > Buckhoists -Hardware > Tools > Hoisting > Chainhoists -Hardware > Tools > Hoisting > Jack Lifts -Hardware > Tools > Hoisting > Pallet Jacks -Hardware > Tools > Hoisting > Wire Hoists Hardware > Tools > Impact Wrenches & Drivers Hardware > Tools > Industrial Vibrators Hardware > Tools > Inspection Mirrors Hardware > Tools > Ladders & Scaffolding Hardware > Tools > Ladders & Scaffolding > Ladder Carts Hardware > Tools > Ladders & Scaffolding > Ladders -Hardware > Tools > Ladders & Scaffolding > Ladders > Aluminum Ladders -Hardware > Tools > Ladders & Scaffolding > Ladders > Wooden Ladders Hardware > Tools > Ladders & Scaffolding > Scaffolding Hardware > Tools > Ladders & Scaffolding > Step Stools Hardware > Tools > Ladders & Scaffolding > Work Platforms Hardware > Tools > Lathes -Hardware > Tools > Lifting Magnets Hardware > Tools > Light Bulb Changers +Hardware > Tools > Lighters & Matches Hardware > Tools > Log Splitters +Hardware > Tools > Magnetic Sweepers Hardware > Tools > Marking Tools -Hardware > Tools > Marking Tools > Carpenter Crayons & Pencils -Hardware > Tools > Marking Tools > Chalk Lines -Hardware > Tools > Marking Tools > Marking Chisels -Hardware > Tools > Marking Tools > Marking Knives Hardware > Tools > Masonry Tools Hardware > Tools > Masonry Tools > Brick Tools Hardware > Tools > Masonry Tools > Cement Mixers Hardware > Tools > Masonry Tools > Construction Lines -Hardware > Tools > Masonry Tools > Edgers Hardware > Tools > Masonry Tools > Floats Hardware > Tools > Masonry Tools > Grout Sponges +Hardware > Tools > Masonry Tools > Masonry Edgers & Groovers Hardware > Tools > Masonry Tools > Masonry Jointers Hardware > Tools > Masonry Tools > Masonry Trowels Hardware > Tools > Masonry Tools > Power Trowels +Hardware > Tools > Mattocks & Pickaxes Hardware > Tools > Measuring Tools & Sensors Hardware > Tools > Measuring Tools & Sensors > Air Quality Meters Hardware > Tools > Measuring Tools & Sensors > Altimeters +Hardware > Tools > Measuring Tools & Sensors > Anemometers Hardware > Tools > Measuring Tools & Sensors > Barometers -Hardware > Tools > Measuring Tools & Sensors > Cable Testers Hardware > Tools > Measuring Tools & Sensors > Calipers Hardware > Tools > Measuring Tools & Sensors > Cruising Rods -Hardware > Tools > Measuring Tools & Sensors > Diagnostic Thermal Cameras Hardware > Tools > Measuring Tools & Sensors > Distance Meters Hardware > Tools > Measuring Tools & Sensors > Dividers +Hardware > Tools > Measuring Tools & Sensors > Electrical Testing Tools Hardware > Tools > Measuring Tools & Sensors > Flow Meters & Controllers Hardware > Tools > Measuring Tools & Sensors > Gas Detectors Hardware > Tools > Measuring Tools & Sensors > Gauges Hardware > Tools > Measuring Tools & Sensors > Geiger Counters Hardware > Tools > Measuring Tools & Sensors > Hygrometers +Hardware > Tools > Measuring Tools & Sensors > Infrared Thermometers Hardware > Tools > Measuring Tools & Sensors > Knife Guides -Hardware > Tools > Measuring Tools & Sensors > Leak Detectors Hardware > Tools > Measuring Tools & Sensors > Levels Hardware > Tools > Measuring Tools & Sensors > Levels > Bubble Levels Hardware > Tools > Measuring Tools & Sensors > Levels > Laser Levels Hardware > Tools > Measuring Tools & Sensors > Levels > Sight Levels +Hardware > Tools > Measuring Tools & Sensors > Measuring Scales Hardware > Tools > Measuring Tools & Sensors > Measuring Wheels -Hardware > Tools > Measuring Tools & Sensors > Metal & Voltage Detectors Hardware > Tools > Measuring Tools & Sensors > Moisture Meters -Hardware > Tools > Measuring Tools & Sensors > Multimeters -Hardware > Tools > Measuring Tools & Sensors > Pipe Locators -Hardware > Tools > Measuring Tools & Sensors > Pressure Sensors & Transducers Hardware > Tools > Measuring Tools & Sensors > Probes & Finders Hardware > Tools > Measuring Tools & Sensors > Protractors Hardware > Tools > Measuring Tools & Sensors > Rebar Locators Hardware > Tools > Measuring Tools & Sensors > Rulers -Hardware > Tools > Measuring Tools & Sensors > Scales Hardware > Tools > Measuring Tools & Sensors > Seismometer Hardware > Tools > Measuring Tools & Sensors > Sound Meters Hardware > Tools > Measuring Tools & Sensors > Squares @@ -3085,12 +2535,12 @@ Hardware > Tools > Measuring Tools & Sensors > Straight Edges Hardware > Tools > Measuring Tools & Sensors > Stud Sensors Hardware > Tools > Measuring Tools & Sensors > Tape Measures Hardware > Tools > Measuring Tools & Sensors > Theodolites -Hardware > Tools > Measuring Tools & Sensors > Thermometers -Hardware > Tools > Measuring Tools & Sensors > Thermometers > Infrared Thermometers +Hardware > Tools > Measuring Tools & Sensors > Thermal Imaging Cameras +Hardware > Tools > Measuring Tools & Sensors > Thermocouples & Thermopiles +Hardware > Tools > Measuring Tools & Sensors > Transducers Hardware > Tools > Measuring Tools & Sensors > UV Light Meters Hardware > Tools > Measuring Tools & Sensors > Vibration Meters Hardware > Tools > Measuring Tools & Sensors > Weather Forecasters & Stations -Hardware > Tools > Measuring Tools & Sensors > Wire Locators Hardware > Tools > Measuring Tools & Sensors > pH Meters Hardware > Tools > Milling Machines Hardware > Tools > Multifunction Power Tools @@ -3098,85 +2548,75 @@ Hardware > Tools > Nail Pullers Hardware > Tools > Nailers & Staplers Hardware > Tools > Oil Filter Drains Hardware > Tools > Paint Tools +Hardware > Tools > Paint Tools > Airbrushes +Hardware > Tools > Paint Tools > Paint Brushes Hardware > Tools > Paint Tools > Paint Edgers Hardware > Tools > Paint Tools > Paint Rollers +Hardware > Tools > Paint Tools > Paint Shakers Hardware > Tools > Paint Tools > Paint Sponges Hardware > Tools > Paint Tools > Paint Sprayers -Hardware > Tools > Paint Tools > Paint Stripper +Hardware > Tools > Paint Tools > Paint Strainers Hardware > Tools > Paint Tools > Paint Trays Hardware > Tools > Pickup Tools -Hardware > Tools > Pickup Tools > Utility Tweezers +Hardware > Tools > Pipe & Bar Benders +Hardware > Tools > Pipe & Tube Cleaners +Hardware > Tools > Pipe Brushes Hardware > Tools > Planers Hardware > Tools > Planes Hardware > Tools > Pliers Hardware > Tools > Plungers Hardware > Tools > Polishers & Buffers Hardware > Tools > Post Hole Diggers -Hardware > Tools > Punches +Hardware > Tools > Pry Bars +Hardware > Tools > Punches & Awls Hardware > Tools > Putty Knives & Scrapers Hardware > Tools > Reamers Hardware > Tools > Riveting Tools Hardware > Tools > Riveting Tools > Rivet Guns Hardware > Tools > Riveting Tools > Rivet Pliers Hardware > Tools > Routing Tools -Hardware > Tools > Sandblasters Hardware > Tools > Sanders Hardware > Tools > Sanding Blocks Hardware > Tools > Saw Horses Hardware > Tools > Saws Hardware > Tools > Saws > Band Saws Hardware > Tools > Saws > Cut-Off Saws -Hardware > Tools > Saws > Hacksaws Hardware > Tools > Saws > Hand Saws Hardware > Tools > Saws > Handheld Circular Saws -Hardware > Tools > Saws > Jig Saws +Hardware > Tools > Saws > Jigsaws Hardware > Tools > Saws > Masonry & Tile Saws Hardware > Tools > Saws > Miter Saws +Hardware > Tools > Saws > Panel Saws Hardware > Tools > Saws > Reciprocating Saws Hardware > Tools > Saws > Scroll Saws Hardware > Tools > Saws > Table Saws Hardware > Tools > Screwdrivers -Hardware > Tools > Screwdrivers > Manual Screwdrivers -Hardware > Tools > Screwdrivers > Power Screwdrivers Hardware > Tools > Shapers Hardware > Tools > Sharpeners -Hardware > Tools > Sharpeners > Chainsaw Sharpeners -Hardware > Tools > Sharpeners > Sharpening Stones Hardware > Tools > Socket Drivers Hardware > Tools > Soldering Irons Hardware > Tools > Tap Reseaters +Hardware > Tools > Taps & Dies Hardware > Tools > Threading Machines -Hardware > Tools > Tool Clamps -Hardware > Tools > Tool Clamps > Vise Clamps +Hardware > Tools > Tool Clamps & Vises Hardware > Tools > Tool Files Hardware > Tools > Tool Keys -Hardware > Tools > Tool Keys > Manhole Keys -Hardware > Tools > Tool Keys > Radiator Keys -Hardware > Tools > Tool Keys > Stopcock Keys Hardware > Tools > Tool Knives -Hardware > Tools > Tool Knives > Sheetrock Knives Hardware > Tools > Tool Sets Hardware > Tools > Tool Sets > Hand Tool Sets Hardware > Tools > Tool Sets > Power Tool Combo Sets -Hardware > Tools > Welding Tools +Hardware > Tools > Welding Guns & Plasma Cutters Hardware > Tools > Wire & Cable Hand Tools -Hardware > Tools > Wire & Cable Hand Tools > Cable Slitters -Hardware > Tools > Wire & Cable Hand Tools > Snippers -Hardware > Tools > Wire & Cable Hand Tools > Wire Crimpers -Hardware > Tools > Wire & Cable Hand Tools > Wire Cutters -Hardware > Tools > Wire & Cable Hand Tools > Wire Strippers Hardware > Tools > Work Lights Hardware > Tools > Wrenches -Hardware > Tools > Wrenches > Hex Keys -Hardware > Tools > Wrenches > Socket Wrenches Health & Beauty Health & Beauty > Health Care Health & Beauty > Health Care > Acupuncture Health & Beauty > Health Care > Acupuncture > Acupuncture Models Health & Beauty > Health Care > Acupuncture > Acupuncture Needles -Health & Beauty > Health Care > Arthritis Care Health & Beauty > Health Care > Bed Pans Health & Beauty > Health Care > Biometric Monitor Accessories +Health & Beauty > Health Care > Biometric Monitor Accessories > Activity Monitor Accessories Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Glucose Meter Accessories Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Glucose Meter Accessories > Blood Glucose Control Solution Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Glucose Meter Accessories > Blood Glucose Test Strips @@ -3184,72 +2624,57 @@ Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Glucose Me Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Pressure Monitor Accessories Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Pressure Monitor Accessories > Blood Pressure Monitor Cuffs Health & Beauty > Health Care > Biometric Monitor Accessories > Body Weight Scale Accessories -Health & Beauty > Health Care > Biometric Monitor Accessories > Fertility Monitor Accessories -Health & Beauty > Health Care > Biometric Monitor Accessories > Heart Rate Monitor Accessories Health & Beauty > Health Care > Biometric Monitors +Health & Beauty > Health Care > Biometric Monitors > Activity Monitors Health & Beauty > Health Care > Biometric Monitors > Blood Glucose Meters Health & Beauty > Health Care > Biometric Monitors > Blood Pressure Monitors Health & Beauty > Health Care > Biometric Monitors > Body Fat Analyzers Health & Beauty > Health Care > Biometric Monitors > Body Weight Scales Health & Beauty > Health Care > Biometric Monitors > Breathalyzers Health & Beauty > Health Care > Biometric Monitors > Cholesterol Analyzers -Health & Beauty > Health Care > Biometric Monitors > Fertility Monitors -Health & Beauty > Health Care > Biometric Monitors > Heart Rate Monitors +Health & Beauty > Health Care > Biometric Monitors > Fertility Monitors and Ovulation Tests Health & Beauty > Health Care > Biometric Monitors > Medical Thermometers -Health & Beauty > Health Care > Biometric Monitors > Pedometers -Health & Beauty > Health Care > Biometric Monitors > Prenatal Heart Monitors +Health & Beauty > Health Care > Biometric Monitors > Prenatal Heart Rate Monitors Health & Beauty > Health Care > Biometric Monitors > Pulse Oximeters -Health & Beauty > Health Care > Blood Typing Test Kits -Health & Beauty > Health Care > CPAP Equipment -Health & Beauty > Health Care > CPAP Equipment > CPAP Machines -Health & Beauty > Health Care > CPAP Equipment > CPAP Masks +Health & Beauty > Health Care > Condoms +Health & Beauty > Health Care > Conductivity Gels & Lotions Health & Beauty > Health Care > Contraceptive Cases -Health & Beauty > Health Care > Contraceptives -Health & Beauty > Health Care > Contraceptives > Condoms -Health & Beauty > Health Care > Contraceptives > Spermicides -Health & Beauty > Health Care > Diabetes Care -Health & Beauty > Health Care > Drug Tests Health & Beauty > Health Care > First Aid Health & Beauty > Health Care > First Aid > Antiseptics & Cleaning Supplies Health & Beauty > Health Care > First Aid > Cast & Bandage Protectors Health & Beauty > Health Care > First Aid > Eye Wash Supplies Health & Beauty > Health Care > First Aid > First Aid Kits -Health & Beauty > Health Care > First Aid > Heat Rubs Health & Beauty > Health Care > First Aid > Hot & Cold Therapies +Health & Beauty > Health Care > First Aid > Hot & Cold Therapies > Heat Rubs Health & Beauty > Health Care > First Aid > Hot & Cold Therapies > Heating Pads Health & Beauty > Health Care > First Aid > Hot & Cold Therapies > Ice Packs Health & Beauty > Health Care > First Aid > Medical Tape & Bandages -Health & Beauty > Health Care > First Aid > Rash & Anti-Itch Treatments Health & Beauty > Health Care > Fitness & Nutrition -Health & Beauty > Health Care > Fitness & Nutrition > Diet Pills Health & Beauty > Health Care > Fitness & Nutrition > Nutrition Bars Health & Beauty > Health Care > Fitness & Nutrition > Nutrition Drinks & Shakes Health & Beauty > Health Care > Fitness & Nutrition > Nutrition Gels & Chews -Health & Beauty > Health Care > Fitness & Nutrition > Nutritional Food Purées -Health & Beauty > Health Care > Fitness & Nutrition > Protein Powder -Health & Beauty > Health Care > Fitness & Nutrition > Traditional Chinese Tonics +Health & Beauty > Health Care > Fitness & Nutrition > Nutritional Food Purées Health & Beauty > Health Care > Fitness & Nutrition > Tube Feeding Supplements Health & Beauty > Health Care > Fitness & Nutrition > Vitamins & Supplements -Health & Beauty > Health Care > HIV Tests Health & Beauty > Health Care > Hearing Aids -Health & Beauty > Health Care > Hearing Enhancers Health & Beauty > Health Care > Incontinence Aids +Health & Beauty > Health Care > Light Therapy Lamps Health & Beauty > Health Care > Medical Alarm Systems Health & Beauty > Health Care > Medical Identification Tags & Jewelry +Health & Beauty > Health Care > Medical Tests +Health & Beauty > Health Care > Medical Tests > Allergy Test Kits +Health & Beauty > Health Care > Medical Tests > Blood Typing Test Kits +Health & Beauty > Health Care > Medical Tests > Drug Tests +Health & Beauty > Health Care > Medical Tests > HIV Tests +Health & Beauty > Health Care > Medical Tests > Pregnancy Tests +Health & Beauty > Health Care > Medical Tests > Urinary Tract Infection Tests Health & Beauty > Health Care > Medicine & Drugs -Health & Beauty > Health Care > Medicine & Drugs > OTC Drugs -Health & Beauty > Health Care > Medicine & Drugs > OTC Drugs > Allergies & Sinus -Health & Beauty > Health Care > Medicine & Drugs > OTC Drugs > Cough, Cold & Flu -Health & Beauty > Health Care > Medicine & Drugs > OTC Drugs > Gastrointestinal Treatments -Health & Beauty > Health Care > Medicine & Drugs > OTC Drugs > Pain Relievers -Health & Beauty > Health Care > Medicine & Drugs > OTC Drugs > Sleeping Medication Health & Beauty > Health Care > Mobility & Accessibility Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment > Mobility Scooters Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment > Stair Lifts +Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment > Transfer Boards & Sheets Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment > Wheelchairs -Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment > Wheelchairs > Manual Wheelchairs -Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment > Wheelchairs > Powered Wheelchairs Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment Accessories Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Furniture & Fixtures Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Furniture & Fixtures > Shower Benches & Seats @@ -3258,22 +2683,33 @@ Health & Beauty > Health Care > Mobility & Accessibility > Walking Aids Health & Beauty > Health Care > Mobility & Accessibility > Walking Aids > Canes & Walking Sticks Health & Beauty > Health Care > Mobility & Accessibility > Walking Aids > Crutches Health & Beauty > Health Care > Mobility & Accessibility > Walking Aids > Walkers -Health & Beauty > Health Care > Physical Therapy Equipment -Health & Beauty > Health Care > Physical Therapy Equipment > Hand Exercisers -Health & Beauty > Health Care > Pregnancy Tests +Health & Beauty > Health Care > Occupational & Physical Therapy Equipment +Health & Beauty > Health Care > Occupational & Physical Therapy Equipment > Electrical Muscle Stimulators +Health & Beauty > Health Care > Occupational & Physical Therapy Equipment > Therapeutic Swings +Health & Beauty > Health Care > Pillboxes Health & Beauty > Health Care > Respiratory Care Health & Beauty > Health Care > Respiratory Care > Nebulizers -Health & Beauty > Health Care > Smoking Cessation +Health & Beauty > Health Care > Respiratory Care > Oxygen Tanks +Health & Beauty > Health Care > Respiratory Care > PAP Machines +Health & Beauty > Health Care > Respiratory Care > PAP Masks +Health & Beauty > Health Care > Respiratory Care > Steam Inhalers +Health & Beauty > Health Care > Specimen Cups +Health & Beauty > Health Care > Spermicides +Health & Beauty > Health Care > Stump Shrinkers Health & Beauty > Health Care > Supports & Braces Health & Beauty > Health Care > Surgical Lubricants Health & Beauty > Jewelry Cleaning & Care -Health & Beauty > Jewelry Cleaning & Care > Jewelry Cleaners +Health & Beauty > Jewelry Cleaning & Care > Jewelry Cleaning Solutions & Polishes +Health & Beauty > Jewelry Cleaning & Care > Jewelry Cleaning Tools Health & Beauty > Jewelry Cleaning & Care > Jewelry Holders +Health & Beauty > Jewelry Cleaning & Care > Jewelry Steam Cleaners +Health & Beauty > Jewelry Cleaning & Care > Watch Repair Kits Health & Beauty > Personal Care Health & Beauty > Personal Care > Back Care Health & Beauty > Personal Care > Back Care > Back & Lumbar Support Cushions Health & Beauty > Personal Care > Cosmetics Health & Beauty > Personal Care > Cosmetics > Bath & Body +Health & Beauty > Personal Care > Cosmetics > Bath & Body > Adult Hygienic Wipes Health & Beauty > Personal Care > Cosmetics > Bath & Body > Bar Soap Health & Beauty > Personal Care > Cosmetics > Bath & Body > Bath Additives Health & Beauty > Personal Care > Cosmetics > Bath & Body > Bath Brushes @@ -3283,9 +2719,9 @@ Health & Beauty > Personal Care > Cosmetics > Bath & Body > Hand Sanitizers & Wi Health & Beauty > Personal Care > Cosmetics > Bath & Body > Liquid Hand Soap Health & Beauty > Personal Care > Cosmetics > Bath & Body > Powdered Hand Soap Health & Beauty > Personal Care > Cosmetics > Bath & Body > Shower Caps -Health & Beauty > Personal Care > Cosmetics > Bath & Body > Wet Wipes Health & Beauty > Personal Care > Cosmetics > Bath & Body Gift Sets -Health & Beauty > Personal Care > Cosmetics > Cosmetic Tool Cleaners +Health & Beauty > Personal Care > Cosmetics > Cosmetic Sets +Health & Beauty > Personal Care > Cosmetics > Cosmetic Tool Cleansers Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Double Eyelid Glue & Tape @@ -3294,58 +2730,67 @@ Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Ey Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Eyelash Curlers Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Face Mirrors Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Facial Blotting Paper -Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > False Eyelash Adhesive -Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > False Eyelash Applicators +Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > False Eyelash Accessories +Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > False Eyelash Accessories > False Eyelash Adhesive +Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > False Eyelash Accessories > False Eyelash Applicators +Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > False Eyelash Accessories > False Eyelash Remover Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Makeup Brushes Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Makeup Sponges +Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Refillable Makeup Palettes & Cases Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Cuticle Pushers Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Cuticle Scissors +Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Manicure & Pedicure Spacers Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Manicure Tool Sets Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Buffers Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Clippers +Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Drill Accessories Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Drills Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Dryers Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Files & Emery Boards -Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Pedicure Toe Seperators Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Facial Saunas Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Foot Files +Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Lotion & Sunscreen Applicators Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Pumice Stones Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Skin Care Extractors Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Skin Care Rollers +Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Skin Cleansing Brush Heads Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Skin Cleansing Brushes & Systems -Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Tweezers Health & Beauty > Personal Care > Cosmetics > Makeup Health & Beauty > Personal Care > Cosmetics > Makeup > Body Makeup Health & Beauty > Personal Care > Cosmetics > Makeup > Body Makeup > Body & Hair Glitter Health & Beauty > Personal Care > Cosmetics > Makeup > Body Makeup > Body Paint & Foundation Health & Beauty > Personal Care > Cosmetics > Makeup > Costume & Stage Makeup Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup -Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Eye Shadow & Primer +Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Eye Primer +Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Eye Shadow Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Eyebrow Enhancers -Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Eyelash Growth Treatments Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Eyeliner Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > False Eyelashes +Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Lash & Brow Growth Treatments Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Mascara +Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Mascara Primer Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup > Blushes & Bronzers Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup > Face Powder +Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup > Face Primer Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup > Foundations & Concealers Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup > Highlighters & Luminizers Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup > Lip & Cheek Stains Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup > Lip Gloss Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup > Lip Liner +Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup > Lip Primer Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup > Lipstick Health & Beauty > Personal Care > Cosmetics > Makeup > Makeup Finishing Sprays -Health & Beauty > Personal Care > Cosmetics > Makeup > Makeup Sets Health & Beauty > Personal Care > Cosmetics > Makeup > Temporary Tattoos Health & Beauty > Personal Care > Cosmetics > Nail Care Health & Beauty > Personal Care > Cosmetics > Nail Care > Cuticle Cream & Oil Health & Beauty > Personal Care > Cosmetics > Nail Care > False Nails +Health & Beauty > Personal Care > Cosmetics > Nail Care > Manicure Glue Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Art Kits & Accessories -Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Glue +Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Polish Drying Drops & Sprays Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Polish Removers Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Polish Thinners Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Polishes @@ -3361,10 +2806,6 @@ Health & Beauty > Personal Care > Cosmetics > Skin Care > Facial Cleansing Kits Health & Beauty > Personal Care > Cosmetics > Skin Care > Facial Pore Strips Health & Beauty > Personal Care > Cosmetics > Skin Care > Lip Balms & Treatments Health & Beauty > Personal Care > Cosmetics > Skin Care > Lotion & Moisturizer -Health & Beauty > Personal Care > Cosmetics > Skin Care > Lotion & Moisturizer > Body Lotion -Health & Beauty > Personal Care > Cosmetics > Skin Care > Lotion & Moisturizer > Face Lotion -Health & Beauty > Personal Care > Cosmetics > Skin Care > Lotion & Moisturizer > Foot Lotion -Health & Beauty > Personal Care > Cosmetics > Skin Care > Lotion & Moisturizer > Hand Lotion Health & Beauty > Personal Care > Cosmetics > Skin Care > Makeup Removers Health & Beauty > Personal Care > Cosmetics > Skin Care > Petroleum Jelly Health & Beauty > Personal Care > Cosmetics > Skin Care > Skin Care Masks & Peels @@ -3372,9 +2813,9 @@ Health & Beauty > Personal Care > Cosmetics > Skin Care > Skin Insect Repellent Health & Beauty > Personal Care > Cosmetics > Skin Care > Sunscreen Health & Beauty > Personal Care > Cosmetics > Skin Care > Tanning Products Health & Beauty > Personal Care > Cosmetics > Skin Care > Tanning Products > Self Tanner -Health & Beauty > Personal Care > Cosmetics > Skin Care > Tanning Products > Self Tanner Applicators & Removers Health & Beauty > Personal Care > Cosmetics > Skin Care > Tanning Products > Tanning Oil & Lotion Health & Beauty > Personal Care > Cosmetics > Skin Care > Toners & Astringents +Health & Beauty > Personal Care > Cosmetics > Skin Care > Wart Removers Health & Beauty > Personal Care > Cotton Balls Health & Beauty > Personal Care > Cotton Swabs Health & Beauty > Personal Care > Deodorant & Anti-Perspirant @@ -3382,6 +2823,7 @@ Health & Beauty > Personal Care > Ear Care Health & Beauty > Personal Care > Ear Care > Ear Candles Health & Beauty > Personal Care > Ear Care > Ear Drops Health & Beauty > Personal Care > Ear Care > Ear Dryers +Health & Beauty > Personal Care > Ear Care > Ear Picks & Spoons Health & Beauty > Personal Care > Ear Care > Ear Syringes Health & Beauty > Personal Care > Ear Care > Ear Wax Removal Kits Health & Beauty > Personal Care > Ear Care > Earplug Dispensers @@ -3389,17 +2831,18 @@ Health & Beauty > Personal Care > Ear Care > Earplugs Health & Beauty > Personal Care > Enema Kits & Supplies Health & Beauty > Personal Care > Feminine Sanitary Supplies Health & Beauty > Personal Care > Feminine Sanitary Supplies > Feminine Deodorant -Health & Beauty > Personal Care > Feminine Sanitary Supplies > Feminine Douches & Washes +Health & Beauty > Personal Care > Feminine Sanitary Supplies > Feminine Douches & Creams Health & Beauty > Personal Care > Feminine Sanitary Supplies > Feminine Pads & Protectors +Health & Beauty > Personal Care > Feminine Sanitary Supplies > Menstrual Cups Health & Beauty > Personal Care > Feminine Sanitary Supplies > Tampons Health & Beauty > Personal Care > Foot Care -Health & Beauty > Personal Care > Foot Care > Antifungal Treatments -Health & Beauty > Personal Care > Foot Care > Bunion Care -Health & Beauty > Personal Care > Foot Care > Corn & Callus Care +Health & Beauty > Personal Care > Foot Care > Bunion Care Supplies +Health & Beauty > Personal Care > Foot Care > Corn & Callus Care Supplies Health & Beauty > Personal Care > Foot Care > Foot Odor Removers Health & Beauty > Personal Care > Foot Care > Insoles & Inserts Health & Beauty > Personal Care > Foot Care > Toe Spacers Health & Beauty > Personal Care > Hair Care +Health & Beauty > Personal Care > Hair Care > Hair Care Kits Health & Beauty > Personal Care > Hair Care > Hair Color Health & Beauty > Personal Care > Hair Care > Hair Color Removers Health & Beauty > Personal Care > Hair Care > Hair Coloring Accessories @@ -3419,26 +2862,32 @@ Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Curling Irons Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Hair Curlers Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Hair Dryers Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Hair Straighteners +Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Hair Styling Tool Sets Health & Beauty > Personal Care > Hair Care > Shampoo & Conditioner Health & Beauty > Personal Care > Massage & Relaxation +Health & Beauty > Personal Care > Massage & Relaxation > Back Scratchers +Health & Beauty > Personal Care > Massage & Relaxation > Eye Pillows Health & Beauty > Personal Care > Massage & Relaxation > Massage Chairs Health & Beauty > Personal Care > Massage & Relaxation > Massage Oil +Health & Beauty > Personal Care > Massage & Relaxation > Massage Stone Warmers +Health & Beauty > Personal Care > Massage & Relaxation > Massage Stones Health & Beauty > Personal Care > Massage & Relaxation > Massage Tables Health & Beauty > Personal Care > Massage & Relaxation > Massagers Health & Beauty > Personal Care > Oral Care Health & Beauty > Personal Care > Oral Care > Breath Spray Health & Beauty > Personal Care > Oral Care > Dental Floss +Health & Beauty > Personal Care > Oral Care > Dental Mouthguards Health & Beauty > Personal Care > Oral Care > Dental Water Jet Replacement Tips Health & Beauty > Personal Care > Oral Care > Dental Water Jets Health & Beauty > Personal Care > Oral Care > Denture Adhesives Health & Beauty > Personal Care > Oral Care > Denture Cleaners +Health & Beauty > Personal Care > Oral Care > Denture Repair Kits Health & Beauty > Personal Care > Oral Care > Dentures Health & Beauty > Personal Care > Oral Care > Gum Stimulators -Health & Beauty > Personal Care > Oral Care > Mouthguards Health & Beauty > Personal Care > Oral Care > Mouthwash -Health & Beauty > Personal Care > Oral Care > Oral Pain Relievers +Health & Beauty > Personal Care > Oral Care > Orthodontic Appliance Cases Health & Beauty > Personal Care > Oral Care > Power Flossers -Health & Beauty > Personal Care > Oral Care > Teeth Whitening +Health & Beauty > Personal Care > Oral Care > Teeth Whiteners Health & Beauty > Personal Care > Oral Care > Tongue Scrapers Health & Beauty > Personal Care > Oral Care > Toothbrush Accessories Health & Beauty > Personal Care > Oral Care > Toothbrush Accessories > Toothbrush Covers @@ -3451,6 +2900,7 @@ Health & Beauty > Personal Care > Oral Care > Toothpicks Health & Beauty > Personal Care > Personal Lubricants Health & Beauty > Personal Care > Shaving & Grooming Health & Beauty > Personal Care > Shaving & Grooming > Aftershave +Health & Beauty > Personal Care > Shaving & Grooming > Body & Facial Hair Bleach Health & Beauty > Personal Care > Shaving & Grooming > Electric Razor Accessories Health & Beauty > Personal Care > Shaving & Grooming > Electric Razors Health & Beauty > Personal Care > Shaving & Grooming > Hair Clipper & Trimmer Accessories @@ -3459,20 +2909,23 @@ Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Depilatories Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Electrolysis Devices Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Epilators -Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Laser Hair Removal Devices -Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Waxing Kits +Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Hair Removal Wax Warmers +Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Laser & IPL Hair Removal Devices +Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Waxing Kits & Supplies Health & Beauty > Personal Care > Shaving & Grooming > Razors & Razor Blades +Health & Beauty > Personal Care > Shaving & Grooming > Shaving Bowls & Mugs Health & Beauty > Personal Care > Shaving & Grooming > Shaving Brushes Health & Beauty > Personal Care > Shaving & Grooming > Shaving Cream Health & Beauty > Personal Care > Shaving & Grooming > Shaving Kits Health & Beauty > Personal Care > Shaving & Grooming > Styptic Pencils Health & Beauty > Personal Care > Sleeping Aids -Health & Beauty > Personal Care > Sleeping Aids > Sleep Masks +Health & Beauty > Personal Care > Sleeping Aids > Eye Masks Health & Beauty > Personal Care > Sleeping Aids > Snoring & Sleep Apnea Aids Health & Beauty > Personal Care > Sleeping Aids > Travel Pillows Health & Beauty > Personal Care > Sleeping Aids > White Noise Machines Health & Beauty > Personal Care > Spray Tanning Tents Health & Beauty > Personal Care > Tanning Beds +Health & Beauty > Personal Care > Tweezers Health & Beauty > Personal Care > Vision Care Health & Beauty > Personal Care > Vision Care > Contact Lens Care Health & Beauty > Personal Care > Vision Care > Contact Lens Care > Contact Lens Care Kits @@ -3480,12 +2933,13 @@ Health & Beauty > Personal Care > Vision Care > Contact Lens Care > Contact Lens Health & Beauty > Personal Care > Vision Care > Contact Lens Care > Contact Lens Solution Health & Beauty > Personal Care > Vision Care > Contact Lenses Health & Beauty > Personal Care > Vision Care > Eye Drops & Lubricants -Health & Beauty > Personal Care > Vision Care > Eyeglass Accessories -Health & Beauty > Personal Care > Vision Care > Eyeglass Accessories > Eyeglass Cases & Holders Health & Beauty > Personal Care > Vision Care > Eyeglass Lenses Health & Beauty > Personal Care > Vision Care > Eyeglasses +Health & Beauty > Personal Care > Vision Care > Eyewear Accessories +Health & Beauty > Personal Care > Vision Care > Eyewear Accessories > Eyewear Cases & Holders +Health & Beauty > Personal Care > Vision Care > Eyewear Accessories > Eyewear Lens Cleaning Solutions +Health & Beauty > Personal Care > Vision Care > Eyewear Accessories > Eyewear Straps & Chains Health & Beauty > Personal Care > Vision Care > Sunglass Lenses -Health & Beauty > Personal Care > Wart Removers Home & Garden Home & Garden > Bathroom Accessories Home & Garden > Bathroom Accessories > Bath Caddies @@ -3498,48 +2952,57 @@ Home & Garden > Bathroom Accessories > Hand Dryer Accessories Home & Garden > Bathroom Accessories > Hand Dryers Home & Garden > Bathroom Accessories > Medicine Cabinets Home & Garden > Bathroom Accessories > Robe Hooks +Home & Garden > Bathroom Accessories > Safety Grab Bars Home & Garden > Bathroom Accessories > Shower Curtain Rings Home & Garden > Bathroom Accessories > Shower Curtains +Home & Garden > Bathroom Accessories > Shower Rods Home & Garden > Bathroom Accessories > Soap & Lotion Dispensers Home & Garden > Bathroom Accessories > Soap Dishes & Holders Home & Garden > Bathroom Accessories > Toilet Brush Replacement Heads -Home & Garden > Bathroom Accessories > Toilet Brushes +Home & Garden > Bathroom Accessories > Toilet Brushes & Holders Home & Garden > Bathroom Accessories > Toilet Paper Holders Home & Garden > Bathroom Accessories > Toothbrush Holders Home & Garden > Bathroom Accessories > Towel Racks & Holders +Home & Garden > Business & Home Security +Home & Garden > Business & Home Security > Dummy Surveillance Cameras +Home & Garden > Business & Home Security > Home Alarm Systems +Home & Garden > Business & Home Security > Motion Sensors +Home & Garden > Business & Home Security > Safety & Security Mirrors +Home & Garden > Business & Home Security > Security Lights +Home & Garden > Business & Home Security > Security Monitors & Recorders +Home & Garden > Business & Home Security > Security Safe Accessories +Home & Garden > Business & Home Security > Security Safes +Home & Garden > Business & Home Security > Security System Sensors Home & Garden > Decor Home & Garden > Decor > Address Signs Home & Garden > Decor > Artificial Flora -Home & Garden > Decor > Artificial Flora > Artificial Flowers -Home & Garden > Decor > Artificial Flora > Artificial Plants -Home & Garden > Decor > Artificial Flora > Artificial Topiaries -Home & Garden > Decor > Artificial Flora > Artificial Trees Home & Garden > Decor > Artificial Food +Home & Garden > Decor > Artwork +Home & Garden > Decor > Artwork > Decorative Tapestries +Home & Garden > Decor > Artwork > Posters, Prints, & Visual Artwork +Home & Garden > Decor > Artwork > Sculptures & Statues Home & Garden > Decor > Backrest Pillows -Home & Garden > Decor > Backyard Feeders -Home & Garden > Decor > Backyard Feeders > Bird Feeders -Home & Garden > Decor > Backyard Feeders > Butterfly Feeders -Home & Garden > Decor > Backyard Feeders > Squirrel Feeders Home & Garden > Decor > Baskets +Home & Garden > Decor > Bird & Wildlife Feeder Accessories +Home & Garden > Decor > Bird & Wildlife Feeders +Home & Garden > Decor > Bird & Wildlife Feeders > Bird Feeders +Home & Garden > Decor > Bird & Wildlife Feeders > Butterfly Feeders +Home & Garden > Decor > Bird & Wildlife Feeders > Squirrel Feeders +Home & Garden > Decor > Bird & Wildlife House Accessories +Home & Garden > Decor > Bird & Wildlife Houses +Home & Garden > Decor > Bird & Wildlife Houses > Bat Houses +Home & Garden > Decor > Bird & Wildlife Houses > Birdhouses +Home & Garden > Decor > Bird & Wildlife Houses > Butterfly Houses Home & Garden > Decor > Bird Baths -Home & Garden > Decor > Bird Feeder Accessories -Home & Garden > Decor > Birdhouses Home & Garden > Decor > Bookends -Home & Garden > Decor > Candle & Oil Warmers -Home & Garden > Decor > Candle Holders -Home & Garden > Decor > Candle Holders > Menorahs -Home & Garden > Decor > Candles -Home & Garden > Decor > Candles > Hanukkah Candles -Home & Garden > Decor > Candles > Unity Candles +Home & Garden > Decor > Cardboard Cutouts Home & Garden > Decor > Chair & Sofa Cushions +Home & Garden > Decor > Clock Parts Home & Garden > Decor > Clocks Home & Garden > Decor > Clocks > Alarm Clocks -Home & Garden > Decor > Clocks > Alarm Clocks > Clock Radios -Home & Garden > Decor > Clocks > Alarm Clocks > Portable Alarm Clocks Home & Garden > Decor > Clocks > Desk & Shelf Clocks Home & Garden > Decor > Clocks > Floor & Grandfather Clocks Home & Garden > Decor > Clocks > Wall Clocks -Home & Garden > Decor > Clocks > Wall Clocks > Cuckoo Clocks Home & Garden > Decor > Coat & Hat Racks Home & Garden > Decor > Decorative Bells Home & Garden > Decor > Decorative Bottles @@ -3556,32 +3019,37 @@ Home & Garden > Decor > Figurines Home & Garden > Decor > Finials Home & Garden > Decor > Flag & Windsock Accessories Home & Garden > Decor > Flag & Windsock Accessories > Flag & Windsock Pole Lights +Home & Garden > Decor > Flag & Windsock Accessories > Flag & Windsock Pole Mounting Hardware & Kits Home & Garden > Decor > Flag & Windsock Accessories > Flag & Windsock Poles Home & Garden > Decor > Flags & Windsocks Home & Garden > Decor > Flameless Candles Home & Garden > Decor > Fountains & Ponds Home & Garden > Decor > Fountains & Ponds > Fountain & Pond Accessories -Home & Garden > Decor > Fountains & Ponds > Fountains -Home & Garden > Decor > Fountains & Ponds > Fountains > Indoor Fountains -Home & Garden > Decor > Fountains & Ponds > Fountains > Outdoor Fountains +Home & Garden > Decor > Fountains & Ponds > Fountains & Waterfalls Home & Garden > Decor > Fountains & Ponds > Ponds Home & Garden > Decor > Garden & Stepping Stones -Home & Garden > Decor > Garden Sculptures +Home & Garden > Decor > Growth Charts +Home & Garden > Decor > Home Decor Decals +Home & Garden > Decor > Home Fragrance Accessories +Home & Garden > Decor > Home Fragrance Accessories > Candle & Oil Warmers +Home & Garden > Decor > Home Fragrance Accessories > Candle Holders +Home & Garden > Decor > Home Fragrance Accessories > Candle Snuffers +Home & Garden > Decor > Home Fragrance Accessories > Incense Holders Home & Garden > Decor > Home Fragrances Home & Garden > Decor > Home Fragrances > Air Fresheners +Home & Garden > Decor > Home Fragrances > Candles Home & Garden > Decor > Home Fragrances > Fragrance Oil Home & Garden > Decor > Home Fragrances > Incense -Home & Garden > Decor > Home Fragrances > Incense Holders Home & Garden > Decor > Home Fragrances > Potpourri +Home & Garden > Decor > Home Fragrances > Wax Tarts +Home & Garden > Decor > Hourglasses Home & Garden > Decor > House Numbers & Letters -Home & Garden > Decor > Lawn Ornaments -Home & Garden > Decor > Lawn Ornaments > Gazing Globes +Home & Garden > Decor > Lawn Ornaments & Garden Sculptures Home & Garden > Decor > Mail Slots Home & Garden > Decor > Mailbox Accessories Home & Garden > Decor > Mailbox Accessories > Mailbox Covers Home & Garden > Decor > Mailbox Accessories > Mailbox Enclosures Home & Garden > Decor > Mailbox Accessories > Mailbox Flags -Home & Garden > Decor > Mailbox Accessories > Mailbox Mounting Brackets Home & Garden > Decor > Mailbox Accessories > Mailbox Posts Home & Garden > Decor > Mailbox Accessories > Mailbox Replacement Doors Home & Garden > Decor > Mailboxes @@ -3591,36 +3059,34 @@ Home & Garden > Decor > Napkin Rings Home & Garden > Decor > Novelty Signs Home & Garden > Decor > Ottoman Cushions Home & Garden > Decor > Picture Frames -Home & Garden > Decor > Picture Frames > Digital Picture Frames -Home & Garden > Decor > Picture Frames > Poster Frames Home & Garden > Decor > Piggy Banks & Money Jars Home & Garden > Decor > Rain Chains Home & Garden > Decor > Rain Gauges Home & Garden > Decor > Refrigerator Magnets Home & Garden > Decor > Rugs -Home & Garden > Decor > Rugs > Electric Rugs Home & Garden > Decor > Seasonal & Holiday Decorations Home & Garden > Decor > Seasonal & Holiday Decorations > Advent Calendars Home & Garden > Decor > Seasonal & Holiday Decorations > Christmas Tree Skirts Home & Garden > Decor > Seasonal & Holiday Decorations > Christmas Tree Stands -Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Ornament Displays +Home & Garden > Decor > Seasonal & Holiday Decorations > Easter Egg Decorating Kits +Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Ornament Displays & Stands +Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Ornament Hooks Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Ornaments Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Stocking Hangers Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Stockings +Home & Garden > Decor > Seasonal & Holiday Decorations > Japanese Traditional Dolls Home & Garden > Decor > Seasonal & Holiday Decorations > Nativity Sets -Home & Garden > Decor > Seasonal & Holiday Decorations > Ornament Storage Containers +Home & Garden > Decor > Seasonal & Holiday Decorations > Seasonal Village Sets & Accessories Home & Garden > Decor > Shadow Boxes Home & Garden > Decor > Slipcovers Home & Garden > Decor > Snow Globes Home & Garden > Decor > Suncatchers Home & Garden > Decor > Sundials Home & Garden > Decor > Throw Pillows -Home & Garden > Decor > Tiki Torches & Oil Lamps Home & Garden > Decor > Trunks +Home & Garden > Decor > Vase Fillers & Table Scatters Home & Garden > Decor > Vases -Home & Garden > Decor > Wall & Window Decals -Home & Garden > Decor > Wall Shelves & Ledges -Home & Garden > Decor > Wax Tarts +Home & Garden > Decor > Wallpaper Home & Garden > Decor > Weather Vanes & Roof Decor Home & Garden > Decor > Wind Chimes Home & Garden > Decor > Wind Wheels & Spinners @@ -3641,19 +3107,10 @@ Home & Garden > Decor > World Globes Home & Garden > Decor > Wreaths & Garlands Home & Garden > Emergency Preparedness Home & Garden > Emergency Preparedness > Earthquake Alarms -Home & Garden > Emergency Preparedness > Emergency Food +Home & Garden > Emergency Preparedness > Emergency Blankets +Home & Garden > Emergency Preparedness > Emergency Food Kits Home & Garden > Emergency Preparedness > Emergency Tools & Kits Home & Garden > Emergency Preparedness > Furniture Anchors -Home & Garden > Fire & Gas Safety -Home & Garden > Fire & Gas Safety > Carbon Monoxide Detectors -Home & Garden > Fire & Gas Safety > Fire Alarm Control Panels -Home & Garden > Fire & Gas Safety > Fire Alarms -Home & Garden > Fire & Gas Safety > Fire Extinguisher Cabinets -Home & Garden > Fire & Gas Safety > Fire Extinguishers -Home & Garden > Fire & Gas Safety > Fire Sprinklers -Home & Garden > Fire & Gas Safety > Heat Detectors -Home & Garden > Fire & Gas Safety > Radon Detectors -Home & Garden > Fire & Gas Safety > Smoke Detectors Home & Garden > Fireplace & Wood Stove Accessories Home & Garden > Fireplace & Wood Stove Accessories > Bellows Home & Garden > Fireplace & Wood Stove Accessories > Fireplace & Wood Stove Grates @@ -3667,63 +3124,46 @@ Home & Garden > Fireplace & Wood Stove Accessories > Log Rack & Carrier Accessor Home & Garden > Fireplace & Wood Stove Accessories > Log Racks & Carriers Home & Garden > Fireplace & Wood Stove Accessories > Wood Stove Fans & Blowers Home & Garden > Fireplaces -Home & Garden > Fireplaces > Indoor Fireplaces -Home & Garden > Fireplaces > Outdoor Fireplaces -Home & Garden > Home Security -Home & Garden > Home Security > Dummy Surveillance Cameras -Home & Garden > Home Security > Home Alarm Systems -Home & Garden > Home Security > Motion Sensors -Home & Garden > Home Security > Security Lights -Home & Garden > Home Security > Security Monitors & Recorders -Home & Garden > Home Security > Security Safes -Home & Garden > Home Security > Security System Sensors -Home & Garden > Home Security > Tracking Devices +Home & Garden > Flood, Fire & Gas Safety +Home & Garden > Flood, Fire & Gas Safety > Fire Alarm Control Panels +Home & Garden > Flood, Fire & Gas Safety > Fire Alarms +Home & Garden > Flood, Fire & Gas Safety > Fire Extinguisher & Equipment Storage +Home & Garden > Flood, Fire & Gas Safety > Fire Extinguishers +Home & Garden > Flood, Fire & Gas Safety > Fire Sprinklers +Home & Garden > Flood, Fire & Gas Safety > Heat Detectors +Home & Garden > Flood, Fire & Gas Safety > Smoke & Carbon Monoxide Detectors +Home & Garden > Flood, Fire & Gas Safety > Water & Flood Detectors Home & Garden > Household Appliance Accessories Home & Garden > Household Appliance Accessories > Air Conditioner Accessories Home & Garden > Household Appliance Accessories > Air Conditioner Accessories > Air Conditioner Covers Home & Garden > Household Appliance Accessories > Air Conditioner Accessories > Air Conditioner Filters Home & Garden > Household Appliance Accessories > Air Purifier Accessories Home & Garden > Household Appliance Accessories > Air Purifier Accessories > Air Purifier Filters -Home & Garden > Household Appliance Accessories > Carpet & Steam Cleaner Accessories Home & Garden > Household Appliance Accessories > Dehumidifier Accessories -Home & Garden > Household Appliance Accessories > Dehumidifier Accessories > Dehumidifier Filters Home & Garden > Household Appliance Accessories > Fan Accessories +Home & Garden > Household Appliance Accessories > Floor & Steam Cleaner Accessories Home & Garden > Household Appliance Accessories > Furnace & Boiler Accessories Home & Garden > Household Appliance Accessories > Heating Radiator Accessories Home & Garden > Household Appliance Accessories > Heating Radiator Accessories > Heating Radiator Reflectors Home & Garden > Household Appliance Accessories > Humidifier Accessories Home & Garden > Household Appliance Accessories > Humidifier Accessories > Humidifier Filters Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories -Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Dryer Accessories Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Garment Steamer Accessories Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Iron Accessories Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Steam Press Accessories -Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Washing Machine Accessories -Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Washing Machine Accessories > Washing Machine & Dryer Pedestals -Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Washing Machine Accessories > Washing Machine Hoses -Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Washing Machine Accessories > Washing Machine Valves +Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Washer & Dryer Accessories Home & Garden > Household Appliance Accessories > Patio Heater Accessories Home & Garden > Household Appliance Accessories > Patio Heater Accessories > Patio Heater Covers -Home & Garden > Household Appliance Accessories > Sewing Machine Accessories -Home & Garden > Household Appliance Accessories > Sewing Machine Accessories > Bobbins & Bobbin Cases -Home & Garden > Household Appliance Accessories > Sewing Machine Accessories > Sewing Machine Cases & Covers -Home & Garden > Household Appliance Accessories > Sewing Machine Accessories > Sewing Machine Feet -Home & Garden > Household Appliance Accessories > Sewing Machine Accessories > Sewing Machine Needles Home & Garden > Household Appliance Accessories > Vacuum Accessories -Home & Garden > Household Appliance Accessories > Vacuum Accessories > Vacuum Attachments -Home & Garden > Household Appliance Accessories > Vacuum Accessories > Vacuum Bags -Home & Garden > Household Appliance Accessories > Vacuum Accessories > Vacuum Belts -Home & Garden > Household Appliance Accessories > Vacuum Accessories > Vacuum Filters -Home & Garden > Household Appliance Accessories > Vacuum Accessories > Vacuum Hoses Home & Garden > Household Appliance Accessories > Water Heater Accessories Home & Garden > Household Appliance Accessories > Water Heater Accessories > Anode Rods -Home & Garden > Household Appliance Accessories > Water Heater Accessories > Hot Water Cylinders +Home & Garden > Household Appliance Accessories > Water Heater Accessories > Hot Water Tanks Home & Garden > Household Appliance Accessories > Water Heater Accessories > Water Heater Elements +Home & Garden > Household Appliance Accessories > Water Heater Accessories > Water Heater Expansion Tanks Home & Garden > Household Appliance Accessories > Water Heater Accessories > Water Heater Pans Home & Garden > Household Appliance Accessories > Water Heater Accessories > Water Heater Stacks Home & Garden > Household Appliance Accessories > Water Heater Accessories > Water Heater Vents Home & Garden > Household Appliances -Home & Garden > Household Appliances > Carpet & Steam Cleaners Home & Garden > Household Appliances > Climate Control Appliances Home & Garden > Household Appliances > Climate Control Appliances > Air Conditioners Home & Garden > Household Appliances > Climate Control Appliances > Air Purifiers @@ -3733,40 +3173,41 @@ Home & Garden > Household Appliances > Climate Control Appliances > Evaporative Home & Garden > Household Appliances > Climate Control Appliances > Fans Home & Garden > Household Appliances > Climate Control Appliances > Fans > Ceiling Fans Home & Garden > Household Appliances > Climate Control Appliances > Fans > Desk & Pedestal Fans -Home & Garden > Household Appliances > Climate Control Appliances > Fans > Personal Handheld Fans +Home & Garden > Household Appliances > Climate Control Appliances > Fans > Powered Hand Fans & Misters Home & Garden > Household Appliances > Climate Control Appliances > Fans > Ventilation Fans +Home & Garden > Household Appliances > Climate Control Appliances > Fans > Wall Mount Fans Home & Garden > Household Appliances > Climate Control Appliances > Furnaces & Boilers Home & Garden > Household Appliances > Climate Control Appliances > Heating Radiators Home & Garden > Household Appliances > Climate Control Appliances > Humidifiers -Home & Garden > Household Appliances > Climate Control Appliances > Kotatsu Home & Garden > Household Appliances > Climate Control Appliances > Outdoor Misting Systems Home & Garden > Household Appliances > Climate Control Appliances > Patio Heaters Home & Garden > Household Appliances > Climate Control Appliances > Space Heaters +Home & Garden > Household Appliances > Floor & Carpet Dryers +Home & Garden > Household Appliances > Floor & Steam Cleaners Home & Garden > Household Appliances > Floor Polishers & Buffers Home & Garden > Household Appliances > Futon Dryers +Home & Garden > Household Appliances > Garage Door Keypads & Remotes Home & Garden > Household Appliances > Garage Door Openers -Home & Garden > Household Appliances > Garage Door Remotes -Home & Garden > Household Appliances > Garage Parking Sensors -Home & Garden > Household Appliances > Home Automation Home & Garden > Household Appliances > Laundry Appliances Home & Garden > Household Appliances > Laundry Appliances > Dryers Home & Garden > Household Appliances > Laundry Appliances > Garment Steamers -Home & Garden > Household Appliances > Laundry Appliances > Irons +Home & Garden > Household Appliances > Laundry Appliances > Irons & Ironing Systems Home & Garden > Household Appliances > Laundry Appliances > Laundry Combo Units Home & Garden > Household Appliances > Laundry Appliances > Steam Presses Home & Garden > Household Appliances > Laundry Appliances > Washing Machines -Home & Garden > Household Appliances > Sewing Machines -Home & Garden > Household Appliances > Sewing Machines > Sergers +Home & Garden > Household Appliances > Ultrasonic Cleaners Home & Garden > Household Appliances > Vacuums Home & Garden > Household Appliances > Wallpaper Steamers Home & Garden > Household Appliances > Water Heaters -Home & Garden > Household Appliances > Water Heaters > Immersion Heaters Home & Garden > Household Supplies Home & Garden > Household Supplies > Drawer & Shelf Liners +Home & Garden > Household Supplies > Floor Protection Films & Runners Home & Garden > Household Supplies > Furniture Floor Protectors +Home & Garden > Household Supplies > Garage Floor Mats Home & Garden > Household Supplies > Garbage Bags Home & Garden > Household Supplies > Household Cleaning Supplies Home & Garden > Household Supplies > Household Cleaning Supplies > Broom & Mop Handles +Home & Garden > Household Supplies > Household Cleaning Supplies > Broom Heads Home & Garden > Household Supplies > Household Cleaning Supplies > Brooms Home & Garden > Household Supplies > Household Cleaning Supplies > Buckets Home & Garden > Household Supplies > Household Cleaning Supplies > Carpet Sweepers @@ -3778,26 +3219,26 @@ Home & Garden > Household Supplies > Household Cleaning Supplies > Fabric & Upho Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > All-Purpose Cleaners Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Carpet Cleaners +Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Descalers & Decalcifiers Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Dish Detergent & Soap Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Dishwasher Cleaners Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Fabric & Upholstery Cleaners +Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Floor Cleaners Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Furniture Cleaners & Polish Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Glass & Surface Cleaners -Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Hardwood Floor Cleaners Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Household Disinfectants -Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Leather Care & Dyes Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Oven & Grill Cleaners Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Pet Odor & Stain Removers Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Rinse Aids Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Stainless Steel Cleaners & Polishes -Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Stone Cleaners Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Toilet Bowl Cleaners Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Tub & Tile Cleaners Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Washing Machine Cleaners Home & Garden > Household Supplies > Household Cleaning Supplies > Mop Heads & Refills Home & Garden > Household Supplies > Household Cleaning Supplies > Mops +Home & Garden > Household Supplies > Household Cleaning Supplies > Scrub Brush Heads & Refills Home & Garden > Household Supplies > Household Cleaning Supplies > Scrub Brushes -Home & Garden > Household Supplies > Household Cleaning Supplies > Scrub Brushes > Baby Bottle Brushes +Home & Garden > Household Supplies > Household Cleaning Supplies > Shop Towels & General-Purpose Cleaning Cloths Home & Garden > Household Supplies > Household Cleaning Supplies > Sponges & Scouring Pads Home & Garden > Household Supplies > Household Cleaning Supplies > Squeegees Home & Garden > Household Supplies > Household Paper Products @@ -3817,14 +3258,16 @@ Home & Garden > Household Supplies > Laundry Supplies > Fabric Softeners & Dryer Home & Garden > Household Supplies > Laundry Supplies > Fabric Stain Removers Home & Garden > Household Supplies > Laundry Supplies > Fabric Starch Home & Garden > Household Supplies > Laundry Supplies > Garment Shields +Home & Garden > Household Supplies > Laundry Supplies > Iron Rests Home & Garden > Household Supplies > Laundry Supplies > Ironing Board Pads & Covers +Home & Garden > Household Supplies > Laundry Supplies > Ironing Board Replacement Parts Home & Garden > Household Supplies > Laundry Supplies > Ironing Boards Home & Garden > Household Supplies > Laundry Supplies > Laundry Balls Home & Garden > Household Supplies > Laundry Supplies > Laundry Baskets Home & Garden > Household Supplies > Laundry Supplies > Laundry Detergent +Home & Garden > Household Supplies > Laundry Supplies > Laundry Wash Bags & Frames Home & Garden > Household Supplies > Laundry Supplies > Lint Rollers -Home & Garden > Household Supplies > Laundry Supplies > Washing Bags & Baskets -Home & Garden > Household Supplies > Laundry Supplies > Wrinkle Releasers & Static Sprays +Home & Garden > Household Supplies > Laundry Supplies > Wrinkle Releasers & Anti-Static Sprays Home & Garden > Household Supplies > Moisture Absorbers Home & Garden > Household Supplies > Pest Control Home & Garden > Household Supplies > Pest Control > Fly Swatters @@ -3840,19 +3283,23 @@ Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Bags Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Brushes Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Care Kits Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Dryers -Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Horns +Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Horns & Dressing Aids Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Polishers Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Polishes & Waxes Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Scrapers Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Treatments & Dyes Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Trees & Shapers +Home & Garden > Household Supplies > Stair Treads Home & Garden > Household Supplies > Storage & Organization Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage +Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Charging Valets +Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Closet Organizers & Garment Racks +Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Clothes Valets Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Hangers Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Hat Boxes Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Shoe Racks & Organizers Home & Garden > Household Supplies > Storage & Organization > Flatware Chests -Home & Garden > Household Supplies > Storage & Organization > Gift Wrap Storage & Organization +Home & Garden > Household Supplies > Storage & Organization > Household Drawer Organizer Inserts Home & Garden > Household Supplies > Storage & Organization > Household Storage Bags Home & Garden > Household Supplies > Storage & Organization > Household Storage Caddies Home & Garden > Household Supplies > Storage & Organization > Household Storage Containers @@ -3860,61 +3307,59 @@ Home & Garden > Household Supplies > Storage & Organization > Household Storage Home & Garden > Household Supplies > Storage & Organization > Photo Storage Home & Garden > Household Supplies > Storage & Organization > Photo Storage > Photo Albums Home & Garden > Household Supplies > Storage & Organization > Photo Storage > Photo Storage Boxes -Home & Garden > Household Supplies > Storage & Organization > Pillboxes Home & Garden > Household Supplies > Storage & Organization > Storage Hooks & Racks -Home & Garden > Household Supplies > Storage & Organization > Storage Hooks & Racks > Garment Racks +Home & Garden > Household Supplies > Storage & Organization > Storage Hooks & Racks > Ironing Board Hooks & Racks Home & Garden > Household Supplies > Storage & Organization > Storage Hooks & Racks > Umbrella Stands & Racks Home & Garden > Household Supplies > Storage & Organization > Storage Hooks & Racks > Utility Hooks -Home & Garden > Household Supplies > Storage & Organization > Valets -Home & Garden > Household Supplies > Storage & Organization > Valets > Charging Valets -Home & Garden > Household Supplies > Storage & Organization > Valets > Clothes Valets -Home & Garden > Household Supplies > Storage & Organization > Valets > Dresser Valets Home & Garden > Household Supplies > Trash Compactor Accessories Home & Garden > Household Supplies > Waste Containment +Home & Garden > Household Supplies > Waste Containment > Dumpsters Home & Garden > Household Supplies > Waste Containment > Hazardous Waste Containers Home & Garden > Household Supplies > Waste Containment > Recycling Containers Home & Garden > Household Supplies > Waste Containment > Trash Cans & Wastebaskets Home & Garden > Household Supplies > Waste Containment Accessories Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Carts -Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Frames +Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Enclosures +Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Labels & Signs Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Lids Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Wheels Home & Garden > Kitchen & Dining Home & Garden > Kitchen & Dining > Barware Home & Garden > Kitchen & Dining > Barware > Absinthe Fountains Home & Garden > Kitchen & Dining > Barware > Beer Dispensers & Taps +Home & Garden > Kitchen & Dining > Barware > Beverage Chilling Cubes & Sticks +Home & Garden > Kitchen & Dining > Barware > Beverage Tubs & Chillers +Home & Garden > Kitchen & Dining > Barware > Bottle Caps Home & Garden > Kitchen & Dining > Barware > Bottle Stoppers & Savers Home & Garden > Kitchen & Dining > Barware > Coaster Holders Home & Garden > Kitchen & Dining > Barware > Coasters +Home & Garden > Kitchen & Dining > Barware > Cocktail & Barware Tool Sets +Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools +Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools > Bar Ice Picks +Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools > Bottle Openers +Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools > Cocktail Shakers +Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools > Cocktail Strainers +Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools > Muddlers Home & Garden > Kitchen & Dining > Barware > Corkscrews Home & Garden > Kitchen & Dining > Barware > Decanters -Home & Garden > Kitchen & Dining > Barware > Drink Shakers & Tools -Home & Garden > Kitchen & Dining > Barware > Drink Shakers & Tools > Bar Ice Picks -Home & Garden > Kitchen & Dining > Barware > Drink Shakers & Tools > Bottle Openers -Home & Garden > Kitchen & Dining > Barware > Drink Shakers & Tools > Drink Shakers -Home & Garden > Kitchen & Dining > Barware > Drink Shakers & Tools > Drink Tool Sets Home & Garden > Kitchen & Dining > Barware > Foil Cutters -Home & Garden > Kitchen & Dining > Barware > Ice Buckets -Home & Garden > Kitchen & Dining > Barware > Whiskey Stones Home & Garden > Kitchen & Dining > Barware > Wine Aerators -Home & Garden > Kitchen & Dining > Barware > Wine Buckets & Chillers +Home & Garden > Kitchen & Dining > Barware > Wine Bottle Holders Home & Garden > Kitchen & Dining > Barware > Wine Glass Charms Home & Garden > Kitchen & Dining > Cookware & Bakeware Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Bakeware Sets Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Baking & Cookie Sheets -Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Baking & Specialty Molds -Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Bread Pans +Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Bread Pans & Molds Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Broiling Pans Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Cake Pans & Molds -Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Muffin & Cupcake Pans +Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Muffin & Pastry Pans Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Pie & Quiche Pans Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Pizza Pans Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Pizza Stones Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Ramekins & Souffle Dishes Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Roasting Pans Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware Accessories -Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware Accessories > Baking Cups Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware Accessories > Baking Mats & Liners Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware Accessories > Baking Weights Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware Accessories > Roasting Pan Racks @@ -3922,26 +3367,25 @@ Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware & Bakeware Combo Sets Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Casserole Dishes Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Cookware Sets -Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Crêpe & Blini Pans +Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Crêpe & Blini Pans Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Double Boilers Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Dutch Ovens Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Fermentation & Pickling Crocks Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Griddles & Grill Pans Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Grill Presses Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Paella Pans -Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Pressure Cookers -Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Pressure Cookers > Electric Pressure Cookers +Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Pressure Cookers & Canners Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Saucepans -Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Sauté Pans +Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Sauté Pans Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Skillets & Frying Pans Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Stock Pots Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Stovetop Kettles -Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Tajines +Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Tagines & Clay Cooking Pots Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Woks Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Pot & Pan Handles Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Pot & Pan Lids -Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Pressure Cooker Accessories +Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Pressure Cooker & Canner Accessories Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Steamer Baskets Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Wok Accessories Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Wok Accessories > Wok Brushes @@ -3950,7 +3394,6 @@ Home & Garden > Kitchen & Dining > Food & Beverage Carriers Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Airpots Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Canteens Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Coolers -Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Drink Lids Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Drink Sleeves Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Drink Sleeves > Can & Bottle Sleeves Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Drink Sleeves > Cup Sleeves @@ -3958,14 +3401,15 @@ Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Flasks Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Insulated Bags Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Lunch Boxes & Totes Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Picnic Baskets +Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Replacement Drink Lids Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Thermoses Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Water Bottles Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Wine Carrier Bags Home & Garden > Kitchen & Dining > Food Storage -Home & Garden > Kitchen & Dining > Food Storage > Bowl Covers Home & Garden > Kitchen & Dining > Food Storage > Bread Boxes & Bags Home & Garden > Kitchen & Dining > Food Storage > Candy Buckets Home & Garden > Kitchen & Dining > Food Storage > Cookie Jars +Home & Garden > Kitchen & Dining > Food Storage > Food Container Covers Home & Garden > Kitchen & Dining > Food Storage > Food Storage Bags Home & Garden > Kitchen & Dining > Food Storage > Food Storage Containers Home & Garden > Kitchen & Dining > Food Storage > Food Wraps @@ -3975,50 +3419,38 @@ Home & Garden > Kitchen & Dining > Food Storage > Food Wraps > Plastic Wrap Home & Garden > Kitchen & Dining > Food Storage > Food Wraps > Wax Paper Home & Garden > Kitchen & Dining > Food Storage > Honey Jars Home & Garden > Kitchen & Dining > Food Storage Accessories +Home & Garden > Kitchen & Dining > Food Storage Accessories > Food & Beverage Labels Home & Garden > Kitchen & Dining > Food Storage Accessories > Food Wrap Dispensers Home & Garden > Kitchen & Dining > Food Storage Accessories > Oxygen Absorbers Home & Garden > Kitchen & Dining > Food Storage Accessories > Twist Ties & Bag Clips Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Blender Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Blender Accessories > Blender Jars -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Blender Accessories > Blender Lids Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Breadmaker Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Decanter Warmers Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Decanters Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Filter Baskets Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Filters +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Grinder Accessories +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Grinders +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Maker & Espresso Machine Replacement Parts Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Maker Water Filters Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Frothing Pitchers Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Portafilters -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Stovetop Espresso Pot Parts -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Cooktop Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Cooktop Accessories > Cooktop Burner Grates +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Cooktop, Oven & Range Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Cotton Candy Machine Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Deep Fryer Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Deep Fryer Accessories > Fryer Baskets -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Dishwasher Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Dishwasher Accessories > Dishwasher Glass Racks +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Dishwasher Parts & Accessories +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Electric Kettle Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Electric Skillet & Wok Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Fondue Set Accessories +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Fondue Set Accessories > Cooking Gel Fuels Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Fondue Set Accessories > Fondue Forks Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Fondue Set Accessories > Fondue Pot Stands Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Dehydrator Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Dehydrator Accessories > Food Dehydrator Sheets Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Dehydrator Accessories > Food Dehydrator Trays Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Grinder Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Grinder Accessories > Coffee Grinder Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Grinder Accessories > Meat Grinder Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Grinder Accessories > Spice Grinder Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Mixer Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Mixer Accessories > Food Mixer Attachments -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Mixer Accessories > Food Mixer Attachments > Juicer Attachments -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Mixer Accessories > Food Mixer Attachments > Meat Grinder Attachments -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Mixer Accessories > Food Mixer Attachments > Pasta Maker Attachments -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Mixer Accessories > Food Mixer Beaters -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Mixer Accessories > Food Mixer Bowls -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Mixer Accessories > Food Mixer Hooks -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Processor Accessories +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Mixer & Blender Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Freezer Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Garbage Disposal Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Ice Cream Maker Accessories @@ -4027,41 +3459,35 @@ Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Ice Crusher & Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Ice Maker Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Juicer Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Microwave Oven Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Microwave Oven Accessories > Microwave Drawers -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Microwave Oven Accessories > Microwave Trim Kits Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Charcoal Briquettes Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Charcoal Chimneys -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Burners Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Carts Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Covers Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Racks & Toppers +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Replacement Parts Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Spits & Baskets Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grilling Planks Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Smoking Chips & Pellets -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Oven Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Oven Accessories > Oven Liners -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Oven Accessories > Oven Rack Guards -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Oven Accessories > Oven Racks Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Pasta Maker Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Popcorn Maker Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Portable Cooking Stove Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Range Accessories -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Range Accessories > Range Burner Covers -Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Range Accessories > Range Drip Pans +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Range Hood Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Refrigerator Accessories +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Soda Maker Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Steam Table Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Steam Table Accessories > Steam Table Pan Covers Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Steam Table Accessories > Steam Table Pans Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Toaster Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Vacuum Sealer Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Vacuum Sealer Accessories > Vacuum Sealer Bags +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Waffle Iron Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Water Cooler Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Water Cooler Accessories > Water Cooler Bottles +Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Wine Fridge Accessories Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Yogurt Maker Accessories Home & Garden > Kitchen & Dining > Kitchen Appliances Home & Garden > Kitchen & Dining > Kitchen Appliances > Beverage Warmers -Home & Garden > Kitchen & Dining > Kitchen Appliances > Blenders Home & Garden > Kitchen & Dining > Kitchen Appliances > Breadmakers Home & Garden > Kitchen & Dining > Kitchen Appliances > Chocolate Tempering Machines Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines @@ -4073,15 +3499,13 @@ Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines > Vacuum Coffee Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Cooktops Home & Garden > Kitchen & Dining > Kitchen Appliances > Cotton Candy Machines -Home & Garden > Kitchen & Dining > Kitchen Appliances > Crêpe Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Deep Fryers +Home & Garden > Kitchen & Dining > Kitchen Appliances > Deli Slicers Home & Garden > Kitchen & Dining > Kitchen Appliances > Dishwashers Home & Garden > Kitchen & Dining > Kitchen Appliances > Electric Griddles & Grills -Home & Garden > Kitchen & Dining > Kitchen Appliances > Electric Griddles & Grills > Electric Griddles -Home & Garden > Kitchen & Dining > Kitchen Appliances > Electric Griddles & Grills > Electric Grills Home & Garden > Kitchen & Dining > Kitchen Appliances > Electric Kettles Home & Garden > Kitchen & Dining > Kitchen Appliances > Electric Skillets & Woks -Home & Garden > Kitchen & Dining > Kitchen Appliances > Fondue Sets +Home & Garden > Kitchen & Dining > Kitchen Appliances > Fondue Pots & Sets Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers > Egg Cookers Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers > Food Steamers @@ -4091,20 +3515,15 @@ Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers > Water Ovens Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Dehydrators Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Grinders & Mills -Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Grinders & Mills > Coffee Grinders -Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Grinders & Mills > Grain Mills -Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Grinders & Mills > Meat Grinders -Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Grinders & Mills > Spice Grinders -Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Mixers -Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Processors -Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Slicers -Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Slicers > Deli Slicers +Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Mixers & Blenders Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Smokers Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Warmers Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Warmers > Chafing Dishes Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Warmers > Food Heat Lamps +Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Warmers > Rice Keepers Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Warmers > Steam Tables Home & Garden > Kitchen & Dining > Kitchen Appliances > Freezers +Home & Garden > Kitchen & Dining > Kitchen Appliances > Frozen Drink Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Garbage Disposals Home & Garden > Kitchen & Dining > Kitchen Appliances > Gas Griddles Home & Garden > Kitchen & Dining > Kitchen Appliances > Hot Drink Makers @@ -4113,18 +3532,12 @@ Home & Garden > Kitchen & Dining > Kitchen Appliances > Ice Cream Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Ice Crushers & Shavers Home & Garden > Kitchen & Dining > Kitchen Appliances > Ice Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Juicers -Home & Garden > Kitchen & Dining > Kitchen Appliances > Juicers > Hand Juicers Home & Garden > Kitchen & Dining > Kitchen Appliances > Knife Sharpeners Home & Garden > Kitchen & Dining > Kitchen Appliances > Microwave Ovens Home & Garden > Kitchen & Dining > Kitchen Appliances > Milk Frothers & Steamers Home & Garden > Kitchen & Dining > Kitchen Appliances > Mochi Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Outdoor Grills -Home & Garden > Kitchen & Dining > Kitchen Appliances > Outdoor Grills > Charcoal Grills -Home & Garden > Kitchen & Dining > Kitchen Appliances > Outdoor Grills > Gas Grills Home & Garden > Kitchen & Dining > Kitchen Appliances > Ovens -Home & Garden > Kitchen & Dining > Kitchen Appliances > Ovens > Conveyor Ovens -Home & Garden > Kitchen & Dining > Kitchen Appliances > Ovens > Deck Ovens -Home & Garden > Kitchen & Dining > Kitchen Appliances > Ovens > Wall Ovens Home & Garden > Kitchen & Dining > Kitchen Appliances > Pasta Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Popcorn Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Portable Cooking Stoves @@ -4132,18 +3545,17 @@ Home & Garden > Kitchen & Dining > Kitchen Appliances > Range Hoods Home & Garden > Kitchen & Dining > Kitchen Appliances > Ranges Home & Garden > Kitchen & Dining > Kitchen Appliances > Refrigerators Home & Garden > Kitchen & Dining > Kitchen Appliances > Roaster Ovens & Rotisseries -Home & Garden > Kitchen & Dining > Kitchen Appliances > Slush Machines Home & Garden > Kitchen & Dining > Kitchen Appliances > Soda Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Soy Milk Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Tea Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills +Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Countertop & Toaster Ovens Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Donut Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Muffin & Cupcake Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Pizza Makers & Ovens Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Pizzelle Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Pretzel Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Sandwich Makers -Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Toaster Ovens Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Toasters Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Tortilla & Flatbread Makers Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Waffle Irons @@ -4163,10 +3575,8 @@ Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cake Decorating Su Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cake Servers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Can Crushers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Can Openers -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Candy & Chocolate Molds Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Carving Forks Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Channel Knives -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Citrus Reamers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Colanders & Strainers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Condiment Dispensers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cookie Cutters @@ -4177,57 +3587,50 @@ Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cooking Timers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cooking Torches Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cooling Racks Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cutting Boards -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Dicers & Choppers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Dish Racks & Drain Boards Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Dough Wheels Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Electric Knife Accessories Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Electric Knife Accessories > Electric Knife Replacement Blades Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Electric Knives Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Flour Sifters +Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food & Drink Stencils Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Crackers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Crackers > Lobster & Crab Crackers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Crackers > Nutcrackers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Crackers > Nutcrackers > Decorative Nutcrackers -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Cutters & Wedgers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Dispensers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Graters & Zesters Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Peelers & Corers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Steaming Bags Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Sticks & Skewers +Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Funnels Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Garlic Presses Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Gelatin Molds Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Ice Cube Trays -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Ice Pop Molds Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Jerky Guns Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Knives Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Molds Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Can Organizers -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Drinkware Racks +Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Drinkware Holders Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Kitchen Cabinet Organizers -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Kitchen Storage Carousels -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Kitchen Utensil Holders +Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Kitchen Counter & Beverage Station Organizers +Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Kitchen Utensil Holders & Racks Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Knife Blocks & Holders Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Napkin Holders & Dispensers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Paper Towel Holders & Dispensers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Pot Racks -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Single Serve Beverage Organizers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Spice Organizers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Straw Holders & Dispensers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Sugar Caddies Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Toothpick Holders & Dispensers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Utensil & Flatware Trays -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Scales Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Scrapers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Scrapers > Bench Scrapers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Scrapers > Bowl Scrapers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Scrapers > Grill Scrapers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Shears Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Slicers -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Slicers > Bread Slicers -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Slicers > Cheese Slicers -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Slicers > Egg Slicers -Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Slicers > Mandoline Slicers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Utensil Sets Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Ladles Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Mashers @@ -4254,16 +3657,20 @@ Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Scoops Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Scoops > Ice Cream Scoops Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Scoops > Ice Scoops Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Scoops > Melon Ballers +Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Scoops > Popcorn & French Fry Scoops Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Sink Caddies Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Sink Mats & Grids Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Slotted Spoons Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Spatulas +Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Spice Grinder Accessories +Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Spice Grinders Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Spoon Rests Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Sugar Dispensers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Sushi Mats Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Tea Strainers Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Tongs Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Whisks +Home & Garden > Kitchen & Dining > Prefabricated Kitchens & Kitchenettes Home & Garden > Kitchen & Dining > Tableware Home & Garden > Kitchen & Dining > Tableware > Coffee & Tea Sets Home & Garden > Kitchen & Dining > Tableware > Coffee Servers & Tea Pots @@ -4273,29 +3680,15 @@ Home & Garden > Kitchen & Dining > Tableware > Dinnerware > Dinnerware Sets Home & Garden > Kitchen & Dining > Tableware > Dinnerware > Plates Home & Garden > Kitchen & Dining > Tableware > Drinkware Home & Garden > Kitchen & Dining > Tableware > Drinkware > Beer Glasses -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Beer Glasses > Pilsner Glasses -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Beer Glasses > Pint Glasses -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Beer Glasses > Tankards & Beer Steins Home & Garden > Kitchen & Dining > Tableware > Drinkware > Coffee & Tea Cups -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Coffee & Tea Cups > Coffee Cups -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Coffee & Tea Cups > Tea Cups Home & Garden > Kitchen & Dining > Tableware > Drinkware > Coffee & Tea Saucers Home & Garden > Kitchen & Dining > Tableware > Drinkware > Drinkware Sets Home & Garden > Kitchen & Dining > Tableware > Drinkware > Mugs Home & Garden > Kitchen & Dining > Tableware > Drinkware > Shot Glasses Home & Garden > Kitchen & Dining > Tableware > Drinkware > Stemware -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Stemware > Brandy Snifters -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Stemware > Champagne Glasses -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Stemware > Margarita Glasses -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Stemware > Martini Glasses -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Stemware > Wine Glasses Home & Garden > Kitchen & Dining > Tableware > Drinkware > Tumblers -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Tumblers > Highball Glasses -Home & Garden > Kitchen & Dining > Tableware > Drinkware > Tumblers > Lowball Glasses Home & Garden > Kitchen & Dining > Tableware > Flatware Home & Garden > Kitchen & Dining > Tableware > Flatware > Chopstick Accessories -Home & Garden > Kitchen & Dining > Tableware > Flatware > Chopstick Accessories > Chopstick Connectors -Home & Garden > Kitchen & Dining > Tableware > Flatware > Chopstick Accessories > Chopstick Rests Home & Garden > Kitchen & Dining > Tableware > Flatware > Chopsticks Home & Garden > Kitchen & Dining > Tableware > Flatware > Flatware Sets Home & Garden > Kitchen & Dining > Tableware > Flatware > Forks @@ -4318,6 +3711,7 @@ Home & Garden > Kitchen & Dining > Tableware > Serveware Accessories Home & Garden > Kitchen & Dining > Tableware > Serveware Accessories > Punch Bowl Stands Home & Garden > Kitchen & Dining > Tableware > Serveware Accessories > Tureen Lids Home & Garden > Kitchen & Dining > Tableware > Serveware Accessories > Tureen Stands +Home & Garden > Kitchen & Dining > Tableware > Tablecloth Clips & Weights Home & Garden > Kitchen & Dining > Tableware > Trivets Home & Garden > Lawn & Garden Home & Garden > Lawn & Garden > Gardening @@ -4327,46 +3721,46 @@ Home & Garden > Lawn & Garden > Gardening > Composting > Compost Aerators Home & Garden > Lawn & Garden > Gardening > Composting > Composters Home & Garden > Lawn & Garden > Gardening > Disease Control Home & Garden > Lawn & Garden > Gardening > Fertilizers +Home & Garden > Lawn & Garden > Gardening > Garden Pot Saucers & Trays Home & Garden > Lawn & Garden > Gardening > Gardening Accessories -Home & Garden > Lawn & Garden > Gardening > Gardening Accessories > Gardening Kneeling Cushions +Home & Garden > Lawn & Garden > Gardening > Gardening Accessories > Gardening Scooters, Seats & Kneelers Home & Garden > Lawn & Garden > Gardening > Gardening Accessories > Gardening Totes Home & Garden > Lawn & Garden > Gardening > Gardening Accessories > Potting Benches +Home & Garden > Lawn & Garden > Gardening > Gardening Tool Accessories +Home & Garden > Lawn & Garden > Gardening > Gardening Tool Accessories > Gardening Tool Handles +Home & Garden > Lawn & Garden > Gardening > Gardening Tool Accessories > Gardening Tool Heads +Home & Garden > Lawn & Garden > Gardening > Gardening Tool Accessories > Wheelbarrow Parts Home & Garden > Lawn & Garden > Gardening > Gardening Tools -Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Brush Axes Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Bulb Planting Tools Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Cultivating Tools -Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Cultivating Tools > Garden Hoes -Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Digging Bars Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Gardening Forks -Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Gardening Sickles +Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Gardening Sickles & Machetes Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Gardening Trowels -Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Grass Edgers Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Lawn & Garden Sprayers -Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Lawn Aerators -Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Machetes -Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Mattocks & Pickaxes +Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Lawn Rollers Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Pruning Saws Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Pruning Shears Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Rakes Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Shovels & Spades Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Spreaders -Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Wheelbarrow Parts Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Wheelbarrows Home & Garden > Lawn & Garden > Gardening > Greenhouses Home & Garden > Lawn & Garden > Gardening > Herbicides Home & Garden > Lawn & Garden > Gardening > Landscape Fabric -Home & Garden > Lawn & Garden > Gardening > Lanscape Fabric Accessories -Home & Garden > Lawn & Garden > Gardening > Lanscape Fabric Accessories > Landscape Fabric Staples & Pins -Home & Garden > Lawn & Garden > Gardening > Lanscape Fabric Accessories > Landscape Fabric Tape +Home & Garden > Lawn & Garden > Gardening > Landscape Fabric Accessories +Home & Garden > Lawn & Garden > Gardening > Landscape Fabric Accessories > Landscape Fabric Staples & Pins +Home & Garden > Lawn & Garden > Gardening > Landscape Fabric Accessories > Landscape Fabric Tape Home & Garden > Lawn & Garden > Gardening > Mulch -Home & Garden > Lawn & Garden > Gardening > Plant Cages -Home & Garden > Lawn & Garden > Gardening > Plant Stakes & Supports +Home & Garden > Lawn & Garden > Gardening > Plant Cages & Supports Home & Garden > Lawn & Garden > Gardening > Plant Stands +Home & Garden > Lawn & Garden > Gardening > Pot & Planter Liners Home & Garden > Lawn & Garden > Gardening > Pots & Planters Home & Garden > Lawn & Garden > Gardening > Rain Barrels Home & Garden > Lawn & Garden > Gardening > Sands & Soils Home & Garden > Lawn & Garden > Outdoor Living -Home & Garden > Lawn & Garden > Outdoor Living > Hammock Accessories +Home & Garden > Lawn & Garden > Outdoor Living > Awning Accessories +Home & Garden > Lawn & Garden > Outdoor Living > Awnings +Home & Garden > Lawn & Garden > Outdoor Living > Hammock Parts & Accessories Home & Garden > Lawn & Garden > Outdoor Living > Hammocks Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Blankets Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Blankets > Beach Mats @@ -4382,17 +3776,21 @@ Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Canopy & G Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Canopy & Gazebo Accessories > Canopy Weights Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Garden Arches, Trellises, Arbors & Pergolas Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Garden Bridges -Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Sheds & Storage +Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Sheds, Garages & Carports Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories > Outdoor Umbrella & Sunshade Fabric Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories > Outdoor Umbrella Bases Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories > Outdoor Umbrella Covers +Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories > Outdoor Umbrella Enclosure Kits Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories > Outdoor Umbrella Lights Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrellas & Sunshades +Home & Garden > Lawn & Garden > Outdoor Living > Porch Swing Accessories Home & Garden > Lawn & Garden > Outdoor Living > Porch Swings Home & Garden > Lawn & Garden > Outdoor Power Equipment Home & Garden > Lawn & Garden > Outdoor Power Equipment > Chainsaws +Home & Garden > Lawn & Garden > Outdoor Power Equipment > Grass Edgers Home & Garden > Lawn & Garden > Outdoor Power Equipment > Hedge Trimmers +Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Aerators & Dethatchers Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Mowers Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Mowers > Riding Mowers Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Mowers > Robotic Mowers @@ -4400,8 +3798,9 @@ Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Mowers > Tow-Behi Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Mowers > Walk-Behind Mowers Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Vacuums Home & Garden > Lawn & Garden > Outdoor Power Equipment > Leaf Blowers -Home & Garden > Lawn & Garden > Outdoor Power Equipment > Outdoor Power Equipment Heads +Home & Garden > Lawn & Garden > Outdoor Power Equipment > Outdoor Power Equipment Base Units Home & Garden > Lawn & Garden > Outdoor Power Equipment > Outdoor Power Equipment Sets +Home & Garden > Lawn & Garden > Outdoor Power Equipment > Power Sweepers Home & Garden > Lawn & Garden > Outdoor Power Equipment > Power Tillers & Cultivators Home & Garden > Lawn & Garden > Outdoor Power Equipment > Pressure Washers Home & Garden > Lawn & Garden > Outdoor Power Equipment > Snow Blowers @@ -4412,35 +3811,41 @@ Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Chainsaw A Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Chainsaw Accessories > Chainsaw Bars Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Chainsaw Accessories > Chainsaw Chains Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Grass Edger Accessories -Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Grass Edger Accessories > Grass Edger Attachments Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Hedge Trimmer Accessories -Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Hedge Trimmer Accessories > Hedge Trimmer Attachments Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Brush Mower Attachments -Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Attachments Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Bags Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Belts Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Blades Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Covers +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Mulch Kits +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Mulch Plugs & Plates Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Pulleys & Idlers +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Tire Tubes Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Tires Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Wheels +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Striping Kits Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Sweepers Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Leaf Blower Accessories -Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Leaf Blower Accessories > Leaf Blower Extension Tubes +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Leaf Blower Accessories > Leaf Blower Tubes +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Grass Edger Attachments +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Ground & Leaf Blower Attachments +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Hedge Trimmer Attachments +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Pole Saw Attachments +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Tiller & Cultivator Attachments +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Weed Trimmer Attachments Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Outdoor Power Equipment Batteries -Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Outdoor Power Equipment Batteries > Hedge Trimmer Batteries -Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Outdoor Power Equipment Batteries > Lawn Mower Batteries -Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Outdoor Power Equipment Batteries > Weed Trimmer Batteries Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Pressure Washer Accessories Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Snow Blower Accessories Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Tractor Parts & Accessories +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Tractor Parts & Accessories > Tractor Tires +Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Tractor Parts & Accessories > Tractor Wheels Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Weed Trimmer Accessories -Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Weed Trimmer Accessories > Weed Trimmer Attachments Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Weed Trimmer Accessories > Weed Trimmer Blades & Spools Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Weed Trimmer Accessories > Weed Trimmer Spool Covers Home & Garden > Lawn & Garden > Snow Removal -Home & Garden > Lawn & Garden > Snow Removal > Ice Scrapers +Home & Garden > Lawn & Garden > Snow Removal > Ice Scrapers & Snow Brushes Home & Garden > Lawn & Garden > Snow Removal > Snow Shovels Home & Garden > Lawn & Garden > Watering & Irrigation Home & Garden > Lawn & Garden > Watering & Irrigation > Garden Hose Fittings & Valves @@ -4450,20 +3855,16 @@ Home & Garden > Lawn & Garden > Watering & Irrigation > Sprinkler Accessories Home & Garden > Lawn & Garden > Watering & Irrigation > Sprinkler Accessories > Sprinkler Controls Home & Garden > Lawn & Garden > Watering & Irrigation > Sprinkler Accessories > Sprinkler Valves Home & Garden > Lawn & Garden > Watering & Irrigation > Sprinklers & Sprinkler Heads -Home & Garden > Lawn & Garden > Watering & Irrigation > Sprinklers & Sprinkler Heads > Sprinkler Heads -Home & Garden > Lawn & Garden > Watering & Irrigation > Sprinklers & Sprinkler Heads > Sprinklers +Home & Garden > Lawn & Garden > Watering & Irrigation > Watering Can Accesssories Home & Garden > Lawn & Garden > Watering & Irrigation > Watering Cans +Home & Garden > Lawn & Garden > Watering & Irrigation > Watering Globes & Spikes Home & Garden > Lighting Home & Garden > Lighting > Emergency Lighting +Home & Garden > Lighting > Floating & Submersible Lights Home & Garden > Lighting > Flood & Spot Lights +Home & Garden > Lighting > In-Ground Lights Home & Garden > Lighting > Lamps -Home & Garden > Lighting > Lamps > Floor Lamps -Home & Garden > Lighting > Lamps > Table Lamps -Home & Garden > Lighting > Landscape Lighting -Home & Garden > Lighting > Landscape Lighting > Deck Lights -Home & Garden > Lighting > Landscape Lighting > Landscape Lanterns & Torches -Home & Garden > Lighting > Landscape Lighting > Landscape Pathway Lighting -Home & Garden > Lighting > Landscape Lighting > Landscape Well Lights +Home & Garden > Lighting > Landscape Pathway Lighting Home & Garden > Lighting > Light Bulbs Home & Garden > Lighting > Light Bulbs > Compact Fluorescent Lamps Home & Garden > Lighting > Light Bulbs > Fluorescent Tubes @@ -4471,13 +3872,13 @@ Home & Garden > Lighting > Light Bulbs > Incandescent Light Bulbs Home & Garden > Lighting > Light Bulbs > LED Light Bulbs Home & Garden > Lighting > Light Ropes & Strings Home & Garden > Lighting > Lighting Fixtures +Home & Garden > Lighting > Lighting Fixtures > Cabinet Light Fixtures Home & Garden > Lighting > Lighting Fixtures > Ceiling Light Fixtures Home & Garden > Lighting > Lighting Fixtures > Chandeliers -Home & Garden > Lighting > Lighting Fixtures > Under Cabinet Light Fixtures Home & Garden > Lighting > Lighting Fixtures > Wall Light Fixtures -Home & Garden > Lighting > Lighting Fixtures > Wall Light Fixtures > Wall Sconces -Home & Garden > Lighting > Night Lights +Home & Garden > Lighting > Night Lights & Ambient Lighting Home & Garden > Lighting > Picture Lights +Home & Garden > Lighting > Tiki Torches & Oil Lamps Home & Garden > Lighting > Track Lighting Home & Garden > Lighting > Track Lighting > Track Lighting Accessories Home & Garden > Lighting > Track Lighting > Track Lighting Fixtures @@ -4487,14 +3888,13 @@ Home & Garden > Lighting Accessories > Lamp Post Bases Home & Garden > Lighting Accessories > Lamp Post Mounts Home & Garden > Lighting Accessories > Lamp Shades Home & Garden > Lighting Accessories > Lighting Timers +Home & Garden > Lighting Accessories > Oil Lamp Fuel Home & Garden > Linens & Bedding Home & Garden > Linens & Bedding > Bedding +Home & Garden > Linens & Bedding > Bedding > Bed Canopies Home & Garden > Linens & Bedding > Bedding > Bed Sheets Home & Garden > Linens & Bedding > Bedding > Bedskirts Home & Garden > Linens & Bedding > Bedding > Blankets -Home & Garden > Linens & Bedding > Bedding > Blankets > Electric Blankets -Home & Garden > Linens & Bedding > Bedding > Blankets > Throw Blankets -Home & Garden > Linens & Bedding > Bedding > Comforters & Comforter Sets Home & Garden > Linens & Bedding > Bedding > Duvet Covers Home & Garden > Linens & Bedding > Bedding > Mattress Protectors Home & Garden > Linens & Bedding > Bedding > Mattress Protectors > Mattress Encasements @@ -4502,10 +3902,8 @@ Home & Garden > Linens & Bedding > Bedding > Mattress Protectors > Mattress Pads Home & Garden > Linens & Bedding > Bedding > Nap Mats Home & Garden > Linens & Bedding > Bedding > Pillowcases & Shams Home & Garden > Linens & Bedding > Bedding > Pillows -Home & Garden > Linens & Bedding > Bedding > Pillows > Body Pillows -Home & Garden > Linens & Bedding > Bedding > Quilts & Quilt Sets -Home & Garden > Linens & Bedding > Table Linen Accessories -Home & Garden > Linens & Bedding > Table Linen Accessories > Tablecloth Clips & Weights +Home & Garden > Linens & Bedding > Bedding > Quilts & Comforters +Home & Garden > Linens & Bedding > Kitchen Linens Sets Home & Garden > Linens & Bedding > Table Linens Home & Garden > Linens & Bedding > Table Linens > Cloth Napkins Home & Garden > Linens & Bedding > Table Linens > Doilies @@ -4522,24 +3920,25 @@ Home & Garden > Plants Home & Garden > Plants > Aquatic Plants Home & Garden > Plants > Flowers Home & Garden > Plants > Indoor & Outdoor Plants -Home & Garden > Plants > Indoor & Outdoor Plants > Indoor Plants -Home & Garden > Plants > Indoor & Outdoor Plants > Outdoor Plants +Home & Garden > Plants > Plant & Herb Growing Kits Home & Garden > Plants > Seeds Home & Garden > Plants > Trees Home & Garden > Pool & Spa Home & Garden > Pool & Spa > Pool & Spa Accessories -Home & Garden > Pool & Spa > Pool & Spa Accessories > Child Swimming Aids Home & Garden > Pool & Spa > Pool & Spa Accessories > Diving Boards +Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool & Spa Chlorine Generators Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool & Spa Filters -Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Brushes +Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool & Spa Maintenance Kits +Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Brushes & Brooms Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Cleaner Hoses Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Cleaners & Chemicals -Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Covers +Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Cover Accessories +Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Covers & Ground Cloths Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Deck Kits Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Floats & Loungers -Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Floats & Loungers > Baby Floats Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Heaters -Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Ladders +Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Ladders, Steps & Ramps +Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Liners Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Skimmers Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Sweeps & Vacuums Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Toys @@ -4552,28 +3951,24 @@ Home & Garden > Smoking Accessories > Ashtrays Home & Garden > Smoking Accessories > Cigar Cases Home & Garden > Smoking Accessories > Cigar Cutters & Punches Home & Garden > Smoking Accessories > Cigarette Cases +Home & Garden > Smoking Accessories > Cigarette Holders Home & Garden > Smoking Accessories > Humidor Accessories Home & Garden > Smoking Accessories > Humidors -Home & Garden > Smoking Accessories > Lighters -Home & Garden > Smoking Accessories > Matches Home & Garden > Umbrella Sleeves & Cases Home & Garden > Wood Stoves Luggage & Bags -Luggage & Bags > Backpack Accessories -Luggage & Bags > Backpack Accessories > Backpack Covers Luggage & Bags > Backpacks -Luggage & Bags > Business Bags -Luggage & Bags > Business Bags > Briefcases -Luggage & Bags > Business Bags > Electronics Bags & Cases -Luggage & Bags > Business Bags > Electronics Bags & Cases > Computer Skins & Sleeves -Luggage & Bags > Business Bags > Electronics Bags & Cases > Laptop Bags & Cases -Luggage & Bags > Business Bags > Electronics Bags & Cases > Tablet Computer Bags & Cases -Luggage & Bags > Business Bags > Garment Bags +Luggage & Bags > Briefcases Luggage & Bags > Cosmetic & Toiletry Bags Luggage & Bags > Diaper Bags +Luggage & Bags > Dry Boxes Luggage & Bags > Duffel Bags Luggage & Bags > Fanny Packs +Luggage & Bags > Garment Bags Luggage & Bags > Luggage Accessories +Luggage & Bags > Luggage Accessories > Dry Box Liners & Inserts +Luggage & Bags > Luggage Accessories > Luggage Covers +Luggage & Bags > Luggage Accessories > Luggage Racks & Stands Luggage & Bags > Luggage Accessories > Luggage Straps Luggage & Bags > Luggage Accessories > Luggage Tags Luggage & Bags > Luggage Accessories > Packing Organizers @@ -4582,12 +3977,10 @@ Luggage & Bags > Luggage Accessories > Travel Pouches Luggage & Bags > Messenger Bags Luggage & Bags > Shopping Totes Luggage & Bags > Suitcases -Luggage & Bags > Suitcases > Carry-On Luggage Luggage & Bags > Train Cases Mature Mature > Erotic Mature > Erotic > Erotic Books -Mature > Erotic > Erotic Books > Erotic Comics Mature > Erotic > Erotic Clothing Mature > Erotic > Erotic DVDs & Videos Mature > Erotic > Erotic Food & Edibles @@ -4597,17 +3990,23 @@ Mature > Erotic > Pole Dancing Kits Mature > Erotic > Sex Toys Mature > Weapons Mature > Weapons > Brass Knuckles -Mature > Weapons > Clubs +Mature > Weapons > Clubs & Batons Mature > Weapons > Combat Knives -Mature > Weapons > Gun Accessories -Mature > Weapons > Gun Accessories > Ammunition -Mature > Weapons > Gun Accessories > Ammunition Belts -Mature > Weapons > Gun Accessories > Ammunition Boxes -Mature > Weapons > Gun Accessories > Gun Bags & Cases -Mature > Weapons > Gun Accessories > Gun Grips -Mature > Weapons > Gun Accessories > Gun Holsters -Mature > Weapons > Gun Accessories > Gun Lights -Mature > Weapons > Gun Accessories > Gun Rails +Mature > Weapons > Gun Care & Accessories +Mature > Weapons > Gun Care & Accessories > Ammunition +Mature > Weapons > Gun Care & Accessories > Ammunition Cases & Holders +Mature > Weapons > Gun Care & Accessories > Gun Cases & Range Bags +Mature > Weapons > Gun Care & Accessories > Gun Cleaning +Mature > Weapons > Gun Care & Accessories > Gun Cleaning > Gun Cleaning Cloths & Swabs +Mature > Weapons > Gun Care & Accessories > Gun Cleaning > Gun Cleaning Patches +Mature > Weapons > Gun Care & Accessories > Gun Cleaning > Gun Cleaning Solvents +Mature > Weapons > Gun Care & Accessories > Gun Grips +Mature > Weapons > Gun Care & Accessories > Gun Holsters +Mature > Weapons > Gun Care & Accessories > Gun Lights +Mature > Weapons > Gun Care & Accessories > Gun Rails +Mature > Weapons > Gun Care & Accessories > Gun Slings +Mature > Weapons > Gun Care & Accessories > Reloading Supplies & Equipment +Mature > Weapons > Gun Care & Accessories > Reloading Supplies & Equipment > Ammunition Reloading Presses Mature > Weapons > Guns Mature > Weapons > Mace & Pepper Spray Mature > Weapons > Nunchucks @@ -4619,71 +4018,19 @@ Mature > Weapons > Throwing Stars Mature > Weapons > Whips Media Media > Books -Media > Books > Fiction -Media > Books > Fiction > Children's Books -Media > Books > Fiction > Comics -Media > Books > Fiction > Horror Novels -Media > Books > Fiction > Literature -Media > Books > Fiction > Mystery Novels -Media > Books > Fiction > Romance Novels -Media > Books > Fiction > Science Fiction & Fantasy Novels -Media > Books > Non-Fiction -Media > Books > Non-Fiction > Animal & Nature Books -Media > Books > Non-Fiction > Architecture Books -Media > Books > Non-Fiction > Art Books -Media > Books > Non-Fiction > Biographies -Media > Books > Non-Fiction > Body, Mind & Spirit Books -Media > Books > Non-Fiction > Business & Economics Books -Media > Books > Non-Fiction > Coloring Books -Media > Books > Non-Fiction > Computer Books -Media > Books > Non-Fiction > Cooking Books -Media > Books > Non-Fiction > Craft, Hobby & Activity Books -Media > Books > Non-Fiction > Drama Books -Media > Books > Non-Fiction > Education Books -Media > Books > Non-Fiction > Education Books > Foreign Language Books -Media > Books > Non-Fiction > Education Books > Study Aids -Media > Books > Non-Fiction > Family Relationship Books -Media > Books > Non-Fiction > Game Books -Media > Books > Non-Fiction > Gardening Books -Media > Books > Non-Fiction > Health & Fitness Books -Media > Books > Non-Fiction > History Books -Media > Books > Non-Fiction > Home Improvement Books -Media > Books > Non-Fiction > Humor Books -Media > Books > Non-Fiction > Juvenile Non-Fiction -Media > Books > Non-Fiction > Language Arts Books -Media > Books > Non-Fiction > Law Books -Media > Books > Non-Fiction > Literary Books -Media > Books > Non-Fiction > Math Books -Media > Books > Non-Fiction > Medical Books -Media > Books > Non-Fiction > Music Books -Media > Books > Non-Fiction > Performing Arts Books -Media > Books > Non-Fiction > Pet Books -Media > Books > Non-Fiction > Philosophy Books -Media > Books > Non-Fiction > Photography Books -Media > Books > Non-Fiction > Poetry -Media > Books > Non-Fiction > Political Science Books -Media > Books > Non-Fiction > Psychology Books -Media > Books > Non-Fiction > Puzzle Books -Media > Books > Non-Fiction > Reference Books -Media > Books > Non-Fiction > Religion Books -Media > Books > Non-Fiction > Science Books -Media > Books > Non-Fiction > Self Help Books -Media > Books > Non-Fiction > Social Science Books -Media > Books > Non-Fiction > Sports Books -Media > Books > Non-Fiction > Technology Books -Media > Books > Non-Fiction > Transportation Books -Media > Books > Non-Fiction > Travel Books -Media > Books > Non-Fiction > True Crime Books +Media > Carpentry & Woodworking Project Plans Media > DVDs & Videos Media > Magazines & Newspapers -Media > Music +Media > Music & Sound Recordings Media > Product Manuals +Media > Product Manuals > Camera & Optics Manuals Media > Product Manuals > Electronics Manuals +Media > Product Manuals > Exercise & Fitness Equipment Manuals Media > Product Manuals > Household Appliance Manuals Media > Product Manuals > Kitchen Appliance Manuals Media > Product Manuals > Model & Toys Manuals +Media > Product Manuals > Office Supply Manuals Media > Product Manuals > Power Tool & Equipment Manuals -Media > Product Manuals > Sports & Recreation Manuals Media > Product Manuals > Vehicle Service Manuals Media > Sheet Music Office Supplies @@ -4692,6 +4039,7 @@ Office Supplies > Book Accessories > Book Covers Office Supplies > Book Accessories > Book Lights Office Supplies > Book Accessories > Book Stands & Rests Office Supplies > Book Accessories > Bookmarks +Office Supplies > Desk Pads & Blotters Office Supplies > Filing & Organization Office Supplies > Filing & Organization > Address Books Office Supplies > Filing & Organization > Binding Supplies @@ -4704,64 +4052,55 @@ Office Supplies > Filing & Organization > Binding Supplies > Binding Combs & Spi Office Supplies > Filing & Organization > Binding Supplies > Binding Machines Office Supplies > Filing & Organization > Business Card Books Office Supplies > Filing & Organization > Business Card Stands -Office Supplies > Filing & Organization > CD/DVD Organizers -Office Supplies > Filing & Organization > CD/DVD Organizers > CD/DVD Pouches & Visors -Office Supplies > Filing & Organization > CD/DVD Organizers > CD/DVD Sleeves -Office Supplies > Filing & Organization > CD/DVD Organizers > Jewel Cases +Office Supplies > Filing & Organization > CD/DVD Cases & Organizers Office Supplies > Filing & Organization > Calendars, Organizers & Planners Office Supplies > Filing & Organization > Card Files Office Supplies > Filing & Organization > Card Sleeves Office Supplies > Filing & Organization > Cash Boxes Office Supplies > Filing & Organization > Desk Organizers -Office Supplies > Filing & Organization > Desk Organizers > Desk Trays Office Supplies > Filing & Organization > File Boxes Office Supplies > Filing & Organization > File Folders Office Supplies > Filing & Organization > Folders & Report Covers Office Supplies > Filing & Organization > Greeting Card Organizers -Office Supplies > Filing & Organization > Laminating -Office Supplies > Filing & Organization > Laminating > Laminating Film, Pouches & Sheets -Office Supplies > Filing & Organization > Laminating > Laminators Office Supplies > Filing & Organization > Mail Sorters Office Supplies > Filing & Organization > Pen & Pencil Cases Office Supplies > Filing & Organization > Portfolios & Padfolios Office Supplies > Filing & Organization > Recipe Card Boxes -Office Supplies > Filing & Organization > Storage Lockers & Cabinets -Office Supplies > General Supplies -Office Supplies > General Supplies > Adhesives -Office Supplies > General Supplies > Adhesives > Office Tape -Office Supplies > General Supplies > Brass Fasteners -Office Supplies > General Supplies > Correction -Office Supplies > General Supplies > Correction > Correction Fluids, Pens & Tapes -Office Supplies > General Supplies > Correction > Erasers -Office Supplies > General Supplies > Labels & Tags -Office Supplies > General Supplies > Labels & Tags > Address Labels -Office Supplies > General Supplies > Labels & Tags > Folder Tabs -Office Supplies > General Supplies > Labels & Tags > Label Clips -Office Supplies > General Supplies > Labels & Tags > Label Maker Tape -Office Supplies > General Supplies > Labels & Tags > Shipping Labels -Office Supplies > General Supplies > Labels & Tags > Shipping Tags -Office Supplies > General Supplies > Paper Clips & Clamps -Office Supplies > General Supplies > Paper Products -Office Supplies > General Supplies > Paper Products > Binder Paper -Office Supplies > General Supplies > Paper Products > Blank ID Cards -Office Supplies > General Supplies > Paper Products > Business Cards -Office Supplies > General Supplies > Paper Products > Business Forms & Receipts -Office Supplies > General Supplies > Paper Products > Checks -Office Supplies > General Supplies > Paper Products > Cover Paper -Office Supplies > General Supplies > Paper Products > Envelopes -Office Supplies > General Supplies > Paper Products > Index Cards -Office Supplies > General Supplies > Paper Products > Notebooks & Notepads -Office Supplies > General Supplies > Paper Products > Post Cards -Office Supplies > General Supplies > Paper Products > Printer & Copier Paper -Office Supplies > General Supplies > Paper Products > Printer & Copier Paper > Photo Printer Paper -Office Supplies > General Supplies > Paper Products > Receipt Paper Rolls -Office Supplies > General Supplies > Paper Products > Stationery -Office Supplies > General Supplies > Paper Products > Sticky Notes -Office Supplies > General Supplies > Rubber Bands -Office Supplies > General Supplies > Stamp Pads & Inks -Office Supplies > General Supplies > Staples -Office Supplies > General Supplies > Tacks & Pushpins +Office Supplies > General Office Supplies +Office Supplies > General Office Supplies > Brass Fasteners +Office Supplies > General Office Supplies > Correction Fluids, Pens & Tapes +Office Supplies > General Office Supplies > Erasers +Office Supplies > General Office Supplies > Labels & Tags +Office Supplies > General Office Supplies > Labels & Tags > Address Labels +Office Supplies > General Office Supplies > Labels & Tags > Folder Tabs +Office Supplies > General Office Supplies > Labels & Tags > Label Clips +Office Supplies > General Office Supplies > Labels & Tags > Label Tapes & Refill Rolls +Office Supplies > General Office Supplies > Labels & Tags > Shipping Labels +Office Supplies > General Office Supplies > Labels & Tags > Shipping Tags +Office Supplies > General Office Supplies > Laminating Film, Pouches & Sheets +Office Supplies > General Office Supplies > Mounting Putty +Office Supplies > General Office Supplies > Office Tape +Office Supplies > General Office Supplies > Paper Clips & Clamps +Office Supplies > General Office Supplies > Paper Products +Office Supplies > General Office Supplies > Paper Products > Binder Paper +Office Supplies > General Office Supplies > Paper Products > Blank ID Cards +Office Supplies > General Office Supplies > Paper Products > Business Cards +Office Supplies > General Office Supplies > Paper Products > Business Forms & Receipts +Office Supplies > General Office Supplies > Paper Products > Checks +Office Supplies > General Office Supplies > Paper Products > Cover Paper +Office Supplies > General Office Supplies > Paper Products > Envelopes +Office Supplies > General Office Supplies > Paper Products > Index Cards +Office Supplies > General Office Supplies > Paper Products > Notebooks & Notepads +Office Supplies > General Office Supplies > Paper Products > Post Cards +Office Supplies > General Office Supplies > Paper Products > Printer & Copier Paper +Office Supplies > General Office Supplies > Paper Products > Receipt & Adding Machine Paper Rolls +Office Supplies > General Office Supplies > Paper Products > Stationery +Office Supplies > General Office Supplies > Paper Products > Sticky Notes +Office Supplies > General Office Supplies > Rubber Bands +Office Supplies > General Office Supplies > Staples +Office Supplies > General Office Supplies > Tacks & Pushpins Office Supplies > Impulse Sealers +Office Supplies > Lap Desks Office Supplies > Name Plates Office Supplies > Office & Chair Mats Office Supplies > Office & Chair Mats > Anti-Fatigue Mats @@ -4774,9 +4113,11 @@ Office Supplies > Office Carts > File Carts Office Supplies > Office Carts > Mail Carts Office Supplies > Office Carts > Utility Carts Office Supplies > Office Equipment +Office Supplies > Office Equipment > Calculator Accessories Office Supplies > Office Equipment > Calculators Office Supplies > Office Equipment > Electronic Dictionaries & Translators Office Supplies > Office Equipment > Label Makers +Office Supplies > Office Equipment > Laminators Office Supplies > Office Equipment > Office Shredders Office Supplies > Office Equipment > Postage Meters Office Supplies > Office Equipment > Time & Attendance Clocks @@ -4785,43 +4126,33 @@ Office Supplies > Office Equipment > Typewriters Office Supplies > Office Instruments Office Supplies > Office Instruments > Call Bells Office Supplies > Office Instruments > Clipboards +Office Supplies > Office Instruments > Letter Openers Office Supplies > Office Instruments > Magnifiers -Office Supplies > Office Instruments > Office Rulers +Office Supplies > Office Instruments > Office Rubber Stamps Office Supplies > Office Instruments > Pencil Sharpeners -Office Supplies > Office Instruments > Rubber Stamps -Office Supplies > Office Instruments > Rubber Stamps > Decorative Rubber Stamps -Office Supplies > Office Instruments > Rubber Stamps > Office Rubber Stamps -Office Supplies > Office Instruments > Scissors Office Supplies > Office Instruments > Staple Removers Office Supplies > Office Instruments > Staplers +Office Supplies > Office Instruments > Tape Dispensers Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories > Marker & Highlighter Ink Refills Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories > Pen Ink & Refills -Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories > Pen Replacement Tips Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories > Pencil Lead & Refills Office Supplies > Office Instruments > Writing & Drawing Instruments Office Supplies > Office Instruments > Writing & Drawing Instruments > Art Charcoals Office Supplies > Office Instruments > Writing & Drawing Instruments > Chalk Office Supplies > Office Instruments > Writing & Drawing Instruments > Crayons Office Supplies > Office Instruments > Writing & Drawing Instruments > Markers & Highlighters +Office Supplies > Office Instruments > Writing & Drawing Instruments > Multifunction Writing Instruments Office Supplies > Office Instruments > Writing & Drawing Instruments > Pastels Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils -Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Multifunction Writing Instruments Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pen & Pencil Sets Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pencils Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pencils > Art Pencils Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pencils > Writing Pencils Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pens Office Supplies > Paper Handling -Office Supplies > Paper Handling > Craft Knives -Office Supplies > Paper Handling > Cutting Mats Office Supplies > Paper Handling > Fingertip Grips Office Supplies > Paper Handling > Hole Punches -Office Supplies > Paper Handling > Hole Punches > Decorative Hole Punches -Office Supplies > Paper Handling > Hole Punches > Office Hole Punches -Office Supplies > Paper Handling > Paper Cutter Accessories -Office Supplies > Paper Handling > Paper Cutter Accessories > Paper Cutter Stands -Office Supplies > Paper Handling > Paper Cutters Office Supplies > Paper Handling > Paper Folding Machines Office Supplies > Paper Handling > Paper Joggers Office Supplies > Paper Handling > Paperweights @@ -4836,36 +4167,40 @@ Office Supplies > Presentation Supplies > Display Boards > Foam Boards Office Supplies > Presentation Supplies > Display Boards > Mounting Boards Office Supplies > Presentation Supplies > Display Boards > Poster Boards Office Supplies > Presentation Supplies > Document Cameras +Office Supplies > Presentation Supplies > Dry-Erase Boards Office Supplies > Presentation Supplies > Easel Pads Office Supplies > Presentation Supplies > Easels Office Supplies > Presentation Supplies > Laser Pointers Office Supplies > Presentation Supplies > Lecterns Office Supplies > Presentation Supplies > Transparencies -Office Supplies > Presentation Supplies > Whiteboards Office Supplies > Presentation Supplies > Wireless Presenters Office Supplies > Shipping Supplies +Office Supplies > Shipping Supplies > Moving & Shipping Boxes Office Supplies > Shipping Supplies > Packing Materials Office Supplies > Shipping Supplies > Packing Tape -Office Supplies > Shipping Supplies > Postal Scales -Office Supplies > Shipping Supplies > Shipping Boxes Religious & Ceremonial Religious & Ceremonial > Memorial Ceremony Supplies Religious & Ceremonial > Memorial Ceremony Supplies > Memorial Urns Religious & Ceremonial > Religious Items Religious & Ceremonial > Religious Items > Prayer Beads +Religious & Ceremonial > Religious Items > Prayer Cards Religious & Ceremonial > Religious Items > Religious Altars Religious & Ceremonial > Religious Items > Religious Veils +Religious & Ceremonial > Religious Items > Tarot Cards Religious & Ceremonial > Wedding Ceremony Supplies +Religious & Ceremonial > Wedding Ceremony Supplies > Aisle Runners Religious & Ceremonial > Wedding Ceremony Supplies > Flower Girl Baskets -Religious & Ceremonial > Wedding Ceremony Supplies > Ring Pillows +Religious & Ceremonial > Wedding Ceremony Supplies > Ring Pillows & Holders Software Software > Computer Software Software > Computer Software > Antivirus & Security Software Software > Computer Software > Business & Productivity Software Software > Computer Software > Compilers & Programming Tools -Software > Computer Software > Computer Utilities & Maintenance +Software > Computer Software > Computer Utilities & Maintenance Software +Software > Computer Software > Dictionary & Translation Software Software > Computer Software > Educational Software Software > Computer Software > Financial, Tax & Accounting Software +Software > Computer Software > GPS Map Data & Software Software > Computer Software > Handheld & PDA Software Software > Computer Software > Multimedia & Design Software Software > Computer Software > Multimedia & Design Software > 3D Modeling Software @@ -4881,147 +4216,324 @@ Software > Computer Software > Multimedia & Design Software > Web Design Softwar Software > Computer Software > Network Software Software > Computer Software > Office Application Software Software > Computer Software > Operating Systems -Software > Computer Software > Reference Software -Software > Computer Software > Reference Software > Dictionary & Translation Software -Software > Computer Software > Reference Software > GPS Map Data & Software Software > Computer Software > Restore Disks Software > Digital Goods & Currency -Software > Digital Goods & Currency > Clip Art Software > Digital Goods & Currency > Computer Icons Software > Digital Goods & Currency > Desktop Wallpaper +Software > Digital Goods & Currency > Digital Artwork Software > Digital Goods & Currency > Document Templates Software > Digital Goods & Currency > Fonts +Software > Digital Goods & Currency > Stock Photographs & Video Footage Software > Digital Goods & Currency > Virtual Currency Software > Video Game Software -Software > Video Game Software > All Game Boy Games -Software > Video Game Software > All Game Boy Games > Game Boy Advance Games -Software > Video Game Software > All Game Boy Games > Game Boy Games -Software > Video Game Software > All PlayStation Games -Software > Video Game Software > All PlayStation Games > PlayStation (original) Games -Software > Video Game Software > All PlayStation Games > PlayStation 2 Games -Software > Video Game Software > All PlayStation Games > PlayStation 3 Games -Software > Video Game Software > All XBox Games -Software > Video Game Software > All XBox Games > XBox (original) Games -Software > Video Game Software > All XBox Games > XBox 360 Games -Software > Video Game Software > Atari 2600 Games -Software > Video Game Software > Atari 5200 Games -Software > Video Game Software > Atari Lynx Games -Software > Video Game Software > ColecoVision Games -Software > Video Game Software > Computer Games -Software > Video Game Software > Computer Games > Mac Games -Software > Video Game Software > Computer Games > PC Games -Software > Video Game Software > Dreamcast Games -Software > Video Game Software > Game Gear Games -Software > Video Game Software > GameCube Games -Software > Video Game Software > Intellivision Games -Software > Video Game Software > Jaguar Games -Software > Video Game Software > LeapFrog Games -Software > Video Game Software > N-Gage Games -Software > Video Game Software > Neo Geo Games -Software > Video Game Software > Neo Geo Pocket Games -Software > Video Game Software > Nintendo 64 Games -Software > Video Game Software > Nintendo DS Games -Software > Video Game Software > Nintendo Entertainment System Games -Software > Video Game Software > PlayStation Portable Games -Software > Video Game Software > PlayStation Vita Games -Software > Video Game Software > Sega Genesis Games -Software > Video Game Software > Sega Master System Games -Software > Video Game Software > Super Nintendo Games -Software > Video Game Software > Turbografx 16 Games -Software > Video Game Software > Wii Games -Software > Video Game Software > Wii U Games Sporting Goods -Sporting Goods > Air Sports -Sporting Goods > Air Sports > Air Suits -Sporting Goods > Air Sports > Hang Gliding -Sporting Goods > Air Sports > Hang Gliding > Hang Gliders -Sporting Goods > Air Sports > Parachutes -Sporting Goods > Combat Sports -Sporting Goods > Combat Sports > Boxing -Sporting Goods > Combat Sports > Boxing & Martial Arts Protective Gear -Sporting Goods > Combat Sports > Boxing > Boxing Gloves & Mitts -Sporting Goods > Combat Sports > Boxing > Boxing Ring Parts -Sporting Goods > Combat Sports > Boxing > Boxing Rings -Sporting Goods > Combat Sports > Boxing > Punching Bag Accessories -Sporting Goods > Combat Sports > Fencing -Sporting Goods > Combat Sports > Fencing > Fencing Protective Gear -Sporting Goods > Combat Sports > Fencing > Fencing Protective Gear > Fencing Gloves -Sporting Goods > Combat Sports > Fencing > Fencing Protective Gear > Fencing Masks -Sporting Goods > Combat Sports > Fencing > Fencing Weapons -Sporting Goods > Combat Sports > Grappling Dummies -Sporting Goods > Combat Sports > Martial Arts -Sporting Goods > Combat Sports > Martial Arts > Martial Arts Belts -Sporting Goods > Combat Sports > Martial Arts > Martial Arts Weapons -Sporting Goods > Combat Sports > Punching & Training Bag Accessories -Sporting Goods > Combat Sports > Punching & Training Bags -Sporting Goods > Combat Sports > Wrestling -Sporting Goods > Combat Sports > Wrestling > Wrestling Mats -Sporting Goods > Combat Sports > Wrestling > Wrestling Protective Gear -Sporting Goods > Dancing -Sporting Goods > Dancing > Ballet Bars +Sporting Goods > Athletics +Sporting Goods > Athletics > Baseball & Softball +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Bases & Plates +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Batting Gloves +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Gloves & Mitts +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Pitching Mats +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Pitching Mounds +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear > Baseball & Softball Batting Helmets +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear > Baseball & Softball Chest Protectors +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear > Baseball & Softball Leg Guards +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear > Catchers Equipment Sets +Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear > Catchers Helmets & Masks +Sporting Goods > Athletics > Baseball & Softball > Baseball Bats +Sporting Goods > Athletics > Baseball & Softball > Baseballs +Sporting Goods > Athletics > Baseball & Softball > Pitching Machines +Sporting Goods > Athletics > Baseball & Softball > Softball Bats +Sporting Goods > Athletics > Baseball & Softball > Softballs +Sporting Goods > Athletics > Basketball +Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories +Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories > Basketball Backboards +Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories > Basketball Hoop Padding +Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories > Basketball Hoop Posts +Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories > Basketball Nets +Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories > Basketball Rims +Sporting Goods > Athletics > Basketball > Basketball Hoops +Sporting Goods > Athletics > Basketball > Basketball Training Aids +Sporting Goods > Athletics > Basketball > Basketballs +Sporting Goods > Athletics > Boxing & Martial Arts +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > Boxing & MMA Hand Wraps +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > Boxing & Martial Arts Arm Guards +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > Boxing & Martial Arts Body Protectors +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > Boxing & Martial Arts Headgear +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > Boxing Gloves & Mitts +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > MMA Shin Guards +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment > Boxing & MMA Punch Mitts +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment > Grappling Dummies +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment > Punching & Training Bag Accessories +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment > Punching & Training Bags +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment > Strike Shields +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing Ring Parts +Sporting Goods > Athletics > Boxing & Martial Arts > Boxing Rings +Sporting Goods > Athletics > Boxing & Martial Arts > Martial Arts Belts +Sporting Goods > Athletics > Boxing & Martial Arts > Martial Arts Weapons +Sporting Goods > Athletics > Broomball Equipment +Sporting Goods > Athletics > Cheerleading +Sporting Goods > Athletics > Cheerleading > Cheerleading Pom Poms +Sporting Goods > Athletics > Coaching & Officiating +Sporting Goods > Athletics > Coaching & Officiating > Captains Armbands +Sporting Goods > Athletics > Coaching & Officiating > Field & Court Boundary Markers +Sporting Goods > Athletics > Coaching & Officiating > Flip Coins & Discs +Sporting Goods > Athletics > Coaching & Officiating > Linesman Flags +Sporting Goods > Athletics > Coaching & Officiating > Penalty Cards & Flags +Sporting Goods > Athletics > Coaching & Officiating > Pitch Counters +Sporting Goods > Athletics > Coaching & Officiating > Referee Stands & Chairs +Sporting Goods > Athletics > Coaching & Officiating > Referee Wallets +Sporting Goods > Athletics > Coaching & Officiating > Scoreboards +Sporting Goods > Athletics > Coaching & Officiating > Sport & Safety Whistles +Sporting Goods > Athletics > Coaching & Officiating > Umpire Indicators +Sporting Goods > Athletics > Cricket +Sporting Goods > Athletics > Cricket > Cricket Balls +Sporting Goods > Athletics > Cricket > Cricket Bat Accessories +Sporting Goods > Athletics > Cricket > Cricket Bat Accessories > Cricket Bat Grips +Sporting Goods > Athletics > Cricket > Cricket Bats +Sporting Goods > Athletics > Cricket > Cricket Equipment Sets +Sporting Goods > Athletics > Cricket > Cricket Protective Gear +Sporting Goods > Athletics > Cricket > Cricket Protective Gear > Cricket Gloves +Sporting Goods > Athletics > Cricket > Cricket Protective Gear > Cricket Helmets +Sporting Goods > Athletics > Cricket > Cricket Protective Gear > Cricket Leg Guards +Sporting Goods > Athletics > Cricket > Cricket Stumps +Sporting Goods > Athletics > Dancing +Sporting Goods > Athletics > Dancing > Ballet Barres +Sporting Goods > Athletics > Fencing +Sporting Goods > Athletics > Fencing > Fencing Protective Gear +Sporting Goods > Athletics > Fencing > Fencing Protective Gear > Fencing Gloves & Cuffs +Sporting Goods > Athletics > Fencing > Fencing Protective Gear > Fencing Jackets & Lamés +Sporting Goods > Athletics > Fencing > Fencing Protective Gear > Fencing Masks +Sporting Goods > Athletics > Fencing > Fencing Weapons +Sporting Goods > Athletics > Field Hockey & Lacrosse +Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey & Lacrosse Protective Gear +Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey & Lacrosse Protective Gear > Field Hockey & Lacrosse Gloves +Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey & Lacrosse Protective Gear > Field Hockey & Lacrosse Helmets +Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey & Lacrosse Protective Gear > Field Hockey & Lacrosse Masks & Goggles +Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey & Lacrosse Protective Gear > Field Hockey & Lacrosse Pads +Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey Balls +Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey Goals +Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey Sticks +Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Balls +Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Equipment Sets +Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Goals +Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Stick Parts +Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Stick Parts > Lacrosse Mesh & String +Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Stick Parts > Lacrosse Stick Heads +Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Stick Parts > Lacrosse Stick Shafts +Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Sticks +Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Training Aids +Sporting Goods > Athletics > Figure Skating & Hockey +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Balls & Pucks +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Goals +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Elbow Pads +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Gloves +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Goalie Equipment Sets +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Helmets +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Pants +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Shin Guards & Leg Pads +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Shoulder Pads & Chest Protectors +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Suspenders & Belts +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Sledges +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Stick Care +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Stick Parts +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Stick Parts > Hockey Stick Blades +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Stick Parts > Hockey Stick Shafts +Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Sticks +Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories +Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories > Figure Skate Boots +Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories > Ice Skate Blades +Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories > Ice Skate Sharpeners +Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories > Skate Blade Guards +Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories > Skate Lace Tighteners +Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skates +Sporting Goods > Athletics > Football +Sporting Goods > Athletics > Football > Football Gloves +Sporting Goods > Athletics > Football > Football Goal Posts +Sporting Goods > Athletics > Football > Football Kicking Tees & Holders +Sporting Goods > Athletics > Football > Football Protective Gear +Sporting Goods > Athletics > Football > Football Protective Gear > Football Girdles +Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmet Accessories +Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmet Accessories > Football Chin Straps +Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmet Accessories > Football Face Masks +Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmet Accessories > Football Helmet Padding +Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmet Accessories > Football Helmet Visors +Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmets +Sporting Goods > Athletics > Football > Football Protective Gear > Football Neck Rolls +Sporting Goods > Athletics > Football > Football Protective Gear > Football Rib Protection Shirts & Vests +Sporting Goods > Athletics > Football > Football Protective Gear > Football Shoulder Pads +Sporting Goods > Athletics > Football > Football Training Equipment +Sporting Goods > Athletics > Football > Football Training Equipment > Football Dummies & Sleds +Sporting Goods > Athletics > Football > Footballs +Sporting Goods > Athletics > General Purpose Athletic Equipment +Sporting Goods > Athletics > General Purpose Athletic Equipment > Altitude Training Masks +Sporting Goods > Athletics > General Purpose Athletic Equipment > Athletic Cups +Sporting Goods > Athletics > General Purpose Athletic Equipment > Ball Carrying Bags & Carts +Sporting Goods > Athletics > General Purpose Athletic Equipment > Ball Pump Accessories +Sporting Goods > Athletics > General Purpose Athletic Equipment > Ball Pump Accessories > Ball Pump Needles +Sporting Goods > Athletics > General Purpose Athletic Equipment > Ball Pumps +Sporting Goods > Athletics > General Purpose Athletic Equipment > Exercise & Gym Mat Storage Racks & Carts +Sporting Goods > Athletics > General Purpose Athletic Equipment > Grip Spray & Chalk +Sporting Goods > Athletics > General Purpose Athletic Equipment > Gym Mats +Sporting Goods > Athletics > General Purpose Athletic Equipment > Practice Nets & Screens +Sporting Goods > Athletics > General Purpose Athletic Equipment > Speed & Agility Ladders & Hurdles +Sporting Goods > Athletics > General Purpose Athletic Equipment > Sports & Agility Cones +Sporting Goods > Athletics > General Purpose Athletic Equipment > Sports Megaphones +Sporting Goods > Athletics > General Purpose Athletic Equipment > Sports Mouthguards +Sporting Goods > Athletics > General Purpose Athletic Equipment > Stadium Seats & Cushions +Sporting Goods > Athletics > Gymnastics +Sporting Goods > Athletics > Gymnastics > Gymnastics Bars & Balance Beams +Sporting Goods > Athletics > Gymnastics > Gymnastics Protective Gear +Sporting Goods > Athletics > Gymnastics > Gymnastics Protective Gear > Gymnastics Grips +Sporting Goods > Athletics > Gymnastics > Gymnastics Rings +Sporting Goods > Athletics > Gymnastics > Gymnastics Springboards +Sporting Goods > Athletics > Gymnastics > Pommel Horses +Sporting Goods > Athletics > Gymnastics > Vaulting Horses +Sporting Goods > Athletics > Racquetball & Squash +Sporting Goods > Athletics > Racquetball & Squash > Racquetball & Squash Balls +Sporting Goods > Athletics > Racquetball & Squash > Racquetball & Squash Eyewear +Sporting Goods > Athletics > Racquetball & Squash > Racquetball & Squash Gloves +Sporting Goods > Athletics > Racquetball & Squash > Racquetball Racquets +Sporting Goods > Athletics > Racquetball & Squash > Squash Racquets +Sporting Goods > Athletics > Rounders +Sporting Goods > Athletics > Rounders > Rounders Bats +Sporting Goods > Athletics > Rounders > Rounders Gloves +Sporting Goods > Athletics > Rugby +Sporting Goods > Athletics > Rugby > Rugby Balls +Sporting Goods > Athletics > Rugby > Rugby Gloves +Sporting Goods > Athletics > Rugby > Rugby Posts +Sporting Goods > Athletics > Rugby > Rugby Protective Gear +Sporting Goods > Athletics > Rugby > Rugby Protective Gear > Rugby Headgear +Sporting Goods > Athletics > Rugby > Rugby Training Aids +Sporting Goods > Athletics > Soccer +Sporting Goods > Athletics > Soccer > Soccer Balls +Sporting Goods > Athletics > Soccer > Soccer Corner Flags +Sporting Goods > Athletics > Soccer > Soccer Gloves +Sporting Goods > Athletics > Soccer > Soccer Goal Accessories +Sporting Goods > Athletics > Soccer > Soccer Goals +Sporting Goods > Athletics > Soccer > Soccer Protective Gear +Sporting Goods > Athletics > Soccer > Soccer Protective Gear > Soccer Shin Guards +Sporting Goods > Athletics > Team Handball +Sporting Goods > Athletics > Team Handball > Handballs +Sporting Goods > Athletics > Tennis +Sporting Goods > Athletics > Tennis > Tennis Ball Hoppers & Carts +Sporting Goods > Athletics > Tennis > Tennis Ball Machines +Sporting Goods > Athletics > Tennis > Tennis Ball Savers +Sporting Goods > Athletics > Tennis > Tennis Balls +Sporting Goods > Athletics > Tennis > Tennis Nets +Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories +Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories > Racquet Vibration Dampeners +Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories > Tennis Racquet Bags +Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories > Tennis Racquet Grips & Tape +Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories > Tennis Racquet Grommets +Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories > Tennis Racquet String +Sporting Goods > Athletics > Tennis > Tennis Racquets +Sporting Goods > Athletics > Track & Field +Sporting Goods > Athletics > Track & Field > Discus +Sporting Goods > Athletics > Track & Field > High Jump Crossbars +Sporting Goods > Athletics > Track & Field > High Jump Pits +Sporting Goods > Athletics > Track & Field > Javelins +Sporting Goods > Athletics > Track & Field > Pole Vault Pits +Sporting Goods > Athletics > Track & Field > Relay Batons +Sporting Goods > Athletics > Track & Field > Shot Puts +Sporting Goods > Athletics > Track & Field > Starter Pistols +Sporting Goods > Athletics > Track & Field > Throwing Hammers +Sporting Goods > Athletics > Track & Field > Track Hurdles +Sporting Goods > Athletics > Track & Field > Track Starting Blocks +Sporting Goods > Athletics > Track & Field > Vaulting Poles +Sporting Goods > Athletics > Volleyball +Sporting Goods > Athletics > Volleyball > Volleyball Nets +Sporting Goods > Athletics > Volleyball > Volleyball Protective Gear +Sporting Goods > Athletics > Volleyball > Volleyball Protective Gear > Volleyball Knee Pads +Sporting Goods > Athletics > Volleyball > Volleyball Training Aids +Sporting Goods > Athletics > Volleyball > Volleyballs +Sporting Goods > Athletics > Wallyball Equipment +Sporting Goods > Athletics > Water Polo +Sporting Goods > Athletics > Water Polo > Water Polo Balls +Sporting Goods > Athletics > Water Polo > Water Polo Caps +Sporting Goods > Athletics > Water Polo > Water Polo Goals +Sporting Goods > Athletics > Wrestling +Sporting Goods > Athletics > Wrestling > Wrestling Protective Gear +Sporting Goods > Athletics > Wrestling > Wrestling Protective Gear > Wrestling Headgear +Sporting Goods > Athletics > Wrestling > Wrestling Protective Gear > Wrestling Knee Pads Sporting Goods > Exercise & Fitness -Sporting Goods > Exercise & Fitness > Abdominal Equipment -Sporting Goods > Exercise & Fitness > Cardio Machine Accessories -Sporting Goods > Exercise & Fitness > Cardio Machines -Sporting Goods > Exercise & Fitness > Cardio Machines > Elliptical Trainers -Sporting Goods > Exercise & Fitness > Cardio Machines > Exercise Bikes -Sporting Goods > Exercise & Fitness > Cardio Machines > Rowing Machines -Sporting Goods > Exercise & Fitness > Cardio Machines > Stair Climbers -Sporting Goods > Exercise & Fitness > Cardio Machines > Treadmills +Sporting Goods > Exercise & Fitness > Ab Wheels & Rollers +Sporting Goods > Exercise & Fitness > Aerobic Steps +Sporting Goods > Exercise & Fitness > Balance Trainers +Sporting Goods > Exercise & Fitness > Cardio +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories > Elliptical Trainer Accessories +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories > Exercise Bike Accessories +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories > Rowing Machine Accessories +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories > Stair Climber & Stepper Accessories +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories > Treadmill Accessories +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Elliptical Trainers +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Exercise Bikes +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Rowing Machines +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Stair Climbers & Steppers +Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Treadmills +Sporting Goods > Exercise & Fitness > Cardio > Jump Ropes Sporting Goods > Exercise & Fitness > Exercise Balls Sporting Goods > Exercise & Fitness > Exercise Bands +Sporting Goods > Exercise & Fitness > Exercise Benches +Sporting Goods > Exercise & Fitness > Exercise Equipment Mats +Sporting Goods > Exercise & Fitness > Exercise Machine & Equipment Sets +Sporting Goods > Exercise & Fitness > Exercise Wedges Sporting Goods > Exercise & Fitness > Foam Roller Accessories Sporting Goods > Exercise & Fitness > Foam Roller Accessories > Foam Roller Storage Bags Sporting Goods > Exercise & Fitness > Foam Rollers -Sporting Goods > Exercise & Fitness > Free Weight Accessories -Sporting Goods > Exercise & Fitness > Free Weight Bars -Sporting Goods > Exercise & Fitness > Free Weights -Sporting Goods > Exercise & Fitness > Gym Mats -Sporting Goods > Exercise & Fitness > Gym Mats > Exercise Equipment Mats -Sporting Goods > Exercise & Fitness > Jump Ropes +Sporting Goods > Exercise & Fitness > Hand Exercisers +Sporting Goods > Exercise & Fitness > Inversion Tables & Systems Sporting Goods > Exercise & Fitness > Medicine Balls +Sporting Goods > Exercise & Fitness > Power Towers +Sporting Goods > Exercise & Fitness > Push Up & Pull Up Bars Sporting Goods > Exercise & Fitness > Reaction Balls +Sporting Goods > Exercise & Fitness > Speed & Resistance Parachutes +Sporting Goods > Exercise & Fitness > Sport Safety Lights & Reflectors Sporting Goods > Exercise & Fitness > Stopwatches -Sporting Goods > Exercise & Fitness > Weight Benches -Sporting Goods > Exercise & Fitness > Weight Lifting Belts -Sporting Goods > Exercise & Fitness > Weight Lifting Gloves & Hand Supports -Sporting Goods > Exercise & Fitness > Weight Lifting Machine Accessories -Sporting Goods > Exercise & Fitness > Weight Lifting Machines +Sporting Goods > Exercise & Fitness > Suspension Trainers +Sporting Goods > Exercise & Fitness > Vibration Exercise Machines +Sporting Goods > Exercise & Fitness > Weight Lifting +Sporting Goods > Exercise & Fitness > Weight Lifting > Free Weight Accessories +Sporting Goods > Exercise & Fitness > Weight Lifting > Free Weight Accessories > Free Weight Storage Racks +Sporting Goods > Exercise & Fitness > Weight Lifting > Free Weight Accessories > Weight Bar Collars +Sporting Goods > Exercise & Fitness > Weight Lifting > Free Weight Accessories > Weight Bars +Sporting Goods > Exercise & Fitness > Weight Lifting > Free Weights +Sporting Goods > Exercise & Fitness > Weight Lifting > Weight Lifting Belts +Sporting Goods > Exercise & Fitness > Weight Lifting > Weight Lifting Gloves & Hand Supports +Sporting Goods > Exercise & Fitness > Weight Lifting > Weight Lifting Machine & Exercise Bench Accessories +Sporting Goods > Exercise & Fitness > Weight Lifting > Weight Lifting Machines & Racks Sporting Goods > Exercise & Fitness > Weighted Clothing Sporting Goods > Exercise & Fitness > Yoga & Pilates Sporting Goods > Exercise & Fitness > Yoga & Pilates > Pilates Machines Sporting Goods > Exercise & Fitness > Yoga & Pilates > Yoga & Pilates Blocks Sporting Goods > Exercise & Fitness > Yoga & Pilates > Yoga & Pilates Mats +Sporting Goods > Exercise & Fitness > Yoga & Pilates > Yoga & Pilates Towels Sporting Goods > Exercise & Fitness > Yoga & Pilates > Yoga Mat Bags & Straps -Sporting Goods > Exercise & Fitness > Yoga & Pilates Accessories -Sporting Goods > Exercise & Fitness > Yoga & Pilates Accessories > Yoga & Pilates Towels -Sporting Goods > Gymnastics -Sporting Goods > Gymnastics > Balance Beams -Sporting Goods > Gymnastics > Gymnastics Bars -Sporting Goods > Gymnastics > Gymnastics Mats -Sporting Goods > Gymnastics > Gymnastics Protective Gear -Sporting Goods > Gymnastics > Gymnastics Rings -Sporting Goods > Gymnastics > Pommel Horses -Sporting Goods > Gymnastics > Springboards -Sporting Goods > Gymnastics > Vaulting Horses Sporting Goods > Indoor Games Sporting Goods > Indoor Games > Air Hockey -Sporting Goods > Indoor Games > Air Hockey > Air Hockey Pucks -Sporting Goods > Indoor Games > Air Hockey > Air Hockey Strikers +Sporting Goods > Indoor Games > Air Hockey > Air Hockey Equipment Sporting Goods > Indoor Games > Air Hockey > Air Hockey Table Parts Sporting Goods > Indoor Games > Air Hockey > Air Hockey Tables Sporting Goods > Indoor Games > Billiards Sporting Goods > Indoor Games > Billiards > Billiard Ball Racks Sporting Goods > Indoor Games > Billiards > Billiard Balls Sporting Goods > Indoor Games > Billiards > Billiard Cue Accessories +Sporting Goods > Indoor Games > Billiards > Billiard Cue Accessories > Billiard Cue Cases +Sporting Goods > Indoor Games > Billiards > Billiard Cue Accessories > Billiard Cue Chalk Sporting Goods > Indoor Games > Billiards > Billiard Cue Accessories > Billiard Cue Racks Sporting Goods > Indoor Games > Billiards > Billiard Cues & Bridges Sporting Goods > Indoor Games > Billiards > Billiard Gloves Sporting Goods > Indoor Games > Billiards > Billiard Table Lights Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories -Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories > Billiard Cloth Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories > Billiard Pockets Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories > Billiard Table Brushes +Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories > Billiard Table Cloth +Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories > Billiard Table Covers Sporting Goods > Indoor Games > Billiards > Billiard Tables Sporting Goods > Indoor Games > Bowling Sporting Goods > Indoor Games > Bowling > Bowling Ball Bags @@ -5029,24 +4541,16 @@ Sporting Goods > Indoor Games > Bowling > Bowling Balls Sporting Goods > Indoor Games > Bowling > Bowling Gloves Sporting Goods > Indoor Games > Bowling > Bowling Pins Sporting Goods > Indoor Games > Bowling > Bowling Wrist Supports -Sporting Goods > Indoor Games > Darts -Sporting Goods > Indoor Games > Darts > Dart Backboards -Sporting Goods > Indoor Games > Darts > Dart Parts -Sporting Goods > Indoor Games > Darts > Dart Parts > Dart Flights -Sporting Goods > Indoor Games > Darts > Dart Parts > Dart Shafts -Sporting Goods > Indoor Games > Darts > Dart Parts > Dart Tips -Sporting Goods > Indoor Games > Darts > Dartboards -Sporting Goods > Indoor Games > Darts > Single Darts Sporting Goods > Indoor Games > Foosball Sporting Goods > Indoor Games > Foosball > Foosball Balls -Sporting Goods > Indoor Games > Foosball > Foosball Table Parts +Sporting Goods > Indoor Games > Foosball > Foosball Table Parts & Accessories Sporting Goods > Indoor Games > Foosball > Foosball Tables Sporting Goods > Indoor Games > Multi-Game Tables Sporting Goods > Indoor Games > Ping Pong Sporting Goods > Indoor Games > Ping Pong > Ping Pong Balls Sporting Goods > Indoor Games > Ping Pong > Ping Pong Nets & Posts Sporting Goods > Indoor Games > Ping Pong > Ping Pong Paddle Accessories -Sporting Goods > Indoor Games > Ping Pong > Ping Pong Paddles +Sporting Goods > Indoor Games > Ping Pong > Ping Pong Paddles & Sets Sporting Goods > Indoor Games > Ping Pong > Ping Pong Robot Accessories Sporting Goods > Indoor Games > Ping Pong > Ping Pong Robots Sporting Goods > Indoor Games > Ping Pong > Ping Pong Tables @@ -5054,92 +4558,168 @@ Sporting Goods > Indoor Games > Table Shuffleboard Sporting Goods > Indoor Games > Table Shuffleboard > Shuffleboard Tables Sporting Goods > Indoor Games > Table Shuffleboard > Table Shuffleboard Powder Sporting Goods > Indoor Games > Table Shuffleboard > Table Shuffleboard Pucks -Sporting Goods > Jumping -Sporting Goods > Jumping > Bungee Jumping -Sporting Goods > Jumping > Jumping Stilts -Sporting Goods > Jumping > Pogo Sticks -Sporting Goods > Jumping > Trampoline Accessories -Sporting Goods > Jumping > Trampoline Accessories > Trampoline Anchors -Sporting Goods > Jumping > Trampoline Accessories > Trampoline Ladders -Sporting Goods > Jumping > Trampoline Accessories > Trampoline Mats -Sporting Goods > Jumping > Trampoline Accessories > Trampoline Nets -Sporting Goods > Jumping > Trampoline Accessories > Trampoline Safety Pads -Sporting Goods > Jumping > Trampoline Accessories > Trampoline Springs -Sporting Goods > Jumping > Trampolines +Sporting Goods > Indoor Games > Throwing Darts +Sporting Goods > Indoor Games > Throwing Darts > Dart Backboards +Sporting Goods > Indoor Games > Throwing Darts > Dart Parts +Sporting Goods > Indoor Games > Throwing Darts > Dart Parts > Dart Flights +Sporting Goods > Indoor Games > Throwing Darts > Dart Parts > Dart Shafts +Sporting Goods > Indoor Games > Throwing Darts > Dart Parts > Dart Tips +Sporting Goods > Indoor Games > Throwing Darts > Dartboards +Sporting Goods > Indoor Games > Throwing Darts > Darts Sporting Goods > Outdoor Recreation -Sporting Goods > Outdoor Recreation > Archery -Sporting Goods > Outdoor Recreation > Archery > Archery Armguards -Sporting Goods > Outdoor Recreation > Archery > Archery Bow Cases -Sporting Goods > Outdoor Recreation > Archery > Archery Targets -Sporting Goods > Outdoor Recreation > Archery > Arrow Parts & Accessories -Sporting Goods > Outdoor Recreation > Archery > Arrows -Sporting Goods > Outdoor Recreation > Archery > Compound Bows -Sporting Goods > Outdoor Recreation > Archery > Crossbows -Sporting Goods > Outdoor Recreation > Archery > Quivers -Sporting Goods > Outdoor Recreation > Archery > Recurve & Longbows -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Camp Furniture -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Camp Furniture > Air Mattress Accessories -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Camp Furniture > Air Mattresses -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Camp Furniture > Cots -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Camping Cookware & Dinnerware -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Camping Lights & Lanterns -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Camping Tools -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Camping Tools > Knives & Blades -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Camping Tools > Knives & Blades > Hunting & Survival Knives -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Camping Tools > Multifunction Tools & Knives -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Chemical Hand Warmers -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Compression Sacks -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Crampons -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Emergency Blankets -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Freeze-Dried Food -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Hiking Pole Accessories -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Hiking Poles -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Mosquito Nets -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Navigational Compasses -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Portable Toilets -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Portable Urination Devices -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Portable Water Filters & Purifiers -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Sleeping Bag Liners -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Sleeping Bags -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Sleeping Pads -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Tent Accessories -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Tent Accessories > Tent Footprints -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Tent Accessories > Tent Poles & Stakes -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Tent Accessories > Tent Vestibules -Sporting Goods > Outdoor Recreation > Camping, Backpacking & Hiking > Tents +Sporting Goods > Outdoor Recreation > Boating & Water Sports +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Boating Gloves +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Canoe Accessories +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Canoes +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Kayak Accessories +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Kayaks +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Paddle Leashes +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Paddles & Oars +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Pedal Boats +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Row Boats +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Whitewater Rafts +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Drysuits +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Life Jacket Accessories +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Life Jackets +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Rash Guards & Swim Shirts +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Water Sport Helmets +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Wetsuit Pieces +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Wetsuit Pieces > Wetsuit Bottoms +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Wetsuit Pieces > Wetsuit Hoods, Gloves & Boots +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Wetsuit Pieces > Wetsuit Tops +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Wetsuits +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Buoyancy Compensators +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Dive Computers +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving & Snorkeling Equipment Sets +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving & Snorkeling Fins +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving & Snorkeling Masks +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving Belts +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving Knives & Shears +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving Regulators +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Snorkels +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing > Kiteboard Cases +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing > Kiteboard Parts +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing > Kiteboards +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing > Kitesurfing & Windsurfing Harnesses +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing > Kitesurfing Kites +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Bodyboards +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Paddleboards +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Skimboards +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surf Leashes +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfboard Cases & Bags +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfboard Fins +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfboard Wax +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfboards +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfing Gloves +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfing Tail Pads +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Child Swimming Aids +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Hand Paddles +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Kickboards +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Pull Buoys +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Belts +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Caps +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Gloves +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Goggle & Mask Accessories +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Goggles & Masks +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Weights +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swimming Fins +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swimming Fins > Monofins +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swimming Fins > Training Fins +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swimming Machines +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swimming Nose Clips +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Kneeboarding +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Kneeboarding > Kneeboards +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Towable Rafts & Tubes +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Towed Water Sport Gloves +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Wakeboarding +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Wakeboarding > Kiteboard & Wakeboard Bindings +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Wakeboarding > Wakeboard Parts +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Wakeboarding > Wakeboards +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Skiing +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Skiing > Sit-Down Hydrofoils +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Skiing > Water Ski Bindings +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Skiing > Water Ski Cases & Bags +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Skiing > Water Skis +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Sport Tow Cables +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Watercraft Storage Racks +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Watercraft Storage Racks > Boat Storage Racks +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Watercraft Storage Racks > Water Sport Board Storage Racks +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing > Windsurfing Board Parts +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing > Windsurfing Board Parts > Windsurfing Board Fins +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing > Windsurfing Board Parts > Windsurfing Board Masts +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing > Windsurfing Boards +Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing > Windsurfing Sails +Sporting Goods > Outdoor Recreation > Camping & Hiking +Sporting Goods > Outdoor Recreation > Camping & Hiking > Camp Furniture +Sporting Goods > Outdoor Recreation > Camping & Hiking > Camp Furniture > Air Mattress & Sleeping Pad Accessories +Sporting Goods > Outdoor Recreation > Camping & Hiking > Camp Furniture > Air Mattresses +Sporting Goods > Outdoor Recreation > Camping & Hiking > Camp Furniture > Cots +Sporting Goods > Outdoor Recreation > Camping & Hiking > Camping Cookware & Dinnerware +Sporting Goods > Outdoor Recreation > Camping & Hiking > Camping Lights & Lanterns +Sporting Goods > Outdoor Recreation > Camping & Hiking > Camping Tools +Sporting Goods > Outdoor Recreation > Camping & Hiking > Camping Tools > Hunting & Survival Knives +Sporting Goods > Outdoor Recreation > Camping & Hiking > Camping Tools > Multifunction Tools & Knives +Sporting Goods > Outdoor Recreation > Camping & Hiking > Chemical Hand Warmers +Sporting Goods > Outdoor Recreation > Camping & Hiking > Compression Sacks +Sporting Goods > Outdoor Recreation > Camping & Hiking > Hiking Pole Accessories +Sporting Goods > Outdoor Recreation > Camping & Hiking > Hiking Poles +Sporting Goods > Outdoor Recreation > Camping & Hiking > Mosquito Nets & Insect Screens +Sporting Goods > Outdoor Recreation > Camping & Hiking > Navigational Compasses +Sporting Goods > Outdoor Recreation > Camping & Hiking > Portable Toilets & Showers +Sporting Goods > Outdoor Recreation > Camping & Hiking > Portable Toilets & Showers > Portable Showers & Privacy Enclosures +Sporting Goods > Outdoor Recreation > Camping & Hiking > Portable Toilets & Showers > Portable Toilets & Urination Devices +Sporting Goods > Outdoor Recreation > Camping & Hiking > Portable Water Filters & Purifiers +Sporting Goods > Outdoor Recreation > Camping & Hiking > Sleeping Bag Liners +Sporting Goods > Outdoor Recreation > Camping & Hiking > Sleeping Bags +Sporting Goods > Outdoor Recreation > Camping & Hiking > Sleeping Pads +Sporting Goods > Outdoor Recreation > Camping & Hiking > Tent Accessories +Sporting Goods > Outdoor Recreation > Camping & Hiking > Tent Accessories > Inner Tents +Sporting Goods > Outdoor Recreation > Camping & Hiking > Tent Accessories > Tent Footprints +Sporting Goods > Outdoor Recreation > Camping & Hiking > Tent Accessories > Tent Poles & Stakes +Sporting Goods > Outdoor Recreation > Camping & Hiking > Tent Accessories > Tent Vestibules +Sporting Goods > Outdoor Recreation > Camping & Hiking > Tents +Sporting Goods > Outdoor Recreation > Camping & Hiking > Windbreaks Sporting Goods > Outdoor Recreation > Climbing -Sporting Goods > Outdoor Recreation > Climbing > Ice Climbing -Sporting Goods > Outdoor Recreation > Climbing > Ice Climbing > Ice Climbing Tools -Sporting Goods > Outdoor Recreation > Climbing > Ice Climbing > Ice Screws -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Ascenders & Descenders -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Belay Devices -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Carabiners -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Climbing Chalk -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Climbing Chalk Bags -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Climbing Harnesses -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Climbing Helmets -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Climbing Protection Devices -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Climbing Rope -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Climbing Rope Bags -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Climbing Webbing -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Crash Pads -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Indoor Climbing Holds -Sporting Goods > Outdoor Recreation > Climbing > Rock Climbing > Quickdraws +Sporting Goods > Outdoor Recreation > Climbing > Belay Devices +Sporting Goods > Outdoor Recreation > Climbing > Carabiners +Sporting Goods > Outdoor Recreation > Climbing > Climbing Apparel & Accessories +Sporting Goods > Outdoor Recreation > Climbing > Climbing Apparel & Accessories > Climbing Gloves +Sporting Goods > Outdoor Recreation > Climbing > Climbing Apparel & Accessories > Climbing Helmets +Sporting Goods > Outdoor Recreation > Climbing > Climbing Apparel & Accessories > Crampons +Sporting Goods > Outdoor Recreation > Climbing > Climbing Ascenders & Descenders +Sporting Goods > Outdoor Recreation > Climbing > Climbing Chalk Bags +Sporting Goods > Outdoor Recreation > Climbing > Climbing Crash Pads +Sporting Goods > Outdoor Recreation > Climbing > Climbing Harnesses +Sporting Goods > Outdoor Recreation > Climbing > Climbing Protection Devices +Sporting Goods > Outdoor Recreation > Climbing > Climbing Rope +Sporting Goods > Outdoor Recreation > Climbing > Climbing Rope Bags +Sporting Goods > Outdoor Recreation > Climbing > Climbing Webbing +Sporting Goods > Outdoor Recreation > Climbing > Ice Climbing Tools +Sporting Goods > Outdoor Recreation > Climbing > Ice Screws +Sporting Goods > Outdoor Recreation > Climbing > Indoor Climbing Holds +Sporting Goods > Outdoor Recreation > Climbing > Quickdraws Sporting Goods > Outdoor Recreation > Cycling Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Bags & Panniers Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Baskets Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Bells & Horns Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Cages +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Child Seat Accessories Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Child Seats Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Computer Accessories Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Computers Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Covers Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Fenders Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Front & Rear Racks -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Lights & Reflectors +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Handlebar Grips & Decor Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Locks Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Mirrors Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Pumps @@ -5147,34 +4727,26 @@ Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Sa Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Shock Pumps Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Spoke Beads Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Stands & Storage -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Surfboard Racks +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Tire Repair Supplies & Kits Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Toe Straps & Clips -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Tools, Cleaners & Lubricants -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Tools, Cleaners & Lubricants > Bicycle Lubrication -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Tools, Cleaners & Lubricants > Bicycle Spoke Wrenches +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Tools Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Trailers Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Trainers Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Training Wheels Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Transport Bags & Cases -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Gear -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Gear > Bicycle Cleat Accessories -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Gear > Bicycle Cleat Accessories > Bicycle Cleat Bolts -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Gear > Bicycle Cleat Accessories > Bicycle Cleat Covers -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Gear > Bicycle Cleat Accessories > Bicycle Cleat Shims & Wedges -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Gear > Bicycle Cleats -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Gear > Bicycle Gloves -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Gear > Bicycle Helmet Covers -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Gear > Bicycle Helmets -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Gear > Bicycle Shoe Covers +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Water Sport Board Racks +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Electric Bicycle Conversion Kits Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Brake Parts Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Brake Parts > Bicycle Brake Calipers Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Brake Parts > Bicycle Brake Levers Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Brake Parts > Bicycle Brake Rotors Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Brake Parts > Bicycle Brake Sets +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Cable Housings +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Cables Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Bottom Brackets -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Cassettes +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Cassettes & Freewheels Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Chainrings Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Chains Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Cranks @@ -5183,102 +4755,117 @@ Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetra Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Shifters Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Forks Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Frames -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Grips & Handlebar Tape +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Groupsets Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Handlebar Extensions Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Handlebars Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Headset Parts Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Headset Parts > Bicycle Headset Bearings Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Headset Parts > Bicycle Headset Spacers Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Headsets +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Kickstands Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Saddles Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Seatpost Clamps Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Seatposts Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Small Parts -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Small Parts > Bicycle Accessory Mounts & Brackets -Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Small Parts > Bicycle Seatpost Shims Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Stems +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Tire Valve Adapters +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Tire Valve Caps +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Tire Valves Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Tires Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Tubes Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Foot Pegs +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Hub Parts Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Hubs +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Rim Strips Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Spokes +Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Wheel Axles & Skewers Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Wheel Nipples Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Wheel Rims Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheels Sporting Goods > Outdoor Recreation > Cycling > Bicycles -Sporting Goods > Outdoor Recreation > Cycling > Bicycles > Cruisers -Sporting Goods > Outdoor Recreation > Cycling > Bicycles > Electric Bicycles -Sporting Goods > Outdoor Recreation > Cycling > Bicycles > Hybrid Bicycles -Sporting Goods > Outdoor Recreation > Cycling > Bicycles > Mountain Bicycles -Sporting Goods > Outdoor Recreation > Cycling > Bicycles > Recumbent Bicycles -Sporting Goods > Outdoor Recreation > Cycling > Bicycles > Road Bicycles -Sporting Goods > Outdoor Recreation > Cycling > Bicycles > Triathlon Bicycles +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Cleat Accessories +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Cleat Accessories > Bicycle Cleat Bolts +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Cleat Accessories > Bicycle Cleat Covers +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Cleat Accessories > Bicycle Cleat Shims & Wedges +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Cleats +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Gloves +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Helmet Parts & Accessories +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Helmets +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Protective Pads +Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Shoe Covers Sporting Goods > Outdoor Recreation > Cycling > Tricycle Accessories Sporting Goods > Outdoor Recreation > Cycling > Tricycles -Sporting Goods > Outdoor Recreation > Cycling > Tricycles > Recumbent Tricycles Sporting Goods > Outdoor Recreation > Cycling > Unicycle Accessories Sporting Goods > Outdoor Recreation > Cycling > Unicycles -Sporting Goods > Outdoor Recreation > Deck Shuffleboard -Sporting Goods > Outdoor Recreation > Deck Shuffleboard > Deck Shuffleboard Cues -Sporting Goods > Outdoor Recreation > Deck Shuffleboard > Deck Shuffleboard Pucks -Sporting Goods > Outdoor Recreation > Disc Golf -Sporting Goods > Outdoor Recreation > Disc Golf > Disc Golf Bags -Sporting Goods > Outdoor Recreation > Disc Golf > Disc Golf Baskets -Sporting Goods > Outdoor Recreation > Disc Golf > Disc Golf Discs Sporting Goods > Outdoor Recreation > Equestrian -Sporting Goods > Outdoor Recreation > Equestrian > Horse Boots & Leg Wraps -Sporting Goods > Outdoor Recreation > Equestrian > Horse Boots & Leg Wraps > Bell Boots -Sporting Goods > Outdoor Recreation > Equestrian > Horse Boots & Leg Wraps > Splint Boots -Sporting Goods > Outdoor Recreation > Equestrian > Horse Supplies -Sporting Goods > Outdoor Recreation > Equestrian > Horse Supplies > Horse Blankets & Sheets -Sporting Goods > Outdoor Recreation > Equestrian > Horse Supplies > Horse Feed -Sporting Goods > Outdoor Recreation > Equestrian > Horse Supplies > Horse Grooming -Sporting Goods > Outdoor Recreation > Equestrian > Horse Supplies > Horse Grooming > Horse Clippers & Trimmers -Sporting Goods > Outdoor Recreation > Equestrian > Horse Supplies > Horse Treats -Sporting Goods > Outdoor Recreation > Equestrian > Horse Supplies > Horse Vitamins & Supplements +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Blankets & Sheets +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Boots & Leg Wraps +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Feed +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Fly Masks +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Grooming +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Grooming > Horse Clippers & Trimmers +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Grooming > Horse Grooming Combs, Brushes & Mitts +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Treats +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Vitamins & Supplements +Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Wormers Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack +Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Bridle Bits Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Bridles Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Cinches -Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Horse Bits +Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Horse Halters Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Horse Harnesses +Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Horse Leads Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Reins Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Saddles +Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Stirrups Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories -Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Racks -Sporting Goods > Outdoor Recreation > Equestrian > Riding Gear -Sporting Goods > Outdoor Recreation > Equestrian > Riding Gear > Equestrian Gloves -Sporting Goods > Outdoor Recreation > Equestrian > Riding Gear > Equestrian Helmets -Sporting Goods > Outdoor Recreation > Equestrian > Riding Gear > Riding Crops -Sporting Goods > Outdoor Recreation > Equestrian > Riding Gear > Riding Pants +Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Horse Tack Boxes +Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Accessories +Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Accessories > Saddle Bags & Panniers +Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Accessories > Saddle Covers & Cases +Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Accessories > Saddle Pads & Blankets +Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Accessories > Saddle Racks +Sporting Goods > Outdoor Recreation > Equestrian > Riding Apparel & Accessories +Sporting Goods > Outdoor Recreation > Equestrian > Riding Apparel & Accessories > Equestrian Gloves +Sporting Goods > Outdoor Recreation > Equestrian > Riding Apparel & Accessories > Equestrian Helmets +Sporting Goods > Outdoor Recreation > Equestrian > Riding Apparel & Accessories > Riding Crops & Whips +Sporting Goods > Outdoor Recreation > Equestrian > Riding Apparel & Accessories > Riding Pants Sporting Goods > Outdoor Recreation > Fishing +Sporting Goods > Outdoor Recreation > Fishing > Bite Alarms Sporting Goods > Outdoor Recreation > Fishing > Fishing & Hunting Waders Sporting Goods > Outdoor Recreation > Fishing > Fishing Bait & Chum Containers -Sporting Goods > Outdoor Recreation > Fishing > Fishing Floats Sporting Goods > Outdoor Recreation > Fishing > Fishing Gaffs Sporting Goods > Outdoor Recreation > Fishing > Fishing Hook Removal Tools -Sporting Goods > Outdoor Recreation > Fishing > Fishing Hooks Sporting Goods > Outdoor Recreation > Fishing > Fishing Lines & Leaders -Sporting Goods > Outdoor Recreation > Fishing > Fishing Lures -Sporting Goods > Outdoor Recreation > Fishing > Fishing Lures > Fishing Flies Sporting Goods > Outdoor Recreation > Fishing > Fishing Nets +Sporting Goods > Outdoor Recreation > Fishing > Fishing Reel Accessories +Sporting Goods > Outdoor Recreation > Fishing > Fishing Reel Accessories > Fishing Reel Bags & Cases +Sporting Goods > Outdoor Recreation > Fishing > Fishing Reel Accessories > Fishing Reel Lubricants +Sporting Goods > Outdoor Recreation > Fishing > Fishing Reel Accessories > Fishing Reel Replacement Spools Sporting Goods > Outdoor Recreation > Fishing > Fishing Reels +Sporting Goods > Outdoor Recreation > Fishing > Fishing Rod Accessories +Sporting Goods > Outdoor Recreation > Fishing > Fishing Rod Accessories > Fishing Rod Bags & Cases +Sporting Goods > Outdoor Recreation > Fishing > Fishing Rod Accessories > Fishing Rod Holders & Storage Racks Sporting Goods > Outdoor Recreation > Fishing > Fishing Rods -Sporting Goods > Outdoor Recreation > Fishing > Fishing Sinkers -Sporting Goods > Outdoor Recreation > Fishing > Fishing Snaps & Swivels Sporting Goods > Outdoor Recreation > Fishing > Fishing Spears +Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle +Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle > Fishing Baits & Lures +Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle > Fishing Floats +Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle > Fishing Hooks +Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle > Fishing Sinkers +Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle > Fishing Snaps & Swivels Sporting Goods > Outdoor Recreation > Fishing > Fishing Traps Sporting Goods > Outdoor Recreation > Fishing > Fly Tying Materials Sporting Goods > Outdoor Recreation > Fishing > Fly Tying Materials > Fishing Beads Sporting Goods > Outdoor Recreation > Fishing > Fly Tying Materials > Fishing Yarn Sporting Goods > Outdoor Recreation > Fishing > Live Bait Sporting Goods > Outdoor Recreation > Fishing > Tackle Bags & Boxes -Sporting Goods > Outdoor Recreation > Geocaching -Sporting Goods > Outdoor Recreation > Geocaching > Geocaches -Sporting Goods > Outdoor Recreation > Geocaching > Geocaching Log Sheets -Sporting Goods > Outdoor Recreation > Geocaching > Geocaching Trackables Sporting Goods > Outdoor Recreation > Golf Sporting Goods > Outdoor Recreation > Golf > Divot Tools +Sporting Goods > Outdoor Recreation > Golf > Golf Accessory Sets Sporting Goods > Outdoor Recreation > Golf > Golf Bag Accessories Sporting Goods > Outdoor Recreation > Golf > Golf Bag Accessories > Golf Bag Carts Sporting Goods > Outdoor Recreation > Golf > Golf Bag Accessories > Golf Bag Covers & Cases @@ -5287,410 +4874,157 @@ Sporting Goods > Outdoor Recreation > Golf > Golf Ball Markers Sporting Goods > Outdoor Recreation > Golf > Golf Balls Sporting Goods > Outdoor Recreation > Golf > Golf Club Parts & Accessories Sporting Goods > Outdoor Recreation > Golf > Golf Club Parts & Accessories > Golf Club Grips -Sporting Goods > Outdoor Recreation > Golf > Golf Club Parts & Accessories > Golf Club Head Covers +Sporting Goods > Outdoor Recreation > Golf > Golf Club Parts & Accessories > Golf Club Headcovers +Sporting Goods > Outdoor Recreation > Golf > Golf Club Parts & Accessories > Golf Club Shafts Sporting Goods > Outdoor Recreation > Golf > Golf Clubs Sporting Goods > Outdoor Recreation > Golf > Golf Flags Sporting Goods > Outdoor Recreation > Golf > Golf Gloves -Sporting Goods > Outdoor Recreation > Golf > Golf Kits Sporting Goods > Outdoor Recreation > Golf > Golf Tees Sporting Goods > Outdoor Recreation > Golf > Golf Towels Sporting Goods > Outdoor Recreation > Golf > Golf Training Aids -Sporting Goods > Outdoor Recreation > Hunting -Sporting Goods > Outdoor Recreation > Hunting & Shooting Protective Gear -Sporting Goods > Outdoor Recreation > Hunting & Shooting Protective Gear > Hunting & Shooting Gloves -Sporting Goods > Outdoor Recreation > Hunting & Shooting Protective Gear > Hunting & Shooting Jackets -Sporting Goods > Outdoor Recreation > Hunting > Animal Traps -Sporting Goods > Outdoor Recreation > Hunting > Game Feeders -Sporting Goods > Outdoor Recreation > Hunting > Hunting Blinds & Screens -Sporting Goods > Outdoor Recreation > Hunting > Hunting Calls -Sporting Goods > Outdoor Recreation > Hunting > Hunting Decoys -Sporting Goods > Outdoor Recreation > Hunting > Hunting Dog Equipment -Sporting Goods > Outdoor Recreation > Hunting > Hunting Shelters -Sporting Goods > Outdoor Recreation > Hunting > Tree Stands -Sporting Goods > Outdoor Recreation > Hunting > Wildlife Attractant +Sporting Goods > Outdoor Recreation > Hang Gliding & Skydiving +Sporting Goods > Outdoor Recreation > Hang Gliding & Skydiving > Air Suits +Sporting Goods > Outdoor Recreation > Hang Gliding & Skydiving > Hang Gliders +Sporting Goods > Outdoor Recreation > Hang Gliding & Skydiving > Parachutes +Sporting Goods > Outdoor Recreation > Hunting & Shooting +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Archery Armguards +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Archery Gloves & Releases +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Archery Targets +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Arrow Parts & Accessories +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Arrow Parts & Accessories > Arrow Fletchings +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Arrow Parts & Accessories > Arrow Nocks +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Arrow Parts & Accessories > Broadheads & Field Points +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Arrows & Bolts +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Bow & Crossbow Accessories +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Bows & Crossbows +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Bows & Crossbows > Compound Bows +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Bows & Crossbows > Crossbows +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Bows & Crossbows > Recurve & Longbows +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Quivers +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Clay Pigeon Shooting +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Clay Pigeon Shooting > Clay Pigeon Throwers +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Clay Pigeon Shooting > Clay Pigeons +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting & Shooting Protective Gear +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting & Shooting Protective Gear > Hunting & Shooting Gloves +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting & Shooting Protective Gear > Hunting & Shooting Jackets +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Animal Traps +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Hearing Enhancers +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Hunting Blinds & Screens +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Hunting Dog Equipment +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Tree Stands +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wild Game Feeders +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wildlife Attractants +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wildlife Attractants > Cover Scents & Scent Attractants +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wildlife Attractants > Hunting & Wildlife Calls +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wildlife Attractants > Hunting & Wildlife Decoys +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wildlife Attractants > Wildlife Bait, Feed & Minerals +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Airsoft +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Airsoft > Airsoft Gun Parts & Accessories +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Airsoft > Airsoft Gun Parts & Accessories > Airsoft Gun Batteries +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Airsoft > Airsoft Guns +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Airsoft > Airsoft Pellets +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball & Airsoft Protective Gear +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball & Airsoft Protective Gear > Paintball & Airsoft Gloves +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball & Airsoft Protective Gear > Paintball & Airsoft Goggles & Masks +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball & Airsoft Protective Gear > Paintball & Airsoft Pads +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball & Airsoft Protective Gear > Paintball & Airsoft Vests +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Grenade Launchers +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Grenades +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Gun Parts & Accessories +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Gun Parts & Accessories > Paintball Air Tanks +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Gun Parts & Accessories > Paintball Gun Barrels +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Gun Parts & Accessories > Paintball Gun Drop Forwards +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Gun Parts & Accessories > Paintball Hoppers +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Guns +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Harnesses & Packs +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintballs +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Shooting & Range Accessories +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Shooting & Range Accessories > Shooting Rests +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Shooting & Range Accessories > Shooting Sticks & Bipods +Sporting Goods > Outdoor Recreation > Hunting & Shooting > Shooting & Range Accessories > Shooting Targets Sporting Goods > Outdoor Recreation > Hydration System Accessories Sporting Goods > Outdoor Recreation > Hydration Systems +Sporting Goods > Outdoor Recreation > Inline & Roller Skating +Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Inline & Roller Skating Protective Gear +Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Inline & Roller Skating Protective Gear > Roller Skating Pads +Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Inline Skate Parts +Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Inline Skates +Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Roller Skate Parts +Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Roller Skates +Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Roller Skis Sporting Goods > Outdoor Recreation > Kite Buggying Sporting Goods > Outdoor Recreation > Kite Buggying > Kite Buggies -Sporting Goods > Outdoor Recreation > Kite Buggying Accessories -Sporting Goods > Outdoor Recreation > Lawn Games -Sporting Goods > Outdoor Recreation > Lawn Games > Bean Bag Toss -Sporting Goods > Outdoor Recreation > Lawn Games > Bocce -Sporting Goods > Outdoor Recreation > Lawn Games > Croquet -Sporting Goods > Outdoor Recreation > Lawn Games > Horseshoe Toss -Sporting Goods > Outdoor Recreation > Lawn Games > Ladder Golf -Sporting Goods > Outdoor Recreation > Lawn Games > Lawn Bowling -Sporting Goods > Outdoor Recreation > Lawn Games > Lawn Bowling > Lawn Bowling Bowls -Sporting Goods > Outdoor Recreation > Lawn Games > Lawn Bowling > Lawn Bowling Jacks -Sporting Goods > Outdoor Recreation > Lawn Games > Lawn Darts -Sporting Goods > Outdoor Recreation > Lawn Games > Ring Toss -Sporting Goods > Outdoor Recreation > Lawn Games > Washer Pitching -Sporting Goods > Outdoor Recreation > Motorsports -Sporting Goods > Outdoor Recreation > Motorsports > Auto Racing -Sporting Goods > Outdoor Recreation > Reflective Fitness Clothing -Sporting Goods > Outdoor Recreation > Reflective Fitness Clothing > Reflective Belts +Sporting Goods > Outdoor Recreation > Kite Buggying > Kite Buggy Accessories +Sporting Goods > Outdoor Recreation > Outdoor Games +Sporting Goods > Outdoor Recreation > Outdoor Games > Badminton +Sporting Goods > Outdoor Recreation > Outdoor Games > Badminton > Badminton Nets +Sporting Goods > Outdoor Recreation > Outdoor Games > Badminton > Badminton Racquets & Sets +Sporting Goods > Outdoor Recreation > Outdoor Games > Badminton > Shuttlecocks +Sporting Goods > Outdoor Recreation > Outdoor Games > Deck Shuffleboard +Sporting Goods > Outdoor Recreation > Outdoor Games > Deck Shuffleboard > Deck Shuffleboard Cues +Sporting Goods > Outdoor Recreation > Outdoor Games > Deck Shuffleboard > Deck Shuffleboard Pucks +Sporting Goods > Outdoor Recreation > Outdoor Games > Disc Golf +Sporting Goods > Outdoor Recreation > Outdoor Games > Disc Golf > Disc Golf Bags +Sporting Goods > Outdoor Recreation > Outdoor Games > Disc Golf > Disc Golf Baskets +Sporting Goods > Outdoor Recreation > Outdoor Games > Lawn Games +Sporting Goods > Outdoor Recreation > Outdoor Games > Paddle Ball Sets +Sporting Goods > Outdoor Recreation > Outdoor Games > Pickleball +Sporting Goods > Outdoor Recreation > Outdoor Games > Pickleball > Pickleball Paddles +Sporting Goods > Outdoor Recreation > Outdoor Games > Pickleball > Pickleballs +Sporting Goods > Outdoor Recreation > Outdoor Games > Platform & Paddle Tennis +Sporting Goods > Outdoor Recreation > Outdoor Games > Platform & Paddle Tennis > Platform & Paddle Tennis Paddles +Sporting Goods > Outdoor Recreation > Outdoor Games > Platform & Paddle Tennis > Platform Tennis Balls +Sporting Goods > Outdoor Recreation > Outdoor Games > Tetherball +Sporting Goods > Outdoor Recreation > Outdoor Games > Tetherball > Tetherball Poles +Sporting Goods > Outdoor Recreation > Outdoor Games > Tetherball > Tetherball Sets +Sporting Goods > Outdoor Recreation > Outdoor Games > Tetherball > Tetherballs Sporting Goods > Outdoor Recreation > Riding Scooters -Sporting Goods > Outdoor Recreation > Riding Scooters > Kick Scooters -Sporting Goods > Outdoor Recreation > Riding Scooters > Powered Scooters -Sporting Goods > Outdoor Recreation > Running -Sporting Goods > Outdoor Recreation > Shooting Games -Sporting Goods > Outdoor Recreation > Shooting Games > Airsoft -Sporting Goods > Outdoor Recreation > Shooting Games > Airsoft > Airsoft Gun Parts & Accessories -Sporting Goods > Outdoor Recreation > Shooting Games > Airsoft > Airsoft Gun Parts & Accessories > Airsoft Gun Batteries -Sporting Goods > Outdoor Recreation > Shooting Games > Airsoft > Airsoft Guns -Sporting Goods > Outdoor Recreation > Shooting Games > Airsoft > Airsoft Pellets -Sporting Goods > Outdoor Recreation > Shooting Games > Airsoft > Airsoft Protective Gear -Sporting Goods > Outdoor Recreation > Shooting Games > Clay Pigeon Shooting -Sporting Goods > Outdoor Recreation > Shooting Games > Clay Pigeon Shooting > Clay Pigeon Throwers -Sporting Goods > Outdoor Recreation > Shooting Games > Clay Pigeon Shooting > Clay Pigeons -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Air Tanks -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Grenade Launchers -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Grenades -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Gun Parts -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Gun Parts > Paintball Gun Barrels -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Gun Parts > Paintball Hoppers -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Guns -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Harnesses & Packs -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Protective Gear -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Protective Gear > Paintball Gloves -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Protective Gear > Paintball Goggles & Masks -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Protective Gear > Paintball Pads -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintball Protective Gear > Paintball Vests -Sporting Goods > Outdoor Recreation > Shooting Games > Paintball > Paintballs -Sporting Goods > Outdoor Recreation > Shooting Games > Shooting Targets Sporting Goods > Outdoor Recreation > Skateboarding Sporting Goods > Outdoor Recreation > Skateboarding > Skate Rails Sporting Goods > Outdoor Recreation > Skateboarding > Skate Ramps Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts -Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts > Skateboard Bearings Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts > Skateboard Decks +Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts > Skateboard Small Parts Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts > Skateboard Trucks Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts > Skateboard Wheels -Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Protective Gear -Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Protective Gear > Skateboard Helmets -Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Protective Gear > Skateboard Pads -Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Protective Gear > Skateboarding Gloves +Sporting Goods > Outdoor Recreation > Skateboarding > Skateboarding Protective Gear +Sporting Goods > Outdoor Recreation > Skateboarding > Skateboarding Protective Gear > Skate Helmets +Sporting Goods > Outdoor Recreation > Skateboarding > Skateboarding Protective Gear > Skateboarding Gloves +Sporting Goods > Outdoor Recreation > Skateboarding > Skateboarding Protective Gear > Skateboarding Pads Sporting Goods > Outdoor Recreation > Skateboarding > Skateboards -Sporting Goods > Outdoor Recreation > Skating -Sporting Goods > Outdoor Recreation > Skating > Figure Skate Boots -Sporting Goods > Outdoor Recreation > Skating > Ice Skate Blades -Sporting Goods > Outdoor Recreation > Skating > Ice Skate Sharpeners -Sporting Goods > Outdoor Recreation > Skating > Ice Skates -Sporting Goods > Outdoor Recreation > Skating > Ice Skates > Figure Skates -Sporting Goods > Outdoor Recreation > Skating > Ice Skates > Ice Hockey Skates -Sporting Goods > Outdoor Recreation > Skating > Inline Skates -Sporting Goods > Outdoor Recreation > Skating > Lace Tighteners -Sporting Goods > Outdoor Recreation > Skating > Roller Skates -Sporting Goods > Outdoor Recreation > Skating > Skate Blade Guards -Sporting Goods > Outdoor Recreation > Skating > Skate Parts -Sporting Goods > Outdoor Recreation > Skating > Skating Helmets & Pads -Sporting Goods > Outdoor Recreation > Stadium Seats & Cushions -Sporting Goods > Outdoor Recreation > Tetherball -Sporting Goods > Outdoor Recreation > Track & Field -Sporting Goods > Outdoor Recreation > Track & Field > Discuses -Sporting Goods > Outdoor Recreation > Track & Field > High Jump Bars -Sporting Goods > Outdoor Recreation > Track & Field > High Jump Pits -Sporting Goods > Outdoor Recreation > Track & Field > Hurdles -Sporting Goods > Outdoor Recreation > Track & Field > Javelins -Sporting Goods > Outdoor Recreation > Track & Field > Pole Vault Pits -Sporting Goods > Outdoor Recreation > Track & Field > Relay Batons -Sporting Goods > Outdoor Recreation > Track & Field > Shot Puts -Sporting Goods > Outdoor Recreation > Track & Field > Starter Pistols -Sporting Goods > Outdoor Recreation > Track & Field > Throwing Hammers -Sporting Goods > Outdoor Recreation > Track & Field > Vaulting Poles -Sporting Goods > Racquet Sports -Sporting Goods > Racquet Sports > Badminton -Sporting Goods > Racquet Sports > Badminton > Badminton Nets -Sporting Goods > Racquet Sports > Badminton > Badminton Rackets -Sporting Goods > Racquet Sports > Badminton > Shuttlecocks -Sporting Goods > Racquet Sports > Paddle Ball Sets -Sporting Goods > Racquet Sports > Paddle Tennis -Sporting Goods > Racquet Sports > Pickleball -Sporting Goods > Racquet Sports > Platform Tennis -Sporting Goods > Racquet Sports > Racquetball -Sporting Goods > Racquet Sports > Racquetball > Racquetball Protective Gear -Sporting Goods > Racquet Sports > Racquetball > Racquetball Protective Gear > Squash & Racquetball Goggles -Sporting Goods > Racquet Sports > Racquetball > Racquetball Rackets -Sporting Goods > Racquet Sports > Racquetball > Racquetballs -Sporting Goods > Racquet Sports > Squash -Sporting Goods > Racquet Sports > Squash > Squash Balls -Sporting Goods > Racquet Sports > Squash > Squash Protective Gear -Sporting Goods > Racquet Sports > Squash > Squash Rackets -Sporting Goods > Racquet Sports > Tennis -Sporting Goods > Racquet Sports > Tennis > Tennis Ball Hoppers -Sporting Goods > Racquet Sports > Tennis > Tennis Ball Machines -Sporting Goods > Racquet Sports > Tennis > Tennis Ball Savers -Sporting Goods > Racquet Sports > Tennis > Tennis Balls -Sporting Goods > Racquet Sports > Tennis > Tennis Nets -Sporting Goods > Racquet Sports > Tennis > Tennis Racket Accessories -Sporting Goods > Racquet Sports > Tennis > Tennis Racket Accessories > Racket Grip Tape -Sporting Goods > Racquet Sports > Tennis > Tennis Racket Accessories > Racket Vibration Dampeners -Sporting Goods > Racquet Sports > Tennis > Tennis Racket Accessories > Tennis Racket Bags -Sporting Goods > Racquet Sports > Tennis > Tennis Racket Accessories > Tennis Racket Grommets -Sporting Goods > Racquet Sports > Tennis > Tennis Racket Accessories > Tennis Racket String -Sporting Goods > Racquet Sports > Tennis > Tennis Rackets -Sporting Goods > Team Sports -Sporting Goods > Team Sports > Ball Carrying Bags -Sporting Goods > Team Sports > Ball Pump Accessories -Sporting Goods > Team Sports > Ball Pump Accessories > Ball Pump Needles -Sporting Goods > Team Sports > Ball Pumps -Sporting Goods > Team Sports > Baseball -Sporting Goods > Team Sports > Baseball > Baseball & Softball Gloves -Sporting Goods > Team Sports > Baseball > Baseball & Softball Gloves > Baseball Gloves & Mitts -Sporting Goods > Team Sports > Baseball > Baseball & Softball Gloves > Softball Gloves & Mitts -Sporting Goods > Team Sports > Baseball > Baseball Bats -Sporting Goods > Team Sports > Baseball > Baseball Diamond Bases -Sporting Goods > Team Sports > Baseball > Baseball Protective Gear -Sporting Goods > Team Sports > Baseball > Baseball Protective Gear > Batting Helmets -Sporting Goods > Team Sports > Baseball > Baseball Screens -Sporting Goods > Team Sports > Baseball > Baseballs -Sporting Goods > Team Sports > Baseball > Batting Gloves -Sporting Goods > Team Sports > Baseball > Pitching Machines -Sporting Goods > Team Sports > Basketball -Sporting Goods > Team Sports > Basketball > Basketball Hoop Parts & Accessories -Sporting Goods > Team Sports > Basketball > Basketball Hoop Parts & Accessories > Basketball Backboards -Sporting Goods > Team Sports > Basketball > Basketball Hoop Parts & Accessories > Basketball Hoop Padding -Sporting Goods > Team Sports > Basketball > Basketball Hoop Parts & Accessories > Basketball Nets -Sporting Goods > Team Sports > Basketball > Basketball Hoop Parts & Accessories > Basketball Poles -Sporting Goods > Team Sports > Basketball > Basketball Hoop Parts & Accessories > Basketball Rims -Sporting Goods > Team Sports > Basketball > Basketball Hoops -Sporting Goods > Team Sports > Basketball > Basketballs -Sporting Goods > Team Sports > Beach Volleyball -Sporting Goods > Team Sports > Beach Volleyball > Beach Volleyball Balls -Sporting Goods > Team Sports > Beach Volleyball > Beach Volleyball Nets -Sporting Goods > Team Sports > Broomball -Sporting Goods > Team Sports > Broomball > Broomball Sticks -Sporting Goods > Team Sports > Cheerleading -Sporting Goods > Team Sports > Cheerleading > Cheerleading Megaphones -Sporting Goods > Team Sports > Cheerleading > Pom-Poms -Sporting Goods > Team Sports > Cricket -Sporting Goods > Team Sports > Cricket > Cricket Balls -Sporting Goods > Team Sports > Cricket > Cricket Bats -Sporting Goods > Team Sports > Cricket > Cricket Gloves -Sporting Goods > Team Sports > Cricket > Cricket Helmets -Sporting Goods > Team Sports > Curling -Sporting Goods > Team Sports > Field Hockey -Sporting Goods > Team Sports > Field Hockey > Field Hockey Balls -Sporting Goods > Team Sports > Field Hockey > Field Hockey Gloves -Sporting Goods > Team Sports > Field Hockey > Field Hockey Goals -Sporting Goods > Team Sports > Field Hockey > Field Hockey Sticks -Sporting Goods > Team Sports > Football -Sporting Goods > Team Sports > Football > Football Gloves -Sporting Goods > Team Sports > Football > Football Goal Posts -Sporting Goods > Team Sports > Football > Football Kicking Tees -Sporting Goods > Team Sports > Football > Football Protective Gear -Sporting Goods > Team Sports > Football > Football Protective Gear > Football Girdles -Sporting Goods > Team Sports > Football > Football Protective Gear > Football Helmet Accessories -Sporting Goods > Team Sports > Football > Football Protective Gear > Football Helmet Accessories > Football Chin Straps -Sporting Goods > Team Sports > Football > Football Protective Gear > Football Helmet Accessories > Football Face Masks -Sporting Goods > Team Sports > Football > Football Protective Gear > Football Helmet Accessories > Football Helmet Padding -Sporting Goods > Team Sports > Football > Football Protective Gear > Football Helmet Accessories > Football Helmet Visors -Sporting Goods > Team Sports > Football > Football Protective Gear > Football Helmets -Sporting Goods > Team Sports > Football > Football Protective Gear > Football Neck Rolls -Sporting Goods > Team Sports > Football > Football Protective Gear > Football Shoulder Pads -Sporting Goods > Team Sports > Football > Football Training Equipment -Sporting Goods > Team Sports > Football > Footballs -Sporting Goods > Team Sports > Hockey -Sporting Goods > Team Sports > Hockey > Hockey Balls & Pucks -Sporting Goods > Team Sports > Hockey > Hockey Balls & Pucks > Ice Hockey Pucks -Sporting Goods > Team Sports > Hockey > Hockey Balls & Pucks > Roller Hockey Balls -Sporting Goods > Team Sports > Hockey > Hockey Goals -Sporting Goods > Team Sports > Hockey > Hockey Goals > Ice Hockey Goals -Sporting Goods > Team Sports > Hockey > Hockey Protective Gear -Sporting Goods > Team Sports > Hockey > Hockey Protective Gear > Hockey Body Pads -Sporting Goods > Team Sports > Hockey > Hockey Protective Gear > Hockey Gloves -Sporting Goods > Team Sports > Hockey > Hockey Protective Gear > Hockey Gloves > Ice Hockey Gloves -Sporting Goods > Team Sports > Hockey > Hockey Protective Gear > Hockey Helmets -Sporting Goods > Team Sports > Hockey > Hockey Protective Gear > Hockey Helmets > Ice Hockey Helmets -Sporting Goods > Team Sports > Hockey > Hockey Protective Gear > Hockey Pants -Sporting Goods > Team Sports > Hockey > Hockey Sledges -Sporting Goods > Team Sports > Hockey > Hockey Stick Care -Sporting Goods > Team Sports > Hockey > Hockey Stick Parts -Sporting Goods > Team Sports > Hockey > Hockey Stick Parts > Hockey Shafts -Sporting Goods > Team Sports > Hockey > Hockey Stick Parts > Hockey Stick Blades -Sporting Goods > Team Sports > Hockey > Hockey Sticks -Sporting Goods > Team Sports > Hockey > Hockey Sticks > Ice Hockey Sticks -Sporting Goods > Team Sports > Hockey > Hockey Sticks > Roller & Street Hockey Sticks -Sporting Goods > Team Sports > Indoor Volleyball -Sporting Goods > Team Sports > Indoor Volleyball > Indoor Volleyball Balls -Sporting Goods > Team Sports > Indoor Volleyball > Indoor Volleyball Nets -Sporting Goods > Team Sports > Indoor Volleyball > Volleyball Bags -Sporting Goods > Team Sports > Lacrosse -Sporting Goods > Team Sports > Lacrosse > Lacrosse Balls -Sporting Goods > Team Sports > Lacrosse > Lacrosse Goals -Sporting Goods > Team Sports > Lacrosse > Lacrosse Protective Gear -Sporting Goods > Team Sports > Lacrosse > Lacrosse Protective Gear > Lacrosse Arm Guards -Sporting Goods > Team Sports > Lacrosse > Lacrosse Protective Gear > Lacrosse Gloves -Sporting Goods > Team Sports > Lacrosse > Lacrosse Protective Gear > Lacrosse Helmets -Sporting Goods > Team Sports > Lacrosse > Lacrosse Protective Gear > Lacrosse Masks & Goggles -Sporting Goods > Team Sports > Lacrosse > Lacrosse Protective Gear > Lacrosse Shoulder Pads -Sporting Goods > Team Sports > Lacrosse > Lacrosse Stick Parts -Sporting Goods > Team Sports > Lacrosse > Lacrosse Stick Parts > Lacrosse Mesh & String -Sporting Goods > Team Sports > Lacrosse > Lacrosse Stick Parts > Lacrosse Stick Heads -Sporting Goods > Team Sports > Lacrosse > Lacrosse Stick Parts > Lacrosse Stick Shafts -Sporting Goods > Team Sports > Lacrosse > Lacrosse Sticks -Sporting Goods > Team Sports > Lacrosse > Lacrosse Training Equipment -Sporting Goods > Team Sports > Referee Accessories -Sporting Goods > Team Sports > Referee Accessories > Linesman Flags -Sporting Goods > Team Sports > Referee Accessories > Penalty Cards -Sporting Goods > Team Sports > Referee Accessories > Referee Whistles -Sporting Goods > Team Sports > Rounders -Sporting Goods > Team Sports > Rounders > Rounders Bats -Sporting Goods > Team Sports > Rounders > Rounders Gloves -Sporting Goods > Team Sports > Rugby -Sporting Goods > Team Sports > Rugby > Rugby Balls -Sporting Goods > Team Sports > Rugby > Rugby Gloves -Sporting Goods > Team Sports > Rugby > Rugby Helmets -Sporting Goods > Team Sports > Rugby > Rugby Posts -Sporting Goods > Team Sports > Rugby > Rugby Training Equipment -Sporting Goods > Team Sports > Soccer -Sporting Goods > Team Sports > Soccer > Soccer Balls -Sporting Goods > Team Sports > Soccer > Soccer Balls > Futsal Balls -Sporting Goods > Team Sports > Soccer > Soccer Captain Armbands -Sporting Goods > Team Sports > Soccer > Soccer Corner Flags -Sporting Goods > Team Sports > Soccer > Soccer Gloves -Sporting Goods > Team Sports > Soccer > Soccer Goal Accessories -Sporting Goods > Team Sports > Soccer > Soccer Goals -Sporting Goods > Team Sports > Soccer > Soccer Shin Guards -Sporting Goods > Team Sports > Softball -Sporting Goods > Team Sports > Softball > Softball Bats -Sporting Goods > Team Sports > Softball > Softball Protective Gear -Sporting Goods > Team Sports > Softball > Softballs -Sporting Goods > Team Sports > Team Handball -Sporting Goods > Water Sports -Sporting Goods > Water Sports > Boating -Sporting Goods > Water Sports > Boating > Boating Gloves -Sporting Goods > Water Sports > Boating > Canoeing -Sporting Goods > Water Sports > Boating > Canoeing > Canoeing Accessories -Sporting Goods > Water Sports > Boating > Canoeing > Canoes -Sporting Goods > Water Sports > Boating > Kayaking -Sporting Goods > Water Sports > Boating > Kayaking > Kayaking Accessories -Sporting Goods > Water Sports > Boating > Kayaking > Kayaking Accessories > Spray Skirts -Sporting Goods > Water Sports > Boating > Kayaking > Kayaks -Sporting Goods > Water Sports > Boating > Pedal Boats -Sporting Goods > Water Sports > Boating > Rafts -Sporting Goods > Water Sports > Boating > Rowing -Sporting Goods > Water Sports > Boating > Rowing > Rowing Boats -Sporting Goods > Water Sports > Boating > Rowing > Rowing Seat Pads -Sporting Goods > Water Sports > Boating > Sailing & Yachting -Sporting Goods > Water Sports > Kitesurfing -Sporting Goods > Water Sports > Kitesurfing > Kiteboard Cases -Sporting Goods > Water Sports > Kitesurfing > Kiteboard Parts -Sporting Goods > Water Sports > Kitesurfing > Kiteboards -Sporting Goods > Water Sports > Kitesurfing > Kitesurfing Harnesses -Sporting Goods > Water Sports > Kitesurfing > Kitesurfing Kites -Sporting Goods > Water Sports > Life Jacket Accessories -Sporting Goods > Water Sports > Life Jackets -Sporting Goods > Water Sports > Paddles & Oars -Sporting Goods > Water Sports > Rash Guards -Sporting Goods > Water Sports > Scuba Diving & Snorkeling -Sporting Goods > Water Sports > Scuba Diving & Snorkeling > Buoyancy Compensators -Sporting Goods > Water Sports > Scuba Diving & Snorkeling > Dive Computers -Sporting Goods > Water Sports > Scuba Diving & Snorkeling > Diving & Snorkeling Fins -Sporting Goods > Water Sports > Scuba Diving & Snorkeling > Diving & Snorkeling Masks -Sporting Goods > Water Sports > Scuba Diving & Snorkeling > Diving Belts -Sporting Goods > Water Sports > Scuba Diving & Snorkeling > Diving Knives & Shears -Sporting Goods > Water Sports > Scuba Diving & Snorkeling > Drysuits -Sporting Goods > Water Sports > Scuba Diving & Snorkeling > Regulators -Sporting Goods > Water Sports > Scuba Diving & Snorkeling > Scuba Diving & Snorkeling Gloves -Sporting Goods > Water Sports > Scuba Diving & Snorkeling > Snorkels -Sporting Goods > Water Sports > Surfing -Sporting Goods > Water Sports > Surfing > Bodyboards -Sporting Goods > Water Sports > Surfing > Paddleboards -Sporting Goods > Water Sports > Surfing > Skimboards -Sporting Goods > Water Sports > Surfing > Surfboard Cases & Bags -Sporting Goods > Water Sports > Surfing > Surfboard Fins -Sporting Goods > Water Sports > Surfing > Surfboard Leashes -Sporting Goods > Water Sports > Surfing > Surfboard Wax -Sporting Goods > Water Sports > Surfing > Surfboards -Sporting Goods > Water Sports > Surfing > Surfing Gloves -Sporting Goods > Water Sports > Surfing > Surfing Tail Pads -Sporting Goods > Water Sports > Swimming -Sporting Goods > Water Sports > Swimming > Hand Paddles -Sporting Goods > Water Sports > Swimming > Kickboards -Sporting Goods > Water Sports > Swimming > Pull Buoys -Sporting Goods > Water Sports > Swimming > Swim Belts -Sporting Goods > Water Sports > Swimming > Swim Caps -Sporting Goods > Water Sports > Swimming > Swim Gloves -Sporting Goods > Water Sports > Swimming > Swim Goggle & Mask Accessories -Sporting Goods > Water Sports > Swimming > Swim Goggles & Masks -Sporting Goods > Water Sports > Swimming > Swim Weights -Sporting Goods > Water Sports > Swimming > Swimming Fins -Sporting Goods > Water Sports > Swimming > Swimming Fins > Monofins -Sporting Goods > Water Sports > Swimming > Swimming Fins > Training Fins -Sporting Goods > Water Sports > Swimming > Swimming Machines -Sporting Goods > Water Sports > Swimming > Swimming Nose Clips -Sporting Goods > Water Sports > Towed Water Sports -Sporting Goods > Water Sports > Towed Water Sports > Kneeboarding -Sporting Goods > Water Sports > Towed Water Sports > Kneeboarding > Kneeboards -Sporting Goods > Water Sports > Towed Water Sports > Parasailing -Sporting Goods > Water Sports > Towed Water Sports > Tow Cables -Sporting Goods > Water Sports > Towed Water Sports > Towable Rafts & Tubes -Sporting Goods > Water Sports > Towed Water Sports > Towed Water Sport Gloves -Sporting Goods > Water Sports > Towed Water Sports > Wakeboarding -Sporting Goods > Water Sports > Towed Water Sports > Wakeboarding > Wakeboard Bindings -Sporting Goods > Water Sports > Towed Water Sports > Wakeboarding > Wakeboards -Sporting Goods > Water Sports > Towed Water Sports > Water Skiing -Sporting Goods > Water Sports > Towed Water Sports > Water Skiing > Sit-Down Hydrofoils -Sporting Goods > Water Sports > Towed Water Sports > Water Skiing > Water Ski Bindings -Sporting Goods > Water Sports > Towed Water Sports > Water Skiing > Water Skiing Cases & Bags -Sporting Goods > Water Sports > Towed Water Sports > Water Skiing > Water Skis -Sporting Goods > Water Sports > Water Polo -Sporting Goods > Water Sports > Water Polo > Water Polo Balls -Sporting Goods > Water Sports > Water Polo > Water Polo Caps -Sporting Goods > Water Sports > Water Polo > Water Polo Goals -Sporting Goods > Water Sports > Water Tubing -Sporting Goods > Water Sports > Watercraft Storage Racks -Sporting Goods > Water Sports > Wetsuits -Sporting Goods > Water Sports > Wetsuits > Wetsuit Accessories -Sporting Goods > Water Sports > Wetsuits > Wetsuit Bottoms -Sporting Goods > Water Sports > Wetsuits > Wetsuit Tops -Sporting Goods > Water Sports > Whitewater Rafting -Sporting Goods > Water Sports > Whitewater Rafting > Whitewater Rafting Helmets -Sporting Goods > Water Sports > Whitewater Rafting > Whitewater Rafts -Sporting Goods > Water Sports > Windsurfing -Sporting Goods > Water Sports > Windsurfing > Windsurfing Board Parts -Sporting Goods > Water Sports > Windsurfing > Windsurfing Board Parts > Windsurfing Board Fins -Sporting Goods > Water Sports > Windsurfing > Windsurfing Board Parts > Windsurfing Board Masts -Sporting Goods > Water Sports > Windsurfing > Windsurfing Board Parts > Windsurfing Sails -Sporting Goods > Water Sports > Windsurfing > Windsurfing Boards -Sporting Goods > Winter Sports -Sporting Goods > Winter Sports > Bobsledding -Sporting Goods > Winter Sports > Luge -Sporting Goods > Winter Sports > Skiing -Sporting Goods > Winter Sports > Skiing > Ski & Snowboard Bags -Sporting Goods > Winter Sports > Skiing > Ski & Snowboard Bags > Ski Bags -Sporting Goods > Winter Sports > Skiing > Ski & Snowboard Bags > Snowboard Bags -Sporting Goods > Winter Sports > Skiing > Ski & Snowboard Goggle Lenses -Sporting Goods > Winter Sports > Skiing > Ski & Snowboard Goggles -Sporting Goods > Winter Sports > Skiing > Ski & Snowboard Helmets -Sporting Goods > Winter Sports > Skiing > Ski & Snowboard Storage Racks -Sporting Goods > Winter Sports > Skiing > Ski Bindings -Sporting Goods > Winter Sports > Skiing > Ski Bindings > Cross-Country Ski Bindings -Sporting Goods > Winter Sports > Skiing > Ski Bindings > Downhill Ski Bindings -Sporting Goods > Winter Sports > Skiing > Ski Boots -Sporting Goods > Winter Sports > Skiing > Ski Boots > Cross-Country Ski Boots -Sporting Goods > Winter Sports > Skiing > Ski Boots > Downhill Ski Boots -Sporting Goods > Winter Sports > Skiing > Ski Poles -Sporting Goods > Winter Sports > Skiing > Skis -Sporting Goods > Winter Sports > Skiing > Skis > Cross-Country Skis -Sporting Goods > Winter Sports > Skiing > Skis > Downhill Skis -Sporting Goods > Winter Sports > Sledding -Sporting Goods > Winter Sports > Sledding > Sleds -Sporting Goods > Winter Sports > Sledding > Sleds > Runner Sleds -Sporting Goods > Winter Sports > Sledding > Sleds > Saucer Sleds -Sporting Goods > Winter Sports > Sledding > Sleds > Toboggans -Sporting Goods > Winter Sports > Sledding > Snow Tubes -Sporting Goods > Winter Sports > Snowboarding -Sporting Goods > Winter Sports > Snowboarding > Snowboard Binding Parts -Sporting Goods > Winter Sports > Snowboarding > Snowboard Bindings -Sporting Goods > Winter Sports > Snowboarding > Snowboard Boots -Sporting Goods > Winter Sports > Snowboarding > Snowboards -Sporting Goods > Winter Sports > Snowmobiling -Sporting Goods > Winter Sports > Snowshoeing -Sporting Goods > Winter Sports > Snowshoeing > Snowshoe Bindings -Sporting Goods > Winter Sports > Snowshoeing > Snowshoes +Sporting Goods > Outdoor Recreation > Winter Sports & Activities +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Avalanche Safety +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Avalanche Safety > Avalanche Probes +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Avalanche Safety > Avalanche Safety Airbags +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Bags +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Goggle Accessories +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Goggle Accessories > Ski & Snowboard Goggle Lenses +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Goggles +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Helmets +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Leashes +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Storage Racks +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Tuning Tools +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Wax +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski Binding Parts +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski Bindings +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski Boots +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski Poles +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Skis +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Skis > Cross-Country Skis +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Skis > Downhill Skis +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Snowboard Binding Parts +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Snowboard Bindings +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Snowboard Boots +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Snowboards +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Sleds +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Snowshoeing +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Snowshoeing > Snowshoe Bindings +Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Snowshoeing > Snowshoes Toys & Games Toys & Games > Game Timers Toys & Games > Games @@ -5699,50 +5033,40 @@ Toys & Games > Games > Battle Tops Toys & Games > Games > Bingo Sets Toys & Games > Games > Blackjack & Craps Sets Toys & Games > Games > Board Games -Toys & Games > Games > Board Games > Backgammon Sets -Toys & Games > Games > Board Games > Checkers Sets -Toys & Games > Games > Board Games > Chess Sets -Toys & Games > Games > Board Games > Parcheesi Toys & Games > Games > Card Game Accessories Toys & Games > Games > Card Games -Toys & Games > Games > Card Games > Trading Card Games -Toys & Games > Games > Card Games > Traditional Playing Cards +Toys & Games > Games > Dexterity Games Toys & Games > Games > Dice Sets & Games -Toys & Games > Games > Dice Sets & Games > Dice & Dice Sets -Toys & Games > Games > Dice Sets & Games > Dice Games Toys & Games > Games > Poker Chip Accessories Toys & Games > Games > Poker Chip Accessories > Poker Chip Carriers & Trays Toys & Games > Games > Poker Chips & Sets Toys & Games > Games > Portable Electronic Games Toys & Games > Games > Roulette Wheels & Sets -Toys & Games > Games > Stacking Games +Toys & Games > Games > Slot Machines Toys & Games > Games > Tile Games -Toys & Games > Games > Tile Games > Dominoes -Toys & Games > Games > Tile Games > Mahjong Toys & Games > Outdoor Play Equipment -Toys & Games > Outdoor Play Equipment > Bounce House Accessories -Toys & Games > Outdoor Play Equipment > Bounce Houses -Toys & Games > Outdoor Play Equipment > Play Parachutes +Toys & Games > Outdoor Play Equipment > Inflatable Bouncer Accessories +Toys & Games > Outdoor Play Equipment > Inflatable Bouncers +Toys & Games > Outdoor Play Equipment > Play Swings Toys & Games > Outdoor Play Equipment > Play Tents & Tunnels Toys & Games > Outdoor Play Equipment > Playhouses +Toys & Games > Outdoor Play Equipment > Pogo Sticks Toys & Games > Outdoor Play Equipment > Sandboxes Toys & Games > Outdoor Play Equipment > See Saws Toys & Games > Outdoor Play Equipment > Slides +Toys & Games > Outdoor Play Equipment > Stilts Toys & Games > Outdoor Play Equipment > Swing Set & Playset Accessories Toys & Games > Outdoor Play Equipment > Swing Sets & Playsets -Toys & Games > Outdoor Play Equipment > Swings & Gliders +Toys & Games > Outdoor Play Equipment > Trampoline Accessories +Toys & Games > Outdoor Play Equipment > Trampolines Toys & Games > Outdoor Play Equipment > Water Play Equipment -Toys & Games > Outdoor Play Equipment > Water Play Equipment > Lawn Water Slides Toys & Games > Outdoor Play Equipment > Water Play Equipment > Play Sprinkers -Toys & Games > Outdoor Play Equipment > Water Play Equipment > Water Parks +Toys & Games > Outdoor Play Equipment > Water Play Equipment > Water Parks & Slides Toys & Games > Outdoor Play Equipment > Water Play Equipment > Water Tables Toys & Games > Puzzles Toys & Games > Puzzles > Jigsaw Puzzle Accessories Toys & Games > Puzzles > Jigsaw Puzzles Toys & Games > Puzzles > Mechanical Puzzles -Toys & Games > Puzzles > Mechanical Puzzles > Assembly & Disassembly Puzzles -Toys & Games > Puzzles > Mechanical Puzzles > Dexterity Puzzles -Toys & Games > Puzzles > Mechanical Puzzles > Tavern Puzzles Toys & Games > Puzzles > Wooden & Pegged Puzzles Toys & Games > Toys Toys & Games > Toys > Activity Toys @@ -5757,18 +5081,15 @@ Toys & Games > Toys > Activity Toys > Ribbon & Streamer Toys Toys & Games > Toys > Activity Toys > Spinning Tops Toys & Games > Toys > Activity Toys > Toy Jacks Toys & Games > Toys > Activity Toys > Yo-Yo Parts & Accessories -Toys & Games > Toys > Activity Toys > Yo-Yo Parts & Accessories > Yo-Yo Gloves Toys & Games > Toys > Activity Toys > Yo-Yos Toys & Games > Toys > Art & Drawing Toys -Toys & Games > Toys > Art & Drawing Toys > Toy Craft Kits +Toys & Games > Toys > Art & Drawing Toys > Play Dough & Putty Toys & Games > Toys > Art & Drawing Toys > Toy Drawing Tablets Toys & Games > Toys > Ball Pit Accessories Toys & Games > Toys > Ball Pit Accessories > Ball Pit Balls Toys & Games > Toys > Ball Pits Toys & Games > Toys > Bath Toys Toys & Games > Toys > Beach & Sand Toys -Toys & Games > Toys > Beach & Sand Toys > Beach Balls -Toys & Games > Toys > Beach & Sand Toys > Sand Pails Toys & Games > Toys > Building Toys Toys & Games > Toys > Building Toys > Construction Set Toys Toys & Games > Toys > Building Toys > Foam Blocks @@ -5777,11 +5098,6 @@ Toys & Games > Toys > Building Toys > Marble Track Sets Toys & Games > Toys > Building Toys > Wooden Blocks Toys & Games > Toys > Dolls, Playsets & Toy Figures Toys & Games > Toys > Dolls, Playsets & Toy Figures > Action & Toy Figures -Toys & Games > Toys > Dolls, Playsets & Toy Figures > Action & Toy Figures > Action Figures -Toys & Games > Toys > Dolls, Playsets & Toy Figures > Action & Toy Figures > Animal Figures -Toys & Games > Toys > Dolls, Playsets & Toy Figures > Action & Toy Figures > Animal Figures > Dinosaur Figures -Toys & Games > Toys > Dolls, Playsets & Toy Figures > Action & Toy Figures > Animal Figures > Horse & Pony Figures -Toys & Games > Toys > Dolls, Playsets & Toy Figures > Action & Toy Figures > Army Men Toys & Games > Toys > Dolls, Playsets & Toy Figures > Bobblehead Figures Toys & Games > Toys > Dolls, Playsets & Toy Figures > Doll & Action Figure Accessories Toys & Games > Toys > Dolls, Playsets & Toy Figures > Dollhouse Accessories @@ -5795,12 +5111,12 @@ Toys & Games > Toys > Dolls, Playsets & Toy Figures > Stuffed Animals Toys & Games > Toys > Dolls, Playsets & Toy Figures > Toy Playsets Toys & Games > Toys > Educational Toys Toys & Games > Toys > Educational Toys > Ant Farms +Toys & Games > Toys > Educational Toys > Astronomy Toys & Models Toys & Games > Toys > Educational Toys > Bug Collecting Kits +Toys & Games > Toys > Educational Toys > Educational Flash Cards Toys & Games > Toys > Educational Toys > Reading Toys -Toys & Games > Toys > Educational Toys > Science Sets +Toys & Games > Toys > Educational Toys > Science & Exploration Sets Toys & Games > Toys > Educational Toys > Toy Abacuses -Toys & Games > Toys > Electronic Toys -Toys & Games > Toys > Electronic Toys > Robotic Toys Toys & Games > Toys > Executive Toys Toys & Games > Toys > Executive Toys > Magnet Toys Toys & Games > Toys > Flying Toy Accessories @@ -5832,46 +5148,49 @@ Toys & Games > Toys > Pretend Play > Pretend Electronics Toys & Games > Toys > Pretend Play > Pretend Housekeeping Toys & Games > Toys > Pretend Play > Pretend Lawn & Garden Toys & Games > Toys > Pretend Play > Pretend Professions & Role Playing +Toys & Games > Toys > Pretend Play > Pretend Shopping & Grocery Toys & Games > Toys > Pretend Play > Toy Kitchens & Play Food Toys & Games > Toys > Pretend Play > Toy Tools Toys & Games > Toys > Remote Control Toy Accessories Toys & Games > Toys > Remote Control Toys Toys & Games > Toys > Remote Control Toys > Remote Control Airships & Blimps Toys & Games > Toys > Remote Control Toys > Remote Control Boats & Watercraft -Toys & Games > Toys > Remote Control Toys > Remote Control Boats & Watercraft > Remote Control Submarines Toys & Games > Toys > Remote Control Toys > Remote Control Cars & Trucks -Toys & Games > Toys > Remote Control Toys > Remote Control Figures Toys & Games > Toys > Remote Control Toys > Remote Control Helicopters Toys & Games > Toys > Remote Control Toys > Remote Control Motorcycles Toys & Games > Toys > Remote Control Toys > Remote Control Planes Toys & Games > Toys > Remote Control Toys > Remote Control Robots Toys & Games > Toys > Remote Control Toys > Remote Control Tanks Toys & Games > Toys > Riding Toy Accessories -Toys & Games > Toys > Riding Toy Accessories > Electric Riding Vehicle Accessories -Toys & Games > Toys > Riding Toy Accessories > Electric Riding Vehicle Accessories > Electric Riding Vehicle Chargers -Toys & Games > Toys > Riding Toy Accessories > Push & Pedal Riding Vehicle Accessories -Toys & Games > Toys > Riding Toy Accessories > Wagon Parts & Accessories Toys & Games > Toys > Riding Toys Toys & Games > Toys > Riding Toys > Electric Riding Vehicles Toys & Games > Toys > Riding Toys > Hobby Horses Toys & Games > Toys > Riding Toys > Push & Pedal Riding Vehicles Toys & Games > Toys > Riding Toys > Rocking & Spring Riding Toys Toys & Games > Toys > Riding Toys > Wagons +Toys & Games > Toys > Robotic Toys +Toys & Games > Toys > Sports Toy Accessories +Toys & Games > Toys > Sports Toy Accessories > Fitness Toy Accessories +Toys & Games > Toys > Sports Toy Accessories > Fitness Toy Accessories > Hula Hoop Accessories Toys & Games > Toys > Sports Toys +Toys & Games > Toys > Sports Toys > Baseball Toys +Toys & Games > Toys > Sports Toys > Basketball Toys Toys & Games > Toys > Sports Toys > Boomerangs +Toys & Games > Toys > Sports Toys > Bowling Toys +Toys & Games > Toys > Sports Toys > Fingerboards & Fingerboard Sets +Toys & Games > Toys > Sports Toys > Fishing Toys Toys & Games > Toys > Sports Toys > Fitness Toys Toys & Games > Toys > Sports Toys > Fitness Toys > Hula Hoops Toys & Games > Toys > Sports Toys > Flying Discs Toys & Games > Toys > Sports Toys > Footbags -Toys & Games > Toys > Sports Toys > Toy Baseball -Toys & Games > Toys > Sports Toys > Toy Basketball -Toys & Games > Toys > Sports Toys > Toy Bowling -Toys & Games > Toys > Sports Toys > Toy Football -Toys & Games > Toys > Sports Toys > Toy Football > Foam Footballs -Toys & Games > Toys > Sports Toys > Toy Golf -Toys & Games > Toys > Sports Toys > Toy Hockey -Toys & Games > Toys > Toy Weapons -Toys & Games > Toys > Toy Weapons > Water Guns +Toys & Games > Toys > Sports Toys > Golf Toys +Toys & Games > Toys > Sports Toys > Hockey Toys +Toys & Games > Toys > Sports Toys > Playground Balls +Toys & Games > Toys > Sports Toys > Racquet Sport Toys +Toys & Games > Toys > Sports Toys > Toy Footballs +Toys & Games > Toys > Toy Gift Baskets +Toys & Games > Toys > Toy Weapon & Gadget Accessories +Toys & Games > Toys > Toy Weapons & Gadgets Toys & Games > Toys > Visual Toys Toys & Games > Toys > Visual Toys > Kaleidoscopes Toys & Games > Toys > Visual Toys > Prisms @@ -5879,304 +5198,180 @@ Toys & Games > Toys > Wind-Up Toys Vehicles & Parts Vehicles & Parts > Vehicle Parts & Accessories Vehicles & Parts > Vehicle Parts & Accessories > Aircraft Parts & Accessories -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio & Video Cables -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio > Car Amplifiers -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio > Car Audio Receivers -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio > Car Audio Receivers > Car Satellite Radios -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio > Car CD Changers -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio > Car Cassette Players -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio > Car Equalizers & Crossovers -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio > Car Speakerphones -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio > Car Speakers -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio > Car Subwoofers -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Audio > Cassette Adapters -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Surge Protection -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Video -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Video > Car DVD Players -Vehicles & Parts > Vehicle Parts & Accessories > Car Audio & Video > Car Video > Car Video Monitors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Jump Starters -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Jumper Cables -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Tire Care -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Tire Care > Hubcaps -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Tire Care > Tire Covers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Tire Care > Tire Markers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Tire Care > Tire Pressure Sensors & Gauges -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Tire Care > Tire Valve Caps -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Battery Chargers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Cleaning -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Cleaning > Car Wash Brushes -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Cleaning > Car Wash Solutions -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Cleaning > Tire Wash & Shine -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Cleaning > Vehicle Aerosol Cleaners -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Cleaning > Vehicle Carpet Cleaners -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Cleaning > Vehicle Glass Cleaners -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Cleaning > Vehicle Upholstery Cleaners -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Cleaning > Vehicle Waxes, Polishes & Protectants -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Covers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > Antenna Balls -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > Bumper Stickers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > Car Seat Covers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > Car Seat Organizers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > License Plate Covers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > License Plate Frames -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > Vehicle Air Fresheners -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > Vehicle Decals -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > Vehicle Display Flags -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > Vehicle Emblems & Hood Ornaments -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > Vehicle Magnets -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Decor > Vehicle Window Films -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Diagnostic Scanners -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Antifreeze -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Brake Fluid -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Cooling System Additives -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Engine Degreasers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Fuel System Cleaners -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Hydraulic Clutch Fluid -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Motor Oil -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Power Steering Fluid -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Transmission Fluid -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Vehicle Greases -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Vehicle Performance Additives -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Fluids > Windshield Fluid -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Vehicle Paint -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Care > Windshield Repair Kits -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Bumper Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Bumpers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Hardtops -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > License Plates -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Body Kits -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Cargo Nets -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Rack Accessories -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Rack Accessories > Vehicle Bicycle Rack Accessories -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Rack Accessories > Vehicle Bicycle Rack Accessories > Bicycle Fork Mount Adapters -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Rack Accessories > Vehicle Bicycle Rack Accessories > Bicycle Frame Adapters -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Rack Accessories > Vehicle Bicycle Rack Accessories > Bicycle Wheel Straps -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Racks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Racks > Vehicle Base Rack Systems -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Racks > Vehicle Bicycle Racks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Racks > Vehicle Canoe & Kayak Racks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Racks > Vehicle Cargo Racks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Racks > Vehicle Fishing Pole Racks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Racks > Vehicle Gun Racks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Racks > Vehicle Motorcycle & Scooter Racks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Racks > Vehicle Ski & Snowboard Racks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Carrying Racks > Vehicle Water Sport Board Racks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Diffusers & Splitters -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Door Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Doors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Grilles -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Hitches -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Running Boards -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Tow Hooks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Trailer Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motor Vehicle Warning Whips -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motorcycle Fairings -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motorcycle Fenders -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motorcycle Foot Pegs -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motorcycle Handlebars & Grips -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motorcycle Seats -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Motorcycle Shift Levers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Soft Tops -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Spoilers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Sunroofs -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Truck Bed Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Truck Bed Parts > Truck Bed Bars -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Truck Beds -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Winch Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Exterior > Winches -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Automotive Fuses -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Car Seat Cushions -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Car Seats -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Cigar Lighter Receptacles -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Cup Holders -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Dashboard Accessories -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Headliners -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Power Seats -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Sun Shields -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Vehicle Armrests -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Vehicle Backrests -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Vehicle Carpets -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Interior > Vehicle Floor Mats -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Monitoring -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Monitoring > Engine Control Unit Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Monitoring > Fuel Meters -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Monitoring > Motor Vehicle Trip Computers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Monitoring > Odometers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Monitoring > Radar Detectors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Monitoring > Speedometers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Monitoring > Tachometers +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle A/V Players & In-Dash Systems +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Amplifiers +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Cassette Adapters +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Cassette Players +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Equalizers & Crossovers +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Parking Cameras +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Speakerphones +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Speakers +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Subwoofers +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Video Monitor Mounts Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Air Intake Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Air Intake Parts > Vehicle Air Filters -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Air Intake Parts > Vehicle Air Manifolds -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Air Intake Parts > Vehicle Air Pump Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Air Intake Parts > Vehicle Air Pumps -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Brake & Clutch Levers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Batteries -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Batteries > Hybrid Batteries -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Belts Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Braking -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Braking > Parking Brake Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Braking > Vehicle Brake Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Braking > Vehicle Manual Brake Parts +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Carpet & Upholstery Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Climate Control -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Climate Control > Vehicle Air Conditioner Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Climate Control > Vehicle Blower Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Climate Control > Vehicle Defroster Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Climate Control > Vehicle Heater Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Climate Control > Vehicle Temperature Controllers +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Controls +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Oil Circulation Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Alternator Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Alternators -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Camshaft Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Camshafts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Carburetor Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Carburetors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Compressor Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Compressors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Crankshaft Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Crankshafts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Cylinder Heads & Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Engine Gaskets -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Engine Timing Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Engine Timing Parts > Vehicle Engine Timing Belts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Flywheels & Flywheel Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Generator Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Ignition Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Ignition Parts > Capacitor Discharge Ignition Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Ignition Parts > Distributor Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Ignition Parts > Ignition Coils -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Ignition Parts > Spark Plugs -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Piston Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Piston Parts > Gudgeon Pins -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Piston Parts > Piston Rings -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Pistons -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Radiator Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Radiators -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Starter Motor Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Starter Motors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Super Charger Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts > Vehicle Vacuum Pump Parts +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engines Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Exhaust -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Exhaust > Catalytic Converters -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Exhaust > Exhaust Gas Recirculation Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Exhaust > Exhaust Manifolds -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Exhaust > Mufflers & Muffler Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Exhaust > Oxygen Sensors & Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Exhaust > Tailpipes & Tailpipe Parts +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Frame & Body Parts Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems > Fuel Injection Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems > Fuel Injectors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems > Fuel Lines & Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems > Fuel Pump Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems > Fuel Pumps -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems > Fuel Screens & Filters -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems > Fuel Tank Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems > Fuel Tanks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems > Nitrous Systems -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems > Vehicle Flow Meters +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Interior Fittings Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting > Exterior Vehicle Light Covers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting > Vehicle Fog Lights -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting > Vehicle Headlights -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting > Vehicle Interior Lighting -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting > Vehicle Light Bulbs -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting > Vehicle Parking Lights -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting > Vehicle Reverse Lights -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting > Vehicle Side Marker Lights -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting > Vehicle Tail & Brake Lights -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting > Vehicle Turn Signal Lights Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Mirrors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Mirrors > Vehicle Rear-View Mirrors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Mirrors > Vehicle Side-View Mirrors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Mirrors > Vehicle Towing Mirrors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Pedals -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Valves & Valve Parts +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Power & Electrical Systems +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Seating +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Sensors & Gauges +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Suspension Parts +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Towing +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Transmission & Drivetrain Parts Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels > ATV & UTV Rims & Wheels -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels > ATV & UTV Rims & Wheels > ATV Rims & Wheels -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels > ATV & UTV Rims & Wheels > UTV Rims & Wheels Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels > Automotive Rims & Wheels Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels > Motorcycle Rims & Wheels +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels > Off-Road and All-Terrain Vehicle Rims & Wheels +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tire Accessories Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires > ATV & UTV Tires -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires > ATV & UTV Tires > ATV Tires -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires > ATV & UTV Tires > UTV Tires Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires > Automotive Tires Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires > Motorcycle Tires +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires > Off-Road and All-Terrain Vehicle Tires Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Wheel Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Tire Accessories -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Tire Accessories > Tire Chains -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Window Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Window Parts > Power Window Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Window Parts > Window & Windshield Glass -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Oil Circulation -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Oil Circulation > Oil Filters -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Oil Circulation > Oil Pump Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Oil Circulation > Oil Pumps -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Oil Circulation > Oil Sumps -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Steering Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Steering Parts > King Pins -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Steering Parts > Power Steering Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Steering Parts > Steering Wheel Controls -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Steering Parts > Steering Wheel Controls > Cruise Control Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Steering Parts > Steering Wheel Controls > Headlight Control Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Steering Parts > Steering Wheel Controls > Vehicle Light Dimmers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Steering Parts > Steering Wheel Controls > Wiper Speed Control Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Steering Parts > Steering Wheels -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Suspension Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Suspension Parts > Shock Absorbers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Axle Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Ball Bearings -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Clutch Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Connecting Rods -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Differentials -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Driveshaft Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Driveshafts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Gearbox Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Gearboxes -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Rocker Arm Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Rocker Arm Parts > Rocker Covers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Rocker Arms -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Transfer Case Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Transmission Parts > Transmission Gears -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Vehicle Battery Parts -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Windshield Wipers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Safety Equipment -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Safety Equipment > Vehicle Parking Sensors -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems > Car Alarm Accessories -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems > Car Alarm Systems -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems > Child Safety Locks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems > Immobilizers -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems > Locking Hubs -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems > Motor Vehicle Security Cameras -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems > Motorcycle Alarms & Locks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems > Power Door Locks -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems > Remote Keyless Systems -Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Security & Locking Systems > Steering Wheel Locks -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Bags & Panniers -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear > Motorcycle Chest & Back Protectors -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear > Motorcycle Elbow & Wrist Guards -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear > Motorcycle Gloves -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear > Motorcycle Goggles -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear > Motorcycle Helmet Parts & Accessories -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear > Motorcycle Helmet Parts & Accessories > Motorcycle Helmet Visors -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear > Motorcycle Helmets -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear > Motorcycle Kidney Belts -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear > Motorcycle Knee & Shin Guards -Vehicles & Parts > Vehicle Parts & Accessories > Motorcycle Accessories > Motorcycle Protective Gear > Motorcycle Neck Braces +Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Window Parts & Accessories +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Portable Fuel Cans +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Car Wash Brushes +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Car Wash Solutions +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Vehicle Carpet & Upholstery Cleaners +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Vehicle Fuel Injection Cleaning Kits +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Vehicle Glass Cleaners +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Vehicle Waxes, Polishes & Protectants +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Golf Cart Enclosures +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Motor Vehicle Windshield Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Tonneau Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Hardtops +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Soft Tops +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers > Automotive Storage Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers > Golf Cart Storage Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers > Motorcycle Storage Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers > Recreational Vehicle Storage Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers > Watercraft Storage Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Bumper Stickers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Air Fresheners +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Antenna Balls +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Dashboard Accessories +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Decals +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Decor Accessory Sets +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Display Flags +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Emblems & Hood Ornaments +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Hitch Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle License Plate Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle License Plate Frames +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle License Plate Mounts & Holders +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle License Plates +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Magnets +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Rear View Mirror Ornaments +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Shift Boots +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Shift Knobs +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Steering Wheel Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Wraps +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Antifreeze +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Brake Fluid +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Cooling System Additives +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Engine Degreasers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Fuel System Cleaners +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Greases +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Hydraulic Clutch Fluid +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Motor Oil +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Performance Additives +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Power Steering Fluid +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Transmission Fluid +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Windshield Fluid +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Paint +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Paint > Motor Vehicle Body Paint +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Paint > Motor Vehicle Brake Caliper Paint +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Motor Vehicle Brake Service Kits +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Motor Vehicle Clutch Alignment & Removal Tools +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Battery Chargers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Battery Testers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Body Filler +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Diagnostic Scanners +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Jump Starters +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Jumper Cables +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Tire Repair & Tire Changing Tools +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Windshield Repair Kits +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Chest & Back Protectors +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Elbow & Wrist Guards +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Gloves +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Goggles +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Hand Guards +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Helmet Parts & Accessories +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Helmets +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Kidney Belts +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Knee & Shin Guards +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Neck Braces +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Off-Road & All-Terrain Vehicle Protective Gear +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Off-Road & All-Terrain Vehicle Protective Gear > ATV & UTV Bar Pads +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Automotive Alarm Accessories +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Automotive Alarm Systems +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Motorcycle Alarms & Locks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Door Locks & Parts +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Door Locks & Parts > Vehicle Door Lock Actuators +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Door Locks & Parts > Vehicle Door Lock Knobs +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Door Locks & Parts > Vehicle Door Locks & Locking Systems +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Hitch Locks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Immobilizers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Remote Keyless Systems +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Steering Wheel Locks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Wheel Clamps +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Car Window Nets +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Emergency Road Flares +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Motor Vehicle Airbag Parts +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Motor Vehicle Roll Cages & Bars +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Seat Belt Buckles +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Seat Belt Covers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Seat Belt Straps +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Seat Belts +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Warning Whips +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Wheel Chocks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Cargo Nets +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Rack Accessories +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Rack Accessories > Vehicle Bicycle Rack Accessories +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Rack Accessories > Vehicle Ski & Snowboard Rack Accessories +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Base Rack Systems +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Bicycle Racks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Boat Racks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Cargo Racks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Fishing Rod Racks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Gun Racks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Motorcycle & Scooter Racks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Ski & Snowboard Racks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Water Sport Board Racks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Loading Ramps +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Trailers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Trailers > Boat Trailers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Trailers > Horse & Livestock Trailers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Trailers > Travel Trailers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Trailers > Utility & Cargo Trailers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motorcycle Bags & Panniers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Truck Bed Storage Boxes & Organizers +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Vehicle Headrest Hangers & Hooks +Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Vehicle Organizers Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring > Anchor Chains @@ -6190,7 +5385,6 @@ Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Sailboat Parts Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Care Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Care > Watercraft Cleaners -Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Care > Watercraft Covers Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Care > Watercraft Polishes Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts > Watercraft Alternators @@ -6215,3 +5409,19 @@ Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Steering Parts Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Steering Parts > Watercraft Steering Cables Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Steering Parts > Watercraft Steering Wheels +Vehicles & Parts > Vehicles +Vehicles & Parts > Vehicles > Aircraft +Vehicles & Parts > Vehicles > Motor Vehicles +Vehicles & Parts > Vehicles > Motor Vehicles > Cars, Trucks & Vans +Vehicles & Parts > Vehicles > Motor Vehicles > Golf Carts +Vehicles & Parts > Vehicles > Motor Vehicles > Motorcycles & Scooters +Vehicles & Parts > Vehicles > Motor Vehicles > Off-Road and All-Terrain Vehicles +Vehicles & Parts > Vehicles > Motor Vehicles > Off-Road and All-Terrain Vehicles > ATVs & UTVs +Vehicles & Parts > Vehicles > Motor Vehicles > Off-Road and All-Terrain Vehicles > Go Karts & Dune Buggies +Vehicles & Parts > Vehicles > Motor Vehicles > Recreational Vehicles +Vehicles & Parts > Vehicles > Motor Vehicles > Snowmobiles +Vehicles & Parts > Vehicles > Watercraft +Vehicles & Parts > Vehicles > Watercraft > Motor Boats +Vehicles & Parts > Vehicles > Watercraft > Personal Watercraft +Vehicles & Parts > Vehicles > Watercraft > Sailboats +Vehicles & Parts > Vehicles > Watercraft > Yachts \ No newline at end of file From 47a2a00d9ea88fd9bb920c5c1fb9c85c925e4fe6 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 24 Jun 2015 19:21:49 +0200 Subject: [PATCH 0178/1256] (Perf) Minor enhancements in AppDomainTypeFinder --- .../Infrastructure/AppDomainTypeFinder.cs | 132 ++++++++++++++---- .../Infrastructure/WebAppTypeFinder.cs | 1 - 2 files changed, 104 insertions(+), 29 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Infrastructure/AppDomainTypeFinder.cs b/src/Libraries/SmartStore.Core/Infrastructure/AppDomainTypeFinder.cs index 56410ec9a3..8e2e1b1498 100644 --- a/src/Libraries/SmartStore.Core/Infrastructure/AppDomainTypeFinder.cs +++ b/src/Libraries/SmartStore.Core/Infrastructure/AppDomainTypeFinder.cs @@ -19,11 +19,17 @@ public class AppDomainTypeFinder : ITypeFinder { #region Private Fields + private static object s_lock = new object(); + private string _assemblySkipLoadingPattern = @"^System|^mscorlib|^Microsoft|^CppCodeProvider|^VJSharpCodeProvider|^WebDev|^Nuget|^Castle|^Iesi|^log4net|^Autofac|^AutoMapper|^EntityFramework|^EPPlus|^Fasterflect|^nunit|^TestDriven|^MbUnit|^Rhino|^QuickGraph|^TestFu|^Telerik|^Antlr3|^Recaptcha|^FluentValidation|^ImageResizer|^itextsharp|^MiniProfiler|^Newtonsoft|^Pandora|^WebGrease|^Noesis|^DotNetOpenAuth|^Facebook|^LinqToTwitter|^PerceptiveMCAPI|^CookComputing|^GCheckout|^Mono\.Math|^Org\.Mentalis|^App_Web|^BundleTransformer|^ClearScript|^JavaScriptEngineSwitcher|^MsieJavaScriptEngine|^Glimpse|^Ionic|^App_GlobalResources|^AjaxMin|^MaxMind|^NReco|^OffAmazonPayments|^UAParser"; + private string _assemblyRestrictToLoadingPattern = ".*"; + private readonly IDictionary _assemblyMatchTable = new Dictionary(); + + private Regex _assemblySkipLoadingRegex = null; + private Regex _assemblyRestrictToLoadingRegex = null; private bool _ignoreReflectionErrors = true; private bool _loadAppDomainAssemblies = true; - private string _assemblyRestrictToLoadingPattern = ".*"; private IList _customAssemblyNames = new List(); #endregion @@ -45,33 +51,53 @@ public virtual AppDomain App get { return AppDomain.CurrentDomain; } } - /// Gets or sets wether SmartStore should iterate assemblies in the app domain when loading SmartStore types. Loading patterns are applied when loading these assemblies. + /// + /// Gets or sets wether SmartStore should iterate assemblies in the app domain when loading SmartStore types. Loading patterns are applied when loading these assemblies. + /// public bool LoadAppDomainAssemblies { get { return _loadAppDomainAssemblies; } set { _loadAppDomainAssemblies = value; } } - /// Gets or sets assemblies loaded at startup in addition to those loaded in the AppDomain. + /// + /// Gets or sets assemblies loaded at startup in addition to those loaded in the AppDomain. + /// public IList CustomAssemblyNames { get { return _customAssemblyNames; } set { _customAssemblyNames = value; } } - /// Gets the pattern for dlls that we know don't need to be investigated. + /// + /// Gets the pattern for dlls that we know don't need to be investigated. + /// public string AssemblySkipLoadingPattern { get { return _assemblySkipLoadingPattern; } - set { _assemblySkipLoadingPattern = value; } + set + { + _assemblySkipLoadingPattern = value; + _assemblySkipLoadingRegex = null; + _assemblyMatchTable.Clear(); + } } - /// Gets or sets the pattern for dll that will be investigated. For ease of use this defaults to match all but to increase performance you might want to configure a pattern that includes assemblies and your own. - /// If you change this so that SmartStore assemblies arn't investigated (e.g. by not including something like "^SmartStore|..." you may break core functionality. + /// + /// Gets or sets the pattern for dll that will be investigated. For ease of use this defaults to match all but to increase performance you might want to configure a pattern that includes assemblies and your own. + /// + /// + /// If you change this so that SmartStore assemblies aren't investigated (e.g. by not including something like "^SmartStore|..." you may break core functionality. + /// public string AssemblyRestrictToLoadingPattern { get { return _assemblyRestrictToLoadingPattern; } - set { _assemblyRestrictToLoadingPattern = value; } + set + { + _assemblyRestrictToLoadingPattern = value; + _assemblyRestrictToLoadingRegex = null; + _assemblyMatchTable.Clear(); + } } #endregion @@ -103,7 +129,7 @@ public IEnumerable FindClassesOfType(Type assignTypeFrom, IEnumerable FindClassesOfType(Type assignTypeFrom, IEnumerable private readonly List _assemblyAttributesSearched = new List(); - /// Gets the assemblies related to the current implementation. + /// + /// Gets the assemblies related to the current implementation. + /// /// Indicates whether uninstalled plugin's assemblies should be filtered out /// A list of assemblies that should be loaded by the SmartStore factory. public virtual IList GetAssemblies(bool ignoreInactivePlugins = false) { - var addedAssemblyNames = new List(); + var addedAssemblyNames = new HashSet(); var assemblies = new List(); if (LoadAppDomainAssemblies) @@ -184,12 +212,15 @@ public virtual IList GetAssemblies(bool ignoreInactivePlugins = false) #endregion - /// Iterates all assemblies in the AppDomain and if it's name matches the configured patterns add it to our list. + /// + /// Iterates all assemblies in the AppDomain and if it's name matches the configured patterns add it to our list. + /// /// /// - private void AddAssembliesInAppDomain(List addedAssemblyNames, List assemblies) + private void AddAssembliesInAppDomain(HashSet addedAssemblyNames, List assemblies) { - foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) + var curDomainAssemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach (var assembly in curDomainAssemblies) { if (Matches(assembly.FullName)) { @@ -202,8 +233,10 @@ private void AddAssembliesInAppDomain(List addedAssemblyNames, ListAdds specificly configured assemblies.
- protected virtual void AddCustomAssemblies(List addedAssemblyNames, List assemblies) + /// + /// Adds specificly configured assemblies. + /// + protected virtual void AddCustomAssemblies(HashSet addedAssemblyNames, List assemblies) { foreach (string assemblyName in CustomAssemblyNames) { @@ -216,25 +249,68 @@ protected virtual void AddCustomAssemblies(List addedAssemblyNames, List } } - /// Check if a dll is one of the shipped dlls that we know don't need to be investigated. + /// + /// Check if a dll is one of the shipped dlls that we know don't need to be investigated. + /// /// The name of the assembly to check. /// True if the assembly should be loaded into SmartStore. public virtual bool Matches(string assemblyFullName) { - return !Matches(assemblyFullName, AssemblySkipLoadingPattern) - && Matches(assemblyFullName, AssemblyRestrictToLoadingPattern); - } + if (_assemblyMatchTable.ContainsKey(assemblyFullName)) + { + return _assemblyMatchTable[assemblyFullName]; + } + + if (_assemblySkipLoadingRegex == null) + { + lock (s_lock) + { + if (_assemblySkipLoadingRegex == null) + { + _assemblySkipLoadingRegex = new Regex(_assemblySkipLoadingPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline); + } + } + } - /// Check if a dll is one of the shipped dlls that we know don't need to be investigated. - /// The assembly name to match. - /// The regular expression pattern to match against the assembly name. - /// True if the pattern matches the assembly name. - protected virtual bool Matches(string assemblyFullName, string pattern) - { - return Regex.IsMatch(assemblyFullName, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); + if (_assemblySkipLoadingRegex.IsMatch(assemblyFullName)) + { + _assemblyMatchTable[assemblyFullName] = false; + return false; + } + + if (_assemblyRestrictToLoadingRegex == null) + { + lock (s_lock) + { + if (_assemblyRestrictToLoadingRegex == null) + { + _assemblyRestrictToLoadingRegex = new Regex(_assemblyRestrictToLoadingPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline); + } + } + } + + var matches = _assemblyRestrictToLoadingRegex.IsMatch(assemblyFullName); + _assemblyMatchTable[assemblyFullName] = matches; + + return matches; + + //return !Matches(assemblyFullName, AssemblySkipLoadingPattern) && Matches(assemblyFullName, AssemblyRestrictToLoadingPattern); } - /// Makes sure matching assemblies in the supplied folder are loaded in the app domain. + ///// + ///// Check if a dll is one of the shipped dlls that we know don't need to be investigated. + ///// + ///// The assembly name to match. + ///// The regular expression pattern to match against the assembly name. + ///// True if the pattern matches the assembly name. + //protected virtual bool Matches(string assemblyFullName, string pattern) + //{ + // return Regex.IsMatch(assemblyFullName, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline); + //} + + /// + /// Makes sure matching assemblies in the supplied folder are loaded in the app domain. + /// /// The physical path to a directory containing dlls to load in the app domain. protected virtual void LoadMatchingAssemblies(string directoryPath) { diff --git a/src/Libraries/SmartStore.Core/Infrastructure/WebAppTypeFinder.cs b/src/Libraries/SmartStore.Core/Infrastructure/WebAppTypeFinder.cs index 9a65536cc2..689a3f9e62 100644 --- a/src/Libraries/SmartStore.Core/Infrastructure/WebAppTypeFinder.cs +++ b/src/Libraries/SmartStore.Core/Infrastructure/WebAppTypeFinder.cs @@ -69,7 +69,6 @@ public override IList GetAssemblies(bool ignoreInactivePlugins = false { _binFolderAssembliesLoaded = true; string binPath = GetBinDirectory(); - //binPath = _webHelper.MapPath("~/bin"); LoadMatchingAssemblies(binPath); } From 618dd48eaf3f75320286ca4ef845d24c830b7cdf Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 24 Jun 2015 20:59:55 +0200 Subject: [PATCH 0179/1256] Fixed compiler warnings --- .../Controllers/DiscountRulesController.cs | 5 ----- .../Controllers/FeedFroogleController.cs | 4 ---- .../Controllers/OfflinePaymentController.cs | 4 ---- .../Controllers/PayPalExpressController.cs | 8 -------- .../Controllers/PackagingController.cs | 2 -- .../Administration/Controllers/PluginController.cs | 4 ---- .../Administration/Controllers/ProductController.cs | 4 ---- .../Controllers/ScheduleTaskController.cs | 3 --- .../Administration/Controllers/ThemeController.cs | 4 ---- .../SmartStore.Web/Controllers/CatalogController.cs | 12 ------------ .../SmartStore.Web/Controllers/CommonController.cs | 4 ---- .../SmartStore.Web/Controllers/HomeController.cs | 4 ---- .../SmartStore.Web/Controllers/OrderController.cs | 3 --- .../SmartStore.Web/Controllers/ProductController.cs | 5 ----- 14 files changed, 66 deletions(-) diff --git a/src/Plugins/SmartStore.DiscountRules/Controllers/DiscountRulesController.cs b/src/Plugins/SmartStore.DiscountRules/Controllers/DiscountRulesController.cs index c004670e23..2892c3c0b3 100644 --- a/src/Plugins/SmartStore.DiscountRules/Controllers/DiscountRulesController.cs +++ b/src/Plugins/SmartStore.DiscountRules/Controllers/DiscountRulesController.cs @@ -31,13 +31,8 @@ public DiscountRulesController( this._customerService = customerService; this._countryService = countryService; this._storeService = storeService; - - T = NullLocalizer.Instance; } - public Localizer T { get; set; } - - #region Global [NonAction] diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/Controllers/FeedFroogleController.cs b/src/Plugins/SmartStore.GoogleMerchantCenter/Controllers/FeedFroogleController.cs index 312ff89ff7..92ac370330 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/Controllers/FeedFroogleController.cs +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/Controllers/FeedFroogleController.cs @@ -30,12 +30,8 @@ public FeedFroogleController( _googleService = googleService; _settingService = settingService; _permissionService = permissionService; - - T = NullLocalizer.Instance; } - public Localizer T { get; set; } - private ActionResult RedirectToConfig() { return RedirectToAction("ConfigurePlugin", "Plugin", new { systemName = _googleService.Helper.SystemName, area = "Admin" }); diff --git a/src/Plugins/SmartStore.OfflinePayment/Controllers/OfflinePaymentController.cs b/src/Plugins/SmartStore.OfflinePayment/Controllers/OfflinePaymentController.cs index 468940bc74..d1c5369d54 100644 --- a/src/Plugins/SmartStore.OfflinePayment/Controllers/OfflinePaymentController.cs +++ b/src/Plugins/SmartStore.OfflinePayment/Controllers/OfflinePaymentController.cs @@ -33,12 +33,8 @@ public OfflinePaymentController( this._services = services; this._storeService = storeService; this._ctx = ctx; - - T = NullLocalizer.Instance; } - public Localizer T { get; set; } - #region Global [NonAction] diff --git a/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs b/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs index a1e1b10db2..b3af94a0b9 100644 --- a/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs +++ b/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs @@ -78,14 +78,6 @@ public PayPalExpressController( _storeService = storeService; _helper = new PluginHelper(ctx, "SmartStore.PayPal", "Plugins.Payments.PayPalExpress"); - - T = NullLocalizer.Instance; - } - - public Localizer T - { - get; - set; } public SelectList TransactModeValues(TransactMode selected) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PackagingController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PackagingController.cs index 65a0c4b1a8..ac947d3c8c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PackagingController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PackagingController.cs @@ -30,8 +30,6 @@ public PackagingController(ICommonServices services, IPackageManager packageMana this._themeRegistry = themeRegistry; } - public Localizer T { get; set; } - [ChildActionOnly] public ActionResult UploadPackage(bool isTheme) { diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs index a997a2cb46..bc697dc796 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs @@ -71,16 +71,12 @@ public PluginController(IPluginFinder pluginFinder, this._providerManager = providerManager; this._pluginMediator = pluginMediator; this._commonService = commonService; - - T = NullLocalizer.Instance; } #endregion  #region Utilities - public Localizer T { get; set; } - [NonAction] protected PluginModel PreparePluginModel(PluginDescriptor pluginDescriptor, bool forList = true) { diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index 3c323b9686..c5fe38faec 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -193,14 +193,10 @@ public ProductController( this._genericAttributeService = genericAttributeService; _pdfConverter = pdfConverter; _services = services; - - T = NullLocalizer.Instance; } #endregion - public Localizer T { get; set; } - #region Update[...] [NonAction] diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs index 16745ce28f..d5d6110dee 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs @@ -42,13 +42,10 @@ public ScheduleTaskController(IScheduleTaskService scheduleTaskService, IPermiss this._scheduleTaskService = scheduleTaskService; this._permissionService = permissionService; this._dateTimeHelper = dateTimeHelper; - T = NullLocalizer.Instance; } #endregion - public Localizer T { get; set; } - #region Utility private bool IsTaskInstalled(ScheduleTask task) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs index 7d376c349f..55c6cee336 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs @@ -62,12 +62,8 @@ public ThemeController( this._services = services; this._themeContext = themeContext; this._themeFileResolver = themeFileResolver; - - this.T = NullLocalizer.Instance; } - public Localizer T { get; set; } - #endregion  #region Methods diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs index 191bdc64fc..ab0236bc10 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs @@ -105,22 +105,10 @@ public CatalogController( this._catalogSettings = catalogSettings; this._helper = helper; - - T = NullLocalizer.Instance; } #endregion - #region Properties - - public Localizer T - { - get; - set; - } - - #endregion - #region Categories [RequireHttpsByConfigAttribute(SslRequirement.No)] diff --git a/src/Presentation/SmartStore.Web/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Controllers/CommonController.cs index ba7a63234c..b7db4b2f44 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CommonController.cs @@ -133,12 +133,8 @@ public CommonController( this._pageAssetsBuilder = pageAssetsBuilder; this._pictureService = pictureService; this._services = services; - - T = NullLocalizer.Instance; } - public Localizer T { get; set; } - #endregion #region Utilities diff --git a/src/Presentation/SmartStore.Web/Controllers/HomeController.cs b/src/Presentation/SmartStore.Web/Controllers/HomeController.cs index 745da0006d..cd16a058b6 100644 --- a/src/Presentation/SmartStore.Web/Controllers/HomeController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/HomeController.cs @@ -68,14 +68,10 @@ public HomeController( this._sitemapGenerator = sitemapGenerator; this._captchaSettings = captchaSettings; this._commonSettings = commonSettings; - - T = NullLocalizer.Instance; } #endregion - public Localizer T { get; set; } - [RequireHttpsByConfigAttribute(SslRequirement.No)] public ActionResult Index() { diff --git a/src/Presentation/SmartStore.Web/Controllers/OrderController.cs b/src/Presentation/SmartStore.Web/Controllers/OrderController.cs index 57c7c32649..b1217ad312 100644 --- a/src/Presentation/SmartStore.Web/Controllers/OrderController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/OrderController.cs @@ -95,11 +95,8 @@ public OrderController( this._pluginMediator = pluginMediator; this._services = services; this._quantityUnitService = quantityUnitService; - T = NullLocalizer.Instance; } - public Localizer T { get; set; } - #endregion #region Utilities diff --git a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs index d778b741b5..e899772842 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs @@ -118,15 +118,10 @@ public ProductController( this._localizationSettings = localizationSettings; this._captchaSettings = captchaSettings; this._helper = helper; - - T = NullLocalizer.Instance; } #endregion - public Localizer T { get; set; } - - #region Products [RequireHttpsByConfigAttribute(SslRequirement.No)] From 7eb8b8de05cbe12b18a824f4126b637687416ba5 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 24 Jun 2015 22:22:30 +0200 Subject: [PATCH 0180/1256] Added EF6 profiling to MiniProfiler --- .../Filters/ProfilerFilter.cs | 24 ++++++++------ .../SmartStore.DevTools/ProfilerHttpModule.cs | 14 --------- .../SmartStore.DevTools.csproj | 6 ++++ src/Plugins/SmartStore.DevTools/Starter.cs | 31 +++++++++++++++++++ src/Plugins/SmartStore.DevTools/Web.config | 4 +++ .../SmartStore.DevTools/packages.config | 1 + src/Presentation/SmartStore.Web/Web.config | 2 +- 7 files changed, 57 insertions(+), 25 deletions(-) create mode 100644 src/Plugins/SmartStore.DevTools/Starter.cs diff --git a/src/Plugins/SmartStore.DevTools/Filters/ProfilerFilter.cs b/src/Plugins/SmartStore.DevTools/Filters/ProfilerFilter.cs index 85a252e7f1..2971dabe08 100644 --- a/src/Plugins/SmartStore.DevTools/Filters/ProfilerFilter.cs +++ b/src/Plugins/SmartStore.DevTools/Filters/ProfilerFilter.cs @@ -54,7 +54,10 @@ public void OnActionExecuted(ActionExecutedContext filterContext) if (!_profilerSettings.EnableMiniProfilerInPublicStore) return; - this._profiler.Value.StepStop("ActionFilter"); + if (!(filterContext.Result is ViewResultBase)) + { + this._profiler.Value.StepStop("ActionFilter"); + } } public void OnResultExecuting(ResultExecutingContext filterContext) @@ -74,15 +77,6 @@ public void OnResultExecuting(ResultExecutingContext filterContext) return; } - if (!filterContext.IsChildAction) - { - _widgetProvider.Value.RegisterAction( - "head_html_tag", - "MiniProfiler", - "DevTools", - new { area = "SmartStore.DevTools" }); - } - var viewName = result.ViewName; if (viewName.IsEmpty()) { @@ -91,6 +85,15 @@ public void OnResultExecuting(ResultExecutingContext filterContext) } this._profiler.Value.StepStart("ResultFilter", string.Format("{0}: {1}", result is PartialViewResult ? "Partial" : "View", viewName)); + + if (!filterContext.IsChildAction) + { + _widgetProvider.Value.RegisterAction( + "head_html_tag", + "MiniProfiler", + "DevTools", + new { area = "SmartStore.DevTools" }); + } } public void OnResultExecuted(ResultExecutedContext filterContext) @@ -110,6 +113,7 @@ public void OnResultExecuted(ResultExecutedContext filterContext) } this._profiler.Value.StepStop("ResultFilter"); + this._profiler.Value.StepStop("ActionFilter"); } private bool ShouldProfile(HttpContextBase ctx) diff --git a/src/Plugins/SmartStore.DevTools/ProfilerHttpModule.cs b/src/Plugins/SmartStore.DevTools/ProfilerHttpModule.cs index 1cbc8981b3..e1c5693558 100644 --- a/src/Plugins/SmartStore.DevTools/ProfilerHttpModule.cs +++ b/src/Plugins/SmartStore.DevTools/ProfilerHttpModule.cs @@ -1,25 +1,11 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Web; -using Microsoft.Web.Infrastructure.DynamicModuleHelper; using SmartStore.Core.Infrastructure; -using SmartStore.Core.Plugins; -using SmartStore.Web.Framework; using StackExchange.Profiling; namespace SmartStore.DevTools { - public class ProfilerStarter : IPreApplicationStart - { - public void Start() - { - DynamicModuleUtility.RegisterModule(typeof(ProfilerHttpModule)); - SmartUrlRoutingModule.RegisterRoutablePath("/mini-profiler-resources/(.*)"); - } - } - public class ProfilerHttpModule : IHttpModule { private const string MP_KEY = "sm.miniprofiler.started"; diff --git a/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj b/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj index e1c88f8d2c..7b08208219 100644 --- a/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj +++ b/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj @@ -96,6 +96,11 @@ ..\..\packages\MiniProfiler.3.1.1.140\lib\net40\MiniProfiler.dll True + + False + ..\..\packages\MiniProfiler.EF6.3.0.11\lib\net40\MiniProfiler.EntityFramework6.dll + True + @@ -155,6 +160,7 @@ + diff --git a/src/Plugins/SmartStore.DevTools/Starter.cs b/src/Plugins/SmartStore.DevTools/Starter.cs new file mode 100644 index 0000000000..b8b9d3c97c --- /dev/null +++ b/src/Plugins/SmartStore.DevTools/Starter.cs @@ -0,0 +1,31 @@ +using Microsoft.Web.Infrastructure.DynamicModuleHelper; +using SmartStore.Core.Infrastructure; +using SmartStore.Core.Plugins; +using SmartStore.Web.Framework; + +namespace SmartStore.DevTools +{ + + public class ProfilerPreApplicationStart : IPreApplicationStart + { + public void Start() + { + DynamicModuleUtility.RegisterModule(typeof(ProfilerHttpModule)); + SmartUrlRoutingModule.RegisterRoutablePath("/mini-profiler-resources/(.*)"); + } + } + + public class ProfilerStartupTask : IStartupTask + { + public void Execute() + { + StackExchange.Profiling.EntityFramework6.MiniProfilerEF6.Initialize(); + } + + public int Order + { + get { return int.MinValue; } + } + } + +} \ No newline at end of file diff --git a/src/Plugins/SmartStore.DevTools/Web.config b/src/Plugins/SmartStore.DevTools/Web.config index 4f2a281983..e0593e522a 100644 --- a/src/Plugins/SmartStore.DevTools/Web.config +++ b/src/Plugins/SmartStore.DevTools/Web.config @@ -120,6 +120,10 @@ + + + + diff --git a/src/Plugins/SmartStore.DevTools/packages.config b/src/Plugins/SmartStore.DevTools/packages.config index 63f26d3792..5fb210cfc1 100644 --- a/src/Plugins/SmartStore.DevTools/packages.config +++ b/src/Plugins/SmartStore.DevTools/packages.config @@ -8,4 +8,5 @@ + \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config index 4cf9b75964..084e63fb0f 100644 --- a/src/Presentation/SmartStore.Web/Web.config +++ b/src/Presentation/SmartStore.Web/Web.config @@ -229,7 +229,7 @@ - + From bf90e329dec59e20e9d548b7fcf81090d59ae7aa Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 24 Jun 2015 23:39:23 +0200 Subject: [PATCH 0181/1256] (Perf) Minor enhancement in WorkContext.WorkingCurrency --- .../WebWorkContext.cs | 33 ++++++++++++------- src/Presentation/SmartStore.Web/Web.config | 2 +- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs b/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs index 9d33ae5f24..bb717b809f 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs @@ -255,6 +255,7 @@ public Language WorkingLanguage } #region Get language from URL (if possible) + if (_localizationSettings.SeoFriendlyUrlsForLanguagesEnabled && _httpContext != null && _httpContext.Request != null) { var helper = new LocalizedUrlHelper(_httpContext.Request, true); @@ -265,6 +266,7 @@ public Language WorkingLanguage { // the language is found. now we need to save it var langBySeoCode = _languageService.GetLanguageBySeoCode(seoCode); + if (this.CurrentCustomer != null && customerLangId != langBySeoCode.Id) { customerLangId = langBySeoCode.Id; @@ -275,6 +277,7 @@ public Language WorkingLanguage } } } + #endregion if (_localizationSettings.DetectBrowserUserLanguage && (customerLangId == 0 || !_languageService.IsPublishedLanguage(customerLangId, storeId))) @@ -363,7 +366,7 @@ public Currency WorkingCurrency { // find current customer language var customer = this.CurrentCustomer; - var currentStoreCurrencies = _currencyService.GetAllCurrencies(storeId: _storeContext.CurrentStore.Id); + var storeCurrenciesMap = _currencyService.GetAllCurrencies(storeId: _storeContext.CurrentStore.Id).ToDictionary(x => x.Id); if (customer != null && !customer.IsSearchEngineAccount()) { @@ -371,37 +374,43 @@ public Currency WorkingCurrency var customerCurrencyId = customer.GetAttribute(SystemCustomerAttributeNames.CurrencyId, _attrService, _storeContext.CurrentStore.Id); if (customerCurrencyId.GetValueOrDefault() > 0) { - currency = VerifyCurrency(_currencyService.GetCurrencyById(customerCurrencyId.Value)); - if (currency == null) - { - _attrService.SaveAttribute(customer, SystemCustomerAttributeNames.CurrencyId, null, _storeContext.CurrentStore.Id); - } + if (storeCurrenciesMap.TryGetValue(customerCurrencyId.Value, out currency)) + { + currency = VerifyCurrency(currency); + if (currency == null) + { + _attrService.SaveAttribute(customer, SystemCustomerAttributeNames.CurrencyId, null, _storeContext.CurrentStore.Id); + } + } } } // find currency by domain ending if (currency == null && _httpContext != null && _httpContext.Request != null && _httpContext.Request.Url != null) { - currency = currentStoreCurrencies.GetByDomainEnding(_httpContext.Request.Url.Authority); + currency = storeCurrenciesMap.Values.GetByDomainEnding(_httpContext.Request.Url.Authority); } // if there's only one currency for current store it dominates the primary currency - if (currentStoreCurrencies.Count == 1) + if (storeCurrenciesMap.Count == 1) { - currency = currentStoreCurrencies.First(); + currency = storeCurrenciesMap[0]; } // get PrimaryStoreCurrency if (currency == null) { - currency = VerifyCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)); - fixPrimaryStoreCurrency = (currency == null); + if (storeCurrenciesMap.TryGetValue(_currencySettings.PrimaryStoreCurrencyId, out currency)) + { + currency = VerifyCurrency(currency); + fixPrimaryStoreCurrency = (currency == null); + } } // get the first published currency for current store if (currency == null) { - currency = currentStoreCurrencies.FirstOrDefault(); + currency = storeCurrenciesMap.Values.FirstOrDefault(); } } diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config index 084e63fb0f..32291a4cfb 100644 --- a/src/Presentation/SmartStore.Web/Web.config +++ b/src/Presentation/SmartStore.Web/Web.config @@ -42,7 +42,7 @@ - + From f8c5d8bbf70b890f0d7e1447ec2c6673bf4950e8 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 25 Jun 2015 01:32:39 +0200 Subject: [PATCH 0182/1256] (Perf) implemented static cache for localized properties, which are all loaded on app startup now. To disable this feature, set 'LocalizationSettings.LoadAllLocalizedPropertiesOnStartup' to false (true by default) --- .../Localization/LocalizationSettings.cs | 6 ++ .../Migrations/201504171629262_V22Final.cs | 2 +- ...06211043073_PaymentShippingRestrictions.cs | 5 ++ .../Localization/LocalizedEntityService.cs | 64 +++++++++++++------ 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Domain/Localization/LocalizationSettings.cs b/src/Libraries/SmartStore.Core/Domain/Localization/LocalizationSettings.cs index 4cd7889fee..b02a4ad2a2 100644 --- a/src/Libraries/SmartStore.Core/Domain/Localization/LocalizationSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Localization/LocalizationSettings.cs @@ -9,6 +9,7 @@ public LocalizationSettings() UseImagesForLanguageSelection = true; DefaultLanguageRedirectBehaviour = DefaultLanguageRedirectBehaviour.StripSeoCode; InvalidLanguageRedirectBehaviour = InvalidLanguageRedirectBehaviour.ReturnHttp404; + LoadAllLocalizedPropertiesOnStartup = true; } /// @@ -26,6 +27,11 @@ public LocalizationSettings() /// public bool LoadAllLocaleRecordsOnStartup { get; set; } + /// + /// A value indicating whether to load all localized entity properties on application startup + /// + public bool LoadAllLocalizedPropertiesOnStartup { get; set; } + /// /// A value indicating whether the browser user lannguage should be detected /// diff --git a/src/Libraries/SmartStore.Data/Migrations/201504171629262_V22Final.cs b/src/Libraries/SmartStore.Data/Migrations/201504171629262_V22Final.cs index 3f28263a18..23b0f56a14 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201504171629262_V22Final.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201504171629262_V22Final.cs @@ -90,7 +90,7 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Admin.Common.UnknownError", "An unknown error has occurred.", "Es ist ein unbekannter Fehler aufgetreten."); - + builder.AddOrUpdate("Plugins.Feed.FreeShippingThreshold", "Free shipping threshold", "Kostenloser Versand ab", diff --git a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs index cc83f0e114..2199b00670 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs @@ -44,6 +44,11 @@ public bool RollbackOnFailure public void Seed(SmartObjectContext context) { context.MigrateLocaleResources(MigrateLocaleResources); + + context.MigrateSettings(x => + { + x.Add("localizationsettings.loadalllocalizedpropertiesonstartup", true); + }); } public void MigrateLocaleResources(LocaleResourcesBuilder builder) diff --git a/src/Libraries/SmartStore.Services/Localization/LocalizedEntityService.cs b/src/Libraries/SmartStore.Services/Localization/LocalizedEntityService.cs index 0aad0675e5..fd48d2a7c6 100644 --- a/src/Libraries/SmartStore.Services/Localization/LocalizedEntityService.cs +++ b/src/Libraries/SmartStore.Services/Localization/LocalizedEntityService.cs @@ -7,6 +7,7 @@ using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Localization; +using SmartStore.Core.Infrastructure; namespace SmartStore.Services.Localization { @@ -18,7 +19,7 @@ public partial class LocalizedEntityService : ILocalizedEntityService #region Constants private const string LOCALIZEDPROPERTY_KEY = "SmartStore.localizedproperty.value-{0}-{1}-{2}-{3}"; - private const string LOCALIZEDPROPERTY_ENTITYID_KEY = "SmartStore.localizedproperty.entityid-{0}-{1}-{2}"; + private const string LOCALIZEDPROPERTY_ALL_KEY = "SmartStore.localizedproperty.all"; private const string LOCALIZEDPROPERTY_PATTERN_KEY = "SmartStore.localizedproperty."; #endregion @@ -27,6 +28,7 @@ public partial class LocalizedEntityService : ILocalizedEntityService private readonly IRepository _localizedPropertyRepository; private readonly ICacheManager _cacheManager; + private readonly LocalizationSettings _localizationSettings; #endregion @@ -37,11 +39,11 @@ public partial class LocalizedEntityService : ILocalizedEntityService ///
/// Cache manager /// Localized property repository - public LocalizedEntityService(ICacheManager cacheManager, - IRepository localizedPropertyRepository) + public LocalizedEntityService(ICacheManager cacheManager, IRepository localizedPropertyRepository, LocalizationSettings localizationSettings) { this._cacheManager = cacheManager; this._localizedPropertyRepository = localizedPropertyRepository; + this._localizationSettings = localizationSettings; } #endregion @@ -87,21 +89,42 @@ public virtual LocalizedProperty GetLocalizedPropertyById(int localizedPropertyI /// Found localized value public virtual string GetLocalizedValue(int languageId, int entityId, string localeKeyGroup, string localeKey) { - string key = string.Format(LOCALIZEDPROPERTY_KEY, languageId, entityId, localeKeyGroup, localeKey); - return _cacheManager.Get(key, () => - { - var query = from lp in _localizedPropertyRepository.Table - where lp.EntityId == entityId && - lp.LocaleKey == localeKey && - lp.LocaleKeyGroup == localeKeyGroup && - lp.LanguageId == languageId - select lp.LocaleValue; - var localeValue = query.FirstOrDefault(); - //little hack here. nulls aren't cacheable so set it to "" - if (localeValue == null) - localeValue = ""; - return localeValue; - }); + string val = null; + + if (_localizationSettings.LoadAllLocalizedPropertiesOnStartup) + { + var allValues = _cacheManager.Get(LOCALIZEDPROPERTY_ALL_KEY, () => + { + var result = _localizedPropertyRepository.TableUntracked.ToDictionary( + x => GenerateKey(x.LanguageId, x.LocaleKeyGroup, x.LocaleKey, x.EntityId), + x => x.LocaleValue); + return result; + }); + + string key = GenerateKey(languageId, localeKeyGroup, localeKey, entityId); + + if (!allValues.TryGetValue(key, out val)) + { + return string.Empty; + } + } + else + { + string cacheKey = string.Format(LOCALIZEDPROPERTY_KEY, languageId, entityId, localeKeyGroup, localeKey); + val = _cacheManager.Get(cacheKey, () => + { + var query = from lp in _localizedPropertyRepository.TableUntracked + where lp.EntityId == entityId && + lp.LocaleKey == localeKey && + lp.LocaleKeyGroup == localeKeyGroup && + lp.LanguageId == languageId + select lp.LocaleValue; + + return query.FirstOrDefault().EmptyNull(); + }); + } + + return val; } /// @@ -238,6 +261,11 @@ public virtual void SaveLocalizedValue(T entity, } } + private string GenerateKey(int languageId, string localeKeyGroup, string localeKey, int entityId) + { + return "{0}.{1}.{2}.{3}".FormatInvariant(languageId, localeKeyGroup, localeKey, entityId); + } + #endregion } } \ No newline at end of file From fe1117bdb599086ca99a3527cf9c858daeb7785b Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 25 Jun 2015 11:19:40 +0200 Subject: [PATCH 0183/1256] _commonServices becomes _services --- .../Catalog/PriceCalculationService.cs | 20 ++-- .../ExportImport/ExportManager.cs | 8 +- .../Filter/FilterService.cs | 10 +- .../Payments/PaymentService.cs | 34 +++--- .../ExternalAuthFacebookController.cs | 28 ++--- .../Core/FacebookProviderAuthorizer.cs | 12 +- .../Providers/PayPalStandardProvider.cs | 20 ++-- .../ByWeightShippingComputationMethod.cs | 6 +- .../Controllers/WebApiController.cs | 20 ++-- .../Controllers/CommonController.cs | 106 +++++++++--------- .../Controllers/ForumController.cs | 42 +++---- .../Controllers/PaymentController.cs | 22 ++-- .../Controllers/PluginController.cs | 38 +++---- .../Controllers/ShippingController.cs | 34 +++--- .../Catalog/PriceCalculationServiceTests.cs | 8 +- .../ExportImport/ExportManagerTests.cs | 6 +- .../Orders/OrderProcessingServiceTests.cs | 6 +- .../OrderTotalCalculationServiceTests.cs | 6 +- .../Payments/PaymentServiceTests.cs | 6 +- 19 files changed, 216 insertions(+), 216 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index e7d0550cde..e61c60cc35 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -26,7 +26,7 @@ public partial class PriceCalculationService : IPriceCalculationService private readonly CatalogSettings _catalogSettings; private readonly IProductAttributeService _productAttributeService; private readonly IDownloadService _downloadService; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; private readonly HttpRequestBase _httpRequestBase; private readonly ITaxService _taxService; @@ -39,7 +39,7 @@ public PriceCalculationService( CatalogSettings catalogSettings, IProductAttributeService productAttributeService, IDownloadService downloadService, - ICommonServices commonServices, + ICommonServices services, HttpRequestBase httpRequestBase, ITaxService taxService) { @@ -51,7 +51,7 @@ public PriceCalculationService( this._catalogSettings = catalogSettings; this._productAttributeService = productAttributeService; this._downloadService = downloadService; - this._commonServices = commonServices; + this._services = services; this._httpRequestBase = httpRequestBase; this._taxService = taxService; } @@ -129,7 +129,7 @@ protected virtual IList GetAllowedDiscounts(Product product, Customer var tierPrices = product.TierPrices .OrderBy(tp => tp.Quantity) - .FilterByStore(_commonServices.StoreContext.CurrentStore.Id) + .FilterByStore(_services.StoreContext.CurrentStore.Id) .FilterForCustomer(customer) .ToList() .RemoveDuplicatedQuantities(); @@ -212,7 +212,7 @@ protected virtual decimal GetPreselectedPrice(Product product, ProductBundleItem if (!isBundle && selectedAttributes.Count > 0) { - string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _commonServices.Localization, + string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _services.Localization, _downloadService, _catalogSettings, _httpRequestBase, new List(), true, bundleItemId); selectedAttributeValues = _productAttributeParser.ParseProductVariantAttributeValues(attributeXml).ToList(); @@ -242,7 +242,7 @@ protected virtual decimal GetPreselectedPrice(Product product, ProductBundleItem bundleItem.AdditionalCharge = attributesTotalPriceBase; } - var result = GetFinalPrice(product, bundleItems, _commonServices.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem); + var result = GetFinalPrice(product, bundleItems, _services.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem); return result; } @@ -290,7 +290,7 @@ protected virtual decimal GetPreselectedPrice(Product product, ProductBundleItem public virtual decimal GetFinalPrice(Product product, bool includeDiscounts) { - var customer = _commonServices.WorkContext.CurrentCustomer; + var customer = _services.WorkContext.CurrentCustomer; return GetFinalPrice(product, customer, includeDiscounts); } @@ -456,7 +456,7 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa } } - decimal lowestPrice = GetFinalPrice(product, bundleItems, _commonServices.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); + decimal lowestPrice = GetFinalPrice(product, bundleItems, _services.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); if (product.LowestAttributeCombinationPrice.HasValue && product.LowestAttributeCombinationPrice.Value < lowestPrice) { @@ -502,7 +502,7 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa foreach (var associatedProduct in associatedProducts) { - var tmpPrice = GetFinalPrice(associatedProduct, _commonServices.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); + var tmpPrice = GetFinalPrice(associatedProduct, _services.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); if (associatedProduct.LowestAttributeCombinationPrice.HasValue && associatedProduct.LowestAttributeCombinationPrice.Value < tmpPrice) { @@ -583,7 +583,7 @@ public virtual decimal GetProductCost(Product product, string attributesXml) /// Discount amount public virtual decimal GetDiscountAmount(Product product) { - var customer = _commonServices.WorkContext.CurrentCustomer; + var customer = _services.WorkContext.CurrentCustomer; return GetDiscountAmount(product, customer, decimal.Zero); } diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 21cb3055a1..0bd5599fd9 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -43,7 +43,7 @@ public partial class ExportManager : IExportManager private readonly INewsLetterSubscriptionService _newsLetterSubscriptionService; private readonly ILanguageService _languageService; private readonly MediaSettings _mediaSettings; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; private readonly IStoreMappingService _storeMappingService; #endregion @@ -58,7 +58,7 @@ public ExportManager(ICategoryService categoryService, INewsLetterSubscriptionService newsLetterSubscriptionService, ILanguageService languageService, MediaSettings mediaSettings, - ICommonServices commonServices, + ICommonServices services, IStoreMappingService storeMappingService) { this._categoryService = categoryService; @@ -69,7 +69,7 @@ public ExportManager(ICategoryService categoryService, this._newsLetterSubscriptionService = newsLetterSubscriptionService; this._languageService = languageService; this._mediaSettings = mediaSettings; - this._commonServices = commonServices; + this._services = services; this._storeMappingService = storeMappingService; Logger = NullLogger.Instance; @@ -728,7 +728,7 @@ public virtual void ExportProductsToXml(Stream stream, ProductSearchContext sear { ProductTemplates = _productTemplateService.GetAllProductTemplates(), Languages = _languageService.GetAllLanguages(true), - Store = _commonServices.StoreContext.CurrentStore + Store = _services.StoreContext.CurrentStore }; using (var writer = XmlWriter.Create(stream, settings)) diff --git a/src/Libraries/SmartStore.Services/Filter/FilterService.cs b/src/Libraries/SmartStore.Services/Filter/FilterService.cs index 66eaf99627..c96a3f23bf 100644 --- a/src/Libraries/SmartStore.Services/Filter/FilterService.cs +++ b/src/Libraries/SmartStore.Services/Filter/FilterService.cs @@ -24,7 +24,7 @@ public partial class FilterService : IFilterService private readonly IRepository _productRepository; private readonly IRepository _productCategoryRepository; private readonly ILocalizedEntityService _localizedEntityService; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; private IQueryable _products; @@ -34,7 +34,7 @@ public FilterService(IProductService productService, IRepository productRepository, IRepository productCategoryRepository, ILocalizedEntityService localizedEntityService, - ICommonServices commonServices) + ICommonServices services) { _productService = productService; _categoryService = categoryService; @@ -42,7 +42,7 @@ public FilterService(IProductService productService, _productRepository = productRepository; _productCategoryRepository = productCategoryRepository; _localizedEntityService = localizedEntityService; - _commonServices = commonServices; + _services = services; } public static string ShortcutPrice { get { return "_Price"; } } @@ -166,7 +166,7 @@ private IQueryable AllProducts(List categoryIds) var searchContext = new ProductSearchContext() { FeaturedProducts = (_catalogSettings.IncludeFeaturedProductsInNormalLists ? null : (bool?)false), - StoreId = _commonServices.StoreContext.CurrentStoreIdIfMultiStoreMode, + StoreId = _services.StoreContext.CurrentStoreIdIfMultiStoreMode, VisibleIndividuallyOnly = true }; @@ -316,7 +316,7 @@ from a in attributes var lst = grouped.OrderByDescending(a => a.MatchCount).ToList(); - int languageId = _commonServices.WorkContext.WorkingLanguage.Id; + int languageId = _services.WorkContext.WorkingLanguage.Id; lst.ForEach(c => { diff --git a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs index 24e39c2d32..f599e0e62f 100644 --- a/src/Libraries/SmartStore.Services/Payments/PaymentService.cs +++ b/src/Libraries/SmartStore.Services/Payments/PaymentService.cs @@ -35,7 +35,7 @@ public partial class PaymentService : IPaymentService private readonly ShoppingCartSettings _shoppingCartSettings; private readonly IProviderManager _providerManager; private readonly ICurrencyService _currencyService; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; private readonly IOrderTotalCalculationService _orderTotalCalculationService; #endregion @@ -56,7 +56,7 @@ public PaymentService( ShoppingCartSettings shoppingCartSettings, IProviderManager providerManager, ICurrencyService currencyService, - ICommonServices commonServices, + ICommonServices services, IOrderTotalCalculationService orderTotalCalculationService) { this._paymentMethodRepository = paymentMethodRepository; @@ -65,7 +65,7 @@ public PaymentService( this._shoppingCartSettings = shoppingCartSettings; this._providerManager = providerManager; this._currencyService = currencyService; - this._commonServices = commonServices; + this._services = services; this._orderTotalCalculationService = orderTotalCalculationService; } @@ -171,7 +171,7 @@ public virtual IEnumerable> LoadActivePaymentMethods( _orderTotalCalculationService.GetShoppingCartSubTotal(cart, out orderSubTotalDiscountAmountBase, out orderSubTotalAppliedDiscount, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); - orderSubTotal = _currencyService.ConvertFromPrimaryStoreCurrency(subTotalWithoutDiscountBase, _commonServices.WorkContext.WorkingCurrency); + orderSubTotal = _currencyService.ConvertFromPrimaryStoreCurrency(subTotalWithoutDiscountBase, _services.WorkContext.WorkingCurrency); } compareAmount = orderSubTotal.Value; @@ -182,7 +182,7 @@ public virtual IEnumerable> LoadActivePaymentMethods( { orderTotal = _orderTotalCalculationService.GetShoppingCartTotal(cart) ?? decimal.Zero; - orderTotal = _currencyService.ConvertFromPrimaryStoreCurrency(orderTotal.Value, _commonServices.WorkContext.WorkingCurrency); + orderTotal = _currencyService.ConvertFromPrimaryStoreCurrency(orderTotal.Value, _services.WorkContext.WorkingCurrency); } compareAmount = orderTotal.Value; @@ -261,7 +261,7 @@ public virtual IEnumerable> LoadAllPaymentMethods(int s /// List of payment method objects public virtual IList GetAllPaymentMethods() { - var paymentMethods = _commonServices.Cache.Get(PAYMENTMETHOD_ALL_KEY, () => + var paymentMethods = _services.Cache.Get(PAYMENTMETHOD_ALL_KEY, () => { var methods = _paymentMethodRepository.TableUntracked.ToList(); @@ -298,9 +298,9 @@ public virtual void InsertPaymentMethod(PaymentMethod paymentMethod) _paymentMethodRepository.Insert(paymentMethod); - _commonServices.Cache.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); + _services.Cache.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); - _commonServices.EventPublisher.EntityInserted(paymentMethod); + _services.EventPublisher.EntityInserted(paymentMethod); } /// @@ -314,9 +314,9 @@ public virtual void UpdatePaymentMethod(PaymentMethod paymentMethod) _paymentMethodRepository.Update(paymentMethod); - _commonServices.Cache.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); + _services.Cache.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); - _commonServices.EventPublisher.EntityUpdated(paymentMethod); + _services.EventPublisher.EntityUpdated(paymentMethod); } /// @@ -330,9 +330,9 @@ public virtual void DeletePaymentMethod(PaymentMethod paymentMethod) _paymentMethodRepository.Delete(paymentMethod); - _commonServices.Cache.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); + _services.Cache.RemoveByPattern(PAYMENTMETHOD_ALL_KEY); - _commonServices.EventPublisher.EntityDeleted(paymentMethod); + _services.EventPublisher.EntityDeleted(paymentMethod); } @@ -481,7 +481,7 @@ public virtual CapturePaymentResult Capture(CapturePaymentRequest capturePayment catch (NotSupportedException) { var result = new CapturePaymentResult(); - result.AddError(_commonServices.Localization.GetResource("Common.Payment.NoCaptureSupport")); + result.AddError(_services.Localization.GetResource("Common.Payment.NoCaptureSupport")); return result; } catch @@ -536,7 +536,7 @@ public virtual RefundPaymentResult Refund(RefundPaymentRequest refundPaymentRequ catch (NotSupportedException) { var result = new RefundPaymentResult(); - result.AddError(_commonServices.Localization.GetResource("Common.Payment.NoRefundSupport")); + result.AddError(_services.Localization.GetResource("Common.Payment.NoRefundSupport")); return result; } catch @@ -578,7 +578,7 @@ public virtual VoidPaymentResult Void(VoidPaymentRequest voidPaymentRequest) catch (NotSupportedException) { var result = new VoidPaymentResult(); - result.AddError(_commonServices.Localization.GetResource("Common.Payment.NoVoidSupport")); + result.AddError(_services.Localization.GetResource("Common.Payment.NoVoidSupport")); return result; } catch @@ -630,7 +630,7 @@ public virtual ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentReques catch (NotSupportedException) { var result = new ProcessPaymentResult(); - result.AddError(_commonServices.Localization.GetResource("Common.Payment.NoRecurringPaymentSupport")); + result.AddError(_services.Localization.GetResource("Common.Payment.NoRecurringPaymentSupport")); return result; } catch @@ -661,7 +661,7 @@ public virtual CancelRecurringPaymentResult CancelRecurringPayment(CancelRecurri catch (NotSupportedException) { var result = new CancelRecurringPaymentResult(); - result.AddError(_commonServices.Localization.GetResource("Common.Payment.NoRecurringPaymentSupport")); + result.AddError(_services.Localization.GetResource("Common.Payment.NoRecurringPaymentSupport")); return result; } catch diff --git a/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs b/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs index 1ed000f3bb..9ac4d52308 100644 --- a/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs +++ b/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs @@ -17,26 +17,26 @@ public class ExternalAuthFacebookController : PluginControllerBase private readonly IOAuthProviderFacebookAuthorizer _oAuthProviderFacebookAuthorizer; private readonly IOpenAuthenticationService _openAuthenticationService; private readonly ExternalAuthenticationSettings _externalAuthenticationSettings; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; public ExternalAuthFacebookController( IOAuthProviderFacebookAuthorizer oAuthProviderFacebookAuthorizer, IOpenAuthenticationService openAuthenticationService, ExternalAuthenticationSettings externalAuthenticationSettings, - ICommonServices commonServices) + ICommonServices services) { this._oAuthProviderFacebookAuthorizer = oAuthProviderFacebookAuthorizer; this._openAuthenticationService = openAuthenticationService; this._externalAuthenticationSettings = externalAuthenticationSettings; - this._commonServices = commonServices; + this._services = services; } private bool HasPermission(bool notify = true) { - bool hasPermission = _commonServices.Permissions.Authorize(StandardPermissionProvider.ManageExternalAuthenticationMethods); + bool hasPermission = _services.Permissions.Authorize(StandardPermissionProvider.ManageExternalAuthenticationMethods); if (notify && !hasPermission) - NotifyError(_commonServices.Localization.GetResource("Admin.AccessDenied.Description")); + NotifyError(_services.Localization.GetResource("Admin.AccessDenied.Description")); return hasPermission; } @@ -48,14 +48,14 @@ public ActionResult Configure() return AccessDeniedPartialView(); var model = new ConfigurationModel(); - int storeScope = this.GetActiveStoreScopeConfiguration(_commonServices.StoreService, _commonServices.WorkContext); - var settings = _commonServices.Settings.LoadSetting(storeScope); + int storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var settings = _services.Settings.LoadSetting(storeScope); model.ClientKeyIdentifier = settings.ClientKeyIdentifier; model.ClientSecret = settings.ClientSecret; var storeDependingSettingHelper = new StoreDependingSettingHelper(ViewData); - storeDependingSettingHelper.GetOverrideKeys(settings, model, storeScope, _commonServices.Settings); + storeDependingSettingHelper.GetOverrideKeys(settings, model, storeScope, _services.Settings); return View(model); } @@ -70,16 +70,16 @@ public ActionResult Configure(ConfigurationModel model, FormCollection form) return Configure(); var storeDependingSettingHelper = new StoreDependingSettingHelper(ViewData); - int storeScope = this.GetActiveStoreScopeConfiguration(_commonServices.StoreService, _commonServices.WorkContext); - var settings = _commonServices.Settings.LoadSetting(storeScope); + int storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var settings = _services.Settings.LoadSetting(storeScope); settings.ClientKeyIdentifier = model.ClientKeyIdentifier; settings.ClientSecret = model.ClientSecret; - storeDependingSettingHelper.UpdateSettings(settings, form, storeScope, _commonServices.Settings); - _commonServices.Settings.ClearCache(); + storeDependingSettingHelper.UpdateSettings(settings, form, storeScope, _services.Settings); + _services.Settings.ClearCache(); - NotifySuccess(_commonServices.Localization.GetResource("Admin.Common.DataSuccessfullySaved")); + NotifySuccess(_services.Localization.GetResource("Admin.Common.DataSuccessfullySaved")); return Configure(); } @@ -93,7 +93,7 @@ public ActionResult PublicInfo() [NonAction] private ActionResult LoginInternal(string returnUrl, bool verifyResponse) { - var processor = _openAuthenticationService.LoadExternalAuthenticationMethodBySystemName(Provider.SystemName, _commonServices.StoreContext.CurrentStore.Id); + var processor = _openAuthenticationService.LoadExternalAuthenticationMethodBySystemName(Provider.SystemName, _services.StoreContext.CurrentStore.Id); if (processor == null || !processor.IsMethodActive(_externalAuthenticationSettings)) { throw new SmartException("Facebook module cannot be loaded"); diff --git a/src/Plugins/SmartStore.FacebookAuth/Core/FacebookProviderAuthorizer.cs b/src/Plugins/SmartStore.FacebookAuth/Core/FacebookProviderAuthorizer.cs index 34eabdbffc..7bb6234362 100644 --- a/src/Plugins/SmartStore.FacebookAuth/Core/FacebookProviderAuthorizer.cs +++ b/src/Plugins/SmartStore.FacebookAuth/Core/FacebookProviderAuthorizer.cs @@ -22,7 +22,7 @@ public class FacebookProviderAuthorizer : IOAuthProviderFacebookAuthorizer private readonly IOpenAuthenticationService _openAuthenticationService; private readonly ExternalAuthenticationSettings _externalAuthenticationSettings; private readonly HttpContextBase _httpContext; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; private FacebookClient _facebookApplication; @@ -34,13 +34,13 @@ public FacebookProviderAuthorizer(IExternalAuthorizer authorizer, IOpenAuthenticationService openAuthenticationService, ExternalAuthenticationSettings externalAuthenticationSettings, HttpContextBase httpContext, - ICommonServices commonServices) + ICommonServices services) { this._authorizer = authorizer; this._openAuthenticationService = openAuthenticationService; this._externalAuthenticationSettings = externalAuthenticationSettings; this._httpContext = httpContext; - this._commonServices = commonServices; + this._services = services; } #endregion @@ -53,7 +53,7 @@ private FacebookClient FacebookApplication { if (_facebookApplication == null) { - var settings = _commonServices.Settings.LoadSetting(_commonServices.StoreContext.CurrentStore.Id); + var settings = _services.Settings.LoadSetting(_services.StoreContext.CurrentStore.Id); _facebookApplication = new FacebookClient(settings.ClientKeyIdentifier, settings.ClientSecret); } @@ -133,7 +133,7 @@ private AuthorizeState RequestAuthentication(string returnUrl) private Uri GenerateLocalCallbackUri() { - string url = string.Format("{0}Plugins/SmartStore.FacebookAuth/logincallback/", _commonServices.WebHelper.GetStoreLocation()); + string url = string.Format("{0}Plugins/SmartStore.FacebookAuth/logincallback/", _services.WebHelper.GetStoreLocation()); return new Uri(url); } @@ -142,7 +142,7 @@ private Uri GenerateServiceLoginUrl() //code copied from DotNetOpenAuth.AspNet.Clients.FacebookClient file var builder = new UriBuilder("https://www.facebook.com/dialog/oauth"); var args = new Dictionary(); - var settings = _commonServices.Settings.LoadSetting(_commonServices.StoreContext.CurrentStore.Id); + var settings = _services.Settings.LoadSetting(_services.StoreContext.CurrentStore.Id); args.Add("client_id", settings.ClientKeyIdentifier); args.Add("redirect_uri", GenerateLocalCallbackUri().AbsoluteUri); diff --git a/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs b/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs index f2e2331ce6..c009c24d3c 100644 --- a/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs +++ b/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs @@ -38,21 +38,21 @@ public partial class PayPalStandardProvider : PaymentPluginBase, IConfigurable private readonly CurrencySettings _currencySettings; private readonly IOrderTotalCalculationService _orderTotalCalculationService; private readonly HttpContextBase _httpContext; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; private readonly ILogger _logger; public PayPalStandardProvider(ICurrencyService currencyService, HttpContextBase httpContext, CurrencySettings currencySettings, IOrderTotalCalculationService orderTotalCalculationService, - ICommonServices commonServices, + ICommonServices services, ILogger logger) { _currencyService = currencyService; _currencySettings = currencySettings; _orderTotalCalculationService = orderTotalCalculationService; _httpContext = httpContext; - _commonServices = commonServices; + _services = services; _logger = logger; } @@ -66,7 +66,7 @@ public override ProcessPaymentResult ProcessPayment(ProcessPaymentRequest proces var result = new ProcessPaymentResult(); result.NewPaymentStatus = PaymentStatus.Pending; - var settings = _commonServices.Settings.LoadSetting(processPaymentRequest.StoreId); + var settings = _services.Settings.LoadSetting(processPaymentRequest.StoreId); if (settings.BusinessEmail.IsEmpty() || settings.PdtToken.IsEmpty()) { @@ -85,7 +85,7 @@ public override void PostProcessPayment(PostProcessPaymentRequest postProcessPay if (postProcessPaymentRequest.Order.PaymentStatus == PaymentStatus.Paid) return; - var settings = _commonServices.Settings.LoadSetting(postProcessPaymentRequest.Order.StoreId); + var settings = _services.Settings.LoadSetting(postProcessPaymentRequest.Order.StoreId); var builder = new StringBuilder(); builder.Append(PayPalHelper.GetPaypalUrl(settings)); @@ -239,8 +239,8 @@ public override void PostProcessPayment(PostProcessPaymentRequest postProcessPay builder.AppendFormat("&no_shipping=1", new object[0]); } - string returnUrl = _commonServices.WebHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/PDTHandler"; - string cancelReturnUrl = _commonServices.WebHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/CancelOrder"; + string returnUrl = _services.WebHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/PDTHandler"; + string cancelReturnUrl = _services.WebHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/CancelOrder"; builder.AppendFormat("&return={0}&cancel_return={1}", HttpUtility.UrlEncode(returnUrl), HttpUtility.UrlEncode(cancelReturnUrl)); //Instant Payment Notification (server to server message) @@ -248,7 +248,7 @@ public override void PostProcessPayment(PostProcessPaymentRequest postProcessPay { string ipnUrl; if (String.IsNullOrWhiteSpace(settings.IpnUrl)) - ipnUrl = _commonServices.WebHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/IPNHandler"; + ipnUrl = _services.WebHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/IPNHandler"; else ipnUrl = settings.IpnUrl; builder.AppendFormat("¬ify_url={0}", ipnUrl); @@ -315,7 +315,7 @@ public override decimal GetAdditionalHandlingFee(IList(_commonServices.StoreContext.CurrentStore.Id); + var settings = _services.Settings.LoadSetting(_services.StoreContext.CurrentStore.Id); result = this.CalculateAdditionalFee(_orderTotalCalculationService, cart, settings.AdditionalFee, settings.AdditionalFeePercentage); } @@ -569,7 +569,7 @@ public void AdjustLineItemAmounts(List paypalItems, PostProcessP public bool VerifyIPN(string formString, out Dictionary values) { // settings: multistore context not possible here. we need the custom value to determine what store it is. - var settings = _commonServices.Settings.LoadSetting(); + var settings = _services.Settings.LoadSetting(); var req = (HttpWebRequest)WebRequest.Create(PayPalHelper.GetPaypalUrl(settings)); req.Method = "POST"; diff --git a/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs b/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs index bc94c7a947..6682416683 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs @@ -27,7 +27,7 @@ public class ByWeightShippingComputationMethod : BasePlugin, IShippingRateComput private readonly ShippingByWeightObjectContext _objectContext; private readonly ILocalizationService _localizationService; private readonly IPriceFormatter _priceFormatter; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; #endregion @@ -40,7 +40,7 @@ public ByWeightShippingComputationMethod(IShippingService shippingService, ShippingByWeightObjectContext objectContext, ILocalizationService localizationService, IPriceFormatter priceFormatter, - ICommonServices commonServices) + ICommonServices services) { this._shippingService = shippingService; this._storeContext = storeContext; @@ -50,7 +50,7 @@ public ByWeightShippingComputationMethod(IShippingService shippingService, this._objectContext = objectContext; this._localizationService = localizationService; this._priceFormatter = priceFormatter; - this._commonServices = commonServices; + this._services = services; } #endregion diff --git a/src/Plugins/SmartStore.WebApi/Controllers/WebApiController.cs b/src/Plugins/SmartStore.WebApi/Controllers/WebApiController.cs index 30c9c98295..58e3d49117 100644 --- a/src/Plugins/SmartStore.WebApi/Controllers/WebApiController.cs +++ b/src/Plugins/SmartStore.WebApi/Controllers/WebApiController.cs @@ -19,36 +19,36 @@ public class WebApiController : PluginControllerBase private readonly WebApiSettings _webApiSettings; private readonly IWebApiPluginService _webApiPluginService; private readonly AdminAreaSettings _adminAreaSettings; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; public WebApiController( WebApiSettings settings, IWebApiPluginService webApiPluginService, AdminAreaSettings adminAreaSettings, - ICommonServices commonServices) + ICommonServices services) { _webApiSettings = settings; _webApiPluginService = webApiPluginService; _adminAreaSettings = adminAreaSettings; - _commonServices = commonServices; + _services = services; } private bool HasPermission(bool notify = true) { - bool hasPermission = _commonServices.Permissions.Authorize(WebApiPermissionProvider.ManageWebApi); + bool hasPermission = _services.Permissions.Authorize(WebApiPermissionProvider.ManageWebApi); if (notify && !hasPermission) - NotifyError(_commonServices.Localization.GetResource("Admin.AccessDenied.Description")); + NotifyError(_services.Localization.GetResource("Admin.AccessDenied.Description")); return hasPermission; } private void AddButtonText() { - ViewData["ButtonTextEnable"] = _commonServices.Localization.GetResource("Plugins.Api.WebApi.Activate"); - ViewData["ButtonTextDisable"] = _commonServices.Localization.GetResource("Plugins.Api.WebApi.Deactivate"); - ViewData["ButtonTextRemoveKeys"] = _commonServices.Localization.GetResource("Plugins.Api.WebApi.RemoveKeys"); - ViewData["ButtonTextCreateKeys"] = _commonServices.Localization.GetResource("Plugins.Api.WebApi.CreateKeys"); + ViewData["ButtonTextEnable"] = _services.Localization.GetResource("Plugins.Api.WebApi.Activate"); + ViewData["ButtonTextDisable"] = _services.Localization.GetResource("Plugins.Api.WebApi.Deactivate"); + ViewData["ButtonTextRemoveKeys"] = _services.Localization.GetResource("Plugins.Api.WebApi.RemoveKeys"); + ViewData["ButtonTextCreateKeys"] = _services.Localization.GetResource("Plugins.Api.WebApi.CreateKeys"); } public ActionResult Configure() @@ -84,7 +84,7 @@ public ActionResult SaveGeneralSettings(WebApiConfigModel model) return AccessDeniedPartialView(); model.Copy(_webApiSettings, false); - _commonServices.Settings.SaveSetting(_webApiSettings); + _services.Settings.SaveSetting(_webApiSettings); WebApiCachingControllingData.Remove(); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs index 82b4cffdee..d9424d8fe0 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs @@ -68,7 +68,7 @@ public class CommonController : AdminControllerBase private readonly Lazy _menuPublisher; private readonly Lazy _pluginFinder; private readonly IGenericAttributeService _genericAttributeService; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; private readonly Func _cache; private readonly static object s_lock = new object(); @@ -95,7 +95,7 @@ public CommonController( Lazy menuPublisher, Lazy pluginFinder, IGenericAttributeService genericAttributeService, - ICommonServices commonServices, + ICommonServices services, Func cache) { this._paymentService = paymentService; @@ -115,7 +115,7 @@ public CommonController( this._menuPublisher = menuPublisher; this._pluginFinder = pluginFinder; this._genericAttributeService = genericAttributeService; - this._commonServices = commonServices; + this._services = services; this._cache = cache; } @@ -128,11 +128,11 @@ public CommonController( [ChildActionOnly] public ActionResult Navbar() { - var currentCustomer = _commonServices.WorkContext.CurrentCustomer; + var currentCustomer = _services.WorkContext.CurrentCustomer; - ViewBag.UserName = _commonServices.Settings.LoadSetting().UsernamesEnabled ? currentCustomer.Username : currentCustomer.Email; - ViewBag.Stores = _commonServices.StoreService.GetAllStores(); - if (_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + ViewBag.UserName = _services.Settings.LoadSetting().UsernamesEnabled ? currentCustomer.Username : currentCustomer.Email; + ViewBag.Stores = _services.StoreService.GetAllStores(); + if (_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) { ViewBag.CheckUpdateResult = AsyncRunner.RunSync(() => CheckUpdateAsync(false)); } @@ -143,10 +143,10 @@ public ActionResult Navbar() [ChildActionOnly] public ActionResult Menu() { - var cacheManager = _commonServices.Cache; + var cacheManager = _services.Cache; - var customerRolesIds = _commonServices.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); - string cacheKey = string.Format("smartstore.pres.adminmenu.navigation-{0}-{1}", _commonServices.WorkContext.WorkingLanguage.Id, string.Join(",", customerRolesIds)); + var customerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); + string cacheKey = string.Format("smartstore.pres.adminmenu.navigation-{0}-{1}", _services.WorkContext.WorkingLanguage.Id, string.Join(",", customerRolesIds)); var rootNode = cacheManager.Get(cacheKey, () => { @@ -255,7 +255,7 @@ private bool MenuItemAccessPermitted(MenuItem item) if (_securitySettings.Value.HideAdminMenuItemsBasedOnPermissions && item.PermissionNames.HasValue()) { - var permitted = item.PermissionNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Any(x => _commonServices.Permissions.Authorize(x.Trim())); + var permitted = item.PermissionNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Any(x => _services.Permissions.Authorize(x.Trim())); if (!permitted) { result = false; @@ -284,24 +284,24 @@ public ActionResult CheckUpdateSuppress(string myVersion, string newVersion) public void CheckUpdateSuppressInternal(string myVersion, string newVersion) { var suppressKey = "SuppressUpdateMessage.{0}.{1}".FormatInvariant(myVersion, newVersion); - _genericAttributeService.SaveAttribute(_commonServices.WorkContext.CurrentCustomer, suppressKey, true); - _commonServices.Cache.RemoveByPattern("Common.CheckUpdateResult"); + _genericAttributeService.SaveAttribute(_services.WorkContext.CurrentCustomer, suppressKey, true); + _services.Cache.RemoveByPattern("Common.CheckUpdateResult"); } [NonAction] private async Task CheckUpdateAsync(bool enforce = false, bool forSuppress = false) { var curVersion = SmartStoreVersion.CurrentFullVersion; - var lang = _commonServices.WorkContext.WorkingLanguage.UniqueSeoCode; + var lang = _services.WorkContext.WorkingLanguage.UniqueSeoCode; var cacheKeyPattern = "Common.CheckUpdateResult"; var cacheKey = "{0}.{1}".FormatInvariant(cacheKeyPattern, lang); if (enforce) { - _commonServices.Cache.RemoveByPattern(cacheKeyPattern); + _services.Cache.RemoveByPattern(cacheKeyPattern); } - var result = await _commonServices.Cache.Get(cacheKey, async () => + var result = await _services.Cache.Get(cacheKey, async () => { var noUpdateResult = new CheckUpdateResult { UpdateAvailable = false, LanguageCode = lang, CurrentVersion = curVersion }; @@ -315,7 +315,7 @@ private async Task CheckUpdateAsync(bool enforce = false, boo client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.UserAgent.ParseAdd("SmartStore.NET {0}".FormatInvariant(curVersion)); - client.DefaultRequestHeaders.Add("Authorization-Key", _commonServices.StoreContext.CurrentStore.Url.TrimEnd('/')); + client.DefaultRequestHeaders.Add("Authorization-Key", _services.StoreContext.CurrentStore.Url.TrimEnd('/')); HttpResponseMessage response = await client.GetAsync(url); @@ -331,7 +331,7 @@ private async Task CheckUpdateAsync(bool enforce = false, boo model.CurrentVersion = curVersion; model.LanguageCode = lang; - if (CommonHelper.IsDevEnvironment || !_commonSettings.Value.AutoUpdateEnabled || !_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (CommonHelper.IsDevEnvironment || !_commonSettings.Value.AutoUpdateEnabled || !_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) { model.AutoUpdatePossible = false; } @@ -341,9 +341,9 @@ private async Task CheckUpdateAsync(bool enforce = false, boo if (enforce) { // but ignore user's decision if 'enforce' - _genericAttributeService.SaveAttribute(_commonServices.WorkContext.CurrentCustomer, suppressKey, null); + _genericAttributeService.SaveAttribute(_services.WorkContext.CurrentCustomer, suppressKey, null); } - var showMessage = enforce || _commonServices.WorkContext.CurrentCustomer.GetAttribute(suppressKey, _genericAttributeService).GetValueOrDefault() == false; + var showMessage = enforce || _services.WorkContext.CurrentCustomer.GetAttribute(suppressKey, _genericAttributeService).GetValueOrDefault() == false; if (!showMessage) { return noUpdateResult; @@ -364,7 +364,7 @@ private async Task CheckUpdateAsync(bool enforce = false, boo public ActionResult InstallUpdate(string packageUrl) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); try @@ -385,7 +385,7 @@ public ActionResult InstallUpdate(string packageUrl) } else { - _commonServices.WebHelper.RestartAppDomain(); + _services.WebHelper.RestartAppDomain(); } } @@ -453,12 +453,12 @@ public ActionResult SystemInfo() model.ServerTimeZone = TimeZone.CurrentTimeZone.StandardName; model.ServerLocalTime = DateTime.Now; model.UtcTime = DateTime.UtcNow; - model.HttpHost = _commonServices.WebHelper.ServerVariables("HTTP_HOST"); + model.HttpHost = _services.WebHelper.ServerVariables("HTTP_HOST"); //Environment.GetEnvironmentVariable("USERNAME"); try { - var mbSize = _commonServices.DbContext.SqlQuery("Select Sum(size)/128.0 From sysfiles").FirstOrDefault(); + var mbSize = _services.DbContext.SqlQuery("Select Sum(size)/128.0 From sysfiles").FirstOrDefault(); model.DatabaseSize = Convert.ToDouble(mbSize); } catch (Exception) { } @@ -468,7 +468,7 @@ public ActionResult SystemInfo() if (DataSettings.Current.IsValid()) { model.DataProviderFriendlyName = DataSettings.Current.ProviderFriendlyName; - model.ShrinkDatabaseEnabled = _commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance) && DataSettings.Current.IsSqlServer; + model.ShrinkDatabaseEnabled = _services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance) && DataSettings.Current.IsSqlServer; } } catch (Exception) { } @@ -498,8 +498,8 @@ public ActionResult Warnings() var model = new List(); //store URL - var storeUrl = _commonServices.StoreContext.CurrentStore.Url.EnsureEndsWith("/"); - if (storeUrl.HasValue() && (storeUrl.IsCaseInsensitiveEqual(_commonServices.WebHelper.GetStoreLocation(false)) || storeUrl.IsCaseInsensitiveEqual(_commonServices.WebHelper.GetStoreLocation(true)))) + var storeUrl = _services.StoreContext.CurrentStore.Url.EnsureEndsWith("/"); + if (storeUrl.HasValue() && (storeUrl.IsCaseInsensitiveEqual(_services.WebHelper.GetStoreLocation(false)) || storeUrl.IsCaseInsensitiveEqual(_services.WebHelper.GetStoreLocation(true)))) { model.Add(new SystemWarningModel { @@ -512,7 +512,7 @@ public ActionResult Warnings() model.Add(new SystemWarningModel { Level = SystemWarningLevel.Warning, - Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.URL.NoMatch"), storeUrl, _commonServices.WebHelper.GetStoreLocation(false)) + Text = string.Format(_localizationService.GetResource("Admin.System.Warnings.URL.NoMatch"), storeUrl, _services.WebHelper.GetStoreLocation(false)) }); } @@ -699,7 +699,7 @@ public ActionResult Warnings() //validate write permissions (the same procedure like during installation) var dirPermissionsOk = true; - var dirsToCheck = FilePermissionHelper.GetDirectoriesWrite(_commonServices.WebHelper); + var dirsToCheck = FilePermissionHelper.GetDirectoriesWrite(_services.WebHelper); foreach (string dir in dirsToCheck) { if (!FilePermissionHelper.CheckPermissions(dir, false, true, true, false)) @@ -722,7 +722,7 @@ public ActionResult Warnings() } var filePermissionsOk = true; - var filesToCheck = FilePermissionHelper.GetFilesWrite(_commonServices.WebHelper); + var filesToCheck = FilePermissionHelper.GetFilesWrite(_services.WebHelper); foreach (string file in filesToCheck) { if (!FilePermissionHelper.CheckPermissions(file, false, true, true, true)) @@ -749,14 +749,14 @@ public ActionResult Warnings() public ActionResult ShrinkDatabase() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); try { if (DataSettings.Current.IsSqlServer) { - _commonServices.DbContext.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); + _services.DbContext.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); NotifySuccess(_localizationService.GetResource("Common.ShrinkDatabaseSuccessful")); } } @@ -770,7 +770,7 @@ public ActionResult ShrinkDatabase() public ActionResult Maintenance() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); var model = new MaintenanceModel(); @@ -791,7 +791,7 @@ public ActionResult Maintenance() [FormValueRequired("delete-image-cache")] public ActionResult MaintenanceDeleteImageCache() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); _imageCache.Value.DeleteCachedImages(); @@ -803,7 +803,7 @@ public ActionResult MaintenanceDeleteImageCache() [FormValueRequired("delete-guests")] public ActionResult MaintenanceDeleteGuests(MaintenanceModel model) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); DateTime? startDateValue = (model.DeleteGuests.StartDate == null) ? null @@ -821,7 +821,7 @@ public ActionResult MaintenanceDeleteGuests(MaintenanceModel model) [FormValueRequired("delete-exported-files")] public ActionResult MaintenanceDeleteFiles(MaintenanceModel model) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); DateTime? startDateValue = (model.DeleteExportedFiles.StartDate == null) ? null @@ -865,7 +865,7 @@ public ActionResult MaintenanceDeleteFiles(MaintenanceModel model) [FormValueRequired("execute-sql-query")] public ActionResult MaintenanceExecuteSql(MaintenanceModel model) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); if (model.SqlQuery.HasValue()) @@ -890,9 +890,9 @@ public ActionResult MaintenanceExecuteSql(MaintenanceModel model) public ActionResult LanguageSelector() { var model = new LanguageSelectorModel(); - model.CurrentLanguage = _commonServices.WorkContext.WorkingLanguage.ToModel(); + model.CurrentLanguage = _services.WorkContext.WorkingLanguage.ToModel(); model.AvailableLanguages = _languageService - .GetAllLanguages(storeId: _commonServices.StoreContext.CurrentStore.Id) + .GetAllLanguages(storeId: _services.StoreContext.CurrentStore.Id) .Select(x => x.ToModel()) .ToList(); return PartialView(model); @@ -902,14 +902,14 @@ public ActionResult LanguageSelected(int customerlanguage) var language = _languageService.GetLanguageById(customerlanguage); if (language != null) { - _commonServices.WorkContext.WorkingLanguage = language; + _services.WorkContext.WorkingLanguage = language; } return Content(_localizationService.GetResource("Admin.Common.DataEditSuccess")); } public ActionResult ClearCache(string previousUrl) { - var cacheManager = _commonServices.Cache; + var cacheManager = _services.Cache; cacheManager.Clear(); cacheManager = _cache("aspnet"); @@ -925,10 +925,10 @@ public ActionResult ClearCache(string previousUrl) public ActionResult RestartApplication(string previousUrl) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); - _commonServices.WebHelper.RestartAppDomain(); + _services.WebHelper.RestartAppDomain(); if (previousUrl.HasValue()) return Redirect(previousUrl); @@ -942,7 +942,7 @@ public ActionResult RestartApplication(string previousUrl) public ActionResult SeNames() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); var model = new UrlRecordListModel(); @@ -952,7 +952,7 @@ public ActionResult SeNames() [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult SeNames(GridCommand command, UrlRecordListModel model) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); var urlRecords = _urlRecordService.GetAllUrlRecords(model.SeName, command.Page - 1, command.PageSize); @@ -991,7 +991,7 @@ public ActionResult SeNames(GridCommand command, UrlRecordListModel model) [HttpPost] public ActionResult DeleteSelectedSeNames(ICollection selectedIds) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageMaintenance)) return AccessDeniedView(); if (selectedIds != null) @@ -1026,10 +1026,10 @@ public ActionResult GenericAttributes(string entityName, int entityId) [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributesSelect(string entityName, int entityId, GridCommand command) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); - var storeId = _commonServices.StoreContext.CurrentStore.Id; + var storeId = _services.StoreContext.CurrentStore.Id; ViewBag.StoreId = storeId; var model = new List(); @@ -1064,7 +1064,7 @@ public ActionResult GenericAttributesSelect(string entityName, int entityId, Gri [GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributeAdd(GenericAttributeModel model, GridCommand command) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); model.Key = model.Key.TrimSafe(); @@ -1077,7 +1077,7 @@ public ActionResult GenericAttributeAdd(GenericAttributeModel model, GridCommand return Content(modelStateErrorMessages.FirstOrDefault()); } - var storeId = _commonServices.StoreContext.CurrentStore.Id; + var storeId = _services.StoreContext.CurrentStore.Id; var attr = _genericAttributeService.GetAttribute(model.EntityName, model.EntityId, model.Key, storeId); if (attr == null) @@ -1103,7 +1103,7 @@ public ActionResult GenericAttributeAdd(GenericAttributeModel model, GridCommand [GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributeUpdate(GenericAttributeModel model, GridCommand command) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); model.Key = model.Key.TrimSafe(); @@ -1116,7 +1116,7 @@ public ActionResult GenericAttributeUpdate(GenericAttributeModel model, GridComm return Content(modelStateErrorMessages.FirstOrDefault()); } - var storeId = _commonServices.StoreContext.CurrentStore.Id; + var storeId = _services.StoreContext.CurrentStore.Id; var attr = _genericAttributeService.GetAttributeById(model.Id); // if the key changed, ensure it isn't being used by another attribute @@ -1142,7 +1142,7 @@ public ActionResult GenericAttributeUpdate(GenericAttributeModel model, GridComm [GridAction(EnableCustomBinding = true)] public ActionResult GenericAttributeDelete(int id, GridCommand command) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel)) return AccessDeniedView(); var attr = _genericAttributeService.GetAttributeById(id); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs index 988c4164de..5b113525ed 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs @@ -18,7 +18,7 @@ namespace SmartStore.Admin.Controllers public class ForumController : AdminControllerBase { private readonly IForumService _forumService; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; private readonly IDateTimeHelper _dateTimeHelper; private readonly IStoreMappingService _storeMappingService; private readonly ILanguageService _languageService; @@ -26,7 +26,7 @@ public class ForumController : AdminControllerBase private readonly IUrlRecordService _urlRecordService; public ForumController(IForumService forumService, - ICommonServices commonServices, + ICommonServices services, IDateTimeHelper dateTimeHelper, IStoreMappingService storeMappingService, ILanguageService languageService, @@ -34,7 +34,7 @@ public ForumController(IForumService forumService, IUrlRecordService urlRecordService) { _forumService = forumService; - _commonServices = commonServices; + _services = services; _dateTimeHelper = dateTimeHelper; _storeMappingService = storeMappingService; _languageService = languageService; @@ -50,7 +50,7 @@ private void PrepareForumGroupModel(ForumGroupModel model, ForumGroup forumGroup if (model == null) throw new ArgumentNullException("model"); - var allStores = _commonServices.StoreService.GetAllStores(); + var allStores = _services.StoreService.GetAllStores(); model.AvailableStores = allStores.Select(s => s.ToModel()).ToList(); @@ -107,7 +107,7 @@ public ActionResult Index() public ActionResult List() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forumGroupsModel = _forumService.GetAllForumGroups(true) @@ -137,7 +137,7 @@ public ActionResult List() public ActionResult CreateForumGroup() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var model = new ForumGroupModel { DisplayOrder = 1 }; @@ -152,7 +152,7 @@ public ActionResult CreateForumGroup() [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult CreateForumGroup(ForumGroupModel model, bool continueEditing) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); if (ModelState.IsValid) @@ -171,7 +171,7 @@ public ActionResult CreateForumGroup(ForumGroupModel model, bool continueEditing _storeMappingService.SaveStoreMappings(forumGroup, model.SelectedStoreIds); - NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Added")); + NotifySuccess(_services.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Added")); return continueEditing ? RedirectToAction("EditForumGroup", new { forumGroup.Id }) : RedirectToAction("List"); } @@ -185,7 +185,7 @@ public ActionResult CreateForumGroup(ForumGroupModel model, bool continueEditing public ActionResult CreateForum() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var model = new ForumModel { DisplayOrder = 1 }; @@ -204,7 +204,7 @@ public ActionResult CreateForum() [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult CreateForum(ForumModel model, bool continueEditing) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); if (ModelState.IsValid) @@ -219,7 +219,7 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing) model.SeName = forum.ValidateSeName(model.SeName, forum.Name, true); _urlRecordService.SaveSlug(forum, model.SeName, 0); - NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Added")); + NotifySuccess(_services.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Added")); return continueEditing ? RedirectToAction("EditForum", new { forum.Id }) : RedirectToAction("List"); } @@ -239,7 +239,7 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing) public ActionResult EditForumGroup(int id) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forumGroup = _forumService.GetForumGroupById(id); @@ -263,7 +263,7 @@ public ActionResult EditForumGroup(int id) [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult EditForumGroup(ForumGroupModel model, bool continueEditing) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forumGroup = _forumService.GetForumGroupById(model.Id); @@ -284,7 +284,7 @@ public ActionResult EditForumGroup(ForumGroupModel model, bool continueEditing) _storeMappingService.SaveStoreMappings(forumGroup, model.SelectedStoreIds); - NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Updated")); return continueEditing ? RedirectToAction("EditForumGroup", forumGroup.Id) : RedirectToAction("List"); } @@ -298,7 +298,7 @@ public ActionResult EditForumGroup(ForumGroupModel model, bool continueEditing) public ActionResult EditForum(int id) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forum = _forumService.GetForumById(id); @@ -325,7 +325,7 @@ public ActionResult EditForum(int id) [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult EditForum(ForumModel model, bool continueEditing) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forum = _forumService.GetForumById(model.Id); @@ -344,7 +344,7 @@ public ActionResult EditForum(ForumModel model, bool continueEditing) UpdateLocales(model, forum); - NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Updated")); return continueEditing ? RedirectToAction("EditForum", forum.Id) : RedirectToAction("List"); } @@ -365,7 +365,7 @@ public ActionResult EditForum(ForumModel model, bool continueEditing) [HttpPost] public ActionResult DeleteForumGroup(int id) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forumGroup = _forumService.GetForumGroupById(id); @@ -374,14 +374,14 @@ public ActionResult DeleteForumGroup(int id) _forumService.DeleteForumGroup(forumGroup); - NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Deleted")); + NotifySuccess(_services.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Deleted")); return RedirectToAction("List"); } [HttpPost] public ActionResult DeleteForum(int id) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageForums)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums)) return AccessDeniedView(); var forum = _forumService.GetForumById(id); @@ -390,7 +390,7 @@ public ActionResult DeleteForum(int id) _forumService.DeleteForum(forum); - NotifySuccess(_commonServices.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Deleted")); + NotifySuccess(_services.Localization.GetResource("Admin.ContentManagement.Forums.Forum.Deleted")); return RedirectToAction("List"); } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs index d66429e90d..f0bc5d51cd 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs @@ -23,7 +23,7 @@ public partial class PaymentController : AdminControllerBase { #region Fields - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; private readonly IPaymentService _paymentService; private readonly PaymentSettings _paymentSettings; private readonly IPluginFinder _pluginFinder; @@ -38,7 +38,7 @@ public partial class PaymentController : AdminControllerBase #region Constructors public PaymentController( - ICommonServices commonServices, + ICommonServices services, IPaymentService paymentService, PaymentSettings paymentSettings, IPluginFinder pluginFinder, @@ -48,7 +48,7 @@ public PaymentController( IShippingService shippingService, ICountryService countryService) { - this._commonServices = commonServices; + this._services = services; this._paymentService = paymentService; this._paymentSettings = paymentSettings; this._pluginFinder = pluginFinder; @@ -111,7 +111,7 @@ private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, Payment public ActionResult Providers() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) return AccessDeniedView(); var paymentMethodsModel = new List(); @@ -125,7 +125,7 @@ public ActionResult Providers() model.SupportPartiallyRefund = instance.SupportPartiallyRefund; model.SupportRefund = instance.SupportRefund; model.SupportVoid = instance.SupportVoid; - model.RecurringPaymentType = instance.RecurringPaymentType.GetLocalizedEnum(_commonServices.Localization); + model.RecurringPaymentType = instance.RecurringPaymentType.GetLocalizedEnum(_services.Localization); paymentMethodsModel.Add(model); } @@ -134,14 +134,14 @@ public ActionResult Providers() public ActionResult ActivateProvider(string systemName, bool activate) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) return AccessDeniedView(); var pm = _paymentService.LoadPaymentMethodBySystemName(systemName); if (activate && !pm.Value.IsActive) { - NotifyWarning(_commonServices.Localization.GetResource("Admin.Configuration.Payment.CannotActivatePaymentMethod")); + NotifyWarning(_services.Localization.GetResource("Admin.Configuration.Payment.CannotActivatePaymentMethod")); } else { @@ -150,7 +150,7 @@ public ActionResult ActivateProvider(string systemName, bool activate) else _paymentSettings.ActivePaymentMethodSystemNames.Add(pm.Metadata.SystemName); - _commonServices.Settings.SaveSetting(_paymentSettings); + _services.Settings.SaveSetting(_paymentSettings); _pluginMediator.ActivateDependentWidgets(pm.Metadata, activate); } @@ -159,7 +159,7 @@ public ActionResult ActivateProvider(string systemName, bool activate) public ActionResult Edit(string systemName) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) return AccessDeniedView(); var provider = _paymentService.LoadPaymentMethodBySystemName(systemName); @@ -181,7 +181,7 @@ public ActionResult Edit(string systemName) [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult Edit(string systemName, bool continueEditing, PaymentMethodEditModel model) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManagePaymentMethods)) return AccessDeniedView(); var provider = _paymentService.LoadPaymentMethodBySystemName(systemName); @@ -217,7 +217,7 @@ public ActionResult Edit(string systemName, bool continueEditing, PaymentMethodE else _paymentService.UpdatePaymentMethod(paymentMethod); - NotifySuccess(_commonServices.Localization.GetResource("Admin.Common.DataEditSuccess")); + NotifySuccess(_services.Localization.GetResource("Admin.Common.DataEditSuccess")); return (continueEditing ? RedirectToAction("Edit", "Payment", new { systemName = systemName }) : diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs index bc697dc796..3511fb4d48 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs @@ -42,7 +42,7 @@ public partial class PluginController : AdminControllerBase private readonly WidgetSettings _widgetSettings; private readonly IProviderManager _providerManager; private readonly PluginMediator _pluginMediator; - private readonly ICommonServices _commonService; + private readonly ICommonServices _services; #endregion @@ -58,7 +58,7 @@ public PluginController(IPluginFinder pluginFinder, WidgetSettings widgetSettings, IProviderManager providerManager, PluginMediator pluginMediator, - ICommonServices commonService) + ICommonServices services) { this._pluginFinder = pluginFinder; this._permissionService = permissionService; @@ -70,7 +70,7 @@ public PluginController(IPluginFinder pluginFinder, this._widgetSettings = widgetSettings; this._providerManager = providerManager; this._pluginMediator = pluginMediator; - this._commonService = commonService; + this._services = services; } #endregion  @@ -86,19 +86,19 @@ protected PluginModel PreparePluginModel(PluginDescriptor pluginDescriptor, bool if (forList) { - model.FriendlyName = pluginDescriptor.GetLocalizedValue(_commonService.Localization, "FriendlyName"); - model.Description = pluginDescriptor.GetLocalizedValue(_commonService.Localization, "Description"); + model.FriendlyName = pluginDescriptor.GetLocalizedValue(_services.Localization, "FriendlyName"); + model.Description = pluginDescriptor.GetLocalizedValue(_services.Localization, "Description"); } //locales AddLocales(_languageService, model.Locales, (locale, languageId) => { - locale.FriendlyName = pluginDescriptor.GetLocalizedValue(_commonService.Localization, "FriendlyName", languageId, false); - locale.Description = pluginDescriptor.GetLocalizedValue(_commonService.Localization, "Description", languageId, false); + locale.FriendlyName = pluginDescriptor.GetLocalizedValue(_services.Localization, "FriendlyName", languageId, false); + locale.Description = pluginDescriptor.GetLocalizedValue(_services.Localization, "Description", languageId, false); }); // Stores - model.SelectedStoreIds = _commonService.Settings.GetSettingByKey(pluginDescriptor.GetSettingKey("LimitedToStores")).ToIntArray(); + model.SelectedStoreIds = _services.Settings.GetSettingByKey(pluginDescriptor.GetSettingKey("LimitedToStores")).ToIntArray(); // Icon model.IconUrl = _pluginMediator.GetIconUrl(pluginDescriptor); @@ -159,7 +159,7 @@ protected LocalPluginsModel PrepareLocalPluginsModel() IsLocalhost = LicenseChecker.IsLocalhost }; - model.AvailableStores = _commonService.StoreService + model.AvailableStores = _services.StoreService .GetAllStores() .Select(s => s.ToModel()) .ToList(); @@ -239,7 +239,7 @@ public ActionResult ExecuteTasks(IEnumerable pluginsToInstall, IEnumerab // restart application if (tasksCount > 0) { - _commonService.WebHelper.RestartAppDomain(aggressive: true); + _services.WebHelper.RestartAppDomain(aggressive: true); } } catch (Exception exc) @@ -256,7 +256,7 @@ public ActionResult ReloadList() return AccessDeniedView(); //restart application - _commonService.WebHelper.RestartAppDomain(); + _services.WebHelper.RestartAppDomain(); return RedirectToAction("List"); } @@ -271,7 +271,7 @@ public ActionResult ConfigurePlugin(string systemName) return HttpNotFound(); var model = PreparePluginModel(descriptor, false); - model.FriendlyName = descriptor.GetLocalizedValue(_commonService.Localization, "FriendlyName"); + model.FriendlyName = descriptor.GetLocalizedValue(_services.Localization, "FriendlyName"); return View(model); } @@ -343,7 +343,7 @@ public ActionResult LicensePlugin(string systemName, string licenseKey) if (!isLicensable) return Content(T("Admin.Common.ResourceNotFound")); - var stores = _commonService.StoreService.GetAllStores(); + var stores = _services.StoreService.GetAllStores(); var model = new LicensePluginModel { SystemName = systemName, @@ -353,7 +353,7 @@ public ActionResult LicensePlugin(string systemName, string licenseKey) // validate store url foreach (var store in stores) { - if (!_commonService.StoreService.IsStoreDataValid(store)) + if (!_services.StoreService.IsStoreDataValid(store)) { model.InvalidDataStoreId = store.Id; return View(model); @@ -511,11 +511,11 @@ public ActionResult SetSelectedStores(string pk /* SystemName */, string name, F var storeIds = (form["value[]"] ?? "0").Split(',').Select(x => x.ToInt()).Where(x => x > 0).ToList(); if (storeIds.Count > 0) { - _commonService.Settings.SetSetting(settingKey, string.Join(",", storeIds)); + _services.Settings.SetSetting(settingKey, string.Join(",", storeIds)); } else { - _commonService.Settings.DeleteSetting(settingKey); + _services.Settings.DeleteSetting(settingKey); } } catch (Exception ex) @@ -570,7 +570,7 @@ public ActionResult UpdateStringResources(string systemName, string returnUrl = } else { - _commonService.Localization.ImportPluginResourcesFromXml(pluginDescriptor, null, false); + _services.Localization.ImportPluginResourcesFromXml(pluginDescriptor, null, false); NotifySuccess(T("Admin.Configuration.Plugins.Resources.UpdateSuccess")); } @@ -594,11 +594,11 @@ public ActionResult UpdateAllStringResources() { if (plugin.Installed) { - _commonService.Localization.ImportPluginResourcesFromXml(plugin, null, false); + _services.Localization.ImportPluginResourcesFromXml(plugin, null, false); } else { - _commonService.Localization.DeleteLocaleStringResources(plugin.ResourceRootKey); + _services.Localization.DeleteLocaleStringResources(plugin.ResourceRootKey); } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs index 4dd03455e0..05ee6e911d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ShippingController.cs @@ -28,7 +28,7 @@ public partial class ShippingController : AdminControllerBase private readonly ILocalizedEntityService _localizedEntityService; private readonly ILanguageService _languageService; private readonly PluginMediator _pluginMediator; - private readonly ICommonServices _commonServices; + private readonly ICommonServices _services; private readonly ICustomerService _customerService; #endregion @@ -41,7 +41,7 @@ public ShippingController(IShippingService shippingService, ILocalizedEntityService localizedEntityService, ILanguageService languageService, PluginMediator pluginMediator, - ICommonServices commonServices, + ICommonServices services, ICustomerService customerService) { this._shippingService = shippingService; @@ -50,7 +50,7 @@ public ShippingController(IShippingService shippingService, this._localizedEntityService = localizedEntityService; this._languageService = languageService; this._pluginMediator = pluginMediator; - this._commonServices = commonServices; + this._services = services; this._customerService = customerService; } @@ -140,7 +140,7 @@ private void ApplyRestrictions(ShippingMethod shippingMethod, ShippingMethodMode public ActionResult Providers() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) return AccessDeniedView(); var shippingProvidersModel = new List(); @@ -157,14 +157,14 @@ public ActionResult Providers() public ActionResult ActivateProvider(string systemName, bool activate) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) return AccessDeniedView(); var srcm = _shippingService.LoadShippingRateComputationMethodBySystemName(systemName); if (activate && !srcm.Value.IsActive) { - NotifyWarning(_commonServices.Localization.GetResource("Admin.Configuration.Payment.CannotActivateShippingRateComputationMethod")); + NotifyWarning(_services.Localization.GetResource("Admin.Configuration.Payment.CannotActivateShippingRateComputationMethod")); } else { @@ -173,7 +173,7 @@ public ActionResult ActivateProvider(string systemName, bool activate) else _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Add(srcm.Metadata.SystemName); - _commonServices.Settings.SaveSetting(_shippingSettings); + _services.Settings.SaveSetting(_shippingSettings); _pluginMediator.ActivateDependentWidgets(srcm.Metadata, activate); } @@ -186,7 +186,7 @@ public ActionResult ActivateProvider(string systemName, bool activate) public ActionResult Methods() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) return AccessDeniedView(); var shippingMethodsModel = _shippingService.GetAllShippingMethods() @@ -204,7 +204,7 @@ public ActionResult Methods() [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult Methods(GridCommand command) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) return AccessDeniedView(); var shippingMethodsModel = _shippingService.GetAllShippingMethods() @@ -227,7 +227,7 @@ public ActionResult Methods(GridCommand command) public ActionResult CreateMethod() { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) return AccessDeniedView(); var model = new ShippingMethodModel(); @@ -241,7 +241,7 @@ public ActionResult CreateMethod() [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult CreateMethod(ShippingMethodModel model, bool continueEditing) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) return AccessDeniedView(); if (ModelState.IsValid) @@ -254,7 +254,7 @@ public ActionResult CreateMethod(ShippingMethodModel model, bool continueEditing //locales UpdateLocales(sm, model); - NotifySuccess(_commonServices.Localization.GetResource("Admin.Configuration.Shipping.Methods.Added")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Shipping.Methods.Added")); return continueEditing ? RedirectToAction("EditMethod", new { id = sm.Id }) : RedirectToAction("Methods"); } @@ -265,7 +265,7 @@ public ActionResult CreateMethod(ShippingMethodModel model, bool continueEditing public ActionResult EditMethod(int id) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) return AccessDeniedView(); var sm = _shippingService.GetShippingMethodById(id); @@ -288,7 +288,7 @@ public ActionResult EditMethod(int id) [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult EditMethod(ShippingMethodModel model, bool continueEditing) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) return AccessDeniedView(); var sm = _shippingService.GetShippingMethodById(model.Id); @@ -305,7 +305,7 @@ public ActionResult EditMethod(ShippingMethodModel model, bool continueEditing) //locales UpdateLocales(sm, model); - NotifySuccess(_commonServices.Localization.GetResource("Admin.Configuration.Shipping.Methods.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Shipping.Methods.Updated")); return continueEditing ? RedirectToAction("EditMethod", sm.Id) : RedirectToAction("Methods"); } @@ -317,7 +317,7 @@ public ActionResult EditMethod(ShippingMethodModel model, bool continueEditing) [HttpPost] public ActionResult DeleteMethod(int id) { - if (!_commonServices.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageShippingSettings)) return AccessDeniedView(); var sm = _shippingService.GetShippingMethodById(id); @@ -326,7 +326,7 @@ public ActionResult DeleteMethod(int id) _shippingService.DeleteShippingMethod(sm); - NotifySuccess(_commonServices.Localization.GetResource("Admin.Configuration.Shipping.Methods.Deleted")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Shipping.Methods.Deleted")); return RedirectToAction("Methods"); } diff --git a/src/Tests/SmartStore.Services.Tests/Catalog/PriceCalculationServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Catalog/PriceCalculationServiceTests.cs index c22aa2c35b..cbcd650019 100644 --- a/src/Tests/SmartStore.Services.Tests/Catalog/PriceCalculationServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Catalog/PriceCalculationServiceTests.cs @@ -28,7 +28,7 @@ public class PriceCalculationServiceTests : ServiceTest IProductAttributeService _productAttributeService; IPriceCalculationService _priceCalcService; IDownloadService _downloadService; - ICommonServices _commonServices; + ICommonServices _services; HttpRequestBase _httpRequestBase; ITaxService _taxService; ShoppingCartSettings _shoppingCartSettings; @@ -52,8 +52,8 @@ public class PriceCalculationServiceTests : ServiceTest _productAttributeService = MockRepository.GenerateMock(); _downloadService = MockRepository.GenerateMock(); - _commonServices = MockRepository.GenerateMock(); - _commonServices.Expect(x => x.StoreContext).Return(_storeContext); + _services = MockRepository.GenerateMock(); + _services.Expect(x => x.StoreContext).Return(_storeContext); _httpRequestBase = MockRepository.GenerateMock(); _taxService = MockRepository.GenerateMock(); @@ -61,7 +61,7 @@ public class PriceCalculationServiceTests : ServiceTest _catalogSettings = new CatalogSettings(); _priceCalcService = new PriceCalculationService(_discountService, _categoryService, _productAttributeParser, _productService, _shoppingCartSettings, _catalogSettings, - _productAttributeService, _downloadService, _commonServices, _httpRequestBase, _taxService); + _productAttributeService, _downloadService, _services, _httpRequestBase, _taxService); } [Test] diff --git a/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs b/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs index 19f85f9865..dcdd328196 100644 --- a/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs +++ b/src/Tests/SmartStore.Services.Tests/ExportImport/ExportManagerTests.cs @@ -35,7 +35,7 @@ public class ExportManagerTests : ServiceTest IExportManager _exportManager; ILanguageService _languageService; MediaSettings _mediaSettings; - ICommonServices _commonServices; + ICommonServices _services; IStoreMappingService _storeMapping; [SetUp] @@ -49,11 +49,11 @@ public class ExportManagerTests : ServiceTest _newsLetterSubscriptionService = MockRepository.GenerateMock(); _languageService = MockRepository.GenerateMock(); _mediaSettings = MockRepository.GenerateMock(); - _commonServices = MockRepository.GenerateMock(); + _services = MockRepository.GenerateMock(); _storeMapping = MockRepository.GenerateMock(); _exportManager = new ExportManager(_categoryService, _manufacturerService, _productService, _productTemplateService, _pictureService, - _newsLetterSubscriptionService, _languageService, _mediaSettings, _commonServices, _storeMapping); + _newsLetterSubscriptionService, _languageService, _mediaSettings, _services, _storeMapping); } //[Test] diff --git a/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs index aee2f5fb64..10f30b2fe8 100644 --- a/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Orders/OrderProcessingServiceTests.cs @@ -88,7 +88,7 @@ public class OrderProcessingServiceTests : ServiceTest IAffiliateService _affiliateService; ISettingService _settingService; IDownloadService _downloadService; - ICommonServices _commonServices; + ICommonServices _services; HttpRequestBase _httpRequestBase; IGeoCountryLookup _geoCountryLookup; @@ -155,7 +155,7 @@ public class OrderProcessingServiceTests : ServiceTest _addressService = MockRepository.GenerateMock(); _addressService.Expect(x => x.GetAddressById(_taxSettings.DefaultTaxAddressId)).Return(new Address() { Id = _taxSettings.DefaultTaxAddressId }); _downloadService = MockRepository.GenerateMock(); - _commonServices = MockRepository.GenerateMock(); + _services = MockRepository.GenerateMock(); _httpRequestBase = MockRepository.GenerateMock(); _geoCountryLookup = MockRepository.GenerateMock(); @@ -164,7 +164,7 @@ public class OrderProcessingServiceTests : ServiceTest _rewardPointsSettings = new RewardPointsSettings(); _priceCalcService = new PriceCalculationService(_discountService, _categoryService, _productAttributeParser, _productService, _shoppingCartSettings, _catalogSettings, - _productAttributeService, _downloadService, _commonServices, _httpRequestBase, _taxService); + _productAttributeService, _downloadService, _services, _httpRequestBase, _taxService); _orderTotalCalcService = new OrderTotalCalculationService(_workContext, _storeContext, _priceCalcService, _taxService, _shippingService, _providerManager, diff --git a/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs index a422832c9a..21affac7fe 100644 --- a/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Orders/OrderTotalCalculationServiceTests.cs @@ -62,7 +62,7 @@ public class OrderTotalCalculationServiceTests : ServiceTest IEventPublisher _eventPublisher; ISettingService _settingService; IDownloadService _downloadService; - ICommonServices _commonServices; + ICommonServices _services; HttpRequestBase _httpRequestBase; IGeoCountryLookup _geoCountryLookup; Store _store; @@ -129,7 +129,7 @@ public class OrderTotalCalculationServiceTests : ServiceTest _addressService = MockRepository.GenerateMock(); _addressService.Expect(x => x.GetAddressById(_taxSettings.DefaultTaxAddressId)).Return(new Address { Id = _taxSettings.DefaultTaxAddressId }); _downloadService = MockRepository.GenerateMock(); - _commonServices = MockRepository.GenerateMock(); + _services = MockRepository.GenerateMock(); _httpRequestBase = MockRepository.GenerateMock(); _geoCountryLookup = MockRepository.GenerateMock(); @@ -138,7 +138,7 @@ public class OrderTotalCalculationServiceTests : ServiceTest _rewardPointsSettings = new RewardPointsSettings(); _priceCalcService = new PriceCalculationService(_discountService, _categoryService, _productAttributeParser, _productService, _shoppingCartSettings, _catalogSettings, - _productAttributeService, _downloadService, _commonServices, _httpRequestBase, _taxService); + _productAttributeService, _downloadService, _services, _httpRequestBase, _taxService); _orderTotalCalcService = new OrderTotalCalculationService(_workContext, _storeContext, _priceCalcService, _taxService, _shippingService, _providerManager, diff --git a/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs index c323239484..2a4a4499af 100644 --- a/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Payments/PaymentServiceTests.cs @@ -22,7 +22,7 @@ public class PaymentServiceTests : ServiceTest ShoppingCartSettings _shoppingCartSettings; IPaymentService _paymentService; ICurrencyService _currencyService; - ICommonServices _commonServices; + ICommonServices _services; IOrderTotalCalculationService _orderTotalCalculationService; [SetUp] @@ -37,14 +37,14 @@ public class PaymentServiceTests : ServiceTest _shoppingCartSettings = new ShoppingCartSettings(); _paymentMethodRepository = MockRepository.GenerateMock>(); _currencyService = MockRepository.GenerateMock(); - _commonServices = MockRepository.GenerateMock(); + _services = MockRepository.GenerateMock(); _orderTotalCalculationService = MockRepository.GenerateMock(); var localizationService = MockRepository.GenerateMock(); localizationService.Expect(ls => ls.GetResource(null)).IgnoreArguments().Return("NotSupported").Repeat.Any(); _paymentService = new PaymentService(_paymentMethodRepository, _paymentSettings, pluginFinder, _shoppingCartSettings, - this.ProviderManager, _currencyService, _commonServices, _orderTotalCalculationService); + this.ProviderManager, _currencyService, _services, _orderTotalCalculationService); } [Test] From acc3f2f7ef8fa51e70ea40d62c5385a5d08ab371 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 25 Jun 2015 17:55:17 +0200 Subject: [PATCH 0184/1256] Resolves #721 Message Queue: implement "Delete all" --- changelog.md | 3 + ...06211043073_PaymentShippingRestrictions.cs | 8 + .../Controllers/QueuedEmailController.cs | 27 ++++ .../Views/QueuedEmail/List.cshtml | 142 +++++++++--------- 4 files changed, 112 insertions(+), 68 deletions(-) diff --git a/changelog.md b/changelog.md index 6bc68c22a9..21fa3d453a 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,9 @@ * #718 ShopConnector: Import option for "Published" and "Disable buy\wishlist button" * #702 Facebook and Twitter external authentication suitable for multi-stores +### Improvements +* #721 Message Queue: implement "Delete all" + ## SmartStore.NET 2.2.2 diff --git a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs index 2199b00670..a419e7a9c7 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs @@ -57,6 +57,14 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Restrictions", "Einschrnkungen"); + builder.AddOrUpdate("Admin.Common.DeleteAll", + "Delete all", + "Alle lschen"); + + builder.AddOrUpdate("Admin.Common.RecordsDeleted", + "{0} records were deleted.", + "Es wurden {0} Datenstze gelscht."); + builder.AddOrUpdate("Common.RequestProcessingFailed", "The request could not be processed.
Controller: {0}, Action: {1}, Reason: {2}.", "Die Anfrage konnte nicht ausgefhrt werden.
Controller: {0}, Action: {1}, Grund: {2}."); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs index 685ccf12ae..b152c898fd 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs @@ -223,5 +223,32 @@ public ActionResult DeleteSelected(ICollection selectedIds) return Json(new { Result = true }); } + + [HttpPost, ActionName("List"), FormValueRequired("delete-all")] + public ActionResult DeleteAll() + { + if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageQueue)) + return AccessDeniedView(); + + int count = 0; + + for (int i = 0; i < 9999999; ++i) + { + var queuedEmails = _queuedEmailService.SearchEmails(null, null, null, null, false, int.MaxValue, false, i, 100, null); + + foreach (var email in queuedEmails) + { + _queuedEmailService.DeleteQueuedEmail(email); + ++count; + } + + if (!queuedEmails.HasNextPage) + break; + } + + NotifySuccess(T("Admin.Common.RecordsDeleted", count)); + + return RedirectToAction("List"); + } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml index 6da45a0a2a..d4497b7a7a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml @@ -12,51 +12,56 @@ @T("Admin.System.QueuedEmails")
- + +
- - - - - - - - - - - - - - - - - - - - - + +
- @Html.SmartLabelFor(model => model.SearchStartDate) - - @Html.EditorFor(model => model.SearchStartDate) -
- @Html.SmartLabelFor(model => model.SearchEndDate) - - @Html.EditorFor(model => Model.SearchEndDate) -
- @Html.SmartLabelFor(model => model.SearchFromEmail) - - @Html.EditorFor(model => Model.SearchFromEmail) -
- @Html.SmartLabelFor(model => model.SearchToEmail) - - @Html.EditorFor(model => Model.SearchToEmail) -
- @Html.SmartLabelFor(model => model.SearchLoadNotSent) - - @Html.EditorFor(model => Model.SearchLoadNotSent) -
+ + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + - - - + + + - -
+ @Html.SmartLabelFor(model => model.SearchStartDate) + + @Html.EditorFor(model => model.SearchStartDate) +
+ @Html.SmartLabelFor(model => model.SearchEndDate) + + @Html.EditorFor(model => Model.SearchEndDate) +
+ @Html.SmartLabelFor(model => model.SearchFromEmail) + + @Html.EditorFor(model => Model.SearchFromEmail) +
+ @Html.SmartLabelFor(model => model.SearchToEmail) + + @Html.EditorFor(model => Model.SearchToEmail) +
+ @Html.SmartLabelFor(model => model.SearchLoadNotSent) + + @Html.EditorFor(model => Model.SearchLoadNotSent) +
@Html.SmartLabelFor(model => model.SearchSendManually) @@ -70,36 +75,37 @@ })
- @Html.SmartLabelFor(model => model.SearchMaxSentTries) - - @Html.EditorFor(model => Model.SearchMaxSentTries) -
- @Html.SmartLabelFor(model => model.GoDirectlyToNumber) - - @Html.EditorFor(model => Model.GoDirectlyToNumber) -
+ @Html.SmartLabelFor(model => model.SearchMaxSentTries) + + @Html.EditorFor(model => Model.SearchMaxSentTries) +
+ @Html.SmartLabelFor(model => model.GoDirectlyToNumber) + + @Html.EditorFor(model => Model.GoDirectlyToNumber) + -
+
  - -
-

-

+ +
+ +

+ + + + + + + + + + + + +
From c4a816b929a92561b082c99c02618e1c3e855edf Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 25 Jun 2015 19:55:49 +0200 Subject: [PATCH 0185/1256] (Perf) implemented static cache for active url slugs, which are all loaded on app startup now. Boosts app startup perf up to 30%. To disable this feature, set 'SeoSettings.LoadAllUrlAliasesOnStartup' to false (true by default). --- changelog.md | 1 + .../SmartStore.Core/Domain/Seo/SeoSettings.cs | 6 ++ ...06211043073_PaymentShippingRestrictions.cs | 1 + .../Seo/UrlRecordService.cs | 98 +++++++++++++------ .../Controllers/CatalogController.cs | 6 +- .../Installation/InstallDataSeeder.cs | 4 +- 6 files changed, 83 insertions(+), 33 deletions(-) diff --git a/changelog.md b/changelog.md index 21fa3d453a..96936ed74e 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,7 @@ * #702 Facebook and Twitter external authentication suitable for multi-stores ### Improvements +* (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%. * #721 Message Queue: implement "Delete all" diff --git a/src/Libraries/SmartStore.Core/Domain/Seo/SeoSettings.cs b/src/Libraries/SmartStore.Core/Domain/Seo/SeoSettings.cs index 6dacb605a6..2479662974 100644 --- a/src/Libraries/SmartStore.Core/Domain/Seo/SeoSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Seo/SeoSettings.cs @@ -17,6 +17,7 @@ public SeoSettings() CanonicalHostNameRule = Seo.CanonicalHostNameRule.NoRule; ReservedUrlRecordSlugs = new List() { "admin", "install", "recentlyviewedproducts", "newproducts", "compareproducts", "clearcomparelist", "setproductreviewhelpfulness", "login", "register", "logout", "cart", "wishlist", "emailwishlist", "checkout", "contactus", "passwordrecovery", "subscribenewsletter", "blog", "boards", "inboxupdate", "sentupdate", "news", "sitemap", "sitemapseo", "search", "config", "api", "odata" }; ExtraRobotsDisallows = new List(); + LoadAllUrlAliasesOnStartup = true; } public string PageTitleSeparator { get; set; } @@ -37,5 +38,10 @@ public SeoSettings() public List ReservedUrlRecordSlugs { get; set; } public List ExtraRobotsDisallows { get; set; } + + /// + /// A value indicating whether to load all URL records and active slugs on application startup + /// + public bool LoadAllUrlAliasesOnStartup { get; set; } } } \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs index a419e7a9c7..1f5f6223e8 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506211043073_PaymentShippingRestrictions.cs @@ -48,6 +48,7 @@ public void Seed(SmartObjectContext context) context.MigrateSettings(x => { x.Add("localizationsettings.loadalllocalizedpropertiesonstartup", true); + x.Add("seosettings.loadallurlaliasesonstartup", true); }); } diff --git a/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs b/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs index b49a0044e1..a3bc57d68e 100644 --- a/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs +++ b/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs @@ -16,8 +16,11 @@ public partial class UrlRecordService : IUrlRecordService { #region Constants - private const string URLRECORD_ACTIVE_BY_ID_NAME_LANGUAGE_KEY = "SmartStore.urlrecord.active.id-name-language-{0}-{1}-{2}"; - private const string URLRECORD_PATTERN_KEY = "SmartStore.urlrecord."; + // {0} = id, {1} = name, {2} = language + private const string URLRECORD_KEY = "SmartStore.urlrecord.{0}-{1}-{2}"; + private const string URLRECORD_ALL_ACTIVESLUGS_KEY = "SmartStore.urlrecord.all-active-slugs"; + private const string URLRECORD_ALL_KEY = "SmartStore.urlrecord.all"; + private const string URLRECORD_PATTERN_KEY = "SmartStore.urlrecord."; #endregion @@ -25,15 +28,17 @@ public partial class UrlRecordService : IUrlRecordService private readonly IRepository _urlRecordRepository; private readonly ICacheManager _cacheManager; + private readonly SeoSettings _seoSettings; #endregion #region Ctor - public UrlRecordService(ICacheManager cacheManager, IRepository urlRecordRepository) + public UrlRecordService(ICacheManager cacheManager, IRepository urlRecordRepository, SeoSettings seoSettings) { this._cacheManager = cacheManager; this._urlRecordRepository = urlRecordRepository; + this._seoSettings = seoSettings; } #endregion @@ -81,18 +86,6 @@ public virtual void UpdateUrlRecord(UrlRecord urlRecord) _cacheManager.RemoveByPattern(URLRECORD_PATTERN_KEY); } - public virtual UrlRecord GetBySlug(string slug) - { - if (String.IsNullOrEmpty(slug)) - return null; - - var query = from ur in _urlRecordRepository.Table - where ur.Slug == slug - select ur; - var urlRecord = query.FirstOrDefault(); - return urlRecord; - } - public virtual IPagedList GetAllUrlRecords(string slug, int pageIndex, int pageSize) { var query = _urlRecordRepository.Table; @@ -121,21 +114,63 @@ public virtual IList GetUrlRecordsFor(string entityName, int entityId return query.ToList(); } + public virtual UrlRecord GetBySlug(string slug) + { + // INFO: (mc) Caching unnecessary here. This is not a 'bottleneck' function. + if (String.IsNullOrEmpty(slug)) + return null; + + var query = from ur in _urlRecordRepository.Table + where ur.Slug == slug + select ur; + var urlRecord = query.FirstOrDefault(); + return urlRecord; + } + public virtual string GetActiveSlug(int entityId, string entityName, int languageId) - { - string key = string.Format(URLRECORD_ACTIVE_BY_ID_NAME_LANGUAGE_KEY, entityId, entityName, languageId); - return _cacheManager.Get(key, () => - { - var query = from ur in _urlRecordRepository.Table - where ur.EntityId == entityId && - ur.EntityName == entityName && - ur.LanguageId == languageId && - ur.IsActive - orderby ur.Id descending - select ur.Slug; - var slug = query.FirstOrDefault(); - return slug ?? ""; - }); + { + string slug = null; + + if (_seoSettings.LoadAllUrlAliasesOnStartup) + { + var allActiveSlugs = _cacheManager.Get(URLRECORD_ALL_ACTIVESLUGS_KEY, () => + { + var query = from x in _urlRecordRepository.TableUntracked + where x.IsActive + orderby x.Id descending + select x; + + var result = query.ToDictionary( + x => GenerateKey(x.EntityId, x.EntityName, x.LanguageId), // Key + x => x.Slug, // Value + StringComparer.OrdinalIgnoreCase); + + return result; + }); + + var key = GenerateKey(entityId, entityName, languageId); + if (!allActiveSlugs.TryGetValue(key, out slug)) + { + return string.Empty; + } + } + else + { + string cacheKey = string.Format(URLRECORD_KEY, entityId, entityName, languageId); + slug = _cacheManager.Get(cacheKey, () => + { + var query = from ur in _urlRecordRepository.Table + where ur.EntityId == entityId && + ur.EntityName == entityName && + ur.LanguageId == languageId && + ur.IsActive + orderby ur.Id descending + select ur.Slug; + return query.FirstOrDefault() ?? string.Empty; + }); + } + + return slug; } public virtual UrlRecord SaveSlug(T entity, string slug, int languageId) where T : BaseEntity, ISlugSupported @@ -265,6 +300,11 @@ public virtual UrlRecord SaveSlug(T entity, Expression> nameP return SaveSlug(entity, existingSeName, 0); } + private string GenerateKey(int entityId, string entityName, int languageId) + { + return "{0}.{1}.{2}".FormatInvariant(entityId, entityName, languageId); + } + #endregion } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs index ab0236bc10..7c210cee70 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs @@ -181,13 +181,13 @@ public ActionResult Category(int categoryId, CatalogPagingFilteringModel command var customerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); - //subcategories + // subcategories model.SubCategories = _categoryService .GetAllCategoriesByParentCategoryId(categoryId) .Select(x => { var subCatName = x.GetLocalized(y => y.Name); - var subCatModel = new CategoryModel.SubCategoryModel() + var subCatModel = new CategoryModel.SubCategoryModel { Id = x.Id, Name = subCatName, @@ -610,7 +610,7 @@ public ActionResult ManufacturerNavigation(int currentManufacturerId) foreach (var manufacturer in manufacturers.Take(_catalogSettings.ManufacturersBlockItemsToDisplay)) { - var modelMan = new ManufacturerBriefInfoModel() + var modelMan = new ManufacturerBriefInfoModel { Id = manufacturer.Id, Name = manufacturer.GetLocalized(x => x.Name), diff --git a/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs b/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs index 60107decb1..597a33ef39 100644 --- a/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs +++ b/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs @@ -614,9 +614,11 @@ private void SetModified(TEntity entity) private string ValidateSeName(TEntity entity, string name) where TEntity : BaseEntity, ISlugSupported { + var seoSettings = new SeoSettings { LoadAllUrlAliasesOnStartup = false }; + if (_urlRecordService == null) { - _urlRecordService = new UrlRecordService(NullCache.Instance, new EfRepository(_ctx) { AutoCommitEnabled = false }); + _urlRecordService = new UrlRecordService(NullCache.Instance, new EfRepository(_ctx) { AutoCommitEnabled = false }, seoSettings); } return entity.ValidateSeName("", name, true, _urlRecordService, new SeoSettings()); From 468b0f9e034f86ac7e32a009d35005e3637ce788 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 25 Jun 2015 21:12:45 +0200 Subject: [PATCH 0186/1256] Web.config cleanup --- src/Presentation/SmartStore.Web/Web.Release.config | 3 +-- src/Presentation/SmartStore.Web/Web.config | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Web.Release.config b/src/Presentation/SmartStore.Web/Web.Release.config index f4b9a73aaa..49f9b30567 100644 --- a/src/Presentation/SmartStore.Web/Web.Release.config +++ b/src/Presentation/SmartStore.Web/Web.Release.config @@ -14,8 +14,7 @@ - - + diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config index 32291a4cfb..cf1a8fedd3 100644 --- a/src/Presentation/SmartStore.Web/Web.config +++ b/src/Presentation/SmartStore.Web/Web.config @@ -86,7 +86,7 @@ - + From 3bc8a235a23a162ef82ccb15a9a9a5aeddd242b6 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 25 Jun 2015 23:32:43 +0200 Subject: [PATCH 0187/1256] * Added method IEmailAccountService.GetDefaultEmailAccount() * (Perf) added request caching to EmailAccountService --- .../SmartStore.Core/Email/EmailMessage.cs | 5 -- .../Messages/EmailAccountService.cs | 87 ++++++++++--------- .../Messages/IEmailAccountService.cs | 6 ++ .../Messages/MessageTokenProvider.cs | 6 +- .../Messages/QueuedEmailService.cs | 6 +- .../Messages/WorkflowMessageService.cs | 4 +- .../Seo/UrlRecordService.cs | 1 - .../Controllers/CampaignController.cs | 6 +- .../Controllers/CustomerController.cs | 6 +- .../Controllers/HomeController.cs | 4 +- 10 files changed, 64 insertions(+), 67 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Email/EmailMessage.cs b/src/Libraries/SmartStore.Core/Email/EmailMessage.cs index 58a8508c07..426f83e100 100644 --- a/src/Libraries/SmartStore.Core/Email/EmailMessage.cs +++ b/src/Libraries/SmartStore.Core/Email/EmailMessage.cs @@ -78,11 +78,6 @@ public EmailMessage(EmailAddress to, string subject, string body, EmailAddress f public NameValueCollection Headers { get; private set; } - public void AddAttachment(Attachment attachment) - { - this.Attachments.Add(attachment); - } - public async void BodyFromFile(string filePathOrUrl) { StreamReader sr = null; diff --git a/src/Libraries/SmartStore.Services/Messages/EmailAccountService.cs b/src/Libraries/SmartStore.Services/Messages/EmailAccountService.cs index ebf71742dc..639c0391cb 100644 --- a/src/Libraries/SmartStore.Services/Messages/EmailAccountService.cs +++ b/src/Libraries/SmartStore.Services/Messages/EmailAccountService.cs @@ -2,36 +2,37 @@ using System.Collections.Generic; using System.Linq; using SmartStore.Core; +using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Messages; using SmartStore.Core.Events; namespace SmartStore.Services.Messages { - public partial class EmailAccountService:IEmailAccountService + public partial class EmailAccountService : IEmailAccountService { - private readonly IRepository _emailAccountRepository; + private const string EMAILACCOUNT_BY_ID_KEY = "SmartStore.emailaccount.id-{0}"; + private const string EMAILACCOUNT_PATTERN_KEY = "SmartStore.emailaccount."; + + private readonly IRepository _emailAccountRepository; private readonly EmailAccountSettings _emailAccountSettings; private readonly IEventPublisher _eventPublisher; + private readonly ICacheManager _cacheManager; - /// - /// Ctor - /// - /// Email account repository - /// - /// Event published - public EmailAccountService(IRepository emailAccountRepository, - EmailAccountSettings emailAccountSettings, IEventPublisher eventPublisher) + private EmailAccount _defaultEmailAccount; + + public EmailAccountService( + IRepository emailAccountRepository, + EmailAccountSettings emailAccountSettings, + IEventPublisher eventPublisher, + ICacheManager cacheManager /* request */) { - _emailAccountRepository = emailAccountRepository; - _emailAccountSettings = emailAccountSettings; - _eventPublisher = eventPublisher; + this._emailAccountRepository = emailAccountRepository; + this._emailAccountSettings = emailAccountSettings; + this._eventPublisher = eventPublisher; + this._cacheManager = cacheManager; } - /// - /// Inserts an email account - /// - /// Email account public virtual void InsertEmailAccount(EmailAccount emailAccount) { if (emailAccount == null) @@ -57,14 +58,12 @@ public virtual void InsertEmailAccount(EmailAccount emailAccount) _emailAccountRepository.Insert(emailAccount); - //event notification + _cacheManager.RemoveByPattern(EMAILACCOUNT_PATTERN_KEY); + _defaultEmailAccount = null; + _eventPublisher.EntityInserted(emailAccount); } - /// - /// Updates an email account - /// - /// Email account public virtual void UpdateEmailAccount(EmailAccount emailAccount) { if (emailAccount == null) @@ -90,14 +89,12 @@ public virtual void UpdateEmailAccount(EmailAccount emailAccount) _emailAccountRepository.Update(emailAccount); - //event notification + _cacheManager.RemoveByPattern(EMAILACCOUNT_PATTERN_KEY); + _defaultEmailAccount = null; + _eventPublisher.EntityUpdated(emailAccount); } - /// - /// Deletes an email account - /// - /// Email account public virtual void DeleteEmailAccount(EmailAccount emailAccount) { if (emailAccount == null) @@ -108,28 +105,38 @@ public virtual void DeleteEmailAccount(EmailAccount emailAccount) _emailAccountRepository.Delete(emailAccount); - //event notification + _cacheManager.RemoveByPattern(EMAILACCOUNT_PATTERN_KEY); + _defaultEmailAccount = null; + _eventPublisher.EntityDeleted(emailAccount); } - /// - /// Gets an email account by identifier - /// - /// The email account identifier - /// Email account public virtual EmailAccount GetEmailAccountById(int emailAccountId) { if (emailAccountId == 0) return null; - - var emailAccount = _emailAccountRepository.GetById(emailAccountId); - return emailAccount; + + string key = string.Format(EMAILACCOUNT_BY_ID_KEY, emailAccountId); + return _cacheManager.Get(key, () => + { + return _emailAccountRepository.GetById(emailAccountId); + }); } - /// - /// Gets all email accounts - /// - /// Email accounts list + public virtual EmailAccount GetDefaultEmailAccount() + { + if (_defaultEmailAccount == null) + { + _defaultEmailAccount = GetEmailAccountById(_emailAccountSettings.DefaultEmailAccountId); + if (_defaultEmailAccount == null) + { + _defaultEmailAccount = GetAllEmailAccounts().FirstOrDefault(); + } + } + + return _defaultEmailAccount; + } + public virtual IList GetAllEmailAccounts() { var query = from ea in _emailAccountRepository.Table diff --git a/src/Libraries/SmartStore.Services/Messages/IEmailAccountService.cs b/src/Libraries/SmartStore.Services/Messages/IEmailAccountService.cs index 5f03d721bd..6b3df6f6eb 100644 --- a/src/Libraries/SmartStore.Services/Messages/IEmailAccountService.cs +++ b/src/Libraries/SmartStore.Services/Messages/IEmailAccountService.cs @@ -30,6 +30,12 @@ public partial interface IEmailAccountService /// Email account EmailAccount GetEmailAccountById(int emailAccountId); + /// + /// Gets the default email account + /// + /// Emil account + EmailAccount GetDefaultEmailAccount(); + /// /// Gets all email accounts /// diff --git a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs index e2f7ad3cac..ed4c1ea719 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs @@ -669,15 +669,11 @@ public virtual void AddStoreTokens(IList tokens, Store store) { tokens.Add(new Token("Store.Name", store.Name)); tokens.Add(new Token("Store.URL", store.Url, true)); - var defaultEmailAccount = _emailAccountService.GetEmailAccountById(_emailAccountSettings.DefaultEmailAccountId); - if (defaultEmailAccount == null) - defaultEmailAccount = _emailAccountService.GetAllEmailAccounts().FirstOrDefault(); + var defaultEmailAccount = _emailAccountService.GetDefaultEmailAccount(); tokens.Add(new Token("Store.SupplierIdentification", GetSupplierIdentification(), true)); tokens.Add(new Token("Store.Email", defaultEmailAccount.Email)); } - //codehint: sm-add begin - public virtual void AddCompanyTokens(IList tokens) { tokens.Add(new Token("Company.CompanyName", _companyInfoSettings.CompanyName)); diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs index 4dc57c2c83..5e72bca45a 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs @@ -108,13 +108,13 @@ public virtual IList GetQueuedEmailsByIds(int[] queuedEmailIds) if (queuedEmailIds == null || queuedEmailIds.Length == 0) return new List(); - var query = from qe in _queuedEmailRepository.Table + var query = from qe in _queuedEmailRepository.Table.Expand(x => x.EmailAccount) where queuedEmailIds.Contains(qe.Id) select qe; var queuedEmails = query.ToList(); - //sort by passed identifiers + // sort by passed identifiers var sortedQueuedEmails = new List(); foreach (int id in queuedEmailIds) @@ -149,7 +149,7 @@ public virtual IPagedList SearchEmails(string fromEmail, fromEmail = (fromEmail ?? String.Empty).Trim(); toEmail = (toEmail ?? String.Empty).Trim(); - var query = _queuedEmailRepository.Table; + var query = _queuedEmailRepository.Table.Expand(x => x.EmailAccount); if (!String.IsNullOrEmpty(fromEmail)) query = query.Where(qe => qe.From.Contains(fromEmail)); diff --git a/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs b/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs index bbad203299..b194690096 100644 --- a/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs +++ b/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs @@ -135,9 +135,7 @@ protected EmailAccount GetEmailAccountOfMessageTemplate(MessageTemplate messageT var emailAccounId = messageTemplate.GetLocalized(mt => mt.EmailAccountId, languageId); var emailAccount = _emailAccountService.GetEmailAccountById(emailAccounId); if (emailAccount == null) - emailAccount = _emailAccountService.GetEmailAccountById(_emailAccountSettings.DefaultEmailAccountId); - if (emailAccount == null) - emailAccount = _emailAccountService.GetAllEmailAccounts().FirstOrDefault(); + emailAccount = _emailAccountService.GetDefaultEmailAccount(); return emailAccount; } diff --git a/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs b/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs index a3bc57d68e..dc5950affa 100644 --- a/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs +++ b/src/Libraries/SmartStore.Services/Seo/UrlRecordService.cs @@ -19,7 +19,6 @@ public partial class UrlRecordService : IUrlRecordService // {0} = id, {1} = name, {2} = language private const string URLRECORD_KEY = "SmartStore.urlrecord.{0}-{1}-{2}"; private const string URLRECORD_ALL_ACTIVESLUGS_KEY = "SmartStore.urlrecord.all-active-slugs"; - private const string URLRECORD_ALL_KEY = "SmartStore.urlrecord.all"; private const string URLRECORD_PATTERN_KEY = "SmartStore.urlrecord."; #endregion diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CampaignController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CampaignController.cs index ade2d40e53..ae1a1ff375 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CampaignController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CampaignController.cs @@ -200,14 +200,14 @@ public ActionResult SendTestEmail(CampaignModel model) try { - var emailAccount = _emailAccountService.GetEmailAccountById(_emailAccountSettings.DefaultEmailAccountId); + var emailAccount = _emailAccountService.GetDefaultEmailAccount(); if (emailAccount == null) throw new SmartException("Email account could not be loaded"); var subscription = _newsLetterSubscriptionService.GetNewsLetterSubscriptionByEmail(model.TestEmail); if (subscription != null) { - //there's a subscription. let's use it + // there's a subscription. let's use it var subscriptions = new List(); subscriptions.Add(subscription); _campaignService.SendCampaign(campaign, emailAccount, subscriptions); @@ -245,7 +245,7 @@ public ActionResult SendMassEmail(CampaignModel model) try { - var emailAccount = _emailAccountService.GetEmailAccountById(_emailAccountSettings.DefaultEmailAccountId); + var emailAccount = _emailAccountService.GetDefaultEmailAccount(); if (emailAccount == null) throw new SmartException("Email account could not be loaded"); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs index 0a8e0c6858..90194daeb2 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs @@ -1035,13 +1035,11 @@ public ActionResult SendEmail(CustomerModel model) if (String.IsNullOrWhiteSpace(model.SendEmail.Body)) throw new SmartException("Email body is empty"); - var emailAccount = _emailAccountService.GetEmailAccountById(_emailAccountSettings.DefaultEmailAccountId); - if (emailAccount == null) - emailAccount = _emailAccountService.GetAllEmailAccounts().FirstOrDefault(); + var emailAccount = _emailAccountService.GetDefaultEmailAccount(); if (emailAccount == null) throw new SmartException("Email account can't be loaded"); - var email = new QueuedEmail() + var email = new QueuedEmail { EmailAccountId = emailAccount.Id, FromName = emailAccount.DisplayName, diff --git a/src/Presentation/SmartStore.Web/Controllers/HomeController.cs b/src/Presentation/SmartStore.Web/Controllers/HomeController.cs index cd16a058b6..8c1f8fc125 100644 --- a/src/Presentation/SmartStore.Web/Controllers/HomeController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/HomeController.cs @@ -141,9 +141,7 @@ public ActionResult ContactUsSend(ContactUsModel model, bool captchaValid) string fullName = model.FullName; string subject = T("ContactUs.EmailSubject", _services.StoreContext.CurrentStore.Name); - var emailAccount = _emailAccountService.Value.GetEmailAccountById(EngineContext.Current.Resolve().DefaultEmailAccountId); - if (emailAccount == null) - emailAccount = _emailAccountService.Value.GetAllEmailAccounts().FirstOrDefault(); + var emailAccount = _emailAccountService.Value.GetDefaultEmailAccount(); string from = null; string fromName = null; From 9f27a88307447834362d3ed02029bdaa9e921f2e Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 26 Jun 2015 12:38:49 +0200 Subject: [PATCH 0188/1256] IsTaxEcempt was never applied --- src/Libraries/SmartStore.Services/Tax/TaxService.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Libraries/SmartStore.Services/Tax/TaxService.cs b/src/Libraries/SmartStore.Services/Tax/TaxService.cs index e07263ec49..4bc52f11c6 100644 --- a/src/Libraries/SmartStore.Services/Tax/TaxService.cs +++ b/src/Libraries/SmartStore.Services/Tax/TaxService.cs @@ -355,7 +355,12 @@ protected virtual decimal GetTaxRateCore(Product product, int taxCategoryId, Cus { return decimal.Zero; } - + + if (IsTaxExempt(product, customer)) + { + return decimal.Zero; + } + // tax request var calculateTaxRequest = CreateCalculateTaxRequest(product, taxCategoryId, customer); From 3be7136a59c9aacc0b77d401f88eb99ddf06b410 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 26 Jun 2015 19:25:07 +0200 Subject: [PATCH 0189/1256] Refactored 'DeleteAllQueuedEmails()': did not operate reliably and was too slow --- .../Messages/IQueuedEmailService.cs | 6 ++ .../Messages/QueuedEmailService.cs | 72 +++++++------------ .../Controllers/QueuedEmailController.cs | 25 ++----- 3 files changed, 38 insertions(+), 65 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs index e01c330ba0..6b1db9e52c 100644 --- a/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs @@ -25,6 +25,12 @@ public partial interface IQueuedEmailService /// Queued email void DeleteQueuedEmail(QueuedEmail queuedEmail); + /// + /// Deletes all queued emails + /// + /// The count of deleted entries + int DeleteAllQueuedEmails(); + /// /// Gets a queued email by identifier /// diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs index 5e72bca45a..2bd191bede 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs @@ -19,11 +19,6 @@ public partial class QueuedEmailService : IQueuedEmailService private readonly ILogger _logger; private readonly ILocalizationService _localizationService; - /// - /// Ctor - /// - /// Queued email repository - /// Event published public QueuedEmailService( IRepository queuedEmailRepository, IEventPublisher eventPublisher, @@ -37,11 +32,7 @@ public QueuedEmailService( _logger = logger; _localizationService = localizationService; } - - /// - /// Inserts a queued email - /// - /// Queued email + public virtual void InsertQueuedEmail(QueuedEmail queuedEmail) { if (queuedEmail == null) @@ -53,10 +44,6 @@ public virtual void InsertQueuedEmail(QueuedEmail queuedEmail) _eventPublisher.EntityInserted(queuedEmail); } - /// - /// Updates a queued email - /// - /// Queued email public virtual void UpdateQueuedEmail(QueuedEmail queuedEmail) { if (queuedEmail == null) @@ -68,10 +55,6 @@ public virtual void UpdateQueuedEmail(QueuedEmail queuedEmail) _eventPublisher.EntityUpdated(queuedEmail); } - /// - /// Deleted a queued email - /// - /// Queued email public virtual void DeleteQueuedEmail(QueuedEmail queuedEmail) { if (queuedEmail == null) @@ -83,11 +66,30 @@ public virtual void DeleteQueuedEmail(QueuedEmail queuedEmail) _eventPublisher.EntityDeleted(queuedEmail); } - /// - /// Gets a queued email by identifier - /// - /// Queued email identifier - /// Queued email + public virtual int DeleteAllQueuedEmails() + { + var autoCommit = _queuedEmailRepository.AutoCommitEnabled; + _queuedEmailRepository.AutoCommitEnabled = false; + + var count = 0; + + using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, hooksEnabled: false)) + { + var queuedEmails = _queuedEmailRepository.Table.ToList(); + foreach (var chunk in queuedEmails.Chunk(500)) + { + _queuedEmailRepository.DeleteRange(chunk.ToList()); + _queuedEmailRepository.Context.SaveChanges(); + } + + count = queuedEmails.Count; + } + + _queuedEmailRepository.AutoCommitEnabled = autoCommit; + + return count; + } + public virtual QueuedEmail GetQueuedEmailById(int queuedEmailId) { if (queuedEmailId == 0) @@ -98,11 +100,6 @@ public virtual QueuedEmail GetQueuedEmailById(int queuedEmailId) } - /// - /// Get queued emails by identifiers - /// - /// queued email identifiers - /// Queued emails public virtual IList GetQueuedEmailsByIds(int[] queuedEmailIds) { if (queuedEmailIds == null || queuedEmailIds.Length == 0) @@ -126,20 +123,6 @@ where queuedEmailIds.Contains(qe.Id) return sortedQueuedEmails; } - /// - /// Gets all queued emails - /// - /// From Email - /// To Email - /// The start time - /// The end time - /// A value indicating whether to load only not sent emails - /// Maximum send tries - /// A value indicating whether we should sort queued email descending; otherwise, ascending. - /// Page index - /// Page size - /// A value indicating whether to load manually send emails - /// Email item list public virtual IPagedList SearchEmails(string fromEmail, string toEmail, DateTime? startTime, DateTime? endTime, bool loadUnsentItemsOnly, int maxSendTries, @@ -181,11 +164,6 @@ public virtual IPagedList SearchEmails(string fromEmail, return queuedEmails; } - /// - /// Sends a queued email - /// - /// Queued email - /// Whether the operation succeeded public virtual bool SendEmail(QueuedEmail queuedEmail) { var result = false; diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs index b152c898fd..2b6f9fce31 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs @@ -21,7 +21,8 @@ public class QueuedEmailController : AdminControllerBase private readonly ILocalizationService _localizationService; private readonly IPermissionService _permissionService; - public QueuedEmailController(IQueuedEmailService queuedEmailService, + public QueuedEmailController( + IQueuedEmailService queuedEmailService, IDateTimeHelper dateTimeHelper, ILocalizationService localizationService, IPermissionService permissionService) { @@ -217,8 +218,10 @@ public ActionResult DeleteSelected(ICollection selectedIds) { var queuedEmails = _queuedEmailService.GetQueuedEmailsByIds(selectedIds.ToArray()); - foreach (var queuedEmail in queuedEmails) - _queuedEmailService.DeleteQueuedEmail(queuedEmail); + foreach (var queuedEmail in queuedEmails) + { + _queuedEmailService.DeleteQueuedEmail(queuedEmail); + } } return Json(new { Result = true }); @@ -230,21 +233,7 @@ public ActionResult DeleteAll() if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageQueue)) return AccessDeniedView(); - int count = 0; - - for (int i = 0; i < 9999999; ++i) - { - var queuedEmails = _queuedEmailService.SearchEmails(null, null, null, null, false, int.MaxValue, false, i, 100, null); - - foreach (var email in queuedEmails) - { - _queuedEmailService.DeleteQueuedEmail(email); - ++count; - } - - if (!queuedEmails.HasNextPage) - break; - } + int count = _queuedEmailService.DeleteAllQueuedEmails(); NotifySuccess(T("Admin.Common.RecordsDeleted", count)); From 866108a5e83f4516d58c481adb0f93678e228824 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 26 Jun 2015 21:52:07 +0200 Subject: [PATCH 0190/1256] Added DeleteAll() extension method to IRepository --- .../Data/RepositoryExtensions.cs | 40 +++++++++++++++++++ .../Messages/QueuedEmailService.cs | 21 +--------- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs b/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs index 2e6e8ac414..8551dd2882 100644 --- a/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs +++ b/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs @@ -51,6 +51,46 @@ public static void Delete(this IRepository rs, object id) where T : BaseEn } } + /// + /// Truncates the whole table + /// + /// Entity type + /// + /// The total number of affected entities + /// + /// This method turns off auto detection, validation and hooking. + /// + public static int DeleteAll(this IRepository rs) where T : BaseEntity + { + var autoCommit = rs.AutoCommitEnabled; + rs.AutoCommitEnabled = false; + + var count = 0; + + try + { + using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, hooksEnabled: false)) + { + var records = rs.Table.ToList(); + foreach (var chunk in records.Chunk(500)) + { + rs.DeleteRange(chunk.ToList()); + count += rs.Context.SaveChanges(); + } + } + } + catch (Exception ex) + { + throw ex; + } + finally + { + rs.AutoCommitEnabled = autoCommit; + } + + return count; + } + public static IQueryable Get( this IRepository rs, Expression> predicate = null, diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs index 2bd191bede..4a504d5f62 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs @@ -68,26 +68,7 @@ public virtual void DeleteQueuedEmail(QueuedEmail queuedEmail) public virtual int DeleteAllQueuedEmails() { - var autoCommit = _queuedEmailRepository.AutoCommitEnabled; - _queuedEmailRepository.AutoCommitEnabled = false; - - var count = 0; - - using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, hooksEnabled: false)) - { - var queuedEmails = _queuedEmailRepository.Table.ToList(); - foreach (var chunk in queuedEmails.Chunk(500)) - { - _queuedEmailRepository.DeleteRange(chunk.ToList()); - _queuedEmailRepository.Context.SaveChanges(); - } - - count = queuedEmails.Count; - } - - _queuedEmailRepository.AutoCommitEnabled = autoCommit; - - return count; + return _queuedEmailRepository.DeleteAll(); } public virtual QueuedEmail GetQueuedEmailById(int queuedEmailId) From db0f0e5ff24bfe38fbe90ae968b94811bc772a92 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 26 Jun 2015 22:55:34 +0200 Subject: [PATCH 0191/1256] E-mail attachments: added entity & map --- .../EmailAttachmentStorageLocation.cs | 22 +++ .../Domain/Messages/QueuedEmail.cs | 14 +- .../Domain/Messages/QueuedEmailAttachment.cs | 66 +++++++++ .../SmartStore.Core/SmartStore.Core.csproj | 2 + .../Messages/QueuedEmailAttachmentMap.cs | 34 +++++ ...2044329_QueuedEmailAttachments.Designer.cs | 29 ++++ .../201506262044329_QueuedEmailAttachments.cs | 40 ++++++ ...01506262044329_QueuedEmailAttachments.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 8 ++ .../Controllers/EmailAccountController.cs | 4 +- 10 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs create mode 100644 src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs create mode 100644 src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.resx diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs b/src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs new file mode 100644 index 0000000000..dc5f240370 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs @@ -0,0 +1,22 @@ +using System; + +namespace SmartStore.Core.Domain.Messages +{ + public enum EmailAttachmentStorageLocation + { + /// + /// Attachment is embedded as Blob + /// + Blob, + + /// + /// Attachment is a reference to + /// + FileReference, + + /// + /// Attachment is located on disk (physical or virtual path) + /// + Path + } +} diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs index 573231b382..f04ae054ea 100644 --- a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs +++ b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace SmartStore.Core.Domain.Messages { @@ -7,7 +8,9 @@ namespace SmartStore.Core.Domain.Messages /// public partial class QueuedEmail : BaseEntity { - /// + private ICollection _attachments; + + /// /// Gets or sets the priority /// public int Priority { get; set; } @@ -91,5 +94,14 @@ public partial class QueuedEmail : BaseEntity /// Gets the email account /// public virtual EmailAccount EmailAccount { get; set; } + + /// + /// Gets or sets the collection of attachments + /// + public virtual ICollection Attachments + { + get { return _attachments ?? (_attachments = new HashSet()); } + protected set { _attachments = value; } + } } } diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs new file mode 100644 index 0000000000..c0f6978143 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SmartStore.Core.Domain.Media; + +namespace SmartStore.Core.Domain.Messages +{ + /// + /// Reperesents an e-mail attachment + /// + public partial class QueuedEmailAttachment : BaseEntity + { + + /// + /// Gets or sets the queued email identifier + /// + public int QueuedEmailId { get; set; } + + /// + /// Gets or sets the queued email entity instance + /// + public virtual QueuedEmail QueuedEmail { get; set; } + + /// + /// Gets or sets the storage location + /// + public EmailAttachmentStorageLocation StorageLocation { get; set; } + + /// + /// A physical or virtual path to the file (only applicable if location is Path) + /// + public string Path { get; set; } + + /// + /// The id of a record (only applicable if location is FileReference) + /// + public int? FileId { get; set; } + + /// + /// Gets the file object + /// + /// + /// This property is not named Download on purpose, because we're going to rename Download to File in a future release. + /// + public virtual Download File { get; set; } + + /// + /// The attachment's binary data (only applicable if location is Blob) + /// + public byte[] Data { get; set; } + + /// + /// The attachment file name (without path) + /// + public string Name { get; set; } + + /// + /// The attachment file's mime type, e.g. + /// + public string MimeType { get; set; } + + } + +} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index fa13b5e483..4251026394 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -158,6 +158,8 @@ + + diff --git a/src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs b/src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs new file mode 100644 index 0000000000..8b654b17d8 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Data.Entity.ModelConfiguration; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SmartStore.Core.Domain.Messages; + +namespace SmartStore.Data.Mapping.Messages +{ + public class QueuedEmailAttachmentMap : EntityTypeConfiguration + { + public QueuedEmailAttachmentMap() + { + this.ToTable("QueuedEmailAttachment"); + this.HasKey(x => x.Id); + + this.Property(x => x.Path).IsOptional().HasMaxLength(1000); + this.Property(x => x.Data).IsMaxLength(); + this.HasOptional(x => x.File) + .WithMany() + .HasForeignKey(x => x.FileId) + .WillCascadeOnDelete(true); + + this.Property(x => x.Name).IsRequired().HasMaxLength(200); + this.Property(x => x.MimeType).IsRequired().HasMaxLength(200); + + this.HasRequired(x => x.QueuedEmail) + .WithMany(qe => qe.Attachments) + .HasForeignKey(x => x.QueuedEmailId) + .WillCascadeOnDelete(true); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.Designer.cs new file mode 100644 index 0000000000..96a93d428d --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class QueuedEmailAttachments : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(QueuedEmailAttachments)); + + string IMigrationMetadata.Id + { + get { return "201506262044329_QueuedEmailAttachments"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs new file mode 100644 index 0000000000..18c4da66ae --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs @@ -0,0 +1,40 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class QueuedEmailAttachments : DbMigration + { + public override void Up() + { + CreateTable( + "dbo.QueuedEmailAttachment", + c => new + { + Id = c.Int(nullable: false, identity: true), + QueuedEmailId = c.Int(nullable: false), + StorageLocation = c.Int(nullable: false), + Path = c.String(maxLength: 1000), + FileId = c.Int(), + Data = c.Binary(), + Name = c.String(nullable: false, maxLength: 200), + MimeType = c.String(nullable: false, maxLength: 200), + }) + .PrimaryKey(t => t.Id) + .ForeignKey("dbo.Download", t => t.FileId, cascadeDelete: true) + .ForeignKey("dbo.QueuedEmail", t => t.QueuedEmailId, cascadeDelete: true) + .Index(t => t.QueuedEmailId) + .Index(t => t.FileId); + + } + + public override void Down() + { + DropForeignKey("dbo.QueuedEmailAttachment", "QueuedEmailId", "dbo.QueuedEmail"); + DropForeignKey("dbo.QueuedEmailAttachment", "FileId", "dbo.Download"); + DropIndex("dbo.QueuedEmailAttachment", new[] { "FileId" }); + DropIndex("dbo.QueuedEmailAttachment", new[] { "QueuedEmailId" }); + DropTable("dbo.QueuedEmailAttachment"); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.resx b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.resx new file mode 100644 index 0000000000..f2ec5c9c8a --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 4d60239cc6..c34ecbb4e8 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -116,6 +116,7 @@ Properties\AssemblyVersionInfo.cs + @@ -281,6 +282,10 @@ 201506211043073_PaymentShippingRestrictions.cs + + + 201506262044329_QueuedEmailAttachments.cs + @@ -544,6 +549,9 @@ 201506211043073_PaymentShippingRestrictions.cs + + 201506262044329_QueuedEmailAttachments.cs + diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs index 7426f8e60f..b7ffea3206 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs @@ -188,7 +188,9 @@ public ActionResult SendTestEmail(EmailAccountModel model) string subject = _storeContext.CurrentStore.Name + ". Testing email functionality."; string body = "Email works fine."; - _emailSender.SendEmail(new SmtpContext(emailAccount), new EmailMessage(to, subject, body, from)); + var msg = new EmailMessage(to, subject, body, from); + + _emailSender.SendEmail(new SmtpContext(emailAccount), msg); NotifySuccess(_localizationService.GetResource("Admin.Configuration.EmailAccounts.SendTestEmail.Success"), false); } From 69255e8ed8d54910c1830e6e241cf5686f7d9ece Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 29 Jun 2015 10:33:02 +0200 Subject: [PATCH 0192/1256] Added zip code to shipping by weight computation method --- changelog.md | 3 +- .../ByWeightShippingComputationMethod.cs | 10 +- .../Controllers/ShippingByWeightController.cs | 2 + .../201506290747117_ZipCode.Designer.cs | 29 ++++ .../Migrations/201506290747117_ZipCode.cs | 18 +++ .../Migrations/201506290747117_ZipCode.resx | 126 ++++++++++++++++++ .../Data/ShippingByWeightRecordMap.cs | 1 + .../Domain/ShippingByWeightRecord.cs | 8 +- .../Localization/resources.de-de.xml | 6 + .../Localization/resources.en-us.xml | 6 + .../Models/ShippingByWeightListModel.cs | 2 + .../Models/ShippingByWeightModel.cs | 3 + .../Services/IShippingByWeightService.cs | 2 +- .../Services/ShippingByWeightService.cs | 36 ++++- .../SmartStore.ShippingByWeight.csproj | 7 + .../Views/ShippingByWeight/Configure.cshtml | 10 ++ 16 files changed, 256 insertions(+), 13 deletions(-) create mode 100644 src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.Designer.cs create mode 100644 src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.cs create mode 100644 src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.resx diff --git a/changelog.md b/changelog.md index 0600e50dfb..4bfdee62c9 100644 --- a/changelog.md +++ b/changelog.md @@ -1,9 +1,10 @@ -# Release Notes +# Release Notes ## SmartStore.NET 2.2.2 ### New Features * #210 Implement multi-store support for import/export +* Added zip code to shipping by weight computation method ### Improvements * (Soft) deletion of SEO slug supporting entities now also deletes the corresponding url records diff --git a/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs b/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs index 48d3ef8851..786862a0d6 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/ByWeightShippingComputationMethod.cs @@ -56,11 +56,11 @@ public ByWeightShippingComputationMethod(IShippingService shippingService, #region Utilities - private decimal? GetRate(decimal subTotal, decimal weight, int shippingMethodId, int storeId, int countryId) + private decimal? GetRate(decimal subTotal, decimal weight, int shippingMethodId, int storeId, int countryId, string zip) { decimal? shippingTotal = null; - var shippingByWeightRecord = _shippingByWeightService.FindRecord(shippingMethodId, storeId, countryId, weight); + var shippingByWeightRecord = _shippingByWeightService.FindRecord(shippingMethodId, storeId, countryId, weight, zip); if (shippingByWeightRecord == null) { if (_shippingByWeightSettings.LimitMethodsToCreated) @@ -127,10 +127,12 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get int storeId = _storeContext.CurrentStore.Id; decimal subTotal = decimal.Zero; int countryId = 0; + string zip = null; if (getShippingOptionRequest.ShippingAddress != null) { countryId = getShippingOptionRequest.ShippingAddress.CountryId ?? 0; + zip = getShippingOptionRequest.ShippingAddress.ZipPostalCode; } foreach (var shoppingCartItem in getShippingOptionRequest.Items) @@ -144,9 +146,9 @@ public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest get var shippingMethods = _shippingService.GetAllShippingMethods(countryId); foreach (var shippingMethod in shippingMethods) { - var record = _shippingByWeightService.FindRecord(shippingMethod.Id, storeId, countryId, weight); + var record = _shippingByWeightService.FindRecord(shippingMethod.Id, storeId, countryId, weight, zip); - decimal? rate = GetRate(subTotal, weight, shippingMethod.Id, storeId, countryId); + decimal? rate = GetRate(subTotal, weight, shippingMethod.Id, storeId, countryId, zip); if (rate.HasValue) { var shippingOption = new ShippingOption(); diff --git a/src/Plugins/SmartStore.ShippingByWeight/Controllers/ShippingByWeightController.cs b/src/Plugins/SmartStore.ShippingByWeight/Controllers/ShippingByWeightController.cs index 6d7c63bf12..5431abad39 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Controllers/ShippingByWeightController.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/Controllers/ShippingByWeightController.cs @@ -107,6 +107,7 @@ public ActionResult RateUpdate(ShippingByWeightModel model, GridCommand command) sbw.From = model.From; sbw.To = model.To; sbw.UsePercentage = model.UsePercentage; + sbw.Zip = model.Zip == "*" ? null : model.Zip; sbw.ShippingChargeAmount = model.ShippingChargeAmount; sbw.ShippingChargePercentage = model.ShippingChargePercentage; sbw.SmallQuantitySurcharge = model.SmallQuantitySurcharge; @@ -139,6 +140,7 @@ public ActionResult AddShippingByWeightRecord(ShippingByWeightListModel model) StoreId = model.AddStoreId, ShippingMethodId = model.AddShippingMethodId, CountryId = model.AddCountryId, + Zip = model.AddZip, //StateProvinceId = 0, From = model.AddFrom, To = model.AddTo, diff --git a/src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.Designer.cs b/src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.Designer.cs new file mode 100644 index 0000000000..f921102152 --- /dev/null +++ b/src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.ShippingByWeight.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class ZipCode : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(ZipCode)); + + string IMigrationMetadata.Id + { + get { return "201506290747117_ZipCode"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.cs b/src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.cs new file mode 100644 index 0000000000..e0ee37f6b9 --- /dev/null +++ b/src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.cs @@ -0,0 +1,18 @@ +namespace SmartStore.ShippingByWeight.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class ZipCode : DbMigration + { + public override void Up() + { + AddColumn("dbo.ShippingByWeight", "Zip", c => c.String()); + } + + public override void Down() + { + DropColumn("dbo.ShippingByWeight", "Zip"); + } + } +} diff --git a/src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.resx b/src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.resx new file mode 100644 index 0000000000..aa32749020 --- /dev/null +++ b/src/Plugins/SmartStore.ShippingByWeight/Data/Migrations/201506290747117_ZipCode.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + H4sIAAAAAAAEAM1ZzW7jNhC+F+g7CDq1QNZykksayLtInKQIuk7SKLsFeqOlsc2WPypJBfaz9dBH6it0qD/LkiVbjrPozaZmvm9mSM3Hsf/9+x//05Iz5xWUplKM3NPB0HVAhDKiYj5yEzP7cOF++vj9d/5txJfO18Lu3Nqhp9Ajd2FMfOl5OlwAJ3rAaaikljMzCCX3SCS9s+HwJ+/01AOEcBHLcfznRBjKIf2CX8dShBCbhLCJjIDpfB2fBCmq80A46JiEMHIDTpQJjFQwCBY0jjHQ69VvQOcLM7ghhrjOFaME4wqAzVyHCCENMRj15RcNgVFSzIMYFwh7WcWAdjPCNOTZXK7N901seGYT89aOBVSYaCN5T8DT87xSXt39oHq7ZSWxlrdYc7OyWaf1xArV6vcMoVSR69SpL8dMWbcdxUcXKhrrGeiJ0+F6Uh6ss8HZYDgYnjjjhJlEwUhAYhRhJ85TMmU0/AVWL/JPECORMFZNDtPDZxsLuPSkZAzKrJ5hlqd8j+l5m35e3bF0q/hk6d8Lc37mOg9ITqYMyrNTKVWa4c8gQBED0RMxBpSwGJBWv8Fe40rddxN2g4wlvl5q9VaY32lcAOB7g/vlOhOy/AxibhYjFz+6zh1dQlSs5KBfBMX+gU5GJTs5iqMwAbOQ0VsjvlOSFwg3EFJOmOs8KfyUt7cL1wlCYvH6g7/Id4PGzvQEKsQjQuZQsFxLyYCI3mBFSccLouZbcI8e/SbhFben7/3IEI39mpD0bQoSFaak34buZaFALySLjkTne+uW3GzUKIoGGyqolm79OP0DQmOtYGm2NG08VHnf1vm7uJlpxhKA6VQD7TrrIDNRbWnx23Mrs1hrupeJeiH+Xov6+xOSslRuA/mKE2RXgfGHoL8q8gzDC/UWcSyjLZmwH+O7U3tqW2wEd1RpY68cU2J3dhzxhln3nrXsR8HdvS11rVvvUuFvP5enuPPO1LajNY71DtxhUTi2lbQ+UEbeeqVoAKVXO8KI2qK1Y8kSLtr0usu7VM8qRLm4P05FQKtIleX9sVIVraKkCz1yaijkRnKNp/sjZ2pZRctW9kewklj1t9/3966pXhWo9qh/tZrit61qTatDmQrVa2cpLHowtEjdBkeLzYEsFYVrZanYNFl8r9Yh6m3Ka/Sp2m283ga7NKVuUrKX2lLTED/v57vHzEaDz0ys1MtXGqXNfaUN8LyB/sXGjILd4MJgQgSdgTbZwOKi/lzUZtP/z5zoaR2xg4bFbz6DUVvjnVNW32ve5tiVcrx16DoEpDJyiVeSvs0/cLL8sQr0lrHqkJiqQ1X0fkPV0aG3DlVT2r8Auwaqo0feNVAdn6xzoHpfusZA9Ua6fgNV8w5/yIDUYz7KJASznNpTn2VRtz14imoqm+9Vf2b1b0DT+RrC/ugqcBjBGq9BC5t7MZPFxmEBqhEVJrV9xU5DIqzjlTJ0RkKDj0PQOv3V6CthCZrc8ilE9+IxMXFirrQGPmUbP4j5Xjd/Oipuxuw/xvabPkYKGCbFFOBRXCfUnsk87rstB60Fwh6pXJYwqsBYeZqvSqQHKfYEyst3AzEIK2ovwGOGYPpRBOQVDokN++FnmJNwVVxQ2kF2b8Rm2f0bSuaKcJ1jrP3tXwee/e/g4381Mg/3bRgAAA== + + + dbo + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.ShippingByWeight/Data/ShippingByWeightRecordMap.cs b/src/Plugins/SmartStore.ShippingByWeight/Data/ShippingByWeightRecordMap.cs index 72eb28c4f0..a42e0fe8bf 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Data/ShippingByWeightRecordMap.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/Data/ShippingByWeightRecordMap.cs @@ -9,6 +9,7 @@ public ShippingByWeightRecordMap() { this.ToTable("ShippingByWeight"); this.HasKey(x => x.Id); + this.Property(x => x.Zip).IsOptional().HasMaxLength(400); } } } \ No newline at end of file diff --git a/src/Plugins/SmartStore.ShippingByWeight/Domain/ShippingByWeightRecord.cs b/src/Plugins/SmartStore.ShippingByWeight/Domain/ShippingByWeightRecord.cs index 50dc8a46c1..b46608072d 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Domain/ShippingByWeightRecord.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/Domain/ShippingByWeightRecord.cs @@ -22,10 +22,10 @@ public partial class ShippingByWeightRecord : BaseEntity ///// //public int StateProvinceId { get; set; } - ///// - ///// Gets or sets the zip - ///// - //public string Zip { get; set; } + /// + /// Gets or sets the zip + /// + public string Zip { get; set; } /// /// Gets or sets the shipping method identifier diff --git a/src/Plugins/SmartStore.ShippingByWeight/Localization/resources.de-de.xml b/src/Plugins/SmartStore.ShippingByWeight/Localization/resources.de-de.xml index d4601b5452..22792b8ccf 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Localization/resources.de-de.xml +++ b/src/Plugins/SmartStore.ShippingByWeight/Localization/resources.de-de.xml @@ -9,6 +9,12 @@ Das Bestimmungsland. Wählen Sie Stern (*), wenn das Land des Kunden bei der Auswertung keine Rolle spielen soll. + + PLZ-(Bereich) + + + PLZ-(Bereich) des Kunden, entweder als spezifischer Wert oder als Muster (z.B. 4000-49999 für das PLZ-Gebiet 4). In einem Muster lassen sich auch Wildcards verwenden, wie Stern (*) oder Fragezeichen (?). Lassen Sie das Feld leer, wenn die Gebühr unabhängig von PLZ für alle Kunden im definierten (Bundes)land gelten soll. + Versandart diff --git a/src/Plugins/SmartStore.ShippingByWeight/Localization/resources.en-us.xml b/src/Plugins/SmartStore.ShippingByWeight/Localization/resources.en-us.xml index dc2700ea71..a08218ae97 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Localization/resources.en-us.xml +++ b/src/Plugins/SmartStore.ShippingByWeight/Localization/resources.en-us.xml @@ -8,6 +8,12 @@ If an asterisk is selected, then this shipping rate will apply to all customers, regardless of the country. + + Zip-(Range) + + + Zip/postal code (range), either as specific value or range pattern (e.g. 4000-4999). You can also define wildcard chars like * or ?. If zip is empty, then this shipping rate will apply to all customers from the given country or state / province, regardless of the zip code. + Shipping method diff --git a/src/Plugins/SmartStore.ShippingByWeight/Models/ShippingByWeightListModel.cs b/src/Plugins/SmartStore.ShippingByWeight/Models/ShippingByWeightListModel.cs index 48cf4723a2..eacf5b06bc 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Models/ShippingByWeightListModel.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/Models/ShippingByWeightListModel.cs @@ -19,6 +19,8 @@ public ShippingByWeightListModel() [SmartResourceDisplayName("Plugins.Shipping.ByWeight.Fields.Country")] public int AddCountryId { get; set; } + [SmartResourceDisplayName("Plugins.Shipping.ByWeight.Fields.Zip")] + public string AddZip { get; set; } [SmartResourceDisplayName("Plugins.Shipping.ByWeight.Fields.ShippingMethod")] public int AddShippingMethodId { get; set; } [SmartResourceDisplayName("Plugins.Shipping.ByWeight.Fields.From")] diff --git a/src/Plugins/SmartStore.ShippingByWeight/Models/ShippingByWeightModel.cs b/src/Plugins/SmartStore.ShippingByWeight/Models/ShippingByWeightModel.cs index a6ba8904bd..2cf20b9b6d 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Models/ShippingByWeightModel.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/Models/ShippingByWeightModel.cs @@ -26,6 +26,9 @@ public class ShippingByWeightModel : EntityModelBase [SmartResourceDisplayName("Plugins.Shipping.ByWeight.Fields.To")] public decimal To { get; set; } + [SmartResourceDisplayName("Plugins.Shipping.ByWeight.Fields.Zip")] + public string Zip { get; set; } + [SmartResourceDisplayName("Plugins.Shipping.ByWeight.Fields.UsePercentage")] public bool UsePercentage { get; set; } diff --git a/src/Plugins/SmartStore.ShippingByWeight/Services/IShippingByWeightService.cs b/src/Plugins/SmartStore.ShippingByWeight/Services/IShippingByWeightService.cs index aab79f76a2..76237a224a 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Services/IShippingByWeightService.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/Services/IShippingByWeightService.cs @@ -23,7 +23,7 @@ public partial interface IShippingByWeightService /// IList GetShippingByWeightModels(int pageIndex, int pageSize, out int totalCount); - ShippingByWeightRecord FindRecord(int shippingMethodId, int storeId, int countryId, decimal weight); + ShippingByWeightRecord FindRecord(int shippingMethodId, int storeId, int countryId, decimal weight, string zip); ShippingByWeightRecord GetById(int shippingByWeightRecordId); diff --git a/src/Plugins/SmartStore.ShippingByWeight/Services/ShippingByWeightService.cs b/src/Plugins/SmartStore.ShippingByWeight/Services/ShippingByWeightService.cs index d518e3124b..8e9cfc5430 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Services/ShippingByWeightService.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/Services/ShippingByWeightService.cs @@ -8,6 +8,7 @@ using SmartStore.Services.Directory; using SmartStore.Services.Shipping; using SmartStore.Services.Stores; +using SmartStore.Utilities; namespace SmartStore.ShippingByWeight.Services { @@ -47,7 +48,7 @@ public virtual IQueryable GetShippingByWeightRecords() { var query = from x in _sbwRepository.Table - orderby x.StoreId, x.CountryId, x.ShippingMethodId, x.From + orderby x.StoreId, x.CountryId, x.ShippingMethodId, x.From, x.Zip select x; return query; @@ -90,6 +91,7 @@ public virtual IList GetShippingByWeightModels(int pageIn CountryId = x.CountryId, From = x.From, To = x.To, + Zip = (x.Zip.HasValue() ? x.Zip : "*"), UsePercentage = x.UsePercentage, ShippingChargePercentage = x.ShippingChargePercentage, ShippingChargeAmount = x.ShippingChargeAmount, @@ -107,7 +109,7 @@ public virtual IList GetShippingByWeightModels(int pageIn return result; } - public virtual ShippingByWeightRecord FindRecord(int shippingMethodId, int storeId, int countryId, decimal weight) + public virtual ShippingByWeightRecord FindRecord(int shippingMethodId, int storeId, int countryId, decimal weight, string zip) { var existingRecords = GetShippingByWeightRecords() .Where(x => x.ShippingMethodId == shippingMethodId && weight >= x.From && weight <= x.To) @@ -147,7 +149,17 @@ public virtual ShippingByWeightRecord FindRecord(int shippingMethodId, int store } } - return matchedByCountry.FirstOrDefault(); + //filter by zip + var matchedByZip = new List(); + foreach (var sbt in matchedByCountry) + { + if ((zip.IsEmpty() && sbt.Zip.IsEmpty()) || (ZipMatches(zip, sbt.Zip))) + { + matchedByZip.Add(sbt); + } + } + + return matchedByZip.LastOrDefault(); } public virtual ShippingByWeightRecord GetById(int shippingByWeightRecordId) @@ -183,6 +195,24 @@ public virtual void UpdateShippingByWeightRecord(ShippingByWeightRecord shipping _sbwRepository.Update(shippingByWeightRecord); } + private bool ZipMatches(string zip, string pattern) + { + if (pattern.IsEmpty() || pattern == "*") + { + return true; // catch all + } + + try + { + var wildcard = new Wildcard(pattern); + return wildcard.IsMatch(zip); + } + catch + { + return zip.IsCaseInsensitiveEqual(pattern); + } + } + #endregion } } diff --git a/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj b/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj index 561149e08f..422aa5517d 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj +++ b/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj @@ -158,6 +158,10 @@ 201406041606037_SmallQuantitySurcharge.cs + + + 201506290747117_ZipCode.cs + @@ -219,6 +223,9 @@ Designer PreserveNewest + + 201506290747117_ZipCode.cs + diff --git a/src/Plugins/SmartStore.ShippingByWeight/Views/ShippingByWeight/Configure.cshtml b/src/Plugins/SmartStore.ShippingByWeight/Views/ShippingByWeight/Configure.cshtml index 3433b37a24..08b5ea8062 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Views/ShippingByWeight/Configure.cshtml +++ b/src/Plugins/SmartStore.ShippingByWeight/Views/ShippingByWeight/Configure.cshtml @@ -17,6 +17,7 @@ { columns.Bound(x => x.StoreName).ReadOnly(); columns.Bound(x => x.CountryName).ReadOnly(); + columns.Bound(x => x.Zip); columns.Bound(x => x.ShippingMethodName).ReadOnly(); columns.Bound(x => x.From) .Format("{0:0.00}"); @@ -104,6 +105,15 @@ @Html.ValidationMessageFor(model => model.AddCountryId)
+ @Html.SmartLabelFor(model => model.AddZip) + + @Html.EditorFor(model => model.AddZip) + @Html.ValidationMessageFor(model => model.AddZip) +
@Html.SmartLabelFor(model => model.AddShippingMethodId) From 6a1bf36ee35b9820cf4a91dc1b90b56c153c4054 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Mon, 29 Jun 2015 20:01:31 +0200 Subject: [PATCH 0193/1256] Revert "E-mail attachments: added entity & map" This reverts commit db0f0e5ff24bfe38fbe90ae968b94811bc772a92. --- .../EmailAttachmentStorageLocation.cs | 22 --- .../Domain/Messages/QueuedEmail.cs | 14 +- .../Domain/Messages/QueuedEmailAttachment.cs | 66 --------- .../SmartStore.Core/SmartStore.Core.csproj | 2 - .../Messages/QueuedEmailAttachmentMap.cs | 34 ----- ...2044329_QueuedEmailAttachments.Designer.cs | 29 ---- .../201506262044329_QueuedEmailAttachments.cs | 40 ------ ...01506262044329_QueuedEmailAttachments.resx | 126 ------------------ .../SmartStore.Data/SmartStore.Data.csproj | 8 -- .../Controllers/EmailAccountController.cs | 4 +- 10 files changed, 2 insertions(+), 343 deletions(-) delete mode 100644 src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs delete mode 100644 src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs delete mode 100644 src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.Designer.cs delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.resx diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs b/src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs deleted file mode 100644 index dc5f240370..0000000000 --- a/src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace SmartStore.Core.Domain.Messages -{ - public enum EmailAttachmentStorageLocation - { - /// - /// Attachment is embedded as Blob - /// - Blob, - - /// - /// Attachment is a reference to - /// - FileReference, - - /// - /// Attachment is located on disk (physical or virtual path) - /// - Path - } -} diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs index f04ae054ea..573231b382 100644 --- a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs +++ b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; namespace SmartStore.Core.Domain.Messages { @@ -8,9 +7,7 @@ namespace SmartStore.Core.Domain.Messages /// public partial class QueuedEmail : BaseEntity { - private ICollection _attachments; - - /// + /// /// Gets or sets the priority /// public int Priority { get; set; } @@ -94,14 +91,5 @@ public partial class QueuedEmail : BaseEntity /// Gets the email account /// public virtual EmailAccount EmailAccount { get; set; } - - /// - /// Gets or sets the collection of attachments - /// - public virtual ICollection Attachments - { - get { return _attachments ?? (_attachments = new HashSet()); } - protected set { _attachments = value; } - } } } diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs deleted file mode 100644 index c0f6978143..0000000000 --- a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using SmartStore.Core.Domain.Media; - -namespace SmartStore.Core.Domain.Messages -{ - /// - /// Reperesents an e-mail attachment - /// - public partial class QueuedEmailAttachment : BaseEntity - { - - /// - /// Gets or sets the queued email identifier - /// - public int QueuedEmailId { get; set; } - - /// - /// Gets or sets the queued email entity instance - /// - public virtual QueuedEmail QueuedEmail { get; set; } - - /// - /// Gets or sets the storage location - /// - public EmailAttachmentStorageLocation StorageLocation { get; set; } - - /// - /// A physical or virtual path to the file (only applicable if location is Path) - /// - public string Path { get; set; } - - /// - /// The id of a record (only applicable if location is FileReference) - /// - public int? FileId { get; set; } - - /// - /// Gets the file object - /// - /// - /// This property is not named Download on purpose, because we're going to rename Download to File in a future release. - /// - public virtual Download File { get; set; } - - /// - /// The attachment's binary data (only applicable if location is Blob) - /// - public byte[] Data { get; set; } - - /// - /// The attachment file name (without path) - /// - public string Name { get; set; } - - /// - /// The attachment file's mime type, e.g. - /// - public string MimeType { get; set; } - - } - -} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 4251026394..fa13b5e483 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -158,8 +158,6 @@ - - diff --git a/src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs b/src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs deleted file mode 100644 index 8b654b17d8..0000000000 --- a/src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data.Entity.ModelConfiguration; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using SmartStore.Core.Domain.Messages; - -namespace SmartStore.Data.Mapping.Messages -{ - public class QueuedEmailAttachmentMap : EntityTypeConfiguration - { - public QueuedEmailAttachmentMap() - { - this.ToTable("QueuedEmailAttachment"); - this.HasKey(x => x.Id); - - this.Property(x => x.Path).IsOptional().HasMaxLength(1000); - this.Property(x => x.Data).IsMaxLength(); - this.HasOptional(x => x.File) - .WithMany() - .HasForeignKey(x => x.FileId) - .WillCascadeOnDelete(true); - - this.Property(x => x.Name).IsRequired().HasMaxLength(200); - this.Property(x => x.MimeType).IsRequired().HasMaxLength(200); - - this.HasRequired(x => x.QueuedEmail) - .WithMany(qe => qe.Attachments) - .HasForeignKey(x => x.QueuedEmailId) - .WillCascadeOnDelete(true); - } - } -} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.Designer.cs deleted file mode 100644 index 96a93d428d..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.Designer.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -namespace SmartStore.Data.Migrations -{ - using System.CodeDom.Compiler; - using System.Data.Entity.Migrations; - using System.Data.Entity.Migrations.Infrastructure; - using System.Resources; - - [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] - public sealed partial class QueuedEmailAttachments : IMigrationMetadata - { - private readonly ResourceManager Resources = new ResourceManager(typeof(QueuedEmailAttachments)); - - string IMigrationMetadata.Id - { - get { return "201506262044329_QueuedEmailAttachments"; } - } - - string IMigrationMetadata.Source - { - get { return null; } - } - - string IMigrationMetadata.Target - { - get { return Resources.GetString("Target"); } - } - } -} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs deleted file mode 100644 index 18c4da66ae..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace SmartStore.Data.Migrations -{ - using System; - using System.Data.Entity.Migrations; - - public partial class QueuedEmailAttachments : DbMigration - { - public override void Up() - { - CreateTable( - "dbo.QueuedEmailAttachment", - c => new - { - Id = c.Int(nullable: false, identity: true), - QueuedEmailId = c.Int(nullable: false), - StorageLocation = c.Int(nullable: false), - Path = c.String(maxLength: 1000), - FileId = c.Int(), - Data = c.Binary(), - Name = c.String(nullable: false, maxLength: 200), - MimeType = c.String(nullable: false, maxLength: 200), - }) - .PrimaryKey(t => t.Id) - .ForeignKey("dbo.Download", t => t.FileId, cascadeDelete: true) - .ForeignKey("dbo.QueuedEmail", t => t.QueuedEmailId, cascadeDelete: true) - .Index(t => t.QueuedEmailId) - .Index(t => t.FileId); - - } - - public override void Down() - { - DropForeignKey("dbo.QueuedEmailAttachment", "QueuedEmailId", "dbo.QueuedEmail"); - DropForeignKey("dbo.QueuedEmailAttachment", "FileId", "dbo.Download"); - DropIndex("dbo.QueuedEmailAttachment", new[] { "FileId" }); - DropIndex("dbo.QueuedEmailAttachment", new[] { "QueuedEmailId" }); - DropTable("dbo.QueuedEmailAttachment"); - } - } -} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.resx b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.resx deleted file mode 100644 index f2ec5c9c8a..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index c34ecbb4e8..4d60239cc6 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -116,7 +116,6 @@ Properties\AssemblyVersionInfo.cs - @@ -282,10 +281,6 @@ 201506211043073_PaymentShippingRestrictions.cs - - - 201506262044329_QueuedEmailAttachments.cs - @@ -549,9 +544,6 @@ 201506211043073_PaymentShippingRestrictions.cs - - 201506262044329_QueuedEmailAttachments.cs - diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs index b7ffea3206..7426f8e60f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs @@ -188,9 +188,7 @@ public ActionResult SendTestEmail(EmailAccountModel model) string subject = _storeContext.CurrentStore.Name + ". Testing email functionality."; string body = "Email works fine."; - var msg = new EmailMessage(to, subject, body, from); - - _emailSender.SendEmail(new SmtpContext(emailAccount), msg); + _emailSender.SendEmail(new SmtpContext(emailAccount), new EmailMessage(to, subject, body, from)); NotifySuccess(_localizationService.GetResource("Admin.Configuration.EmailAccounts.SendTestEmail.Success"), false); } From 91734c63e7068dfdbef454f96d10b4b8994343d8 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 30 Jun 2015 00:42:56 +0200 Subject: [PATCH 0194/1256] E-mail attachments: convert QueuedEmail > EmailMessage --- .../Email/DefaultEmailSender.cs | 9 +- .../Messages/QueuedEmailService.cs | 55 +++++++++++ .../Messages/QueuedEmailPersistenceTests.cs | 95 ++++++++++++++++++- 3 files changed, 147 insertions(+), 12 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Email/DefaultEmailSender.cs b/src/Libraries/SmartStore.Core/Email/DefaultEmailSender.cs index d519fb2239..42f9b99eec 100644 --- a/src/Libraries/SmartStore.Core/Email/DefaultEmailSender.cs +++ b/src/Libraries/SmartStore.Core/Email/DefaultEmailSender.cs @@ -14,10 +14,6 @@ namespace SmartStore.Core.Email public class DefaultEmailSender : IEmailSender { - public DefaultEmailSender() - { - } - /// /// Builds System.Net.Mail.Message /// @@ -54,10 +50,7 @@ protected virtual MailMessage BuildMailMessage(EmailMessage original) msg.Bcc.AddRange(original.Bcc.Where(x => x.Address.HasValue()).Select(x => x.ToMailAddress())); msg.ReplyToList.AddRange(original.ReplyTo.Where(x => x.Address.HasValue()).Select(x => x.ToMailAddress())); - foreach (var attachment in original.Attachments) - { - msg.Attachments.Add(attachment); - } + msg.Attachments.AddRange(original.Attachments); if (original.Headers != null) msg.Headers.AddRange(original.Headers); diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs index 4a504d5f62..78fe190196 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Mail; +using System.IO; using SmartStore.Core; using SmartStore.Core.Data; using SmartStore.Core.Domain.Messages; @@ -8,6 +10,8 @@ using SmartStore.Core.Events; using SmartStore.Core.Logging; using SmartStore.Services.Localization; +using SmartStore.Utilities; +using System.Web; namespace SmartStore.Services.Messages { @@ -177,6 +181,8 @@ public virtual bool SendEmail(QueuedEmail queuedEmail) msg.Bcc.AddRange(bcc.Where(x => x.HasValue()).Select(x => new EmailAddress(x))); } + CreateAttachments(queuedEmail, msg); + _emailSender.SendEmail(smtpContext, msg); queuedEmail.SentOnUtc = DateTime.UtcNow; @@ -191,7 +197,56 @@ public virtual bool SendEmail(QueuedEmail queuedEmail) queuedEmail.SentTries = queuedEmail.SentTries + 1; UpdateQueuedEmail(queuedEmail); } + return result; } + + private void CreateAttachments(QueuedEmail qe, EmailMessage msg) + { + if (qe.Attachments == null || qe.Attachments.Count == 0) + return; + + foreach (var qea in qe.Attachments) + { + Attachment attachment = null; + + if (qea.StorageLocation == EmailAttachmentStorageLocation.Blob) + { + var data = qea.Data; + if (data != null && data.Length > 0) + { + attachment = new Attachment(data.ToStream(), qea.Name, qea.MimeType); + } + } + else if (qea.StorageLocation == EmailAttachmentStorageLocation.Path) + { + var path = qea.Path; + if (path.HasValue()) + { + if (path[0] == '~' || path[0] == '/') + { + path = CommonHelper.MapPath(VirtualPathUtility.ToAppRelative(path)); + } + if (File.Exists(path)) + { + attachment = new Attachment(path, qea.MimeType); + } + } + } + else if (qea.StorageLocation == EmailAttachmentStorageLocation.FileReference) + { + var file = qea.File; + if (file != null && file.UseDownloadUrl == false && file.DownloadBinary != null && file.DownloadBinary.Length > 0) + { + attachment = new Attachment(file.DownloadBinary.ToStream(), file.Filename + file.Extension, file.ContentType); + } + } + + if (attachment != null) + { + msg.Attachments.Add(attachment); + } + } + } } } diff --git a/src/Tests/SmartStore.Data.Tests/Messages/QueuedEmailPersistenceTests.cs b/src/Tests/SmartStore.Data.Tests/Messages/QueuedEmailPersistenceTests.cs index 66e5261771..0228d4c3f1 100644 --- a/src/Tests/SmartStore.Data.Tests/Messages/QueuedEmailPersistenceTests.cs +++ b/src/Tests/SmartStore.Data.Tests/Messages/QueuedEmailPersistenceTests.cs @@ -1,7 +1,10 @@ using System; +using System.Collections.Generic; +using System.Linq; using SmartStore.Core.Domain.Messages; using SmartStore.Tests; using NUnit.Framework; +using SmartStore.Core.Domain.Media; namespace SmartStore.Data.Tests.Messages { @@ -11,7 +14,7 @@ public class QueuedEmailPersistenceTests : PersistenceTest [Test] public void Can_save_and_load_queuedEmail() { - var qe = new QueuedEmail() + var qe = new QueuedEmail { Priority = 1, From = "From", @@ -35,11 +38,9 @@ public void Can_save_and_load_queuedEmail() Password = "111", EnableSsl = true, UseDefaultCredentials = true - } - + }, }; - var fromDb = SaveAndLoadEntity(qe); fromDb.ShouldNotBeNull(); fromDb.Priority.ShouldEqual(1); @@ -58,5 +59,91 @@ public void Can_save_and_load_queuedEmail() fromDb.EmailAccount.ShouldNotBeNull(); fromDb.EmailAccount.DisplayName.ShouldEqual("Administrator"); } + + [Test] + public void Can_cascade_delete_attachment() + { + var account = new EmailAccount + { + Email = "admin@yourstore.com", + Host = "127.0.0.1", + Username = "John", + Password = "111" + }; + + var download = new Download + { + ContentType = "text/plain", + DownloadBinary = new byte[10], + DownloadGuid = Guid.NewGuid(), + Extension = "txt", + Filename = "file" + }; + + // add attachment + var attach = new QueuedEmailAttachment + { + StorageLocation = EmailAttachmentStorageLocation.FileReference, + Name = "file.txt", + MimeType = "text/plain", + File = download + }; + + var qe = new QueuedEmail + { + Priority = 1, + From = "From", + To = "To", + Subject = "Subject", + CreatedOnUtc = DateTime.UtcNow, + EmailAccount = account + }; + + qe.Attachments.Add(attach); + + var fromDb = SaveAndLoadEntity(qe); + fromDb.ShouldNotBeNull(); + + Assert.AreEqual(fromDb.Attachments.Count, 1); + attach = fromDb.Attachments.FirstOrDefault(); + attach.ShouldNotBeNull(); + + download = attach.File; + download.ShouldNotBeNull(); + + var attachId = attach.Id; + var downloadId = download.Id; + + // delete Attachment.Download + context.Set().Remove(download); + context.SaveChanges(); + base.ReloadContext(); + + attach = context.Set().Find(attachId); + attach.ShouldBeNull(); + + // add new attachment + attach = new QueuedEmailAttachment + { + StorageLocation = EmailAttachmentStorageLocation.FileReference, + Name = "file.txt", + MimeType = "text/plain" + }; + + qe = context.Set().FirstOrDefault(); + qe.Attachments.Add(attach); + + fromDb = SaveAndLoadEntity(qe); + fromDb.ShouldNotBeNull(); + + // delete QueuedEmail + context.Set().Remove(fromDb); + context.SaveChanges(); + base.ReloadContext(); + + // Attachment should also be gone now + attach = context.Set().FirstOrDefault(); + attach.ShouldBeNull(); + } } } \ No newline at end of file From e85a366bd13caf211b58bd6802633058c9ff1b08 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Fri, 26 Jun 2015 13:42:23 +0200 Subject: [PATCH 0195/1256] Primary store currency and exchange rate currency on store entity --- .../SmartStore.Core/Domain/Stores/Store.cs | 27 ++++ .../Mapping/Stores/StoreMap.cs | 8 ++ .../201506261018157_Merge.Designer.cs | 29 ++++ .../Migrations/201506261018157_Merge.cs | 16 +++ .../Migrations/201506261018157_Merge.resx | 126 ++++++++++++++++++ ...PrimaryStoreCurrencyMultiStore.Designer.cs | 29 ++++ ...61028198_PrimaryStoreCurrencyMultiStore.cs | 68 ++++++++++ ...028198_PrimaryStoreCurrencyMultiStore.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 14 ++ 9 files changed, 443 insertions(+) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.resx create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.resx diff --git a/src/Libraries/SmartStore.Core/Domain/Stores/Store.cs b/src/Libraries/SmartStore.Core/Domain/Stores/Store.cs index 0b5c7e30b2..597198913e 100644 --- a/src/Libraries/SmartStore.Core/Domain/Stores/Store.cs +++ b/src/Libraries/SmartStore.Core/Domain/Stores/Store.cs @@ -1,4 +1,5 @@ using System.Runtime.Serialization; +using SmartStore.Core.Domain.Directory; namespace SmartStore.Core.Domain.Stores { @@ -59,8 +60,34 @@ public partial class Store : BaseEntity /// /// Gets or sets the CDN host name, if static media content should be served through a CDN. /// + [DataMember] public string ContentDeliveryNetwork { get; set; } + /// + /// Gets or sets the primary store currency identifier + /// + [DataMember] + public int? PrimaryStoreCurrencyId { get; set; } + + /// + /// Gets or sets the primary exchange rate currency identifier + /// + [DataMember] + public int? PrimaryExchangeRateCurrencyId { get; set; } + + /// + /// Gets or sets the primary store currency + /// + [DataMember] + public virtual Currency PrimaryStoreCurrency { get; set; } + + /// + /// Gets or sets the primary exchange rate currency + /// + [DataMember] + public virtual Currency PrimaryExchangeRateCurrency { get; set; } + + /// /// Gets the security mode for the store /// diff --git a/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs b/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs index 486167b3a6..4203d1a743 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs @@ -14,6 +14,14 @@ public StoreMap() this.Property(s => s.ContentDeliveryNetwork).HasMaxLength(400); this.Property(s => s.SecureUrl).HasMaxLength(400); this.Property(s => s.Hosts).HasMaxLength(1000); + + this.HasOptional(s => s.PrimaryStoreCurrency) + .WithMany() + .HasForeignKey(s => s.PrimaryStoreCurrencyId).WillCascadeOnDelete(false); + + this.HasOptional(s => s.PrimaryExchangeRateCurrency) + .WithMany() + .HasForeignKey(s => s.PrimaryExchangeRateCurrencyId).WillCascadeOnDelete(false); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.Designer.cs new file mode 100644 index 0000000000..8d36b523ab --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class Merge : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(Merge)); + + string IMigrationMetadata.Id + { + get { return "201506261018157_Merge"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.cs b/src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.cs new file mode 100644 index 0000000000..d5201b31f3 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.cs @@ -0,0 +1,16 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class Merge : DbMigration + { + public override void Up() + { + } + + public override void Down() + { + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.resx b/src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.resx new file mode 100644 index 0000000000..01a895415e --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506261018157_Merge.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.Designer.cs new file mode 100644 index 0000000000..26e9e30860 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class PrimaryStoreCurrencyMultiStore : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(PrimaryStoreCurrencyMultiStore)); + + string IMigrationMetadata.Id + { + get { return "201506261028198_PrimaryStoreCurrencyMultiStore"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.cs new file mode 100644 index 0000000000..02f5cc517f --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.cs @@ -0,0 +1,68 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Linq; + using System.Data.Entity.Migrations; + using SmartStore.Core.Domain.Configuration; + using SmartStore.Data.Setup; + using SmartStore.Core.Domain.Stores; + + public partial class PrimaryStoreCurrencyMultiStore : DbMigration, ILocaleResourcesProvider, IDataSeeder + { + public override void Up() + { + AddColumn("dbo.Store", "PrimaryStoreCurrencyId", c => c.Int()); + AddColumn("dbo.Store", "PrimaryExchangeRateCurrencyId", c => c.Int()); + CreateIndex("dbo.Store", "PrimaryStoreCurrencyId"); + CreateIndex("dbo.Store", "PrimaryExchangeRateCurrencyId"); + AddForeignKey("dbo.Store", "PrimaryExchangeRateCurrencyId", "dbo.Currency", "Id"); + AddForeignKey("dbo.Store", "PrimaryStoreCurrencyId", "dbo.Currency", "Id"); + } + + public override void Down() + { + DropForeignKey("dbo.Store", "PrimaryStoreCurrencyId", "dbo.Currency"); + DropForeignKey("dbo.Store", "PrimaryExchangeRateCurrencyId", "dbo.Currency"); + DropIndex("dbo.Store", new[] { "PrimaryExchangeRateCurrencyId" }); + DropIndex("dbo.Store", new[] { "PrimaryStoreCurrencyId" }); + DropColumn("dbo.Store", "PrimaryExchangeRateCurrencyId"); + DropColumn("dbo.Store", "PrimaryStoreCurrencyId"); + } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + + var settings = context.Set(); + var primaryStoreCurrency = settings.FirstOrDefault(x => x.Name == "CurrencySettings.PrimaryStoreCurrencyId"); + var primaryExchangeRateCurrency = settings.FirstOrDefault(x => x.Name == "CurrencySettings.PrimaryExchangeRateCurrencyId"); + + var stores = context.Set().ToList(); + + foreach (var store in stores) + { + int id = primaryStoreCurrency.Value.ToInt(); + if (id != 0) + store.PrimaryStoreCurrencyId = id; + + id = primaryExchangeRateCurrency.Value.ToInt(); + if (id != 0) + store.PrimaryExchangeRateCurrencyId = id; + } + + settings.Remove(primaryStoreCurrency); + settings.Remove(primaryExchangeRateCurrency); + + context.SaveChanges(); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.resx b/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.resx new file mode 100644 index 0000000000..b90afc9625 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 4d60239cc6..962e995619 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -281,6 +281,14 @@ 201506211043073_PaymentShippingRestrictions.cs + + + 201506261018157_Merge.cs + + + + 201506261028198_PrimaryStoreCurrencyMultiStore.cs + @@ -544,6 +552,12 @@ 201506211043073_PaymentShippingRestrictions.cs + + 201506261018157_Merge.cs + + + 201506261028198_PrimaryStoreCurrencyMultiStore.cs + From f8279ef623e2dd3d9742c6aa5d5b5e618be6b334 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 27 Jun 2015 11:10:17 +0200 Subject: [PATCH 0196/1256] Refactored and removed CurrencySettings.PrimaryStoreCurrencyId --- .../Domain/Directory/CurrencySettings.cs | 4 +- .../SmartStore.Core/Domain/Stores/Store.cs | 4 +- .../Mapping/Stores/StoreMap.cs | 4 +- ...028198_PrimaryStoreCurrencyMultiStore.resx | 126 ---- ...rimaryStoreCurrencyMultiStore.Designer.cs} | 2 +- ...1756463_PrimaryStoreCurrencyMultiStore.cs} | 9 +- ...756463_PrimaryStoreCurrencyMultiStore.resx | 126 ++++ .../Setup/SeedData/InvariantSeedData.cs | 10 +- .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../Directory/CurrencyService.cs | 15 +- .../Directory/ICurrencyService.cs | 7 +- .../Orders/OrderProcessingService.cs | 4 +- .../FroogleFeedPlugin.cs | 22 +- .../Services/GoogleFeedService.cs | 12 +- .../Controllers/PayPalExpressController.cs | 11 +- .../Providers/PayPalDirectProvider.cs | 26 +- .../Providers/PayPalExpressProvider.cs | 56 +- .../Providers/PayPalProviderBase.cs | 14 +- .../Providers/PayPalStandardProvider.cs | 11 +- .../Controllers/ByTotalController.cs | 46 +- .../Controllers/ShippingByWeightController.cs | 74 +-- .../Plugins/PluginHelper.cs | 26 - .../WebWorkContext.cs | 27 +- .../CheckoutAttributeController.cs | 77 +-- .../Controllers/CommonController.cs | 2 +- .../Controllers/CurrencyController.cs | 86 +-- .../Controllers/DiscountController.cs | 84 ++- .../Controllers/GiftCardController.cs | 75 +-- .../Controllers/OrderController.cs | 2 +- .../Controllers/ProductController.cs | 4 +- .../Controllers/SettingController.cs | 600 +++++++++--------- .../Controllers/CatalogHelper.cs | 8 +- .../Installation/DeDESeedData.cs | 1 - .../Installation/InstallDataSeeder.cs | 2 +- .../Catalog/PriceFormatterTests.cs | 5 +- .../Directory/CurrencyServiceTests.cs | 10 +- 36 files changed, 765 insertions(+), 837 deletions(-) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.resx rename src/Libraries/SmartStore.Data/Migrations/{201506261028198_PrimaryStoreCurrencyMultiStore.Designer.cs => 201506261756463_PrimaryStoreCurrencyMultiStore.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201506261028198_PrimaryStoreCurrencyMultiStore.cs => 201506261756463_PrimaryStoreCurrencyMultiStore.cs} (97%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.resx diff --git a/src/Libraries/SmartStore.Core/Domain/Directory/CurrencySettings.cs b/src/Libraries/SmartStore.Core/Domain/Directory/CurrencySettings.cs index d1c807b4a6..77caffa2b6 100644 --- a/src/Libraries/SmartStore.Core/Domain/Directory/CurrencySettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Directory/CurrencySettings.cs @@ -1,11 +1,9 @@ - -using SmartStore.Core.Configuration; +using SmartStore.Core.Configuration; namespace SmartStore.Core.Domain.Directory { public class CurrencySettings : ISettings { - public int PrimaryStoreCurrencyId { get; set; } public int PrimaryExchangeRateCurrencyId { get; set; } public string ActiveExchangeRateProviderSystemName { get; set; } public bool AutoUpdateEnabled { get; set; } diff --git a/src/Libraries/SmartStore.Core/Domain/Stores/Store.cs b/src/Libraries/SmartStore.Core/Domain/Stores/Store.cs index 597198913e..0d9fe6be96 100644 --- a/src/Libraries/SmartStore.Core/Domain/Stores/Store.cs +++ b/src/Libraries/SmartStore.Core/Domain/Stores/Store.cs @@ -67,13 +67,13 @@ public partial class Store : BaseEntity /// Gets or sets the primary store currency identifier /// [DataMember] - public int? PrimaryStoreCurrencyId { get; set; } + public int PrimaryStoreCurrencyId { get; set; } /// /// Gets or sets the primary exchange rate currency identifier /// [DataMember] - public int? PrimaryExchangeRateCurrencyId { get; set; } + public int PrimaryExchangeRateCurrencyId { get; set; } /// /// Gets or sets the primary store currency diff --git a/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs b/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs index 4203d1a743..bc204d80e9 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs @@ -15,11 +15,11 @@ public StoreMap() this.Property(s => s.SecureUrl).HasMaxLength(400); this.Property(s => s.Hosts).HasMaxLength(1000); - this.HasOptional(s => s.PrimaryStoreCurrency) + this.HasRequired(s => s.PrimaryStoreCurrency) .WithMany() .HasForeignKey(s => s.PrimaryStoreCurrencyId).WillCascadeOnDelete(false); - this.HasOptional(s => s.PrimaryExchangeRateCurrency) + this.HasRequired(s => s.PrimaryExchangeRateCurrency) .WithMany() .HasForeignKey(s => s.PrimaryExchangeRateCurrencyId).WillCascadeOnDelete(false); } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.resx b/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.resx deleted file mode 100644 index b90afc9625..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.Designer.cs index 26e9e30860..11aadff013 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class PrimaryStoreCurrencyMultiStore : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201506261028198_PrimaryStoreCurrencyMultiStore"; } + get { return "201506261756463_PrimaryStoreCurrencyMultiStore"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs similarity index 97% rename from src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.cs rename to src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs index 02f5cc517f..ed33800321 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261028198_PrimaryStoreCurrencyMultiStore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -1,18 +1,17 @@ namespace SmartStore.Data.Migrations { - using System; - using System.Linq; using System.Data.Entity.Migrations; + using System.Linq; using SmartStore.Core.Domain.Configuration; - using SmartStore.Data.Setup; using SmartStore.Core.Domain.Stores; + using SmartStore.Data.Setup; public partial class PrimaryStoreCurrencyMultiStore : DbMigration, ILocaleResourcesProvider, IDataSeeder { public override void Up() { - AddColumn("dbo.Store", "PrimaryStoreCurrencyId", c => c.Int()); - AddColumn("dbo.Store", "PrimaryExchangeRateCurrencyId", c => c.Int()); + AddColumn("dbo.Store", "PrimaryStoreCurrencyId", c => c.Int(nullable: false)); + AddColumn("dbo.Store", "PrimaryExchangeRateCurrencyId", c => c.Int(nullable: false)); CreateIndex("dbo.Store", "PrimaryStoreCurrencyId"); CreateIndex("dbo.Store", "PrimaryExchangeRateCurrencyId"); AddForeignKey("dbo.Store", "PrimaryExchangeRateCurrencyId", "dbo.Currency", "Id"); diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.resx b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.resx new file mode 100644 index 0000000000..7e45cc22c4 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs index d6f664d19d..970ba62e41 100644 --- a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs +++ b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs @@ -73,6 +73,10 @@ public IList Stores() var seName = GetSeName("company-logo"); var imgCompanyLogo = _ctx.Set().Where(x => x.SeoFilename == seName).FirstOrDefault(); + var currency = _ctx.Set().FirstOrDefault(x => x.CurrencyCode == "EUR"); + if (currency == null) + currency = _ctx.Set().First(); + var entities = new List() { new Store() @@ -82,7 +86,9 @@ public IList Stores() Hosts = "yourstore.com,www.yourstore.com", SslEnabled = false, DisplayOrder = 1, - LogoPictureId = imgCompanyLogo.Id + LogoPictureId = imgCompanyLogo.Id, + PrimaryStoreCurrencyId = currency.Id, + PrimaryExchangeRateCurrencyId = currency.Id } }; this.Alter(entities); @@ -4244,8 +4250,6 @@ public IList Settings() }, new CurrencySettings() { - PrimaryStoreCurrencyId = _ctx.Set().First().Id, - PrimaryExchangeRateCurrencyId = _ctx.Set().First().Id, }, new MeasureSettings() { diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 962e995619..1d9b57ac77 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -285,9 +285,9 @@ 201506261018157_Merge.cs - - - 201506261028198_PrimaryStoreCurrencyMultiStore.cs + + + 201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -555,8 +555,8 @@ 201506261018157_Merge.cs - - 201506261028198_PrimaryStoreCurrencyMultiStore.cs + + 201506261756463_PrimaryStoreCurrencyMultiStore.cs diff --git a/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs b/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs index 6b436fd14d..25fcf7762c 100644 --- a/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs +++ b/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs @@ -33,6 +33,7 @@ public partial class CurrencyService : ICurrencyService private readonly IPluginFinder _pluginFinder; private readonly IEventPublisher _eventPublisher; private readonly IProviderManager _providerManager; + private readonly IStoreContext _storeContext; #endregion @@ -53,7 +54,8 @@ public CurrencyService(ICacheManager cacheManager, CurrencySettings currencySettings, IPluginFinder pluginFinder, IEventPublisher eventPublisher, - IProviderManager providerManager) + IProviderManager providerManager, + IStoreContext storeContext) { this._cacheManager = cacheManager; this._currencyRepository = currencyRepository; @@ -62,6 +64,7 @@ public CurrencyService(ICacheManager cacheManager, this._pluginFinder = pluginFinder; this._eventPublisher = eventPublisher; this._providerManager = providerManager; + this._storeContext = storeContext; } #endregion @@ -268,11 +271,13 @@ public virtual decimal ConvertFromPrimaryExchangeRateCurrency(decimal amount, Cu /// /// Amount /// Source currency code + /// Store to get the primary store currency from /// Converted value - public virtual decimal ConvertToPrimaryStoreCurrency(decimal amount, Currency sourceCurrencyCode) + public virtual decimal ConvertToPrimaryStoreCurrency(decimal amount, Currency sourceCurrencyCode, Store store = null) { decimal result = amount; - var primaryStoreCurrency = GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + var primaryStoreCurrency = (store == null ? _storeContext.CurrentStore.PrimaryStoreCurrency : store.PrimaryStoreCurrency); + if (result != decimal.Zero && sourceCurrencyCode.Id != primaryStoreCurrency.Id) { decimal exchangeRate = sourceCurrencyCode.Rate; @@ -289,10 +294,10 @@ public virtual decimal ConvertToPrimaryStoreCurrency(decimal amount, Currency so /// Amount /// Target currency code /// Converted value - public virtual decimal ConvertFromPrimaryStoreCurrency(decimal amount, Currency targetCurrencyCode) + public virtual decimal ConvertFromPrimaryStoreCurrency(decimal amount, Currency targetCurrencyCode, Store store = null) { decimal result = amount; - var primaryStoreCurrency = GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + var primaryStoreCurrency = (store == null ? _storeContext.CurrentStore.PrimaryStoreCurrency : store.PrimaryStoreCurrency); result = ConvertCurrency(amount, primaryStoreCurrency, targetCurrencyCode); return result; } diff --git a/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs b/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs index b1481d03f3..f7285a3ecf 100644 --- a/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs +++ b/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using SmartStore.Core.Domain.Directory; +using SmartStore.Core.Domain.Stores; using SmartStore.Core.Plugins; namespace SmartStore.Services.Directory @@ -96,16 +97,18 @@ public partial interface ICurrencyService /// /// Amount /// Source currency code + /// Store to get the primary store currency from /// Converted value - decimal ConvertToPrimaryStoreCurrency(decimal amount, Currency sourceCurrencyCode); + decimal ConvertToPrimaryStoreCurrency(decimal amount, Currency sourceCurrencyCode, Store store = null); /// /// Converts from primary store currency /// /// Amount /// Target currency code + /// Store to get the primary store currency from /// Converted value - decimal ConvertFromPrimaryStoreCurrency(decimal amount, Currency targetCurrencyCode); + decimal ConvertFromPrimaryStoreCurrency(decimal amount, Currency targetCurrencyCode, Store store = null); diff --git a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs index a1b07c3749..e7179516c0 100644 --- a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs +++ b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs @@ -521,7 +521,9 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR var currencyTmp = _currencyService.GetCurrencyById(customer.GetAttribute(SystemCustomerAttributeNames.CurrencyId, processPaymentRequest.StoreId)); var customerCurrency = (currencyTmp != null && currencyTmp.Published) ? currencyTmp : _workContext.WorkingCurrency; customerCurrencyCode = customerCurrency.CurrencyCode; - var primaryStoreCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + + var primaryStoreCurrency = _storeContext.CurrentStore.PrimaryStoreCurrency; + customerCurrencyRate = customerCurrency.Rate / primaryStoreCurrency.Rate; } else diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/FroogleFeedPlugin.cs b/src/Plugins/SmartStore.GoogleMerchantCenter/FroogleFeedPlugin.cs index 478cd9cd2d..a4f5d4d476 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/FroogleFeedPlugin.cs +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/FroogleFeedPlugin.cs @@ -3,25 +3,21 @@ using SmartStore.Core.Plugins; using SmartStore.GoogleMerchantCenter.Data.Migrations; using SmartStore.GoogleMerchantCenter.Services; -using SmartStore.Services.Configuration; -using SmartStore.Services.Localization; +using SmartStore.Services; namespace SmartStore.GoogleMerchantCenter { public class FroogleFeedPlugin : BasePlugin, IConfigurable { private readonly IGoogleFeedService _googleService; - private readonly ISettingService _settingService; - private readonly ILocalizationService _localizationService; + private readonly ICommonServices _services; public FroogleFeedPlugin( IGoogleFeedService googleService, - ISettingService settingService, - ILocalizationService localizationService) + ICommonServices services) { _googleService = googleService; - _settingService = settingService; - _localizationService = localizationService; + _services = services; } /// @@ -43,11 +39,11 @@ public void GetConfigurationRoute(out string actionName, out string controllerNa public override void Install() { var settings = new FroogleSettings(); - settings.CurrencyId = _googleService.Helper.CurrencyID; + settings.CurrencyId = _services.StoreContext.CurrentStore.PrimaryStoreCurrencyId; - _settingService.SaveSetting(settings); + _services.Settings.SaveSetting(settings); - _localizationService.ImportPluginResourcesFromXml(this.PluginDescriptor); + _services.Localization.ImportPluginResourcesFromXml(this.PluginDescriptor); _googleService.Helper.InsertScheduleTask(); @@ -62,9 +58,9 @@ public override void Uninstall() _googleService.Helper.DeleteFeedFiles(); _googleService.Helper.DeleteScheduleTask(); - _settingService.DeleteSetting(); + _services.Settings.DeleteSetting(); - _localizationService.DeleteLocaleStringResources(PluginDescriptor.ResourceRootKey); + _services.Localization.DeleteLocaleStringResources(PluginDescriptor.ResourceRootKey); var migrator = new DbMigrator(new Configuration()); migrator.Update(DbMigrator.InitialDatabase); diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs b/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs index c0e67eff5a..de92f5e59b 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs @@ -14,6 +14,7 @@ using SmartStore.Core.Logging; using SmartStore.GoogleMerchantCenter.Domain; using SmartStore.GoogleMerchantCenter.Models; +using SmartStore.Services; using SmartStore.Services.Catalog; using SmartStore.Services.Directory; using SmartStore.Services.Localization; @@ -35,6 +36,8 @@ public partial class GoogleFeedService : IGoogleFeedService private readonly MeasureSettings _measureSettings; private readonly IDbContext _dbContext; private readonly AdminAreaSettings _adminAreaSettings; + private readonly ICurrencyService _currencyService; + private readonly ICommonServices _services; public GoogleFeedService( IRepository gpRepository, @@ -45,6 +48,8 @@ public GoogleFeedService( MeasureSettings measureSettings, IDbContext dbContext, AdminAreaSettings adminAreaSettings, + ICurrencyService currencyService, + ICommonServices services, IComponentContext ctx) { _gpRepository = gpRepository; @@ -55,6 +60,8 @@ public GoogleFeedService( _measureSettings = measureSettings; _dbContext = dbContext; _adminAreaSettings = adminAreaSettings; + _currencyService = currencyService; + _services = services; _helper = new FeedPluginHelper(ctx, "SmartStore.GoogleMerchantCenter", "SmartStore.GoogleMerchantCenter", () => { @@ -690,9 +697,12 @@ private void CreateFeed(FeedFileCreationContext fileCreation, TaskExecutionConte VisibleIndividuallyOnly = true }; - var currency = Helper.GetUsedCurrency(Settings.CurrencyId); + var currency = _currencyService.GetCurrencyById(Settings.CurrencyId); var measureWeightSystemKey = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).SystemKeyword; + if (currency == null || !currency.Published) + currency = _services.WorkContext.WorkingCurrency; + writer.WriteStartDocument(); writer.WriteStartElement("rss"); writer.WriteAttributeString("version", "2.0"); diff --git a/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs b/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs index b3af94a0b9..0318a9e097 100644 --- a/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs +++ b/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs @@ -364,13 +364,14 @@ public ActionResult SubmitButton() if ((_services.WorkContext.CurrentCustomer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed)) return RedirectToRoute("Login"); - var settings = _services.Settings.LoadSetting(_services.StoreContext.CurrentStore.Id); - var cart = _services.WorkContext.CurrentCustomer.GetCartItems(ShoppingCartType.ShoppingCart, _services.StoreContext.CurrentStore.Id); + var store = _services.StoreContext.CurrentStore; + var settings = _services.Settings.LoadSetting(store.Id); + var cart = _services.WorkContext.CurrentCustomer.GetCartItems(ShoppingCartType.ShoppingCart, store.Id); if (cart.Count == 0) return RedirectToRoute("ShoppingCart"); - var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + var currency = store.PrimaryStoreCurrency.CurrencyCode; if (String.IsNullOrEmpty(settings.ApiAccountName)) throw new ApplicationException("PayPal API Account Name is not set"); @@ -393,9 +394,9 @@ public ActionResult SubmitButton() Discount orderSubTotalAppliedDiscount = null; decimal subTotalWithoutDiscountBase = decimal.Zero; decimal subTotalWithDiscountBase = decimal.Zero; + _orderTotalCalculationService.GetShoppingCartSubTotal(cart, - out orderSubTotalDiscountAmountBase, out orderSubTotalAppliedDiscount, - out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); + out orderSubTotalDiscountAmountBase, out orderSubTotalAppliedDiscount, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); //order total decimal resultTemp = decimal.Zero; diff --git a/src/Plugins/SmartStore.PayPal/Providers/PayPalDirectProvider.cs b/src/Plugins/SmartStore.PayPal/Providers/PayPalDirectProvider.cs index 1227e36887..ec49fe64e7 100644 --- a/src/Plugins/SmartStore.PayPal/Providers/PayPalDirectProvider.cs +++ b/src/Plugins/SmartStore.PayPal/Providers/PayPalDirectProvider.cs @@ -3,16 +3,13 @@ using Autofac; using SmartStore.Core; using SmartStore.Core.Domain.Catalog; -using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Payments; using SmartStore.Core.Plugins; using SmartStore.PayPal.Controllers; using SmartStore.PayPal.PayPalSvc; using SmartStore.PayPal.Services; using SmartStore.PayPal.Settings; -using SmartStore.Services.Configuration; using SmartStore.Services.Customers; -using SmartStore.Services.Directory; using SmartStore.Services.Payments; namespace SmartStore.PayPal @@ -27,22 +24,17 @@ public class PayPalDirectProvider : PayPalProviderBase(processPaymentRequest.StoreId); + var settings = Services.Settings.LoadSetting(processPaymentRequest.StoreId); var req = new DoDirectPaymentReq(); req.DoDirectPaymentRequest = new DoDirectPaymentRequestType(); @@ -72,7 +65,7 @@ public override ProcessPaymentResult ProcessPayment(ProcessPaymentRequest proces var details = new DoDirectPaymentRequestDetailsType(); req.DoDirectPaymentRequest.DoDirectPaymentRequestDetails = details; - details.IPAddress = CommonServices.WebHelper.GetCurrentIpAddress(); + details.IPAddress = Services.WebHelper.GetCurrentIpAddress(); if (details.IPAddress.IsEmpty()) details.IPAddress = "127.0.0.1"; @@ -110,8 +103,10 @@ public override ProcessPaymentResult ProcessPayment(ProcessPaymentRequest proces details.CreditCard.CardOwner.PayerName = new PersonNameType(); details.CreditCard.CardOwner.PayerName.FirstName = customer.BillingAddress.FirstName; details.CreditCard.CardOwner.PayerName.LastName = customer.BillingAddress.LastName; - //order totals - var payPalCurrency = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)); + + //order totals + var payPalCurrency = PayPalHelper.GetPaypalCurrency(store.PrimaryStoreCurrency); + details.PaymentDetails = new PaymentDetailsType(); details.PaymentDetails.OrderTotal = new BasicAmountType(); details.PaymentDetails.OrderTotal.Value = Math.Round(processPaymentRequest.OrderTotal, 2).ToString("N", new CultureInfo("en-us")); @@ -180,8 +175,9 @@ public override ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentReque { var result = new ProcessPaymentResult(); + var store = Services.StoreService.GetStoreById(processPaymentRequest.StoreId); var customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); - var settings = CommonServices.Settings.LoadSetting(processPaymentRequest.StoreId); + var settings = Services.Settings.LoadSetting(processPaymentRequest.StoreId); var req = new CreateRecurringPaymentsProfileReq(); req.CreateRecurringPaymentsProfileRequest = new CreateRecurringPaymentsProfileRequestType(); @@ -228,7 +224,7 @@ public override ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentReque details.ScheduleDetails.PaymentPeriod = new BillingPeriodDetailsType(); details.ScheduleDetails.PaymentPeriod.Amount = new BasicAmountType(); details.ScheduleDetails.PaymentPeriod.Amount.Value = Math.Round(processPaymentRequest.OrderTotal, 2).ToString("N", new CultureInfo("en-us")); - details.ScheduleDetails.PaymentPeriod.Amount.currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)); + details.ScheduleDetails.PaymentPeriod.Amount.currencyID = PayPalHelper.GetPaypalCurrency(store.PrimaryStoreCurrency); details.ScheduleDetails.PaymentPeriod.BillingFrequency = processPaymentRequest.RecurringCycleLength; switch (processPaymentRequest.RecurringCyclePeriod) { diff --git a/src/Plugins/SmartStore.PayPal/Providers/PayPalExpressProvider.cs b/src/Plugins/SmartStore.PayPal/Providers/PayPalExpressProvider.cs index d46643b8f7..8322cfe177 100644 --- a/src/Plugins/SmartStore.PayPal/Providers/PayPalExpressProvider.cs +++ b/src/Plugins/SmartStore.PayPal/Providers/PayPalExpressProvider.cs @@ -5,7 +5,6 @@ using System.Web; using SmartStore.Core; using SmartStore.Core.Domain.Customers; -using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; using SmartStore.Core.Domain.Shipping; @@ -15,10 +14,8 @@ using SmartStore.PayPal.PayPalSvc; using SmartStore.PayPal.Services; using SmartStore.PayPal.Settings; -using SmartStore.Services; using SmartStore.Services.Catalog; using SmartStore.Services.Common; -using SmartStore.Services.Configuration; using SmartStore.Services.Customers; using SmartStore.Services.Directory; using SmartStore.Services.Orders; @@ -33,7 +30,6 @@ namespace SmartStore.PayPal public partial class PayPalExpress : PayPalProviderBase { private readonly ICurrencyService _currencyService; - private readonly CurrencySettings _currencySettings; private readonly IPriceCalculationService _priceCalculationService; private readonly IGenericAttributeService _genericAttributeService; private readonly IStateProvinceService _stateProvinceService; @@ -45,7 +41,6 @@ public partial class PayPalExpress : PayPalProviderBase(processPaymentRequest.StoreId); + var settings = Services.Settings.LoadSetting(processPaymentRequest.StoreId); if (doPayment.Ack == AckCodeType.Success) { @@ -122,7 +116,7 @@ public override void PostProcessPayment(PostProcessPaymentRequest postProcessPay public override CapturePaymentResult Capture(CapturePaymentRequest capturePaymentRequest) { var result = new DoCaptureResponseType(); - var settings = CommonServices.Settings.LoadSetting(capturePaymentRequest.Order.StoreId); + var settings = Services.Settings.LoadSetting(capturePaymentRequest.Order.StoreId); // build the request var req = new DoCaptureReq @@ -188,8 +182,9 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq IList cart) { var result = new SetExpressCheckoutResponseType(); - var currentStore = CommonServices.StoreContext.CurrentStore; - var settings = CommonServices.Settings.LoadSetting(processPaymentRequest.StoreId); + var store = Services.StoreService.GetStoreById(processPaymentRequest.StoreId); + var settings = Services.Settings.LoadSetting(processPaymentRequest.StoreId); + var payPalCurrency = PayPalHelper.GetPaypalCurrency(store.PrimaryStoreCurrency); var req = new SetExpressCheckoutReq { @@ -204,8 +199,8 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq { PaymentAction = PayPalHelper.GetPaymentAction(settings), PaymentActionSpecified = true, - CancelURL = CommonServices.WebHelper.GetStoreLocation(currentStore.SslEnabled) + "cart", - ReturnURL = CommonServices.WebHelper.GetStoreLocation(currentStore.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/GetDetails", + CancelURL = Services.WebHelper.GetStoreLocation(store.SslEnabled) + "cart", + ReturnURL = Services.WebHelper.GetStoreLocation(store.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/GetDetails", //CallbackURL = _webHelper.GetStoreLocation(currentStore.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/ShippingOptions?CustomerID=" + _workContext.CurrentCustomer.Id.ToString(), //CallbackTimeout = _payPalExpressPaymentSettings.CallbackTimeout.ToString() ReqConfirmShipping = settings.ConfirmedShipment.ToString(), @@ -218,7 +213,7 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq foreach (OrganizedShoppingCartItem item in cart) { decimal shoppingCartUnitPriceWithDiscountBase = _priceCalculationService.GetUnitPrice(item, true); - decimal shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, CommonServices.WorkContext.WorkingCurrency); + decimal shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, Services.WorkContext.WorkingCurrency); decimal priceIncludingTier = shoppingCartUnitPriceWithDiscount; cartItems.Add(new PaymentDetailsItemType() @@ -228,7 +223,7 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq Quantity = item.Item.Quantity.ToString(), Amount = new BasicAmountType() // this is the per item cost { - currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)), + currencyID = payPalCurrency, Value = (priceIncludingTier).ToString("N", new CultureInfo("en-us")) } }); @@ -243,7 +238,7 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq Quantity = "1", Amount = new BasicAmountType() { - currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)), + currencyID = payPalCurrency, Value = (additionalHandlingFee).ToString("N", new CultureInfo("en-us")) } }); @@ -256,7 +251,7 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq decimal? shoppingCartShippingBase = OrderTotalCalculationService.GetShoppingCartShippingTotal(cart); if (shoppingCartShippingBase.HasValue && shoppingCartShippingBase > 0) { - shippingTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, CommonServices.WorkContext.WorkingCurrency); + shippingTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, Services.WorkContext.WorkingCurrency); } else { @@ -295,7 +290,7 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq Quantity = "1", Amount = new BasicAmountType() // this is the total discount { - currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)), + currencyID = payPalCurrency, Value = discount.ToString("N", new CultureInfo("en-us")) } }); @@ -304,7 +299,7 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq } // get customer - int customerId = Convert.ToInt32(CommonServices.WorkContext.CurrentCustomer.Id.ToString()); + int customerId = Convert.ToInt32(Services.WorkContext.CurrentCustomer.Id.ToString()); var customer = _customerService.GetCustomerById(customerId); if (!cart.IsRecurring()) @@ -332,7 +327,7 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq Quantity = "1", Amount = new BasicAmountType() { - currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)), + currencyID = payPalCurrency, Value = amountToSubtract.ToString("N", new CultureInfo("en-us")) } }); @@ -350,12 +345,12 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq ItemTotal = new BasicAmountType { Value = Math.Round(itemTotal, 2).ToString("N", new CultureInfo("en-us")), - currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) + currencyID = payPalCurrency }, ShippingTotal = new BasicAmountType { Value = Math.Round(shippingTotal, 2).ToString("N", new CultureInfo("en-us")), - currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) + currencyID = payPalCurrency }, //TaxTotal = new BasicAmountType //{ @@ -365,7 +360,7 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq OrderTotal = new BasicAmountType { Value = Math.Round(itemTotal + shippingTotal, 2).ToString("N", new CultureInfo("en-us")), - currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) + currencyID = payPalCurrency }, Custom = processPaymentRequest.OrderGuid.ToString(), ButtonSource = SmartStoreVersion.CurrentFullVersion, @@ -394,7 +389,7 @@ public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentReq public GetExpressCheckoutDetailsResponseType GetExpressCheckoutDetails(string token) { var result = new GetExpressCheckoutDetailsResponseType(); - var settings = CommonServices.Settings.LoadSetting(CommonServices.StoreContext.CurrentStore.Id); + var settings = Services.Settings.LoadSetting(Services.StoreContext.CurrentStore.Id); using (var service = new PayPalAPIAASoapBinding()) { @@ -414,14 +409,14 @@ public GetExpressCheckoutDetailsResponseType GetExpressCheckoutDetails(string to public ProcessPaymentRequest SetCheckoutDetails(ProcessPaymentRequest processPaymentRequest, GetExpressCheckoutDetailsResponseDetailsType checkoutDetails) { - int customerId = Convert.ToInt32(CommonServices.WorkContext.CurrentCustomer.Id.ToString()); + int customerId = Convert.ToInt32(Services.WorkContext.CurrentCustomer.Id.ToString()); var customer = _customerService.GetCustomerById(customerId); - var settings = CommonServices.Settings.LoadSetting(CommonServices.StoreContext.CurrentStore.Id); + var settings = Services.Settings.LoadSetting(Services.StoreContext.CurrentStore.Id); - CommonServices.WorkContext.CurrentCustomer = customer; + Services.WorkContext.CurrentCustomer = customer; //var cart = customer.ShoppingCartItems.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart).ToList(); - var cart = CommonServices.WorkContext.CurrentCustomer.GetCartItems(ShoppingCartType.ShoppingCart, CommonServices.StoreContext.CurrentStore.Id); + var cart = Services.WorkContext.CurrentCustomer.GetCartItems(ShoppingCartType.ShoppingCart, Services.StoreContext.CurrentStore.Id); // get/update billing address string billingFirstName = checkoutDetails.PayerInfo.PayerName.FirstName; @@ -541,7 +536,7 @@ public ProcessPaymentRequest SetCheckoutDetails(ProcessPaymentRequest processPay if (checkoutDetails.UserSelectedOptions.ShippingOptionName.Contains(shippingOption.Name) && checkoutDetails.UserSelectedOptions.ShippingOptionName.Contains(shippingOption.Description)) { - _genericAttributeService.SaveAttribute(CommonServices.WorkContext.CurrentCustomer, SystemCustomerAttributeNames.SelectedShippingOption, shippingOption); + _genericAttributeService.SaveAttribute(Services.WorkContext.CurrentCustomer, SystemCustomerAttributeNames.SelectedShippingOption, shippingOption); isShippingSet = true; break; } @@ -569,7 +564,8 @@ public ProcessPaymentRequest SetCheckoutDetails(ProcessPaymentRequest processPay public DoExpressCheckoutPaymentResponseType DoExpressCheckoutPayment(ProcessPaymentRequest processPaymentRequest) { var result = new DoExpressCheckoutPaymentResponseType(); - var settings = CommonServices.Settings.LoadSetting(processPaymentRequest.StoreId); + var store = Services.StoreService.GetStoreById(processPaymentRequest.StoreId); + var settings = Services.Settings.LoadSetting(processPaymentRequest.StoreId); // populate payment details var paymentDetails = new PaymentDetailsType @@ -577,7 +573,7 @@ public DoExpressCheckoutPaymentResponseType DoExpressCheckoutPayment(ProcessPaym OrderTotal = new BasicAmountType { Value = Math.Round(processPaymentRequest.OrderTotal, 2).ToString("N", new CultureInfo("en-us")), - currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) + currencyID = PayPalHelper.GetPaypalCurrency(store.PrimaryStoreCurrency) }, Custom = processPaymentRequest.OrderGuid.ToString(), ButtonSource = SmartStoreVersion.CurrentFullVersion diff --git a/src/Plugins/SmartStore.PayPal/Providers/PayPalProviderBase.cs b/src/Plugins/SmartStore.PayPal/Providers/PayPalProviderBase.cs index 687d179faf..656429ce43 100644 --- a/src/Plugins/SmartStore.PayPal/Providers/PayPalProviderBase.cs +++ b/src/Plugins/SmartStore.PayPal/Providers/PayPalProviderBase.cs @@ -31,7 +31,7 @@ protected PayPalProviderBase() public ILogger Logger { get; set; } - public ICommonServices CommonServices { get; set; } + public ICommonServices Services { get; set; } public IOrderService OrderService { get; set; } @@ -63,7 +63,7 @@ public PluginHelper Helper public bool VerifyIPN(string formString, out Dictionary values) { // settings: multistore context not possible here. we need the custom value to determine what store it is. - var settings = CommonServices.Settings.LoadSetting(); + var settings = Services.Settings.LoadSetting(); var req = (HttpWebRequest)WebRequest.Create(PayPalHelper.GetPaypalUrl(settings)); req.Method = "POST"; @@ -107,7 +107,7 @@ public override decimal GetAdditionalHandlingFee(IList(); + var settings = Services.Settings.LoadSetting(); result = this.CalculateAdditionalFee(OrderTotalCalculationService, cart, settings.AdditionalFee, settings.AdditionalFeePercentage); } @@ -129,7 +129,7 @@ public override CapturePaymentResult Capture(CapturePaymentRequest capturePaymen NewPaymentStatus = capturePaymentRequest.Order.PaymentStatus }; - var settings = CommonServices.Settings.LoadSetting(capturePaymentRequest.Order.StoreId); + var settings = Services.Settings.LoadSetting(capturePaymentRequest.Order.StoreId); string authorizationId = capturePaymentRequest.Order.AuthorizationTransactionId; var req = new DoCaptureReq(); @@ -175,7 +175,7 @@ public override RefundPaymentResult Refund(RefundPaymentRequest request) NewPaymentStatus = request.Order.PaymentStatus }; - var settings = CommonServices.Settings.LoadSetting(request.Order.StoreId); + var settings = Services.Settings.LoadSetting(request.Order.StoreId); string transactionId = request.Order.CaptureTransactionId; var req = new RefundTransactionReq(); @@ -221,7 +221,7 @@ public override VoidPaymentResult Void(VoidPaymentRequest request) }; string transactionId = request.Order.AuthorizationTransactionId; - var settings = CommonServices.Settings.LoadSetting(request.Order.StoreId); + var settings = Services.Settings.LoadSetting(request.Order.StoreId); if (String.IsNullOrEmpty(transactionId)) transactionId = request.Order.CaptureTransactionId; @@ -262,7 +262,7 @@ public override CancelRecurringPaymentResult CancelRecurringPayment(CancelRecurr { var result = new CancelRecurringPaymentResult(); var order = request.Order; - var settings = CommonServices.Settings.LoadSetting(order.StoreId); + var settings = Services.Settings.LoadSetting(order.StoreId); var req = new ManageRecurringPaymentsProfileStatusReq(); req.ManageRecurringPaymentsProfileStatusRequest = new ManageRecurringPaymentsProfileStatusRequestType(); diff --git a/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs b/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs index c009c24d3c..609a7192e5 100644 --- a/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs +++ b/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs @@ -9,7 +9,6 @@ using System.Web; using System.Web.Routing; using SmartStore.Core.Domain.Common; -using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; using SmartStore.Core.Domain.Shipping; @@ -34,22 +33,17 @@ namespace SmartStore.PayPal [DisplayOrder(2)] public partial class PayPalStandardProvider : PaymentPluginBase, IConfigurable { - private readonly ICurrencyService _currencyService; - private readonly CurrencySettings _currencySettings; private readonly IOrderTotalCalculationService _orderTotalCalculationService; private readonly HttpContextBase _httpContext; private readonly ICommonServices _services; private readonly ILogger _logger; - public PayPalStandardProvider(ICurrencyService currencyService, + public PayPalStandardProvider( HttpContextBase httpContext, - CurrencySettings currencySettings, IOrderTotalCalculationService orderTotalCalculationService, ICommonServices services, ILogger logger) { - _currencyService = currencyService; - _currencySettings = currencySettings; _orderTotalCalculationService = orderTotalCalculationService; _httpContext = httpContext; _services = services; @@ -85,6 +79,7 @@ public override void PostProcessPayment(PostProcessPaymentRequest postProcessPay if (postProcessPaymentRequest.Order.PaymentStatus == PaymentStatus.Paid) return; + var store = _services.StoreService.GetStoreById(postProcessPaymentRequest.Order.StoreId); var settings = _services.Settings.LoadSetting(postProcessPaymentRequest.Order.StoreId); var builder = new StringBuilder(); @@ -220,7 +215,7 @@ public override void PostProcessPayment(PostProcessPaymentRequest postProcessPay builder.AppendFormat("&custom={0}", postProcessPaymentRequest.Order.OrderGuid); builder.AppendFormat("&charset={0}", "utf-8"); - builder.Append(string.Format("&no_note=1¤cy_code={0}", HttpUtility.UrlEncode(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode))); + builder.Append(string.Format("&no_note=1¤cy_code={0}", HttpUtility.UrlEncode(store.PrimaryStoreCurrency.CurrencyCode))); builder.AppendFormat("&invoice={0}", HttpUtility.UrlEncode(orderNumber)); builder.AppendFormat("&rm=2", new object[0]); diff --git a/src/Plugins/SmartStore.Shipping/Controllers/ByTotalController.cs b/src/Plugins/SmartStore.Shipping/Controllers/ByTotalController.cs index c751879157..92b915c7d5 100644 --- a/src/Plugins/SmartStore.Shipping/Controllers/ByTotalController.cs +++ b/src/Plugins/SmartStore.Shipping/Controllers/ByTotalController.cs @@ -1,13 +1,11 @@ using System.Web.Mvc; using SmartStore.Core.Domain.Common; -using SmartStore.Core.Domain.Directory; +using SmartStore.Services; +using SmartStore.Services.Directory; +using SmartStore.Services.Shipping; using SmartStore.Shipping.Domain; using SmartStore.Shipping.Models; using SmartStore.Shipping.Services; -using SmartStore.Services.Configuration; -using SmartStore.Services.Directory; -using SmartStore.Services.Shipping; -using SmartStore.Services.Stores; using SmartStore.Web.Framework.Controllers; using Telerik.Web.Mvc; @@ -17,34 +15,26 @@ namespace SmartStore.Shipping.Controllers public class ByTotalController : PluginControllerBase { private readonly IShippingService _shippingService; - private readonly IStoreService _storeService; - private readonly ISettingService _settingService; private readonly IShippingByTotalService _shippingByTotalService; private readonly ShippingByTotalSettings _shippingByTotalSettings; private readonly ICountryService _countryService; - private readonly ICurrencyService _currencyService; - private readonly CurrencySettings _currencySettings; private readonly AdminAreaSettings _adminAreaSettings; + private readonly ICommonServices _services; - public ByTotalController(IShippingService shippingService, - IStoreService storeService, - ISettingService settingService, + public ByTotalController( + IShippingService shippingService, IShippingByTotalService shippingByTotalService, ShippingByTotalSettings shippingByTotalSettings, ICountryService countryService, - ICurrencyService currencyService, - CurrencySettings currencySettings, - AdminAreaSettings adminAreaSettings) + AdminAreaSettings adminAreaSettings, + ICommonServices services) { this._shippingService = shippingService; - this._storeService = storeService; - this._settingService = settingService; this._shippingByTotalService = shippingByTotalService; this._shippingByTotalSettings = shippingByTotalSettings; this._countryService = countryService; - this._currencyService = currencyService; - this._currencySettings = currencySettings; this._adminAreaSettings = adminAreaSettings; + this._services = services; } public ActionResult Configure() @@ -56,29 +46,31 @@ public ActionResult Configure() } var model = new ByTotalListModel(); + var allStores = _services.StoreService.GetAllStores(); + foreach (var sm in shippingMethods) { - model.AvailableShippingMethods.Add(new SelectListItem() { Text = sm.Name, Value = sm.Id.ToString() }); + model.AvailableShippingMethods.Add(new SelectListItem { Text = sm.Name, Value = sm.Id.ToString() }); } //stores - model.AvailableStores.Add(new SelectListItem() { Text = "*", Value = "0" }); - foreach (var store in _storeService.GetAllStores()) + model.AvailableStores.Add(new SelectListItem { Text = "*", Value = "0" }); + foreach (var store in allStores) { - model.AvailableStores.Add(new SelectListItem() { Text = store.Name, Value = store.Id.ToString() }); + model.AvailableStores.Add(new SelectListItem { Text = store.Name, Value = store.Id.ToString() }); } - //model.AvailableCountries.Add(new SelectListItem() { Text = "*", Value = "0" }); + //model.AvailableCountries.Add(new SelectListItem { Text = "*", Value = "0" }); var countries = _countryService.GetAllCountries(true); foreach (var c in countries) { - model.AvailableCountries.Add(new SelectListItem() { Text = c.Name, Value = c.Id.ToString() }); + model.AvailableCountries.Add(new SelectListItem { Text = c.Name, Value = c.Id.ToString() }); } model.LimitMethodsToCreated = _shippingByTotalSettings.LimitMethodsToCreated; model.SmallQuantityThreshold = _shippingByTotalSettings.SmallQuantityThreshold; model.SmallQuantitySurcharge = _shippingByTotalSettings.SmallQuantitySurcharge; - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; model.GridPageSize = _adminAreaSettings.GridPageSize; return View(model); @@ -166,7 +158,7 @@ public ActionResult SaveGeneralSettings(ByTotalListModel model) _shippingByTotalSettings.SmallQuantityThreshold = model.SmallQuantityThreshold; _shippingByTotalSettings.SmallQuantitySurcharge = model.SmallQuantitySurcharge; - _settingService.SaveSetting(_shippingByTotalSettings); + _services.Settings.SaveSetting(_shippingByTotalSettings); return Json(new { Result = true }); } diff --git a/src/Plugins/SmartStore.ShippingByWeight/Controllers/ShippingByWeightController.cs b/src/Plugins/SmartStore.ShippingByWeight/Controllers/ShippingByWeightController.cs index 6d7c63bf12..1e6c968f0a 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/Controllers/ShippingByWeightController.cs +++ b/src/Plugins/SmartStore.ShippingByWeight/Controllers/ShippingByWeightController.cs @@ -1,16 +1,12 @@ -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Web.Mvc; +using System.Web.Mvc; using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Directory; +using SmartStore.Services; +using SmartStore.Services.Directory; +using SmartStore.Services.Shipping; using SmartStore.ShippingByWeight.Domain; using SmartStore.ShippingByWeight.Models; using SmartStore.ShippingByWeight.Services; -using SmartStore.Services.Configuration; -using SmartStore.Services.Directory; -using SmartStore.Services.Shipping; -using SmartStore.Services.Stores; using SmartStore.Web.Framework.Controllers; using Telerik.Web.Mvc; @@ -21,37 +17,32 @@ namespace SmartStore.ShippingByWeight.Controllers public class ShippingByWeightController : PluginControllerBase { private readonly IShippingService _shippingService; - private readonly IStoreService _storeService; private readonly ICountryService _countryService; private readonly ShippingByWeightSettings _shippingByWeightSettings; private readonly IShippingByWeightService _shippingByWeightService; - private readonly ISettingService _settingService; - - private readonly ICurrencyService _currencyService; - private readonly CurrencySettings _currencySettings; private readonly IMeasureService _measureService; private readonly MeasureSettings _measureSettings; private readonly AdminAreaSettings _adminAreaSettings; - - public ShippingByWeightController(IShippingService shippingService, - IStoreService storeService, ICountryService countryService, ShippingByWeightSettings shippingByWeightSettings, - IShippingByWeightService shippingByWeightService, ISettingService settingService, - ICurrencyService currencyService, CurrencySettings currencySettings, - IMeasureService measureService, MeasureSettings measureSettings, - AdminAreaSettings adminAreaSettings) + private readonly ICommonServices _services; + + public ShippingByWeightController( + IShippingService shippingService, + ICountryService countryService, + ShippingByWeightSettings shippingByWeightSettings, + IShippingByWeightService shippingByWeightService, + IMeasureService measureService, + MeasureSettings measureSettings, + AdminAreaSettings adminAreaSettings, + ICommonServices services) { this._shippingService = shippingService; - this._storeService = storeService; this._countryService = countryService; this._shippingByWeightSettings = shippingByWeightSettings; this._shippingByWeightService = shippingByWeightService; - this._settingService = settingService; - - this._currencyService = currencyService; - this._currencySettings = currencySettings; this._measureService = measureService; this._measureSettings = measureSettings; this._adminAreaSettings = adminAreaSettings; + this._services = services; } public ActionResult Configure() @@ -61,21 +52,30 @@ public ActionResult Configure() return Content("No shipping methods can be loaded"); var model = new ShippingByWeightListModel(); - foreach (var sm in shippingMethods) - model.AvailableShippingMethods.Add(new SelectListItem() { Text = sm.Name, Value = sm.Id.ToString() }); + var countries = _countryService.GetAllCountries(true); + var allStores = _services.StoreService.GetAllStores(); + + foreach (var sm in shippingMethods) + { + model.AvailableShippingMethods.Add(new SelectListItem { Text = sm.Name, Value = sm.Id.ToString() }); + } //stores - model.AvailableStores.Add(new SelectListItem() { Text = "*", Value = "0" }); - foreach (var store in _storeService.GetAllStores()) - model.AvailableStores.Add(new SelectListItem() { Text = store.Name, Value = store.Id.ToString() }); - - model.AvailableCountries.Add(new SelectListItem() { Text = "*", Value = "0" }); - var countries = _countryService.GetAllCountries(true); - foreach (var c in countries) - model.AvailableCountries.Add(new SelectListItem() { Text = c.Name, Value = c.Id.ToString() }); + model.AvailableStores.Add(new SelectListItem { Text = "*", Value = "0" }); + foreach (var store in allStores) + { + model.AvailableStores.Add(new SelectListItem { Text = store.Name, Value = store.Id.ToString() }); + } + + model.AvailableCountries.Add(new SelectListItem { Text = "*", Value = "0" }); + foreach (var c in countries) + { + model.AvailableCountries.Add(new SelectListItem { Text = c.Name, Value = c.Id.ToString() }); + } + model.LimitMethodsToCreated = _shippingByWeightSettings.LimitMethodsToCreated; model.CalculatePerWeightUnit = _shippingByWeightSettings.CalculatePerWeightUnit; - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; model.BaseWeightIn = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name; model.GridPageSize = _adminAreaSettings.GridPageSize; @@ -160,7 +160,7 @@ public ActionResult SaveGeneralSettings(ShippingByWeightListModel model) //save settings _shippingByWeightSettings.LimitMethodsToCreated = model.LimitMethodsToCreated; _shippingByWeightSettings.CalculatePerWeightUnit = model.CalculatePerWeightUnit; - _settingService.SaveSetting(_shippingByWeightSettings); + _services.Settings.SaveSetting(_shippingByWeightSettings); return Configure(); } diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/PluginHelper.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/PluginHelper.cs index 0f6789e863..b3d71558e0 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/PluginHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/PluginHelper.cs @@ -24,7 +24,6 @@ public partial class PluginHelper private string _pluginResRootKey; private string _providerResRootKey; private Language _language; - private int? _currencyID; private string _currencyCode; private Currency _euroCurrency; private Dictionary _resMap = new Dictionary(); @@ -101,18 +100,6 @@ public bool IsLanguageGerman } } - public int CurrencyID - { - get - { - if (!_currencyID.HasValue) - { - _currencyID = _ctx.Resolve().PrimaryStoreCurrencyId; - } - return _currencyID ?? 1; - } - } - public string CurrencyCode { get @@ -219,19 +206,6 @@ public XmlDocument CreateXmlDocument(Func content) } } - public Currency GetUsedCurrency(int currencyId) - { - var currencyService = _ctx.Resolve(); - var currency = currencyService.GetCurrencyById(currencyId); - - if (currency == null || !currency.Published) - { - currency = currencyService.GetCurrencyById(CurrencyID); - } - - return currency; - } - public decimal ConvertFromStoreCurrency(decimal price, Currency currency) { return _ctx.Resolve().ConvertFromPrimaryStoreCurrency(price, currency); diff --git a/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs b/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs index bb717b809f..1b9a6d7c96 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs @@ -10,7 +10,6 @@ using SmartStore.Core.Fakes; using SmartStore.Services.Authentication; using SmartStore.Services.Common; -using SmartStore.Services.Configuration; using SmartStore.Services.Customers; using SmartStore.Services.Directory; using SmartStore.Services.Localization; @@ -35,11 +34,9 @@ public partial class WebWorkContext : IWorkContext private readonly ICurrencyService _currencyService; private readonly IGenericAttributeService _attrService; private readonly TaxSettings _taxSettings; - private readonly CurrencySettings _currencySettings; private readonly LocalizationSettings _localizationSettings; private readonly ICacheManager _cacheManager; private readonly IStoreService _storeService; - private readonly ISettingService _settingService; private readonly Lazy _taxService; private readonly IUserAgent _userAgent; @@ -58,9 +55,10 @@ public WebWorkContext(Func cacheManager, ILanguageService languageService, ICurrencyService currencyService, IGenericAttributeService attrService, - TaxSettings taxSettings, CurrencySettings currencySettings, - LocalizationSettings localizationSettings, Lazy taxService, - IStoreService storeService, ISettingService settingService, + TaxSettings taxSettings, + LocalizationSettings localizationSettings, + Lazy taxService, + IStoreService storeService, IUserAgent userAgent) { this._cacheManager = cacheManager("static"); @@ -73,10 +71,8 @@ public WebWorkContext(Func cacheManager, this._currencyService = currencyService; this._taxSettings = taxSettings; this._taxService = taxService; - this._currencySettings = currencySettings; this._localizationSettings = localizationSettings; this._storeService = storeService; - this._settingService = settingService; this._userAgent = userAgent; } @@ -353,13 +349,12 @@ public Currency WorkingCurrency if (_cachedCurrency != null) return _cachedCurrency; - bool fixPrimaryStoreCurrency = false; Currency currency = null; // return primary store currency when we're in admin area/mode if (this.IsAdmin) { - currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + currency = _storeContext.CurrentStore.PrimaryStoreCurrency; } if (currency == null) @@ -400,11 +395,7 @@ public Currency WorkingCurrency // get PrimaryStoreCurrency if (currency == null) { - if (storeCurrenciesMap.TryGetValue(_currencySettings.PrimaryStoreCurrencyId, out currency)) - { - currency = VerifyCurrency(currency); - fixPrimaryStoreCurrency = (currency == null); - } + currency = VerifyCurrency(_storeContext.CurrentStore.PrimaryStoreCurrency); } // get the first published currency for current store @@ -431,12 +422,6 @@ public Currency WorkingCurrency } } - if (fixPrimaryStoreCurrency) - { - _currencySettings.PrimaryStoreCurrencyId = currency.Id; - _settingService.UpdateSetting(_currencySettings, x => x.PrimaryStoreCurrencyId, true, _storeContext.CurrentStore.Id); - } - _cachedCurrency = currency; return _cachedCurrency; } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CheckoutAttributeController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CheckoutAttributeController.cs index 11009f3784..36002de30e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CheckoutAttributeController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CheckoutAttributeController.cs @@ -2,12 +2,12 @@ using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Orders; -using SmartStore.Core; using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Logging; +using SmartStore.Services; using SmartStore.Services.Directory; using SmartStore.Services.Localization; -using SmartStore.Core.Logging; using SmartStore.Services.Orders; using SmartStore.Services.Security; using SmartStore.Services.Tax; @@ -24,40 +24,33 @@ public class CheckoutAttributeController : AdminControllerBase private readonly ICheckoutAttributeService _checkoutAttributeService; private readonly ILanguageService _languageService; private readonly ILocalizedEntityService _localizedEntityService; - private readonly ILocalizationService _localizationService; private readonly ITaxCategoryService _taxCategoryService; - private readonly IWorkContext _workContext; - private readonly ICurrencyService _currencyService; - private readonly CurrencySettings _currencySettings; private readonly IMeasureService _measureService; private readonly MeasureSettings _measureSettings; private readonly ICustomerActivityService _customerActivityService; - private readonly IPermissionService _permissionService; + private readonly ICommonServices _services; #endregion #region Constructors public CheckoutAttributeController(ICheckoutAttributeService checkoutAttributeService, - ILanguageService languageService, ILocalizedEntityService localizedEntityService, - ILocalizationService localizationService, ITaxCategoryService taxCategoryService, - IWorkContext workContext, ICurrencyService currencyService, - ICustomerActivityService customerActivityService, CurrencySettings currencySettings, - IMeasureService measureService, MeasureSettings measureSettings, - IPermissionService permissionService) + ILanguageService languageService, + ILocalizedEntityService localizedEntityService, + ITaxCategoryService taxCategoryService, + ICustomerActivityService customerActivityService, + IMeasureService measureService, + MeasureSettings measureSettings, + ICommonServices services) { this._checkoutAttributeService = checkoutAttributeService; this._languageService = languageService; this._localizedEntityService = localizedEntityService; - this._localizationService = localizationService; this._taxCategoryService = taxCategoryService; - this._workContext = workContext; - this._currencyService = currencyService; this._customerActivityService = customerActivityService; - this._currencySettings = currencySettings; this._measureService = measureService; this._measureSettings = measureSettings; - this._permissionService = permissionService; + this._services = services; } #endregion @@ -117,7 +110,7 @@ public ActionResult Index() public ActionResult List() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); return View(); @@ -126,7 +119,7 @@ public ActionResult List() [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult List(GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var checkoutAttributes = _checkoutAttributeService.GetAllCheckoutAttributes(true); @@ -135,7 +128,7 @@ public ActionResult List(GridCommand command) Data = checkoutAttributes.Select(x => { var caModel = x.ToModel(); - caModel.AttributeControlTypeName = x.AttributeControlType.GetLocalizedEnum(_localizationService, _workContext); + caModel.AttributeControlTypeName = x.AttributeControlType.GetLocalizedEnum(_services.Localization, _services.WorkContext); return caModel; }), Total = checkoutAttributes.Count() @@ -149,7 +142,7 @@ public ActionResult List(GridCommand command) //create public ActionResult Create() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var model = new CheckoutAttributeModel(); @@ -164,7 +157,7 @@ public ActionResult Create() [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult Create(CheckoutAttributeModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); if (ModelState.IsValid) @@ -174,9 +167,9 @@ public ActionResult Create(CheckoutAttributeModel model, bool continueEditing) UpdateAttributeLocales(checkoutAttribute, model); //activity log - _customerActivityService.InsertActivity("AddNewCheckoutAttribute", _localizationService.GetResource("ActivityLog.AddNewCheckoutAttribute"), checkoutAttribute.Name); + _customerActivityService.InsertActivity("AddNewCheckoutAttribute", _services.Localization.GetResource("ActivityLog.AddNewCheckoutAttribute"), checkoutAttribute.Name); - NotifySuccess(_localizationService.GetResource("Admin.Catalog.Attributes.CheckoutAttributes.Added")); + NotifySuccess(_services.Localization.GetResource("Admin.Catalog.Attributes.CheckoutAttributes.Added")); return continueEditing ? RedirectToAction("Edit", new { id = checkoutAttribute.Id }) : RedirectToAction("List"); } @@ -188,7 +181,7 @@ public ActionResult Create(CheckoutAttributeModel model, bool continueEditing) //edit public ActionResult Edit(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var checkoutAttribute = _checkoutAttributeService.GetCheckoutAttributeById(id); @@ -211,7 +204,7 @@ public ActionResult Edit(int id) [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult Edit(CheckoutAttributeModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var checkoutAttribute = _checkoutAttributeService.GetCheckoutAttributeById(model.Id); @@ -227,9 +220,9 @@ public ActionResult Edit(CheckoutAttributeModel model, bool continueEditing) UpdateAttributeLocales(checkoutAttribute, model); //activity log - _customerActivityService.InsertActivity("EditCheckoutAttribute", _localizationService.GetResource("ActivityLog.EditCheckoutAttribute"), checkoutAttribute.Name); + _customerActivityService.InsertActivity("EditCheckoutAttribute", _services.Localization.GetResource("ActivityLog.EditCheckoutAttribute"), checkoutAttribute.Name); - NotifySuccess(_localizationService.GetResource("Admin.Catalog.Attributes.CheckoutAttributes.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Catalog.Attributes.CheckoutAttributes.Updated")); return continueEditing ? RedirectToAction("Edit", checkoutAttribute.Id) : RedirectToAction("List"); } @@ -242,16 +235,16 @@ public ActionResult Edit(CheckoutAttributeModel model, bool continueEditing) [HttpPost, ActionName("Delete")] public ActionResult DeleteConfirmed(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var checkoutAttribute = _checkoutAttributeService.GetCheckoutAttributeById(id); _checkoutAttributeService.DeleteCheckoutAttribute(checkoutAttribute); //activity log - _customerActivityService.InsertActivity("DeleteCheckoutAttribute", _localizationService.GetResource("ActivityLog.DeleteCheckoutAttribute"), checkoutAttribute.Name); + _customerActivityService.InsertActivity("DeleteCheckoutAttribute", _services.Localization.GetResource("ActivityLog.DeleteCheckoutAttribute"), checkoutAttribute.Name); - NotifySuccess(_localizationService.GetResource("Admin.Catalog.Attributes.CheckoutAttributes.Deleted")); + NotifySuccess(_services.Localization.GetResource("Admin.Catalog.Attributes.CheckoutAttributes.Deleted")); return RedirectToAction("List"); } @@ -263,7 +256,7 @@ public ActionResult DeleteConfirmed(int id) [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult ValueList(int checkoutAttributeId, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var values = _checkoutAttributeService.GetCheckoutAttributeValues(checkoutAttributeId); @@ -290,12 +283,12 @@ public ActionResult ValueList(int checkoutAttributeId, GridCommand command) //create public ActionResult ValueCreatePopup(int checkoutAttributeId) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var model = new CheckoutAttributeValueModel(); model.CheckoutAttributeId = checkoutAttributeId; - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; model.BaseWeightIn = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name; //locales @@ -306,7 +299,7 @@ public ActionResult ValueCreatePopup(int checkoutAttributeId) [HttpPost] public ActionResult ValueCreatePopup(string btnId, string formId, CheckoutAttributeValueModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var checkoutAttribute = _checkoutAttributeService.GetCheckoutAttributeById(model.CheckoutAttributeId); @@ -314,7 +307,7 @@ public ActionResult ValueCreatePopup(string btnId, string formId, CheckoutAttrib //No checkout attribute found with the specified id return RedirectToAction("List"); - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; model.BaseWeightIn = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name; if (ModelState.IsValid) @@ -337,7 +330,7 @@ public ActionResult ValueCreatePopup(string btnId, string formId, CheckoutAttrib //edit public ActionResult ValueEditPopup(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var cav = _checkoutAttributeService.GetCheckoutAttributeValueById(id); @@ -346,7 +339,7 @@ public ActionResult ValueEditPopup(int id) return RedirectToAction("List"); var model = cav.ToModel(); - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; model.BaseWeightIn = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name; //locales @@ -361,7 +354,7 @@ public ActionResult ValueEditPopup(int id) [HttpPost] public ActionResult ValueEditPopup(string btnId, string formId, CheckoutAttributeValueModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var cav = _checkoutAttributeService.GetCheckoutAttributeValueById(model.Id); @@ -369,7 +362,7 @@ public ActionResult ValueEditPopup(string btnId, string formId, CheckoutAttribut //No checkout attribute value found with the specified id return RedirectToAction("List"); - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; model.BaseWeightIn = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name; if (ModelState.IsValid) @@ -393,7 +386,7 @@ public ActionResult ValueEditPopup(string btnId, string formId, CheckoutAttribut [GridAction(EnableCustomBinding = true)] public ActionResult ValueDelete(int valueId, int checkoutAttributeId, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); var cav = _checkoutAttributeService.GetCheckoutAttributeValueById(valueId); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs index d9424d8fe0..ce27f22ebc 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs @@ -578,7 +578,7 @@ public ActionResult Warnings() } //primary store currency - var pscCurrency = _currencyService.Value.GetCurrencyById(_currencySettings.Value.PrimaryStoreCurrencyId); + var pscCurrency = _services.StoreContext.CurrentStore.PrimaryStoreCurrency; if (pscCurrency != null) { model.Add(new SystemWarningModel diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs index 6af5cd0a89..4006edb580 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs @@ -4,7 +4,7 @@ using System.Web.Mvc; using SmartStore.Admin.Models.Directory; using SmartStore.Core.Domain.Directory; -using SmartStore.Services.Configuration; +using SmartStore.Services; using SmartStore.Services.Directory; using SmartStore.Services.Helpers; using SmartStore.Services.Localization; @@ -23,40 +23,34 @@ public class CurrencyController : AdminControllerBase private readonly ICurrencyService _currencyService; private readonly CurrencySettings _currencySettings; - private readonly ISettingService _settingService; private readonly IDateTimeHelper _dateTimeHelper; - private readonly ILocalizationService _localizationService; - private readonly IPermissionService _permissionService; private readonly ILocalizedEntityService _localizedEntityService; private readonly ILanguageService _languageService; - private readonly IStoreService _storeService; private readonly IStoreMappingService _storeMappingService; private readonly PluginMediator _pluginMediator; + private readonly ICommonServices _services; #endregion #region Constructors public CurrencyController(ICurrencyService currencyService, - CurrencySettings currencySettings, ISettingService settingService, - IDateTimeHelper dateTimeHelper, ILocalizationService localizationService, - IPermissionService permissionService, - ILocalizedEntityService localizedEntityService, ILanguageService languageService, - IStoreService storeService, + CurrencySettings currencySettings, + IDateTimeHelper dateTimeHelper, + ILocalizedEntityService localizedEntityService, + ILanguageService languageService, IStoreMappingService storeMappingService, - PluginMediator pluginMediator) + PluginMediator pluginMediator, + ICommonServices services) { this._currencyService = currencyService; this._currencySettings = currencySettings; - this._settingService = settingService; this._dateTimeHelper = dateTimeHelper; - this._localizationService = localizationService; - this._permissionService = permissionService; this._localizedEntityService = localizedEntityService; this._languageService = languageService; - this._storeService = storeService; this._storeMappingService = storeMappingService; this._pluginMediator = pluginMediator; + this._services = services; } #endregion @@ -81,7 +75,7 @@ private void PrepareStoresMappingModel(CurrencyModel model, Currency currency, b if (model == null) throw new ArgumentNullException("model"); - model.AvailableStores = _storeService + model.AvailableStores = _services.StoreService .GetAllStores() .Select(s => s.ToModel()) .ToList(); @@ -109,14 +103,21 @@ public ActionResult Index() public ActionResult List(bool liveRates = false) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); var currenciesModel = _currencyService.GetAllCurrencies(true).Select(x => x.ToModel()).ToList(); - foreach (var currency in currenciesModel) - currency.IsPrimaryExchangeRateCurrency = currency.Id == _currencySettings.PrimaryExchangeRateCurrencyId ? true : false; - foreach (var currency in currenciesModel) - currency.IsPrimaryStoreCurrency = currency.Id == _currencySettings.PrimaryStoreCurrencyId ? true : false; + + foreach (var currency in currenciesModel) + { + currency.IsPrimaryExchangeRateCurrency = (currency.Id == _services.StoreContext.CurrentStore.PrimaryExchangeRateCurrencyId); + } + + foreach (var currency in currenciesModel) + { + currency.IsPrimaryStoreCurrency = (currency.Id == _services.StoreContext.CurrentStore.PrimaryStoreCurrencyId); + } + if (liveRates) { try @@ -153,7 +154,7 @@ public ActionResult List(bool liveRates = false) public ActionResult ApplyRate(string currencyCode, decimal rate) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); Currency currency = _currencyService.GetCurrencyByCode(currencyCode); @@ -169,19 +170,19 @@ public ActionResult ApplyRate(string currencyCode, decimal rate) [HttpPost] public ActionResult Save(FormCollection formValues) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); _currencySettings.ActiveExchangeRateProviderSystemName = formValues["exchangeRateProvider"]; _currencySettings.AutoUpdateEnabled = formValues["autoUpdateEnabled"].Equals("false") ? false : true; - _settingService.SaveSetting(_currencySettings); + _services.Settings.SaveSetting(_currencySettings); return RedirectToAction("List", "Currency"); } [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult List(GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); var currencies = _currencyService.GetAllCurrencies(true); @@ -198,21 +199,21 @@ public ActionResult List(GridCommand command) public ActionResult MarkAsPrimaryExchangeRateCurrency(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); _currencySettings.PrimaryExchangeRateCurrencyId = id; - _settingService.SaveSetting(_currencySettings); + _services.Settings.SaveSetting(_currencySettings); return RedirectToAction("List"); } public ActionResult MarkAsPrimaryStoreCurrency(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); - _currencySettings.PrimaryStoreCurrencyId = id; - _settingService.SaveSetting(_currencySettings); + //_currencySettings.PrimaryStoreCurrencyId = id; + //_services.Settings.SaveSetting(_currencySettings); return RedirectToAction("List"); } @@ -222,7 +223,7 @@ public ActionResult MarkAsPrimaryStoreCurrency(int id) public ActionResult Create() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); var model = new CurrencyModel(); @@ -239,7 +240,7 @@ public ActionResult Create() [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult Create(CurrencyModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); if (ModelState.IsValid) @@ -256,7 +257,7 @@ public ActionResult Create(CurrencyModel model, bool continueEditing) //Stores _storeMappingService.SaveStoreMappings(currency, model.SelectedStoreIds); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Currencies.Added")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Currencies.Added")); return continueEditing ? RedirectToAction("Edit", new { id = currency.Id }) : RedirectToAction("List"); } @@ -270,7 +271,7 @@ public ActionResult Create(CurrencyModel model, bool continueEditing) public ActionResult Edit(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); var currency = _currencyService.GetCurrencyById(id); @@ -304,7 +305,7 @@ public ActionResult Edit(int id) [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult Edit(CurrencyModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); var currency = _currencyService.GetCurrencyById(model.Id); @@ -324,7 +325,7 @@ public ActionResult Edit(CurrencyModel model, bool continueEditing) //Stores _storeMappingService.SaveStoreMappings(currency, model.SelectedStoreIds); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Currencies.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Currencies.Updated")); return continueEditing ? RedirectToAction("Edit", new { id = currency.Id }) : RedirectToAction("List"); } @@ -340,7 +341,7 @@ public ActionResult Edit(CurrencyModel model, bool continueEditing) [HttpPost, ActionName("Delete")] public ActionResult DeleteConfirmed(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrencies)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); var currency = _currencyService.GetCurrencyById(id); @@ -349,15 +350,16 @@ public ActionResult DeleteConfirmed(int id) try { - if (currency.Id == _currencySettings.PrimaryStoreCurrencyId) - throw new SmartException(_localizationService.GetResource("Admin.Configuration.Currencies.CantDeletePrimary")); + // TODO + //if (currency.Id == _currencySettings.PrimaryStoreCurrencyId) + // throw new SmartException(_services.Localization.GetResource("Admin.Configuration.Currencies.CantDeletePrimary")); - if (currency.Id == _currencySettings.PrimaryExchangeRateCurrencyId) - throw new SmartException(_localizationService.GetResource("Admin.Configuration.Currencies.CantDeleteExchange")); + //if (currency.Id == _currencySettings.PrimaryExchangeRateCurrencyId) + // throw new SmartException(_services.Localization.GetResource("Admin.Configuration.Currencies.CantDeleteExchange")); _currencyService.DeleteCurrency(currency); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Currencies.Deleted")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Currencies.Deleted")); return RedirectToAction("List"); } catch (Exception exc) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/DiscountController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/DiscountController.cs index ff5d7b75ca..a12bea379e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/DiscountController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/DiscountController.cs @@ -2,22 +2,16 @@ using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Discounts; -using SmartStore.Core.Plugins; -using SmartStore.Core; -using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Discounts; +using SmartStore.Core.Logging; +using SmartStore.Services; using SmartStore.Services.Catalog; -using SmartStore.Services.Directory; using SmartStore.Services.Discounts; using SmartStore.Services.Helpers; -using SmartStore.Services.Localization; -using SmartStore.Core.Logging; using SmartStore.Services.Security; using SmartStore.Web.Framework.Controllers; -using Telerik.Web.Mvc; -using SmartStore.Core.ComponentModel; -using System.Collections.Generic; using SmartStore.Web.Framework.Plugins; +using Telerik.Web.Mvc; namespace SmartStore.Admin.Controllers { @@ -27,40 +21,33 @@ public class DiscountController : AdminControllerBase #region Fields private readonly IDiscountService _discountService; - private readonly ILocalizationService _localizationService; - private readonly IWebHelper _webHelper; private readonly IDateTimeHelper _dateTimeHelper; private readonly ICustomerActivityService _customerActivityService; - private readonly ICurrencyService _currencyService; private readonly ICategoryService _categoryService; private readonly IProductService _productService; - private readonly CurrencySettings _currencySettings; - private readonly IPermissionService _permissionService; private readonly PluginMediator _pluginMediator; + private readonly ICommonServices _services; #endregion #region Constructors - public DiscountController(IDiscountService discountService, - ILocalizationService localizationService, ICurrencyService currencyService, - ICategoryService categoryService, IProductService productService, - IWebHelper webHelper, IDateTimeHelper dateTimeHelper, - ICustomerActivityService customerActivityService, CurrencySettings currencySettings, - IPermissionService permissionService, - PluginMediator pluginMediator) + public DiscountController( + IDiscountService discountService, + ICategoryService categoryService, + IProductService productService, + IDateTimeHelper dateTimeHelper, + ICustomerActivityService customerActivityService, + PluginMediator pluginMediator, + ICommonServices services) { this._discountService = discountService; - this._localizationService = localizationService; - this._currencyService = currencyService; this._categoryService = categoryService; this._productService = productService; - this._webHelper = webHelper; this._dateTimeHelper = dateTimeHelper; this._customerActivityService = customerActivityService; - this._currencySettings = currencySettings; - this._permissionService = permissionService; this._pluginMediator = pluginMediator; + this._services = services; } #endregion @@ -76,7 +63,7 @@ public string GetRequirementUrlInternal(IDiscountRequirementRule discountRequire if (discount == null) throw new ArgumentNullException("discount"); - string url = string.Format("{0}{1}", _webHelper.GetStoreLocation(), discountRequirementRule.GetConfigurationUrl(discount.Id, discountRequirementId)); + string url = string.Format("{0}{1}", _services.WebHelper.GetStoreLocation(), discountRequirementRule.GetConfigurationUrl(discount.Id, discountRequirementId)); return url; } @@ -86,9 +73,10 @@ private void PrepareDiscountModel(DiscountModel model, Discount discount) if (model == null) throw new ArgumentNullException("model"); - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; - model.AvailableDiscountRequirementRules.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Promotions.Discounts.Requirements.DiscountRequirementType.Select"), Value = "" }); - var discountRules = _discountService.LoadAllDiscountRequirementRules(); + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; + model.AvailableDiscountRequirementRules.Add(new SelectListItem() { Text = _services.Localization.GetResource("Admin.Promotions.Discounts.Requirements.DiscountRequirementType.Select"), Value = "" }); + + var discountRules = _discountService.LoadAllDiscountRequirementRules(); foreach (var discountRule in discountRules) { model.AvailableDiscountRequirementRules.Add(new SelectListItem() @@ -156,7 +144,7 @@ public ActionResult Index() public ActionResult List() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); var discounts = _discountService.GetAllDiscounts(null, null, true); @@ -171,7 +159,7 @@ public ActionResult List() [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult List(GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); var discounts = _discountService.GetAllDiscounts(null, null, true); @@ -189,7 +177,7 @@ public ActionResult List(GridCommand command) //create public ActionResult Create() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); var model = new DiscountModel(); @@ -202,7 +190,7 @@ public ActionResult Create() [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult Create(DiscountModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); if (ModelState.IsValid) @@ -211,9 +199,9 @@ public ActionResult Create(DiscountModel model, bool continueEditing) _discountService.InsertDiscount(discount); //activity log - _customerActivityService.InsertActivity("AddNewDiscount", _localizationService.GetResource("ActivityLog.AddNewDiscount"), discount.Name); + _customerActivityService.InsertActivity("AddNewDiscount", _services.Localization.GetResource("ActivityLog.AddNewDiscount"), discount.Name); - NotifySuccess(_localizationService.GetResource("Admin.Promotions.Discounts.Added")); + NotifySuccess(_services.Localization.GetResource("Admin.Promotions.Discounts.Added")); return continueEditing ? RedirectToAction("Edit", new { id = discount.Id }) : RedirectToAction("List"); } @@ -225,7 +213,7 @@ public ActionResult Create(DiscountModel model, bool continueEditing) //edit public ActionResult Edit(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); var discount = _discountService.GetDiscountById(id); @@ -241,7 +229,7 @@ public ActionResult Edit(int id) [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult Edit(DiscountModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); var discount = _discountService.GetDiscountById(model.Id); @@ -280,9 +268,9 @@ public ActionResult Edit(DiscountModel model, bool continueEditing) } //activity log - _customerActivityService.InsertActivity("EditDiscount", _localizationService.GetResource("ActivityLog.EditDiscount"), discount.Name); + _customerActivityService.InsertActivity("EditDiscount", _services.Localization.GetResource("ActivityLog.EditDiscount"), discount.Name); - NotifySuccess(_localizationService.GetResource("Admin.Promotions.Discounts.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Promotions.Discounts.Updated")); return continueEditing ? RedirectToAction("Edit", discount.Id) : RedirectToAction("List"); } @@ -295,7 +283,7 @@ public ActionResult Edit(DiscountModel model, bool continueEditing) [HttpPost, ActionName("Delete")] public ActionResult DeleteConfirmed(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); var discount = _discountService.GetDiscountById(id); @@ -317,9 +305,9 @@ public ActionResult DeleteConfirmed(int id) _productService.UpdateHasDiscountsApplied(product); //activity log - _customerActivityService.InsertActivity("DeleteDiscount", _localizationService.GetResource("ActivityLog.DeleteDiscount"), discount.Name); + _customerActivityService.InsertActivity("DeleteDiscount", _services.Localization.GetResource("ActivityLog.DeleteDiscount"), discount.Name); - NotifySuccess(_localizationService.GetResource("Admin.Promotions.Discounts.Deleted")); + NotifySuccess(_services.Localization.GetResource("Admin.Promotions.Discounts.Deleted")); return RedirectToAction("List"); } @@ -330,7 +318,7 @@ public ActionResult DeleteConfirmed(int id) [AcceptVerbs(HttpVerbs.Get)] public ActionResult GetDiscountRequirementConfigurationUrl(string systemName, int discountId, int? discountRequirementId) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); if (String.IsNullOrEmpty(systemName)) @@ -350,7 +338,7 @@ public ActionResult GetDiscountRequirementConfigurationUrl(string systemName, in public ActionResult GetDiscountRequirementMetaInfo(int discountRequirementId, int discountId) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); var discount = _discountService.GetDiscountById(discountId); @@ -373,7 +361,7 @@ public ActionResult GetDiscountRequirementMetaInfo(int discountRequirementId, in public ActionResult DeleteDiscountRequirement(int discountRequirementId, int discountId) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); var discount = _discountService.GetDiscountById(discountId); @@ -396,7 +384,7 @@ public ActionResult DeleteDiscountRequirement(int discountRequirementId, int dis [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult UsageHistoryList(int discountId, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); var discount = _discountService.GetDiscountById(discountId); @@ -427,7 +415,7 @@ public ActionResult UsageHistoryList(int discountId, GridCommand command) [GridAction(EnableCustomBinding = true)] public ActionResult UsageHistoryDelete(int discountId, int id, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageDiscounts)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageDiscounts)) return AccessDeniedView(); var discount = _discountService.GetDiscountById(discountId); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/GiftCardController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/GiftCardController.cs index 17f6cc0416..0d2a1ef483 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/GiftCardController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/GiftCardController.cs @@ -2,14 +2,12 @@ using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Orders; -using SmartStore.Core; -using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Localization; +using SmartStore.Core.Logging; +using SmartStore.Services; using SmartStore.Services.Catalog; -using SmartStore.Services.Directory; using SmartStore.Services.Helpers; using SmartStore.Services.Localization; -using SmartStore.Core.Logging; using SmartStore.Services.Messages; using SmartStore.Services.Orders; using SmartStore.Services.Security; @@ -29,35 +27,31 @@ public class GiftCardController : AdminControllerBase private readonly IWorkflowMessageService _workflowMessageService; private readonly IDateTimeHelper _dateTimeHelper; private readonly LocalizationSettings _localizationSettings; - private readonly ICurrencyService _currencyService; - private readonly CurrencySettings _currencySettings; - private readonly ILocalizationService _localizationService; private readonly ILanguageService _languageService; private readonly ICustomerActivityService _customerActivityService; - private readonly IPermissionService _permissionService; + private readonly ICommonServices _services; #endregion #region Constructors public GiftCardController(IGiftCardService giftCardService, - IPriceFormatter priceFormatter, IWorkflowMessageService workflowMessageService, - IDateTimeHelper dateTimeHelper, LocalizationSettings localizationSettings, - ICurrencyService currencyService, CurrencySettings currencySettings, - ILocalizationService localizationService, ILanguageService languageService, - ICustomerActivityService customerActivityService, IPermissionService permissionService) + IPriceFormatter priceFormatter, + IWorkflowMessageService workflowMessageService, + IDateTimeHelper dateTimeHelper, + LocalizationSettings localizationSettings, + ILanguageService languageService, + ICustomerActivityService customerActivityService, + ICommonServices services) { this._giftCardService = giftCardService; this._priceFormatter = priceFormatter; this._workflowMessageService = workflowMessageService; this._dateTimeHelper = dateTimeHelper; this._localizationSettings = localizationSettings; - this._currencyService = currencyService; - this._currencySettings = currencySettings; - this._localizationService = localizationService; this._languageService = languageService; this._customerActivityService = customerActivityService; - this._permissionService = permissionService; + this._services = services; } #endregion @@ -72,7 +66,7 @@ public ActionResult Index() public ActionResult List() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageGiftCards)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageGiftCards)) return AccessDeniedView(); var model = new GiftCardListModel(); @@ -80,17 +74,17 @@ public ActionResult List() { Value = "0", Selected = true, - Text = _localizationService.GetResource("Common.All", logIfNotFound: false, defaultValue: "All") + Text = _services.Localization.GetResource("Common.All", logIfNotFound: false, defaultValue: "All") }); model.ActivatedList.Add(new SelectListItem() { Value = "1", - Text = _localizationService.GetResource("Common.Activated", logIfNotFound: false, defaultValue: "Activated") + Text = _services.Localization.GetResource("Common.Activated", logIfNotFound: false, defaultValue: "Activated") }); model.ActivatedList.Add(new SelectListItem() { Value = "2", - Text = _localizationService.GetResource("Common.Deactivated", logIfNotFound: false, defaultValue: "Deactivated") + Text = _services.Localization.GetResource("Common.Deactivated", logIfNotFound: false, defaultValue: "Deactivated") }); return View(model); } @@ -98,7 +92,7 @@ public ActionResult List() [GridAction(EnableCustomBinding = true)] public ActionResult GiftCardList(GridCommand command, GiftCardListModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageGiftCards)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageGiftCards)) return AccessDeniedView(); bool? isGiftCardActivated = null; @@ -127,11 +121,11 @@ public ActionResult GiftCardList(GridCommand command, GiftCardListModel model) public ActionResult Create() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageGiftCards)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageGiftCards)) return AccessDeniedView(); var model = new GiftCardModel(); - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; return View(model); } @@ -139,7 +133,7 @@ public ActionResult Create() [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] public ActionResult Create(GiftCardModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageGiftCards)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageGiftCards)) return AccessDeniedView(); if (ModelState.IsValid) @@ -149,20 +143,21 @@ public ActionResult Create(GiftCardModel model, bool continueEditing) _giftCardService.InsertGiftCard(giftCard); //activity log - _customerActivityService.InsertActivity("AddNewGiftCard", _localizationService.GetResource("ActivityLog.AddNewGiftCard"), giftCard.GiftCardCouponCode); + _customerActivityService.InsertActivity("AddNewGiftCard", _services.Localization.GetResource("ActivityLog.AddNewGiftCard"), giftCard.GiftCardCouponCode); - NotifySuccess(_localizationService.GetResource("Admin.GiftCards.Added")); + NotifySuccess(_services.Localization.GetResource("Admin.GiftCards.Added")); return continueEditing ? RedirectToAction("Edit", new { id = giftCard.Id }) : RedirectToAction("List"); } //If we got this far, something failed, redisplay form - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; + return View(model); } public ActionResult Edit(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageGiftCards)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageGiftCards)) return AccessDeniedView(); var giftCard = _giftCardService.GetGiftCardById(id); @@ -175,7 +170,7 @@ public ActionResult Edit(int id) model.RemainingAmountStr = _priceFormatter.FormatPrice(giftCard.GetGiftCardRemainingAmount(), true, false); model.AmountStr = _priceFormatter.FormatPrice(giftCard.Amount, true, false); model.CreatedOn = _dateTimeHelper.ConvertToUserTime(giftCard.CreatedOnUtc, DateTimeKind.Utc); - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; return View(model); } @@ -184,7 +179,7 @@ public ActionResult Edit(int id) [FormValueRequired("save", "save-continue")] public ActionResult Edit(GiftCardModel model, bool continueEditing) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageGiftCards)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageGiftCards)) return AccessDeniedView(); var giftCard = _giftCardService.GetGiftCardById(model.Id); @@ -193,7 +188,7 @@ public ActionResult Edit(GiftCardModel model, bool continueEditing) model.RemainingAmountStr = _priceFormatter.FormatPrice(giftCard.GetGiftCardRemainingAmount(), true, false); model.AmountStr = _priceFormatter.FormatPrice(giftCard.Amount, true, false); model.CreatedOn = _dateTimeHelper.ConvertToUserTime(giftCard.CreatedOnUtc, DateTimeKind.Utc); - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; if (ModelState.IsValid) { @@ -201,9 +196,9 @@ public ActionResult Edit(GiftCardModel model, bool continueEditing) _giftCardService.UpdateGiftCard(giftCard); //activity log - _customerActivityService.InsertActivity("EditGiftCard", _localizationService.GetResource("ActivityLog.EditGiftCard"), giftCard.GiftCardCouponCode); + _customerActivityService.InsertActivity("EditGiftCard", _services.Localization.GetResource("ActivityLog.EditGiftCard"), giftCard.GiftCardCouponCode); - NotifySuccess(_localizationService.GetResource("Admin.GiftCards.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.GiftCards.Updated")); return continueEditing ? RedirectToAction("Edit", giftCard.Id) : RedirectToAction("List"); } @@ -221,7 +216,7 @@ public ActionResult GenerateCouponCode() [FormValueRequired("notifyRecipient")] public ActionResult NotifyRecipient(GiftCardModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageGiftCards)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageGiftCards)) return AccessDeniedView(); var giftCard = _giftCardService.GetGiftCardById(model.Id); @@ -231,7 +226,7 @@ public ActionResult NotifyRecipient(GiftCardModel model) model.RemainingAmountStr = _priceFormatter.FormatPrice(giftCard.GetGiftCardRemainingAmount(), true, false); model.AmountStr = _priceFormatter.FormatPrice(giftCard.Amount, true, false); model.CreatedOn = _dateTimeHelper.ConvertToUserTime(giftCard.CreatedOnUtc, DateTimeKind.Utc); - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; try { @@ -272,7 +267,7 @@ public ActionResult NotifyRecipient(GiftCardModel model) [HttpPost, ActionName("Delete")] public ActionResult DeleteConfirmed(int id) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageGiftCards)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageGiftCards)) return AccessDeniedView(); var giftCard = _giftCardService.GetGiftCardById(id); @@ -283,9 +278,9 @@ public ActionResult DeleteConfirmed(int id) _giftCardService.DeleteGiftCard(giftCard); //activity log - _customerActivityService.InsertActivity("DeleteGiftCard", _localizationService.GetResource("ActivityLog.DeleteGiftCard"), giftCard.GiftCardCouponCode); + _customerActivityService.InsertActivity("DeleteGiftCard", _services.Localization.GetResource("ActivityLog.DeleteGiftCard"), giftCard.GiftCardCouponCode); - NotifySuccess(_localizationService.GetResource("Admin.GiftCards.Deleted")); + NotifySuccess(_services.Localization.GetResource("Admin.GiftCards.Deleted")); return RedirectToAction("List"); } @@ -293,7 +288,7 @@ public ActionResult DeleteConfirmed(int id) [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult UsageHistoryList(int giftCardId, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageGiftCards)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageGiftCards)) return AccessDeniedView(); var giftCard = _giftCardService.GetGiftCardById(giftCardId); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs index c4157b9b0a..06d9801b8e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs @@ -187,7 +187,7 @@ protected void PrepareOrderDetailsModel(OrderModel model, Order order) throw new ArgumentNullException("model"); var store = _storeService.GetStoreById(order.StoreId); - var primaryStoreCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + var primaryStoreCurrency = store.PrimaryStoreCurrency; model.Id = order.Id; model.OrderStatus = order.OrderStatus.GetLocalizedEnum(_localizationService, _workContext); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index c5fe38faec..feb12bf6c3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -649,7 +649,7 @@ protected void PrepareProductModel(ProductModel model, Product product, bool set model.ProductUrl = Url.RouteUrl("Product", new { SeName = product.GetSeName() }, Request.Url.Scheme); } - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode; model.BaseWeightIn = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name; model.BaseDimensionIn = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId).Name; @@ -3004,7 +3004,7 @@ protected void PreparePrintableProductsModel(PrintableProductsModel model, IList model.MerchantContactData = contactSettings; string dimension = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId).Name; - string currencyCode = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + string currencyCode = store.PrimaryStoreCurrency.CurrencyCode; foreach (var product in products) { diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs index 48bd56cf5f..e754b7f659 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs @@ -4,7 +4,6 @@ using System.Web.Mvc; using SmartStore.Admin.Models.Common; using SmartStore.Admin.Models.Settings; -using SmartStore.Core; using SmartStore.Core.Domain; using SmartStore.Core.Domain.Blogs; using SmartStore.Core.Domain.Catalog; @@ -22,8 +21,8 @@ using SmartStore.Core.Domain.Tax; using SmartStore.Core.Logging; using SmartStore.Core.Themes; +using SmartStore.Services; using SmartStore.Services.Common; -using SmartStore.Services.Configuration; using SmartStore.Services.Customers; using SmartStore.Services.Directory; using SmartStore.Services.Helpers; @@ -31,7 +30,6 @@ using SmartStore.Services.Media; using SmartStore.Services.Orders; using SmartStore.Services.Security; -using SmartStore.Services.Stores; using SmartStore.Services.Tax; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Controllers; @@ -47,30 +45,24 @@ public partial class SettingController : AdminControllerBase { #region Fields - private readonly ISettingService _settingService; - private readonly ICountryService _countryService; - private readonly IStateProvinceService _stateProvinceService; - private readonly IAddressService _addressService; - private readonly ITaxCategoryService _taxCategoryService; - private readonly ICurrencyService _currencyService; - private readonly IPictureService _pictureService; - private readonly ILocalizationService _localizationService; - private readonly IDateTimeHelper _dateTimeHelper; - private readonly IOrderService _orderService; - private readonly IEncryptionService _encryptionService; - private readonly IThemeRegistry _themeRegistry; - private readonly ICustomerService _customerService; - private readonly ICustomerActivityService _customerActivityService; - private readonly IPermissionService _permissionService; - private readonly IWebHelper _webHelper; - private readonly IFulltextService _fulltextService; - private readonly IMaintenanceService _maintenanceService; - private readonly IStoreService _storeService; - private readonly IWorkContext _workContext; + private readonly ICountryService _countryService; + private readonly IStateProvinceService _stateProvinceService; + private readonly IAddressService _addressService; + private readonly ITaxCategoryService _taxCategoryService; + private readonly IPictureService _pictureService; + private readonly IDateTimeHelper _dateTimeHelper; + private readonly IOrderService _orderService; + private readonly IEncryptionService _encryptionService; + private readonly IThemeRegistry _themeRegistry; + private readonly ICustomerService _customerService; + private readonly ICustomerActivityService _customerActivityService; + private readonly IFulltextService _fulltextService; + private readonly IMaintenanceService _maintenanceService; private readonly IGenericAttributeService _genericAttributeService; private readonly ILocalizedEntityService _localizedEntityService; private readonly ILanguageService _languageService; private readonly IDeliveryTimeService _deliveryTimesService; + private readonly ICommonServices _services; private StoreDependingSettingHelper _storeDependingSettings; @@ -78,45 +70,44 @@ public partial class SettingController : AdminControllerBase #region Constructors - public SettingController(ISettingService settingService, - ICountryService countryService, IStateProvinceService stateProvinceService, - IAddressService addressService, ITaxCategoryService taxCategoryService, - ICurrencyService currencyService, IPictureService pictureService, - ILocalizationService localizationService, IDateTimeHelper dateTimeHelper, - IOrderService orderService, IEncryptionService encryptionService, - IThemeRegistry themeRegistry, ICustomerService customerService, - ICustomerActivityService customerActivityService, IPermissionService permissionService, - IWebHelper webHelper, IFulltextService fulltextService, - IMaintenanceService maintenanceService, IStoreService storeService, - IWorkContext workContext, IGenericAttributeService genericAttributeService, + public SettingController( + ICountryService countryService, + IStateProvinceService stateProvinceService, + IAddressService addressService, + ITaxCategoryService taxCategoryService, + IPictureService pictureService, + IDateTimeHelper dateTimeHelper, + IOrderService orderService, + IEncryptionService encryptionService, + IThemeRegistry themeRegistry, + ICustomerService customerService, + ICustomerActivityService customerActivityService, + IFulltextService fulltextService, + IMaintenanceService maintenanceService, + IGenericAttributeService genericAttributeService, ILocalizedEntityService localizedEntityService, ILanguageService languageService, - IDeliveryTimeService deliveryTimesService) + IDeliveryTimeService deliveryTimesService, + ICommonServices services) { - this._settingService = settingService; this._countryService = countryService; this._stateProvinceService = stateProvinceService; this._addressService = addressService; this._taxCategoryService = taxCategoryService; - this._currencyService = currencyService; this._pictureService = pictureService; - this._localizationService = localizationService; this._dateTimeHelper = dateTimeHelper; this._orderService = orderService; this._encryptionService = encryptionService; this._themeRegistry = themeRegistry; this._customerService = customerService; this._customerActivityService = customerActivityService; - this._permissionService = permissionService; - this._webHelper = webHelper; this._fulltextService = fulltextService; this._maintenanceService = maintenanceService; - this._storeService = storeService; - this._workContext = workContext; this._genericAttributeService = genericAttributeService; this._localizedEntityService = localizedEntityService; this._languageService = languageService; this._deliveryTimesService = deliveryTimesService; + this._services = services; } #endregion  @@ -136,13 +127,13 @@ private StoreDependingSettingHelper StoreDependingSettings [ChildActionOnly] public ActionResult StoreScopeConfiguration() { - var allStores = _storeService.GetAllStores(); + var allStores = _services.StoreService.GetAllStores(); if (allStores.Count < 2) return Content(""); var model = new StoreScopeConfigurationModel() { - StoreId = this.GetActiveStoreScopeConfiguration(_storeService, _workContext) + StoreId = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext) }; foreach (var store in allStores) @@ -157,7 +148,7 @@ public ActionResult StoreScopeConfiguration() model.AllStores.Insert(0, new SelectListItem() { - Text = _localizationService.GetResource("Admin.Common.StoresAll"), + Text = _services.Localization.GetResource("Admin.Common.StoresAll"), Selected = (0 == model.StoreId), Value = Url.Action("ChangeStoreScopeConfiguration", "Setting", new { storeid = 0, returnUrl = Request.RawUrl }) }); @@ -167,16 +158,16 @@ public ActionResult StoreScopeConfiguration() public ActionResult ChangeStoreScopeConfiguration(int storeid, string returnUrl = "") { - var store = _storeService.GetStoreById(storeid); + var store = _services.StoreService.GetStoreById(storeid); if (store != null || storeid == 0) { - _genericAttributeService.SaveAttribute(_workContext.CurrentCustomer, + _genericAttributeService.SaveAttribute(_services.WorkContext.CurrentCustomer, SystemCustomerAttributeNames.AdminAreaStoreScopeConfiguration, storeid); } //url referrer if (String.IsNullOrEmpty(returnUrl)) - returnUrl = _webHelper.GetUrlReferrer(); + returnUrl = _services.WebHelper.GetUrlReferrer(); //home page if (String.IsNullOrEmpty(returnUrl)) @@ -187,38 +178,38 @@ public ActionResult ChangeStoreScopeConfiguration(int storeid, string returnUrl public ActionResult Blog() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var blogSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var blogSettings = _services.Settings.LoadSetting(storeScope); var model = blogSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(blogSettings, model, storeScope, _settingService); + StoreDependingSettings.GetOverrideKeys(blogSettings, model, storeScope, _services.Settings); return View(model); } [HttpPost] public ActionResult Blog(BlogSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var blogSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var blogSettings = _services.Settings.LoadSetting(storeScope); blogSettings = model.ToEntity(blogSettings); - StoreDependingSettings.UpdateSettings(blogSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(blogSettings, form, storeScope, _services.Settings); //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("Blog"); } @@ -227,15 +218,15 @@ public ActionResult Blog(BlogSettingsModel model, FormCollection form) public ActionResult Forum() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var forumSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var forumSettings = _services.Settings.LoadSetting(storeScope); var model = forumSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(forumSettings, model, storeScope, _settingService); + StoreDependingSettings.GetOverrideKeys(forumSettings, model, storeScope, _services.Settings); model.ForumEditorValues = forumSettings.ForumEditor.ToSelectList(); @@ -244,23 +235,23 @@ public ActionResult Forum() [HttpPost] public ActionResult Forum(ForumSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var forumSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var forumSettings = _services.Settings.LoadSetting(storeScope); forumSettings = model.ToEntity(forumSettings); - StoreDependingSettings.UpdateSettings(forumSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(forumSettings, form, storeScope, _services.Settings); //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("Forum"); } @@ -269,38 +260,38 @@ public ActionResult Forum(ForumSettingsModel model, FormCollection form) public ActionResult News() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var newsSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var newsSettings = _services.Settings.LoadSetting(storeScope); var model = newsSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(newsSettings, model, storeScope, _settingService); + StoreDependingSettings.GetOverrideKeys(newsSettings, model, storeScope, _services.Settings); return View(model); } [HttpPost] public ActionResult News(NewsSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var newsSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var newsSettings = _services.Settings.LoadSetting(storeScope); newsSettings = model.ToEntity(newsSettings); - StoreDependingSettings.UpdateSettings(newsSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(newsSettings, form, storeScope, _services.Settings); //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("News"); } @@ -309,18 +300,18 @@ public ActionResult News(NewsSettingsModel model, FormCollection form) public ActionResult Shipping() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var shippingSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var shippingSettings = _services.Settings.LoadSetting(storeScope); var model = shippingSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(shippingSettings, model, storeScope, _settingService); + StoreDependingSettings.GetOverrideKeys(shippingSettings, model, storeScope, _services.Settings); //shipping origin - if (storeScope > 0 && _settingService.SettingExists(shippingSettings, x => x.ShippingOriginAddressId, storeScope)) + if (storeScope > 0 && _services.Settings.SettingExists(shippingSettings, x => x.ShippingOriginAddressId, storeScope)) StoreDependingSettings.AddOverrideKey(shippingSettings, "ShippingOriginAddress"); var originAddress = shippingSettings.ShippingOriginAddressId > 0 @@ -351,7 +342,7 @@ public ActionResult Shipping() else { model.ShippingOriginAddress.AvailableStates.Add( - new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.OtherNonUS"), Value = "0" } + new SelectListItem() { Text = _services.Localization.GetResource("Admin.Address.OtherNonUS"), Value = "0" } ); } @@ -365,22 +356,22 @@ public ActionResult Shipping() [HttpPost] public ActionResult Shipping(ShippingSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var shippingSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var shippingSettings = _services.Settings.LoadSetting(storeScope); shippingSettings = model.ToEntity(shippingSettings); - StoreDependingSettings.UpdateSettings(shippingSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(shippingSettings, form, storeScope, _services.Settings); bool shippingOriginAddressOverride = StoreDependingSettings.IsOverrideChecked(shippingSettings, "ShippingOriginAddress", form); if (shippingOriginAddressOverride || storeScope == 0) { //update address - var addressId = _settingService.SettingExists(shippingSettings, x => x.ShippingOriginAddressId, storeScope) ? shippingSettings.ShippingOriginAddressId : 0; + var addressId = _services.Settings.SettingExists(shippingSettings, x => x.ShippingOriginAddressId, storeScope) ? shippingSettings.ShippingOriginAddressId : 0; var originAddress = _addressService.GetAddressById(addressId) ?? new Core.Domain.Common.Address() { CreatedOnUtc = DateTime.UtcNow }; @@ -393,22 +384,22 @@ public ActionResult Shipping(ShippingSettingsModel model, FormCollection form) _addressService.InsertAddress(originAddress); shippingSettings.ShippingOriginAddressId = originAddress.Id; - _settingService.SaveSetting(shippingSettings, x => x.ShippingOriginAddressId, storeScope, false); + _services.Settings.SaveSetting(shippingSettings, x => x.ShippingOriginAddressId, storeScope, false); } else { _addressService.DeleteAddress(shippingSettings.ShippingOriginAddressId); - _settingService.DeleteSetting(shippingSettings, x => x.ShippingOriginAddressId, storeScope); + _services.Settings.DeleteSetting(shippingSettings, x => x.ShippingOriginAddressId, storeScope); } //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("Shipping"); } @@ -417,15 +408,15 @@ public ActionResult Shipping(ShippingSettingsModel model, FormCollection form) public ActionResult Tax() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var taxSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var taxSettings = _services.Settings.LoadSetting(storeScope); var model = taxSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(taxSettings, model, storeScope, _settingService); + StoreDependingSettings.GetOverrideKeys(taxSettings, model, storeScope, _services.Settings); model.TaxBasedOnValues = taxSettings.TaxBasedOn.ToSelectList(); model.TaxDisplayTypeValues = taxSettings.TaxDisplayType.ToSelectList(); @@ -464,7 +455,7 @@ public ActionResult Tax() else model.DefaultTaxAddress = new AddressModel(); - if (storeScope > 0 && _settingService.SettingExists(taxSettings, x => x.DefaultTaxAddressId, storeScope)) + if (storeScope > 0 && _services.Settings.SettingExists(taxSettings, x => x.DefaultTaxAddressId, storeScope)) StoreDependingSettings.AddOverrideKey(taxSettings, "DefaultTaxAddress"); foreach (var c in _countryService.GetAllCountries(true)) @@ -488,7 +479,7 @@ public ActionResult Tax() else { model.DefaultTaxAddress.AvailableStates.Add( - new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.OtherNonUS"), Value = "0" } + new SelectListItem() { Text = _services.Localization.GetResource("Admin.Address.OtherNonUS"), Value = "0" } ); } model.DefaultTaxAddress.CountryEnabled = true; @@ -501,25 +492,25 @@ public ActionResult Tax() [HttpPost] public ActionResult Tax(TaxSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var taxSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var taxSettings = _services.Settings.LoadSetting(storeScope); taxSettings = model.ToEntity(taxSettings); - StoreDependingSettings.UpdateSettings(taxSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(taxSettings, form, storeScope, _services.Settings); bool defaultTaxAddressOverride = StoreDependingSettings.IsOverrideChecked(taxSettings, "DefaultTaxAddress", form); taxSettings.AllowCustomersToSelectTaxDisplayType = false; - _settingService.UpdateSetting(taxSettings, x => x.AllowCustomersToSelectTaxDisplayType, false, storeScope); + _services.Settings.UpdateSetting(taxSettings, x => x.AllowCustomersToSelectTaxDisplayType, false, storeScope); if (defaultTaxAddressOverride || storeScope == 0) { //update address - var addressId = _settingService.SettingExists(taxSettings, x => x.DefaultTaxAddressId, storeScope) ? taxSettings.DefaultTaxAddressId : 0; + var addressId = _services.Settings.SettingExists(taxSettings, x => x.DefaultTaxAddressId, storeScope) ? taxSettings.DefaultTaxAddressId : 0; var originAddress = _addressService.GetAddressById(addressId) ?? new Core.Domain.Common.Address() { CreatedOnUtc = DateTime.UtcNow }; @@ -532,22 +523,22 @@ public ActionResult Tax(TaxSettingsModel model, FormCollection form) _addressService.InsertAddress(originAddress); taxSettings.DefaultTaxAddressId = originAddress.Id; - _settingService.SaveSetting(taxSettings, x => x.DefaultTaxAddressId, storeScope, false); + _services.Settings.SaveSetting(taxSettings, x => x.DefaultTaxAddressId, storeScope, false); } else if (storeScope > 0) { _addressService.DeleteAddress(taxSettings.DefaultTaxAddressId); - _settingService.DeleteSetting(taxSettings, x => x.DefaultTaxAddressId, storeScope); + _services.Settings.DeleteSetting(taxSettings, x => x.DefaultTaxAddressId, storeScope); } //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("Tax"); } @@ -556,23 +547,23 @@ public ActionResult Tax(TaxSettingsModel model, FormCollection form) public ActionResult Catalog() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var catalogSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var catalogSettings = _services.Settings.LoadSetting(storeScope); var model = catalogSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(catalogSettings, model, storeScope, _settingService); + StoreDependingSettings.GetOverrideKeys(catalogSettings, model, storeScope, _services.Settings); model.AvailableSubCategoryDisplayTypes = catalogSettings.SubCategoryDisplayType.ToSelectList(); model.AvailableDefaultViewModes.Add( - new SelectListItem { Value = "grid", Text = _localizationService.GetResource("Common.Grid"), Selected = model.DefaultViewMode.IsCaseInsensitiveEqual("grid") } + new SelectListItem { Value = "grid", Text = _services.Localization.GetResource("Common.Grid"), Selected = model.DefaultViewMode.IsCaseInsensitiveEqual("grid") } ); model.AvailableDefaultViewModes.Add( - new SelectListItem { Value = "list", Text = _localizationService.GetResource("Common.List"), Selected = model.DefaultViewMode.IsCaseInsensitiveEqual("list") } + new SelectListItem { Value = "list", Text = _services.Localization.GetResource("Common.List"), Selected = model.DefaultViewMode.IsCaseInsensitiveEqual("list") } ); var deliveryTimes = _deliveryTimesService.GetAllDeliveryTimes(); @@ -591,23 +582,23 @@ public ActionResult Catalog() [HttpPost] public ActionResult Catalog(CatalogSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var catalogSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var catalogSettings = _services.Settings.LoadSetting(storeScope); catalogSettings = model.ToEntity(catalogSettings); - StoreDependingSettings.UpdateSettings(catalogSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(catalogSettings, form, storeScope, _services.Settings); //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("Catalog"); } @@ -615,54 +606,56 @@ public ActionResult Catalog(CatalogSettingsModel model, FormCollection form) public ActionResult RewardPoints() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var rewardPointsSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var rewardPointsSettings = _services.Settings.LoadSetting(storeScope); + var store = (storeScope == 0 ? _services.StoreContext.CurrentStore : _services.StoreService.GetStoreById(storeScope)); + var model = rewardPointsSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(rewardPointsSettings, model, storeScope, _settingService); + StoreDependingSettings.GetOverrideKeys(rewardPointsSettings, model, storeScope, _services.Settings); - if (storeScope > 0 && (_settingService.SettingExists(rewardPointsSettings, x => x.PointsForPurchases_Amount, storeScope) || - _settingService.SettingExists(rewardPointsSettings, x => x.PointsForPurchases_Points, storeScope))) + if (storeScope > 0 && (_services.Settings.SettingExists(rewardPointsSettings, x => x.PointsForPurchases_Amount, storeScope) || + _services.Settings.SettingExists(rewardPointsSettings, x => x.PointsForPurchases_Points, storeScope))) { StoreDependingSettings.AddOverrideKey(rewardPointsSettings, "PointsForPurchases_OverrideForStore"); } - var currencySettings = _settingService.LoadSetting(storeScope); - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = store.PrimaryStoreCurrency.CurrencyCode; return View(model); } + [HttpPost] public ActionResult RewardPoints(RewardPointsSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); if (ModelState.IsValid) { //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var rewardPointsSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var rewardPointsSettings = _services.Settings.LoadSetting(storeScope); rewardPointsSettings = model.ToEntity(rewardPointsSettings); - StoreDependingSettings.UpdateSettings(rewardPointsSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(rewardPointsSettings, form, storeScope, _services.Settings); bool pointsForPurchases = StoreDependingSettings.IsOverrideChecked(rewardPointsSettings, "PointsForPurchases", form); - _settingService.UpdateSetting(rewardPointsSettings, x => x.PointsForPurchases_Amount, pointsForPurchases, storeScope); - _settingService.UpdateSetting(rewardPointsSettings, x => x.PointsForPurchases_Points, pointsForPurchases, storeScope); + _services.Settings.UpdateSetting(rewardPointsSettings, x => x.PointsForPurchases_Amount, pointsForPurchases, storeScope); + _services.Settings.UpdateSetting(rewardPointsSettings, x => x.PointsForPurchases_Points, pointsForPurchases, storeScope); //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); } else { @@ -679,18 +672,19 @@ public ActionResult RewardPoints(RewardPointsSettingsModel model, FormCollection public ActionResult Order() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var orderSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var orderSettings = _services.Settings.LoadSetting(storeScope); + var store = (storeScope == 0 ? _services.StoreContext.CurrentStore : _services.StoreService.GetStoreById(storeScope)); + var model = orderSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(orderSettings, model, storeScope, _settingService); + StoreDependingSettings.GetOverrideKeys(orderSettings, model, storeScope, _services.Settings); - var currencySettings = _settingService.LoadSetting(storeScope); - model.PrimaryStoreCurrencyCode = _currencyService.GetCurrencyById(currencySettings.PrimaryStoreCurrencyId).CurrencyCode; + model.PrimaryStoreCurrencyCode = store.PrimaryStoreCurrency.CurrencyCode; //gift card activation/deactivation model.GiftCards_Activated_OrderStatuses = OrderStatus.Pending.ToSelectList(false).ToList(); @@ -710,20 +704,20 @@ public ActionResult Order() [HttpPost] public ActionResult Order(OrderSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); if (ModelState.IsValid) { //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var orderSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var orderSettings = _services.Settings.LoadSetting(storeScope); orderSettings = model.ToEntity(orderSettings); - StoreDependingSettings.UpdateSettings(orderSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(orderSettings, form, storeScope, _services.Settings); - _settingService.SaveSetting(orderSettings, x => x.ReturnRequestActions, 0, false); - _settingService.SaveSetting(orderSettings, x => x.ReturnRequestReasons, 0, false); + _services.Settings.SaveSetting(orderSettings, x => x.ReturnRequestActions, 0, false); + _services.Settings.SaveSetting(orderSettings, x => x.ReturnRequestReasons, 0, false); foreach (var localized in model.Locales) { @@ -732,17 +726,17 @@ public ActionResult Order(OrderSettingsModel model, FormCollection form) } if (model.GiftCards_Activated_OrderStatusId.HasValue) - _settingService.SaveSetting(orderSettings, x => x.GiftCards_Activated_OrderStatusId, 0, false); + _services.Settings.SaveSetting(orderSettings, x => x.GiftCards_Activated_OrderStatusId, 0, false); else - _settingService.DeleteSetting(orderSettings, x => x.GiftCards_Activated_OrderStatusId); + _services.Settings.DeleteSetting(orderSettings, x => x.GiftCards_Activated_OrderStatusId); if (model.GiftCards_Deactivated_OrderStatusId.HasValue) - _settingService.SaveSetting(orderSettings, x => x.GiftCards_Deactivated_OrderStatusId, 0, false); + _services.Settings.SaveSetting(orderSettings, x => x.GiftCards_Deactivated_OrderStatusId, 0, false); else - _settingService.DeleteSetting(orderSettings, x => x.GiftCards_Deactivated_OrderStatusId); + _services.Settings.DeleteSetting(orderSettings, x => x.GiftCards_Deactivated_OrderStatusId); //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //order ident if (model.OrderIdent.HasValue) @@ -758,9 +752,9 @@ public ActionResult Order(OrderSettingsModel model, FormCollection form) } //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); } else { @@ -779,15 +773,15 @@ public ActionResult Order(OrderSettingsModel model, FormCollection form) public ActionResult ShoppingCart() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var shoppingCartSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var shoppingCartSettings = _services.Settings.LoadSetting(storeScope); var model = shoppingCartSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(shoppingCartSettings, model, storeScope, _settingService); + StoreDependingSettings.GetOverrideKeys(shoppingCartSettings, model, storeScope, _services.Settings); return View(model); @@ -795,23 +789,23 @@ public ActionResult ShoppingCart() [HttpPost] public ActionResult ShoppingCart(ShoppingCartSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var shoppingCartSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var shoppingCartSettings = _services.Settings.LoadSetting(storeScope); shoppingCartSettings = model.ToEntity(shoppingCartSettings); - StoreDependingSettings.UpdateSettings(shoppingCartSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(shoppingCartSettings, form, storeScope, _services.Settings); //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("ShoppingCart"); } @@ -820,32 +814,32 @@ public ActionResult ShoppingCart(ShoppingCartSettingsModel model, FormCollection public ActionResult Media() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var mediaSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var mediaSettings = _services.Settings.LoadSetting(storeScope); var model = mediaSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(mediaSettings, model, storeScope, _settingService); + StoreDependingSettings.GetOverrideKeys(mediaSettings, model, storeScope, _services.Settings); model.PicturesStoredIntoDatabase = _pictureService.StoreInDb; var resKey = "Admin.Configuration.Settings.Media.PictureZoomType."; model.AvailablePictureZoomTypes.Add(new SelectListItem { - Text = _localizationService.GetResource(resKey + "Window"), + Text = _services.Localization.GetResource(resKey + "Window"), Value = "window", Selected = model.PictureZoomType.Equals("window") }); model.AvailablePictureZoomTypes.Add(new SelectListItem { - Text = _localizationService.GetResource(resKey + "Inner"), + Text = _services.Localization.GetResource(resKey + "Inner"), Value = "inner", Selected = model.PictureZoomType.Equals("inner") }); model.AvailablePictureZoomTypes.Add(new SelectListItem { - Text = _localizationService.GetResource(resKey + "Lens"), + Text = _services.Localization.GetResource(resKey + "Lens"), Value = "lens", Selected = model.PictureZoomType.Equals("lens") }); @@ -856,38 +850,38 @@ public ActionResult Media() [FormValueRequired("save")] public ActionResult Media(MediaSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var mediaSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var mediaSettings = _services.Settings.LoadSetting(storeScope); mediaSettings = model.ToEntity(mediaSettings); - StoreDependingSettings.UpdateSettings(mediaSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(mediaSettings, form, storeScope, _services.Settings); //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("Media"); } [HttpPost, ActionName("Media")] [FormValueRequired("change-picture-storage")] public ActionResult ChangePictureStorage() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); _pictureService.StoreInDb = !_pictureService.StoreInDb; //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("Media"); } @@ -895,26 +889,26 @@ public ActionResult ChangePictureStorage() public ActionResult CustomerUser() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); StoreDependingSettings.CreateViewDataObject(storeScope); - var customerSettings = _settingService.LoadSetting(storeScope); - var addressSettings = _settingService.LoadSetting(storeScope); - var dateTimeSettings = _settingService.LoadSetting(storeScope); - var externalAuthenticationSettings = _settingService.LoadSetting(storeScope); + var customerSettings = _services.Settings.LoadSetting(storeScope); + var addressSettings = _services.Settings.LoadSetting(storeScope); + var dateTimeSettings = _services.Settings.LoadSetting(storeScope); + var externalAuthenticationSettings = _services.Settings.LoadSetting(storeScope); //merge settings var model = new CustomerUserSettingsModel(); model.CustomerSettings = customerSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(customerSettings, model.CustomerSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(customerSettings, model.CustomerSettings, storeScope, _services.Settings, false); model.AddressSettings = addressSettings.ToModel(); - StoreDependingSettings.GetOverrideKeys(addressSettings, model.AddressSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(addressSettings, model.AddressSettings, storeScope, _services.Settings, false); model.DateTimeSettings.AllowCustomersToSetTimeZone = dateTimeSettings.AllowCustomersToSetTimeZone; model.DateTimeSettings.DefaultStoreTimeZoneId = _dateTimeHelper.DefaultStoreTimeZone.Id; @@ -928,52 +922,52 @@ public ActionResult CustomerUser() }); } - StoreDependingSettings.GetOverrideKeys(dateTimeSettings, model.DateTimeSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(dateTimeSettings, model.DateTimeSettings, storeScope, _services.Settings, false); model.ExternalAuthenticationSettings.AutoRegisterEnabled = externalAuthenticationSettings.AutoRegisterEnabled; - StoreDependingSettings.GetOverrideKeys(externalAuthenticationSettings, model.ExternalAuthenticationSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(externalAuthenticationSettings, model.ExternalAuthenticationSettings, storeScope, _services.Settings, false); return View(model); } [HttpPost] public ActionResult CustomerUser(CustomerUserSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); - var customerSettings = _settingService.LoadSetting(storeScope); + var customerSettings = _services.Settings.LoadSetting(storeScope); customerSettings = model.CustomerSettings.ToEntity(customerSettings); - StoreDependingSettings.UpdateSettings(customerSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(customerSettings, form, storeScope, _services.Settings); - _settingService.SaveSetting(customerSettings, x => x.DefaultPasswordFormat, 0, false); + _services.Settings.SaveSetting(customerSettings, x => x.DefaultPasswordFormat, 0, false); - var addressSettings = _settingService.LoadSetting(storeScope); + var addressSettings = _services.Settings.LoadSetting(storeScope); addressSettings = model.AddressSettings.ToEntity(addressSettings); - StoreDependingSettings.UpdateSettings(addressSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(addressSettings, form, storeScope, _services.Settings); - var dateTimeSettings = _settingService.LoadSetting(storeScope); + var dateTimeSettings = _services.Settings.LoadSetting(storeScope); dateTimeSettings.DefaultStoreTimeZoneId = model.DateTimeSettings.DefaultStoreTimeZoneId; dateTimeSettings.AllowCustomersToSetTimeZone = model.DateTimeSettings.AllowCustomersToSetTimeZone; - StoreDependingSettings.UpdateSettings(dateTimeSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(dateTimeSettings, form, storeScope, _services.Settings); - var externalAuthenticationSettings = _settingService.LoadSetting(storeScope); + var externalAuthenticationSettings = _services.Settings.LoadSetting(storeScope); externalAuthenticationSettings.AutoRegisterEnabled = model.ExternalAuthenticationSettings.AutoRegisterEnabled; - StoreDependingSettings.UpdateSettings(externalAuthenticationSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(externalAuthenticationSettings, form, storeScope, _services.Settings); //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("CustomerUser"); } @@ -984,26 +978,26 @@ public ActionResult CustomerUser(CustomerUserSettingsModel model, FormCollection public ActionResult GeneralCommon() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //set page timeout to 5 minutes this.Server.ScriptTimeout = 300; var model = new GeneralCommonSettingsModel(); - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); StoreDependingSettings.CreateViewDataObject(storeScope); //store information - var storeInformationSettings = _settingService.LoadSetting(storeScope); + var storeInformationSettings = _services.Settings.LoadSetting(storeScope); model.StoreInformationSettings.StoreClosed = storeInformationSettings.StoreClosed; model.StoreInformationSettings.StoreClosedAllowForAdmins = storeInformationSettings.StoreClosedAllowForAdmins; - StoreDependingSettings.GetOverrideKeys(storeInformationSettings, model.StoreInformationSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(storeInformationSettings, model.StoreInformationSettings, storeScope, _services.Settings, false); //seo settings - var seoSettings = _settingService.LoadSetting(storeScope); + var seoSettings = _services.Settings.LoadSetting(storeScope); model.SeoSettings.PageTitleSeoAdjustment = seoSettings.PageTitleSeoAdjustment; model.SeoSettings.PageTitleSeparator = seoSettings.PageTitleSeparator; model.SeoSettings.DefaultTitle = seoSettings.DefaultTitle; @@ -1013,10 +1007,10 @@ public ActionResult GeneralCommon() model.SeoSettings.CanonicalUrlsEnabled = seoSettings.CanonicalUrlsEnabled; model.SeoSettings.CanonicalHostNameRule = seoSettings.CanonicalHostNameRule; - StoreDependingSettings.GetOverrideKeys(seoSettings, model.SeoSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(seoSettings, model.SeoSettings, storeScope, _services.Settings, false); //security settings - var securitySettings = _settingService.LoadSetting(storeScope); + var securitySettings = _services.Settings.LoadSetting(storeScope); model.SecuritySettings.EncryptionKey = securitySettings.EncryptionKey; if (securitySettings.AdminAreaAllowedIpAddresses != null) { @@ -1029,7 +1023,7 @@ public ActionResult GeneralCommon() } model.SecuritySettings.HideAdminMenuItemsBasedOnPermissions = securitySettings.HideAdminMenuItemsBasedOnPermissions; - var captchaSettings = _settingService.LoadSetting(storeScope); + var captchaSettings = _services.Settings.LoadSetting(storeScope); model.CaptchaSettings.Enabled = captchaSettings.Enabled; model.CaptchaSettings.ShowOnLoginPage = captchaSettings.ShowOnLoginPage; model.CaptchaSettings.ShowOnRegistrationPage = captchaSettings.ShowOnRegistrationPage; @@ -1043,18 +1037,18 @@ public ActionResult GeneralCommon() model.CaptchaSettings.ReCaptchaPublicKey = captchaSettings.ReCaptchaPublicKey; model.CaptchaSettings.ReCaptchaPrivateKey = captchaSettings.ReCaptchaPrivateKey; - StoreDependingSettings.GetOverrideKeys(captchaSettings, model.CaptchaSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(captchaSettings, model.CaptchaSettings, storeScope, _services.Settings, false); //PDF settings - var pdfSettings = _settingService.LoadSetting(storeScope); + var pdfSettings = _services.Settings.LoadSetting(storeScope); model.PdfSettings.Enabled = pdfSettings.Enabled; model.PdfSettings.LetterPageSizeEnabled = pdfSettings.LetterPageSizeEnabled; model.PdfSettings.LogoPictureId = pdfSettings.LogoPictureId; - StoreDependingSettings.GetOverrideKeys(pdfSettings, model.PdfSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(pdfSettings, model.PdfSettings, storeScope, _services.Settings, false); //localization - var localizationSettings = _settingService.LoadSetting(storeScope); + var localizationSettings = _services.Settings.LoadSetting(storeScope); model.LocalizationSettings.UseImagesForLanguageSelection = localizationSettings.UseImagesForLanguageSelection; model.LocalizationSettings.SeoFriendlyUrlsForLanguagesEnabled = localizationSettings.SeoFriendlyUrlsForLanguagesEnabled; model.LocalizationSettings.LoadAllLocaleRecordsOnStartup = localizationSettings.LoadAllLocaleRecordsOnStartup; @@ -1062,17 +1056,17 @@ public ActionResult GeneralCommon() model.LocalizationSettings.InvalidLanguageRedirectBehaviour = localizationSettings.InvalidLanguageRedirectBehaviour; model.LocalizationSettings.DetectBrowserUserLanguage = localizationSettings.DetectBrowserUserLanguage; - StoreDependingSettings.GetOverrideKeys(localizationSettings, model.LocalizationSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(localizationSettings, model.LocalizationSettings, storeScope, _services.Settings, false); //full-text support - var commonSettings = _settingService.LoadSetting(storeScope); + var commonSettings = _services.Settings.LoadSetting(storeScope); model.FullTextSettings.Supported = _fulltextService.IsFullTextSupported(); model.FullTextSettings.Enabled = commonSettings.UseFullTextSearch; model.FullTextSettings.SearchMode = commonSettings.FullTextMode; model.FullTextSettings.SearchModeValues = commonSettings.FullTextMode.ToSelectList(); //company information - var companySettings = _settingService.LoadSetting(storeScope); + var companySettings = _services.Settings.LoadSetting(storeScope); model.CompanyInformationSettings.CompanyName = companySettings.CompanyName; model.CompanyInformationSettings.Salutation = companySettings.Salutation; model.CompanyInformationSettings.Title = companySettings.Title; @@ -1090,7 +1084,7 @@ public ActionResult GeneralCommon() model.CompanyInformationSettings.CommercialRegister = companySettings.CommercialRegister; model.CompanyInformationSettings.TaxNumber = companySettings.TaxNumber; - StoreDependingSettings.GetOverrideKeys(companySettings, model.CompanyInformationSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(companySettings, model.CompanyInformationSettings, storeScope, _services.Settings, false); foreach (var c in _countryService.GetAllCountries(true)) { @@ -1118,7 +1112,7 @@ public ActionResult GeneralCommon() ResToSelectListItem("Admin.Configuration.Settings.GeneralCommon.CompanyInformationSettings.ManagementDescriptions.ManagingPartner")); //contact data - var contactDataSettings = _settingService.LoadSetting(storeScope); + var contactDataSettings = _services.Settings.LoadSetting(storeScope); model.ContactDataSettings.CompanyTelephoneNumber = contactDataSettings.CompanyTelephoneNumber; model.ContactDataSettings.HotlineTelephoneNumber = contactDataSettings.HotlineTelephoneNumber; model.ContactDataSettings.MobileTelephoneNumber = contactDataSettings.MobileTelephoneNumber; @@ -1128,10 +1122,10 @@ public ActionResult GeneralCommon() model.ContactDataSettings.SupportEmailAddress = contactDataSettings.SupportEmailAddress; model.ContactDataSettings.ContactEmailAddress = contactDataSettings.ContactEmailAddress; - StoreDependingSettings.GetOverrideKeys(contactDataSettings, model.ContactDataSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(contactDataSettings, model.ContactDataSettings, storeScope, _services.Settings, false); //bank connection - var bankConnectionSettings = _settingService.LoadSetting(storeScope); + var bankConnectionSettings = _services.Settings.LoadSetting(storeScope); model.BankConnectionSettings.Bankname = bankConnectionSettings.Bankname; model.BankConnectionSettings.Bankcode = bankConnectionSettings.Bankcode; model.BankConnectionSettings.AccountNumber = bankConnectionSettings.AccountNumber; @@ -1139,10 +1133,10 @@ public ActionResult GeneralCommon() model.BankConnectionSettings.Iban = bankConnectionSettings.Iban; model.BankConnectionSettings.Bic = bankConnectionSettings.Bic; - StoreDependingSettings.GetOverrideKeys(bankConnectionSettings, model.BankConnectionSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(bankConnectionSettings, model.BankConnectionSettings, storeScope, _services.Settings, false); //social - var socialSettings = _settingService.LoadSetting(storeScope); + var socialSettings = _services.Settings.LoadSetting(storeScope); model.SocialSettings.ShowSocialLinksInFooter = socialSettings.ShowSocialLinksInFooter; model.SocialSettings.FacebookLink = socialSettings.FacebookLink; model.SocialSettings.GooglePlusLink = socialSettings.GooglePlusLink; @@ -1150,14 +1144,14 @@ public ActionResult GeneralCommon() model.SocialSettings.PinterestLink = socialSettings.PinterestLink; model.SocialSettings.YoutubeLink = socialSettings.YoutubeLink; - StoreDependingSettings.GetOverrideKeys(socialSettings, model.SocialSettings, storeScope, _settingService, false); + StoreDependingSettings.GetOverrideKeys(socialSettings, model.SocialSettings, storeScope, _services.Settings, false); return View(model); } private SelectListItem ResToSelectListItem(string resourceKey) { - string value = _localizationService.GetResource(resourceKey).EmptyNull(); + string value = _services.Localization.GetResource(resourceKey).EmptyNull(); return new SelectListItem() { Text = value, Value = value }; } @@ -1165,21 +1159,21 @@ private SelectListItem ResToSelectListItem(string resourceKey) [FormValueRequired("save")] public ActionResult GeneralCommon(GeneralCommonSettingsModel model, FormCollection form) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); //store information - var storeInformationSettings = _settingService.LoadSetting(storeScope); + var storeInformationSettings = _services.Settings.LoadSetting(storeScope); storeInformationSettings.StoreClosed = model.StoreInformationSettings.StoreClosed; storeInformationSettings.StoreClosedAllowForAdmins = model.StoreInformationSettings.StoreClosedAllowForAdmins; - StoreDependingSettings.UpdateSettings(storeInformationSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(storeInformationSettings, form, storeScope, _services.Settings); //seo settings - var seoSettings = _settingService.LoadSetting(storeScope); + var seoSettings = _services.Settings.LoadSetting(storeScope); seoSettings.PageTitleSeparator = model.SeoSettings.PageTitleSeparator; seoSettings.PageTitleSeoAdjustment = model.SeoSettings.PageTitleSeoAdjustment; seoSettings.DefaultTitle = model.SeoSettings.DefaultTitle; @@ -1189,10 +1183,10 @@ public ActionResult GeneralCommon(GeneralCommonSettingsModel model, FormCollecti seoSettings.CanonicalUrlsEnabled = model.SeoSettings.CanonicalUrlsEnabled; seoSettings.CanonicalHostNameRule = model.SeoSettings.CanonicalHostNameRule; - StoreDependingSettings.UpdateSettings(seoSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(seoSettings, form, storeScope, _services.Settings); //security settings - var securitySettings = _settingService.LoadSetting(storeScope); + var securitySettings = _services.Settings.LoadSetting(storeScope); if (securitySettings.AdminAreaAllowedIpAddresses == null) securitySettings.AdminAreaAllowedIpAddresses = new List(); securitySettings.AdminAreaAllowedIpAddresses.Clear(); @@ -1205,9 +1199,9 @@ public ActionResult GeneralCommon(GeneralCommonSettingsModel model, FormCollecti } } securitySettings.HideAdminMenuItemsBasedOnPermissions = model.SecuritySettings.HideAdminMenuItemsBasedOnPermissions; - _settingService.SaveSetting(securitySettings); + _services.Settings.SaveSetting(securitySettings); - var captchaSettings = _settingService.LoadSetting(storeScope); + var captchaSettings = _services.Settings.LoadSetting(storeScope); captchaSettings.Enabled = model.CaptchaSettings.Enabled; captchaSettings.ShowOnLoginPage = model.CaptchaSettings.ShowOnLoginPage; captchaSettings.ShowOnRegistrationPage = model.CaptchaSettings.ShowOnRegistrationPage; @@ -1221,51 +1215,51 @@ public ActionResult GeneralCommon(GeneralCommonSettingsModel model, FormCollecti captchaSettings.ReCaptchaPublicKey = model.CaptchaSettings.ReCaptchaPublicKey; captchaSettings.ReCaptchaPrivateKey = model.CaptchaSettings.ReCaptchaPrivateKey; - StoreDependingSettings.UpdateSettings(captchaSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(captchaSettings, form, storeScope, _services.Settings); if (captchaSettings.Enabled && (String.IsNullOrWhiteSpace(captchaSettings.ReCaptchaPublicKey) || String.IsNullOrWhiteSpace(captchaSettings.ReCaptchaPrivateKey))) { - NotifyError(_localizationService.GetResource("Admin.Configuration.Settings.GeneralCommon.CaptchaEnabledNoKeys")); + NotifyError(_services.Localization.GetResource("Admin.Configuration.Settings.GeneralCommon.CaptchaEnabledNoKeys")); } //PDF settings - var pdfSettings = _settingService.LoadSetting(storeScope); + var pdfSettings = _services.Settings.LoadSetting(storeScope); pdfSettings.Enabled = model.PdfSettings.Enabled; pdfSettings.LetterPageSizeEnabled = model.PdfSettings.LetterPageSizeEnabled; pdfSettings.LogoPictureId = model.PdfSettings.LogoPictureId; - StoreDependingSettings.UpdateSettings(pdfSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(pdfSettings, form, storeScope, _services.Settings); //localization settings - var localizationSettings = _settingService.LoadSetting(storeScope); + var localizationSettings = _services.Settings.LoadSetting(storeScope); localizationSettings.LoadAllLocaleRecordsOnStartup = model.LocalizationSettings.LoadAllLocaleRecordsOnStartup; localizationSettings.DefaultLanguageRedirectBehaviour = model.LocalizationSettings.DefaultLanguageRedirectBehaviour; localizationSettings.InvalidLanguageRedirectBehaviour = model.LocalizationSettings.InvalidLanguageRedirectBehaviour; localizationSettings.UseImagesForLanguageSelection = model.LocalizationSettings.UseImagesForLanguageSelection; localizationSettings.DetectBrowserUserLanguage = model.LocalizationSettings.DetectBrowserUserLanguage; - StoreDependingSettings.UpdateSettings(localizationSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(localizationSettings, form, storeScope, _services.Settings); - _settingService.SaveSetting(localizationSettings, x => x.LoadAllLocaleRecordsOnStartup, 0, false); - _settingService.SaveSetting(localizationSettings, x => x.DefaultLanguageRedirectBehaviour, 0, false); - _settingService.SaveSetting(localizationSettings, x => x.InvalidLanguageRedirectBehaviour, 0, false); + _services.Settings.SaveSetting(localizationSettings, x => x.LoadAllLocaleRecordsOnStartup, 0, false); + _services.Settings.SaveSetting(localizationSettings, x => x.DefaultLanguageRedirectBehaviour, 0, false); + _services.Settings.SaveSetting(localizationSettings, x => x.InvalidLanguageRedirectBehaviour, 0, false); if (localizationSettings.SeoFriendlyUrlsForLanguagesEnabled != model.LocalizationSettings.SeoFriendlyUrlsForLanguagesEnabled) { localizationSettings.SeoFriendlyUrlsForLanguagesEnabled = model.LocalizationSettings.SeoFriendlyUrlsForLanguagesEnabled; - _settingService.SaveSetting(localizationSettings, x => x.SeoFriendlyUrlsForLanguagesEnabled, 0, false); + _services.Settings.SaveSetting(localizationSettings, x => x.SeoFriendlyUrlsForLanguagesEnabled, 0, false); System.Web.Routing.RouteTable.Routes.ClearSeoFriendlyUrlsCachedValueForRoutes(); // clear cached values of routes } //full-text - var commonSettings = _settingService.LoadSetting(storeScope); + var commonSettings = _services.Settings.LoadSetting(storeScope); commonSettings.FullTextMode = model.FullTextSettings.SearchMode; - _settingService.SaveSetting(commonSettings); + _services.Settings.SaveSetting(commonSettings); //company information - var companySettings = _settingService.LoadSetting(storeScope); + var companySettings = _services.Settings.LoadSetting(storeScope); companySettings.CompanyName = model.CompanyInformationSettings.CompanyName; companySettings.Salutation = model.CompanyInformationSettings.Salutation; companySettings.Title = model.CompanyInformationSettings.Title; @@ -1287,10 +1281,10 @@ public ActionResult GeneralCommon(GeneralCommonSettingsModel model, FormCollecti companySettings.CommercialRegister = model.CompanyInformationSettings.CommercialRegister; companySettings.TaxNumber = model.CompanyInformationSettings.TaxNumber; - StoreDependingSettings.UpdateSettings(companySettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(companySettings, form, storeScope, _services.Settings); //contact data - var contactDataSettings = _settingService.LoadSetting(storeScope); + var contactDataSettings = _services.Settings.LoadSetting(storeScope); contactDataSettings.CompanyTelephoneNumber = model.ContactDataSettings.CompanyTelephoneNumber; contactDataSettings.HotlineTelephoneNumber = model.ContactDataSettings.HotlineTelephoneNumber; contactDataSettings.MobileTelephoneNumber = model.ContactDataSettings.MobileTelephoneNumber; @@ -1300,10 +1294,10 @@ public ActionResult GeneralCommon(GeneralCommonSettingsModel model, FormCollecti contactDataSettings.SupportEmailAddress = model.ContactDataSettings.SupportEmailAddress; contactDataSettings.ContactEmailAddress = model.ContactDataSettings.ContactEmailAddress; - StoreDependingSettings.UpdateSettings(contactDataSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(contactDataSettings, form, storeScope, _services.Settings); //bank connection - var bankConnectionSettings = _settingService.LoadSetting(storeScope); + var bankConnectionSettings = _services.Settings.LoadSetting(storeScope); bankConnectionSettings.Bankname = model.BankConnectionSettings.Bankname; bankConnectionSettings.Bankcode = model.BankConnectionSettings.Bankcode; bankConnectionSettings.AccountNumber = model.BankConnectionSettings.AccountNumber; @@ -1311,10 +1305,10 @@ public ActionResult GeneralCommon(GeneralCommonSettingsModel model, FormCollecti bankConnectionSettings.Iban = model.BankConnectionSettings.Iban; bankConnectionSettings.Bic = model.BankConnectionSettings.Bic; - StoreDependingSettings.UpdateSettings(bankConnectionSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(bankConnectionSettings, form, storeScope, _services.Settings); //social - var socialSettings = _settingService.LoadSetting(storeScope); + var socialSettings = _services.Settings.LoadSetting(storeScope); socialSettings.ShowSocialLinksInFooter = model.SocialSettings.ShowSocialLinksInFooter; socialSettings.FacebookLink = model.SocialSettings.FacebookLink; socialSettings.GooglePlusLink = model.SocialSettings.GooglePlusLink; @@ -1322,29 +1316,29 @@ public ActionResult GeneralCommon(GeneralCommonSettingsModel model, FormCollecti socialSettings.PinterestLink = model.SocialSettings.PinterestLink; socialSettings.YoutubeLink = model.SocialSettings.YoutubeLink; - StoreDependingSettings.UpdateSettings(socialSettings, form, storeScope, _settingService); + StoreDependingSettings.UpdateSettings(socialSettings, form, storeScope, _services.Settings); //now clear settings cache - _settingService.ClearCache(); + _services.Settings.ClearCache(); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Updated")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Updated")); return RedirectToAction("GeneralCommon"); } [HttpPost, ActionName("GeneralCommon")] [FormValueRequired("changeencryptionkey")] public ActionResult ChangeEnryptionKey(GeneralCommonSettingsModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); //set page timeout to 5 minutes this.Server.ScriptTimeout = 300; - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var securitySettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var securitySettings = _services.Settings.LoadSetting(storeScope); try { @@ -1355,11 +1349,11 @@ public ActionResult ChangeEnryptionKey(GeneralCommonSettingsModel model) var newEncryptionPrivateKey = model.SecuritySettings.EncryptionKey; if (String.IsNullOrEmpty(newEncryptionPrivateKey) || newEncryptionPrivateKey.Length != 16) - throw new SmartException(_localizationService.GetResource("Admin.Configuration.Settings.GeneralCommon.EncryptionKey.TooShort")); + throw new SmartException(_services.Localization.GetResource("Admin.Configuration.Settings.GeneralCommon.EncryptionKey.TooShort")); string oldEncryptionPrivateKey = securitySettings.EncryptionKey; if (oldEncryptionPrivateKey == newEncryptionPrivateKey) - throw new SmartException(_localizationService.GetResource("Admin.Configuration.Settings.GeneralCommon.EncryptionKey.TheSame")); + throw new SmartException(_services.Localization.GetResource("Admin.Configuration.Settings.GeneralCommon.EncryptionKey.TheSame")); //update encrypted order info var orders = _orderService.LoadAllOrders(); @@ -1431,8 +1425,8 @@ public ActionResult ChangeEnryptionKey(GeneralCommonSettingsModel model) } securitySettings.EncryptionKey = newEncryptionPrivateKey; - _settingService.SaveSetting(securitySettings); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Settings.GeneralCommon.EncryptionKey.Changed")); + _services.Settings.SaveSetting(securitySettings); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Settings.GeneralCommon.EncryptionKey.Changed")); } catch (Exception exc) { @@ -1444,34 +1438,34 @@ public ActionResult ChangeEnryptionKey(GeneralCommonSettingsModel model) [FormValueRequired("togglefulltext")] public ActionResult ToggleFullText(GeneralCommonSettingsModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); - var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); - var commonSettings = _settingService.LoadSetting(storeScope); + var storeScope = this.GetActiveStoreScopeConfiguration(_services.StoreService, _services.WorkContext); + var commonSettings = _services.Settings.LoadSetting(storeScope); try { if (! _fulltextService.IsFullTextSupported()) - throw new SmartException(_localizationService.GetResource("Admin.Configuration.Settings.GeneralCommon.FullTextSettings.NotSupported")); + throw new SmartException(_services.Localization.GetResource("Admin.Configuration.Settings.GeneralCommon.FullTextSettings.NotSupported")); if (commonSettings.UseFullTextSearch) { _fulltextService.DisableFullText(); commonSettings.UseFullTextSearch = false; - _settingService.SaveSetting(commonSettings, storeScope); + _services.Settings.SaveSetting(commonSettings, storeScope); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Settings.GeneralCommon.FullTextSettings.Disabled")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Settings.GeneralCommon.FullTextSettings.Disabled")); } else { _fulltextService.EnableFullText(); commonSettings.UseFullTextSearch = true; - _settingService.SaveSetting(commonSettings, storeScope); + _services.Settings.SaveSetting(commonSettings, storeScope); - NotifySuccess(_localizationService.GetResource("Admin.Configuration.Settings.GeneralCommon.FullTextSettings.Enabled")); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Settings.GeneralCommon.FullTextSettings.Enabled")); } } catch (Exception exc) @@ -1487,7 +1481,7 @@ public ActionResult ToggleFullText(GeneralCommonSettingsModel model) //all settings public ActionResult AllSettings() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); return View(); @@ -1496,13 +1490,13 @@ public ActionResult AllSettings() [HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult AllSettings(GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); - var stores = _storeService.GetAllStores(); - string allStoresString = _localizationService.GetResource("Admin.Common.StoresAll"); + var stores = _services.StoreService.GetAllStores(); + string allStoresString = _services.Localization.GetResource("Admin.Common.StoresAll"); - var settings = _settingService + var settings = _services.Settings .GetAllSettings() .Select(x => { @@ -1544,7 +1538,7 @@ public ActionResult AllSettings(GridCommand command) [GridAction(EnableCustomBinding = true)] public ActionResult SettingUpdate(SettingModel model, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); if (model.Name != null) @@ -1559,9 +1553,9 @@ public ActionResult SettingUpdate(SettingModel model, GridCommand command) return Content(modelStateErrors.FirstOrDefault()); } - var setting = _settingService.GetSettingById(model.Id); + var setting = _services.Settings.GetSettingById(model.Id); if (setting == null) - return Content(_localizationService.GetResource("Admin.Configuration.Settings.NoneWithThatId")); + return Content(_services.Localization.GetResource("Admin.Configuration.Settings.NoneWithThatId")); var storeId = model.Store.ToInt(); //use Store property (not StoreId) because appropriate property is stored in it @@ -1569,20 +1563,20 @@ public ActionResult SettingUpdate(SettingModel model, GridCommand command) setting.StoreId != storeId) { //setting name or store has been changed - _settingService.DeleteSetting(setting); + _services.Settings.DeleteSetting(setting); } - _settingService.SetSetting(model.Name, model.Value, storeId); + _services.Settings.SetSetting(model.Name, model.Value, storeId); //activity log - _customerActivityService.InsertActivity("EditSettings", _localizationService.GetResource("ActivityLog.EditSettings")); + _customerActivityService.InsertActivity("EditSettings", _services.Localization.GetResource("ActivityLog.EditSettings")); return AllSettings(command); } [GridAction(EnableCustomBinding = true)] public ActionResult SettingAdd([Bind(Exclude = "Id")] SettingModel model, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); if (model.Name != null) @@ -1598,26 +1592,26 @@ public ActionResult SettingAdd([Bind(Exclude = "Id")] SettingModel model, GridCo } var storeId = model.Store.ToInt(); //use Store property (not StoreId) because appropriate property is stored in it - _settingService.SetSetting(model.Name, model.Value, storeId); + _services.Settings.SetSetting(model.Name, model.Value, storeId); //activity log - _customerActivityService.InsertActivity("AddNewSetting", _localizationService.GetResource("ActivityLog.AddNewSetting"), model.Name); + _customerActivityService.InsertActivity("AddNewSetting", _services.Localization.GetResource("ActivityLog.AddNewSetting"), model.Name); return AllSettings(command); } [GridAction(EnableCustomBinding = true)] public ActionResult SettingDelete(int id, GridCommand command) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings)) + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageSettings)) return AccessDeniedView(); - var setting = _settingService.GetSettingById(id); + var setting = _services.Settings.GetSettingById(id); if (setting == null) throw new ArgumentException("No setting found with the specified id"); - _settingService.DeleteSetting(setting); + _services.Settings.DeleteSetting(setting); //activity log - _customerActivityService.InsertActivity("DeleteSetting", _localizationService.GetResource("ActivityLog.DeleteSetting"), setting.Name); + _customerActivityService.InsertActivity("DeleteSetting", _services.Localization.GetResource("ActivityLog.DeleteSetting"), setting.Name); return AllSettings(command); } diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index 6ecce2697c..3049beedef 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -58,7 +58,6 @@ public class CatalogHelper private readonly CatalogSettings _catalogSettings; private readonly CustomerSettings _customerSettings; private readonly CaptchaSettings _captchaSettings; - private readonly CurrencySettings _currencySettings; private readonly TaxSettings _taxSettings; private readonly IMeasureService _measureService; private readonly IQuantityUnitService _quantityUnitService; @@ -91,7 +90,6 @@ public CatalogHelper( MediaSettings mediaSettings, CatalogSettings catalogSettings, CustomerSettings customerSettings, - CurrencySettings currencySettings, CaptchaSettings captchaSettings, IMeasureService measureService, IQuantityUnitService quantityUnitService, @@ -131,7 +129,6 @@ public CatalogHelper( this._catalogSettings = catalogSettings; this._customerSettings = customerSettings; this._captchaSettings = captchaSettings; - this._currencySettings = currencySettings; this._menuPublisher = _menuPublisher; this._httpRequest = httpRequest; this._urlHelper = urlHelper; @@ -1314,9 +1311,8 @@ from a in colorAttr.ProductVariantAttributeValues.Take(50) model.BasePriceInfo = minPriceProduct.GetBasePriceInfo(_localizationService, _priceFormatter); } - var addShippingPrice = _currencyService.ConvertCurrency( - minPriceProduct.AdditionalShippingCharge, - _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId), _services.WorkContext.WorkingCurrency); + var addShippingPrice = _currencyService.ConvertCurrency(minPriceProduct.AdditionalShippingCharge, + _services.StoreContext.CurrentStore.PrimaryStoreCurrency, _services.WorkContext.WorkingCurrency); if (addShippingPrice > 0 && displayPrices) { diff --git a/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs b/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs index 54df8e0005..69fb6c60a5 100644 --- a/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs +++ b/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs @@ -2114,7 +2114,6 @@ protected override void Alter(IList settings) .Alter(x => { - x.PrimaryStoreCurrencyId = base.DbContext.Set().Where(c => c.CurrencyCode == "EUR").Single().Id; x.PrimaryExchangeRateCurrencyId = base.DbContext.Set().Where(c => c.CurrencyCode == "EUR").Single().Id; }) diff --git a/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs b/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs index 597a33ef39..55ad836c04 100644 --- a/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs +++ b/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs @@ -549,12 +549,12 @@ public virtual void Seed(SmartObjectContext context) }); Populate("PopulatePictures", _data.Pictures()); + Populate("PopulateCurrencies", PopulateCurrencies); Populate("PopulateStores", PopulateStores); Populate("InstallLanguages", () => PopulateLanguage(_config.Language)); Populate("PopulateMeasureDimensions", _data.MeasureDimensions()); Populate("PopulateMeasureWeights", _data.MeasureWeights()); Populate("PopulateTaxCategories", PopulateTaxCategories); - Populate("PopulateCurrencies", PopulateCurrencies); Populate("PopulateCountriesAndStates", PopulateCountriesAndStates); Populate("PopulateShippingMethods", PopulateShippingMethods); Populate("PopulateDeliveryTimes", _data.DeliveryTimes()); diff --git a/src/Tests/SmartStore.Services.Tests/Catalog/PriceFormatterTests.cs b/src/Tests/SmartStore.Services.Tests/Catalog/PriceFormatterTests.cs index 73ab646fc2..9b1d90095f 100644 --- a/src/Tests/SmartStore.Services.Tests/Catalog/PriceFormatterTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Catalog/PriceFormatterTests.cs @@ -31,6 +31,7 @@ public class PriceFormatterTests : ServiceTest ILocalizationService _localizationService; TaxSettings _taxSettings; IPriceFormatter _priceFormatter; + IStoreContext _storeContext; [SetUp] public new void SetUp() @@ -64,14 +65,16 @@ public class PriceFormatterTests : ServiceTest CreatedOnUtc = DateTime.UtcNow, UpdatedOnUtc= DateTime.UtcNow }; + _currencyRepo = MockRepository.GenerateMock>(); _currencyRepo.Expect(x => x.Table).Return(new List() { currency1, currency2 }.AsQueryable()); _storeMappingService = MockRepository.GenerateMock(); + _storeContext = MockRepository.GenerateMock(); var pluginFinder = new PluginFinder(); _currencyService = new CurrencyService(cacheManager, _currencyRepo, _storeMappingService, - _currencySettings, pluginFinder, null, this.ProviderManager); + _currencySettings, pluginFinder, null, this.ProviderManager, _storeContext); _taxSettings = new TaxSettings(); diff --git a/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs index 8d87cc1d6b..3b1c680985 100644 --- a/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs @@ -14,6 +14,7 @@ using NUnit.Framework; using Rhino.Mocks; using SmartStore.Services.Stores; +using SmartStore.Core; namespace SmartStore.Services.Tests.Directory { @@ -25,6 +26,7 @@ public class CurrencyServiceTests : ServiceTest CurrencySettings _currencySettings; IEventPublisher _eventPublisher; ICurrencyService _currencyService; + IStoreContext _storeContext; Currency currencyUSD, currencyRUR, currencyEUR; @@ -70,6 +72,7 @@ public class CurrencyServiceTests : ServiceTest CreatedOnUtc = DateTime.UtcNow, UpdatedOnUtc = DateTime.UtcNow, }; + _currencyRepository = MockRepository.GenerateMock>(); _currencyRepository.Expect(x => x.Table).Return(new List() { currencyUSD, currencyEUR, currencyRUR }.AsQueryable()); _currencyRepository.Expect(x => x.GetById(currencyUSD.Id)).Return(currencyUSD); @@ -77,20 +80,19 @@ public class CurrencyServiceTests : ServiceTest _currencyRepository.Expect(x => x.GetById(currencyRUR.Id)).Return(currencyRUR); _storeMappingService = MockRepository.GenerateMock(); + _storeContext = MockRepository.GenerateMock(); var cacheManager = new NullCache(); _currencySettings = new CurrencySettings(); - _currencySettings.PrimaryStoreCurrencyId = currencyUSD.Id; _currencySettings.PrimaryExchangeRateCurrencyId = currencyEUR.Id; _eventPublisher = MockRepository.GenerateMock(); _eventPublisher.Expect(x => x.Publish(Arg.Is.Anything)); var pluginFinder = new PluginFinder(); - _currencyService = new CurrencyService(cacheManager, - _currencyRepository, _storeMappingService, - _currencySettings, pluginFinder, _eventPublisher, this.ProviderManager); + _currencyService = new CurrencyService(cacheManager, _currencyRepository, _storeMappingService, + _currencySettings, pluginFinder, _eventPublisher, this.ProviderManager, _storeContext); } [Test] From 8e751c8823b8f161dfc4cf975ed0d9ef6fcb01c6 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 27 Jun 2015 11:35:46 +0200 Subject: [PATCH 0197/1256] Refactored and removed CurrencySettings.PrimaryExchangeRateCurrencyId --- .../Domain/Directory/CurrencySettings.cs | 1 - .../Directory/CurrencyService.cs | 13 ++++---- .../Directory/ICurrencyService.cs | 6 ++-- .../Directory/UpdateExchangeRateTask.cs | 16 +++++----- .../Controllers/CommonController.cs | 7 +++-- .../Controllers/CurrencyController.cs | 6 ++-- .../Installation/DeDESeedData.cs | 30 ++++++------------- .../Directory/CurrencyServiceTests.cs | 14 ++++----- 8 files changed, 42 insertions(+), 51 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Domain/Directory/CurrencySettings.cs b/src/Libraries/SmartStore.Core/Domain/Directory/CurrencySettings.cs index 77caffa2b6..371d202799 100644 --- a/src/Libraries/SmartStore.Core/Domain/Directory/CurrencySettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Directory/CurrencySettings.cs @@ -4,7 +4,6 @@ namespace SmartStore.Core.Domain.Directory { public class CurrencySettings : ISettings { - public int PrimaryExchangeRateCurrencyId { get; set; } public string ActiveExchangeRateProviderSystemName { get; set; } public bool AutoUpdateEnabled { get; set; } public long LastUpdateTime { get; set; } diff --git a/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs b/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs index 25fcf7762c..b71220ab74 100644 --- a/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs +++ b/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs @@ -8,7 +8,6 @@ using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; using SmartStore.Core.Plugins; -using SmartStore.Services.Customers; using SmartStore.Services.Stores; namespace SmartStore.Services.Directory @@ -231,11 +230,13 @@ public virtual decimal ConvertCurrency(decimal amount, Currency sourceCurrencyCo /// /// Amount /// Source currency code + /// Store to get the primary exchange rate currency from /// Converted value - public virtual decimal ConvertToPrimaryExchangeRateCurrency(decimal amount, Currency sourceCurrencyCode) + public virtual decimal ConvertToPrimaryExchangeRateCurrency(decimal amount, Currency sourceCurrencyCode, Store store = null) { decimal result = amount; - var primaryExchangeRateCurrency = GetCurrencyById(_currencySettings.PrimaryExchangeRateCurrencyId); + var primaryExchangeRateCurrency = (store == null ? _storeContext.CurrentStore.PrimaryExchangeRateCurrency : store.PrimaryExchangeRateCurrency); + if (result != decimal.Zero && sourceCurrencyCode.Id != primaryExchangeRateCurrency.Id) { decimal exchangeRate = sourceCurrencyCode.Rate; @@ -251,11 +252,13 @@ public virtual decimal ConvertToPrimaryExchangeRateCurrency(decimal amount, Curr /// /// Amount /// Target currency code + /// Store to get the primary exchange rate currency from /// Converted value - public virtual decimal ConvertFromPrimaryExchangeRateCurrency(decimal amount, Currency targetCurrencyCode) + public virtual decimal ConvertFromPrimaryExchangeRateCurrency(decimal amount, Currency targetCurrencyCode, Store store = null) { decimal result = amount; - var primaryExchangeRateCurrency = GetCurrencyById(_currencySettings.PrimaryExchangeRateCurrencyId); + var primaryExchangeRateCurrency = (store == null ? _storeContext.CurrentStore.PrimaryExchangeRateCurrency : store.PrimaryExchangeRateCurrency); + if (result != decimal.Zero && targetCurrencyCode.Id != primaryExchangeRateCurrency.Id) { decimal exchangeRate = targetCurrencyCode.Rate; diff --git a/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs b/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs index f7285a3ecf..6c609d61eb 100644 --- a/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs +++ b/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs @@ -81,16 +81,18 @@ public partial interface ICurrencyService /// /// Amount /// Source currency code + /// Store to get the primary exchange rate currency from /// Converted value - decimal ConvertToPrimaryExchangeRateCurrency(decimal amount, Currency sourceCurrencyCode); + decimal ConvertToPrimaryExchangeRateCurrency(decimal amount, Currency sourceCurrencyCode, Store store = null); /// /// Converts from primary exchange rate currency /// /// Amount /// Target currency code + /// Store to get the primary exchange rate currency from /// Converted value - decimal ConvertFromPrimaryExchangeRateCurrency(decimal amount, Currency targetCurrencyCode); + decimal ConvertFromPrimaryExchangeRateCurrency(decimal amount, Currency targetCurrencyCode, Store store = null); /// /// Converts to primary store currency diff --git a/src/Libraries/SmartStore.Services/Directory/UpdateExchangeRateTask.cs b/src/Libraries/SmartStore.Services/Directory/UpdateExchangeRateTask.cs index a3d52f317c..0882af90c5 100644 --- a/src/Libraries/SmartStore.Services/Directory/UpdateExchangeRateTask.cs +++ b/src/Libraries/SmartStore.Services/Directory/UpdateExchangeRateTask.cs @@ -1,6 +1,5 @@ using System; using SmartStore.Core.Domain.Directory; -using SmartStore.Services.Configuration; using SmartStore.Services.Tasks; namespace SmartStore.Services.Directory @@ -11,15 +10,17 @@ namespace SmartStore.Services.Directory public partial class UpdateExchangeRateTask : ITask { private readonly ICurrencyService _currencyService; - private readonly ISettingService _settingService; private readonly CurrencySettings _currencySettings; + private readonly ICommonServices _services; - public UpdateExchangeRateTask(ICurrencyService currencyService, - ISettingService settingService, CurrencySettings currencySettings) + public UpdateExchangeRateTask( + ICurrencyService currencyService, + CurrencySettings currencySettings, + ICommonServices services) { this._currencyService = currencyService; - this._settingService = settingService; this._currencySettings = currencySettings; + this._services = services; } /// @@ -33,10 +34,11 @@ public void Execute(TaskExecutionContext ctx) long lastUpdateTimeTicks = _currencySettings.LastUpdateTime; DateTime lastUpdateTime = DateTime.FromBinary(lastUpdateTimeTicks); lastUpdateTime = DateTime.SpecifyKind(lastUpdateTime, DateTimeKind.Utc); + if (lastUpdateTime.AddHours(1) < DateTime.UtcNow) { //update rates each one hour - var exchangeRates = _currencyService.GetCurrencyLiveRates(_currencyService.GetCurrencyById(_currencySettings.PrimaryExchangeRateCurrencyId).CurrencyCode); + var exchangeRates = _currencyService.GetCurrencyLiveRates(_services.StoreContext.CurrentStore.PrimaryExchangeRateCurrency.CurrencyCode); foreach (var exchageRate in exchangeRates) { @@ -51,7 +53,7 @@ public void Execute(TaskExecutionContext ctx) //save new update time value _currencySettings.LastUpdateTime = DateTime.UtcNow.ToBinary(); - _settingService.SaveSetting(_currencySettings); + _services.Settings.SaveSetting(_currencySettings); } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs index ce27f22ebc..3abb1f2d5b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs @@ -496,9 +496,10 @@ public ActionResult SystemInfo() public ActionResult Warnings() { var model = new List(); + var store = _services.StoreContext.CurrentStore; //store URL - var storeUrl = _services.StoreContext.CurrentStore.Url.EnsureEndsWith("/"); + var storeUrl = store.Url.EnsureEndsWith("/"); if (storeUrl.HasValue() && (storeUrl.IsCaseInsensitiveEqual(_services.WebHelper.GetStoreLocation(false)) || storeUrl.IsCaseInsensitiveEqual(_services.WebHelper.GetStoreLocation(true)))) { model.Add(new SystemWarningModel @@ -550,7 +551,7 @@ public ActionResult Warnings() } //primary exchange rate currency - var perCurrency = _currencyService.Value.GetCurrencyById(_currencySettings.Value.PrimaryExchangeRateCurrencyId); + var perCurrency = store.PrimaryExchangeRateCurrency; if (perCurrency != null) { model.Add(new SystemWarningModel @@ -578,7 +579,7 @@ public ActionResult Warnings() } //primary store currency - var pscCurrency = _services.StoreContext.CurrentStore.PrimaryStoreCurrency; + var pscCurrency = store.PrimaryStoreCurrency; if (pscCurrency != null) { model.Add(new SystemWarningModel diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs index 4006edb580..57094f5593 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs @@ -122,7 +122,7 @@ public ActionResult List(bool liveRates = false) { try { - var primaryExchangeCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryExchangeRateCurrencyId); + var primaryExchangeCurrency = _services.StoreContext.CurrentStore.PrimaryExchangeRateCurrency; if (primaryExchangeCurrency == null) throw new SmartException("Primary exchange rate currency is not set"); @@ -202,8 +202,8 @@ public ActionResult MarkAsPrimaryExchangeRateCurrency(int id) if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); - _currencySettings.PrimaryExchangeRateCurrencyId = id; - _services.Settings.SaveSetting(_currencySettings); + //_currencySettings.PrimaryExchangeRateCurrencyId = id; + //_services.Settings.SaveSetting(_currencySettings); return RedirectToAction("List"); } diff --git a/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs b/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs index 69fb6c60a5..446edc1c2d 100644 --- a/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs +++ b/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs @@ -1,35 +1,28 @@ using System; -using System.Linq; -using System.Linq.Expressions; using System.Collections.Generic; -using System.IO; -using SmartStore.Core; +using System.Linq; using SmartStore.Core.Configuration; -using SmartStore.Core.Domain; using SmartStore.Core.Domain.Blogs; +using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Cms; using SmartStore.Core.Domain.Common; +using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Discounts; -using SmartStore.Core.Domain.Messages; using SmartStore.Core.Domain.Forums; using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Logging; +using SmartStore.Core.Domain.Media; +using SmartStore.Core.Domain.Messages; using SmartStore.Core.Domain.News; +using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Polls; -using SmartStore.Core.Domain.Tax; -using SmartStore.Core.Domain.Topics; using SmartStore.Core.Domain.Seo; -using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Shipping; -using SmartStore.Core.Domain.Tasks; -using SmartStore.Core.Domain.Payments; -using SmartStore.Core.Infrastructure; -using SmartStore.Core.Data; -using SmartStore.Core.Domain.Customers; -using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Stores; -using SmartStore.Core.Domain.Media; +using SmartStore.Core.Domain.Tasks; +using SmartStore.Core.Domain.Tax; +using SmartStore.Core.Domain.Topics; using SmartStore.Data.Setup; namespace SmartStore.Web.Infrastructure.Installation @@ -2112,11 +2105,6 @@ protected override void Alter(IList settings) x.BaseWeightId = base.DbContext.Set().Where(m => m.SystemKeyword == "kg").Single().Id; }) - .Alter(x => - { - x.PrimaryExchangeRateCurrencyId = base.DbContext.Set().Where(c => c.CurrencyCode == "EUR").Single().Id; - }) - .Alter(x => { x.DefaultTitle = "Mein Shop"; diff --git a/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs index 3b1c680985..7f0055c635 100644 --- a/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs @@ -1,20 +1,17 @@ using System; using System.Collections.Generic; using System.Linq; +using NUnit.Framework; +using Rhino.Mocks; +using SmartStore.Core; using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Directory; -using SmartStore.Core.Domain.Stores; -using SmartStore.Core.Infrastructure; +using SmartStore.Core.Events; using SmartStore.Core.Plugins; -using SmartStore.Services.Customers; using SmartStore.Services.Directory; -using SmartStore.Core.Events; -using SmartStore.Tests; -using NUnit.Framework; -using Rhino.Mocks; using SmartStore.Services.Stores; -using SmartStore.Core; +using SmartStore.Tests; namespace SmartStore.Services.Tests.Directory { @@ -85,7 +82,6 @@ public class CurrencyServiceTests : ServiceTest var cacheManager = new NullCache(); _currencySettings = new CurrencySettings(); - _currencySettings.PrimaryExchangeRateCurrencyId = currencyEUR.Id; _eventPublisher = MockRepository.GenerateMock(); _eventPublisher.Expect(x => x.Publish(Arg.Is.Anything)); From ecb243724f319ce621b30d5900126b8c5fe64c85 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 27 Jun 2015 12:07:53 +0200 Subject: [PATCH 0198/1256] A currency cannot be deleted or deactivated if it is attached to a store as primary or exchange rate currency. --- ...61756463_PrimaryStoreCurrencyMultiStore.cs | 8 +++ .../Controllers/CurrencyController.cs | 53 ++++++++++++------- .../Models/Directory/CurrencyModel.cs | 10 ++-- 3 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs index ed33800321..029472c05c 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -62,6 +62,14 @@ public void Seed(SmartObjectContext context) public void MigrateLocaleResources(LocaleResourcesBuilder builder) { + builder.AddOrUpdate("Admin.Configuration.Currencies.NoDeleteOrDeactivate", + "The currency cannot be deleted or deactivated because it is attached to the store \"{0}\" as primary or exchange rate currency.", + "Die Whrung kann nicht gelscht oder deaktiviert werden, weil sie dem Shop \"{0}\" als Leit- oder Umrechnungswhrung zugeordnet ist."); + + + + builder.Delete("Admin.Configuration.Currencies.CantDeletePrimary"); + builder.Delete("Admin.Configuration.Currencies.CantDeleteExchange"); } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs index 57094f5593..dc8f7c3bc0 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs @@ -4,6 +4,7 @@ using System.Web.Mvc; using SmartStore.Admin.Models.Directory; using SmartStore.Core.Domain.Directory; +using SmartStore.Core.Domain.Stores; using SmartStore.Services; using SmartStore.Services.Directory; using SmartStore.Services.Helpers; @@ -92,6 +93,19 @@ private void PrepareStoresMappingModel(CurrencyModel model, Currency currency, b } } + private bool IsAttachedToStore(Currency currency, IList stores) + { + foreach (var store in stores) + { + if (store.PrimaryStoreCurrencyId == currency.Id || store.PrimaryExchangeRateCurrencyId == currency.Id) + { + NotifyError(T("Admin.Configuration.Currencies.NoDeleteOrDeactivate", store.Name)); + return true; + } + } + return false; + } + #endregion #region Methods @@ -315,18 +329,22 @@ public ActionResult Edit(CurrencyModel model, bool continueEditing) if (ModelState.IsValid) { currency = model.ToEntity(currency); - currency.UpdatedOnUtc = DateTime.UtcNow; + + if (currency.Published || (!currency.Published && !IsAttachedToStore(currency, _services.StoreService.GetAllStores()))) + { + currency.UpdatedOnUtc = DateTime.UtcNow; - _currencyService.UpdateCurrency(currency); + _currencyService.UpdateCurrency(currency); - //locales - UpdateLocales(currency, model); + //locales + UpdateLocales(currency, model); - //Stores - _storeMappingService.SaveStoreMappings(currency, model.SelectedStoreIds); + //Stores + _storeMappingService.SaveStoreMappings(currency, model.SelectedStoreIds); - NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Currencies.Updated")); - return continueEditing ? RedirectToAction("Edit", new { id = currency.Id }) : RedirectToAction("List"); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Currencies.Updated")); + return continueEditing ? RedirectToAction("Edit", new { id = currency.Id }) : RedirectToAction("List"); + } } //If we got this far, something failed, redisplay form @@ -350,23 +368,20 @@ public ActionResult DeleteConfirmed(int id) try { - // TODO - //if (currency.Id == _currencySettings.PrimaryStoreCurrencyId) - // throw new SmartException(_services.Localization.GetResource("Admin.Configuration.Currencies.CantDeletePrimary")); - - //if (currency.Id == _currencySettings.PrimaryExchangeRateCurrencyId) - // throw new SmartException(_services.Localization.GetResource("Admin.Configuration.Currencies.CantDeleteExchange")); - - _currencyService.DeleteCurrency(currency); + if (!IsAttachedToStore(currency, _services.StoreService.GetAllStores())) + { + _currencyService.DeleteCurrency(currency); - NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Currencies.Deleted")); - return RedirectToAction("List"); + NotifySuccess(_services.Localization.GetResource("Admin.Configuration.Currencies.Deleted")); + return RedirectToAction("List"); + } } catch (Exception exc) { NotifyError(exc); - return RedirectToAction("Edit", new { id = currency.Id }); } + + return RedirectToAction("Edit", new { id = currency.Id }); } #endregion diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Directory/CurrencyModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Directory/CurrencyModel.cs index 179fa5bd37..e62df8f0e1 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Directory/CurrencyModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Directory/CurrencyModel.cs @@ -17,12 +17,12 @@ public CurrencyModel() { Locales = new List(); - AvailableDomainEndings = new List() + AvailableDomainEndings = new List { - new SelectListItem() { Text = ".com", Value = ".com" }, - new SelectListItem() { Text = ".uk", Value = ".uk" }, - new SelectListItem() { Text = ".de", Value = ".de" }, - new SelectListItem() { Text = ".ch", Value = ".ch" } + new SelectListItem { Text = ".com", Value = ".com" }, + new SelectListItem { Text = ".uk", Value = ".uk" }, + new SelectListItem { Text = ".de", Value = ".de" }, + new SelectListItem { Text = ".ch", Value = ".ch" } }; } [SmartResourceDisplayName("Admin.Configuration.Currencies.Fields.Name")] From 0d0ab6b386cad0c4508c528a33043549bedaf8f2 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 27 Jun 2015 12:43:42 +0200 Subject: [PATCH 0199/1256] Edit primary store and exchange rate currency --- ...61756463_PrimaryStoreCurrencyMultiStore.cs | 10 +++++ .../Controllers/StoreController.cs | 41 ++++++++++++++----- .../Infrastructure/AutoMapperStartupTask.cs | 3 +- .../Models/Stores/StoreModel.cs | 11 ++++- .../Views/Store/_CreateOrUpdate.cshtml | 18 ++++++++ 5 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs index 029472c05c..7e70a09bca 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -66,7 +66,17 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "The currency cannot be deleted or deactivated because it is attached to the store \"{0}\" as primary or exchange rate currency.", "Die Whrung kann nicht gelscht oder deaktiviert werden, weil sie dem Shop \"{0}\" als Leit- oder Umrechnungswhrung zugeordnet ist."); + builder.AddOrUpdate("Admin.Configuration.Stores.Fields.PrimaryStoreCurrencyId", + "Primary store currency", + "Leitwhrung", + "Specifies the the primary store currency.", + "Legt die Leitwhrung des Shops fest."); + builder.AddOrUpdate("Admin.Configuration.Stores.Fields.PrimaryExchangeRateCurrencyId", + "Primary exchange rate currency", + "Haupwhrung fr Whrungsumrechnung", + "Specifies the primary exchange rate currency for this store.", + "Legt die Haupwhrung fr Whrungsumrechnungen fr diesen Shop fest."); builder.Delete("Admin.Configuration.Currencies.CantDeletePrimary"); builder.Delete("Admin.Configuration.Currencies.CantDeleteExchange"); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs index b29282d610..70fbc6b815 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs @@ -1,9 +1,7 @@ using System; using System.Linq; using System.Web.Mvc; -using SmartStore.Admin.Models.Directory; using SmartStore.Admin.Models.Stores; -using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Stores; using SmartStore.Services.Configuration; using SmartStore.Services.Directory; @@ -22,16 +20,30 @@ public partial class StoreController : AdminControllerBase private readonly ISettingService _settingService; private readonly ILocalizationService _localizationService; private readonly IPermissionService _permissionService; + private readonly ICurrencyService _currencyService; public StoreController(IStoreService storeService, ISettingService settingService, ILocalizationService localizationService, - IPermissionService permissionService) + IPermissionService permissionService, + ICurrencyService currencyService) { this._storeService = storeService; this._settingService = settingService; this._localizationService = localizationService; this._permissionService = permissionService; + this._currencyService = currencyService; + } + + private void PrepareStoreModel(StoreModel model, Store store) + { + model.AvailableCurrencies = _currencyService.GetAllCurrencies() + .Select(x => new SelectListItem + { + Text = x.Name, + Value = x.Id.ToString() + }) + .ToList(); } public ActionResult List() @@ -91,6 +103,8 @@ public ActionResult Create() return AccessDeniedView(); var model = new StoreModel(); + PrepareStoreModel(model, null); + return View(model); } @@ -103,6 +117,7 @@ public ActionResult Create(StoreModel model, bool continueEditing) if (ModelState.IsValid) { var store = model.ToEntity(); + //ensure we have "/" at the end store.Url = store.Url.EnsureEndsWith("/"); _storeService.InsertStore(store); @@ -112,6 +127,7 @@ public ActionResult Create(StoreModel model, bool continueEditing) } //If we got this far, something failed, redisplay form + PrepareStoreModel(model, null); return View(model); } @@ -122,10 +138,11 @@ public ActionResult Edit(int id) var store = _storeService.GetStoreById(id); if (store == null) - //No store found with the specified id return RedirectToAction("List"); var model = store.ToModel(); + PrepareStoreModel(model, store); + return View(model); } @@ -138,12 +155,12 @@ public ActionResult Edit(StoreModel model, bool continueEditing) var store = _storeService.GetStoreById(model.Id); if (store == null) - //No store found with the specified id return RedirectToAction("List"); if (ModelState.IsValid) { store = model.ToEntity(store); + //ensure we have "/" at the end store.Url = store.Url.EnsureEndsWith("/"); _storeService.UpdateStore(store); @@ -153,6 +170,7 @@ public ActionResult Edit(StoreModel model, bool continueEditing) } //If we got this far, something failed, redisplay form + PrepareStoreModel(model, store); return View(model); } @@ -164,7 +182,6 @@ public ActionResult Delete(int id) var store = _storeService.GetStoreById(id); if (store == null) - //No store found with the specified id return RedirectToAction("List"); try @@ -176,18 +193,20 @@ public ActionResult Delete(int id) .GetAllSettings() .Where(s => s.StoreId == id) .ToList(); - foreach (var setting in settingsToDelete) - _settingService.DeleteSetting(setting); + + settingsToDelete.ForEach(x => _settingService.DeleteSetting(x)); + //when we had two stores and now have only one store, we also should delete all "per store" settings var allStores = _storeService.GetAllStores(); + if (allStores.Count == 1) { settingsToDelete = _settingService .GetAllSettings() .Where(s => s.StoreId == allStores[0].Id) .ToList(); - foreach (var setting in settingsToDelete) - _settingService.DeleteSetting(setting); + + settingsToDelete.ForEach(x => _settingService.DeleteSetting(x)); } NotifySuccess(_localizationService.GetResource("Admin.Configuration.Stores.Deleted")); @@ -196,8 +215,8 @@ public ActionResult Delete(int id) catch (Exception exc) { NotifyError(exc); - return RedirectToAction("Edit", new { id = store.Id }); } + return RedirectToAction("Edit", new { id = store.Id }); } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index 958b035003..271fcbcf2a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -567,7 +567,8 @@ public void Execute() .ForMember(dest => dest.IsRecipientNotified, mo => mo.Ignore()) .ForMember(dest => dest.CreatedOnUtc, mo => mo.Ignore()); //stores - Mapper.CreateMap(); + Mapper.CreateMap() + .ForMember(dest => dest.AvailableCurrencies, mo => mo.Ignore()); Mapper.CreateMap(); //Settings diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs index f64293b561..1fa8c5b051 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Web.Mvc; using FluentValidation.Attributes; using SmartStore.Admin.Validators.Stores; @@ -42,5 +43,13 @@ public partial class StoreModel : EntityModelBase [SmartResourceDisplayName("Admin.Configuration.Stores.Fields.ContentDeliveryNetwork")] [AllowHtml] public string ContentDeliveryNetwork { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Stores.Fields.PrimaryStoreCurrencyId")] + public int PrimaryStoreCurrencyId { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Stores.Fields.PrimaryExchangeRateCurrencyId")] + public int PrimaryExchangeRateCurrencyId { get; set; } + + public List AvailableCurrencies { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml index aac7dff4f0..ae8d7a39ad 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml @@ -94,6 +94,24 @@ @Html.ValidationMessageFor(model => model.HtmlBodyId)
+ @Html.SmartLabelFor(model => model.PrimaryStoreCurrencyId) + + @Html.DropDownListFor(model => model.PrimaryStoreCurrencyId, Model.AvailableCurrencies) + @Html.ValidationMessageFor(model => model.PrimaryStoreCurrencyId) +
+ @Html.SmartLabelFor(model => model.PrimaryExchangeRateCurrencyId) + + @Html.DropDownListFor(model => model.PrimaryExchangeRateCurrencyId, Model.AvailableCurrencies) + @Html.ValidationMessageFor(model => model.PrimaryExchangeRateCurrencyId) +
@Html.SmartLabelFor(model => model.DisplayOrder) From 4b9b2861e5c700c3644a5374770d7de5eaf03740 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sun, 28 Jun 2015 16:36:44 +0200 Subject: [PATCH 0200/1256] More UI changes for multi-store qualified primary store and exchange rate currency --- .../Mapping/Stores/StoreMap.cs | 6 +- ...61756463_PrimaryStoreCurrencyMultiStore.cs | 50 ++++++- .../UI/ScaffoldExtensions.cs | 29 +++- .../Controllers/CurrencyController.cs | 129 ++++++++++-------- .../Controllers/StoreController.cs | 13 +- .../Infrastructure/AutoMapperStartupTask.cs | 6 +- .../Models/Directory/CurrencyModel.cs | 10 +- .../Models/Stores/StoreModel.cs | 33 ++++- .../Administration/Views/Currency/List.cshtml | 79 +++++------ .../Views/Currency/_CreateOrUpdate.cshtml | 36 +++++ .../Administration/Views/Store/List.cshtml | 8 +- .../Views/Store/_CreateOrUpdate.cshtml | 46 +++---- 12 files changed, 302 insertions(+), 143 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs b/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs index bc204d80e9..6e8cdad339 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Stores/StoreMap.cs @@ -17,11 +17,13 @@ public StoreMap() this.HasRequired(s => s.PrimaryStoreCurrency) .WithMany() - .HasForeignKey(s => s.PrimaryStoreCurrencyId).WillCascadeOnDelete(false); + .HasForeignKey(s => s.PrimaryStoreCurrencyId) + .WillCascadeOnDelete(false); this.HasRequired(s => s.PrimaryExchangeRateCurrency) .WithMany() - .HasForeignKey(s => s.PrimaryExchangeRateCurrencyId).WillCascadeOnDelete(false); + .HasForeignKey(s => s.PrimaryExchangeRateCurrencyId) + .WillCascadeOnDelete(false); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs index 7e70a09bca..98d7b998ea 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -11,9 +11,15 @@ public partial class PrimaryStoreCurrencyMultiStore : DbMigration, ILocaleResour public override void Up() { AddColumn("dbo.Store", "PrimaryStoreCurrencyId", c => c.Int(nullable: false)); - AddColumn("dbo.Store", "PrimaryExchangeRateCurrencyId", c => c.Int(nullable: false)); + AddColumn("dbo.Store", "PrimaryExchangeRateCurrencyId", c => c.Int(nullable: false)); + + // avoid conflicts with foreign key constraint + Sql("Update dbo.Store Set PrimaryStoreCurrencyId = (Select Top(1) [Id] From dbo.Currency)"); + Sql("Update dbo.Store Set PrimaryExchangeRateCurrencyId = (Select Top(1) [Id] From dbo.Currency)"); + CreateIndex("dbo.Store", "PrimaryStoreCurrencyId"); CreateIndex("dbo.Store", "PrimaryExchangeRateCurrencyId"); + AddForeignKey("dbo.Store", "PrimaryExchangeRateCurrencyId", "dbo.Currency", "Id"); AddForeignKey("dbo.Store", "PrimaryStoreCurrencyId", "dbo.Currency", "Id"); } @@ -22,8 +28,10 @@ public override void Down() { DropForeignKey("dbo.Store", "PrimaryStoreCurrencyId", "dbo.Currency"); DropForeignKey("dbo.Store", "PrimaryExchangeRateCurrencyId", "dbo.Currency"); + DropIndex("dbo.Store", new[] { "PrimaryExchangeRateCurrencyId" }); DropIndex("dbo.Store", new[] { "PrimaryStoreCurrencyId" }); + DropColumn("dbo.Store", "PrimaryExchangeRateCurrencyId"); DropColumn("dbo.Store", "PrimaryStoreCurrencyId"); } @@ -62,10 +70,14 @@ public void Seed(SmartObjectContext context) public void MigrateLocaleResources(LocaleResourcesBuilder builder) { - builder.AddOrUpdate("Admin.Configuration.Currencies.NoDeleteOrDeactivate", + builder.AddOrUpdate("Admin.Configuration.Currencies.DeleteOrPublishStoreConflict", "The currency cannot be deleted or deactivated because it is attached to the store \"{0}\" as primary or exchange rate currency.", "Die Whrung kann nicht gelscht oder deaktiviert werden, weil sie dem Shop \"{0}\" als Leit- oder Umrechnungswhrung zugeordnet ist."); + //builder.AddOrUpdate("Admin.Configuration.Currencies.StoreLimitationConflict", + // "The store limitations must include store \"{0}\" because the currency is attached to it as primary or exchange rate currency.", + // "Die Shop-Eingrenzungen mssen den Shop \"{0}\" enthalten, da ihm die Whrung als Leit- oder Umrechnungswhrung zugeordnet ist."); + builder.AddOrUpdate("Admin.Configuration.Stores.Fields.PrimaryStoreCurrencyId", "Primary store currency", "Leitwhrung", @@ -73,13 +85,41 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Legt die Leitwhrung des Shops fest."); builder.AddOrUpdate("Admin.Configuration.Stores.Fields.PrimaryExchangeRateCurrencyId", - "Primary exchange rate currency", - "Haupwhrung fr Whrungsumrechnung", + "Exchange rate currency", + "Umrechnungswhrung", "Specifies the primary exchange rate currency for this store.", - "Legt die Haupwhrung fr Whrungsumrechnungen fr diesen Shop fest."); + "Legt die Umrechnungswhrung fr diesen Shop fest."); + + builder.AddOrUpdate("Admin.Configuration.Currencies.Fields.IsPrimaryStoreCurrency", + "Primary currency", + "Leitwhrung"); + + builder.AddOrUpdate("Admin.Configuration.Currencies.Fields.IsPrimaryExchangeRateCurrency", + "Exchange rate currency", + "Umrechnungswhrung"); + + builder.AddOrUpdate("Admin.Configuration.Currencies.Fields.PrimaryStoreCurrencyStores", + "Is primary store currency for", + "Ist Leitwhrung fr", + "A list of shores where the currency is primary store currency.", + "Eine Liste mit Shops, in denen die Whrung Leitwhrung ist."); + + builder.AddOrUpdate("Admin.Configuration.Currencies.Fields.PrimaryExchangeRateCurrencyStores", + "Is exchange rate currency for", + "Ist Umrechnungswhrung fr", + "A list of shores where the currency is primary exchange rate currency.", + "Eine Liste mit Shops, in denen die Whrung Umrechnungswhrung ist."); + + builder.AddOrUpdate("Admin.Configuration.Stores.Fields.SslEnabled", + "SSL", + "SSL", + "Specifies whether the store should be SSL secured.", + "Legt fest, ob der Shop SSL gesichert werden soll."); builder.Delete("Admin.Configuration.Currencies.CantDeletePrimary"); builder.Delete("Admin.Configuration.Currencies.CantDeleteExchange"); + builder.Delete("Admin.Configuration.Currencies.Fields.MarkAsPrimaryStoreCurrency"); + builder.Delete("Admin.Configuration.Currencies.Fields.MarkAsPrimaryExchangeRateCurrency"); } } } diff --git a/src/Presentation/SmartStore.Web.Framework/UI/ScaffoldExtensions.cs b/src/Presentation/SmartStore.Web.Framework/UI/ScaffoldExtensions.cs index 71f761010f..6c30d0edcb 100644 --- a/src/Presentation/SmartStore.Web.Framework/UI/ScaffoldExtensions.cs +++ b/src/Presentation/SmartStore.Web.Framework/UI/ScaffoldExtensions.cs @@ -1,10 +1,11 @@ -using System.Web.Mvc; +using System.Text; +using System.Web.Mvc; using System.Web.WebPages; -using Telerik.Web.Mvc.UI.Fluent; -using SmartStore.Core.Infrastructure; using SmartStore.Core.Domain.Common; +using SmartStore.Core.Infrastructure; using SmartStore.Core.Localization; using SmartStore.Services.Localization; +using Telerik.Web.Mvc.UI.Fluent; namespace SmartStore.Web.Framework.UI { @@ -73,6 +74,28 @@ public static string LabeledOrderNumber(this HtmlHelper helper) return "<# if(HasNewPaymentNotification) {{ #>{0}<# }} #>{1}".FormatInvariant(label, link); } + public static HelperResult LabeledCurrencyName(this HtmlHelper helper, int id, string name, bool isPrimaryStoreCurrency, bool isPrimaryExchangeRateCurrency) + { + var localize = EngineContext.Current.Resolve(); + var sb = new StringBuilder(); + + if (isPrimaryStoreCurrency) + { + sb.AppendFormat("{0}", localize.GetResource("Admin.Configuration.Currencies.Fields.IsPrimaryStoreCurrency")); + } + + if (isPrimaryExchangeRateCurrency) + { + sb.AppendFormat("{0}", localize.GetResource("Admin.Configuration.Currencies.Fields.IsPrimaryExchangeRateCurrency")); + } + + string url = UrlHelper.GenerateContentUrl("~/Admin/Currency/Edit/", helper.ViewContext.RequestContext.HttpContext); + + sb.AppendFormat("{2}", url, id, helper.Encode(name.NaIfEmpty())); + + return new HelperResult(writer => writer.Write(sb.ToString())); + } + public static string RichEditorFlavor(this HtmlHelper helper) { return EngineContext.Current.Resolve().RichEditorFlavor.NullEmpty() ?? "RichEditor"; diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs index dc8f7c3bc0..00fb1f65db 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CurrencyController.cs @@ -70,38 +70,66 @@ public void UpdateLocales(Currency currency, CurrencyModel model) } } - [NonAction] - private void PrepareStoresMappingModel(CurrencyModel model, Currency currency, bool excludeProperties) + private void PrepareCurrencyModel(CurrencyModel model, Currency currency, bool excludeProperties) { if (model == null) throw new ArgumentNullException("model"); - model.AvailableStores = _services.StoreService - .GetAllStores() - .Select(s => s.ToModel()) - .ToList(); + var allStores = _services.StoreService.GetAllStores(); + + model.AvailableStores = allStores.Select(s => s.ToModel()).ToList(); + + if (currency != null) + { + model.PrimaryStoreCurrencyStores = allStores + .Where(x => x.PrimaryStoreCurrencyId == currency.Id) + .Select(x => new SelectListItem + { + Text = x.Name, + Value = Url.Action("Edit", "Store", new { id = x.Id }) + }) + .ToList(); + + model.PrimaryExchangeRateCurrencyStores = allStores + .Where(x => x.PrimaryExchangeRateCurrencyId == currency.Id) + .Select(x => new SelectListItem + { + Text = x.Name, + Value = Url.Action("Edit", "Store", new { id = x.Id }) + }) + .ToList(); + } + if (!excludeProperties) { - if (currency != null) - { - model.SelectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(currency); - } - else - { - model.SelectedStoreIds = new int[0]; - } + model.SelectedStoreIds = (currency == null ? new int[0] : _storeMappingService.GetStoresIdsWithAccess(currency)); } } - private bool IsAttachedToStore(Currency currency, IList stores) + private bool IsAttachedToStore(Currency currency, IList stores, bool force) { - foreach (var store in stores) + var attachedStore = stores.FirstOrDefault(x => x.PrimaryStoreCurrencyId == currency.Id || x.PrimaryExchangeRateCurrencyId == currency.Id); + + if (attachedStore != null) { - if (store.PrimaryStoreCurrencyId == currency.Id || store.PrimaryExchangeRateCurrencyId == currency.Id) + if (force || (!force && !currency.Published)) { - NotifyError(T("Admin.Configuration.Currencies.NoDeleteOrDeactivate", store.Name)); + NotifyError(T("Admin.Configuration.Currencies.DeleteOrPublishStoreConflict", attachedStore.Name)); return true; } + + // Must store limitations include the store where the currency is attached as primary or exchange rate currency? + //if (currency.LimitedToStores) + //{ + // if (selectedStoreIds == null) + // selectedStoreIds = _storeMappingService.GetStoreMappingsFor("Currency", currency.Id).Select(x => x.StoreId).ToArray(); + + // if (!selectedStoreIds.Contains(attachedStore.Id)) + // { + // NotifyError(T("Admin.Configuration.Currencies.StoreLimitationConflict", attachedStore.Name)); + // return true; + // } + //} } return false; } @@ -120,17 +148,26 @@ public ActionResult List(bool liveRates = false) if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) return AccessDeniedView(); - var currenciesModel = _currencyService.GetAllCurrencies(true).Select(x => x.ToModel()).ToList(); + var store = _services.StoreContext.CurrentStore; + var models = _currencyService.GetAllCurrencies(true).Select(x => x.ToModel()).ToList(); - foreach (var currency in currenciesModel) + foreach (var model in models) { - currency.IsPrimaryExchangeRateCurrency = (currency.Id == _services.StoreContext.CurrentStore.PrimaryExchangeRateCurrencyId); + model.IsPrimaryStoreCurrency = (store.PrimaryStoreCurrencyId == model.Id); + model.IsPrimaryExchangeRateCurrency = (store.PrimaryExchangeRateCurrencyId == model.Id); } - foreach (var currency in currenciesModel) - { - currency.IsPrimaryStoreCurrency = (currency.Id == _services.StoreContext.CurrentStore.PrimaryStoreCurrencyId); - } + //var allStores = _services.StoreService.GetAllStores(); + //foreach (var model in models) + //{ + // var storeNames = allStores.Where(x => x.PrimaryStoreCurrencyId == model.Id).Select(x => x.Name).ToList(); + + // model.IsPrimaryStoreCurrency = string.Join("
", storeNames); + + // storeNames = allStores.Where(x => x.PrimaryExchangeRateCurrencyId == model.Id).Select(x => x.Name).ToList(); + + // model.IsPrimaryExchangeRateCurrency = string.Join("
", storeNames); + //} if (liveRates) { @@ -147,21 +184,25 @@ public ActionResult List(bool liveRates = false) NotifyError(exc, false); } } + ViewBag.ExchangeRateProviders = new List(); + foreach (var erp in _currencyService.LoadAllExchangeRateProviders()) { - ViewBag.ExchangeRateProviders.Add(new SelectListItem() + ViewBag.ExchangeRateProviders.Add(new SelectListItem { Text = _pluginMediator.GetLocalizedFriendlyName(erp.Metadata), Value = erp.Metadata.SystemName, Selected = erp.Metadata.SystemName.Equals(_currencySettings.ActiveExchangeRateProviderSystemName, StringComparison.InvariantCultureIgnoreCase) }); } + ViewBag.AutoUpdateEnabled = _currencySettings.AutoUpdateEnabled; + var gridModel = new GridModel { - Data = currenciesModel, - Total = currenciesModel.Count() + Data = models, + Total = models.Count() }; return View(gridModel); } @@ -210,26 +251,6 @@ public ActionResult List(GridCommand command) Data = gridModel }; } - - public ActionResult MarkAsPrimaryExchangeRateCurrency(int id) - { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) - return AccessDeniedView(); - - //_currencySettings.PrimaryExchangeRateCurrencyId = id; - //_services.Settings.SaveSetting(_currencySettings); - return RedirectToAction("List"); - } - - public ActionResult MarkAsPrimaryStoreCurrency(int id) - { - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageCurrencies)) - return AccessDeniedView(); - - //_currencySettings.PrimaryStoreCurrencyId = id; - //_services.Settings.SaveSetting(_currencySettings); - return RedirectToAction("List"); - } #endregion @@ -244,7 +265,7 @@ public ActionResult Create() //locales AddLocales(_languageService, model.Locales); //Stores - PrepareStoresMappingModel(model, null, false); + PrepareCurrencyModel(model, null, false); //default values model.Published = true; model.Rate = 1; @@ -278,7 +299,7 @@ public ActionResult Create(CurrencyModel model, bool continueEditing) //If we got this far, something failed, redisplay form //Stores - PrepareStoresMappingModel(model, null, true); + PrepareCurrencyModel(model, null, true); return View(model); } @@ -311,7 +332,7 @@ public ActionResult Edit(int id) } //Stores - PrepareStoresMappingModel(model, currency, false); + PrepareCurrencyModel(model, currency, false); return View(model); } @@ -330,7 +351,7 @@ public ActionResult Edit(CurrencyModel model, bool continueEditing) { currency = model.ToEntity(currency); - if (currency.Published || (!currency.Published && !IsAttachedToStore(currency, _services.StoreService.GetAllStores()))) + if (!IsAttachedToStore(currency, _services.StoreService.GetAllStores(), false)) { currency.UpdatedOnUtc = DateTime.UtcNow; @@ -351,7 +372,7 @@ public ActionResult Edit(CurrencyModel model, bool continueEditing) model.CreatedOn = _dateTimeHelper.ConvertToUserTime(currency.CreatedOnUtc, DateTimeKind.Utc); //Stores - PrepareStoresMappingModel(model, currency, true); + PrepareCurrencyModel(model, currency, true); return View(model); } @@ -368,7 +389,7 @@ public ActionResult DeleteConfirmed(int id) try { - if (!IsAttachedToStore(currency, _services.StoreService.GetAllStores())) + if (!IsAttachedToStore(currency, _services.StoreService.GetAllStores(), true)) { _currencyService.DeleteCurrency(currency); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs index 70fbc6b815..e5196ce3d9 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs @@ -37,7 +37,7 @@ public StoreController(IStoreService storeService, private void PrepareStoreModel(StoreModel model, Store store) { - model.AvailableCurrencies = _currencyService.GetAllCurrencies() + model.AvailableCurrencies = _currencyService.GetAllCurrencies(false, store == null ? 0 : store.Id) .Select(x => new SelectListItem { Text = x.Name, @@ -82,7 +82,16 @@ public ActionResult List(GridCommand command) return AccessDeniedView(); var storeModels = _storeService.GetAllStores() - .Select(x => x.ToModel()) + .Select(x => + { + var model = x.ToModel(); + + PrepareStoreModel(model, x); + + model.Hosts = model.Hosts.EmptyNull().Replace(",", "
"); + + return model; + }) .ToList(); var gridModel = new GridModel diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index 271fcbcf2a..beb5350570 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -317,6 +317,8 @@ public void Execute() .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) .ForMember(dest => dest.IsPrimaryExchangeRateCurrency, mo => mo.Ignore()) .ForMember(dest => dest.IsPrimaryStoreCurrency, mo => mo.Ignore()) + .ForMember(dest => dest.PrimaryStoreCurrencyStores, mo => mo.Ignore()) + .ForMember(dest => dest.PrimaryExchangeRateCurrencyStores, mo => mo.Ignore()) .ForMember(dest => dest.Locales, mo => mo.Ignore()) .ForMember(dest => dest.AvailableStores, mo => mo.Ignore()) .ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore()) @@ -568,7 +570,9 @@ public void Execute() .ForMember(dest => dest.CreatedOnUtc, mo => mo.Ignore()); //stores Mapper.CreateMap() - .ForMember(dest => dest.AvailableCurrencies, mo => mo.Ignore()); + .ForMember(dest => dest.AvailableCurrencies, mo => mo.Ignore()) + .ForMember(dest => dest.PrimaryStoreCurrency, mo => mo.Ignore()) + .ForMember(dest => dest.PrimaryExchangeRateCurrency, mo => mo.Ignore()); Mapper.CreateMap(); //Settings diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Directory/CurrencyModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Directory/CurrencyModel.cs index e62df8f0e1..395fa757dd 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Directory/CurrencyModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Directory/CurrencyModel.cs @@ -53,11 +53,14 @@ public CurrencyModel() [SmartResourceDisplayName("Admin.Configuration.Currencies.Fields.CreatedOn")] public DateTime CreatedOn { get; set; } - [SmartResourceDisplayName("Admin.Configuration.Currencies.Fields.IsPrimaryExchangeRateCurrency")] + public bool IsPrimaryStoreCurrency { get; set; } public bool IsPrimaryExchangeRateCurrency { get; set; } - [SmartResourceDisplayName("Admin.Configuration.Currencies.Fields.IsPrimaryStoreCurrency")] - public bool IsPrimaryStoreCurrency { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Currencies.Fields.PrimaryStoreCurrencyStores")] + public IList PrimaryStoreCurrencyStores { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Currencies.Fields.PrimaryExchangeRateCurrencyStores")] + public IList PrimaryExchangeRateCurrencyStores { get; set; } [SmartResourceDisplayName("Admin.Configuration.Currencies.Fields.DomainEndings")] public string DomainEndings { get; set; } @@ -68,6 +71,7 @@ public CurrencyModel() //Store mapping [SmartResourceDisplayName("Admin.Common.Store.LimitedTo")] public bool LimitedToStores { get; set; } + [SmartResourceDisplayName("Admin.Common.Store.AvailableFor")] public List AvailableStores { get; set; } public int[] SelectedStoreIds { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs index 1fa8c5b051..bfbaafc87b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System.Linq; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Web.Mvc; using FluentValidation.Attributes; @@ -47,9 +48,39 @@ public partial class StoreModel : EntityModelBase [SmartResourceDisplayName("Admin.Configuration.Stores.Fields.PrimaryStoreCurrencyId")] public int PrimaryStoreCurrencyId { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Stores.Fields.PrimaryStoreCurrencyId")] + public string PrimaryStoreCurrency + { + get + { + try + { + return AvailableCurrencies.First(x => x.Value == PrimaryStoreCurrencyId.ToString()).Text; + } + catch { } + + return null; + } + } + [SmartResourceDisplayName("Admin.Configuration.Stores.Fields.PrimaryExchangeRateCurrencyId")] public int PrimaryExchangeRateCurrencyId { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Stores.Fields.PrimaryExchangeRateCurrencyId")] + public string PrimaryExchangeRateCurrency + { + get + { + try + { + return AvailableCurrencies.First(x => x.Value == PrimaryExchangeRateCurrencyId.ToString()).Text; + } + catch { } + + return null; + } + } + public List AvailableCurrencies { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Currency/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Currency/List.cshtml index f659ace41d..029108bc38 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Currency/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Currency/List.cshtml @@ -3,9 +3,10 @@ @{ List rates = ViewBag.Rates; bool autoUpdateEnabled = ViewBag.AutoUpdateEnabled ?? false; - //page title + ViewBag.Title = T("Admin.Configuration.Currencies").Text; } +
@@ -26,6 +27,7 @@
+ @using (Html.BeginForm("Save", "Currency", FormMethod.Post, new { name = "CurrencySettings" })) { @@ -48,58 +50,41 @@
} +
@(Html.Telerik().Grid() - .Name("currencies-grid") - .BindTo(Model.Data) - .Columns(columns => - { - columns.Bound(x => x.Name) - .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })); - columns.Bound(x => x.CurrencyCode) - .Centered(); - columns.Bound(x => x.Rate) - .RightAlign() - .Format("{0:0.00000000}") - .Width(180); - columns.Bound(x => x.DomainEndings); - columns.Bound(x => x.IsPrimaryExchangeRateCurrency) - .Centered() - .Template( - @ - @if (item.IsPrimaryExchangeRateCurrency) - { - - } - @T("Admin.Telerik.GridLocalization.Select") - - ) - .Width(100); - columns.Bound(x => x.IsPrimaryStoreCurrency) - .Centered() - .Template( - @ - @if (item.IsPrimaryStoreCurrency) - { - - } - @T("Admin.Telerik.GridLocalization.Select") - - ) - .Width(100); - columns.Bound(x => x.Published) - .Template(item => Html.SymbolForBool(item.Published)) - .Centered() - .Width(100); - }) -) + .Name("currencies-grid") + .BindTo(Model.Data) + .Columns(columns => + { + columns.Bound(x => x.Name) + .Template(x => Html.LabeledCurrencyName(x.Id, x.Name, x.IsPrimaryStoreCurrency, x.IsPrimaryExchangeRateCurrency)); + columns.Bound(x => x.CurrencyCode) + .Centered() + .Width(160); + columns.Bound(x => x.Published) + .Template(item => Html.SymbolForBool(item.Published)) + .Centered() + .Width(160); + columns.Bound(x => x.Rate) + .RightAlign() + .Format("{0:0.00000000}") + .Width(160); + columns.Bound(x => x.LimitedToStores) + .Template(item => Html.SymbolForBool(item.LimitedToStores)) + .Centered() + .Width(160); + columns.Bound(x => x.DomainEndings); + }) + )
-

-

+ +

+ @if (rates != null) {

@T("Admin.Configuration.Currencies.LiveRates")

@@ -129,7 +114,7 @@ }) .EnableCustomBinding(true) - ) + )
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Currency/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Currency/_CreateOrUpdate.cshtml index 270d2f982b..2e86287c4b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Currency/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Currency/_CreateOrUpdate.cshtml @@ -141,6 +141,42 @@ } + + + @Html.SmartLabelFor(model => model.PrimaryStoreCurrencyStores) + + + @if (Model.PrimaryStoreCurrencyStores != null && Model.PrimaryStoreCurrencyStores.Count > 0) + { + foreach (var store in Model.PrimaryStoreCurrencyStores) + { + @store.Text.NaIfEmpty()
+ } + } + else + { + @T("Common.Unspecified") + } + + + + + @Html.SmartLabelFor(model => model.PrimaryExchangeRateCurrencyStores) + + + @if (Model.PrimaryExchangeRateCurrencyStores != null && Model.PrimaryExchangeRateCurrencyStores.Count > 0) + { + foreach (var store in Model.PrimaryExchangeRateCurrencyStores) + { + @store.Text.NaIfEmpty()
+ } + } + else + { + @T("Common.Unspecified") + } + + } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml index ff0728c169..0376a98f21 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml @@ -23,13 +23,17 @@ .ClientTemplate("\"><#= Name #>"); columns.Bound(x => x.Url) .ClientTemplate("\" target=\"_blank\"><#= Url #>"); + columns.Bound(x => x.Hosts) + .Encoded(false); + columns.Bound(x => x.PrimaryStoreCurrency); + columns.Bound(x => x.PrimaryExchangeRateCurrency); columns.Bound(x => x.ContentDeliveryNetwork) .ClientTemplate("\" target=\"_blank\"><#= ContentDeliveryNetwork #>"); - columns.Bound(x => x.Hosts); columns.Bound(x => x.SslEnabled) .Template(item => @Html.SymbolForBool(item.SslEnabled)) .ClientTemplate(@Html.SymbolForBool("SslEnabled")) - .Centered(); + .Centered() + .Width(80); columns.Bound(x => x.DisplayOrder) .Centered(); }) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml index ae8d7a39ad..04f6cbc086 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml @@ -51,65 +51,65 @@ - @Html.SmartLabelFor(model => model.ContentDeliveryNetwork) + @Html.SmartLabelFor(model => model.Hosts) - @Html.EditorFor(model => model.ContentDeliveryNetwork) - @Html.ValidationMessageFor(model => model.ContentDeliveryNetwork) + @Html.TextBoxFor(model => model.Hosts, new { @class = "input-large" }) + @Html.ValidationMessageFor(model => model.Hosts) - @Html.SmartLabelFor(model => model.SslEnabled) + @Html.SmartLabelFor(model => model.ContentDeliveryNetwork) - @Html.EditorFor(model => model.SslEnabled) - @Html.ValidationMessageFor(model => model.SslEnabled) + @Html.EditorFor(model => model.ContentDeliveryNetwork) + @Html.ValidationMessageFor(model => model.ContentDeliveryNetwork) - + - @Html.SmartLabelFor(model => model.SecureUrl) + @Html.SmartLabelFor(model => model.PrimaryStoreCurrencyId) - @Html.EditorFor(model => model.SecureUrl) - @Html.ValidationMessageFor(model => model.SecureUrl) + @Html.DropDownListFor(model => model.PrimaryStoreCurrencyId, Model.AvailableCurrencies) + @Html.ValidationMessageFor(model => model.PrimaryStoreCurrencyId) - @Html.SmartLabelFor(model => model.Hosts) + @Html.SmartLabelFor(model => model.PrimaryExchangeRateCurrencyId) - @Html.TextBoxFor(model => model.Hosts, new { @class = "input-large" }) - @Html.ValidationMessageFor(model => model.Hosts) + @Html.DropDownListFor(model => model.PrimaryExchangeRateCurrencyId, Model.AvailableCurrencies) + @Html.ValidationMessageFor(model => model.PrimaryExchangeRateCurrencyId) - @Html.SmartLabelFor(model => model.HtmlBodyId) + @Html.SmartLabelFor(model => model.SslEnabled) - @Html.EditorFor(model => model.HtmlBodyId) - @Html.ValidationMessageFor(model => model.HtmlBodyId) + @Html.EditorFor(model => model.SslEnabled) + @Html.ValidationMessageFor(model => model.SslEnabled) - + - @Html.SmartLabelFor(model => model.PrimaryStoreCurrencyId) + @Html.SmartLabelFor(model => model.SecureUrl) - @Html.DropDownListFor(model => model.PrimaryStoreCurrencyId, Model.AvailableCurrencies) - @Html.ValidationMessageFor(model => model.PrimaryStoreCurrencyId) + @Html.EditorFor(model => model.SecureUrl) + @Html.ValidationMessageFor(model => model.SecureUrl) - @Html.SmartLabelFor(model => model.PrimaryExchangeRateCurrencyId) + @Html.SmartLabelFor(model => model.HtmlBodyId) - @Html.DropDownListFor(model => model.PrimaryExchangeRateCurrencyId, Model.AvailableCurrencies) - @Html.ValidationMessageFor(model => model.PrimaryExchangeRateCurrencyId) + @Html.EditorFor(model => model.HtmlBodyId) + @Html.ValidationMessageFor(model => model.HtmlBodyId) From 09f07682dd1bea6905f484a007fc6244c6ecc043 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 29 Jun 2015 12:00:36 +0200 Subject: [PATCH 0201/1256] Testing multi-store qualified primary store and exchange rate currency --- changelog.md | 1 + .../SmartStore.Core/IStoreContext.cs | 8 +---- .../Directory/CurrencyService.cs | 10 +++--- .../Directory/ICurrencyService.cs | 3 +- .../Services/GoogleFeedService.cs | 4 +-- .../Plugins/FeedPluginHelper.cs | 15 ++++++--- .../Plugins/PluginHelper.cs | 5 --- .../Infrastructure/AutoMapperStartupTask.cs | 8 +++-- .../Stores/StorePersistenceTests.cs | 31 +++++++++++++++++-- .../Directory/CurrencyServiceTests.cs | 10 ++++++ 10 files changed, 65 insertions(+), 30 deletions(-) diff --git a/changelog.md b/changelog.md index 96936ed74e..eddfefc44a 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,7 @@ * #526 Min\max amount option for which the payment method should be offered during checkout * #718 ShopConnector: Import option for "Published" and "Disable buy\wishlist button" * #702 Facebook and Twitter external authentication suitable for multi-stores +* #704 Make primary store currency suitable for multi-stores ### Improvements * (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%. diff --git a/src/Libraries/SmartStore.Core/IStoreContext.cs b/src/Libraries/SmartStore.Core/IStoreContext.cs index 0986f24bb8..2ab8bfede9 100644 --- a/src/Libraries/SmartStore.Core/IStoreContext.cs +++ b/src/Libraries/SmartStore.Core/IStoreContext.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using SmartStore.Core.Domain.Stores; +using SmartStore.Core.Domain.Stores; namespace SmartStore.Core { @@ -44,7 +39,6 @@ public interface IStoreContext /// /// IsSingleStoreMode ? 0 : CurrentStore.Id /// - /// codehint: sm-add int CurrentStoreIdIfMultiStoreMode { get; } } } diff --git a/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs b/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs index b71220ab74..5dd60700e7 100644 --- a/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs +++ b/src/Libraries/SmartStore.Services/Directory/CurrencyService.cs @@ -191,7 +191,6 @@ public virtual void UpdateCurrency(Currency currency) } - /// /// Converts currency /// @@ -211,16 +210,17 @@ public virtual decimal ConvertCurrency(decimal amount, decimal exchangeRate) /// Amount /// Source currency code /// Target currency code + /// Store to get the primary currencies from /// Converted value - public virtual decimal ConvertCurrency(decimal amount, Currency sourceCurrencyCode, Currency targetCurrencyCode) + public virtual decimal ConvertCurrency(decimal amount, Currency sourceCurrencyCode, Currency targetCurrencyCode, Store store = null) { decimal result = amount; if (sourceCurrencyCode.Id == targetCurrencyCode.Id) return result; if (result != decimal.Zero && sourceCurrencyCode.Id != targetCurrencyCode.Id) { - result = ConvertToPrimaryExchangeRateCurrency(result, sourceCurrencyCode); - result = ConvertFromPrimaryExchangeRateCurrency(result, targetCurrencyCode); + result = ConvertToPrimaryExchangeRateCurrency(result, sourceCurrencyCode, store); + result = ConvertFromPrimaryExchangeRateCurrency(result, targetCurrencyCode, store); } return result; } @@ -301,7 +301,7 @@ public virtual decimal ConvertFromPrimaryStoreCurrency(decimal amount, Currency { decimal result = amount; var primaryStoreCurrency = (store == null ? _storeContext.CurrentStore.PrimaryStoreCurrency : store.PrimaryStoreCurrency); - result = ConvertCurrency(amount, primaryStoreCurrency, targetCurrencyCode); + result = ConvertCurrency(amount, primaryStoreCurrency, targetCurrencyCode, store); return result; } diff --git a/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs b/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs index 6c609d61eb..65f633fed4 100644 --- a/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs +++ b/src/Libraries/SmartStore.Services/Directory/ICurrencyService.cs @@ -73,8 +73,9 @@ public partial interface ICurrencyService /// Amount /// Source currency code /// Target currency code + /// Store to get the primary currencies from /// Converted value - decimal ConvertCurrency(decimal amount, Currency sourceCurrencyCode, Currency targetCurrencyCode); + decimal ConvertCurrency(decimal amount, Currency sourceCurrencyCode, Currency targetCurrencyCode, Store store = null); /// /// Converts to primary exchange rate currency diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs b/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs index de92f5e59b..9eb7c134dc 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/Services/GoogleFeedService.cs @@ -394,7 +394,7 @@ private void WriteItem(FeedFileCreationContext fileCreation, XmlWriter writer, P writer.WriteElementString("g", "condition", _googleNamespace, Condition()); writer.WriteElementString("g", "availability", _googleNamespace, Availability(product)); - decimal price = Helper.GetProductPrice(product, currency); + decimal price = Helper.GetProductPrice(product, currency, fileCreation.Store); string specialPriceDate; if (SpecialPrice(product, out specialPriceDate)) @@ -405,7 +405,7 @@ private void WriteItem(FeedFileCreationContext fileCreation, XmlWriter writer, P // get regular price ignoring any special price decimal specialPrice = product.SpecialPrice.Value; product.SpecialPrice = null; - price = Helper.GetProductPrice(product, currency); + price = Helper.GetProductPrice(product, currency, fileCreation.Store); product.SpecialPrice = specialPrice; _dbContext.SetToUnchanged(product); diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs index 235c0bbf40..9acc2ee0b5 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs @@ -17,6 +17,7 @@ using SmartStore.Core.Html; using SmartStore.Core.Logging; using SmartStore.Services.Catalog; +using SmartStore.Services.Directory; using SmartStore.Services.Localization; using SmartStore.Services.Media; using SmartStore.Services.Seo; @@ -110,6 +111,12 @@ private IWorkContext WorkContext get { return _workContext ?? (_workContext = _ctx.Resolve()); } } + private ICurrencyService _currencyService; + private ICurrencyService CurrencyService + { + get { return _currencyService ?? (_currencyService = _ctx.Resolve()); } + } + #endregion private PromotionFeedSettings BaseSettings @@ -266,7 +273,7 @@ public string GetProductDetailUrl(Store store, Product product) return "{0}{1}".FormatWith(store.Url, product.GetSeName(Language.Id, UrlRecordService, LanguageService)); } - public decimal GetProductPrice(Product product, Currency currency) + public decimal GetProductPrice(Product product, Currency currency, Store store) { decimal priceBase = PriceCalculationService.GetPreselectedPrice(product); @@ -276,11 +283,11 @@ public decimal GetProductPrice(Product product, Currency currency) priceBase = TaxService.GetProductPrice(product, priceBase, true, WorkContext.CurrentCustomer, out taxRate); } - decimal price = ConvertFromStoreCurrency(priceBase, currency); + decimal price = CurrencyService.ConvertFromPrimaryStoreCurrency(priceBase, currency, store); return price; } - public decimal? GetOldPrice(Product product, Currency currency) + public decimal? GetOldPrice(Product product, Currency currency, Store store) { if (!decimal.Equals(product.OldPrice, decimal.Zero) && !decimal.Equals(product.OldPrice, product.Price) && !(product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing)) @@ -293,7 +300,7 @@ public decimal GetProductPrice(Product product, Currency currency) price = TaxService.GetProductPrice(product, price, true, WorkContext.CurrentCustomer, out taxRate); } - return ConvertFromStoreCurrency(price, currency); + return CurrencyService.ConvertFromPrimaryStoreCurrency(price, currency, store); } return null; } diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/PluginHelper.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/PluginHelper.cs index b3d71558e0..f18077c900 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/PluginHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/PluginHelper.cs @@ -206,11 +206,6 @@ public XmlDocument CreateXmlDocument(Func content) } } - public decimal ConvertFromStoreCurrency(decimal price, Currency currency) - { - return _ctx.Resolve().ConvertFromPrimaryStoreCurrency(price, currency); - } - public List AvailableCurrencies() { var lst = new List(); diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index beb5350570..6380f0632c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -389,12 +389,14 @@ public void Execute() //shipping methods Mapper.CreateMap() .ForMember(dest => dest.Locales, mo => mo.Ignore()) + .ForMember(dest => dest.ExcludedCountryIds, mo => mo.Ignore()) .ForMember(dest => dest.AvailableCustomerRoles, mo => mo.Ignore()) .ForMember(dest => dest.AvailableCountries, mo => mo.Ignore()) .ForMember(dest => dest.AvailableCountryExclusionContextTypes, mo => mo.Ignore()); - Mapper.CreateMap() - .ForMember(dest => dest.RestrictedCountries, mo => mo.Ignore()) - .ForMember(dest => dest.ExcludedCustomerRoleIds, mo => mo.Ignore()); + Mapper.CreateMap() + .ForMember(dest => dest.RestrictedCountries, mo => mo.Ignore()) + .ForMember(dest => dest.ExcludedCustomerRoleIds, mo => mo.Ignore()) + .ForMember(dest => dest.CountryExclusionContextId, mo => mo.Ignore()); //plugins Mapper.CreateMap() .ForMember(dest => dest.ConfigurationUrl, mo => mo.Ignore()) diff --git a/src/Tests/SmartStore.Data.Tests/Stores/StorePersistenceTests.cs b/src/Tests/SmartStore.Data.Tests/Stores/StorePersistenceTests.cs index eebc1ebded..65509fe49a 100644 --- a/src/Tests/SmartStore.Data.Tests/Stores/StorePersistenceTests.cs +++ b/src/Tests/SmartStore.Data.Tests/Stores/StorePersistenceTests.cs @@ -1,24 +1,49 @@ using SmartStore.Core.Domain.Stores; using SmartStore.Tests; using NUnit.Framework; +using SmartStore.Core.Domain.Directory; +using System; namespace SmartStore.Data.Tests.Stores { [TestFixture] public class StorePersistenceTests : PersistenceTest { - [Test] - public void Can_save_and_load_store() + public static Store GetTestStore() { + var currency = new Currency + { + Name = "US Dollar", + CurrencyCode = "USD", + Rate = 1.1M, + DisplayLocale = "en-US", + CustomFormatting = "CustomFormatting 1", + LimitedToStores = true, + Published = true, + DisplayOrder = 2, + CreatedOnUtc = new DateTime(2010, 01, 01), + UpdatedOnUtc = new DateTime(2010, 01, 02), + }; + var store = new Store { Name = "Computer store", Url = "http://www.yourStore.com", Hosts = "yourStore.com,www.yourStore.com", LogoPictureId = 0, - DisplayOrder = 1 + DisplayOrder = 1, + PrimaryStoreCurrency = currency, + PrimaryExchangeRateCurrency = currency }; + return store; + } + + [Test] + public void Can_save_and_load_store() + { + var store = GetTestStore(); + var fromDb = SaveAndLoadEntity(store); fromDb.ShouldNotBeNull(); fromDb.Name.ShouldEqual("Computer store"); diff --git a/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs index 7f0055c635..7f5b6ea83d 100644 --- a/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Directory/CurrencyServiceTests.cs @@ -7,6 +7,7 @@ using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Directory; +using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; using SmartStore.Core.Plugins; using SmartStore.Services.Directory; @@ -83,6 +84,15 @@ public class CurrencyServiceTests : ServiceTest _currencySettings = new CurrencySettings(); + _storeContext.Expect(x => x.CurrentStore).Return(new Store + { + Name = "Computer store", + Url = "http://www.yourStore.com", + Hosts = "yourStore.com,www.yourStore.com", + PrimaryStoreCurrency = currencyUSD, + PrimaryExchangeRateCurrency = currencyEUR + }); + _eventPublisher = MockRepository.GenerateMock(); _eventPublisher.Expect(x => x.Publish(Arg.Is.Anything)); From 589c89568b60b9e23272b00cc0cd8705178d4d25 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 29 Jun 2015 17:00:55 +0200 Subject: [PATCH 0202/1256] WorkingCurrency may throw exception Admin warnigs should catch exceptions --- .../WebWorkContext.cs | 12 ++++----- .../Controllers/CommonController.cs | 26 +++++++++++++++---- .../Infrastructure/AutoMapperStartupTask.cs | 5 ++-- .../Models/Stores/StoreModel.cs | 4 +-- .../Administration/Views/Store/List.cshtml | 4 +-- 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs b/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs index 1b9a6d7c96..58684d0f8a 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebWorkContext.cs @@ -380,16 +380,16 @@ public Currency WorkingCurrency } } - // find currency by domain ending - if (currency == null && _httpContext != null && _httpContext.Request != null && _httpContext.Request.Url != null) + // if there's only one currency for current store it dominates the primary currency + if (storeCurrenciesMap.Count == 1) { - currency = storeCurrenciesMap.Values.GetByDomainEnding(_httpContext.Request.Url.Authority); + currency = storeCurrenciesMap[storeCurrenciesMap.Keys.First()]; } - // if there's only one currency for current store it dominates the primary currency - if (storeCurrenciesMap.Count == 1) + // find currency by domain ending + if (currency == null && _httpContext != null && _httpContext.Request != null && _httpContext.Request.Url != null) { - currency = storeCurrenciesMap[0]; + currency = storeCurrenciesMap.Values.GetByDomainEnding(_httpContext.Request.Url.Authority); } // get PrimaryStoreCurrency diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs index 3abb1f2d5b..b2e0ec9a03 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CommonController.cs @@ -655,10 +655,18 @@ public ActionResult Warnings() }); } - // shipping rate coputation methods - if (_shippingService.Value.LoadActiveShippingRateComputationMethods() - .Where(x => x.Value.ShippingRateComputationMethodType == ShippingRateComputationMethodType.Offline) - .Count() > 1) + // shipping rate coputation methods + int activeShippingMethodCount = 0; + + try + { + activeShippingMethodCount = _shippingService.Value.LoadActiveShippingRateComputationMethods() + .Where(x => x.Value.ShippingRateComputationMethodType == ShippingRateComputationMethodType.Offline) + .Count(); + } + catch { } + + if (activeShippingMethodCount > 1) { model.Add(new SystemWarningModel { @@ -668,7 +676,15 @@ public ActionResult Warnings() } //payment methods - if (_paymentService.Value.LoadActivePaymentMethods().Count() > 0) + int activePaymentMethodCount = 0; + + try + { + activePaymentMethodCount = _paymentService.Value.LoadActivePaymentMethods().Count(); + } + catch { } + + if (activePaymentMethodCount > 0) { model.Add(new SystemWarningModel { diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index 6380f0632c..81fcb2d184 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -573,10 +573,11 @@ public void Execute() //stores Mapper.CreateMap() .ForMember(dest => dest.AvailableCurrencies, mo => mo.Ignore()) + .ForMember(dest => dest.PrimaryStoreCurrencyName, mo => mo.Ignore()) + .ForMember(dest => dest.PrimaryExchangeRateCurrencyName, mo => mo.Ignore()); + Mapper.CreateMap() .ForMember(dest => dest.PrimaryStoreCurrency, mo => mo.Ignore()) .ForMember(dest => dest.PrimaryExchangeRateCurrency, mo => mo.Ignore()); - Mapper.CreateMap(); - //Settings Mapper.CreateMap() .ForMember(dest => dest.DefaultTaxAddress, mo => mo.Ignore()) diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs index bfbaafc87b..8da3b70ada 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Stores/StoreModel.cs @@ -49,7 +49,7 @@ public partial class StoreModel : EntityModelBase public int PrimaryStoreCurrencyId { get; set; } [SmartResourceDisplayName("Admin.Configuration.Stores.Fields.PrimaryStoreCurrencyId")] - public string PrimaryStoreCurrency + public string PrimaryStoreCurrencyName { get { @@ -67,7 +67,7 @@ public string PrimaryStoreCurrency public int PrimaryExchangeRateCurrencyId { get; set; } [SmartResourceDisplayName("Admin.Configuration.Stores.Fields.PrimaryExchangeRateCurrencyId")] - public string PrimaryExchangeRateCurrency + public string PrimaryExchangeRateCurrencyName { get { diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml index 0376a98f21..b3832779c4 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Store/List.cshtml @@ -25,8 +25,8 @@ .ClientTemplate("\" target=\"_blank\"><#= Url #>"); columns.Bound(x => x.Hosts) .Encoded(false); - columns.Bound(x => x.PrimaryStoreCurrency); - columns.Bound(x => x.PrimaryExchangeRateCurrency); + columns.Bound(x => x.PrimaryStoreCurrencyName); + columns.Bound(x => x.PrimaryExchangeRateCurrencyName); columns.Bound(x => x.ContentDeliveryNetwork) .ClientTemplate("\" target=\"_blank\"><#= ContentDeliveryNetwork #>"); columns.Bound(x => x.SslEnabled) From fb9e46395abfc9c20af3aee731cf1eceb541f5f2 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 30 Jun 2015 12:23:02 +0200 Subject: [PATCH 0203/1256] PrimaryStoreCurrencyMultiStore migration may fail for SQL-Server Compact --- ...61756463_PrimaryStoreCurrencyMultiStore.cs | 53 ++++++++++++------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs index 98d7b998ea..95492db892 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -2,7 +2,9 @@ namespace SmartStore.Data.Migrations { using System.Data.Entity.Migrations; using System.Linq; + using SmartStore.Core.Data; using SmartStore.Core.Domain.Configuration; + using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Stores; using SmartStore.Data.Setup; @@ -10,18 +12,27 @@ public partial class PrimaryStoreCurrencyMultiStore : DbMigration, ILocaleResour { public override void Up() { - AddColumn("dbo.Store", "PrimaryStoreCurrencyId", c => c.Int(nullable: false)); - AddColumn("dbo.Store", "PrimaryExchangeRateCurrencyId", c => c.Int(nullable: false)); + AddColumn("dbo.Store", "PrimaryStoreCurrencyId", c => c.Int(nullable: false, defaultValue: 1)); + AddColumn("dbo.Store", "PrimaryExchangeRateCurrencyId", c => c.Int(nullable: false, defaultValue: 1)); // avoid conflicts with foreign key constraint - Sql("Update dbo.Store Set PrimaryStoreCurrencyId = (Select Top(1) [Id] From dbo.Currency)"); - Sql("Update dbo.Store Set PrimaryExchangeRateCurrencyId = (Select Top(1) [Id] From dbo.Currency)"); + if (DataSettings.Current.IsSqlServer) + { + // what sql-server compact does not support here: + // - Update Set with a select sub-query + // - Select in variable via declare + // - Alter table to check/nocheck a constraint + // so the the foreign key check constraint fails here (and therefore this migration) if there's no currency with id 1. + + Sql("Update dbo.Store Set PrimaryStoreCurrencyId = (Select Min(Id) From dbo.Currency)"); + Sql("Update dbo.Store Set PrimaryExchangeRateCurrencyId = (Select Min(Id) From dbo.Currency)"); + } CreateIndex("dbo.Store", "PrimaryStoreCurrencyId"); CreateIndex("dbo.Store", "PrimaryExchangeRateCurrencyId"); - AddForeignKey("dbo.Store", "PrimaryExchangeRateCurrencyId", "dbo.Currency", "Id"); - AddForeignKey("dbo.Store", "PrimaryStoreCurrencyId", "dbo.Currency", "Id"); + AddForeignKey("dbo.Store", "PrimaryExchangeRateCurrencyId", "dbo.Currency", "Id"); + AddForeignKey("dbo.Store", "PrimaryStoreCurrencyId", "dbo.Currency", "Id"); } public override void Down() @@ -46,24 +57,28 @@ public void Seed(SmartObjectContext context) context.MigrateLocaleResources(MigrateLocaleResources); var settings = context.Set(); - var primaryStoreCurrency = settings.FirstOrDefault(x => x.Name == "CurrencySettings.PrimaryStoreCurrencyId"); - var primaryExchangeRateCurrency = settings.FirstOrDefault(x => x.Name == "CurrencySettings.PrimaryExchangeRateCurrencyId"); + var primaryStoreCurrencySetting = settings.FirstOrDefault(x => x.Name == "CurrencySettings.PrimaryStoreCurrencyId"); + var primaryExchangeRateCurrencySetting = settings.FirstOrDefault(x => x.Name == "CurrencySettings.PrimaryExchangeRateCurrencyId"); + + int primaryStoreCurrencyId = primaryStoreCurrencySetting.Value.ToInt(); + int primaryExchangeRateCurrencyId = primaryExchangeRateCurrencySetting.Value.ToInt(); + + if (primaryStoreCurrencyId == 0) + primaryStoreCurrencyId = context.Set().First().Id; + + if (primaryExchangeRateCurrencyId == 0) + primaryExchangeRateCurrencyId = primaryStoreCurrencyId; var stores = context.Set().ToList(); - foreach (var store in stores) + stores.ForEach(x => { - int id = primaryStoreCurrency.Value.ToInt(); - if (id != 0) - store.PrimaryStoreCurrencyId = id; - - id = primaryExchangeRateCurrency.Value.ToInt(); - if (id != 0) - store.PrimaryExchangeRateCurrencyId = id; - } + x.PrimaryStoreCurrencyId = primaryStoreCurrencyId; + x.PrimaryExchangeRateCurrencyId = primaryExchangeRateCurrencyId; + }); - settings.Remove(primaryStoreCurrency); - settings.Remove(primaryExchangeRateCurrency); + settings.Remove(primaryStoreCurrencySetting); + settings.Remove(primaryExchangeRateCurrencySetting); context.SaveChanges(); } From d757c8ba5dcd3a3d1dd5bc5d7fa04b429003dce9 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 30 Jun 2015 12:36:13 +0200 Subject: [PATCH 0204/1256] Fixed unit testing failure --- .../Forums/PrivateMessagePersistenceTests.cs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/Tests/SmartStore.Data.Tests/Forums/PrivateMessagePersistenceTests.cs b/src/Tests/SmartStore.Data.Tests/Forums/PrivateMessagePersistenceTests.cs index 9ab69bb6e7..26f7b200ab 100644 --- a/src/Tests/SmartStore.Data.Tests/Forums/PrivateMessagePersistenceTests.cs +++ b/src/Tests/SmartStore.Data.Tests/Forums/PrivateMessagePersistenceTests.cs @@ -1,9 +1,9 @@ using System; +using NUnit.Framework; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Forums; +using SmartStore.Data.Tests.Stores; using SmartStore.Tests; -using NUnit.Framework; -using SmartStore.Core.Domain.Stores; namespace SmartStore.Data.Tests.Forums { @@ -13,7 +13,7 @@ public class PrivateMessagePersistenceTests : PersistenceTest [Test] public void Can_save_and_load_privatemessage() { - var store = GetTestStore(); + var store = StorePersistenceTests.GetTestStore(); var storeFromDb = SaveAndLoadEntity(store); storeFromDb.ShouldNotBeNull(); @@ -59,15 +59,5 @@ protected Customer GetTestCustomer() LastActivityDateUtc = new DateTime(2010, 01, 02) }; } - - protected Store GetTestStore() - { - return new Store - { - Name = "Store 1", - Url = "http://www.test.com", - DisplayOrder = 1 - }; - } } } From 79ebde8c484b1886d031a7e8667eca1189511756 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 30 Jun 2015 16:38:59 +0200 Subject: [PATCH 0205/1256] Resolves #725 Prevent LowestProductPrice being 0 --- changelog.md | 1 + .../Catalog/PriceCalculationService.cs | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/changelog.md b/changelog.md index eddfefc44a..5060856f29 100644 --- a/changelog.md +++ b/changelog.md @@ -14,6 +14,7 @@ ### Improvements * (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%. * #721 Message Queue: implement "Delete all" +* #725 Prevent LowestProductPrice being 0 ## SmartStore.NET 2.2.2 diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index e61c60cc35..e28b08d053 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -476,6 +476,15 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa } } + if (lowestPrice == decimal.Zero && product.Price == decimal.Zero) + { + var combination = product.ProductVariantAttributeCombinations.OrderBy(x => x.Price).FirstOrDefault(x => x.Price > decimal.Zero); + if (combination != null) + { + lowestPrice = combination.Price ?? decimal.Zero; + } + } + return lowestPrice; } From 368471c9939d3572a77884c6086b8919fa251f63 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 30 Jun 2015 17:29:55 +0200 Subject: [PATCH 0206/1256] Topics grid: fix 'maxJsonLength exceeded' error --- .../Administration/Controllers/TopicController.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/TopicController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/TopicController.cs index 70e91c379a..6531b74c64 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/TopicController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/TopicController.cs @@ -121,10 +121,13 @@ public ActionResult List() return AccessDeniedView(); var model = new TopicListModel(); - //stores + + // stores model.AvailableStores.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" }); foreach (var s in _storeService.GetAllStores()) + { model.AvailableStores.Add(new SelectListItem() { Text = s.Name, Value = s.Id.ToString() }); + } return View(model); } @@ -138,7 +141,12 @@ public ActionResult List(GridCommand command, TopicListModel model) var topics = _topicService.GetAllTopics(model.SearchStoreId); var gridModel = new GridModel { - Data = topics.Select(x => x.ToModel()), + Data = topics.Select(x => { + var item = x.ToModel(); + // otherwise maxJsonLength could be exceeded + item.Body = ""; + return item; + }), Total = topics.Count }; return new JsonResult From 9f90717731f652c3c1d62d7ef8af25d7f7ae4495 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 30 Jun 2015 17:31:31 +0200 Subject: [PATCH 0207/1256] Updated changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 4bfdee62c9..36cac97370 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,7 @@ * #694 Product variant attribute in product page should not be preselected implicitly * Fixed: If currencies are limited to one for a multi-store, this currency should dominate the setting for the primary store currency * #563 Scheduled Tasks: ensure, that 'LastEndUtc' is ALWAYS set +* Topics grid: fixed 'maxJsonLength exceeded' error ## SmartStore.NET 2.2.1 From b8b855e6f9dcc68e61960caf1118e49d13e7c8a3 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 30 Jun 2015 21:04:14 +0200 Subject: [PATCH 0208/1256] E-mail attachments: test cases --- .../Email/DefaultEmailSender.cs | 17 +- .../Messages/QueuedEmailService.cs | 149 ++++++++--------- .../Controllers/EmailAccountController.cs | 1 - .../Messages/Attachment.pdf | Bin 0 -> 5064 bytes .../Messages/QueuedEmailServiceTests.cs | 155 ++++++++++++++++++ .../SmartStore.Services.Tests.csproj | 3 + 6 files changed, 243 insertions(+), 82 deletions(-) create mode 100644 src/Tests/SmartStore.Services.Tests/Messages/Attachment.pdf create mode 100644 src/Tests/SmartStore.Services.Tests/Messages/QueuedEmailServiceTests.cs diff --git a/src/Libraries/SmartStore.Core/Email/DefaultEmailSender.cs b/src/Libraries/SmartStore.Core/Email/DefaultEmailSender.cs index 42f9b99eec..b9862e0c52 100644 --- a/src/Libraries/SmartStore.Core/Email/DefaultEmailSender.cs +++ b/src/Libraries/SmartStore.Core/Email/DefaultEmailSender.cs @@ -68,11 +68,12 @@ public void SendEmail(SmtpContext context, EmailMessage message) Guard.ArgumentNotNull(() => context); Guard.ArgumentNotNull(() => message); - var msg = this.BuildMailMessage(message); - - using (var client = context.ToSmtpClient()) + using (var msg = this.BuildMailMessage(message)) { - client.Send(msg); + using (var client = context.ToSmtpClient()) + { + client.Send(msg); + } } } @@ -81,12 +82,14 @@ public Task SendEmailAsync(SmtpContext context, EmailMessage message) Guard.ArgumentNotNull(() => context); Guard.ArgumentNotNull(() => message); + var client = context.ToSmtpClient(); var msg = this.BuildMailMessage(message); - using (var client = context.ToSmtpClient()) + return client.SendMailAsync(msg).ContinueWith(t => { - return client.SendMailAsync(msg); - } + client.Dispose(); + msg.Dispose(); + }); } #endregion diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs index 78fe190196..1c40be1554 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs @@ -12,30 +12,28 @@ using SmartStore.Services.Localization; using SmartStore.Utilities; using System.Web; +using SmartStore.Core.Localization; namespace SmartStore.Services.Messages { public partial class QueuedEmailService : IQueuedEmailService { private readonly IRepository _queuedEmailRepository; - private readonly IEventPublisher _eventPublisher; private readonly IEmailSender _emailSender; - private readonly ILogger _logger; - private readonly ILocalizationService _localizationService; - - public QueuedEmailService( - IRepository queuedEmailRepository, - IEventPublisher eventPublisher, - IEmailSender emailSender, - ILogger logger, - ILocalizationService localizationService) + private readonly ICommonServices _services; + + public QueuedEmailService(IRepository queuedEmailRepository, IEmailSender emailSender, ICommonServices services) { - _queuedEmailRepository = queuedEmailRepository; - _eventPublisher = eventPublisher; - _emailSender = emailSender; - _logger = logger; - _localizationService = localizationService; + this._queuedEmailRepository = queuedEmailRepository; + this._emailSender = emailSender; + this._services = services; + + T = NullLocalizer.Instance; + Logger = NullLogger.Instance; } + + public Localizer T { get; set; } + public ILogger Logger { get; set; } public virtual void InsertQueuedEmail(QueuedEmail queuedEmail) { @@ -45,7 +43,7 @@ public virtual void InsertQueuedEmail(QueuedEmail queuedEmail) _queuedEmailRepository.Insert(queuedEmail); //event notification - _eventPublisher.EntityInserted(queuedEmail); + _services.EventPublisher.EntityInserted(queuedEmail); } public virtual void UpdateQueuedEmail(QueuedEmail queuedEmail) @@ -56,7 +54,7 @@ public virtual void UpdateQueuedEmail(QueuedEmail queuedEmail) _queuedEmailRepository.Update(queuedEmail); //event notification - _eventPublisher.EntityUpdated(queuedEmail); + _services.EventPublisher.EntityUpdated(queuedEmail); } public virtual void DeleteQueuedEmail(QueuedEmail queuedEmail) @@ -67,7 +65,7 @@ public virtual void DeleteQueuedEmail(QueuedEmail queuedEmail) _queuedEmailRepository.Delete(queuedEmail); //event notification - _eventPublisher.EntityDeleted(queuedEmail); + _services.EventPublisher.EntityDeleted(queuedEmail); } public virtual int DeleteAllQueuedEmails() @@ -155,33 +153,8 @@ public virtual bool SendEmail(QueuedEmail queuedEmail) try { - var bcc = String.IsNullOrWhiteSpace(queuedEmail.Bcc) ? null : queuedEmail.Bcc.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - var cc = String.IsNullOrWhiteSpace(queuedEmail.CC) ? null : queuedEmail.CC.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - var smtpContext = new SmtpContext(queuedEmail.EmailAccount); - - var msg = new EmailMessage( - new EmailAddress(queuedEmail.To, queuedEmail.ToName), - queuedEmail.Subject, - queuedEmail.Body, - new EmailAddress(queuedEmail.From, queuedEmail.FromName)); - - if (queuedEmail.ReplyTo.HasValue()) - { - msg.ReplyTo.Add(new EmailAddress(queuedEmail.ReplyTo, queuedEmail.ReplyToName)); - } - - if (cc != null) - { - msg.Cc.AddRange(cc.Where(x => x.HasValue()).Select(x => new EmailAddress(x))); - } - - if (bcc != null) - { - msg.Bcc.AddRange(bcc.Where(x => x.HasValue()).Select(x => new EmailAddress(x))); - } - - CreateAttachments(queuedEmail, msg); + var msg = ConvertEmail(queuedEmail); _emailSender.SendEmail(smtpContext, msg); @@ -190,7 +163,7 @@ public virtual bool SendEmail(QueuedEmail queuedEmail) } catch (Exception exc) { - _logger.Error(string.Concat(_localizationService.GetResource("Admin.Common.ErrorSendingEmail"), ": ", exc.Message), exc); + Logger.Error(string.Concat(T("Admin.Common.ErrorSendingEmail"), ": ", exc.Message), exc); } finally { @@ -201,52 +174,80 @@ public virtual bool SendEmail(QueuedEmail queuedEmail) return result; } - private void CreateAttachments(QueuedEmail qe, EmailMessage msg) + private void AddEmailAddresses(string addresses, ICollection target) + { + var arr = addresses.IsEmpty() ? null : addresses.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + if (arr != null && arr.Length > 0) + { + target.AddRange(arr.Where(x => x.Trim().HasValue()).Select(x => new EmailAddress(x))); + } + } + + internal EmailMessage ConvertEmail(QueuedEmail qe) { - if (qe.Attachments == null || qe.Attachments.Count == 0) - return; + // 'internal' for testing purposes + + var msg = new EmailMessage( + new EmailAddress(qe.To, qe.ToName), + qe.Subject, + qe.Body, + new EmailAddress(qe.From, qe.FromName)); - foreach (var qea in qe.Attachments) + if (qe.ReplyTo.HasValue()) { - Attachment attachment = null; + msg.ReplyTo.Add(new EmailAddress(qe.ReplyTo, qe.ReplyToName)); + } - if (qea.StorageLocation == EmailAttachmentStorageLocation.Blob) + AddEmailAddresses(qe.CC, msg.Cc); + AddEmailAddresses(qe.Bcc, msg.Bcc); + + if (qe.Attachments != null && qe.Attachments.Count > 0) + { + foreach (var qea in qe.Attachments) { - var data = qea.Data; - if (data != null && data.Length > 0) + Attachment attachment = null; + + if (qea.StorageLocation == EmailAttachmentStorageLocation.Blob) { - attachment = new Attachment(data.ToStream(), qea.Name, qea.MimeType); + var data = qea.Data; + if (data != null && data.Length > 0) + { + attachment = new Attachment(data.ToStream(), qea.Name, qea.MimeType); + } } - } - else if (qea.StorageLocation == EmailAttachmentStorageLocation.Path) - { - var path = qea.Path; - if (path.HasValue()) + else if (qea.StorageLocation == EmailAttachmentStorageLocation.Path) { - if (path[0] == '~' || path[0] == '/') + var path = qea.Path; + if (path.HasValue()) { - path = CommonHelper.MapPath(VirtualPathUtility.ToAppRelative(path)); + if (path[0] == '~' || path[0] == '/') + { + path = CommonHelper.MapPath(VirtualPathUtility.ToAppRelative(path), false); + } + if (File.Exists(path)) + { + attachment = new Attachment(path, qea.MimeType); + attachment.Name = qea.Name; + } } - if (File.Exists(path)) + } + else if (qea.StorageLocation == EmailAttachmentStorageLocation.FileReference) + { + var file = qea.File; + if (file != null && file.UseDownloadUrl == false && file.DownloadBinary != null && file.DownloadBinary.Length > 0) { - attachment = new Attachment(path, qea.MimeType); + attachment = new Attachment(file.DownloadBinary.ToStream(), file.Filename + file.Extension, file.ContentType); } } - } - else if (qea.StorageLocation == EmailAttachmentStorageLocation.FileReference) - { - var file = qea.File; - if (file != null && file.UseDownloadUrl == false && file.DownloadBinary != null && file.DownloadBinary.Length > 0) + + if (attachment != null) { - attachment = new Attachment(file.DownloadBinary.ToStream(), file.Filename + file.Extension, file.ContentType); + msg.Attachments.Add(attachment); } } - - if (attachment != null) - { - msg.Attachments.Add(attachment); - } } + + return msg; } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs index b7ffea3206..c71aaed290 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs @@ -182,7 +182,6 @@ public ActionResult SendTestEmail(EmailAccountModel model) if (String.IsNullOrWhiteSpace(model.SendTestEmailTo)) throw new SmartException("Enter test email address"); - var to = new EmailAddress(model.SendTestEmailTo); var from = new EmailAddress(emailAccount.Email, emailAccount.DisplayName); string subject = _storeContext.CurrentStore.Name + ". Testing email functionality."; diff --git a/src/Tests/SmartStore.Services.Tests/Messages/Attachment.pdf b/src/Tests/SmartStore.Services.Tests/Messages/Attachment.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e6654ec8bedfb85691ae63c6bbbb280b5ab63ee9 GIT binary patch literal 5064 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 literal 0 HcmV?d00001 diff --git a/src/Tests/SmartStore.Services.Tests/Messages/QueuedEmailServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Messages/QueuedEmailServiceTests.cs new file mode 100644 index 0000000000..7f0ea69976 --- /dev/null +++ b/src/Tests/SmartStore.Services.Tests/Messages/QueuedEmailServiceTests.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using SmartStore.Core.Data; +using SmartStore.Core.Domain.Messages; +using SmartStore.Core.Events; +using SmartStore.Core.Email; +using SmartStore.Services.Messages; +using NUnit.Framework; +using Rhino.Mocks; +using SmartStore.Services.Stores; +using System.Web.Mail; +using SmartStore.Utilities; +using SmartStore.Core.Domain.Media; +using System.Threading.Tasks; + +namespace SmartStore.Services.Tests.Messages +{ + [TestFixture] + public class QueuedEmailServiceTests : ServiceTest + { + IRepository _qeRepository; + IEmailSender _emailSender; + ICommonServices _commonServices; + QueuedEmailService _queuedEmailService; + + [SetUp] + public new void SetUp() + { + _qeRepository = MockRepository.GenerateStub>(); + _emailSender = MockRepository.GenerateStub(); + _commonServices = MockRepository.GenerateStub(); + + _queuedEmailService = new QueuedEmailService(_qeRepository, _emailSender, _commonServices); + } + + [Test] + public void Can_convert_email() + { + var qe = new QueuedEmail + { + Bcc = "bcc1@mail.com;bcc2@mail.com", + Body = "Body", + CC = "cc1@mail.com;cc2@mail.com", + CreatedOnUtc = DateTime.UtcNow, + From = "from@mail.com", + FromName = "FromName", + Priority = 10, + ReplyTo = "replyto@mail.com", + ReplyToName = "ReplyToName", + Subject = "Subject", + To = "to@mail.com", + ToName = "ToName" + }; + + // load attachment file resource and save as file + var asm = typeof(QueuedEmailServiceTests).Assembly; + var pdfStream = asm.GetManifestResourceStream("{0}.Messages.Attachment.pdf".FormatInvariant(asm.GetName().Name)); + var pdfBinary = pdfStream.ToByteArray(); + pdfStream.Seek(0, SeekOrigin.Begin); + var path1 = "~/Attachment.pdf"; + var path2 = CommonHelper.MapPath(path1, false); + Assert.IsTrue(pdfStream.ToFile(path2)); + + var attachBlob = new QueuedEmailAttachment + { + StorageLocation = EmailAttachmentStorageLocation.Blob, + Data = pdfBinary, + Name = "blob.pdf", + MimeType = "application/pdf" + }; + var attachPath1 = new QueuedEmailAttachment + { + StorageLocation = EmailAttachmentStorageLocation.Path, + Path = path1, + Name = "path1.pdf", + MimeType = "application/pdf" + }; + var attachPath2 = new QueuedEmailAttachment + { + StorageLocation = EmailAttachmentStorageLocation.Path, + Path = path2, + Name = "path2.pdf", + MimeType = "application/pdf" + }; + var attachFile = new QueuedEmailAttachment + { + StorageLocation = EmailAttachmentStorageLocation.FileReference, + Name = "file.pdf", + MimeType = "application/pdf", + File = new Download + { + ContentType = "application/pdf", + DownloadBinary = pdfBinary, + Extension = ".pdf", + Filename = "file" + } + }; + + qe.Attachments.Add(attachBlob); + qe.Attachments.Add(attachFile); + qe.Attachments.Add(attachPath1); + qe.Attachments.Add(attachPath2); + + var msg = _queuedEmailService.ConvertEmail(qe); + + Assert.IsNotNull(msg); + Assert.IsNotNull(msg.To); + Assert.IsNotNull(msg.From); + + Assert.AreEqual(msg.ReplyTo.Count, 1); + Assert.AreEqual(qe.ReplyTo, msg.ReplyTo.First().Address); + Assert.AreEqual(qe.ReplyToName, msg.ReplyTo.First().DisplayName); + + Assert.AreEqual(msg.Cc.Count, 2); + Assert.AreEqual(msg.Cc.First().Address, "cc1@mail.com"); + Assert.AreEqual(msg.Cc.ElementAt(1).Address, "cc2@mail.com"); + + Assert.AreEqual(msg.Bcc.Count, 2); + Assert.AreEqual(msg.Bcc.First().Address, "bcc1@mail.com"); + Assert.AreEqual(msg.Bcc.ElementAt(1).Address, "bcc2@mail.com"); + + Assert.AreEqual(qe.Subject, msg.Subject); + Assert.AreEqual(qe.Body, msg.Body); + + Assert.AreEqual(msg.Attachments.Count, 4); + + var attach1 = msg.Attachments.First(); + var attach2 = msg.Attachments.ElementAt(1); + var attach3 = msg.Attachments.ElementAt(2); + var attach4 = msg.Attachments.ElementAt(3); + + // test file names + Assert.AreEqual(attach1.Name, "blob.pdf"); + Assert.AreEqual(attach2.Name, "file.pdf"); + Assert.AreEqual(attach3.Name, "path1.pdf"); + Assert.AreEqual(attach4.Name, "path2.pdf"); + + // test file streams + Assert.AreEqual(attach1.ContentStream.Length, pdfBinary.Length); + Assert.AreEqual(attach2.ContentStream.Length, pdfBinary.Length); + Assert.Greater(attach3.ContentStream.Length, 0); + Assert.Greater(attach4.ContentStream.Length, 0); + + // cleanup + msg.Attachments.Each(x => x.Dispose()); + msg.Attachments.Clear(); + + // delete attachment file + File.Delete(path2); + } + + } +} \ No newline at end of file diff --git a/src/Tests/SmartStore.Services.Tests/SmartStore.Services.Tests.csproj b/src/Tests/SmartStore.Services.Tests/SmartStore.Services.Tests.csproj index a264eb3938..4ea6b276d1 100644 --- a/src/Tests/SmartStore.Services.Tests/SmartStore.Services.Tests.csproj +++ b/src/Tests/SmartStore.Services.Tests/SmartStore.Services.Tests.csproj @@ -77,6 +77,7 @@ + @@ -104,6 +105,7 @@ + @@ -143,6 +145,7 @@ + From efb74dd791b5264d5878d52bd43789eb1b0f445f Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 1 Jul 2015 00:19:01 +0200 Subject: [PATCH 0209/1256] E-mail attachments: event & co. --- .../Messages/EventPublisherExtensions.cs | 7 +- .../Messages/MessageTokenProvider.cs | 12 ++- .../Messages/QueuingEmailEvent.cs | 42 +++++++++ .../Messages/QueuingEmailEventConsumer.cs | 46 ++++++++++ .../Messages/WorkflowMessageService.cs | 17 +++- .../Orders/OrderProcessingService.cs | 86 +++++++++---------- .../SmartStore.Services.csproj | 2 + .../OrderPlacedEventConsumer.cs | 4 +- 8 files changed, 154 insertions(+), 62 deletions(-) create mode 100644 src/Libraries/SmartStore.Services/Messages/QueuingEmailEvent.cs create mode 100644 src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs diff --git a/src/Libraries/SmartStore.Services/Messages/EventPublisherExtensions.cs b/src/Libraries/SmartStore.Services/Messages/EventPublisherExtensions.cs index ada12006c8..681cb588b6 100644 --- a/src/Libraries/SmartStore.Services/Messages/EventPublisherExtensions.cs +++ b/src/Libraries/SmartStore.Services/Messages/EventPublisherExtensions.cs @@ -1,4 +1,5 @@ -using SmartStore.Core; +using System.Collections.Generic; +using SmartStore.Core; using SmartStore.Core.Domain.Messages; using SmartStore.Core.Events; @@ -26,12 +27,12 @@ public static void PublishNewsletterUnsubscribe(this IEventPublisher eventPublis eventPublisher.Publish(new EmailUnsubscribedEvent(email)); } - public static void EntityTokensAdded(this IEventPublisher eventPublisher, T entity, System.Collections.Generic.IList tokens) where T : BaseEntity + public static void EntityTokensAdded(this IEventPublisher eventPublisher, T entity, IList tokens) where T : BaseEntity { eventPublisher.Publish(new EntityTokensAddedEvent(entity, tokens)); } - public static void MessageTokensAdded(this IEventPublisher eventPublisher, MessageTemplate message, System.Collections.Generic.IList tokens) + public static void MessageTokensAdded(this IEventPublisher eventPublisher, MessageTemplate message, IList tokens) { eventPublisher.Publish(new MessageTokensAddedEvent(message, tokens)); } diff --git a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs index ed4c1ea719..23a16fffb2 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs @@ -716,16 +716,14 @@ public virtual void AddContactDataTokens(IList tokens) tokens.Add(new Token("Contact.ContactEmailAddress", _contactDataSettings.ContactEmailAddress)); } - //codehint: sm-add end - public virtual void AddOrderTokens(IList tokens, Order order, int languageId) { - tokens.Add(new Token("Order.OrderNumber", order.GetOrderNumber())); + tokens.Add(new Token("Order.ID", order.Id.ToString())); + tokens.Add(new Token("Order.OrderNumber", order.GetOrderNumber())); tokens.Add(new Token("Order.CustomerFullName", string.Format("{0} {1}", order.BillingAddress.FirstName, order.BillingAddress.LastName))); tokens.Add(new Token("Order.CustomerEmail", order.BillingAddress.Email)); - tokens.Add(new Token("Order.BillingFirstName", order.BillingAddress.FirstName)); tokens.Add(new Token("Order.BillingLastName", order.BillingAddress.LastName)); tokens.Add(new Token("Order.BillingPhoneNumber", order.BillingAddress.PhoneNumber)); @@ -772,7 +770,7 @@ public virtual void AddOrderTokens(IList tokens, Order order, int languag tokens.Add(new Token("Order.CreatedOn", order.CreatedOnUtc.ToString("D"))); } - //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) + // TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) tokens.Add(new Token("Order.OrderURLForCustomer", string.Format("{0}order/details/{1}", _webHelper.GetStoreLocation(false), order.Id), true)); tokens.Add(new Token("Order.Disclaimer", TopicToHtml("Disclaimer", languageId), true)); @@ -861,13 +859,13 @@ public virtual void AddGiftCardTokens(IList tokens, GiftCard giftCard) public virtual void AddCustomerTokens(IList tokens, Customer customer) { - tokens.Add(new Token("Customer.Email", customer.Email)); + tokens.Add(new Token("Customer.ID", customer.Id.ToString())); + tokens.Add(new Token("Customer.Email", customer.Email)); tokens.Add(new Token("Customer.Username", customer.Username)); tokens.Add(new Token("Customer.FullName", customer.GetFullName())); tokens.Add(new Token("Customer.VatNumber", customer.GetAttribute(SystemCustomerAttributeNames.VatNumber))); tokens.Add(new Token("Customer.VatNumberStatus", ((VatNumberStatus)customer.GetAttribute(SystemCustomerAttributeNames.VatNumberStatusId)).ToString())); - //note: we do not use SEO friendly URLS because we can get errors caused by having .(dot) in the URL (from the emauk address) //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) string passwordRecoveryUrl = string.Format("{0}customer/passwordrecoveryconfirm?token={1}&email={2}", _webHelper.GetStoreLocation(), diff --git a/src/Libraries/SmartStore.Services/Messages/QueuingEmailEvent.cs b/src/Libraries/SmartStore.Services/Messages/QueuingEmailEvent.cs new file mode 100644 index 0000000000..d9efdacd84 --- /dev/null +++ b/src/Libraries/SmartStore.Services/Messages/QueuingEmailEvent.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using SmartStore.Core.Domain.Messages; + +namespace SmartStore.Services.Messages +{ + /// + /// An event message, which gets published just before a new instance + /// of is persisted to the database + /// + public class QueuingEmailEvent + { + public QueuedEmail QueuedEmail + { + get; + set; + } + + public MessageTemplate MessageTemplate + { + get; + set; + } + + public EmailAccount EmailAccount + { + get; + set; + } + + public IList Tokens + { + get; + set; + } + + public int LanguageId + { + get; + set; + } + } +} diff --git a/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs b/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs new file mode 100644 index 0000000000..04bb77d509 --- /dev/null +++ b/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SmartStore.Core.Domain.Common; +using SmartStore.Core.Domain.Messages; +using SmartStore.Core.Events; + +namespace SmartStore.Services.Messages +{ + public class QueuingEmailEventConsumer : IConsumer + { + private readonly PdfSettings _pdfSettings; + + public QueuingEmailEventConsumer(PdfSettings pdfSettings) + { + this._pdfSettings = pdfSettings; + } + + public void HandleEvent(QueuingEmailEvent eventMessage) + { + var qe = eventMessage.QueuedEmail; + var tpl = eventMessage.MessageTemplate; + + // TODO: (mc) determine and apply PdfSettings + + if (tpl.Name.IsCaseInsensitiveEqual("OrderPlaced.CustomerNotification")) + { + var orderId = eventMessage.Tokens.First(x => x.Key.IsCaseInsensitiveEqual("Order.ID")).Value.ToInt(); + var qea = CreatePdfInvoiceAttachment(orderId); + if (qea != null) + { + qe.Attachments.Add(qea); + } + } + } + + private QueuedEmailAttachment CreatePdfInvoiceAttachment(int orderId) + { + // TODO: (mc) implement + return null; + } + + } +} diff --git a/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs b/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs index b194690096..57efae24d2 100644 --- a/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs +++ b/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs @@ -74,7 +74,7 @@ protected int SendNotification( MessageTemplate messageTemplate, EmailAccount emailAccount, int languageId, - IEnumerable tokens, + IList tokens, string toEmailAddress, string toName, string replyTo = null, @@ -90,7 +90,7 @@ protected int SendNotification( var bodyReplaced = _tokenizer.Replace(body, tokens, true); bodyReplaced = WebHelper.MakeAllUrlsAbsolute(bodyReplaced, _httpRequest); - + var email = new QueuedEmail { Priority = 5, @@ -109,7 +109,18 @@ protected int SendNotification( SendManually = messageTemplate.SendManually }; + // publish event so that integrators can add attachments, alter the email etc. + _eventPublisher.Publish(new QueuingEmailEvent + { + EmailAccount = emailAccount, + LanguageId = languageId, + MessageTemplate = messageTemplate, + QueuedEmail = email, + Tokens = tokens + }); + _queuedEmailService.InsertQueuedEmail(email); + return email.Id; } @@ -434,7 +445,7 @@ public virtual int SendOrderPlacedCustomerNotification(Order order, int language _messageTokenProvider.AddBankConnectionTokens(tokens); _messageTokenProvider.AddContactDataTokens(tokens); - //event notification + // event notification _eventPublisher.MessageTokensAdded(messageTemplate, tokens); var emailAccount = GetEmailAccountOfMessageTemplate(messageTemplate, languageId); diff --git a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs index a1b07c3749..1ce5ce0eb6 100644 --- a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs +++ b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs @@ -203,7 +203,7 @@ private decimal Round(decimal value) return (_shoppingCartSettings.RoundPricesDuringCalculation ? Math.Round(value, 2) : value); } - private string T(string resKey) + private string TNote(string resKey) { return _localizationService.GetResource("Admin.OrderNotice." + resKey); } @@ -348,26 +348,24 @@ protected void SetOrderStatus(Order order, OrderStatus os, bool notifyCustomer) _orderService.UpdateOrder(order); //order notes, notifications - order.OrderNotes.Add(new OrderNote() + order.OrderNotes.Add(new OrderNote { - Note = string.Format(T("OrderStatusChanged"), os.GetLocalizedEnum(_localizationService)), + Note = string.Format(TNote("OrderStatusChanged"), os.GetLocalizedEnum(_localizationService)), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); - if (prevOrderStatus != OrderStatus.Complete && - os == OrderStatus.Complete - && notifyCustomer) + if (prevOrderStatus != OrderStatus.Complete && os == OrderStatus.Complete && notifyCustomer) { //notification int orderCompletedCustomerNotificationQueuedEmailId = _workflowMessageService.SendOrderCompletedCustomerNotification(order, order.CustomerLanguageId); if (orderCompletedCustomerNotificationQueuedEmailId > 0) { - order.OrderNotes.Add(new OrderNote() + order.OrderNotes.Add(new OrderNote { - Note = string.Format(T("CustomerCompletedEmailQueued"), orderCompletedCustomerNotificationQueuedEmailId), + Note = string.Format(TNote("CustomerCompletedEmailQueued"), orderCompletedCustomerNotificationQueuedEmailId), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -375,17 +373,15 @@ protected void SetOrderStatus(Order order, OrderStatus os, bool notifyCustomer) } } - if (prevOrderStatus != OrderStatus.Cancelled && - os == OrderStatus.Cancelled - && notifyCustomer) + if (prevOrderStatus != OrderStatus.Cancelled && os == OrderStatus.Cancelled && notifyCustomer) { //notification int orderCancelledCustomerNotificationQueuedEmailId = _workflowMessageService.SendOrderCancelledCustomerNotification(order, order.CustomerLanguageId); if (orderCancelledCustomerNotificationQueuedEmailId > 0) { - order.OrderNotes.Add(new OrderNote() + order.OrderNotes.Add(new OrderNote { - Note = string.Format(T("CustomerCancelledEmailQueued"), orderCancelledCustomerNotificationQueuedEmailId), + Note = string.Format(TNote("CustomerCancelledEmailQueued"), orderCancelledCustomerNotificationQueuedEmailId), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -437,8 +433,7 @@ public void CheckOrderStatus(Order order) if (order.OrderStatus == OrderStatus.Pending) { - if (order.PaymentStatus == PaymentStatus.Authorized || - order.PaymentStatus == PaymentStatus.Paid) + if (order.PaymentStatus == PaymentStatus.Authorized || order.PaymentStatus == PaymentStatus.Paid) { SetOrderStatus(order, OrderStatus.Processing, false); } @@ -446,16 +441,13 @@ public void CheckOrderStatus(Order order) if (order.OrderStatus == OrderStatus.Pending) { - if (order.ShippingStatus == ShippingStatus.PartiallyShipped || - order.ShippingStatus == ShippingStatus.Shipped || - order.ShippingStatus == ShippingStatus.Delivered) + if (order.ShippingStatus == ShippingStatus.PartiallyShipped || order.ShippingStatus == ShippingStatus.Shipped || order.ShippingStatus == ShippingStatus.Delivered) { SetOrderStatus(order, OrderStatus.Processing, false); } } - if (order.OrderStatus != OrderStatus.Cancelled && - order.OrderStatus != OrderStatus.Complete) + if (order.OrderStatus != OrderStatus.Cancelled && order.OrderStatus != OrderStatus.Complete) { if (order.PaymentStatus == PaymentStatus.Paid) { @@ -1348,7 +1340,7 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR //notes, messages order.OrderNotes.Add(new OrderNote() { - Note = T("OrderPlaced"), + Note = TNote("OrderPlaced"), DisplayToCustomer = false, CreatedOnUtc = utcNow }); @@ -1358,9 +1350,9 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR int orderPlacedStoreOwnerNotificationQueuedEmailId = _workflowMessageService.SendOrderPlacedStoreOwnerNotification(order, _localizationSettings.DefaultAdminLanguageId); if (orderPlacedStoreOwnerNotificationQueuedEmailId > 0) { - order.OrderNotes.Add(new OrderNote() + order.OrderNotes.Add(new OrderNote { - Note = string.Format(T("MerchantEmailQueued"), orderPlacedStoreOwnerNotificationQueuedEmailId), + Note = string.Format(TNote("MerchantEmailQueued"), orderPlacedStoreOwnerNotificationQueuedEmailId), DisplayToCustomer = false, CreatedOnUtc = utcNow }); @@ -1370,9 +1362,9 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR int orderPlacedCustomerNotificationQueuedEmailId = _workflowMessageService.SendOrderPlacedCustomerNotification(order, order.CustomerLanguageId); if (orderPlacedCustomerNotificationQueuedEmailId > 0) { - order.OrderNotes.Add(new OrderNote() + order.OrderNotes.Add(new OrderNote { - Note = string.Format(T("CustomerEmailQueued"), orderPlacedCustomerNotificationQueuedEmailId), + Note = string.Format(TNote("CustomerEmailQueued"), orderPlacedCustomerNotificationQueuedEmailId), DisplayToCustomer = false, CreatedOnUtc = utcNow }); @@ -1405,7 +1397,7 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR _localizationService.GetResource("ActivityLog.PublicStore.PlaceOrder"), order.GetOrderNumber()); } - + //raise event if (order.PaymentStatus == PaymentStatus.Paid) { @@ -1463,7 +1455,7 @@ public virtual void DeleteOrder(Order order) //add a note order.OrderNotes.Add(new OrderNote() { - Note = T("OrderDeleted"), + Note = TNote("OrderDeleted"), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -1577,7 +1569,7 @@ public virtual IList CancelRecurringPayment(RecurringPayment recurringPa //add a note initialOrder.OrderNotes.Add(new OrderNote() { - Note = T("RecurringPaymentCancelled"), + Note = TNote("RecurringPaymentCancelled"), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -1610,7 +1602,7 @@ public virtual IList CancelRecurringPayment(RecurringPayment recurringPa //add a note initialOrder.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("RecurringPaymentCancellationError"), error), + Note = string.Format(TNote("RecurringPaymentCancellationError"), error), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -1692,7 +1684,7 @@ public virtual void Ship(Shipment shipment, bool notifyCustomer) //add a note order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("ShipmentSent"), shipment.Id), + Note = string.Format(TNote("ShipmentSent"), shipment.Id), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -1706,7 +1698,7 @@ public virtual void Ship(Shipment shipment, bool notifyCustomer) { order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("CustomerShippedEmailQueued"), queuedEmailId), + Note = string.Format(TNote("CustomerShippedEmailQueued"), queuedEmailId), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -1745,7 +1737,7 @@ public virtual void Deliver(Shipment shipment, bool notifyCustomer) //add a note order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("ShipmentDelivered"), shipment.Id), + Note = string.Format(TNote("ShipmentDelivered"), shipment.Id), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -1759,7 +1751,7 @@ public virtual void Deliver(Shipment shipment, bool notifyCustomer) { order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("CustomerDeliveredEmailQueued"), queuedEmailId), + Note = string.Format(TNote("CustomerDeliveredEmailQueued"), queuedEmailId), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -1808,7 +1800,7 @@ public virtual void CancelOrder(Order order, bool notifyCustomer) //add a note order.OrderNotes.Add(new OrderNote() { - Note = T("OrderCancelled"), + Note = TNote("OrderCancelled"), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -1926,7 +1918,7 @@ public virtual void MarkAsAuthorized(Order order) //add a note order.OrderNotes.Add(new OrderNote() { - Note = T("OrderMarkedAsAuthorized"), + Note = TNote("OrderMarkedAsAuthorized"), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2032,7 +2024,7 @@ public virtual IList Capture(Order order) //add a note order.OrderNotes.Add(new OrderNote() { - Note = T("OrderCaptured"), + Note = TNote("OrderCaptured"), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2075,7 +2067,7 @@ public virtual IList Capture(Order order) _orderService.UpdateOrder(order); //log it - string logError = string.Format(T("OrderCaptureError"), order.GetOrderNumber(), error); + string logError = string.Format(TNote("OrderCaptureError"), order.GetOrderNumber(), error); _logger.InsertLog(LogLevel.Error, logError, logError); } return result.Errors; @@ -2121,7 +2113,7 @@ public virtual void MarkOrderAsPaid(Order order) //add a note order.OrderNotes.Add(new OrderNote() { - Note = T("OrderMarkedAsPaid"), + Note = TNote("OrderMarkedAsPaid"), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2196,7 +2188,7 @@ public virtual IList Refund(Order order) //add a note order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("OrderRefunded"), _priceFormatter.FormatPrice(request.AmountToRefund, true, false)), + Note = string.Format(TNote("OrderRefunded"), _priceFormatter.FormatPrice(request.AmountToRefund, true, false)), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2227,7 +2219,7 @@ public virtual IList Refund(Order order) //add a note order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("OrderRefundError"), error), + Note = string.Format(TNote("OrderRefundError"), error), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2289,7 +2281,7 @@ public virtual void RefundOffline(Order order) //add a note order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("OrderMarkedAsRefunded"), _priceFormatter.FormatPrice(amountToRefund, true, false)), + Note = string.Format(TNote("OrderMarkedAsRefunded"), _priceFormatter.FormatPrice(amountToRefund, true, false)), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2370,7 +2362,7 @@ public virtual IList PartiallyRefund(Order order, decimal amountToRefund //add a note order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("OrderPartiallyRefunded"), _priceFormatter.FormatPrice(amountToRefund, true, false)), + Note = string.Format(TNote("OrderPartiallyRefunded"), _priceFormatter.FormatPrice(amountToRefund, true, false)), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2400,7 +2392,7 @@ public virtual IList PartiallyRefund(Order order, decimal amountToRefund //add a note order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("OrderPartiallyRefundError"), error), + Note = string.Format(TNote("OrderPartiallyRefundError"), error), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2470,7 +2462,7 @@ public virtual void PartiallyRefundOffline(Order order, decimal amountToRefund) //add a note order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("OrderMarkedAsPartiallyRefunded"), _priceFormatter.FormatPrice(amountToRefund, true, false)), + Note = string.Format(TNote("OrderMarkedAsPartiallyRefunded"), _priceFormatter.FormatPrice(amountToRefund, true, false)), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2535,7 +2527,7 @@ public virtual IList Void(Order order) //add a note order.OrderNotes.Add(new OrderNote() { - Note = T("OrderVoided"), + Note = TNote("OrderVoided"), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2565,7 +2557,7 @@ public virtual IList Void(Order order) //add a note order.OrderNotes.Add(new OrderNote() { - Note = string.Format(T("OrderVoidError"), error), + Note = string.Format(TNote("OrderVoidError"), error), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); @@ -2619,7 +2611,7 @@ public virtual void VoidOffline(Order order) //add a note order.OrderNotes.Add(new OrderNote() { - Note = T("OrderMarkedAsVoided"), + Note = TNote("OrderMarkedAsVoided"), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index 91cca5e43a..d479dda36e 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -161,6 +161,8 @@ + + diff --git a/src/Plugins/SmartStore.Clickatell/OrderPlacedEventConsumer.cs b/src/Plugins/SmartStore.Clickatell/OrderPlacedEventConsumer.cs index 580460d574..3ba9e1742b 100644 --- a/src/Plugins/SmartStore.Clickatell/OrderPlacedEventConsumer.cs +++ b/src/Plugins/SmartStore.Clickatell/OrderPlacedEventConsumer.cs @@ -14,7 +14,7 @@ public class OrderPlacedEventConsumer : IConsumer private readonly IPluginFinder _pluginFinder; private readonly IOrderService _orderService; private readonly IStoreContext _storeContext; - private readonly ISettingService _settingService; // codehint: sm-add + private readonly ISettingService _settingService; public OrderPlacedEventConsumer(ClickatellSettings clickatellSettings, IPluginFinder pluginFinder, @@ -26,7 +26,7 @@ public OrderPlacedEventConsumer(ClickatellSettings clickatellSettings, this._pluginFinder = pluginFinder; this._orderService = orderService; this._storeContext = storeContext; - this._settingService = settingService; // codehint: sm-add + this._settingService = settingService; } /// From 471885419de3ae23ecf0a69891341aeb3c135cab Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 1 Jul 2015 11:58:43 +0200 Subject: [PATCH 0210/1256] #709 News feed produced invalid RSS feed. Added content:encoded. Added maximum news age setting for feed export. --- changelog.md | 1 + .../Domain/News/NewsSettings.cs | 9 +- .../SmartStore.Core/SmartStore.Core.csproj | 1 + .../Utilities/SmartSyndicationFeed.cs | 35 +++++++ ...61756463_PrimaryStoreCurrencyMultiStore.cs | 6 ++ .../SmartStore.Services/News/INewsService.cs | 14 ++- .../SmartStore.Services/News/NewsService.cs | 96 ++++++++++++++++--- .../SmartStore.Services.csproj | 1 + .../Controllers/RssActionResult.cs | 6 +- .../Models/Settings/NewsSettingsModel.cs | 3 + .../Administration/Views/Setting/News.cshtml | 9 ++ .../Controllers/NewsController.cs | 32 ++----- .../SmartStore.Web/Views/News/List.cshtml | 2 +- 13 files changed, 171 insertions(+), 44 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Utilities/SmartSyndicationFeed.cs diff --git a/changelog.md b/changelog.md index 5060856f29..fe27596550 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,7 @@ * (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%. * #721 Message Queue: implement "Delete all" * #725 Prevent LowestProductPrice being 0 +* #709 News feed produced invalid RSS feed. Added content:encoded. Added maximum news age setting for feed export. ## SmartStore.NET 2.2.2 diff --git a/src/Libraries/SmartStore.Core/Domain/News/NewsSettings.cs b/src/Libraries/SmartStore.Core/Domain/News/NewsSettings.cs index 479b3c5c9b..ffceb3edab 100644 --- a/src/Libraries/SmartStore.Core/Domain/News/NewsSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/News/NewsSettings.cs @@ -1,5 +1,4 @@ - -using SmartStore.Core.Configuration; +using SmartStore.Core.Configuration; namespace SmartStore.Core.Domain.News { @@ -12,6 +11,7 @@ public NewsSettings() ShowNewsOnMainPage = true; MainPageNewsCount = 3; NewsArchivePageSize = 10; + MaxAgeInDays = 180; } /// @@ -44,6 +44,11 @@ public NewsSettings() /// public int NewsArchivePageSize { get; set; } + /// + /// The maximum age of news (in days) for RSS feed + /// + public int MaxAgeInDays { get; set; } + /// /// Enable the news RSS feed link in customers browser address bar /// diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index fa13b5e483..c1e2d2bae1 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -560,6 +560,7 @@ + diff --git a/src/Libraries/SmartStore.Core/Utilities/SmartSyndicationFeed.cs b/src/Libraries/SmartStore.Core/Utilities/SmartSyndicationFeed.cs new file mode 100644 index 0000000000..ccc8d5e68d --- /dev/null +++ b/src/Libraries/SmartStore.Core/Utilities/SmartSyndicationFeed.cs @@ -0,0 +1,35 @@ +using System; +using System.ServiceModel.Syndication; +using System.Xml; +using System.Xml.Linq; +using SmartStore.Core.Domain.Localization; + +namespace SmartStore.Utilities +{ + public class SmartSyndicationFeed : SyndicationFeed + { + public SmartSyndicationFeed(Uri feedAlternateLink, string title, string description = null) + : base(title, description ?? title, feedAlternateLink, null, DateTime.UtcNow) + { + } + + public static string UrlAtom { get { return "http://www.w3.org/2005/Atom"; } } + public static string UrlPurlContent { get { return "http://purl.org/rss/1.0/modules/content/"; } } + + public void AddNamespaces(bool purlContent) + { + this.AttributeExtensions.Add(new XmlQualifiedName("atom", XNamespace.Xmlns.NamespaceName), UrlAtom); + + if (purlContent) + this.AttributeExtensions.Add(new XmlQualifiedName("content", XNamespace.Xmlns.ToString()), UrlPurlContent); + } + + public void Init(string selfLink, Language language = null) + { + this.ElementExtensions.Add(new XElement(((XNamespace)UrlAtom) + "link", new XAttribute("href", selfLink), new XAttribute("rel", "self"), new XAttribute("type", "application/rss+xml"))); + + if (language != null) + this.Language = language.LanguageCulture.EmptyNull().ToLower(); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs index 95492db892..e6954aacb8 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -131,6 +131,12 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Specifies whether the store should be SSL secured.", "Legt fest, ob der Shop SSL gesichert werden soll."); + builder.AddOrUpdate("Admin.Configuration.Settings.News.MaxAgeInDays", + "Maximum age (in days)", + "Maximales Alter (in Tagen)", + "Specifies the maximum news age in days. Older news are not exported in the RSS feed.", + "Legt das maximale News-Alter in Tagen fest. ltere News werden im RSS-Feed nicht exportiert."); + builder.Delete("Admin.Configuration.Currencies.CantDeletePrimary"); builder.Delete("Admin.Configuration.Currencies.CantDeleteExchange"); builder.Delete("Admin.Configuration.Currencies.Fields.MarkAsPrimaryStoreCurrency"); diff --git a/src/Libraries/SmartStore.Services/News/INewsService.cs b/src/Libraries/SmartStore.Services/News/INewsService.cs index e2308c6260..c07cceb570 100644 --- a/src/Libraries/SmartStore.Services/News/INewsService.cs +++ b/src/Libraries/SmartStore.Services/News/INewsService.cs @@ -1,6 +1,9 @@ +using System; using System.Linq; +using System.Web.Mvc; using SmartStore.Core; using SmartStore.Core.Domain.News; +using SmartStore.Utilities; namespace SmartStore.Services.News { @@ -37,8 +40,9 @@ public partial interface INewsService /// Page index /// Page size /// A value indicating whether to show hidden records + /// The maximum age of returned news /// News items - IPagedList GetAllNews(int languageId, int storeId, int pageIndex, int pageSize, bool showHidden = false); + IPagedList GetAllNews(int languageId, int storeId, int pageIndex, int pageSize, bool showHidden = false, DateTime? maxAge = null); /// /// Inserts a news item @@ -57,5 +61,13 @@ public partial interface INewsService /// /// News item void UpdateCommentTotals(NewsItem newsItem); + + /// + /// Creates a RSS feed with news items + /// + /// UrlHelper to generate URLs + /// Language identifier + /// SmartSyndicationFeed object + SmartSyndicationFeed CreateRssFeed(UrlHelper urlHelper, int languageId); } } diff --git a/src/Libraries/SmartStore.Services/News/NewsService.cs b/src/Libraries/SmartStore.Services/News/NewsService.cs index c715f78a84..77ad186e06 100644 --- a/src/Libraries/SmartStore.Services/News/NewsService.cs +++ b/src/Libraries/SmartStore.Services/News/NewsService.cs @@ -1,11 +1,16 @@ using System; +using System.Collections.Generic; using System.Linq; +using System.ServiceModel.Syndication; +using System.Web.Mvc; using SmartStore.Core; -using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.News; using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; +using SmartStore.Services.Localization; +using SmartStore.Services.Seo; +using SmartStore.Utilities; namespace SmartStore.Services.News { @@ -18,8 +23,10 @@ public partial class NewsService : INewsService private readonly IRepository _newsItemRepository; private readonly IRepository _storeMappingRepository; - private readonly ICacheManager _cacheManager; - private readonly IEventPublisher _eventPublisher; + private readonly ICommonServices _services; + private readonly ILanguageService _languageService; + + private readonly NewsSettings _newsSettings; #endregion @@ -27,13 +34,15 @@ public partial class NewsService : INewsService public NewsService(IRepository newsItemRepository, IRepository storeMappingRepository, - ICacheManager cacheManager, - IEventPublisher eventPublisher) + ICommonServices services, + ILanguageService languageService, + NewsSettings newsSettings) { _newsItemRepository = newsItemRepository; _storeMappingRepository = storeMappingRepository; - _cacheManager = cacheManager; - _eventPublisher = eventPublisher; + _services = services; + _languageService = languageService; + _newsSettings = newsSettings; this.QuerySettings = DbQuerySettings.Default; } @@ -56,7 +65,7 @@ public virtual void DeleteNews(NewsItem newsItem) _newsItemRepository.Delete(newsItem); //event notification - _eventPublisher.EntityDeleted(newsItem); + _services.EventPublisher.EntityDeleted(newsItem); } /// @@ -98,12 +107,22 @@ where newsIds.Contains(x.Id) /// Page index /// Page size /// A value indicating whether to show hidden records + /// The maximum age of returned news /// News items - public virtual IPagedList GetAllNews(int languageId, int storeId, int pageIndex, int pageSize, bool showHidden = false) + public virtual IPagedList GetAllNews(int languageId, int storeId, int pageIndex, int pageSize, bool showHidden = false, DateTime? maxAge = null) { var query = _newsItemRepository.Table; - if (languageId > 0) - query = query.Where(n => languageId == n.LanguageId); + + if (languageId > 0) + { + query = query.Where(n => languageId == n.LanguageId); + } + + if (maxAge.HasValue) + { + query = query.Where(n => n.CreatedOnUtc >= maxAge.Value); + } + if (!showHidden) { var utcNow = DateTime.UtcNow; @@ -111,6 +130,7 @@ public virtual IPagedList GetAllNews(int languageId, int storeId, int query = query.Where(n => !n.StartDateUtc.HasValue || n.StartDateUtc <= utcNow); query = query.Where(n => !n.EndDateUtc.HasValue || n.EndDateUtc >= utcNow); } + query = query.OrderByDescending(n => n.CreatedOnUtc); //Store mapping @@ -128,6 +148,7 @@ from sm in n_sm.DefaultIfEmpty() group n by n.Id into nGroup orderby nGroup.Key select nGroup.FirstOrDefault(); + query = query.OrderByDescending(n => n.CreatedOnUtc); } @@ -147,7 +168,7 @@ public virtual void InsertNews(NewsItem news) _newsItemRepository.Insert(news); //event notification - _eventPublisher.EntityInserted(news); + _services.EventPublisher.EntityInserted(news); } /// @@ -162,7 +183,7 @@ public virtual void UpdateNews(NewsItem news) _newsItemRepository.Update(news); //event notification - _eventPublisher.EntityUpdated(news); + _services.EventPublisher.EntityUpdated(news); } /// @@ -190,6 +211,55 @@ public virtual void UpdateCommentTotals(NewsItem newsItem) UpdateNews(newsItem); } + /// + /// Creates a RSS feed with news items + /// + /// UrlHelper to generate URLs + /// Language identifier + /// SmartSyndicationFeed object + public virtual SmartSyndicationFeed CreateRssFeed(UrlHelper urlHelper, int languageId) + { + if (urlHelper == null) + throw new ArgumentNullException("urlHelper"); + + DateTime? maxAge = null; + var protocol = _services.WebHelper.IsCurrentConnectionSecured() ? "https" : "http"; + var selfLink = urlHelper.Action("rss", null, new { languageId = languageId }, protocol); + var newsLink = urlHelper.RouteUrl("NewsArchive", null, protocol); + + var title = "{0} - News".FormatInvariant(_services.StoreContext.CurrentStore.Name); + + if (_newsSettings.MaxAgeInDays > 0) + maxAge = DateTime.UtcNow.Subtract(new TimeSpan(_newsSettings.MaxAgeInDays, 0, 0, 0)); + + var language = _languageService.GetLanguageById(languageId); + var feed = new SmartSyndicationFeed(new Uri(newsLink), title); + + feed.AddNamespaces(true); + feed.Init(selfLink, language); + + if (!_newsSettings.Enabled) + return feed; + + var items = new List(); + var newsItems = GetAllNews(languageId, _services.StoreContext.CurrentStore.Id, 0, int.MaxValue, false, maxAge); + + foreach (var n in newsItems) + { + var newsUrl = urlHelper.RouteUrl("NewsItem", new { SeName = n.GetSeName(n.LanguageId, ensureTwoPublishedLanguages: false) }, "http"); + + var item = new SyndicationItem(n.Title, n.Short, new Uri(newsUrl), newsUrl, n.CreatedOnUtc); + + item.ElementExtensions.Add("encoded", SmartSyndicationFeed.UrlPurlContent, n.Full); + + items.Add(item); + } + + feed.Items = items; + + return feed; + } + #endregion } } diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index 91cca5e43a..de2ce339ea 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -113,6 +113,7 @@ ..\..\packages\System.Linq.Dynamic.1.0.0\lib\net40\System.Linq.Dynamic.dll + False diff --git a/src/Presentation/SmartStore.Web.Framework/Controllers/RssActionResult.cs b/src/Presentation/SmartStore.Web.Framework/Controllers/RssActionResult.cs index 2015b85b1b..eb6c4dd45a 100644 --- a/src/Presentation/SmartStore.Web.Framework/Controllers/RssActionResult.cs +++ b/src/Presentation/SmartStore.Web.Framework/Controllers/RssActionResult.cs @@ -12,8 +12,10 @@ public override void ExecuteResult(ControllerContext context) { context.HttpContext.Response.ContentType = "application/rss+xml"; - var rssFormatter = new Rss20FeedFormatter(Feed); - using (var writer = XmlWriter.Create(context.HttpContext.Response.Output)) + var rssFormatter = new Rss20FeedFormatter(Feed, false); + var settings = new XmlWriterSettings { Indent = true, IndentChars = "\t", CheckCharacters = false }; + + using (var writer = XmlWriter.Create(context.HttpContext.Response.Output, settings)) { rssFormatter.WriteTo(writer); } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Settings/NewsSettingsModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Settings/NewsSettingsModel.cs index 4bc18260a2..f7a00fd03e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Settings/NewsSettingsModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Settings/NewsSettingsModel.cs @@ -22,6 +22,9 @@ public class NewsSettingsModel [SmartResourceDisplayName("Admin.Configuration.Settings.News.NewsArchivePageSize")] public int NewsArchivePageSize { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Settings.News.MaxAgeInDays")] + public int MaxAgeInDays { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Settings.News.ShowHeaderRSSUrl")] public bool ShowHeaderRssUrl { get; set; } } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/News.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/News.cshtml index cf0d619047..cd65a40c30 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/News.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/News.cshtml @@ -73,6 +73,15 @@ @Html.ValidationMessageFor(model => model.NewsArchivePageSize) + + + @Html.SmartLabelFor(model => model.MaxAgeInDays) + + + @Html.SettingEditorFor(model => model.MaxAgeInDays) + @Html.ValidationMessageFor(model => model.MaxAgeInDays) + + @Html.SmartLabelFor(model => model.ShowHeaderRssUrl) diff --git a/src/Presentation/SmartStore.Web/Controllers/NewsController.cs b/src/Presentation/SmartStore.Web/Controllers/NewsController.cs index ccc30b1c10..b3ada79a8b 100644 --- a/src/Presentation/SmartStore.Web/Controllers/NewsController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/NewsController.cs @@ -1,27 +1,24 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.ServiceModel.Syndication; using System.Web.Mvc; using SmartStore.Core; using SmartStore.Core.Caching; -using SmartStore.Core.Domain; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.News; +using SmartStore.Core.Logging; using SmartStore.Services.Common; using SmartStore.Services.Customers; using SmartStore.Services.Helpers; using SmartStore.Services.Localization; -using SmartStore.Core.Logging; using SmartStore.Services.Media; using SmartStore.Services.Messages; using SmartStore.Services.News; using SmartStore.Services.Seo; using SmartStore.Services.Stores; -using SmartStore.Web.Framework; using SmartStore.Web.Framework.Controllers; +using SmartStore.Web.Framework.Mvc; using SmartStore.Web.Framework.Security; using SmartStore.Web.Framework.UI.Captcha; using SmartStore.Web.Infrastructure.Cache; @@ -208,28 +205,12 @@ public ActionResult List(NewsPagingFilteringModel command) return View(model); } - [ActionName("rss")] + [ActionName("rss"), Compress] public ActionResult ListRss(int languageId) { - var feed = new SyndicationFeed( - string.Format("{0}: News", _storeContext.CurrentStore.Name), - "News", - new Uri(_webHelper.GetStoreLocation(false)), - "NewsRSS", - DateTime.UtcNow); - - if (!_newsSettings.Enabled) - return new RssActionResult() { Feed = feed }; + var feed = _newsService.CreateRssFeed(Url, languageId); - var items = new List(); - var newsItems = _newsService.GetAllNews(languageId, _storeContext.CurrentStore.Id, 0, int.MaxValue); - foreach (var n in newsItems) - { - string newsUrl = Url.RouteUrl("NewsItem", new { SeName = n.GetSeName(n.LanguageId, ensureTwoPublishedLanguages: false) }, "http"); - items.Add(new SyndicationItem(n.Title, n.Short, new Uri(newsUrl), String.Format("Blog:{0}", n.Id), n.CreatedOnUtc)); - } - feed.Items = items; - return new RssActionResult() { Feed = feed }; + return new RssActionResult { Feed = feed }; } public ActionResult NewsItem(int newsItemId) @@ -319,7 +300,8 @@ public ActionResult RssHeaderLink() return Content(""); string link = string.Format("", - Url.Action("rss", null, new { languageId = _workContext.WorkingLanguage.Id }, _webHelper.IsCurrentConnectionSecured() ? "https" : "http"), _storeContext.CurrentStore.Name); + Url.Action("rss", null, new { languageId = _workContext.WorkingLanguage.Id }, _webHelper.IsCurrentConnectionSecured() ? "https" : "http"), + _storeContext.CurrentStore.Name); return Content(link); } diff --git a/src/Presentation/SmartStore.Web/Views/News/List.cshtml b/src/Presentation/SmartStore.Web/Views/News/List.cshtml index 5a282b3eb4..cd0474dbad 100644 --- a/src/Presentation/SmartStore.Web/Views/News/List.cshtml +++ b/src/Presentation/SmartStore.Web/Views/News/List.cshtml @@ -10,7 +10,7 @@ }
- + @T("News.RSS") From 714ac296ef1118704e1908e7909e4c38bea740d4 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 1 Jul 2015 14:53:50 +0200 Subject: [PATCH 0211/1256] #709 Blog post RSS feed improvements. --- .../Domain/Blogs/BlogSettings.cs | 6 ++ ...61756463_PrimaryStoreCurrencyMultiStore.cs | 6 ++ .../SmartStore.Services/Blogs/BlogService.cs | 86 ++++++++++++++++--- .../SmartStore.Services/Blogs/IBlogService.cs | 13 ++- .../SmartStore.Services/News/NewsService.cs | 8 +- .../Models/Settings/BlogSettingsModel.cs | 3 + .../Administration/Views/Setting/Blog.cshtml | 9 ++ .../Controllers/BlogController.cs | 26 ++---- 8 files changed, 120 insertions(+), 37 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Domain/Blogs/BlogSettings.cs b/src/Libraries/SmartStore.Core/Domain/Blogs/BlogSettings.cs index 8a1b5ca08e..e0c7492934 100644 --- a/src/Libraries/SmartStore.Core/Domain/Blogs/BlogSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Blogs/BlogSettings.cs @@ -11,6 +11,7 @@ public BlogSettings() PostsPageSize = 10; AllowNotRegisteredUsersToLeaveComments = true; NumberOfTags = 15; + MaxAgeInDays = 180; } /// @@ -38,6 +39,11 @@ public BlogSettings() /// public int NumberOfTags { get; set; } + /// + /// The maximum age of blog items (in days) for RSS feed + /// + public int MaxAgeInDays { get; set; } + /// /// Enable the blog RSS feed link in customers browser address bar /// diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs index e6954aacb8..1903182830 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -137,6 +137,12 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Specifies the maximum news age in days. Older news are not exported in the RSS feed.", "Legt das maximale News-Alter in Tagen fest. ltere News werden im RSS-Feed nicht exportiert."); + builder.AddOrUpdate("Admin.Configuration.Settings.Blog.MaxAgeInDays", + "Maximum age (in days)", + "Maximales Alter (in Tagen)", + "Specifies the maximum news age in days. Older blog posts are not exported in the RSS feed.", + "Legt das maximale Blog-Alter in Tagen fest. ltere Blog-Eintrge werden im RSS-Feed nicht exportiert."); + builder.Delete("Admin.Configuration.Currencies.CantDeletePrimary"); builder.Delete("Admin.Configuration.Currencies.CantDeleteExchange"); builder.Delete("Admin.Configuration.Currencies.Fields.MarkAsPrimaryStoreCurrency"); diff --git a/src/Libraries/SmartStore.Services/Blogs/BlogService.cs b/src/Libraries/SmartStore.Services/Blogs/BlogService.cs index 79a9d607e2..8ed8612483 100644 --- a/src/Libraries/SmartStore.Services/Blogs/BlogService.cs +++ b/src/Libraries/SmartStore.Services/Blogs/BlogService.cs @@ -1,12 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; +using System.ServiceModel.Syndication; +using System.Web.Mvc; using SmartStore.Core; -using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Blogs; using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; +using SmartStore.Services.Localization; +using SmartStore.Services.Seo; +using SmartStore.Utilities; namespace SmartStore.Services.Blogs { @@ -15,13 +19,14 @@ namespace SmartStore.Services.Blogs ///
public partial class BlogService : IBlogService { - #region Fields private readonly IRepository _blogPostRepository; private readonly IRepository _storeMappingRepository; - private readonly ICacheManager _cacheManager; - private readonly IEventPublisher _eventPublisher; + private readonly ICommonServices _services; + private readonly ILanguageService _languageService; + + private readonly BlogSettings _blogSettings; #endregion @@ -29,13 +34,15 @@ public partial class BlogService : IBlogService public BlogService(IRepository blogPostRepository, IRepository storeMappingRepository, - ICacheManager cacheManager, - IEventPublisher eventPublisher) + ICommonServices services, + ILanguageService languageService, + BlogSettings blogSettings) { _blogPostRepository = blogPostRepository; _storeMappingRepository = storeMappingRepository; - _cacheManager = cacheManager; - _eventPublisher = eventPublisher; + _services = services; + _languageService = languageService; + _blogSettings = blogSettings; this.QuerySettings = DbQuerySettings.Default; } @@ -58,7 +65,7 @@ public virtual void DeleteBlogPost(BlogPost blogPost) _blogPostRepository.Delete(blogPost); //event notification - _eventPublisher.EntityDeleted(blogPost); + _services.EventPublisher.EntityDeleted(blogPost); } /// @@ -84,17 +91,25 @@ public virtual BlogPost GetBlogPostById(int blogPostId) /// Page index /// Page size /// A value indicating whether to show hidden records + /// The maximum age of returned blog posts /// Blog posts public virtual IPagedList GetAllBlogPosts(int storeId, int languageId, - DateTime? dateFrom, DateTime? dateTo, int pageIndex, int pageSize, bool showHidden = false) + DateTime? dateFrom, DateTime? dateTo, int pageIndex, int pageSize, bool showHidden = false, DateTime? maxAge = null) { var query = _blogPostRepository.Table; + if (dateFrom.HasValue) query = query.Where(b => dateFrom.Value <= b.CreatedOnUtc); + if (dateTo.HasValue) query = query.Where(b => dateTo.Value >= b.CreatedOnUtc); + if (languageId > 0) query = query.Where(b => languageId == b.LanguageId); + + if (maxAge.HasValue) + query = query.Where(b => b.CreatedOnUtc >= maxAge.Value); + if (!showHidden) { var utcNow = DateTime.UtcNow; @@ -202,7 +217,7 @@ public virtual void InsertBlogPost(BlogPost blogPost) _blogPostRepository.Insert(blogPost); //event notification - _eventPublisher.EntityInserted(blogPost); + _services.EventPublisher.EntityInserted(blogPost); } /// @@ -217,7 +232,7 @@ public virtual void UpdateBlogPost(BlogPost blogPost) _blogPostRepository.Update(blogPost); //event notification - _eventPublisher.EntityUpdated(blogPost); + _services.EventPublisher.EntityUpdated(blogPost); } /// @@ -245,6 +260,53 @@ public virtual void UpdateCommentTotals(BlogPost blogPost) UpdateBlogPost(blogPost); } + /// + /// Creates a RSS feed with blog posts + /// + /// UrlHelper to generate URLs + /// Language identifier + /// SmartSyndicationFeed object + public virtual SmartSyndicationFeed CreateRssFeed(UrlHelper urlHelper, int languageId) + { + if (urlHelper == null) + throw new ArgumentNullException("urlHelper"); + + DateTime? maxAge = null; + var protocol = _services.WebHelper.IsCurrentConnectionSecured() ? "https" : "http"; + var selfLink = urlHelper.RouteUrl("BlogRSS", new { languageId = languageId }, protocol); + var blogLink = urlHelper.RouteUrl("Blog", null, protocol); + + var title = "{0} - Blog".FormatInvariant(_services.StoreContext.CurrentStore.Name); + + if (_blogSettings.MaxAgeInDays > 0) + maxAge = DateTime.UtcNow.Subtract(new TimeSpan(_blogSettings.MaxAgeInDays, 0, 0, 0)); + + var language = _languageService.GetLanguageById(languageId); + var feed = new SmartSyndicationFeed(new Uri(blogLink), title); + + feed.AddNamespaces(false); + feed.Init(selfLink, language); + + if (!_blogSettings.Enabled) + return feed; + + var items = new List(); + var blogPosts = GetAllBlogPosts(_services.StoreContext.CurrentStore.Id, languageId, null, null, 0, int.MaxValue, false, maxAge); + + foreach (var blogPost in blogPosts) + { + var blogPostUrl = urlHelper.RouteUrl("BlogPost", new { SeName = blogPost.GetSeName(blogPost.LanguageId, ensureTwoPublishedLanguages: false) }, "http"); + + var item = new SyndicationItem(blogPost.Title, blogPost.Body.RemoveInvalidXmlChars(), new Uri(blogPostUrl), blogPostUrl, blogPost.CreatedOnUtc); + + items.Add(item); + } + + feed.Items = items; + + return feed; + } + #endregion } } diff --git a/src/Libraries/SmartStore.Services/Blogs/IBlogService.cs b/src/Libraries/SmartStore.Services/Blogs/IBlogService.cs index eabf47a802..983932b0bf 100644 --- a/src/Libraries/SmartStore.Services/Blogs/IBlogService.cs +++ b/src/Libraries/SmartStore.Services/Blogs/IBlogService.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Web.Mvc; using SmartStore.Core; using SmartStore.Core.Domain.Blogs; +using SmartStore.Utilities; namespace SmartStore.Services.Blogs { @@ -33,9 +35,10 @@ public partial interface IBlogService /// Page index /// Page size /// A value indicating whether to show hidden records + /// The maximum age of returned blog posts /// Blog posts IPagedList GetAllBlogPosts(int storeId, int languageId, - DateTime? dateFrom, DateTime? dateTo, int pageIndex, int pageSize, bool showHidden = false); + DateTime? dateFrom, DateTime? dateTo, int pageIndex, int pageSize, bool showHidden = false, DateTime? maxAge = null); /// /// Gets all blog posts @@ -76,5 +79,13 @@ IPagedList GetAllBlogPostsByTag(int storeId, int languageId, string ta /// /// Blog post void UpdateCommentTotals(BlogPost blogPost); + + /// + /// Creates a RSS feed with blog posts + /// + /// UrlHelper to generate URLs + /// Language identifier + /// SmartSyndicationFeed object + SmartSyndicationFeed CreateRssFeed(UrlHelper urlHelper, int languageId); } } diff --git a/src/Libraries/SmartStore.Services/News/NewsService.cs b/src/Libraries/SmartStore.Services/News/NewsService.cs index 77ad186e06..c0d576ca29 100644 --- a/src/Libraries/SmartStore.Services/News/NewsService.cs +++ b/src/Libraries/SmartStore.Services/News/NewsService.cs @@ -244,13 +244,13 @@ public virtual SmartSyndicationFeed CreateRssFeed(UrlHelper urlHelper, int langu var items = new List(); var newsItems = GetAllNews(languageId, _services.StoreContext.CurrentStore.Id, 0, int.MaxValue, false, maxAge); - foreach (var n in newsItems) + foreach (var news in newsItems) { - var newsUrl = urlHelper.RouteUrl("NewsItem", new { SeName = n.GetSeName(n.LanguageId, ensureTwoPublishedLanguages: false) }, "http"); + var newsUrl = urlHelper.RouteUrl("NewsItem", new { SeName = news.GetSeName(news.LanguageId, ensureTwoPublishedLanguages: false) }, "http"); - var item = new SyndicationItem(n.Title, n.Short, new Uri(newsUrl), newsUrl, n.CreatedOnUtc); + var item = new SyndicationItem(news.Title, news.Short.RemoveInvalidXmlChars(), new Uri(newsUrl), newsUrl, news.CreatedOnUtc); - item.ElementExtensions.Add("encoded", SmartSyndicationFeed.UrlPurlContent, n.Full); + item.ElementExtensions.Add("encoded", SmartSyndicationFeed.UrlPurlContent, news.Full.RemoveInvalidXmlChars()); items.Add(item); } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Settings/BlogSettingsModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Settings/BlogSettingsModel.cs index 17b4578b0f..1e16f2230d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Settings/BlogSettingsModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Settings/BlogSettingsModel.cs @@ -20,6 +20,9 @@ public class BlogSettingsModel : ModelBase [SmartResourceDisplayName("Admin.Configuration.Settings.Blog.NumberOfTags")] public int NumberOfTags { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Settings.Blog.MaxAgeInDays")] + public int MaxAgeInDays { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Settings.Blog.ShowHeaderRSSUrl")] public bool ShowHeaderRssUrl { get; set; } } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/Blog.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/Blog.cshtml index dc64352a48..973aa0703f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/Blog.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/Blog.cshtml @@ -64,6 +64,15 @@ @Html.ValidationMessageFor(model => model.NumberOfTags) + + + @Html.SmartLabelFor(model => model.MaxAgeInDays) + + + @Html.SettingEditorFor(model => model.MaxAgeInDays) + @Html.ValidationMessageFor(model => model.MaxAgeInDays) + + @Html.SmartLabelFor(model => model.ShowHeaderRssUrl) diff --git a/src/Presentation/SmartStore.Web/Controllers/BlogController.cs b/src/Presentation/SmartStore.Web/Controllers/BlogController.cs index a1aa99e822..194543c724 100644 --- a/src/Presentation/SmartStore.Web/Controllers/BlogController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/BlogController.cs @@ -27,6 +27,7 @@ using SmartStore.Web.Framework.UI.Captcha; using SmartStore.Web.Infrastructure.Cache; using SmartStore.Web.Models.Blogs; +using SmartStore.Web.Framework.Mvc; namespace SmartStore.Web.Controllers { @@ -228,28 +229,12 @@ public ActionResult BlogByMonth(BlogPagingFilteringModel command) return View("List", model); } + [Compress] public ActionResult ListRss(int languageId) { - var feed = new SyndicationFeed( - string.Format("{0}: Blog", _storeContext.CurrentStore.Name), - "Blog", - new Uri(_webHelper.GetStoreLocation(false)), - "BlogRSS", - DateTime.UtcNow); + var feed = _blogService.CreateRssFeed(Url, languageId); - if (!_blogSettings.Enabled) - return new RssActionResult() { Feed = feed }; - - var items = new List(); - var blogPosts = _blogService.GetAllBlogPosts(_storeContext.CurrentStore.Id, languageId, - null, null, 0, int.MaxValue); - foreach (var blogPost in blogPosts) - { - string blogPostUrl = Url.RouteUrl("BlogPost", new { SeName = blogPost.GetSeName(blogPost.LanguageId, ensureTwoPublishedLanguages: false) }, "http"); - items.Add(new SyndicationItem(blogPost.Title, blogPost.Body, new Uri(blogPostUrl), String.Format("Blog:{0}", blogPost.Id), blogPost.CreatedOnUtc)); - } - feed.Items = items; - return new RssActionResult() { Feed = feed }; + return new RssActionResult { Feed = feed }; } public ActionResult BlogPost(int blogPostId) @@ -449,11 +434,12 @@ public ActionResult RssHeaderLink() if (!_blogSettings.Enabled || !_blogSettings.ShowHeaderRssUrl) return Content(""); - string link = string.Format("", + string link = string.Format("", Url.RouteUrl("BlogRSS", new { languageId = _workContext.WorkingLanguage.Id }, _webHelper.IsCurrentConnectionSecured() ? "https" : "http"), _storeContext.CurrentStore.Name); return Content(link); } + #endregion } } From ed957839c4d8f92bb39a80f1b1c2a444044340c8 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 1 Jul 2015 21:09:47 +0200 Subject: [PATCH 0212/1256] #709 Recently added products RSS feed improvements. --- .../Utilities/SmartSyndicationFeed.cs | 46 ++++- .../SmartStore.Services/Blogs/BlogService.cs | 2 +- .../Catalog/IProductService.cs | 9 + .../Catalog/ProductService.cs | 160 +++++++++++++----- .../SmartStore.Services/News/NewsService.cs | 6 +- .../Controllers/CatalogController.cs | 34 +--- .../Catalog/RecentlyAddedProducts.cshtml | 10 +- 7 files changed, 187 insertions(+), 80 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Utilities/SmartSyndicationFeed.cs b/src/Libraries/SmartStore.Core/Utilities/SmartSyndicationFeed.cs index ccc8d5e68d..f93e4e6ea3 100644 --- a/src/Libraries/SmartStore.Core/Utilities/SmartSyndicationFeed.cs +++ b/src/Libraries/SmartStore.Core/Utilities/SmartSyndicationFeed.cs @@ -3,6 +3,7 @@ using System.Xml; using System.Xml.Linq; using SmartStore.Core.Domain.Localization; +using SmartStore.Core.Domain.Media; namespace SmartStore.Utilities { @@ -21,15 +22,58 @@ public void AddNamespaces(bool purlContent) this.AttributeExtensions.Add(new XmlQualifiedName("atom", XNamespace.Xmlns.NamespaceName), UrlAtom); if (purlContent) + { this.AttributeExtensions.Add(new XmlQualifiedName("content", XNamespace.Xmlns.ToString()), UrlPurlContent); + } } public void Init(string selfLink, Language language = null) { - this.ElementExtensions.Add(new XElement(((XNamespace)UrlAtom) + "link", new XAttribute("href", selfLink), new XAttribute("rel", "self"), new XAttribute("type", "application/rss+xml"))); + this.ElementExtensions.Add( + new XElement(((XNamespace)UrlAtom) + "link", + new XAttribute("href", selfLink), + new XAttribute("rel", "self"), + new XAttribute("type", "application/rss+xml"))); if (language != null) + { this.Language = language.LanguageCulture.EmptyNull().ToLower(); + } + } + + public SyndicationItem CreateItem(string title, string synopsis, string url, DateTimeOffset published, string contentEncoded = null) + { + var item = new SyndicationItem( + title.RemoveInvalidXmlChars().EmptyNull(), + synopsis.RemoveInvalidXmlChars().EmptyNull(), + new Uri(url), + url, + published); + + if (contentEncoded != null) + { + item.ElementExtensions.Add("encoded", SmartSyndicationFeed.UrlPurlContent, contentEncoded.RemoveInvalidXmlChars().EmptyNull()); + } + + return item; + } + + public bool AddEnclosue(SyndicationItem item, Picture picture, string pictureUrl) + { + if (picture != null && pictureUrl.HasValue()) + { + long pictureLength = 10000; // 0 omits the length attribute but that invalidates the feed + + if (picture.PictureBinary != null) + pictureLength = picture.PictureBinary.LongLength; + + var enclosure = SyndicationLink.CreateMediaEnclosureLink(new Uri(pictureUrl), picture.MimeType.EmptyNull(), pictureLength); + + item.Links.Add(enclosure); + + return true; + } + return false; } } } diff --git a/src/Libraries/SmartStore.Services/Blogs/BlogService.cs b/src/Libraries/SmartStore.Services/Blogs/BlogService.cs index 8ed8612483..c616abefbe 100644 --- a/src/Libraries/SmartStore.Services/Blogs/BlogService.cs +++ b/src/Libraries/SmartStore.Services/Blogs/BlogService.cs @@ -297,7 +297,7 @@ public virtual SmartSyndicationFeed CreateRssFeed(UrlHelper urlHelper, int langu { var blogPostUrl = urlHelper.RouteUrl("BlogPost", new { SeName = blogPost.GetSeName(blogPost.LanguageId, ensureTwoPublishedLanguages: false) }, "http"); - var item = new SyndicationItem(blogPost.Title, blogPost.Body.RemoveInvalidXmlChars(), new Uri(blogPostUrl), blogPostUrl, blogPost.CreatedOnUtc); + var item = feed.CreateItem(blogPost.Title, blogPost.Body, blogPostUrl, blogPost.CreatedOnUtc); items.Add(item); } diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductService.cs b/src/Libraries/SmartStore.Services/Catalog/IProductService.cs index aa3199641f..e080a437b5 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductService.cs @@ -2,9 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using System.Web.Mvc; using SmartStore.Core; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Orders; +using SmartStore.Utilities; namespace SmartStore.Services.Catalog { @@ -151,6 +153,13 @@ public partial interface IProductService /// Product void UpdateHasDiscountsApplied(Product product); + /// + /// Creates a RSS feed with recently added products + /// + /// UrlHelper to generate URLs + /// SmartSyndicationFeed object + SmartSyndicationFeed CreateRecentlyAddedProductsRssFeed(UrlHelper urlHelper); + #endregion #region Related products diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs index 2f8c1270e3..5618ba86ad 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs @@ -3,19 +3,24 @@ using System.Data; using System.Linq; using System.Linq.Expressions; +using System.ServiceModel.Syndication; +using System.Web.Mvc; using SmartStore.Core; -using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Localization; +using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Security; using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; using SmartStore.Services.Localization; +using SmartStore.Services.Media; using SmartStore.Services.Messages; using SmartStore.Services.Orders; +using SmartStore.Services.Seo; +using SmartStore.Utilities; namespace SmartStore.Services.Catalog { @@ -50,12 +55,12 @@ public partial class ProductService : IProductService private readonly IWorkflowMessageService _workflowMessageService; private readonly IDataProvider _dataProvider; private readonly IDbContext _dbContext; - private readonly ICacheManager _cacheManager; - private readonly IWorkContext _workContext; - private readonly IStoreContext _storeContext; private readonly LocalizationSettings _localizationSettings; private readonly CommonSettings _commonSettings; - private readonly IEventPublisher _eventPublisher; + private readonly ICommonServices _services; + private readonly CatalogSettings _catalogSettings; + private readonly MediaSettings _mediaSettings; + private readonly IPictureService _pictureService; #endregion @@ -85,7 +90,7 @@ public partial class ProductService : IProductService /// Localization settings /// Common settings /// Event published - public ProductService(ICacheManager cacheManager, + public ProductService( IRepository productRepository, IRepository relatedProductRepository, IRepository crossSellProductRepository, @@ -101,13 +106,15 @@ public ProductService(ICacheManager cacheManager, IProductAttributeParser productAttributeParser, ILanguageService languageService, IWorkflowMessageService workflowMessageService, - IDataProvider dataProvider, IDbContext dbContext, - IWorkContext workContext, - IStoreContext storeContext, - LocalizationSettings localizationSettings, CommonSettings commonSettings, - IEventPublisher eventPublisher) + IDataProvider dataProvider, + IDbContext dbContext, + LocalizationSettings localizationSettings, + CommonSettings commonSettings, + ICommonServices services, + CatalogSettings catalogSettings, + MediaSettings mediaSettings, + IPictureService pictureService) { - this._cacheManager = cacheManager; this._productRepository = productRepository; this._relatedProductRepository = relatedProductRepository; this._crossSellProductRepository = crossSellProductRepository; @@ -125,11 +132,12 @@ public ProductService(ICacheManager cacheManager, this._workflowMessageService = workflowMessageService; this._dataProvider = dataProvider; this._dbContext = dbContext; - this._workContext = workContext; - this._storeContext = storeContext; this._localizationSettings = localizationSettings; this._commonSettings = commonSettings; - this._eventPublisher = eventPublisher; + this._services = services; + this._catalogSettings = catalogSettings; + this._mediaSettings = mediaSettings; + this._pictureService = pictureService; this.QuerySettings = DbQuerySettings.Default; } @@ -264,7 +272,7 @@ public virtual Product GetProductById(int productId) return null; string key = string.Format(PRODUCTS_BY_ID_KEY, productId); - return _cacheManager.Get(key, () => + return _services.Cache.Get(key, () => { return _productRepository.GetById(productId); }); @@ -306,10 +314,10 @@ public virtual void InsertProduct(Product product) _productRepository.Insert(product); //clear cache - _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); + _services.Cache.RemoveByPattern(PRODUCTS_PATTERN_KEY); //event notification - _eventPublisher.EntityInserted(product); + _services.EventPublisher.EntityInserted(product); } /// @@ -331,12 +339,12 @@ public virtual void UpdateProduct(Product product, bool publishEvent = true) _productRepository.Update(product); // cache - _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); + _services.Cache.RemoveByPattern(PRODUCTS_PATTERN_KEY); // event notification if (publishEvent && modified) { - _eventPublisher.EntityUpdated(product); + _services.EventPublisher.EntityUpdated(product); } } @@ -355,7 +363,7 @@ public virtual IPagedList SearchProducts(ProductSearchContext ctx) ctx.FilterableSpecificationAttributeOptionIds = new List(); - _eventPublisher.Publish(new ProductsSearchingEvent(ctx)); + _services.EventPublisher.Publish(new ProductsSearchingEvent(ctx)); //search by keyword bool searchLocalizedValue = false; @@ -378,7 +386,7 @@ public virtual IPagedList SearchProducts(ProductSearchContext ctx) ctx.CategoryIds.Remove(0); //Access control list. Allowed customer roles - var allowedCustomerRolesIds = _workContext.CurrentCustomer.CustomerRoles + var allowedCustomerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles .Where(cr => cr.Active).Select(cr => cr.Id).ToList(); if (_commonSettings.UseStoredProceduresIfSupported && _dataProvider.StoredProceduresSupported) @@ -735,7 +743,7 @@ public virtual IQueryable PrepareProductSearchQuery( if (allowedCustomerRolesIds == null) { - allowedCustomerRolesIds = _workContext.CurrentCustomer.CustomerRoles.Where(cr => cr.Active).Select(cr => cr.Id).ToList(); + allowedCustomerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(cr => cr.Active).Select(cr => cr.Id).ToList(); } // products @@ -1249,6 +1257,76 @@ public virtual void UpdateHasDiscountsApplied(Product product) UpdateProduct(product); } + /// + /// Creates a RSS feed with recently added products + /// + /// UrlHelper to generate URLs + /// SmartSyndicationFeed object + public virtual SmartSyndicationFeed CreateRecentlyAddedProductsRssFeed(UrlHelper urlHelper) + { + if (urlHelper == null) + throw new ArgumentNullException("urlHelper"); + + var protocol = _services.WebHelper.IsCurrentConnectionSecured() ? "https" : "http"; + var selfLink = urlHelper.RouteUrl("RecentlyAddedProductsRSS", null, protocol); + var recentProductsLink = urlHelper.RouteUrl("RecentlyAddedProducts", null, protocol); + + var title = "{0} - {1}".FormatInvariant(_services.StoreContext.CurrentStore.Name, _services.Localization.GetResource("RSS.RecentlyAddedProducts")); + + var feed = new SmartSyndicationFeed(new Uri(recentProductsLink), title, _services.Localization.GetResource("RSS.InformationAboutProducts")); + + feed.AddNamespaces(true); + feed.Init(selfLink, _services.WorkContext.WorkingLanguage); + + if (!_catalogSettings.RecentlyAddedProductsEnabled) + return feed; + + var items = new List(); + var searchContext = new ProductSearchContext + { + LanguageId = _services.WorkContext.WorkingLanguage.Id, + OrderBy = ProductSortingEnum.CreatedOn, + PageSize = _catalogSettings.RecentlyAddedProductsNumber, + StoreId = _services.StoreContext.CurrentStoreIdIfMultiStoreMode, + VisibleIndividuallyOnly = true + }; + + var products = SearchProducts(searchContext); + var storeUrl = _services.StoreContext.CurrentStore.Url; + + foreach (var product in products) + { + string productUrl = urlHelper.RouteUrl("Product", new { SeName = product.GetSeName() }, "http"); + if (productUrl.HasValue()) + { + var item = feed.CreateItem( + product.GetLocalized(x => x.Name), + product.GetLocalized(x => x.ShortDescription), + productUrl, + product.CreatedOnUtc, + product.FullDescription); + + try + { + // we add only the first picture + var picture = product.ProductPictures.OrderBy(x => x.DisplayOrder).Select(x => x.Picture).FirstOrDefault(); + + if (picture != null) + { + feed.AddEnclosue(item, picture, _pictureService.GetPictureUrl(picture, _mediaSettings.ProductDetailsPictureSize, false, storeUrl)); + } + } + catch { } + + items.Add(item); + } + } + + feed.Items = items; + + return feed; + } + #endregion #region Related products @@ -1265,7 +1343,7 @@ public virtual void DeleteRelatedProduct(RelatedProduct relatedProduct) _relatedProductRepository.Delete(relatedProduct); //event notification - _eventPublisher.EntityDeleted(relatedProduct); + _services.EventPublisher.EntityDeleted(relatedProduct); } /// @@ -1312,7 +1390,7 @@ public virtual void InsertRelatedProduct(RelatedProduct relatedProduct) _relatedProductRepository.Insert(relatedProduct); //event notification - _eventPublisher.EntityInserted(relatedProduct); + _services.EventPublisher.EntityInserted(relatedProduct); } /// @@ -1327,7 +1405,7 @@ public virtual void UpdateRelatedProduct(RelatedProduct relatedProduct) _relatedProductRepository.Update(relatedProduct); //event notification - _eventPublisher.EntityUpdated(relatedProduct); + _services.EventPublisher.EntityUpdated(relatedProduct); } /// @@ -1363,7 +1441,7 @@ public virtual void DeleteCrossSellProduct(CrossSellProduct crossSellProduct) _crossSellProductRepository.Delete(crossSellProduct); //event notification - _eventPublisher.EntityDeleted(crossSellProduct); + _services.EventPublisher.EntityDeleted(crossSellProduct); } /// @@ -1411,7 +1489,7 @@ public virtual void InsertCrossSellProduct(CrossSellProduct crossSellProduct) _crossSellProductRepository.Insert(crossSellProduct); //event notification - _eventPublisher.EntityInserted(crossSellProduct); + _services.EventPublisher.EntityInserted(crossSellProduct); } /// @@ -1426,7 +1504,7 @@ public virtual void UpdateCrossSellProduct(CrossSellProduct crossSellProduct) _crossSellProductRepository.Update(crossSellProduct); //event notification - _eventPublisher.EntityUpdated(crossSellProduct); + _services.EventPublisher.EntityUpdated(crossSellProduct); } /// @@ -1510,10 +1588,10 @@ public virtual void DeleteTierPrice(TierPrice tierPrice) _tierPriceRepository.Delete(tierPrice); - _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); + _services.Cache.RemoveByPattern(PRODUCTS_PATTERN_KEY); //event notification - _eventPublisher.EntityDeleted(tierPrice); + _services.EventPublisher.EntityDeleted(tierPrice); } /// @@ -1541,10 +1619,10 @@ public virtual void InsertTierPrice(TierPrice tierPrice) _tierPriceRepository.Insert(tierPrice); - _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); + _services.Cache.RemoveByPattern(PRODUCTS_PATTERN_KEY); //event notification - _eventPublisher.EntityInserted(tierPrice); + _services.EventPublisher.EntityInserted(tierPrice); } /// @@ -1558,10 +1636,10 @@ public virtual void UpdateTierPrice(TierPrice tierPrice) _tierPriceRepository.Update(tierPrice); - _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); + _services.Cache.RemoveByPattern(PRODUCTS_PATTERN_KEY); //event notification - _eventPublisher.EntityUpdated(tierPrice); + _services.EventPublisher.EntityUpdated(tierPrice); } #endregion @@ -1582,7 +1660,7 @@ public virtual void DeleteProductPicture(ProductPicture productPicture) _productPictureRepository.Delete(productPicture); //event notification - _eventPublisher.EntityDeleted(productPicture); + _services.EventPublisher.EntityDeleted(productPicture); } private void UnassignDeletedPictureFromVariantCombinations(ProductPicture productPicture) @@ -1656,7 +1734,7 @@ public virtual void InsertProductPicture(ProductPicture productPicture) _productPictureRepository.Insert(productPicture); //event notification - _eventPublisher.EntityInserted(productPicture); + _services.EventPublisher.EntityInserted(productPicture); } /// @@ -1671,7 +1749,7 @@ public virtual void UpdateProductPicture(ProductPicture productPicture) _productPictureRepository.Update(productPicture); //event notification - _eventPublisher.EntityUpdated(productPicture); + _services.EventPublisher.EntityUpdated(productPicture); } #endregion @@ -1699,7 +1777,7 @@ public virtual void InsertBundleItem(ProductBundleItem bundleItem) _productBundleItemRepository.Insert(bundleItem); //event notification - _eventPublisher.EntityInserted(bundleItem); + _services.EventPublisher.EntityInserted(bundleItem); } /// @@ -1714,7 +1792,7 @@ public virtual void UpdateBundleItem(ProductBundleItem bundleItem) _productBundleItemRepository.Update(bundleItem); //event notification - _eventPublisher.EntityUpdated(bundleItem); + _services.EventPublisher.EntityUpdated(bundleItem); } /// @@ -1729,7 +1807,7 @@ public virtual void DeleteBundleItem(ProductBundleItem bundleItem) _productBundleItemRepository.Delete(bundleItem); //event notification - _eventPublisher.EntityDeleted(bundleItem); + _services.EventPublisher.EntityDeleted(bundleItem); } /// diff --git a/src/Libraries/SmartStore.Services/News/NewsService.cs b/src/Libraries/SmartStore.Services/News/NewsService.cs index c0d576ca29..66adadf90e 100644 --- a/src/Libraries/SmartStore.Services/News/NewsService.cs +++ b/src/Libraries/SmartStore.Services/News/NewsService.cs @@ -224,7 +224,7 @@ public virtual SmartSyndicationFeed CreateRssFeed(UrlHelper urlHelper, int langu DateTime? maxAge = null; var protocol = _services.WebHelper.IsCurrentConnectionSecured() ? "https" : "http"; - var selfLink = urlHelper.Action("rss", null, new { languageId = languageId }, protocol); + var selfLink = urlHelper.Action("rss", "News", new { languageId = languageId }, protocol); var newsLink = urlHelper.RouteUrl("NewsArchive", null, protocol); var title = "{0} - News".FormatInvariant(_services.StoreContext.CurrentStore.Name); @@ -248,9 +248,7 @@ public virtual SmartSyndicationFeed CreateRssFeed(UrlHelper urlHelper, int langu { var newsUrl = urlHelper.RouteUrl("NewsItem", new { SeName = news.GetSeName(news.LanguageId, ensureTwoPublishedLanguages: false) }, "http"); - var item = new SyndicationItem(news.Title, news.Short.RemoveInvalidXmlChars(), new Uri(newsUrl), newsUrl, news.CreatedOnUtc); - - item.ElementExtensions.Add("encoded", SmartSyndicationFeed.UrlPurlContent, news.Full.RemoveInvalidXmlChars()); + var item = feed.CreateItem(news.Title, news.Short, newsUrl, news.CreatedOnUtc, news.Full); items.Add(item); } diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs index 7c210cee70..1e77b41b24 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs @@ -22,6 +22,7 @@ using SmartStore.Services.Seo; using SmartStore.Services.Stores; using SmartStore.Web.Framework.Controllers; +using SmartStore.Web.Framework.Mvc; using SmartStore.Web.Framework.Security; using SmartStore.Web.Framework.UI; using SmartStore.Web.Infrastructure.Cache; @@ -854,39 +855,12 @@ public ActionResult RecentlyAddedProducts(CatalogPagingFilteringModel command) return View(model); } + [Compress] public ActionResult RecentlyAddedProductsRss() { - var feed = new SyndicationFeed( - string.Format("{0}: {1}", _services.StoreContext.CurrentStore.Name, T("RSS.RecentlyAddedProducts")), - T("RSS.InformationAboutProducts"), - new Uri(_services.WebHelper.GetStoreLocation(false)), - "RecentlyAddedProductsRSS", - DateTime.UtcNow); + var feed = _productService.CreateRecentlyAddedProductsRssFeed(Url); - if (!_catalogSettings.RecentlyAddedProductsEnabled) - return new RssActionResult() { Feed = feed }; - - var items = new List(); - - var ctx = new ProductSearchContext(); - ctx.LanguageId = _services.WorkContext.WorkingLanguage.Id; - ctx.OrderBy = ProductSortingEnum.CreatedOn; - ctx.PageSize = _catalogSettings.RecentlyAddedProductsNumber; - ctx.StoreId = _services.StoreContext.CurrentStoreIdIfMultiStoreMode; - ctx.VisibleIndividuallyOnly = true; - - var products = _productService.SearchProducts(ctx); - - foreach (var product in products) - { - string productUrl = Url.RouteUrl("Product", new { SeName = product.GetSeName() }, "http"); - if (!String.IsNullOrEmpty(productUrl)) - { - items.Add(new SyndicationItem(product.GetLocalized(x => x.Name), product.GetLocalized(x => x.ShortDescription), new Uri(productUrl), String.Format("RecentlyAddedProduct:{0}", product.Id), product.CreatedOnUtc)); - } - } - feed.Items = items; - return new RssActionResult() { Feed = feed }; + return new RssActionResult { Feed = feed }; } #endregion diff --git a/src/Presentation/SmartStore.Web/Views/Catalog/RecentlyAddedProducts.cshtml b/src/Presentation/SmartStore.Web/Views/Catalog/RecentlyAddedProducts.cshtml index db5b531560..0fadfa1646 100644 --- a/src/Presentation/SmartStore.Web/Views/Catalog/RecentlyAddedProducts.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Catalog/RecentlyAddedProducts.cshtml @@ -24,11 +24,15 @@
-
-
+ +
+
@*@if (ShowListOptions()) { From 991d84d8b27c340db5b2d21a187aeca45f2afd46 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 2 Jul 2015 01:03:49 +0200 Subject: [PATCH 0213/1256] E-mail attachments: further development --- .../Extensions/ConversionExtensions.cs | 51 ++++---------- .../Extensions/HttpExtensions.cs | 17 +++++ .../Messages/QueuingEmailEventConsumer.cs | 67 ++++++++++++++++++- .../Services/ProfilerService.cs | 7 +- .../Controllers/OrderController.cs | 1 + 5 files changed, 102 insertions(+), 41 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs index 20ff82f9a2..35781072ef 100644 --- a/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs @@ -498,45 +498,23 @@ public static byte[] ToByteArray(this Stream stream) { Guard.ArgumentNotNull(stream, "stream"); - byte[] buffer; - - if (stream is MemoryStream && stream.CanRead && stream.CanSeek) - { - int len = System.Convert.ToInt32(stream.Length); - buffer = new byte[len]; - stream.Read(buffer, 0, len); - return buffer; - } - - MemoryStream memStream = null; - try - { - buffer = new byte[1024]; - memStream = new MemoryStream(); - int bytesRead = stream.Read(buffer, 0, buffer.Length); - if (bytesRead > 0) - { - memStream.Write(buffer, 0, bytesRead); - bytesRead = stream.Read(buffer, 0, buffer.Length); - } - } - finally - { - if (memStream != null) - memStream.Close(); - } - - if (memStream != null) - { - return memStream.ToArray(); - } - - return null; + if (stream is MemoryStream) + { + return ((MemoryStream)stream).ToArray(); + } + else + { + using (var ms = new MemoryStream()) + { + stream.CopyTo(ms); + return ms.ToArray(); + } + } } public static string AsString(this Stream stream) { - // convert memory stream to string + // convert stream to string string result; stream.Position = 0; @@ -546,7 +524,6 @@ public static string AsString(this Stream stream) } return result; - } #endregion @@ -644,7 +621,7 @@ internal static byte[] ToByteArray(this Image image, ImageFormat format) using (var stream = new MemoryStream()) { image.Save(stream, format); - return stream.ToByteArray(); + return stream.ToArray(); } } diff --git a/src/Libraries/SmartStore.Core/Extensions/HttpExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/HttpExtensions.cs index be4e64b78b..4279070910 100644 --- a/src/Libraries/SmartStore.Core/Extensions/HttpExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/HttpExtensions.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Net; using System.Text; using System.Web; +using System.Web.Security; namespace SmartStore { @@ -31,6 +33,21 @@ public static bool IsSecureConnection(this HttpRequest request) { return (request.IsSecureConnection || (request.ServerVariables[HTTP_CLUSTER_VAR] != null || request.ServerVariables[HTTP_CLUSTER_VAR] == "on")); } + + public static void SetFormsAuthenticationCookie(this HttpWebRequest webRequest, HttpRequestBase httpRequest) + { + Guard.ArgumentNotNull(() => webRequest); + Guard.ArgumentNotNull(() => httpRequest); + + var authCookie = httpRequest.Cookies[FormsAuthentication.FormsCookieName]; + var sendCookie = new Cookie(authCookie.Name, authCookie.Value, authCookie.Path, httpRequest.Url.Host); + + if (webRequest.CookieContainer == null) + { + webRequest.CookieContainer = new CookieContainer(); + } + webRequest.CookieContainer.Add(sendCookie); + } } } diff --git a/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs b/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs index 04bb77d509..63d2ae0eae 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs @@ -1,23 +1,36 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; +using System.Net.Mime; using System.Text; using System.Threading.Tasks; +using System.Web; +using System.Web.Mvc; +using System.Web.Security; +using SmartStore.Core; using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Messages; using SmartStore.Core.Events; +using SmartStore.Core.Logging; namespace SmartStore.Services.Messages { public class QueuingEmailEventConsumer : IConsumer { private readonly PdfSettings _pdfSettings; + private readonly HttpRequestBase _httpRequest; - public QueuingEmailEventConsumer(PdfSettings pdfSettings) + public QueuingEmailEventConsumer(PdfSettings pdfSettings, HttpRequestBase httpRequest) { this._pdfSettings = pdfSettings; + this._httpRequest = httpRequest; + + Logger = NullLogger.Instance; } + public ILogger Logger { get; set; } + public void HandleEvent(QueuingEmailEvent eventMessage) { var qe = eventMessage.QueuedEmail; @@ -38,7 +51,57 @@ public void HandleEvent(QueuingEmailEvent eventMessage) private QueuedEmailAttachment CreatePdfInvoiceAttachment(int orderId) { - // TODO: (mc) implement + // TODO: (mc) create common util function 'CreateAttachmentFromUrl()' OR 'DownloadFile()' + + var urlHelper = new UrlHelper(_httpRequest.RequestContext); + var path = urlHelper.Action("Print", "Order", new { id = orderId, pdf = true }); + var url = WebHelper.GetAbsoluteUrl(path, _httpRequest); + + var request = (HttpWebRequest)WebRequest.Create(url); + request.UserAgent = "SmartStore.NET"; + request.Timeout = 5000; + + request.SetFormsAuthenticationCookie(_httpRequest); + + HttpWebResponse response = null; + + try + { + response = (HttpWebResponse)request.GetResponse(); + + using (var stream = response.GetResponseStream()) + { + if (response.StatusCode == HttpStatusCode.OK && response.ContentType == "application/pdf") + { + var pdfBinary = stream.ToByteArray(); + + var cd = new ContentDisposition(response.Headers["Content-Disposition"]); + var fileName = cd.FileName; + + return new QueuedEmailAttachment + { + StorageLocation = EmailAttachmentStorageLocation.Blob, + Data = pdfBinary, + MimeType = "application/pdf", + Name = fileName + }; + } + } + } + catch (Exception ex) + { + // TODO localize + Logger.Error("Error occured while creating e-mail attachment", ex); + } + finally + { + if (response != null) + { + response.Close(); + response.Dispose(); + } + } + return null; } diff --git a/src/Plugins/SmartStore.DevTools/Services/ProfilerService.cs b/src/Plugins/SmartStore.DevTools/Services/ProfilerService.cs index 462451a123..e490e592f2 100644 --- a/src/Plugins/SmartStore.DevTools/Services/ProfilerService.cs +++ b/src/Plugins/SmartStore.DevTools/Services/ProfilerService.cs @@ -43,9 +43,12 @@ public void StepStop(string key) } IDisposable step; - if (this.steps[key].TryPop(out step)) + if (this.steps.ContainsKey(key)) { - step.Dispose(); + if (this.steps[key].TryPop(out step)) + { + step.Dispose(); + } } } diff --git a/src/Presentation/SmartStore.Web/Controllers/OrderController.cs b/src/Presentation/SmartStore.Web/Controllers/OrderController.cs index b1217ad312..70ba4ddab4 100644 --- a/src/Presentation/SmartStore.Web/Controllers/OrderController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/OrderController.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Web.Mvc; using System.Web.Routing; +using System.Web.SessionState; using SmartStore.Core.Data; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Common; From 37cc732562089cdd37ad04de61abb635b17cd287 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Fri, 3 Jul 2015 11:11:04 +0200 Subject: [PATCH 0214/1256] Updated changelog --- changelog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 36cac97370..f804da9730 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,4 @@ -# Release Notes +# Release Notes ## SmartStore.NET 2.2.2 @@ -16,6 +16,7 @@ * Fixed: If currencies are limited to one for a multi-store, this currency should dominate the setting for the primary store currency * #563 Scheduled Tasks: ensure, that 'LastEndUtc' is ALWAYS set * Topics grid: fixed 'maxJsonLength exceeded' error +* Debitoor: Fixed "The property named 'lines.0.productOrService' should be defined" ## SmartStore.NET 2.2.1 From 48da5ef9d9111efc9aa2a087bba697be5cf2ef85 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Sat, 4 Jul 2015 01:04:54 +0200 Subject: [PATCH 0215/1256] E-mail attachments: further development --- .../Domain/Common/PdfSettings.cs | 10 ++ .../Domain/Messages/QueuedEmailAttachment.cs | 2 +- .../Utilities/FileDownloadManager.cs | 82 ++++++++++++- .../Messages/IQueuedEmailService.cs | 31 +++-- .../Messages/QueuedEmailService.cs | 110 +++++++++++++----- .../Messages/QueuedMessagesSendTask.cs | 9 +- .../Messages/QueuingEmailEventConsumer.cs | 71 +++++------ .../Orders/OrderProcessingService.cs | 4 +- .../DependencyRegistrar.cs | 1 + .../Controllers/QueuedEmailController.cs | 55 ++++++++- .../Controllers/SettingController.cs | 4 + .../Infrastructure/AutoMapperStartupTask.cs | 14 ++- .../Models/Messages/QueuedEmailModel.cs | 20 +++- .../Settings/GeneralCommonSettingsModel.cs | 6 + .../Views/QueuedEmail/List.cshtml | 9 +- .../Views/QueuedEmail/_CreateOrUpdate.cshtml | 17 +++ .../Views/Setting/GeneralCommon.cshtml | 23 ++++ .../Messages/QueuedEmailServiceTests.cs | 4 +- 18 files changed, 366 insertions(+), 106 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Domain/Common/PdfSettings.cs b/src/Libraries/SmartStore.Core/Domain/Common/PdfSettings.cs index 45a7c50906..bddfb93963 100644 --- a/src/Libraries/SmartStore.Core/Domain/Common/PdfSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Common/PdfSettings.cs @@ -30,5 +30,15 @@ public PdfSettings() /// Gets or sets a value indicating whether to render order notes in PDf reports ///
public bool RenderOrderNotes { get; set; } + + /// + /// Gets or sets a value indicating whether to attach the order PDF to 'Order Placed (customer)' email + /// + public bool AttachOrderPdfToOrderPlacedEmail { get; set; } + + /// + /// Gets or sets a value indicating whether to attach the order PDF to 'Order Completed (customer)' email + /// + public bool AttachOrderPdfToOrderCompletedEmail { get; set; } } } \ No newline at end of file diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs index c0f6978143..6f131b0a41 100644 --- a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs +++ b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs @@ -57,7 +57,7 @@ public partial class QueuedEmailAttachment : BaseEntity public string Name { get; set; } /// - /// The attachment file's mime type, e.g. + /// The attachment file's mime type, e.g. application/pdf /// public string MimeType { get; set; } diff --git a/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs b/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs index 6b95e181b6..de2db7a3e9 100644 --- a/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs +++ b/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs @@ -5,8 +5,11 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Net.Mime; using System.Threading; using System.Threading.Tasks; +using System.Web; +using SmartStore.Core; using SmartStore.Core.Logging; namespace SmartStore.Utilities @@ -15,8 +18,57 @@ public class FileDownloadManager { private const int _bufferSize = 16384; + private readonly HttpRequestBase _httpRequest; + + public FileDownloadManager(HttpRequestBase httpRequest) + { + this._httpRequest = httpRequest; + } + /// - /// Start asynchronous download of files + /// Downloads a single file synchronously + /// + /// The URL to download the file from (either a fully qualified URL or an app relative/absolute path) + /// Specifies whether the FormsAuthenticationCookie should be sent + /// Timeout in milliseconds + public FileDownloadResponse DownloadFile(string url, bool sendAuthCookie = false, int? timeout = null) + { + Guard.ArgumentNotEmpty(() => url); + + url = WebHelper.GetAbsoluteUrl(url, _httpRequest); + + var req = (HttpWebRequest)WebRequest.Create(url); + req.UserAgent = "SmartStore.NET"; + + if (timeout.HasValue) + { + req.Timeout = timeout.Value; + } + + if (sendAuthCookie) + { + req.SetFormsAuthenticationCookie(_httpRequest); + } + + using (var resp = (HttpWebResponse)req.GetResponse()) + { + using (var stream = resp.GetResponseStream()) + { + if (resp.StatusCode == HttpStatusCode.OK) + { + var data = stream.ToByteArray(); + var cd = new ContentDisposition(resp.Headers["Content-Disposition"]); + var fileName = cd.FileName; + return new FileDownloadResponse(data, fileName, resp.ContentType); + } + } + } + + return null; + } + + /// + /// Starts asynchronous download of files and saves them to disk /// /// Download context /// Items to be downloaded @@ -96,6 +148,34 @@ private async Task ProcessUrl(FileDownloadManagerContext context, HttpClient cli } + public class FileDownloadResponse + { + public FileDownloadResponse(byte[] data, string fileName, string contentType) + { + Guard.ArgumentNotNull(() => data); + Guard.ArgumentNotEmpty(() => fileName); + Guard.ArgumentNotEmpty(() => contentType); + + this.Data = data; + this.FileName = fileName; + this.ContentType = contentType; + } + + /// + /// The downloaded file's byte array + /// + public byte[] Data { get; private set; } + + /// + /// The file name + /// + public string FileName { get; private set; } + + /// + /// The mime type opf the downloaded file + /// + public string ContentType { get; private set; } + } public class FileDownloadManagerContext { diff --git a/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs index 6b1db9e52c..12baf20719 100644 --- a/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/IQueuedEmailService.cs @@ -48,23 +48,9 @@ public partial interface IQueuedEmailService /// /// Search queued emails /// - /// From Email - /// To Email - /// The start time - /// The end time - /// A value indicating whether to load only not sent emails - /// Maximum send tries - /// A value indicating whether we should sort queued email descending; otherwise, ascending. - /// Page index - /// Page size - /// A value indicating whether to load manually send emails + /// An object containing the query criteria /// Email item collection - IPagedList SearchEmails( - string fromEmail, string toEmail, - DateTime? startTime, DateTime? endTime, - bool loadUnsentItemsOnly, int maxSendTries, - bool loadNewest, int pageIndex, int pageSize, - bool? sendManually = null); + IPagedList SearchEmails(SearchEmailsQuery query); /// /// Sends a queued email @@ -72,5 +58,18 @@ IPagedList SearchEmails( /// Queued email /// Whether the operation succeeded bool SendEmail(QueuedEmail queuedEmail); + + /// + /// Gets a queued email attachment by identifier + /// + /// Queued email attachment identifier + /// Queued email attachment + QueuedEmailAttachment GetQueuedEmailAttachmentById(int id); + + /// + /// Deleted a queued email attachment + /// + /// Queued email attachment + void DeleteQueuedEmailAttachment(QueuedEmailAttachment qea); } } diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs index 1c40be1554..8a742c99e6 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs @@ -19,12 +19,18 @@ namespace SmartStore.Services.Messages public partial class QueuedEmailService : IQueuedEmailService { private readonly IRepository _queuedEmailRepository; + private readonly IRepository _queuedEmailAttachmentRepository; private readonly IEmailSender _emailSender; private readonly ICommonServices _services; - public QueuedEmailService(IRepository queuedEmailRepository, IEmailSender emailSender, ICommonServices services) + public QueuedEmailService( + IRepository queuedEmailRepository, + IRepository queuedEmailAttachmentRepository, + IEmailSender emailSender, + ICommonServices services) { this._queuedEmailRepository = queuedEmailRepository; + this._queuedEmailAttachmentRepository = queuedEmailAttachmentRepository; this._emailSender = emailSender; this._services = services; @@ -80,7 +86,6 @@ public virtual QueuedEmail GetQueuedEmailById(int queuedEmailId) var queuedEmail = _queuedEmailRepository.GetById(queuedEmailId); return queuedEmail; - } public virtual IList GetQueuedEmailsByIds(int[] queuedEmailIds) @@ -106,44 +111,48 @@ where queuedEmailIds.Contains(qe.Id) return sortedQueuedEmails; } - public virtual IPagedList SearchEmails(string fromEmail, - string toEmail, DateTime? startTime, DateTime? endTime, - bool loadUnsentItemsOnly, int maxSendTries, - bool loadNewest, int pageIndex, int pageSize, - bool? sendManually = null) + public virtual IPagedList SearchEmails(SearchEmailsQuery query) { - fromEmail = (fromEmail ?? String.Empty).Trim(); - toEmail = (toEmail ?? String.Empty).Trim(); + Guard.ArgumentNotNull(() => query); - var query = _queuedEmailRepository.Table.Expand(x => x.EmailAccount); + var q = _queuedEmailRepository.Table; - if (!String.IsNullOrEmpty(fromEmail)) - query = query.Where(qe => qe.From.Contains(fromEmail)); + if (query.Expand.HasValue()) + { + var expands = query.Expand.Split(','); + foreach (var expand in expands) + { + q = q.Expand(expand.Trim()); + } + } - if (!String.IsNullOrEmpty(toEmail)) - query = query.Where(qe => qe.To.Contains(toEmail)); + if (query.From.HasValue()) + q = q.Where(qe => qe.From.Contains(query.From.Trim())); - if (startTime.HasValue) - query = query.Where(qe => qe.CreatedOnUtc >= startTime); + if (query.To.HasValue()) + q = q.Where(qe => qe.To.Contains(query.To.Trim())); - if (endTime.HasValue) - query = query.Where(qe => qe.CreatedOnUtc <= endTime); + if (query.StartTime.HasValue) + q = q.Where(qe => qe.CreatedOnUtc >= query.StartTime); - if (loadUnsentItemsOnly) - query = query.Where(qe => !qe.SentOnUtc.HasValue); + if (query.EndTime.HasValue) + q = q.Where(qe => qe.CreatedOnUtc <= query.EndTime); - if (sendManually.HasValue) - query = query.Where(qe => qe.SendManually == sendManually.Value); + if (query.UnsentOnly) + q = q.Where(qe => !qe.SentOnUtc.HasValue); - query = query.Where(qe => qe.SentTries < maxSendTries); + if (query.SendManually.HasValue) + q = q.Where(qe => qe.SendManually == query.SendManually.Value); + + q = q.Where(qe => qe.SentTries < query.MaxSendTries); - query = query.OrderByDescending(qe => qe.Priority); + q = q.OrderByDescending(qe => qe.Priority); - query = loadNewest ? - ((IOrderedQueryable)query).ThenByDescending(qe => qe.CreatedOnUtc) : - ((IOrderedQueryable)query).ThenBy(qe => qe.CreatedOnUtc); + q = query.OrderByLatest ? + ((IOrderedQueryable)q).ThenByDescending(qe => qe.CreatedOnUtc) : + ((IOrderedQueryable)q).ThenBy(qe => qe.CreatedOnUtc); - var queuedEmails = new PagedList(query, pageIndex, pageSize); + var queuedEmails = new PagedList(q, query.PageIndex, query.PageSize); return queuedEmails; } @@ -249,5 +258,48 @@ internal EmailMessage ConvertEmail(QueuedEmail qe) return msg; } - } + + #region Attachments + + public virtual QueuedEmailAttachment GetQueuedEmailAttachmentById(int id) + { + if (id == 0) + return null; + + var qea = _queuedEmailAttachmentRepository.GetById(id); + return qea; + } + + public virtual void DeleteQueuedEmailAttachment(QueuedEmailAttachment qea) + { + if (qea == null) + throw new ArgumentNullException("qea"); + + _queuedEmailAttachmentRepository.Delete(qea); + + _services.EventPublisher.EntityDeleted(qea); + } + + #endregion + } + + public class SearchEmailsQuery + { + public string From { get; set; } + public string To { get; set; } + public DateTime? StartTime { get; set; } + public DateTime? EndTime { get; set; } + public bool UnsentOnly { get; set; } + public int MaxSendTries { get; set; } + public bool OrderByLatest { get; set; } + public int PageIndex { get; set; } + public int PageSize { get; set; } + public bool? SendManually { get; set; } + + /// + /// Navigation properties to eager load (comma separataed) + /// + public string Expand { get; set; } + } + } diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs index 3223633b5f..b3058c31a8 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs @@ -21,7 +21,14 @@ public void Execute(TaskExecutionContext ctx) for (int i = 0; i < 9999999; ++i) { - var queuedEmails = _queuedEmailService.SearchEmails(null, null, null, null, true, maxTries, false, i, pageSize, false); + var q = new SearchEmailsQuery + { + MaxSendTries = maxTries, + PageIndex = i, + PageSize = pageSize, + Expand = "Attachments" + }; + var queuedEmails = _queuedEmailService.SearchEmails(q); foreach (var queuedEmail in queuedEmails) { diff --git a/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs b/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs index 63d2ae0eae..dd50b40c44 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs @@ -13,6 +13,7 @@ using SmartStore.Core.Domain.Messages; using SmartStore.Core.Events; using SmartStore.Core.Logging; +using SmartStore.Utilities; namespace SmartStore.Services.Messages { @@ -20,11 +21,16 @@ public class QueuingEmailEventConsumer : IConsumer { private readonly PdfSettings _pdfSettings; private readonly HttpRequestBase _httpRequest; + private readonly Lazy _fileDownloadManager; - public QueuingEmailEventConsumer(PdfSettings pdfSettings, HttpRequestBase httpRequest) + public QueuingEmailEventConsumer( + PdfSettings pdfSettings, + HttpRequestBase httpRequest, + Lazy fileDownloadManager) { this._pdfSettings = pdfSettings; this._httpRequest = httpRequest; + this._fileDownloadManager = fileDownloadManager; Logger = NullLogger.Instance; } @@ -36,9 +42,14 @@ public void HandleEvent(QueuingEmailEvent eventMessage) var qe = eventMessage.QueuedEmail; var tpl = eventMessage.MessageTemplate; - // TODO: (mc) determine and apply PdfSettings - - if (tpl.Name.IsCaseInsensitiveEqual("OrderPlaced.CustomerNotification")) + var handledTemplates = new Dictionary(StringComparer.OrdinalIgnoreCase) + { + { "OrderPlaced.CustomerNotification", _pdfSettings.AttachOrderPdfToOrderPlacedEmail }, + { "OrderCompleted.CustomerNotification", _pdfSettings.AttachOrderPdfToOrderCompletedEmail } + }; + + bool shouldHandle = false; + if (handledTemplates.TryGetValue(tpl.Name, out shouldHandle) && shouldHandle) { var orderId = eventMessage.Tokens.First(x => x.Key.IsCaseInsensitiveEqual("Order.ID")).Value.ToInt(); var qea = CreatePdfInvoiceAttachment(orderId); @@ -51,56 +62,36 @@ public void HandleEvent(QueuingEmailEvent eventMessage) private QueuedEmailAttachment CreatePdfInvoiceAttachment(int orderId) { - // TODO: (mc) create common util function 'CreateAttachmentFromUrl()' OR 'DownloadFile()' - var urlHelper = new UrlHelper(_httpRequest.RequestContext); - var path = urlHelper.Action("Print", "Order", new { id = orderId, pdf = true }); - var url = WebHelper.GetAbsoluteUrl(path, _httpRequest); - - var request = (HttpWebRequest)WebRequest.Create(url); - request.UserAgent = "SmartStore.NET"; - request.Timeout = 5000; - - request.SetFormsAuthenticationCookie(_httpRequest); - - HttpWebResponse response = null; + var path = urlHelper.Action("Print", "Order", new { id = orderId, pdf = true, area = "" }); try { - response = (HttpWebResponse)request.GetResponse(); + var fileResponse = _fileDownloadManager.Value.DownloadFile(path, true, 5000); - using (var stream = response.GetResponseStream()) + if (fileResponse == null) { - if (response.StatusCode == HttpStatusCode.OK && response.ContentType == "application/pdf") - { - var pdfBinary = stream.ToByteArray(); - - var cd = new ContentDisposition(response.Headers["Content-Disposition"]); - var fileName = cd.FileName; + // ... + } - return new QueuedEmailAttachment - { - StorageLocation = EmailAttachmentStorageLocation.Blob, - Data = pdfBinary, - MimeType = "application/pdf", - Name = fileName - }; - } + if (!fileResponse.ContentType.IsCaseInsensitiveEqual("application/pdf")) + { + // ... } + + return new QueuedEmailAttachment + { + StorageLocation = EmailAttachmentStorageLocation.Blob, + Data = fileResponse.Data, + MimeType = fileResponse.ContentType, + Name = fileResponse.FileName + }; } catch (Exception ex) { // TODO localize Logger.Error("Error occured while creating e-mail attachment", ex); } - finally - { - if (response != null) - { - response.Close(); - response.Dispose(); - } - } return null; } diff --git a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs index 1ce5ce0eb6..d955f22aab 100644 --- a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs +++ b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs @@ -2111,7 +2111,7 @@ public virtual void MarkOrderAsPaid(Order order) _orderService.UpdateOrder(order); //add a note - order.OrderNotes.Add(new OrderNote() + order.OrderNotes.Add(new OrderNote { Note = TNote("OrderMarkedAsPaid"), DisplayToCustomer = false, @@ -2121,7 +2121,7 @@ public virtual void MarkOrderAsPaid(Order order) CheckOrderStatus(order); - //raise event + // raise event if (order.PaymentStatus == PaymentStatus.Paid) { _eventPublisher.PublishOrderPaid(order); diff --git a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs index 549ad459a9..51d8199e1a 100644 --- a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs +++ b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs @@ -575,6 +575,7 @@ protected override void Load(ContainerBuilder builder) builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().InstancePerRequest(); + builder.RegisterType().InstancePerRequest(); builder.RegisterFilterProvider(); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs index 2b6f9fce31..d00783f2cf 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Web; using System.Web.Mvc; using SmartStore.Admin.Models.Messages; using SmartStore.Core.Domain.Messages; @@ -8,6 +9,7 @@ using SmartStore.Services.Localization; using SmartStore.Services.Messages; using SmartStore.Services.Security; +using SmartStore.Utilities; using SmartStore.Web.Framework.Controllers; using Telerik.Web.Mvc; @@ -53,13 +55,22 @@ public ActionResult QueuedEmailList(GridCommand command, QueuedEmailListModel mo return AccessDeniedView(); DateTime? startDateValue = (model.SearchStartDate == null) ? null : (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.SearchStartDate.Value, _dateTimeHelper.CurrentTimeZone); - DateTime? endDateValue = (model.SearchEndDate == null) ? null : (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.SearchEndDate.Value, _dateTimeHelper.CurrentTimeZone).AddDays(1); - var queuedEmails = _queuedEmailService.SearchEmails(model.SearchFromEmail, model.SearchToEmail, - startDateValue, endDateValue, - model.SearchLoadNotSent, model.SearchMaxSentTries, true, - command.Page - 1, command.PageSize, model.SearchSendManually); + var q = new SearchEmailsQuery + { + EndTime = endDateValue, + From = model.SearchFromEmail, + MaxSendTries = model.SearchMaxSentTries, + OrderByLatest = true, + PageIndex = command.Page - 1, + PageSize = command.PageSize, + SendManually = model.SearchSendManually, + StartTime = startDateValue, + To = model.SearchToEmail, + UnsentOnly = model.SearchLoadNotSent + }; + var queuedEmails = _queuedEmailService.SearchEmails(q); var gridModel = new GridModel { @@ -239,5 +250,39 @@ public ActionResult DeleteAll() return RedirectToAction("List"); } + + public ActionResult DownloadAttachment(int id) + { + if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageQueue)) + return AccessDeniedView(); + + var qea = _queuedEmailService.GetQueuedEmailAttachmentById(id); + if (qea == null) + return HttpNotFound("List"); + + if (qea.StorageLocation == EmailAttachmentStorageLocation.Blob) + { + return File(qea.Data, qea.MimeType, qea.Name); + } + else if (qea.StorageLocation == EmailAttachmentStorageLocation.Path) + { + var path = qea.Path; + if (path[0] == '~' || path[0] == '/') + { + path = CommonHelper.MapPath(VirtualPathUtility.ToAppRelative(path), false); + } + return File(path, qea.MimeType, qea.Name); + } + + // FileReference + if (qea.FileId.HasValue) + { + return RedirectToAction("DownloadFile", "Download", new { downloadId = qea.FileId.Value }); + } + + NotifyError("Could not download e-mail attachment: no data"); + return RedirectToAction("List"); + + } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs index 48bd56cf5f..90b04c7bfc 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs @@ -1050,6 +1050,8 @@ public ActionResult GeneralCommon() model.PdfSettings.Enabled = pdfSettings.Enabled; model.PdfSettings.LetterPageSizeEnabled = pdfSettings.LetterPageSizeEnabled; model.PdfSettings.LogoPictureId = pdfSettings.LogoPictureId; + model.PdfSettings.AttachOrderPdfToOrderPlacedEmail = pdfSettings.AttachOrderPdfToOrderPlacedEmail; + model.PdfSettings.AttachOrderPdfToOrderCompletedEmail = pdfSettings.AttachOrderPdfToOrderCompletedEmail; StoreDependingSettings.GetOverrideKeys(pdfSettings, model.PdfSettings, storeScope, _settingService, false); @@ -1233,6 +1235,8 @@ public ActionResult GeneralCommon(GeneralCommonSettingsModel model, FormCollecti pdfSettings.Enabled = model.PdfSettings.Enabled; pdfSettings.LetterPageSizeEnabled = model.PdfSettings.LetterPageSizeEnabled; pdfSettings.LogoPictureId = model.PdfSettings.LogoPictureId; + pdfSettings.AttachOrderPdfToOrderPlacedEmail = model.PdfSettings.AttachOrderPdfToOrderPlacedEmail; + pdfSettings.AttachOrderPdfToOrderCompletedEmail = model.PdfSettings.AttachOrderPdfToOrderCompletedEmail; StoreDependingSettings.UpdateSettings(pdfSettings, form, storeScope, _settingService); diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index 958b035003..ea8671c313 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -1,4 +1,5 @@ using System.Reflection; +using System.Linq; using AutoMapper; using SmartStore.Admin.Models.Blogs; using SmartStore.Admin.Models.Catalog; @@ -147,17 +148,20 @@ public void Execute() .ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore()); Mapper.CreateMap(); //queued email - Mapper.CreateMap() - .ForMember(dest => dest.EmailAccountName, mo => mo.MapFrom(src => src.EmailAccount != null ? src.EmailAccount.FriendlyName : string.Empty)) - .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) - .ForMember(dest => dest.SentOn, mo => mo.Ignore()); + Mapper.CreateMap() + .ForMember(dest => dest.EmailAccountName, mo => mo.MapFrom(src => src.EmailAccount != null ? src.EmailAccount.FriendlyName : string.Empty)) + .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) + .ForMember(dest => dest.SentOn, mo => mo.Ignore()) + .ForMember(dest => dest.AttachmentsCount, mo => mo.MapFrom(src => src.Attachments.Count)) + .ForMember(dest => dest.Attachments, mo => mo.MapFrom(src => src.Attachments.Select(x => new QueuedEmailModel.QueuedEmailAttachmentModel { Id = x.Id, Name = x.Name, MimeType = x.MimeType } ))); Mapper.CreateMap() .ForMember(dest=> dest.CreatedOnUtc, dt=> dt.Ignore()) .ForMember(dest => dest.SentOnUtc, mo => mo.Ignore()) .ForMember(dest => dest.EmailAccount, mo => mo.Ignore()) .ForMember(dest => dest.EmailAccountId, mo => mo.Ignore()) .ForMember(dest => dest.ReplyTo, mo => mo.Ignore()) - .ForMember(dest => dest.ReplyToName, mo => mo.Ignore()); + .ForMember(dest => dest.ReplyToName, mo => mo.Ignore()) + .ForMember(dest => dest.Attachments, mo => mo.Ignore()); //campaign Mapper.CreateMap() .ForMember(dest => dest.CreatedOn, mo => mo.Ignore()) diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Messages/QueuedEmailModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Messages/QueuedEmailModel.cs index fd843f7bc6..844e79e388 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Messages/QueuedEmailModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Messages/QueuedEmailModel.cs @@ -1,8 +1,10 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Web.Mvc; using FluentValidation.Attributes; using SmartStore.Admin.Validators.Messages; +using SmartStore.Core.Domain.Messages; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Mvc; @@ -11,7 +13,12 @@ namespace SmartStore.Admin.Models.Messages [Validator(typeof(QueuedEmailValidator))] public class QueuedEmailModel : EntityModelBase { - [SmartResourceDisplayName("Admin.System.QueuedEmails.Fields.Id")] + public QueuedEmailModel() + { + this.Attachments = new List(); + } + + [SmartResourceDisplayName("Admin.System.QueuedEmails.Fields.Id")] public override int Id { get; set; } [SmartResourceDisplayName("Admin.System.QueuedEmails.Fields.Priority")] @@ -65,5 +72,16 @@ public class QueuedEmailModel : EntityModelBase [SmartResourceDisplayName("Admin.System.QueuedEmails.Fields.SendManually")] public bool SendManually { get; set; } + + public int AttachmentsCount { get; set; } + + [SmartResourceDisplayName("Admin.System.QueuedEmails.Fields.Attachments")] + public ICollection Attachments { get; set; } + + public class QueuedEmailAttachmentModel : EntityModelBase + { + public string Name { get; set; } + public string MimeType { get; set; } + } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Settings/GeneralCommonSettingsModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Settings/GeneralCommonSettingsModel.cs index 5605695ad8..da408da1f3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Settings/GeneralCommonSettingsModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Settings/GeneralCommonSettingsModel.cs @@ -153,6 +153,12 @@ public partial class PdfSettingsModel [SmartResourceDisplayName("Admin.Configuration.Settings.GeneralCommon.PdfLogo")] [UIHint("Picture")] public int LogoPictureId { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Settings.GeneralCommon.AttachOrderPdfToOrderPlacedEmail")] + public bool AttachOrderPdfToOrderPlacedEmail { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Settings.GeneralCommon.AttachOrderPdfToOrderCompletedEmail")] + public bool AttachOrderPdfToOrderCompletedEmail { get; set; } } public partial class LocalizationSettingsModel diff --git a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml index d4497b7a7a..ad1a0f5350 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml @@ -119,15 +119,16 @@ .HtmlAttributes(new { style = "text-align:center" }) .HeaderHtmlAttributes(new { style = "text-align:center" }); columns.Bound(x => x.Id) - .Template(x => Html.ActionLink(x.Id.ToString(), "Edit", new { id = x.Id })) .ClientTemplate("\"><#= Id #>"); + columns.Bound(x => x.AttachmentsCount) + .HeaderTemplate("") + .Width(20); columns.Bound(x => x.Subject); columns.Bound(x => x.Priority) .Centered(); - columns.Bound(x => x.From); - columns.Bound(x => x.FromName); + columns.Bound(x => x.From) + .ClientTemplate("<#= FromName #> (<#= From #>)"); columns.Bound(x => x.SendManually) - .Template(item => @Html.SymbolForBool(item.SendManually)) .ClientTemplate(@Html.SymbolForBool("SendManually")) .Centered(); columns.Bound(x => x.SentTries) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/_CreateOrUpdate.cshtml index f297897a7a..b1720f9b11 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/_CreateOrUpdate.cshtml @@ -79,6 +79,23 @@ @Html.ValidationMessageFor(model => model.Subject) + @if (Model.Attachments.Any()) + { + + + @Html.SmartLabelFor(model => model.Attachments) + + + @foreach (var attach in Model.Attachments) + { + + + @attach.Name + + } + + + } @Html.SmartLabelFor(model => model.Body) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml index 76180000af..a10cd45bd9 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml @@ -359,6 +359,29 @@ @Html.ValidationMessageFor(model => model.PdfSettings.LogoPictureId) + + +
+ + + + + @Html.SmartLabelFor(model => model.PdfSettings.AttachOrderPdfToOrderPlacedEmail) + + + @Html.SettingEditorFor(model => model.PdfSettings.AttachOrderPdfToOrderPlacedEmail) + @Html.ValidationMessageFor(model => model.PdfSettings.AttachOrderPdfToOrderPlacedEmail) + + + + + @Html.SmartLabelFor(model => model.PdfSettings.AttachOrderPdfToOrderCompletedEmail) + + + @Html.SettingEditorFor(model => model.PdfSettings.AttachOrderPdfToOrderCompletedEmail) + @Html.ValidationMessageFor(model => model.PdfSettings.AttachOrderPdfToOrderCompletedEmail) + + } @helper TabLocalizationSettings() diff --git a/src/Tests/SmartStore.Services.Tests/Messages/QueuedEmailServiceTests.cs b/src/Tests/SmartStore.Services.Tests/Messages/QueuedEmailServiceTests.cs index 7f0ea69976..39991dda91 100644 --- a/src/Tests/SmartStore.Services.Tests/Messages/QueuedEmailServiceTests.cs +++ b/src/Tests/SmartStore.Services.Tests/Messages/QueuedEmailServiceTests.cs @@ -21,6 +21,7 @@ namespace SmartStore.Services.Tests.Messages public class QueuedEmailServiceTests : ServiceTest { IRepository _qeRepository; + IRepository _qeaRepository; IEmailSender _emailSender; ICommonServices _commonServices; QueuedEmailService _queuedEmailService; @@ -29,10 +30,11 @@ public class QueuedEmailServiceTests : ServiceTest public new void SetUp() { _qeRepository = MockRepository.GenerateStub>(); + _qeaRepository = MockRepository.GenerateStub>(); _emailSender = MockRepository.GenerateStub(); _commonServices = MockRepository.GenerateStub(); - _queuedEmailService = new QueuedEmailService(_qeRepository, _emailSender, _commonServices); + _queuedEmailService = new QueuedEmailService(_qeRepository, _qeaRepository, _emailSender, _commonServices); } [Test] From 3d4bbe00fd43def2d5d7b0d47721471a15f35432 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 6 Jul 2015 17:53:55 +0200 Subject: [PATCH 0216/1256] Added customizable css file to mobile themes & Minor UI fix for mobile light theme --- src/Presentation/SmartStore.Web/SmartStore.Web.csproj | 1 + .../SmartStore.Web/Themes/Mobile/Content/user.css | 6 ++++++ .../Themes/Mobile/Views/Shared/Head.Mobile.cshtml | 2 +- .../SmartStore.Web/Themes/MobileLight/Content/user.css | 10 ++++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/Presentation/SmartStore.Web/Themes/Mobile/Content/user.css create mode 100644 src/Presentation/SmartStore.Web/Themes/MobileLight/Content/user.css diff --git a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj index e4db2c4359..fa9ed189b2 100644 --- a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj +++ b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj @@ -1596,6 +1596,7 @@ + diff --git a/src/Presentation/SmartStore.Web/Themes/Mobile/Content/user.css b/src/Presentation/SmartStore.Web/Themes/Mobile/Content/user.css new file mode 100644 index 0000000000..dac21231b8 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Themes/Mobile/Content/user.css @@ -0,0 +1,6 @@ +// +// Customize the (child) theme here with css overrides +// or new selectors (for users) +// -------------------------------------------------- + + diff --git a/src/Presentation/SmartStore.Web/Themes/Mobile/Views/Shared/Head.Mobile.cshtml b/src/Presentation/SmartStore.Web/Themes/Mobile/Views/Shared/Head.Mobile.cshtml index 31e743b55d..fd125c4cef 100644 --- a/src/Presentation/SmartStore.Web/Themes/Mobile/Views/Shared/Head.Mobile.cshtml +++ b/src/Presentation/SmartStore.Web/Themes/Mobile/Views/Shared/Head.Mobile.cshtml @@ -2,5 +2,5 @@ Html.AppendCssFileParts( "~/Themes/Mobile/Content/jquery.mobile.structure-1.3.2.css", "~/Themes/Mobile/Content/jquery.mobile.theme-1.3.2.css"); - Html.AppendCssFileParts("~/Themes/Mobile/Content/styles.css"); + Html.AppendCssFileParts("~/Themes/Mobile/Content/styles.css", "~/Themes/Mobile/Content/user.css"); } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Themes/MobileLight/Content/user.css b/src/Presentation/SmartStore.Web/Themes/MobileLight/Content/user.css new file mode 100644 index 0000000000..cffe7dcfd7 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Themes/MobileLight/Content/user.css @@ -0,0 +1,10 @@ +/* +// Customize the (child) theme here with css overrides +// or new selectors (for users) +// -------------------------------------------------- +*/ + +.legal-hints { + background: none !important; + border-bottom: 1px solid #aaa !important; +} \ No newline at end of file From 8e3e00191a6b72a14f3fac9df6d1c66663c54b4d Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Mon, 6 Jul 2015 18:00:43 +0200 Subject: [PATCH 0217/1256] Minor WebApi fixes --- .../WebApi/WebApiEntityController.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs index 4bec2890bf..039d981db0 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs @@ -91,15 +91,15 @@ protected virtual internal HttpResponseMessage UnmappedGetProperty(TEntity entit return Request.CreateErrorResponse(HttpStatusCode.BadRequest, WebApiGlobal.Error.PropertyNotFound.FormatWith(propertyName)); } - protected virtual IRepository CreateRepository() - { - var repository = EngineContext.Current.Resolve>(); + //protected virtual IRepository CreateRepository() + //{ + // var repository = EngineContext.Current.Resolve>(); - // false means not resolving navigation properties (related entities) - repository.Context.ProxyCreationEnabled = false; + // // false means not resolving navigation properties (related entities) + // repository.Context.ProxyCreationEnabled = false; - return repository; - } + // return repository; + //} /// /// Auto injected by Autofac @@ -163,7 +163,7 @@ protected override TEntity GetEntityByKey(int key) if (!ModelState.IsValid) throw this.ExceptionInvalidModelState(); - return GetEntitySet().FirstOrDefault(x => x.Id == key); + return this.Repository.GetById(key); } protected internal virtual TEntity GetEntityByKeyNotNull(int key) From ddb5bfb8e60b66d03b3e5a539b89414c3a12e38c Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 7 Jul 2015 01:50:38 +0200 Subject: [PATCH 0218/1256] E-mail attachments: finalized queued email attachments. Next step: message template attachments. --- .../Data/RepositoryExtensions.cs | 46 ++++++++++- .../201506262044329_QueuedEmailAttachments.cs | 82 +++++++++++++++++-- .../Setup/SeedData/InvariantSeedData.cs | 8 ++ .../Messages/QueuedEmailService.cs | 4 +- .../Messages/QueuedMessagesClearTask.cs | 28 +++++++ .../Messages/QueuingEmailEventConsumer.cs | 49 ++++++----- .../SmartStore.Services.csproj | 1 + .../Controllers/QueuedEmailController.cs | 2 +- .../Views/QueuedEmail/List.cshtml | 9 +- .../Controllers/OrderController.cs | 3 +- .../Installation/DeDESeedData.cs | 4 + 11 files changed, 189 insertions(+), 47 deletions(-) create mode 100644 src/Libraries/SmartStore.Services/Messages/QueuedMessagesClearTask.cs diff --git a/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs b/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs index 8551dd2882..0685c1a477 100644 --- a/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs +++ b/src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs @@ -52,15 +52,16 @@ public static void Delete(this IRepository rs, object id) where T : BaseEn } /// - /// Truncates the whole table + /// Truncates the table /// /// Entity type - /// + /// The repository + /// An optional filter /// The total number of affected entities /// /// This method turns off auto detection, validation and hooking. /// - public static int DeleteAll(this IRepository rs) where T : BaseEntity + public static int DeleteAll(this IRepository rs, Expression> predicate = null) where T : BaseEntity { var autoCommit = rs.AutoCommitEnabled; rs.AutoCommitEnabled = false; @@ -71,7 +72,13 @@ public static int DeleteAll(this IRepository rs) where T : BaseEntity { using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, hooksEnabled: false)) { - var records = rs.Table.ToList(); + var query = rs.Table; + if (predicate != null) + { + query = query.Where(predicate); + } + + var records = query.ToList(); foreach (var chunk in records.Chunk(500)) { rs.DeleteRange(chunk.ToList()); @@ -91,6 +98,37 @@ public static int DeleteAll(this IRepository rs) where T : BaseEntity return count; } + private static int DeleteAllInternal(IRepository rs, Expression> predicate) where T : BaseEntity + { + var autoCommit = rs.AutoCommitEnabled; + rs.AutoCommitEnabled = false; + + var count = 0; + + try + { + using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, hooksEnabled: false)) + { + var records = rs.Table.ToList(); + foreach (var chunk in records.Chunk(500)) + { + rs.DeleteRange(chunk.ToList()); + count += rs.Context.SaveChanges(); + } + } + } + catch (Exception ex) + { + throw ex; + } + finally + { + rs.AutoCommitEnabled = autoCommit; + } + + return count; + } + public static IQueryable Get( this IRepository rs, Expression> predicate = null, diff --git a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs index 18c4da66ae..225aaf9d43 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs @@ -1,9 +1,11 @@ namespace SmartStore.Data.Migrations { - using System; - using System.Data.Entity.Migrations; - - public partial class QueuedEmailAttachments : DbMigration + using System; + using System.Data.Entity.Migrations; + using SmartStore.Core.Domain.Tasks; + using SmartStore.Data.Setup; + + public partial class QueuedEmailAttachments : DbMigration, ILocaleResourcesProvider, IDataSeeder { public override void Up() { @@ -24,8 +26,7 @@ public override void Up() .ForeignKey("dbo.Download", t => t.FileId, cascadeDelete: true) .ForeignKey("dbo.QueuedEmail", t => t.QueuedEmailId, cascadeDelete: true) .Index(t => t.QueuedEmailId) - .Index(t => t.FileId); - + .Index(t => t.FileId); } public override void Down() @@ -36,5 +37,72 @@ public override void Down() DropIndex("dbo.QueuedEmailAttachment", new[] { "QueuedEmailId" }); DropTable("dbo.QueuedEmailAttachment"); } - } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + + context.Set().AddOrUpdate(x => x.Type, + new ScheduleTask + { + Name = "Clear email queue", + Seconds = 86400, // 1 day + Type = "SmartStore.Services.Messages.QueuedMessagesClearTask, SmartStore.Services", + Enabled = true, + StopOnError = false, + } + ); + + context.SaveChanges(); + } + + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Admin.Configuration.Settings.GeneralCommon.AttachOrderPdfToOrderPlacedEmail", + "Attach order PDF to 'Order Placed' email", + "Bei Bestelleingang PDF mitsenden", + "Dynamically creates and attaches the order PDF to the 'Order Placed' customer notification email.", + "Erstellt bei Bestelleingang das Auftrags-PDF-Dokument und hngt es der Kunden-Benachrichtigungs-Email an"); + + builder.AddOrUpdate("Admin.Configuration.Settings.GeneralCommon.AttachOrderPdfToOrderCompletedEmail", + "Attach order PDF to 'Order Completed' email", + "Bei Abschluss einer Bestellung PDF mitsenden", + "Dynamically creates and attaches the order PDF to the 'Order Completed' customer notification email.", + "Erstellt bei Abschluss einer Bestellung das Auftrags-PDF-Dokument und hngt es der Kunden-Benachrichtigungs-Email an"); + + builder.AddOrUpdate("Admin.System.QueuedEmails.Fields.Attachments", + "Attachments", + "Anhnge"); + + builder.AddOrUpdate("Admin.System.QueuedEmails.CouldNotDownloadAttachment", + "Could not download e-mail attachment: no data.", + "E-Mail Anhang konnte nicht herunterladen: Daten nicht verfgbar."); + + builder.AddOrUpdate("Admin.System.QueuedEmails.ErrorCreatingAttachment", + "An error occured while creating e-mail attachment", + "Whrend der Erstellung des E-Mail-Anhangs ist ein Fehler aufgetreten"); + + builder.AddOrUpdate("Admin.System.QueuedEmails.ErrorEmptyAttachmentResult", + "The e-mail attachment data could not be downloaded from path '{0}'", + "Daten fr den E-Mail Anhang konnten nicht heruntergeladen werden. Pfad: {0}"); + + builder.AddOrUpdate("Admin.System.QueuedEmails.ErrorNoPdfAttachment", + "The content type of the e-mail attachment must be 'application/pdf'", + "Der Inhaltstyp des E-Mail Anhangs muss 'application/pdf' sein"); + + builder.AddOrUpdate("Admin.System.QueuedEmails.List.AttachmentsCount", + "Number of attachments", + "Anzahl Anhnge"); + + builder.AddOrUpdate("Order.PdfInvoiceFileName", + "order-{0}.pdf", + "bestellung-{0}.pdf"); + } + } } diff --git a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs index d6f664d19d..ab25464ca0 100644 --- a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs +++ b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs @@ -4812,6 +4812,14 @@ public IList ScheduleTasks() Enabled = true, StopOnError = false, }, + new ScheduleTask + { + Name = "Clear email queue", + Seconds = 86400, // 1 day + Type = "SmartStore.Services.Messages.QueuedMessagesClearTask, SmartStore.Services", + Enabled = true, + StopOnError = false, + }, }; this.Alter(entities); return entities; diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs index 8a742c99e6..68cf11d375 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Net.Mail; using System.IO; using SmartStore.Core; @@ -76,7 +77,8 @@ public virtual void DeleteQueuedEmail(QueuedEmail queuedEmail) public virtual int DeleteAllQueuedEmails() { - return _queuedEmailRepository.DeleteAll(); + // do not delete e-mails which are about to be sent + return _queuedEmailRepository.DeleteAll(x => x.SentOnUtc.HasValue || x.SentTries >= 3); } public virtual QueuedEmail GetQueuedEmailById(int queuedEmailId) diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesClearTask.cs b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesClearTask.cs new file mode 100644 index 0000000000..a51b84a925 --- /dev/null +++ b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesClearTask.cs @@ -0,0 +1,28 @@ +using System; +using System.Linq; +using System.Linq.Expressions; +using SmartStore.Core.Data; +using SmartStore.Core.Domain.Messages; +using SmartStore.Services.Tasks; + +namespace SmartStore.Services.Messages +{ + /// + /// Represents a task for deleting sent emails from the message queue + /// + public partial class QueuedMessagesClearTask : ITask + { + private readonly IRepository _qeRepository; + + public QueuedMessagesClearTask(IRepository qeRepository) + { + this._qeRepository = qeRepository; + } + + public void Execute(TaskExecutionContext ctx) + { + var olderThan = DateTime.UtcNow.AddDays(-14); + _qeRepository.DeleteAll(x => x.SentOnUtc.HasValue && x.CreatedOnUtc < olderThan); + } + } +} diff --git a/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs b/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs index dd50b40c44..11eca682cc 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuingEmailEventConsumer.cs @@ -12,6 +12,7 @@ using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Messages; using SmartStore.Core.Events; +using SmartStore.Core.Localization; using SmartStore.Core.Logging; using SmartStore.Utilities; @@ -33,9 +34,11 @@ public QueuingEmailEventConsumer( this._fileDownloadManager = fileDownloadManager; Logger = NullLogger.Instance; + T = NullLocalizer.Instance; } public ILogger Logger { get; set; } + public Localizer T { get; set; } public void HandleEvent(QueuingEmailEvent eventMessage) { @@ -52,11 +55,15 @@ public void HandleEvent(QueuingEmailEvent eventMessage) if (handledTemplates.TryGetValue(tpl.Name, out shouldHandle) && shouldHandle) { var orderId = eventMessage.Tokens.First(x => x.Key.IsCaseInsensitiveEqual("Order.ID")).Value.ToInt(); - var qea = CreatePdfInvoiceAttachment(orderId); - if (qea != null) + try { + var qea = CreatePdfInvoiceAttachment(orderId); qe.Attachments.Add(qea); } + catch (Exception ex) + { + Logger.Error(T("Admin.System.QueuedEmails.ErrorCreatingAttachment"), ex); + } } } @@ -65,35 +72,25 @@ private QueuedEmailAttachment CreatePdfInvoiceAttachment(int orderId) var urlHelper = new UrlHelper(_httpRequest.RequestContext); var path = urlHelper.Action("Print", "Order", new { id = orderId, pdf = true, area = "" }); - try - { - var fileResponse = _fileDownloadManager.Value.DownloadFile(path, true, 5000); - - if (fileResponse == null) - { - // ... - } - - if (!fileResponse.ContentType.IsCaseInsensitiveEqual("application/pdf")) - { - // ... - } + var fileResponse = _fileDownloadManager.Value.DownloadFile(path, true, 5000); - return new QueuedEmailAttachment - { - StorageLocation = EmailAttachmentStorageLocation.Blob, - Data = fileResponse.Data, - MimeType = fileResponse.ContentType, - Name = fileResponse.FileName - }; + if (fileResponse == null) + { + throw new InvalidOperationException(T("Admin.System.QueuedEmails.ErrorEmptyAttachmentResult", path)); } - catch (Exception ex) + + if (!fileResponse.ContentType.IsCaseInsensitiveEqual("application/pdf")) { - // TODO localize - Logger.Error("Error occured while creating e-mail attachment", ex); + throw new InvalidOperationException(T("Admin.System.QueuedEmails.ErrorNoPdfAttachment")); } - return null; + return new QueuedEmailAttachment + { + StorageLocation = EmailAttachmentStorageLocation.Blob, + Data = fileResponse.Data, + MimeType = fileResponse.ContentType, + Name = fileResponse.FileName + }; } } diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index d479dda36e..8c64d2273a 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -161,6 +161,7 @@ + diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs index d00783f2cf..115d2b1beb 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/QueuedEmailController.cs @@ -280,7 +280,7 @@ public ActionResult DownloadAttachment(int id) return RedirectToAction("DownloadFile", "Download", new { downloadId = qea.FileId.Value }); } - NotifyError("Could not download e-mail attachment: no data"); + NotifyError(T("Admin.System.QueuedEmails.CouldNotDownloadAttachment")); return RedirectToAction("List"); } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml index ad1a0f5350..44c2fe7f1e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/QueuedEmail/List.cshtml @@ -67,12 +67,7 @@ @Html.SmartLabelFor(model => model.SearchSendManually) - @Html.DropDownList("SearchSendManually", new List - { - new SelectListItem { Text = T("Common.Unspecified"), Value = "", Selected = !Model.SearchSendManually.HasValue }, - new SelectListItem { Text = T("Admin.Common.Yes"), Value = "true", Selected = Model.SearchSendManually ?? false }, - new SelectListItem { Text = T("Admin.Common.No"), Value = "false", Selected = !Model.SearchSendManually ?? false } - }) + @Html.EditorFor(model => Model.SearchSendManually) @@ -121,7 +116,7 @@ columns.Bound(x => x.Id) .ClientTemplate("\"><#= Id #>"); columns.Bound(x => x.AttachmentsCount) - .HeaderTemplate("") + .HeaderTemplate(@) .Width(20); columns.Bound(x => x.Subject); columns.Bound(x => x.Priority) diff --git a/src/Presentation/SmartStore.Web/Controllers/OrderController.cs b/src/Presentation/SmartStore.Web/Controllers/OrderController.cs index 70ba4ddab4..bf25af3aaa 100644 --- a/src/Presentation/SmartStore.Web/Controllers/OrderController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/OrderController.cs @@ -514,8 +514,9 @@ public ActionResult Print(int id, bool pdf = false) return new HttpUnauthorizedResult(); var model = PrepareOrderDetailsModel(order); + var fileName = T("Order.PdfInvoiceFileName", order.Id); - return PrintCore(new List { model }, pdf, "order-{0}.pdf".FormatWith(order.Id)); + return PrintCore(new List { model }, pdf, fileName); } [AdminAuthorize] diff --git a/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs b/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs index 54df8e0005..cd7ddaf22c 100644 --- a/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs +++ b/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs @@ -2530,6 +2530,10 @@ protected override void Alter(IList entities) { x.Name = "E-Mail senden"; }) + .Alter("Clear email queue", x => + { + x.Name = "E-Mail Queue bereinigen"; + }) .Alter("Keep alive", x => { x.Name = "Keep alive"; From 86f4a446d6f69a44940e532453f2cd74dadcb452 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 7 Jul 2015 11:02:00 +0200 Subject: [PATCH 0219/1256] Bug fix: GetPreselectedPrice should not leave product with merged values. Feeds would export mixed up product values here. --- .../Catalog/PriceCalculationService.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index e7d0550cde..4a7ea62463 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -163,6 +163,7 @@ protected virtual decimal GetPreselectedPrice(Product product, ProductBundleItem var bundleItemId = (bundleItem == null ? 0 : bundleItem.Item.Id); var attributes = (isBundle ? new List() : _productAttributeService.GetProductVariantAttributesByProductId(product.Id)); var selectedAttributes = new NameValueCollection(); + var clearDataMerging = false; List selectedAttributeValues = null; foreach (var attribute in attributes) @@ -222,7 +223,10 @@ protected virtual decimal GetPreselectedPrice(Product product, ProductBundleItem var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml)); if (selectedCombination != null && selectedCombination.IsActive) + { + clearDataMerging = true; product.MergeWithCombination(selectedCombination); + } } if (_catalogSettings.EnableDynamicPriceUpdate && !isBundlePricing) @@ -243,6 +247,13 @@ protected virtual decimal GetPreselectedPrice(Product product, ProductBundleItem } var result = GetFinalPrice(product, bundleItems, _commonServices.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem); + + if (clearDataMerging && product.MergedDataValues != null) + { + // GetPreselectedPrice should not leave product with merged values. + product.MergedDataValues.Clear(); + } + return result; } From 81aa3b935d2721257d917565fcac48359b56129e Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 8 Jul 2015 00:31:52 +0200 Subject: [PATCH 0220/1256] E-mail attachments: added attachment support to message templates. Next step: proper UI (upload files) --- .../Domain/Messages/MessageTemplate.cs | 16 +++ ...058_MessageTemplateAttachments.Designer.cs | 29 ++++ ...507072138058_MessageTemplateAttachments.cs | 22 +++ ...7072138058_MessageTemplateAttachments.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 7 + .../Media/DownloadService.cs | 60 +++------ .../Media/IDownloadService.cs | 8 ++ .../Messages/MessageTemplateService.cs | 16 ++- .../Messages/WorkflowMessageService.cs | 108 +++++++++------ .../Controllers/MessageTemplateController.cs | 48 +++---- .../Models/Messages/MessageTemplateModel.cs | 18 +++ .../MessageTemplate/_CreateOrUpdate.cshtml | 59 +++++++- .../Shared/EditorTemplates/Download.cshtml | 1 + 13 files changed, 405 insertions(+), 113 deletions(-) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.resx diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/MessageTemplate.cs b/src/Libraries/SmartStore.Core/Domain/Messages/MessageTemplate.cs index 282fc0407d..75f66564ae 100644 --- a/src/Libraries/SmartStore.Core/Domain/Messages/MessageTemplate.cs +++ b/src/Libraries/SmartStore.Core/Domain/Messages/MessageTemplate.cs @@ -1,4 +1,5 @@ using SmartStore.Core.Domain.Localization; +using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Stores; namespace SmartStore.Core.Domain.Messages @@ -47,5 +48,20 @@ public partial class MessageTemplate : BaseEntity, ILocalizedEntity, IStoreMappi /// Gets or sets a value indicating whether emails derived from the template are only send manually /// public bool SendManually { get; set; } + + /// + /// Gets or sets the attachment 1 file identifier + /// + public int? Attachment1FileId { get; set; } + + /// + /// Gets or sets the attachment 2 file identifier + /// + public int? Attachment2FileId { get; set; } + + /// + /// Gets or sets the attachment 3 file identifier + /// + public int? Attachment3FileId { get; set; } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.Designer.cs new file mode 100644 index 0000000000..cb29f9e05f --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class MessageTemplateAttachments : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(MessageTemplateAttachments)); + + string IMigrationMetadata.Id + { + get { return "201507072138058_MessageTemplateAttachments"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs b/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs new file mode 100644 index 0000000000..0a48be7f37 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs @@ -0,0 +1,22 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class MessageTemplateAttachments : DbMigration + { + public override void Up() + { + AddColumn("dbo.MessageTemplate", "Attachment1FileId", c => c.Int()); + AddColumn("dbo.MessageTemplate", "Attachment2FileId", c => c.Int()); + AddColumn("dbo.MessageTemplate", "Attachment3FileId", c => c.Int()); + } + + public override void Down() + { + DropColumn("dbo.MessageTemplate", "Attachment3FileId"); + DropColumn("dbo.MessageTemplate", "Attachment2FileId"); + DropColumn("dbo.MessageTemplate", "Attachment1FileId"); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.resx b/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.resx new file mode 100644 index 0000000000..3970382b24 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index c34ecbb4e8..0cdc69b343 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -286,6 +286,10 @@ 201506262044329_QueuedEmailAttachments.cs + + + 201507072138058_MessageTemplateAttachments.cs + @@ -552,6 +556,9 @@ 201506262044329_QueuedEmailAttachments.cs + + 201507072138058_MessageTemplateAttachments.cs + diff --git a/src/Libraries/SmartStore.Services/Media/DownloadService.cs b/src/Libraries/SmartStore.Services/Media/DownloadService.cs index 71117a3bcd..25d9bc9b2c 100644 --- a/src/Libraries/SmartStore.Services/Media/DownloadService.cs +++ b/src/Libraries/SmartStore.Services/Media/DownloadService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using SmartStore.Core.Data; using SmartStore.Core.Domain.Catalog; @@ -23,13 +24,7 @@ public partial class DownloadService : IDownloadService #region Ctor - /// - /// Ctor - /// - /// Download repository - /// - public DownloadService(IRepository downloadRepository, - IEventPublisher eventPubisher) + public DownloadService(IRepository downloadRepository, IEventPublisher eventPubisher) { _downloadRepository = downloadRepository; _eventPubisher = eventPubisher; @@ -39,11 +34,6 @@ public DownloadService(IRepository downloadRepository, #region Methods - /// - /// Gets a download - /// - /// Download identifier - /// Download public virtual Download GetDownloadById(int downloadId) { if (downloadId == 0) @@ -53,11 +43,25 @@ public virtual Download GetDownloadById(int downloadId) return download; } - /// - /// Gets a download by GUID - /// - /// Download GUID - /// Download + public virtual IList GetDownloadsByIds(int[] downloadIds) + { + if (downloadIds == null || downloadIds.Length == 0) + return new List(); + + var query = from dl in _downloadRepository.Table + where downloadIds.Contains(dl.Id) + select dl; + + var downloads = query.ToList(); + + // sort by passed identifier sequence + var sortQuery = from i in downloadIds + join d in downloads on i equals d.Id + select d; + + return sortQuery.ToList(); + } + public virtual Download GetDownloadByGuid(Guid downloadGuid) { if (downloadGuid == Guid.Empty) @@ -70,10 +74,6 @@ public virtual Download GetDownloadByGuid(Guid downloadGuid) return order; } - /// - /// Deletes a download - /// - /// Download public virtual void DeleteDownload(Download download) { if (download == null) @@ -84,10 +84,6 @@ public virtual void DeleteDownload(Download download) _eventPubisher.EntityDeleted(download); } - /// - /// Inserts a download - /// - /// Download public virtual void InsertDownload(Download download) { if (download == null) @@ -98,10 +94,6 @@ public virtual void InsertDownload(Download download) _eventPubisher.EntityInserted(download); } - /// - /// Updates the download - /// - /// Download public virtual void UpdateDownload(Download download) { if (download == null) @@ -112,11 +104,6 @@ public virtual void UpdateDownload(Download download) _eventPubisher.EntityUpdated(download); } - /// - /// Gets a value indicating whether download is allowed - /// - /// Order item to check - /// True if download is allowed; otherwise, false. public virtual bool IsDownloadAllowed(OrderItem orderItem) { if (orderItem == null) @@ -182,11 +169,6 @@ public virtual bool IsDownloadAllowed(OrderItem orderItem) return false; } - /// - /// Gets a value indicating whether license download is allowed - /// - /// Order item to check - /// True if license download is allowed; otherwise, false. public virtual bool IsLicenseDownloadAllowed(OrderItem orderItem) { if (orderItem == null) diff --git a/src/Libraries/SmartStore.Services/Media/IDownloadService.cs b/src/Libraries/SmartStore.Services/Media/IDownloadService.cs index 73afed9a32..70282f56a4 100644 --- a/src/Libraries/SmartStore.Services/Media/IDownloadService.cs +++ b/src/Libraries/SmartStore.Services/Media/IDownloadService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Orders; @@ -16,6 +17,13 @@ public partial interface IDownloadService /// Download Download GetDownloadById(int downloadId); + /// + /// Gets downloads by identifiers + /// + /// Download identifiers + /// List of download entities + IList GetDownloadsByIds(int[] downloadIds); + /// /// Gets a download by GUID /// diff --git a/src/Libraries/SmartStore.Services/Messages/MessageTemplateService.cs b/src/Libraries/SmartStore.Services/Messages/MessageTemplateService.cs index 92ae48a637..65d8fe735c 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageTemplateService.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageTemplateService.cs @@ -45,7 +45,8 @@ public partial class MessageTemplateService: IMessageTemplateService /// Store mapping service /// Message template repository /// Event published - public MessageTemplateService(ICacheManager cacheManager, + public MessageTemplateService( + ICacheManager cacheManager, IRepository storeMappingRepository, ILanguageService languageService, ILocalizedEntityService localizedEntityService, @@ -209,7 +210,7 @@ public virtual MessageTemplate CopyMessageTemplate(MessageTemplate messageTempla if (messageTemplate == null) throw new ArgumentNullException("messageTemplate"); - var mtCopy = new MessageTemplate() + var mtCopy = new MessageTemplate { Name = messageTemplate.Name, BccEmailAddresses = messageTemplate.BccEmailAddresses, @@ -218,25 +219,26 @@ public virtual MessageTemplate CopyMessageTemplate(MessageTemplate messageTempla IsActive = messageTemplate.IsActive, EmailAccountId = messageTemplate.EmailAccountId, LimitedToStores = messageTemplate.LimitedToStores + // INFO: we do not copy attachments }; InsertMessageTemplate(mtCopy); var languages = _languageService.GetAllLanguages(true); - //localization + // localization foreach (var lang in languages) { var bccEmailAddresses = messageTemplate.GetLocalized(x => x.BccEmailAddresses, lang.Id, false, false); - if (!String.IsNullOrEmpty(bccEmailAddresses)) + if (bccEmailAddresses.HasValue()) _localizedEntityService.SaveLocalizedValue(mtCopy, x => x.BccEmailAddresses, bccEmailAddresses, lang.Id); var subject = messageTemplate.GetLocalized(x => x.Subject, lang.Id, false, false); - if (!String.IsNullOrEmpty(subject)) + if (subject.HasValue()) _localizedEntityService.SaveLocalizedValue(mtCopy, x => x.Subject, subject, lang.Id); var body = messageTemplate.GetLocalized(x => x.Body, lang.Id, false, false); - if (!String.IsNullOrEmpty(body)) + if (body.HasValue()) _localizedEntityService.SaveLocalizedValue(mtCopy, x => x.Body, subject, lang.Id); var emailAccountId = messageTemplate.GetLocalized(x => x.EmailAccountId, lang.Id, false, false); @@ -244,7 +246,7 @@ public virtual MessageTemplate CopyMessageTemplate(MessageTemplate messageTempla _localizedEntityService.SaveLocalizedValue(mtCopy, x => x.EmailAccountId, emailAccountId, lang.Id); } - //store mapping + // store mapping var selectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(messageTemplate); foreach (var id in selectedStoreIds) { diff --git a/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs b/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs index 57efae24d2..64adb4aa26 100644 --- a/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs +++ b/src/Libraries/SmartStore.Services/Messages/WorkflowMessageService.cs @@ -16,6 +16,7 @@ using SmartStore.Core.Events; using SmartStore.Services.Customers; using SmartStore.Services.Localization; +using SmartStore.Services.Media; using SmartStore.Services.Stores; namespace SmartStore.Services.Messages @@ -36,21 +37,26 @@ public partial class WorkflowMessageService : IWorkflowMessageService private readonly IEventPublisher _eventPublisher; private readonly IWorkContext _workContext; private readonly HttpRequestBase _httpRequest; + private readonly IDownloadService _downloadServioce; #endregion #region Ctor - public WorkflowMessageService(IMessageTemplateService messageTemplateService, - IQueuedEmailService queuedEmailService, ILanguageService languageService, - ITokenizer tokenizer, IEmailAccountService emailAccountService, + public WorkflowMessageService( + IMessageTemplateService messageTemplateService, + IQueuedEmailService queuedEmailService, + ILanguageService languageService, + ITokenizer tokenizer, + IEmailAccountService emailAccountService, IMessageTokenProvider messageTokenProvider, IStoreService storeService, IStoreContext storeContext, EmailAccountSettings emailAccountSettings, IEventPublisher eventPublisher, IWorkContext workContext, - HttpRequestBase httpRequest) + HttpRequestBase httpRequest, + IDownloadService downloadServioce) { this._messageTemplateService = messageTemplateService; this._queuedEmailService = queuedEmailService; @@ -63,7 +69,8 @@ public WorkflowMessageService(IMessageTemplateService messageTemplateService, this._emailAccountSettings = emailAccountSettings; this._eventPublisher = eventPublisher; this._workContext = workContext; - _httpRequest = httpRequest; + this._httpRequest = httpRequest; + this._downloadServioce = downloadServioce; } #endregion @@ -109,6 +116,33 @@ protected int SendNotification( SendManually = messageTemplate.SendManually }; + // create attachments if any + var fileIds = (new int?[] + { + messageTemplate.GetLocalized(x => x.Attachment1FileId, languageId), + messageTemplate.GetLocalized(x => x.Attachment2FileId, languageId), + messageTemplate.GetLocalized(x => x.Attachment3FileId, languageId) + }) + .Where(x => x.HasValue) + .Select(x => x.Value) + .ToArray(); + + if (fileIds.Any()) + { + var files = _downloadServioce.GetDownloadsByIds(fileIds); + foreach (var file in files) + { + email.Attachments.Add(new QueuedEmailAttachment + { + StorageLocation = EmailAttachmentStorageLocation.FileReference, + FileId = file.Id, + Name = (file.Filename.NullEmpty() ?? file.Id.ToString()) + file.Extension.EmptyNull(), + MimeType = file.ContentType.NullEmpty() ?? "application/octet-stream" + }); + } + } + + // publish event so that integrators can add attachments, alter the email etc. _eventPublisher.Publish(new QueuingEmailEvent { @@ -124,12 +158,10 @@ protected int SendNotification( return email.Id; } - protected MessageTemplate GetLocalizedActiveMessageTemplate(string messageTemplateName, int languageId, int storeId) + protected MessageTemplate GetActiveMessageTemplate(string messageTemplateName, int storeId) { - //TODO remove languageId parameter var messageTemplate = _messageTemplateService.GetMessageTemplateByName(messageTemplateName, storeId); - //no template found if (messageTemplate == null) return null; @@ -241,7 +273,7 @@ public virtual int SendCustomerRegisteredNotificationMessage(Customer customer, var store = _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("NewCustomer.Notification", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("NewCustomer.Notification", store.Id); if (messageTemplate == null) return 0; @@ -280,7 +312,7 @@ public virtual int SendCustomerWelcomeMessage(Customer customer, int languageId) var store = _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("Customer.WelcomeMessage", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("Customer.WelcomeMessage", store.Id); if (messageTemplate == null) return 0; @@ -314,7 +346,7 @@ public virtual int SendCustomerEmailValidationMessage(Customer customer, int lan var store = _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("Customer.EmailValidationMessage", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("Customer.EmailValidationMessage", store.Id); if (messageTemplate == null) return 0; @@ -348,7 +380,7 @@ public virtual int SendCustomerPasswordRecoveryMessage(Customer customer, int la var store = _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("Customer.PasswordRecovery", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("Customer.PasswordRecovery", store.Id); if (messageTemplate == null) return 0; @@ -386,7 +418,7 @@ public virtual int SendOrderPlacedStoreOwnerNotification(Order order, int langua var store = _storeService.GetStoreById(order.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("OrderPlaced.StoreOwnerNotification", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("OrderPlaced.StoreOwnerNotification", store.Id); if (messageTemplate == null) return 0; @@ -431,7 +463,7 @@ public virtual int SendOrderPlacedCustomerNotification(Order order, int language var store = _storeService.GetStoreById(order.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("OrderPlaced.CustomerNotification", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("OrderPlaced.CustomerNotification", store.Id); if (messageTemplate == null) return 0; @@ -474,7 +506,7 @@ public virtual int SendShipmentSentCustomerNotification(Shipment shipment, int l var store = _storeService.GetStoreById(order.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("ShipmentSent.CustomerNotification", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("ShipmentSent.CustomerNotification", store.Id); if (messageTemplate == null) return 0; @@ -514,7 +546,7 @@ public virtual int SendShipmentDeliveredCustomerNotification(Shipment shipment, var store = _storeService.GetStoreById(order.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("ShipmentDelivered.CustomerNotification", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("ShipmentDelivered.CustomerNotification", store.Id); if (messageTemplate == null) return 0; @@ -550,7 +582,7 @@ public virtual int SendOrderCompletedCustomerNotification(Order order, int langu var store = _storeService.GetStoreById(order.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("OrderCompleted.CustomerNotification", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("OrderCompleted.CustomerNotification", store.Id); if (messageTemplate == null) return 0; @@ -589,7 +621,7 @@ public virtual int SendOrderCancelledCustomerNotification(Order order, int langu var store = _storeService.GetStoreById(order.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("OrderCancelled.CustomerNotification", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("OrderCancelled.CustomerNotification", store.Id); if (messageTemplate == null) return 0; @@ -626,7 +658,7 @@ public virtual int SendNewOrderNoteAddedCustomerNotification(OrderNote orderNote var store = _storeService.GetStoreById(order.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("Customer.NewOrderNote", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("Customer.NewOrderNote", store.Id); if (messageTemplate == null) return 0; @@ -662,7 +694,7 @@ public virtual int SendRecurringPaymentCancelledStoreOwnerNotification(Recurring var store = _storeService.GetStoreById(recurringPayment.InitialOrder.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("RecurringPaymentCancelled.StoreOwnerNotification", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("RecurringPaymentCancelled.StoreOwnerNotification", store.Id); if (messageTemplate == null) return 0; @@ -704,7 +736,7 @@ public virtual int SendNewsLetterSubscriptionActivationMessage(NewsLetterSubscri var store = _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("NewsLetterSubscription.ActivationMessage", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("NewsLetterSubscription.ActivationMessage", store.Id); if (messageTemplate == null) return 0; @@ -739,7 +771,7 @@ public virtual int SendNewsLetterSubscriptionDeactivationMessage(NewsLetterSubsc var store = _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("NewsLetterSubscription.DeactivationMessage", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("NewsLetterSubscription.DeactivationMessage", store.Id); if (messageTemplate == null) return 0; @@ -784,7 +816,7 @@ public virtual int SendProductEmailAFriendMessage(Customer customer, int languag var store = _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("Service.EmailAFriend", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("Service.EmailAFriend", store.Id); if (messageTemplate == null) return 0; @@ -822,7 +854,7 @@ public virtual int SendProductQuestionMessage(Customer customer, int languageId, var store = _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("Product.AskQuestion", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("Product.AskQuestion", store.Id); if (messageTemplate == null) return 0; @@ -864,7 +896,7 @@ public virtual int SendWishlistEmailAFriendMessage(Customer customer, int langua var store = _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("Wishlist.EmailAFriend", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("Wishlist.EmailAFriend", store.Id); if (messageTemplate == null) return 0; @@ -905,7 +937,7 @@ public virtual int SendNewReturnRequestStoreOwnerNotification(ReturnRequest retu var store = _storeService.GetStoreById(orderItem.Order.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("NewReturnRequest.StoreOwnerNotification", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("NewReturnRequest.StoreOwnerNotification", store.Id); if (messageTemplate == null) return 0; @@ -946,7 +978,7 @@ public virtual int SendReturnRequestStatusChangedCustomerNotification(ReturnRequ var store = _storeService.GetStoreById(orderItem.Order.StoreId) ?? _storeContext.CurrentStore; languageId = EnsureLanguageIsActive(languageId, store.Id); - var messageTemplate = GetLocalizedActiveMessageTemplate("ReturnRequestStatusChanged.CustomerNotification", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("ReturnRequestStatusChanged.CustomerNotification", store.Id); if (messageTemplate == null) return 0; @@ -991,7 +1023,7 @@ public int SendNewForumTopicMessage(Customer customer, var store = _storeContext.CurrentStore; - var messageTemplate = GetLocalizedActiveMessageTemplate("Forums.NewForumTopic", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("Forums.NewForumTopic", store.Id); if (messageTemplate == null) { return 0; @@ -1035,7 +1067,7 @@ public int SendNewForumPostMessage(Customer customer, var store = _storeContext.CurrentStore; - var messageTemplate = GetLocalizedActiveMessageTemplate("Forums.NewForumPost", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("Forums.NewForumPost", store.Id); if (messageTemplate == null) { return 0; @@ -1074,7 +1106,7 @@ public int SendPrivateMessageNotification(Customer customer, PrivateMessage priv var store = _storeService.GetStoreById(privateMessage.StoreId) ?? _storeContext.CurrentStore; - var messageTemplate = GetLocalizedActiveMessageTemplate("Customer.NewPM", languageId, store.Id); + var messageTemplate = GetActiveMessageTemplate("Customer.NewPM", store.Id); if (messageTemplate == null) { return 0; @@ -1133,7 +1165,7 @@ public virtual int SendGenericMessage(string messageTemplateName, Action x.BccEmailAddresses, - localized.BccEmailAddresses, - localized.LanguageId); - - _localizedEntityService.SaveLocalizedValue(mt, - x => x.Subject, - localized.Subject, - localized.LanguageId); - - _localizedEntityService.SaveLocalizedValue(mt, - x => x.Body, - localized.Body, - localized.LanguageId); - - _localizedEntityService.SaveLocalizedValue(mt, - x => x.EmailAccountId, - localized.EmailAccountId, - localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(mt, x => x.BccEmailAddresses, localized.BccEmailAddresses, localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(mt, x => x.Subject, localized.Subject, localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(mt,x => x.Body, localized.Body, localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(mt, x => x.EmailAccountId, localized.EmailAccountId, localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(mt, x => x.Attachment1FileId, localized.Attachment1FileId, localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(mt, x => x.Attachment2FileId, localized.Attachment2FileId, localized.LanguageId); + _localizedEntityService.SaveLocalizedValue(mt, x => x.Attachment3FileId, localized.Attachment3FileId, localized.LanguageId); } } - [NonAction] private void PrepareStoresMappingModel(MessageTemplateModel model, MessageTemplate messageTemplate, bool excludeProperties) { @@ -156,7 +143,9 @@ public ActionResult List() //stores model.AvailableStores.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" }); foreach (var s in _storeService.GetAllStores()) + { model.AvailableStores.Add(new SelectListItem() { Text = s.Name, Value = s.Id.ToString() }); + } return View(model); } @@ -192,19 +181,24 @@ public ActionResult Edit(int id) FillTokensTree(model.TokensTree, _messageTokenProvider.GetListOfAllowedTokens()); - //available email accounts - foreach (var ea in _emailAccountService.GetAllEmailAccounts()) - model.AvailableEmailAccounts.Add(ea.ToModel()); + // available email accounts + foreach (var ea in _emailAccountService.GetAllEmailAccounts()) + { + model.AvailableEmailAccounts.Add(ea.ToModel()); + } - //Store + // Store PrepareStoresMappingModel(model, messageTemplate, false); - //locales + // locales AddLocales(_languageService, model.Locales, (locale, languageId) => { locale.BccEmailAddresses = messageTemplate.GetLocalized(x => x.BccEmailAddresses, languageId, false, false); locale.Subject = messageTemplate.GetLocalized(x => x.Subject, languageId, false, false); locale.Body = messageTemplate.GetLocalized(x => x.Body, languageId, false, false); + locale.Attachment1FileId = messageTemplate.GetLocalized(x => x.Attachment1FileId, languageId, false, false); + locale.Attachment2FileId = messageTemplate.GetLocalized(x => x.Attachment2FileId, languageId, false, false); + locale.Attachment3FileId = messageTemplate.GetLocalized(x => x.Attachment3FileId, languageId, false, false); var emailAccountId = messageTemplate.GetLocalized(x => x.EmailAccountId, languageId, false, false); locale.EmailAccountId = emailAccountId > 0 ? emailAccountId : _emailAccountSettings.DefaultEmailAccountId; @@ -229,10 +223,10 @@ public ActionResult Edit(MessageTemplateModel model, bool continueEditing) messageTemplate = model.ToEntity(messageTemplate); _messageTemplateService.UpdateMessageTemplate(messageTemplate); - //Stores + // Stores _storeMappingService.SaveStoreMappings(messageTemplate, model.SelectedStoreIds); - //locales + // locales UpdateLocales(messageTemplate, model); NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.MessageTemplates.Updated")); diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Messages/MessageTemplateModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Messages/MessageTemplateModel.cs index a0de763db5..5764db0656 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Messages/MessageTemplateModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Messages/MessageTemplateModel.cs @@ -52,6 +52,15 @@ public MessageTemplateModel() [SmartResourceDisplayName("Admin.ContentManagement.MessageTemplates.Fields.SendManually")] public bool SendManually { get; set; } + [SmartResourceDisplayName("Admin.ContentManagement.MessageTemplates.Fields.Attachment1FileId")] + public int? Attachment1FileId { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.MessageTemplates.Fields.Attachment2FileId")] + public int? Attachment2FileId { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.MessageTemplates.Fields.Attachment3FileId")] + public int? Attachment3FileId { get; set; } + //Store mapping [SmartResourceDisplayName("Admin.Common.Store.LimitedTo")] public bool LimitedToStores { get; set; } @@ -81,5 +90,14 @@ public class MessageTemplateLocalizedModel : ILocalizedModelLocal [SmartResourceDisplayName("Admin.ContentManagement.MessageTemplates.Fields.EmailAccount")] public int EmailAccountId { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.MessageTemplates.Fields.Attachment1FileId")] + public int? Attachment1FileId { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.MessageTemplates.Fields.Attachment2FileId")] + public int? Attachment2FileId { get; set; } + + [SmartResourceDisplayName("Admin.ContentManagement.MessageTemplates.Fields.Attachment3FileId")] + public int? Attachment3FileId { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml index 82c2317d34..7021397e30 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml @@ -13,7 +13,7 @@ x.Add().Text(T("Admin.Common.Info").Text).Content(TabInfo()).Selected(true); x.Add().Text(T("Admin.Common.Stores").Text).Content(TabStores()); - //generate an event + // generate an event EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "template-edit", this.Html, this.Model)); }) @@ -126,6 +126,33 @@ @Html.ValidationMessageFor(model => model.Locales[item].Subject) + + + @Html.SmartLabelFor(model => model.Locales[item].Attachment1FileId) + + + @Html.EditorFor(model => Model.Locales[item].Attachment1FileId) + @Html.ValidationMessageFor(model => model.Locales[item].Attachment1FileId) + + + + + @Html.SmartLabelFor(model => model.Locales[item].Attachment2FileId) + + + @Html.EditorFor(model => Model.Locales[item].Attachment2FileId) + @Html.ValidationMessageFor(model => model.Locales[item].Attachment2FileId) + + + + + @Html.SmartLabelFor(model => model.Locales[item].Attachment3FileId) + + + @Html.EditorFor(model => Model.Locales[item].Attachment3FileId) + @Html.ValidationMessageFor(model => model.Locales[item].Attachment3FileId) + + @Html.SmartLabelFor(model => model.Locales[item].Body) @@ -170,6 +197,33 @@ @Html.ValidationMessageFor(model => model.Subject) + + + @Html.SmartLabelFor(model => model.Attachment1FileId) + + + @Html.EditorFor(model => Model.Attachment1FileId) + @Html.ValidationMessageFor(model => model.Attachment1FileId) + + + + + @Html.SmartLabelFor(model => model.Attachment2FileId) + + + @Html.EditorFor(model => Model.Attachment2FileId) + @Html.ValidationMessageFor(model => model.Attachment2FileId) + + + + + @Html.SmartLabelFor(model => model.Attachment3FileId) + + + @Html.EditorFor(model => Model.Attachment3FileId) + @Html.ValidationMessageFor(model => model.Attachment3FileId) + + @Html.SmartLabelFor(model => model.Body) @@ -246,7 +300,8 @@ else {
@T("Admin.Configuration.Stores.NoStoresDefined")
- } + } + } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download.cshtml index d530182896..a3b33585b9 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download.cshtml @@ -55,6 +55,7 @@ } +
@(download != null ? download.Filename : "")
From 3b1ad7f9f741caa04daf310ac61e76f12685cee4 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 8 Jul 2015 14:45:39 +0200 Subject: [PATCH 0221/1256] Send currency code of primary store currency (not of working currency) to payment gateway. This commit will conflict with 2.5 branch. --- changelog.md | 1 + .../SmartStore.AmazonPay/Description.txt | 2 +- .../Services/AmazonPayApi.cs | 43 ++++++++++++++++-- .../Services/AmazonPayService.cs | 44 ++++++++++--------- .../Services/IAmazonPayApi.cs | 2 + src/Plugins/SmartStore.AmazonPay/changelog.md | 4 ++ 6 files changed, 71 insertions(+), 25 deletions(-) diff --git a/changelog.md b/changelog.md index f804da9730..437b9b7823 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,7 @@ * #563 Scheduled Tasks: ensure, that 'LastEndUtc' is ALWAYS set * Topics grid: fixed 'maxJsonLength exceeded' error * Debitoor: Fixed "The property named 'lines.0.productOrService' should be defined" +* Send currency code of primary store currency (not of working currency) to payment gateway ## SmartStore.NET 2.2.1 diff --git a/src/Plugins/SmartStore.AmazonPay/Description.txt b/src/Plugins/SmartStore.AmazonPay/Description.txt index bebde13958..ab15464d35 100644 --- a/src/Plugins/SmartStore.AmazonPay/Description.txt +++ b/src/Plugins/SmartStore.AmazonPay/Description.txt @@ -1,6 +1,6 @@ FriendlyName: Pay with Amazon SystemName: SmartStore.AmazonPay -Version: 2.2.0.1 +Version: 2.2.0.2 Group: Payment MinAppVersion: 2.2.0 Author: SmartStore AG diff --git a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs index 64d21b0428..6e69b3596c 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs @@ -21,6 +21,8 @@ using SmartStore.Services.Helpers; using SmartStore.Core.Infrastructure; using SmartStore.Core.Plugins; +using SmartStore.Core.Domain.Directory; +using SmartStore.Core.Domain.Discounts; namespace SmartStore.AmazonPay.Api { @@ -32,6 +34,9 @@ public class AmazonPayApi : IAmazonPayApi private readonly ILocalizationService _localizationService; private readonly IAddressService _addressService; private readonly IDateTimeHelper _dateTimeHelper; + private readonly ICurrencyService _currencyService; + private readonly CurrencySettings _currencySettings; + private readonly IOrderTotalCalculationService _orderTotalCalculationService; public AmazonPayApi( ICountryService countryService, @@ -39,7 +44,10 @@ public AmazonPayApi( IOrderService orderService, ILocalizationService localizationService, IAddressService addressService, - IDateTimeHelper dateTimeHelper) + IDateTimeHelper dateTimeHelper, + ICurrencyService currencyService, + CurrencySettings currencySettings, + IOrderTotalCalculationService orderTotalCalculationService) { _countryService = countryService; _stateProvinceService = stateProvinceService; @@ -47,6 +55,9 @@ public AmazonPayApi( _localizationService = localizationService; _addressService = addressService; _dateTimeHelper = dateTimeHelper; + _currencyService = currencyService; + _currencySettings = currencySettings; + _orderTotalCalculationService = orderTotalCalculationService; } private string GetRandomId(string prefix) @@ -213,7 +224,7 @@ public OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, st attributes.OrderTotal = new OrderTotal() { Amount = orderTotalAmount.Value.ToString("0.00", CultureInfo.InvariantCulture), - CurrencyCode = currencyCode + CurrencyCode = currencyCode ?? "EUR" }; } @@ -240,6 +251,26 @@ public OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, st return null; } + public OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, string orderReferenceId, Customer customer, List cart) + { + decimal orderTotalDiscountAmountBase = decimal.Zero; + Discount orderTotalAppliedDiscount = null; + List appliedGiftCards = null; + int redeemedRewardPoints = 0; + decimal redeemedRewardPointsAmount = decimal.Zero; + + decimal? shoppingCartTotalBase = _orderTotalCalculationService.GetShoppingCartTotal(cart, + out orderTotalDiscountAmountBase, out orderTotalAppliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); + + if (shoppingCartTotalBase.HasValue) + { + var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + + return SetOrderReferenceDetails(client, orderReferenceId, shoppingCartTotalBase, currency.CurrencyCode); + } + return null; + } + /// Confirm an order reference informs Amazon that the buyer has placed the order. public void ConfirmOrderReference(AmazonPayClient client, string orderReferenceId) { @@ -404,6 +435,8 @@ public void Capture(AmazonPayClient client, CapturePaymentRequest capture, Captu result.NewPaymentStatus = capture.Order.PaymentStatus; var request = new CaptureRequest(); + var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + request.SellerId = client.Settings.SellerId; request.AmazonAuthorizationId = capture.Order.AuthorizationTransactionId; request.CaptureReferenceId = GetRandomId("Capture"); @@ -412,7 +445,7 @@ public void Capture(AmazonPayClient client, CapturePaymentRequest capture, Captu request.CaptureAmount = new Price() { Amount = capture.Order.OrderTotal.ToString("0.00", CultureInfo.InvariantCulture), - CurrencyCode = capture.Order.CustomerCurrencyCode ?? "EUR" + CurrencyCode = currency.CurrencyCode }; var response = client.Service.Capture(request); @@ -499,6 +532,8 @@ public string Refund(AmazonPayClient client, RefundPaymentRequest refund, Refund result.NewPaymentStatus = refund.Order.PaymentStatus; string amazonRefundId = null; + var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + var request = new RefundRequest(); request.SellerId = client.Settings.SellerId; request.AmazonCaptureId = refund.Order.CaptureTransactionId; @@ -508,7 +543,7 @@ public string Refund(AmazonPayClient client, RefundPaymentRequest refund, Refund request.RefundAmount = new Price() { Amount = refund.AmountToRefund.ToString("0.00", CultureInfo.InvariantCulture), - CurrencyCode = refund.Order.CustomerCurrencyCode ?? "EUR" + CurrencyCode = currency.CurrencyCode }; var response = client.Service.Refund(request); diff --git a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs index 457844290e..04c34acd1c 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs @@ -18,6 +18,7 @@ using SmartStore.Core.Data; using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Discounts; using SmartStore.Core.Domain.Logging; using SmartStore.Core.Domain.Orders; @@ -48,6 +49,7 @@ public class AmazonPayService : IAmazonPayService private readonly IGenericAttributeService _genericAttributeService; private readonly IOrderTotalCalculationService _orderTotalCalculationService; private readonly ICurrencyService _currencyService; + private readonly CurrencySettings _currencySettings; private readonly ICustomerService _customerService; private readonly IStoreService _storeService; private readonly IPriceFormatter _priceFormatter; @@ -67,6 +69,7 @@ public AmazonPayService( IGenericAttributeService genericAttributeService, IOrderTotalCalculationService orderTotalCalculationService, ICurrencyService currencyService, + CurrencySettings currencySettings, ICustomerService customerService, IStoreService storeService, IPriceFormatter priceFormatter, @@ -85,6 +88,7 @@ public AmazonPayService( _genericAttributeService = genericAttributeService; _orderTotalCalculationService = orderTotalCalculationService; _currencyService = currencyService; + _currencySettings = currencySettings; _customerService = customerService; _storeService = storeService; _priceFormatter = priceFormatter; @@ -109,27 +113,27 @@ private string GetPluginUrl(string action, bool useSsl = false) return pluginUrl; } - private decimal? GetOrderTotal() - { - decimal orderTotalDiscountAmountBase = decimal.Zero; - Discount orderTotalAppliedDiscount = null; - List appliedGiftCards = null; - int redeemedRewardPoints = 0; - decimal redeemedRewardPointsAmount = decimal.Zero; + //private decimal? GetOrderTotal() + //{ + // decimal orderTotalDiscountAmountBase = decimal.Zero; + // Discount orderTotalAppliedDiscount = null; + // List appliedGiftCards = null; + // int redeemedRewardPoints = 0; + // decimal redeemedRewardPointsAmount = decimal.Zero; - var cart = _services.WorkContext.CurrentCustomer.GetCartItems(ShoppingCartType.ShoppingCart, _services.StoreContext.CurrentStore.Id); + // var cart = _services.WorkContext.CurrentCustomer.GetCartItems(ShoppingCartType.ShoppingCart, _services.StoreContext.CurrentStore.Id); - decimal? shoppingCartTotalBase = _orderTotalCalculationService.GetShoppingCartTotal(cart, - out orderTotalDiscountAmountBase, out orderTotalAppliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); + // decimal? shoppingCartTotalBase = _orderTotalCalculationService.GetShoppingCartTotal(cart, + // out orderTotalDiscountAmountBase, out orderTotalAppliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); - if (shoppingCartTotalBase.HasValue) // shipping method needs to be selected here! - { - decimal shoppingCartTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTotalBase.Value, _services.WorkContext.WorkingCurrency); + // if (shoppingCartTotalBase.HasValue) // shipping method needs to be selected here! + // { + // decimal shoppingCartTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTotalBase.Value, _services.WorkContext.WorkingCurrency); - return shoppingCartTotal; - } - return null; - } + // return shoppingCartTotal; + // } + // return null; + //} private void SerializeOrderAttribute(AmazonPayOrderAttribute attribute, Order order) { @@ -530,7 +534,7 @@ public AmazonPayViewModel ProcessPluginRequest(AmazonPayRequestType type, TempDa _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.SelectedPaymentMethod, AmazonPayCore.SystemName, store.Id); var client = new AmazonPayClient(settings); - var details = _api.SetOrderReferenceDetails(client, model.OrderReferenceId, GetOrderTotal(), currency.CurrencyCode); + var unused = _api.SetOrderReferenceDetails(client, model.OrderReferenceId, customer, cart); // this is ugly... var paymentRequest = _httpContext.Session["OrderPaymentInfo"] as ProcessPaymentRequest; @@ -899,7 +903,7 @@ public PreProcessPaymentResult PreProcessPayment(ProcessPaymentRequest request) var orderGuid = request.OrderGuid.ToString(); var store = _storeService.GetStoreById(request.StoreId); var customer = _customerService.GetCustomerById(request.CustomerId); - var currency = _services.WorkContext.WorkingCurrency; + var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); var settings = _services.Settings.LoadSetting(store.Id); var state = _httpContext.GetAmazonPayState(_services.Localization); var client = new AmazonPayClient(settings); @@ -968,7 +972,7 @@ public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest request) { var orderGuid = request.OrderGuid.ToString(); var store = _storeService.GetStoreById(request.StoreId); - var currency = _services.WorkContext.WorkingCurrency; + var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); var settings = _services.Settings.LoadSetting(store.Id); var state = _httpContext.GetAmazonPayState(_services.Localization); var client = new AmazonPayClient(settings); diff --git a/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayApi.cs b/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayApi.cs index 838e9187fe..df245dd32f 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayApi.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayApi.cs @@ -21,6 +21,8 @@ public partial interface IAmazonPayApi OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, string orderReferenceId, decimal? orderTotalAmount, string currencyCode, string orderGuid = null, string storeName = null); + OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, string orderReferenceId, Customer customer, List cart); + void ConfirmOrderReference(AmazonPayClient client, string orderReferenceId); void CancelOrderReference(AmazonPayClient client, string orderReferenceId); diff --git a/src/Plugins/SmartStore.AmazonPay/changelog.md b/src/Plugins/SmartStore.AmazonPay/changelog.md index 21aa9f7c0f..416414c398 100644 --- a/src/Plugins/SmartStore.AmazonPay/changelog.md +++ b/src/Plugins/SmartStore.AmazonPay/changelog.md @@ -1,5 +1,9 @@ #Release Notes# +##Pay with Amazon 2.2.0.2 +###Bugfixes### +* Send currency code of primary store currency (not of working currency) to payment gateway + ##Pay with Amazon 2.2.0.1 ### New Features * Supports order list label for new incoming IPNs From 99973fe6bf450d0188546c23bf38c542b23c98fa Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 8 Jul 2015 19:07:02 +0200 Subject: [PATCH 0222/1256] Updated CREDITS.txt --- CREDITS.txt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/CREDITS.txt b/CREDITS.txt index f03fe54186..88b2d0a6be 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -13,7 +13,7 @@ copyright notices, and licenses. 51Degrees --------------------------------------------- -WebSite: http://http://51degrees.mobi/ +WebSite: http://51degrees.mobi/ Copyright: Copyright 2010 - 2013 51Degrees.mobi Limited License: Mozilla Public License 2.0 (MPL-2.0) @@ -44,7 +44,7 @@ License: MIT AutoMapper --------------------------------------------- -WebSite: http://http://www.automapper.org +WebSite: http://www.automapper.org Copyright: Copyright 2008-2013 Jimmy Bogard and other contributors License: MIT @@ -58,7 +58,7 @@ License: Apache License 2.0 (Apache) DotNetOpenAuth --------------------------------------------- -Website: http://http://dotnetopenauth.net/ +Website: http://dotnetopenauth.net/ Copyright: Copyright (c) 2011, Outercurve Foundation License: MS-PL @@ -145,12 +145,6 @@ Copyright: Copyright (c) 2007 James Newton-King License: MIT -LESS CSS for .NET ---------------------------------------------- -Website: http://www.dotlesscss.org/ -License: Apache License v2.0 - - GeoLite Free by MaxMind --------------------------------------------- Website: http://www.maxmind.com From 38a32540b984530e393c6ca2a27e462b08ca7554 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 8 Jul 2015 20:47:22 +0200 Subject: [PATCH 0223/1256] Minor change --- .../SmartStore.AmazonPay/Localization/resources.de-de.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugins/SmartStore.AmazonPay/Localization/resources.de-de.xml b/src/Plugins/SmartStore.AmazonPay/Localization/resources.de-de.xml index 87a9e2e3a0..3c5dce6dd0 100644 --- a/src/Plugins/SmartStore.AmazonPay/Localization/resources.de-de.xml +++ b/src/Plugins/SmartStore.AmazonPay/Localization/resources.de-de.xml @@ -8,7 +8,7 @@ - Registrieren Sie sich bei Amazon Payments an.

+ Registrieren Sie sich bei Amazon Payments.

So richten Sie "Bezahlen mit Amazon" ein:

  • Tragen Sie Ihre Amazon-Zugangsdaten unten in die dafür vorgesehenen Felder ein. Sie finden diese Daten in Ihrem Amazon Seller Central Konto.
  • Ihre Händlernummer finden Sie dort rechts oben unter Einstellungen - Integrationseinstellungen.
  • From 3e7b90b2260a5a30fc8d1068f49e034b88ce232d Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Thu, 9 Jul 2015 16:04:59 +0200 Subject: [PATCH 0224/1256] Closes #691 Product quantity not added to cart on mobile theme --- .../SmartStore.Web/Controllers/ProductController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs index c630094401..ff7660fd01 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs @@ -237,7 +237,7 @@ public ActionResult AddProductToCart(int productId, FormCollection form) foreach (string formKey in form.AllKeys) { - if (formKey.Equals(string.Format("addtocart_{0}.EnteredQuantity", productId), StringComparison.InvariantCultureIgnoreCase)) + if (formKey.Equals(string.Format("addtocart_{0}.AddToCart.EnteredQuantity", productId), StringComparison.InvariantCultureIgnoreCase)) { int.TryParse(form[formKey], out quantity); break; From e8161ddb6ec7ceccb8138d3c0023ae1612ab7af5 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Thu, 9 Jul 2015 16:25:42 +0200 Subject: [PATCH 0225/1256] Closes #186 Mobile: variant images do not refresh --- changelog.md | 4 +++- .../SmartStore.Web/Scripts/public.product-detail.mobile.js | 2 +- .../Views/Product/_PictureGallery.Mobile.cshtml | 4 +--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/changelog.md b/changelog.md index 437b9b7823..3f66800d8b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,4 @@ -# Release Notes +# Release Notes ## SmartStore.NET 2.2.2 @@ -18,6 +18,8 @@ * Topics grid: fixed 'maxJsonLength exceeded' error * Debitoor: Fixed "The property named 'lines.0.productOrService' should be defined" * Send currency code of primary store currency (not of working currency) to payment gateway +* #691 Product quantity not added to cart on mobile theme +* #186 Mobile: variant images do not refresh ## SmartStore.NET 2.2.1 diff --git a/src/Presentation/SmartStore.Web/Scripts/public.product-detail.mobile.js b/src/Presentation/SmartStore.Web/Scripts/public.product-detail.mobile.js index 30d3475e29..e15764dc15 100644 --- a/src/Presentation/SmartStore.Web/Scripts/public.product-detail.mobile.js +++ b/src/Presentation/SmartStore.Web/Scripts/public.product-detail.mobile.js @@ -106,7 +106,7 @@ updateAttrLine(".attr-height", data.Measure.Height.Text); updateAttrLine(".attr-stock", data.Stock.Availability.Text); - console.log(data.Stock.Availability.Text); + UpdateMainImage(imageUrls[data.GalleryStartIndex]); context.find('.add-to-cart .form-inline').toggle(data.Stock.Availability.Available); diff --git a/src/Presentation/SmartStore.Web/Views/Product/_PictureGallery.Mobile.cshtml b/src/Presentation/SmartStore.Web/Views/Product/_PictureGallery.Mobile.cshtml index 29d30b86e0..7f5c93fc21 100644 --- a/src/Presentation/SmartStore.Web/Views/Product/_PictureGallery.Mobile.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Product/_PictureGallery.Mobile.cshtml @@ -1,5 +1,4 @@ -@*codehint: sm-edit (new model)*@ -@model ProductDetailsPictureModel +@model ProductDetailsPictureModel @using SmartStore.Web.Models.Catalog; @if (Model.PictureModels.Count > 0) { @@ -29,7 +28,6 @@ imageUrls.push('@(picture.FullSizeImageUrl)'); } - $(document).bind('pageinit', function (e) { $("#default-image").on("swipeleft", swipeLeftHandler); $("#default-image").on("swiperight", swipeRightHandler); From 8052f9f73d23f248c998197eb4a3f90a461cb7ae Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Thu, 9 Jul 2015 17:08:10 +0200 Subject: [PATCH 0226/1256] Closes #648 Add hint for * at mandatory form fields at address creation --- changelog.md | 1 + .../SmartStore.Data/Migrations/201505272236124_V222.cs | 4 ++++ .../SmartStore.Web/Themes/Alpha/Content/checkout.less | 5 +++++ .../Views/Shared/_CreateOrUpdateAddress.cshtml | 8 +++++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 3f66800d8b..62afa69f8c 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,7 @@ * (Soft) deletion of SEO slug supporting entities now also deletes the corresponding url records * License checker now supports IDN mapping for domain names * #716 Supporting of paged google-product data query for SQL-Server Compact Edition +* #648 Add hint for * at mandatory form fields at address creation ### Bugfixes * #694 Product variant attribute in product page should not be preselected implicitly diff --git a/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs b/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs index 62653a9d70..5f241dbe73 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs @@ -44,6 +44,10 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Not in assortment", "Nicht im Sortiment"); + builder.AddOrUpdate("Address.Fields.Required.Hint", + "* Input elements with asterisk are required and have to be filled out.", + "* Eingabefelder mit Sternchen sind Pflichfelder und mssen ausgefllt werden."); + } } } diff --git a/src/Presentation/SmartStore.Web/Themes/Alpha/Content/checkout.less b/src/Presentation/SmartStore.Web/Themes/Alpha/Content/checkout.less index ea2111083c..f59456e104 100644 --- a/src/Presentation/SmartStore.Web/Themes/Alpha/Content/checkout.less +++ b/src/Presentation/SmartStore.Web/Themes/Alpha/Content/checkout.less @@ -167,6 +167,11 @@ text-align:left; } +.address-required-hint { + margin-bottom: 12px; + font-size: 12px; +} + .checkout-data .payment-info { padding: 10px 0; border-top: 1px solid #d7d7d7; diff --git a/src/Presentation/SmartStore.Web/Views/Shared/_CreateOrUpdateAddress.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/_CreateOrUpdateAddress.cshtml index ddca2b31bc..23bde2bdda 100644 --- a/src/Presentation/SmartStore.Web/Views/Shared/_CreateOrUpdateAddress.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Shared/_CreateOrUpdateAddress.cshtml @@ -176,4 +176,10 @@
} - \ No newline at end of file +
+
+ @T("Address.Fields.Required.Hint") +
+
+ + From ba075db18fa63d8d1dbbb689d224a70e0fc070b6 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Thu, 9 Jul 2015 18:44:59 +0200 Subject: [PATCH 0227/1256] Closes #671 Bundle products: display base price according to applied discount --- changelog.md | 1 + .../Migrations/201505272236124_V222.cs | 3 +++ .../Views/Product/_CreateOrUpdate.Price.cshtml | 13 +++++++++++++ .../SmartStore.Web/Controllers/CatalogHelper.cs | 1 + 4 files changed, 18 insertions(+) diff --git a/changelog.md b/changelog.md index 62afa69f8c..2d8240fc1c 100644 --- a/changelog.md +++ b/changelog.md @@ -21,6 +21,7 @@ * Send currency code of primary store currency (not of working currency) to payment gateway * #691 Product quantity not added to cart on mobile theme * #186 Mobile: variant images do not refresh +* #671 Bundle products: display base price according to applied discount ## SmartStore.NET 2.2.1 diff --git a/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs b/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs index 5f241dbe73..3fa7e01294 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201505272236124_V222.cs @@ -48,6 +48,9 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "* Input elements with asterisk are required and have to be filled out.", "* Eingabefelder mit Sternchen sind Pflichfelder und mssen ausgefllt werden."); + builder.AddOrUpdate("Admin.Products.BasePrice.Hint", + "Please keep in mind, the base price is depending on several factors and will therefore only be calculated reliable in the front end.", + "Bitte beachten Sie, dass der tatschliche Grundpreis von verschiedenen Faktoren abhngig ist und erst im Shop zuverlssig berechnet werden kann."); } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Price.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Price.cshtml index 4c843c04e6..ce16846d32 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Price.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Price.cshtml @@ -51,10 +51,12 @@ if ($('#@Html.FieldIdFor(model => model.BasePriceEnabled)').is(':checked')) { $('#pnlBasePriceBaseAmount').show(); $('#pnlBasePriceAmount').show(); + $('#pnlBasePriceAmountHint').show(); } else { $('#pnlBasePriceBaseAmount').hide(); $('#pnlBasePriceAmount').hide(); + $('#pnlBasePriceAmountHint').hide(); } } @@ -224,6 +226,17 @@ @*@T("Admin.Catalog.Products.Fields.BasePriceInfo")*@ + + +   + + +
+ @T("Admin.Products.BasePrice.Hint") +
+ + +
diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index 7c54a404b2..dceb88c312 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -845,6 +845,7 @@ public ProductDetailsModel PrepareProductDetailModel( if (isBundle && product.BundlePerItemPricing && !string.IsNullOrWhiteSpace(model.ProductPrice.PriceWithDiscount)) { model.ProductPrice.NoteWithDiscount = T("Products.Bundle.PriceWithDiscount.Note"); + model.BasePriceInfo = product.GetBasePriceInfo(_localizationService, _priceFormatter, (product.Price - finalPriceWithDiscount) * (-1)); } } } From e1f94a7ec6b77b6c11796f395d2e71bc3adde148 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 9 Jul 2015 20:52:17 +0200 Subject: [PATCH 0228/1256] Minor changes --- src/Plugins/SmartStore.PayPal/Models/ApiConfigurationModels.cs | 2 ++ .../SmartStore.PayPal/Models/PayPalDirectPaymentInfoModel.cs | 3 +++ src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj | 1 + 3 files changed, 6 insertions(+) diff --git a/src/Plugins/SmartStore.PayPal/Models/ApiConfigurationModels.cs b/src/Plugins/SmartStore.PayPal/Models/ApiConfigurationModels.cs index 6918df7103..91ac993572 100644 --- a/src/Plugins/SmartStore.PayPal/Models/ApiConfigurationModels.cs +++ b/src/Plugins/SmartStore.PayPal/Models/ApiConfigurationModels.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Web.Mvc; using SmartStore.PayPal.Settings; using SmartStore.Web.Framework; @@ -21,6 +22,7 @@ public abstract class ApiConfigurationModel: ModelBase public string ApiAccountName { get; set; } [SmartResourceDisplayName("Plugins.Payments.PayPal.ApiAccountPassword")] + [DataType(DataType.Password)] public string ApiAccountPassword { get; set; } [SmartResourceDisplayName("Plugins.Payments.PayPal.Signature")] diff --git a/src/Plugins/SmartStore.PayPal/Models/PayPalDirectPaymentInfoModel.cs b/src/Plugins/SmartStore.PayPal/Models/PayPalDirectPaymentInfoModel.cs index 6f42e1e694..86922f5a0d 100644 --- a/src/Plugins/SmartStore.PayPal/Models/PayPalDirectPaymentInfoModel.cs +++ b/src/Plugins/SmartStore.PayPal/Models/PayPalDirectPaymentInfoModel.cs @@ -17,6 +17,7 @@ public PayPalDirectPaymentInfoModel() [SmartResourceDisplayName("Payment.SelectCreditCard")] [AllowHtml] public string CreditCardType { get; set; } + [SmartResourceDisplayName("Payment.SelectCreditCard")] public IList CreditCardTypes { get; set; } @@ -31,9 +32,11 @@ public PayPalDirectPaymentInfoModel() [SmartResourceDisplayName("Payment.ExpirationDate")] [AllowHtml] public string ExpireMonth { get; set; } + [SmartResourceDisplayName("Payment.ExpirationDate")] [AllowHtml] public string ExpireYear { get; set; } + public IList ExpireMonths { get; set; } public IList ExpireYears { get; set; } diff --git a/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj b/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj index 1efcc29c03..763d76c4f8 100644 --- a/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj +++ b/src/Plugins/SmartStore.PayPal/SmartStore.PayPal.csproj @@ -68,6 +68,7 @@ ..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + From 9b3061cf17210c431ba2cf9cf4c5937aaa3100db Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 10 Jul 2015 13:11:45 +0200 Subject: [PATCH 0229/1256] New widget zones account_dropdown_before & account_dropdown_after --- .../SmartStore.Web/Views/Common/AccountDropdown.cshtml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Presentation/SmartStore.Web/Views/Common/AccountDropdown.cshtml b/src/Presentation/SmartStore.Web/Views/Common/AccountDropdown.cshtml index 8e4a0e5ce4..cacb881673 100644 --- a/src/Presentation/SmartStore.Web/Views/Common/AccountDropdown.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Common/AccountDropdown.cshtml @@ -17,6 +17,7 @@ @if (Model.IsAuthenticated) { } else From 8251e878f2b002dea3871d68893f5c5491b75c13 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 10 Jul 2015 15:13:20 +0200 Subject: [PATCH 0230/1256] Minor UI fix --- .../Administration/Views/Security/Permissions.cshtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Security/Permissions.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Security/Permissions.cshtml index 5703d75a62..0d02bfd4b2 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Security/Permissions.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Security/Permissions.cshtml @@ -33,12 +33,12 @@ - @T("Admin.Configuration.ACL.Permission") + @T("Admin.Configuration.ACL.Permission") @foreach (var cr in Model.AvailableCustomerRoles) { - @cr.Name + @cr.Name } From a7dfc3dd2310af7c8a689cfa2aa431eb07aa4d9f Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 10 Jul 2015 15:52:34 +0200 Subject: [PATCH 0231/1256] More minor UI fixes --- .../Administration/Views/CustomerRole/List.cshtml | 2 +- .../SmartStore.Web/Administration/Views/GiftCard/List.cshtml | 2 +- .../SmartStore.Web/Administration/Views/Order/Edit.cshtml | 2 +- .../Administration/Views/Order/ShipmentList.cshtml | 2 +- .../SmartStore.Web/Administration/Views/Shipping/Methods.cshtml | 2 +- .../Administration/Views/Shipping/Restrictions.cshtml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/CustomerRole/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/CustomerRole/List.cshtml index 2e2c603a07..ae06ccaff5 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/CustomerRole/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/CustomerRole/List.cshtml @@ -50,7 +50,7 @@ .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") .Width(50) .Centered() - .HeaderTemplate(T("Admin.Common.Edit").Text) + .HeaderTemplate("{0}".FormatWith(T("Admin.Common.Edit").Text)) .Filterable(false); }) .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "CustomerRole")) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/GiftCard/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/GiftCard/List.cshtml index 7e7f8b1277..fdcacfa7ea 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/GiftCard/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/GiftCard/List.cshtml @@ -72,7 +72,7 @@ .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") .Width(50) .Centered() - .HeaderTemplate(T("Admin.Common.Edit").Text) + .HeaderTemplate("{0}".FormatWith(T("Admin.Common.Edit").Text)) .Filterable(false); }) .Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both)) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Order/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Order/Edit.cshtml index 3093b1cbfd..e8e44b680d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Order/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Order/Edit.cshtml @@ -1231,7 +1231,7 @@ .ClientTemplate("\">" + T("Admin.Common.View").Text + "") .Width(50) .Centered() - .HeaderTemplate(T("Admin.Common.View").Text); + .HeaderTemplate("{0}".FormatWith(T("Admin.Common.View").Text)); }) .EnableCustomBinding(true)) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Order/ShipmentList.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Order/ShipmentList.cshtml index 8744d91dce..967a96ac86 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Order/ShipmentList.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Order/ShipmentList.cshtml @@ -96,7 +96,7 @@ .ClientTemplate("\">" + T("Admin.Common.View").Text + "") .Width(50) .Centered() - .HeaderTemplate(T("Admin.Common.View").Text); + .HeaderTemplate("{0}".FormatWith(T("Admin.Common.View").Text)); }) .Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both)) .DataBinding(dataBinding => dataBinding.Ajax().Select("ShipmentListSelect", "Order")) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Methods.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Methods.cshtml index 494932317a..61f5ba0fb9 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Methods.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Methods.cshtml @@ -40,7 +40,7 @@ .ClientTemplate("\">" + T("Admin.Common.Edit").Text + "") .Width(160) .Centered() - .HeaderTemplate(T("Admin.Common.Edit").Text); + .HeaderTemplate("{0}".FormatWith(T("Admin.Common.Edit").Text)); }) .DataBinding(dataBinding => dataBinding.Ajax().Select("Methods", "Shipping")) .EnableCustomBinding(true)) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml index e13f1fe8e5..d7936aacde 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml @@ -75,7 +75,7 @@ @foreach (var sm in Model.AvailableShippingMethods) { var restricted = Model.Restricted.ContainsKey(c.Id) && Model.Restricted[c.Id][sm.Id]; - + } From 92a029ac81867a18629d48021a5211fbffdde4a7 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 10 Jul 2015 19:02:19 +0200 Subject: [PATCH 0232/1256] Added documentation link --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 39784f16b0..f2236086a6 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ The state-of-the-art architecture of SmartStore.NET - with `ASP.NET 4.5` + `MVC * **Website:** [http://www.smartstore.com/net](http://www.smartstore.com/net) * **Forum:** [http://community.smartstore.com](http://community.smartstore.com) * **Marketplace:** [http://community.smartstore.com/marketplace](http://community.smartstore.com/marketplace) +* **Documentation:** [https://smartstore.atlassian.net/wiki/display/SD/SmartStore.NET+Documentation](https://smartstore.atlassian.net/wiki/display/SD/SmartStore.NET+Documentation) ## Highlights From b2de9a790e6f82e8c45b20db9152bc8f794615a6 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 10 Jul 2015 19:06:06 +0200 Subject: [PATCH 0233/1256] Altered display text for documentation --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index f2236086a6..ed0aca09a1 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,7 @@ The state-of-the-art architecture of SmartStore.NET - with `ASP.NET 4.5` + `MVC * **Website:** [http://www.smartstore.com/net](http://www.smartstore.com/net) * **Forum:** [http://community.smartstore.com](http://community.smartstore.com) * **Marketplace:** [http://community.smartstore.com/marketplace](http://community.smartstore.com/marketplace) -* **Documentation:** [https://smartstore.atlassian.net/wiki/display/SD/SmartStore.NET+Documentation](https://smartstore.atlassian.net/wiki/display/SD/SmartStore.NET+Documentation) - +* **Documentation:** [https://smartstore.atlassian.net/wiki/display/SD/SmartStore.NET+Documentation](SmartStore.NET Documentation in English) ## Highlights From eb84ec500760103fad896b56993e8849ea126316 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 10 Jul 2015 19:06:06 +0200 Subject: [PATCH 0234/1256] Altered display text for documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed0aca09a1..7f4940713b 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ The state-of-the-art architecture of SmartStore.NET - with `ASP.NET 4.5` + `MVC * **Website:** [http://www.smartstore.com/net](http://www.smartstore.com/net) * **Forum:** [http://community.smartstore.com](http://community.smartstore.com) * **Marketplace:** [http://community.smartstore.com/marketplace](http://community.smartstore.com/marketplace) -* **Documentation:** [https://smartstore.atlassian.net/wiki/display/SD/SmartStore.NET+Documentation](SmartStore.NET Documentation in English) +* **Documentation:** [SmartStore.NET Documentation in English](https://smartstore.atlassian.net/wiki/display/SD/SmartStore.NET+Documentation) ## Highlights From fad9d8b6bb901db9a06a45ceba7c6b0d663dbe59 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Fri, 10 Jul 2015 21:54:17 +0200 Subject: [PATCH 0235/1256] Minor change --- .../201506181858349_AclRecordCustomerRole.cs | 35 ++++++++++++++++++- .../Localization/resources.de-de.xml | 4 +-- .../Localization/resources.de-de.xml | 4 +-- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs index 2641ef6b47..c3af119d84 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs @@ -61,7 +61,40 @@ before you can assign them to all subcategories and products.
builder.AddOrUpdate("Admin.Configuration.Acl.NoRolesDefined", "No customer roles defined", "Es sind keine Kundengruppen definiert"); - + + builder.AddOrUpdate("Admin.Orders.Fields.OrderGuid", + "Order reference number", + "Bestellreferenznummer", + "The internal order reference number. In contrast to the order number it already exists during checkout that is before order creation.", + "Die interne Bestellreferenznummer. Im Gegensatz zur Auftragsnummer existiert diese bereits im Kassenbereich, d.h. vor der eigentlichen Erstelllung des Auftrags."); + + builder.AddOrUpdate("Admin.Configuration.Payment.CannotActivatePaymentMethod") + .Value("de", "Das Plugin erlaubt keine Aktivierung dieser Zahlungsart."); + + builder.AddOrUpdate("Admin.Orders.Fields.PaymentMethod") + .Value("de", "Zahlungsart"); + + builder.AddOrUpdate("Admin.Orders.Fields.PaymentMethod.Hint") + .Value("de", "Die Zahlungsart fr diese Transaktion"); + + builder.AddOrUpdate("Admin.System.Warnings.PaymentMethods.NoActive") + .Value("de", "Es existieren keine aktiven Zahlungsarten."); + + builder.AddOrUpdate("Admin.System.Warnings.PaymentMethods.OK") + .Value("de", "Die Zahlungsarten sind OK."); + + builder.AddOrUpdate("Checkout.NoPaymentMethods") + .Value("de", "Es sind keine Zahlungsarten verfgbar."); + + builder.AddOrUpdate("Checkout.PaymentMethod") + .Value("de", "Zahlungsarten"); + + builder.AddOrUpdate("Order.PaymentMethod") + .Value("de", "Zahlungsart"); + + builder.AddOrUpdate("Admin.Configuration.Payment.CannotActivatePaymentMethod") + .Value("de", "Das Plugin erlaubt keine Aktivierung dieser Zahlungsart."); + } } } diff --git a/src/Plugins/SmartStore.AmazonPay/Localization/resources.de-de.xml b/src/Plugins/SmartStore.AmazonPay/Localization/resources.de-de.xml index 3c5dce6dd0..da4712b22d 100644 --- a/src/Plugins/SmartStore.AmazonPay/Localization/resources.de-de.xml +++ b/src/Plugins/SmartStore.AmazonPay/Localization/resources.de-de.xml @@ -28,13 +28,13 @@ Textvorschläge:
    Es wurde keine Auftrags-Referenz-ID durch Amazon übermittelt! - Zahlungsmethode "Bezahlen mit Amazon" ist für Shop "{0}" nicht verfügbar. + Die Zahlungsart "Bezahlen mit Amazon" ist für Shop "{0}" nicht verfügbar. Fehlender Checkout-Sitzungsstatus für "Bezahlen mit Amazon". Ihre Zahlung kann leider nicht bearbeitet werden. Bitte gehen Sie zurück in den Warenkorb und Durchlaufen Sie den Checkout erneut. - Ein Auftrag mit der Zahlungsmethode "Bezahlen mit Amazon" und der Kennung {0} wurde nicht gefunden. + Ein Auftrag mit der Zahlungsart "Bezahlen mit Amazon" und der Kennung {0} wurde nicht gefunden. diff --git a/src/Plugins/SmartStore.PayPal/Localization/resources.de-de.xml b/src/Plugins/SmartStore.PayPal/Localization/resources.de-de.xml index 0b796c2b89..fcb196c6b0 100644 --- a/src/Plugins/SmartStore.PayPal/Localization/resources.de-de.xml +++ b/src/Plugins/SmartStore.PayPal/Localization/resources.de-de.xml @@ -1,10 +1,10 @@  - PayPal Zahlungsmethoden + PayPal Zahlungsarten - Stellt die PayPal-Zahlungsmethoden PayPal Express, PayPal Standard und PayPal Direct zur Verfügung. + Stellt die PayPal-Zahlungsarten PayPal Express, PayPal Standard und PayPal Direct zur Verfügung. From f6301f03a2cb1b0a176cabf32c8a1c26d3fdeb7c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 13 Jul 2015 11:29:00 +0200 Subject: [PATCH 0236/1256] Payment pre-processing should not output unlocalized messages --- .../Migrations/201506181858349_AclRecordCustomerRole.cs | 4 ++++ .../SmartStore.Services/Orders/OrderProcessingService.cs | 9 +++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs index 2641ef6b47..9723bf49da 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs @@ -30,6 +30,10 @@ public void Seed(SmartObjectContext context) public void MigrateLocaleResources(LocaleResourcesBuilder builder) { + builder.AddOrUpdate("Common.Error.PreProcessPayment", + "Unfortunately the selected payment method caused an error. Please correct your entries, try it again or select another payment method.", + "Die gewhlte Zahlungsart verursachte leider einen Fehler. Bitte korrigieren Sie Ihre Eingaben, versuchen Sie es erneut oder whlen Sie eine andere Zahlungsart."); + builder.AddOrUpdate("Admin.Configuration.Category.Acl.AssignToSubCategoriesAndProducts", "Transfer this ACL configuration to children", "Diese Konfiguration fr Kindelemente bernehmen"); diff --git a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs index a1b07c3749..0c2a0176b3 100644 --- a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs +++ b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs @@ -808,12 +808,9 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR if (!preProcessPaymentResult.Success) { - foreach (var paymentError in preProcessPaymentResult.Errors) - { - result.AddError(string.Format("Payment error: {0}", paymentError)); - } - - throw new SmartException("Error while pre-processing the payment"); + result.Errors.AddRange(preProcessPaymentResult.Errors); + result.Errors.Add(T("Common.Error.PreProcessPayment")); + return result; } Address billingAddress = null; From cb13b148b753d1e92b80a9748f40eb140548475f Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 13 Jul 2015 11:33:50 +0200 Subject: [PATCH 0237/1256] Updated changelog --- changelog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 2d8240fc1c..daf03d0e7f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,10 +1,11 @@ -# Release Notes +# Release Notes ## SmartStore.NET 2.2.2 ### New Features * #210 Implement multi-store support for import/export * Added zip code to shipping by weight computation method +* Skrill payment plugin ### Improvements * (Soft) deletion of SEO slug supporting entities now also deletes the corresponding url records From 9a89768c69df96a87d5a9f619b5ea94e47074e7c Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 13 Jul 2015 14:21:15 +0200 Subject: [PATCH 0238/1256] Weight adjustments of attributes weren't applied in shopping cart overview --- changelog.md | 1 + .../SmartStore.Web/Controllers/ShoppingCartController.cs | 7 +++++++ .../SmartStore.Web/Views/Checkout/ShippingAddress.cshtml | 4 ++-- .../SmartStore.Web/Views/Product/_Attributes.Mobile.cshtml | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index daf03d0e7f..eedc045a1d 100644 --- a/changelog.md +++ b/changelog.md @@ -23,6 +23,7 @@ * #691 Product quantity not added to cart on mobile theme * #186 Mobile: variant images do not refresh * #671 Bundle products: display base price according to applied discount +* Weight adjustment of attributes weren't applied in shopping cart overview ## SmartStore.NET 2.2.1 diff --git a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs index 9229462276..ea2abd62de 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs @@ -271,6 +271,13 @@ private ShoppingCartModel.ShoppingCartItemModel PrepareShoppingCartItemModel(Org else { model.AttributeInfo = _productAttributeFormatter.FormatAttributes(product, item.AttributesXml); + + var selectedAttributeValues = _productAttributeParser.ParseProductVariantAttributeValues(item.AttributesXml).ToList(); + if (selectedAttributeValues != null) + { + foreach (var attributeValue in selectedAttributeValues) + model.Weight = decimal.Add(model.Weight, attributeValue.WeightAdjustment); + } } if (product.DisplayDeliveryTimeAccordingToStock(_catalogSettings)) diff --git a/src/Presentation/SmartStore.Web/Views/Checkout/ShippingAddress.cshtml b/src/Presentation/SmartStore.Web/Views/Checkout/ShippingAddress.cshtml index 1d7d4e6552..e003882015 100644 --- a/src/Presentation/SmartStore.Web/Views/Checkout/ShippingAddress.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Checkout/ShippingAddress.cshtml @@ -45,8 +45,8 @@ @item.PhoneNumber
} - @if (item.FaxEnabled) - { + @if (item.FaxEnabled && !String.IsNullOrEmpty(item.FaxNumber)) +{
@T("Address.Fields.FaxNumber"): @item.FaxNumber diff --git a/src/Presentation/SmartStore.Web/Views/Product/_Attributes.Mobile.cshtml b/src/Presentation/SmartStore.Web/Views/Product/_Attributes.Mobile.cshtml index 1f759cc15d..c7b07caebf 100644 --- a/src/Presentation/SmartStore.Web/Views/Product/_Attributes.Mobile.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Product/_Attributes.Mobile.cshtml @@ -51,7 +51,7 @@ } @foreach (var pvaValue in attribute.Values) { - + } } From e3d8592be3a8424ca5896e729ffd3c57faa2c765 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 13 Jul 2015 15:52:23 +0200 Subject: [PATCH 0239/1256] Added link to imprint and disclaimer to footer in mobile theme --- changelog.md | 5 +++-- .../Views/Common/InfoBlock.Mobile.cshtml | 12 +++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/changelog.md b/changelog.md index eedc045a1d..fafe3b82cf 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,4 @@ -# Release Notes +# Release Notes ## SmartStore.NET 2.2.2 @@ -11,7 +11,8 @@ * (Soft) deletion of SEO slug supporting entities now also deletes the corresponding url records * License checker now supports IDN mapping for domain names * #716 Supporting of paged google-product data query for SQL-Server Compact Edition -* #648 Add hint for * at mandatory form fields at address creation +* #648 Add hint for * at mandatory form fields at address creation +* Added link to imprint and disclaimer to footer in mobile theme ### Bugfixes * #694 Product variant attribute in product page should not be preselected implicitly diff --git a/src/Presentation/SmartStore.Web/Views/Common/InfoBlock.Mobile.cshtml b/src/Presentation/SmartStore.Web/Views/Common/InfoBlock.Mobile.cshtml index 118f1f892d..3eb5680b4e 100644 --- a/src/Presentation/SmartStore.Web/Views/Common/InfoBlock.Mobile.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Common/InfoBlock.Mobile.cshtml @@ -19,7 +19,7 @@ @@ -30,13 +30,19 @@
  • @T("ConditionsOfUse")
  • + @if (Model.AllowPrivateMessages) { - + } -@Html.Widget("mobile_infoblock_after") \ No newline at end of file +@Html.Widget("mobile_infoblock_after") From aea09827418dcf5cd59dd6222e0f04bf7d9b2f2d Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 13 Jul 2015 20:42:35 +0200 Subject: [PATCH 0240/1256] Changed some string resources --- .../201506181858349_AclRecordCustomerRole.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs index 7b37421da7..9126926fe2 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs @@ -99,6 +99,26 @@ before you can assign them to all subcategories and products.
    builder.AddOrUpdate("Admin.Configuration.Payment.CannotActivatePaymentMethod") .Value("de", "Das Plugin erlaubt keine Aktivierung dieser Zahlungsart."); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.Fields.SupportCapture", + "Supports capture", + "Buchung mglich"); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.Fields.SupportPartiallyRefund", + "Supports partial refund", + "Teilerstattung mglich"); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.Fields.SupportRefund", + "Supports refund", + "Erstattung mglich"); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.Fields.SupportVoid", + "Supports void", + "Stornierung mglich"); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.Fields.RecurringPaymentType", + "Recurring payments", + "Wiederkehrende Zahlungen"); } } } From af28c9bc56b68f800c0f64c2f485c312bdb3c812 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 14 Jul 2015 00:46:19 +0200 Subject: [PATCH 0241/1256] Solution did not compile: Included missing files and code. Re-created QueuedEmailAttachments migration. --- .../EmailAttachmentStorageLocation.cs | 21 +++ .../Domain/Messages/QueuedEmail.cs | 12 ++ .../Domain/Messages/QueuedEmailAttachment.cs | 7 +- .../SmartStore.Core/Plugins/ILicensable.cs | 11 -- .../SmartStore.Core/SmartStore.Core.csproj | 2 + .../Messages/QueuedEmailAttachmentMap.cs | 29 ++++ ...2241575_QueuedEmailAttachments.Designer.cs | 29 ++++ ...201507132241575_QueuedEmailAttachments.cs} | 9 +- ...01507132241575_QueuedEmailAttachments.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 8 ++ .../Controllers/EmailAccountController.cs | 4 +- 11 files changed, 235 insertions(+), 23 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs delete mode 100644 src/Libraries/SmartStore.Core/Plugins/ILicensable.cs create mode 100644 src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.Designer.cs rename src/Libraries/SmartStore.Data/Migrations/{201506262044329_QueuedEmailAttachments.cs => 201507132241575_QueuedEmailAttachments.cs} (98%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.resx diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs b/src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs new file mode 100644 index 0000000000..34d369c1cf --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/Messages/EmailAttachmentStorageLocation.cs @@ -0,0 +1,21 @@ + +namespace SmartStore.Core.Domain.Messages +{ + public enum EmailAttachmentStorageLocation + { + /// + /// Attachment is embedded as Blob + /// + Blob, + + /// + /// Attachment is a reference to + /// + FileReference, + + /// + /// Attachment is located on disk (physical or virtual path) + /// + Path + } +} diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs index 573231b382..d3f7e63b93 100644 --- a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs +++ b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmail.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace SmartStore.Core.Domain.Messages { @@ -7,6 +8,8 @@ namespace SmartStore.Core.Domain.Messages ///
    public partial class QueuedEmail : BaseEntity { + private ICollection _attachments; + /// /// Gets or sets the priority /// @@ -91,5 +94,14 @@ public partial class QueuedEmail : BaseEntity /// Gets the email account ///
    public virtual EmailAccount EmailAccount { get; set; } + + /// + /// Gets or sets the collection of attachments + /// + public virtual ICollection Attachments + { + get { return _attachments ?? (_attachments = new HashSet()); } + protected set { _attachments = value; } + } } } diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs index 6f131b0a41..cd6d436139 100644 --- a/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs +++ b/src/Libraries/SmartStore.Core/Domain/Messages/QueuedEmailAttachment.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using SmartStore.Core.Domain.Media; +using SmartStore.Core.Domain.Media; namespace SmartStore.Core.Domain.Messages { diff --git a/src/Libraries/SmartStore.Core/Plugins/ILicensable.cs b/src/Libraries/SmartStore.Core/Plugins/ILicensable.cs deleted file mode 100644 index b2c4b60eb8..0000000000 --- a/src/Libraries/SmartStore.Core/Plugins/ILicensable.cs +++ /dev/null @@ -1,11 +0,0 @@ - -namespace SmartStore.Core.Plugins -{ - /// - /// Marks a plugin as a licensed piece of code where the user has to enter a license key that has to be activated. - /// Note that a license key is only valid for the IP address that activated the key. - /// - public interface ILicensable - { - } -} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index c1e2d2bae1..f4d3363c1d 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -158,6 +158,8 @@ + + diff --git a/src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs b/src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs new file mode 100644 index 0000000000..1ed9e206e3 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Mapping/Messages/QueuedEmailAttachmentMap.cs @@ -0,0 +1,29 @@ +using System.Data.Entity.ModelConfiguration; +using SmartStore.Core.Domain.Messages; + +namespace SmartStore.Data.Mapping.Messages +{ + public class QueuedEmailAttachmentMap : EntityTypeConfiguration + { + public QueuedEmailAttachmentMap() + { + this.ToTable("QueuedEmailAttachment"); + this.HasKey(x => x.Id); + + this.Property(x => x.Path).IsOptional().HasMaxLength(1000); + this.Property(x => x.Data).IsMaxLength(); + this.HasOptional(x => x.File) + .WithMany() + .HasForeignKey(x => x.FileId) + .WillCascadeOnDelete(true); + + this.Property(x => x.Name).IsRequired().HasMaxLength(200); + this.Property(x => x.MimeType).IsRequired().HasMaxLength(200); + + this.HasRequired(x => x.QueuedEmail) + .WithMany(qe => qe.Attachments) + .HasForeignKey(x => x.QueuedEmailId) + .WillCascadeOnDelete(true); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.Designer.cs new file mode 100644 index 0000000000..c4e3a3c11d --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class QueuedEmailAttachments : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(QueuedEmailAttachments)); + + string IMigrationMetadata.Id + { + get { return "201507132241575_QueuedEmailAttachments"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs b/src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.cs similarity index 98% rename from src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs rename to src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.cs index 225aaf9d43..cf40d1a76d 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506262044329_QueuedEmailAttachments.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.cs @@ -1,6 +1,5 @@ namespace SmartStore.Data.Migrations { - using System; using System.Data.Entity.Migrations; using SmartStore.Core.Domain.Tasks; using SmartStore.Data.Setup; @@ -26,7 +25,8 @@ public override void Up() .ForeignKey("dbo.Download", t => t.FileId, cascadeDelete: true) .ForeignKey("dbo.QueuedEmail", t => t.QueuedEmailId, cascadeDelete: true) .Index(t => t.QueuedEmailId) - .Index(t => t.FileId); + .Index(t => t.FileId); + } public override void Down() @@ -46,7 +46,7 @@ public bool RollbackOnFailure public void Seed(SmartObjectContext context) { context.MigrateLocaleResources(MigrateLocaleResources); - + context.Set().AddOrUpdate(x => x.Type, new ScheduleTask { @@ -61,7 +61,6 @@ public void Seed(SmartObjectContext context) context.SaveChanges(); } - public void MigrateLocaleResources(LocaleResourcesBuilder builder) { builder.AddOrUpdate("Admin.Configuration.Settings.GeneralCommon.AttachOrderPdfToOrderPlacedEmail", @@ -104,5 +103,5 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "order-{0}.pdf", "bestellung-{0}.pdf"); } - } + } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.resx b/src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.resx new file mode 100644 index 0000000000..4bcdc56bda --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507132241575_QueuedEmailAttachments.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + H4sIAAAAAAAEAOy92XIcObIo+D5m8w8yPd07dq5UUneZ9W2rmmskRUq0o4VNUtI554UGRoLMaEZGZMXCpcfmy+ZhPml+YQDEktj3iMjMyhcpGXA4AIe7w+FwOP6//+f//e1/Pa+yV4+wrNIi//31uze/vH4F86RYpPn976+b+u5//O31//o///f/7bfTxer51Y8e7i8YDtXMq99fL+t6/fe3b6tkCVegerNKk7Koirv6TVKs3oJF8fb9L7/8z7fv3r2FCMVrhOvVq98um7xOV5D8gf48KfIErusGZF+KBcyq7jsquSJYX30FK1itQQJ/f321AmV9VRclfPMB1OD1q6MsBagbVzC7e/0K5HlRgxp18u/fK3hVl0V+f7VGH0B2/bKGCO4OZBXsOv/3DbjtOH55j8fxdlOxR5U0VV2sHBG++0tHmLd8dS/yvh4Ih0h3ikhcv+BRE/L9/vofDSCfvudp/foV3+DfT7ISAzMUPiFkRmBp/uZDWsIEfX15QyP6t1cc+L8NXPL+zfs3v7z55d9enTRZ3ZTw9xw2dQmyf3t10dxmafLv8OW6eID573mTZXTXUedRGfMBfbooizUs65dLeNcN6Hzx+tVbtt5bvuJQjarTDvM8r//y/vWrr6hxcJvBgTMokpBRfYQ5LEENFxegrmGZYxyQjF9onWsL/9u3hlgRidTrV1/A82eY39fL31//imToLH2Gi/5D1wFEViSAqE5dNlDSQX2jH2CVlOm65aHQtg1NpdU6Ay+fiwRkEQZq1di3cgFL0xTqMZ1XH+AdQDzZozkuigyC3IDot7cbiTLIGWzg4hQJTXZU1yBZrhC7eAjcF1hV4B5Wb6QID4KnbosimLlZPSrcEzQJmMcZkUKrzRtuRgRQx6bQMJcaKXr3yy8x5OgszaBAFIPokXW2k5U0B+UL0zH0U96vIO343nK0jkT+gswO3OYELX8Fj+k9YQXJFLx+dQkzUlgt03XHUFJBv2nBz8pidVlkKv1CoG6uiqZM8NgKI+g1KO9hbd9pCpVD35lapiFQXy1HQteQDchaZ38onvKsAAsvNb1IwZsewUEta/RIR6OPTTq02v52FGJk2ve4vpeZ2zKu7haFSqIVlFrOzYrp2urVaGylinZSNZoMg4aLMxasRnK9Eo/T0OkzGlOlN2jjtHRefYVP45uFkYzBg65Rt3VRpkVJ4EKsP7xiaTc2o9gouFXj3jGGLXhdTD+462KSoV3CdfYSZXxW7UwyppOT0Zs4TpLR27hqbv8Jk3r8rc5xsXgZfck4KSFWUN/y7/VAOrRhgtfpyl04rvDaXaawCty0IjSKDhlWWmJfJ0nR5HXwzhnmiy8gb0CWvTibaMptyMb4r6bYhvSbCvttSL9xsR0QTXLTiG5YYOlAGBjdNooFDNo9sd3yt21oPAfjxiCmOg/Gr7+O4lpuXbAmx41l4/q2PhWVboUYaYQXRVmHaT20NS0Nm6Kx+g6q6qkoF9O3fJpj4KsqeCeO9/Wtax6tqkQWUK2RtmMX4AXr7i+wXhY+bp+ufvWGQXTQWjoGpQh19VLV0LTL+autHejKsM9J1izg4oRMOizx2ni+qEa3fId28QJXvuibfB/HCO7bvEIWxRq10ZJ/itF2oyQdwBJAfFPPwXbllzRPV82KHAQerVqTo7NyYZKuANJCFyX61UU0/O31qyt8Pom4yYgZPI+EucV2CStE66T2pYW9biuLRZPUx02+QIyN5AzZqmV629TwLM1qfH7qrO5OQA2y4v6NCfVBAarb2hAtVAYGokdD9ANkTTC28wrJB9q0oN09XMTb823oJt0gmVjyhq6/2TM5VBO2US51g3ZWQkMxRfcgq+q2OmKFSkRL7EjI+rirMCxoF5fEXNt6fBcQiUheo4186DbAbBXG8EIu0V7PLlgq2nEZYsFBUTjuayQ75HQBr5fN6jannAG+yH6gib/NgmeOKIdq6aH8R4v2iuqf/b5eBCDTOTXp1UPu2ZxgmeO9nT5LpNui3rVgN+Abro5mkCyoef3m4F2DY9yGYTUA+67rOu1qaISbFwejQqMeWxLh5kJtgQtQojY/lkWzRh2JY190i8B5vkgf04Xfwc04S7nr0dPkazvq35TtHS1WaX5SrNrI4pEb67kWrtCSHL7lRJPz9C3/VKzgRQRb8QusARJx7PjWebTi2Iy4sSmnGbd3ndba4Po4IzvKsuJpcIfCxxQ+BRuoR+t1WTzCxSXSnfn9VbMK45uvRR0ZY4/uGqn3jBt0cB/jIe3iJa6LoyTYzv+crtIad46sZMFTfPXQjC90IG/uQIINhhKtevVXtOXZbApGa/YjYrHRGzmvPqZ39QkogzdMPZ4YtsUl/KNJS/itXiKKt8o/mFM6nBtTRaetI8X/HDXYkq3TBFsyR4sF14fgMZ1Xm7DxOCHIoTP3Pc9aAe8RBo8RzUorcN/uBJye/qcOzenzOi2JWf0BvPA47VAcJXX6SFDEYPtPoLoCyMaBsWaVxeZ46Qb1BscSHN2XENJmXsDZ+gbZNXwe3248ry5h0pQt9lDt0SE6eUky2HYqVMfRGC9gmRbB0jfgJGs/QRwoK+cVPrZt4yuC2fG8OkPT358DB1t3i0WKJQ9kPcaTJXZA2LuVnbt/DZ5Pn9EuJFgWzqvTKpicqDcnaDt0X+CD/MAjbZCjrdB5/ohEE6Hrj+iDby4mD9GODLA3lmA8egQpqptmFNZAL6+0p94LVppHHPnn4qkdNV5pELbQSUEbhPTuhWzfz4qy7+MxRLuvwIMmkDwU2FuOMygEnwrj3SDGeN7SEu1Ahk1vsEVBfPpdEEecSWoxtsEbcTASAsBFh4yKxx7PWEWygDt43LwcN3W9cS4EyBaG/plWyyyt6jhIO+HPIGJepNeZ4xlfnCfIOifo0iT8/IlGEn0F+pYtxm2g25icULGv0du4WiM8IHMciD3Oqxrt0fszMY8rCDSu03wRgKl3Z53m+EwtCn91aovBDEdmik6xTdom2nxcp7CVyWCFj9ZQWNXD0eFJsbpN8+4ULSIToj73oQjV0XqdpeEW80+Y3i/HE0V2HxMd/c90MSL2T+PSZlhpQvXJgChMmcQLSIgXIwEz6BNnt70BEuIA00dYvuDKjt4TOkWVY9VjUMFu9Ymy7R7wfYGgakrYpt/SxF7HuPnYtxk3jHlAi3+wqO1IS4IWyImWwQMVx73eBXXAEsdJxHJ8MEgxNWLjvFoWrT8FlO6eDnWMUbskDkukNFalL73poK+Lja98E6yihhIiiDSgrgFDtDbQBdrcsIBCjA1TrgqvYYE8w4E2MTqWEV3+AU7GyC1FQJTjiDqHF9kQqwfUu8U0gU48iGoAApxnx+lDRG3faUBN/2VgqjFIYT3HcZESPNohdDCa3nMQqo7zYJ59Hg7B1V1uQTQ9ZgFUHeagPPtLdqB3aZvFjY7XVfdfXkUzHn0F1fgMtTzHew3utYO7YeBEfUoVK9UpDeOpTX+AMkVGnWwfqe2+pp5mgixqqWbJpqrnVPGonQbuMFrXIXqPi81Jq+FBFlBkQrpcyYUMkCsb8mfDms7yoGJ3WQhlhzkw1y7TPhxJd4diGWcIhQIviBCy2bdPwTfcS/FITdwZtcOvQxSyui1DTO5IiTf7mYkRqfG9wnulSLeN1PeXoju1+qZcd+XOJ7+dy8wnA1DrJfOo2UVXVSdFs8YXnBfBMyNikh+/xTl9IzND4iOJlIXy6AYTJp5rHIhpG39dGLZi4sabrqDby2/ghGVJC+y6OElcDGN4JMxjEJwX1h6JDlXH+eqkVEOb8hqSccgA1UORQgddB+r33QH3gXoUh6VY3ZZhKR7pegy+rRKpZZMDf7q7EsdFjfh00ks4+OGR0VemXoxiXb85XJiJMrL2/l2sAMDO0+Z4UoXvT12l/4JhbTNXf6rros3fweP2jsjp8Hxjg8cC9h0WEUCXIL/XxmxFSyEQ8SbbCPELW3xzaNtOwfcy4YBAKpJb70cKn77oN1We2jj24aPHlsV8ACnZ31h7YVs1Le395qSqB9r0mC8TLHkBIOwuf98Dz7csuvoHw12jvloSjfWMg8UrNX8d5+Y8LCyedfhLpMuPzo8txD4hFUVVDmE8IeXk2k9sGZzhmTgOYjxVli+V+T6dDeK1ZHlLg+K4SiU0jhIcN7bB1NcYyXMk/rcop1gUvoMUa+UmyosFErJfNhm0SlUcx39xtYajnw4dp1mGowv7HMSBtwz7y59x0PUpcomhzmRndvKMbNAMGl7nDogzeVSjdKbrKRvuZ8PsbYndcucXcJyn02ekqOjnJSfYi27iDMY7qVHuQrXnOn5rDxPtGvCqM43osNqo2zIsBOO86nxSZEX5CT6TNM2Tt74TDz277rMiHHFymA5So24r0k4r1oHLeXUGAZ6I3kCY0X+sXKk2HGoRa78BVgfbDz8UmyIRcIQtnM/tAFN/o+ziLsRw/XDdQGM76IfR9QNN7j+FjmC51fJeC1tJf7mF+UMhh+oKI+iPkBs6Nv2PoksiKZGD9tjmOKpJI1soTjiEAm1XKNAheGcHg3cO8Sy7F8/idcrFLu7iGZesXDAUpEAxdhvtldXwfUaLJ5qN8ApneOjaJ9EtnYoh79bl9espbHmT9o7lwsaEmyQhapu2PIwon2C2vmuy/4QVSTIaBdnXwgdXiA3vet9bYbcrboU7drTF0tEih1WFZNWU4kCoc8PJs2JEyhr6K+3qakFnB71U+6if3uYYfh32J+q2ehp9bNKh1fa3RxZnQ3BWpHyUpjfGIzVj8Wp1pFdMuobOinIFwiN+OmxXIBt/3Zj0tZeIaZaP7u7SLI2wUSXZd4N3M5Es6/OqDQg5SphnFL1j9G2iS+I8yPwZVPX5+mixQPud8WMDou4bcNc/F/dp7nk5GdfvczgrUfhfym1JqjAZeuV/Q4FRseFCqRgdLoK4mjpd0M8w97pu8rCSvrIg6g5zcK695ncdum53MDcbm0bsNw8jGF1KQNebAnTskoHcHKiE2gyEmtgsmCutT5+xSQOyo6ZeYqOmTTJ0CZPWOygZga6GdBqsKghzYlfLdYKQGdCsLopKcRdlKJYORCwVei0B8eridbFOE00fSbm6k2yxvJccjGs3iYtJ3kNSJO0cWyL0iyt27dIlRLuMHMdYQdUEMyDSLsohhK4qwNy7/ATKxUWR5nX1Ka1q1bG/BE7RezWcZAwaYNeR9DGIVmuNACxRfxyMWgHygM4ZnqjEm+qsjTyUlPxKIIH2asigrf1AUPedPdpoFPmbDsFhV69u6ywtq3qSuHBsvk7SkGnXH2lrUKzWIH+ZoB15ULphR4a4AydKfUzzxPVU74R6emREfwARzXdTNfR+9Ib+K11jWwlkhmRPkVxByyKHxmckI70M3L+ft+X7bfVOppUh6VLYL7QDzGYB5IqERZsvd16raSHVdo6DFLvIACg7ykKFJVfqyRUQrd/hOCzP6rYMC6Zteh6fiIyqc3wEe1AJsliZ66+fis8QE/G8KgyK9n0EhXS9LCG0bfAvERpEihaWacI1Fvjo8g8Q7OKNFxsSLagjNPpFs4/l76INt+Ckeyka5mZTuVVvXOIPM7Rkd2Ws4ry/pRcCxbCYtUKyOkoBxM5LoYK2hSw9PFagHgE3dYd1SKOW9j44NZ5eOr/PEa3bl2SDY/JOn5OsWSBZZy4S606+4pyzdZJKmsciQE4Tnt3PnC2ULKUnp1CvvHHsoJH91BVruwfYywymg7YyMm/wQ7fzGN+3tyV8TIFB68XJzLkNZp3Xtt3TPBGEX2vEBAWkDQe+EeLSOlwHmdfIfEeq4BtzFsElcW4KnOMUmYj19ur5Q2M0QfwACNVZmjJSwkusj7PifohfcxZpXLt6Q+HYjij3rjOTRI7jwWMHeTwTsscoZSmK1jcbwA07ycoFVpICBbNR25UAHsIIDmuBuq3PIL9vwH1wzGas2xuu2a2KRYwDOK9reC2zB29b+5Wtw3cieWbV1Rgv6vhI2+fgRlZ88zxlc7gYu41XLEc64KTWKbkXxWs15H252iXTtqu9blZ2k2DdQLF9ZAqlyzULEbRWbzrhvFaTNFPpvwjwmx7PYclWtzWPr6WfmY7q2i3fGO2j2n808ApOcZR5loH78xUaLE6ObbyrEeOqaL2/DzaM4O1qM9O1k3EJK6La5MpcBinVmFpAQb3roYOO7GSog7WqBOdBw5p1XYT0toTWBhUy0hOcfeumJJIjbZLOKyxdF1lzn+aCEjFeSiyaRKZ8ophOkZQCb1LZqRAvpXChuB0eK5EEhXI7vG1M70LF8CeougHGC3y5YO//T5k6QJsdwZxxwIsBv8Knyt+li2u/oVBsB4/1Ht1J8o5M6T7GlMZ3S+K5j3uMUkanJvZmA7hha1m5wMRSoGCWbbviz6+4/sFQUre1497jq2VRxhBHx2bPiOqautVoO7p5nLR/Rp/7VnlUD07zKCPz27IMS6JsmyIUSldXFsL1Ag61Pss9LV5WAO9X0ZoKfjunIst+FDXZkiUk8ZCzNYBRVG94RNthw+JeHeXVk0cwj3prM+CU72s4QtzQ8NRmRg0m7mA0sGH7ZqprAfPeojgYgno+HDmGdCSzqL2u+e0O8d9mhd2iB/0KrCIUYtiJSAvDih5VJBU3utw5kSInrorUieF6QkiSaKFTvPVEkIY46AZ1W7E2ifPohzZhW2fpjn9XPdomLepj9WTz9ZGk17kusKbcnquN8+xGR7tQqd0FEG0t2wEwBVJ972/5b3SsWs9bLkQyfS5bqIIuE2DUUW4SYEQHva5uy3Sq+euvozjPSgij3ZCPlfoUIeo0GsbDTYFBtUZJdtpnKW2ZP3DpsElRaju71loGlqu0qgw5CHkodTZFPaSoifTgYcYlh9vnGjZMmhJhFQhw0E/e+mlUe3Ee3bh5FHD0lgNSoUYTYsHOsZN5LyHWpSUNsjZ0iA/SreH1SJcYp0mB189yO7q7dIIEYX2TnWEyYcvfMC8T7pumqaMkgVU1TYMX+AI02rRaqfnYb5lrL4aOlJ+ZV7JuWZ29dO2QTNlDsZK61Sah80GFqtsimaCDn2iOpIcjRUa57psuzFfY46SP2PmL58450nnNoUmjbtvBTQJzQxdpQFknqUzo6m5SQOH6rOtMkEIjOA4aTd0WodLWaDQ8WxhBKKIuOaEuFsXyFpL72Wj3ZkJI93+k8CkQBU6I7ZUQQYEn1hT3+Fq963aEsB8LgtuDFFJdq3i0wmlNMHWwA5L2jvzUda0FCF8CArX/QfGr2yIE+lgWzXrkU+aR7mpNGdz4dfPMTBChoiwOWING2Yfs4xLx53rVeSPDam1+QwNx2pwqk2tzGiBcm3edCFLpBMdBr2uUzN5r472U8amiZVpZClcX0ofSZPrES110c+usKdqn1tr/DkpC3RYh0ETPrpC2gt91JgPeFj8F+2pnsLOCfZXN8UElQl6cabaJ1pE42C7AC76VEhVZm0Z7zJMkBcecNGUJ8+RlkueX+sYuwSZs9ANM0hXIXr+6KNEvosVev/vb61dXOIPC76//5i0LbCBW6Dz9APWUauWqua2RSszO8yS7xmitiPVX52ExjeG09VM0do0bQ3NDXtGeaoRMo9OMtNM604ywa2zSkaGGHETZvTFGOaJVJMUmAsjOIBybpuqWxyawuuWxqd3hHz+1J+Gh0Zm0l/VxWyFqZbQmkOHd5Au4OFqNOhL6FeCfsISI7SKkV1/C5KFo6qMa8dFtU8Mpt9JC49V/rCZ43bQzPWJdczq6u0uzFMlktP3BenQakPtBeFODXzYuIdJfJ4i3WNvJm6UQJjqqfryJxF2exAwXaDNeIgNQPcCFakpGHeHJ4+P4L8nihk6f12lJHAlfirxeTtzmf0IwPj1p+WofOfoAb9PgaysUqqOErJufimwxAX+IDU/EmFTDxyB/mGQDzLU5iYqh2zw/mbK54X2h6Zo8vwUTGBfdakoMwCEV3thy36ANQdmlcb0uQV6BBP/cmAaTNz2JyKgav4RVk41P9hOwxo70aQkuNjrRaK+a28FGn3bIF02ZLEEFp3TgX4DU99I3/5rq2PPSNYf350jhrJv2tGRyr/EHmMF6r17e0uyELyE+eqPuFlsdW3wC1Vf41Hlxvhb4nk3CvEoYftTJntJIjzyJGN3wgJtjT1m5ECkhBXKNydPGDbYtyEIG2RJF17wDBXvf0PcK7dI/pVVdKB5MlAHedIe4m86qoYTjZA2o65sgH9M7spEzDkIGePO9goufab0UBmOGFgZlUcV1cKQWzvmm4W+SEk7oP1ckdJYv9+rZ1zZFlKpnuFjRs02RvGdUuWvPLuECwhVc0ErsVPkWKA1lZAojsDAYcw3n59dR39VJB/tSkexsifSheKrYp1drK20sQPLajgNQKD0eKih8Ta4IPV5bbtFUUoV5CFhRtzUcgwZ6eFutFuomHuedrc1JjO0Ku6lhWGT7j4Ks6KFd7YVOp4xhIFh1nNVcXpIutxZ8A9Fk2A5irm6rp1eohDIraAxkzIsw0Q8WR1IoPTXtrd1NDYOh238U5FIP7apQOENrCqPdakBymy5I4YQrmYNiUbfV+80orSB77sNOO8UIlBs5VOG86jtLsqWBCN6oHuFJ0awncmpfImKsU+wgmsJrN7Q2TYKbK5jjfewUI2ubmmZYX9Bmi8qfOlo759WGO4j7cG5/60gOKPcl2crtJCzgtqORa1LteG5UdcQRKUCVq7IKPmhJpnoYdAPl8BaSzWYcESn4dkgUO/+iffwtFM0/GtCNPmjTkaf1RZkmo4fwDg2NHrE7xWgmGcnYEca9b6O1EccmGdva2LSbJcx12vDWD8VTnhVgEeE5q/OqRxbNjP+MBCSvYI/XcQuEtfVPmN4vHbYuhrt0Tb7IIDKzwPiBDK2CPyF58mLxt9JQOqqqIsFRyYveWJGfekS0klSWn8mqCvfvOhw0So9rJAeR1gZpO6uGbg1Qso51hZqu9RDhduVX8hZEkF2JURzsSnVbUazBr9SbHdNlV+yvYhabYI+t3NMaNIHdwb5U3CQH/17CJjlYD8o6LcF3kEEN30W6at8SPAaOY5CBPIGB27Jq9FtmUznQRtIM2kA2WbSLLKxNByeoDS1w/BOnyAFBNqOJeNzUh/H4PKnRRdQMMUQH/aduK4oNcl2C5AFRfKJAb3JJN+7ujvAM9A0f/wCz9BGWL57VJ7d9rIPreKFXxN65hvypA0FpiJuNDhA7yAAogwBZqKBUTzTKGErp4HQ3SyShU5RIOtkh+jT+cqMwxJQDlbzKpcVzv4LYMb+Ef+A3I/0dBAyagxxo5CBGQrFoQhBruxTn8OkSgqrIz4qy5abp3SAd/0Li9o5yQBDWAf3lKbup7W7Ajp835qoGd3dfiylS1BwtVmluvtr711+iPAjC6LY4eeW26Iqd746aooliLy2DkOw7pWCBm82CGGcnaBEKi6fgMR1WNp38R1jZLkDZ2TeOJ4TteZ5HRXqKY0RYRvNAxgkLmSfFEhJJWCIewmERo3ks4xgdu6CKN8yt2F2wWuqGhqf3GEowyU5DDRv1jrHQkGwtUQKZ++3tkdWd7wqtSI55VTDmLkc59O2QXK2RrPV33Add4HMiBWqQFfdvtHgPy+Po+lxO+G9rNhGI51qBk1edpRkaWIQ32xFfP33Lu2FfUEdL/kmwvBPwe0m5ltVlIm9VQXwM2aqWs29Wwyceo9WjsyWBDosjXbSownYP2qF6K04d2oPedFV4Iz8eNW6YzRgaTE4mxbvuc4s6f74TQWuE6UW5ladtV4GHMgDdq4u2oQeOEZRfdLV3UHh/BtWk417FefH0IiecNQeIbchO7Rrch2/LEJKDaHmL1l8jPVJmWqu1q/LNZioryXJLF6vWUQYmBm/+AGUK8k269pNidZvmINAiNiM/8LK6rauHJgIrG+7e16nuEDROI19A3tyBBE9ieYFm2xh1FqdZR9+04XYT6UgsbD/TRTxkn+JemwIVJJRzjUa2RIt/sKitDnGOqiq9z5EUpYSPzhe6M+h3cY6F+yhB7Nt3PHPqTy7wJVjXm3AVuZIX7EzbyeMlpDKThzjHPsTX+a2pv90RpO15rzNR1UnVKObQrfaaxe+GxSFYArZVVY416/oxT04s2lY7Vi1q+QzW18VKS7HvYFkcTiOmq/oMm6kf46yJbyy+aXiwB0dX6B2aaI7Wa/hco0+r9fjp8XFqnj+atAy/rE7JS16XRRYjLmSm0ytehBzUq6tO9VakPM/5jEfqD7Kt4zpCvbPVYqg8YpLnUesWkNa4UWpeIw209VWOBTckMTwPEReTwypisYocZSkw7J0iaOqZXNyjpX4JtZS6NK+xzSWC9sDt6rYUdAuPo9khITJERxZZUV790YASVpf3t6MPqvUtLf6JJIEO7o8eO9peN52gofMKYUILOUwiJFEKsCE5TEQ1xDBrP6f5Aw70nTOHnau1tT12lqXdaWesea1I1yksO1e49/Iz4DisNTrNFif+M8Ytiz4oGjOdp+s61MsQ9WKAMfQcD1Qq9QPr3rCgG7mWQwiSqwCL6TvdNCHZwwuFmh7q9un2kUKYEX1uzuMvVfvfQV+o25ooVoFr9XupO8UZqdGrKjvNMXywgXQFE8QrcQZhOFYtKu2d2kiHjJ+L+2I41JzNAcmPvV5lx8XiZYq3Vou8RvLSn0d9hfVTUT5MERyAFNMLEeGTpixhnryEe9YJztPnZAnye0geC/VFrVk/lI3IA+7wCG+0tajwOhOwGL9qrOG+QIozYx4ZB64YEgOlHwsLGrSQbrrl8bAbflq7KF/e9EgOK6q6LcOK+usoa1s/MYaHS34dJZuEfbbwv/kuJ58LjCCcrDYblrOiXKFJp+6mjdXe53SVIha7LlprNTjYBgtYtdwmB9AWXXvmx0h022m+QDMb3cJy2958AeRmbuAup8NyUM3qtlryh1pYLZZ5Nk4efhl7H90SriBx+91mPltuUr96w6A5cKO6LUKo0fcYkfjUws+vaeV9nG3qmNx/DJKH85xEaV41t9QRrre/WoHxIBJRJ3g0F3isDDtzZKJWsJ4064kJVtihGivE9EarGpP4pg2g1uOI4remr5tcwxUyp4OCi2ToDopE3dY81tmPFD6hri6nb9l3x2bvPkLTcF+ULxF4mUd14OMDH0/Gx51yj8DGHKYDFx+4eDIuJlORJkFhy8VqVeRveEwHNla3Fcd9hEb0sSya9fRsiVqeQQoNroGRorDHdBUcJdklTAr8arW7xxaHDiB0bwYkB4kbW+LmdNhqY+Ccg3zPF5tDsPDbw8awtYFHlWFrcghhq60AC9phfy9DpLB4M9Q/COA+C+BV1ujOcUdqNVb+hM8gv2/A/Vgr2VWyhIsmg9egevA58UHVqjc0koMsqduKdJPGPVaxyBeBb0ziutN3PVa0Zl2sv+WnZVkEvzf7GZCnOcra46UUXPc0X3jWvGqSBFaVb7v04CcPcji6u0uz1M/bMtStNj8PSkbd1tFiUSI+CY7ihRmMcJPMcxFUvzrfjk5urPbscTNAUXYqXyiaqAJE2PkPBBXiv/69yYCYSwbTgfXVbRnWV9ubo66ry0tVwxWiwxPZikzd/CUm3djRl+M5Mjvm/oDWsbzyC7cQJGVAdhCWg7Dsk7CcFWWzCgxOIjiqNwKqg6xouJai08cmHVpuf88UVkRmMDhtVrFOk10McBL4VxrapIYSzD8NaGDSuvQR0eILMijJ2zS+AsviOUirRlpjxBBiHoolqddFLEyIP/8JE+1bpONcL8Lp9ab3/+BMeyB4D3pedZvZ45ejpl6GO4EohJfIclinVGIXX5wj6VCajRXpSGi1csPC01lHlGCS5CJqWNfI0I3o2PSehlb2fQNk6jkFGbQEECcI+vS58Lnig2rdI3l7Q2E5aH91WxSZcJNbEwRufEV6JB06kmLhyKw4PR5gbgR4+ghZCSY5R1bDRn0vlG5IplRk5dreRlclLRljqBMMf1Ap6rZmdloYPDXvx2nV6+zNIZp8tQbpvY8Do1udqzc9jgPrevPOWEfOxm3KSA3jbDG7tsTyp7UhKQEc3O5EiAKi4Acx5FAdpNFbGkfS5MdJcoqmLOuONaEu2YFtF0LlP1LaqkjyPk0oVzsJSYJfHQpPhxo1ccgVzBf4hiHIspeRNM5X+FR9hlhgAg8wBsUjx3jQPxr9I6VY8IkGYWydUvl1lLRDcaQy6uI95qWDkyVMHoom6KmC9vmpNwKqg9BohGaWqOWdfM/mapmu1xi+uxoZC+95dQ2eT58hRQ1fVAhRf/042pt02/F6TyyrRe0v47WG5jUZOeyNRIdtXGq2dYRXY6wrBr0UI28lohI+PKNhWqp5ioVK2zyq/fD2xEga0F5zTa+z+KMBZ2XnpbMu8WVTzNcX4AWzwKe0woGS/kpLgfCgtdRt8SQLVVpkJrY0ZIsfq1TOFDx0I1beyJltHUHOrCtGlbN4AnaQLA0TvyQZZJ9E95QGjOgClmmxCI/1qkFG8AXeuCO3zLBIxvBLxHJhRroVdJ6ndQqybdZkdBettNgNW0OtuhhAo75ioV1DHJTr/9Rqmd+yOetzL7VMkoan/yLvhhGyeMVLEBwE+I2A8KCe1W3FSR3gdwFegockkJ8v987Q/lxNT5WHR6mM+pmUah9Bsm424Bt9o4YSFKkGNNDUy4g09OlHvdPHsYgOikTd1kWfz/ddmAoY8Lyfx0lr72osi6pCYpGFcxmP6sBn28pnDlZNSBj5IXzcsFbef4aPMAu+qbMsynq49DV1RNoZAo/XuGEztx7SLYwcVqSMxTeII6KC/qm+OIRATA7LEpZTtDXhszqme3Lwj6Z9VizsegR5f+8TqPTZWn1I53cBQBX4rw34jxfofwW7B6g88rrmd+l9U7Y71g7PQeWr25onKnMP06JSsRVeueSe31AYDhzrzbG7mtSaJCPw4Rxcr2r/O7CNRvbJPaZIV0JMHv4kaxbwPL9KUZNg8Lf5R4BdgKrC969QQR0l0KBHODotrtNa+3JlnFYmCYX/AmvQ3YPTmfvxGvsAqVDxCdqbZq4iR+9fwhyp5KPqZ7poD1mCsLVY/qvIx6dD29TPEqw7+1/ou019tNV+YuYtbOTHBV7gIuiXMi1KopWDzpPxwK6BLoOxz1yo1+RmRa3I7ZWVugbJEp/GYXZFm2nsWm8l8rw6y8B9NbTof5lD31K0VR3RBE1u9oJoSM8KOwVf4OoWlr1ezYrb16+Itf7761+E6WJgz9IMEi8A2hDDodI7faX2hZIO9r04Te2E0B+PqqpIUkKYDsc/GtjABUfDG9wdbmin+eJVu1VVV9nsatuZw7thKTTiQkTzdI2ojFjp99f/hzBQq+aGs+FNcx+KpzwrcOoXtoVf3rx595o3xL7lbVjCKxzjgIMZT0CVgIUoWoiYC/ZLN1n4gB1poArxTZrXoqGX5km6Bpn1UDgMlsYi7uHQFl/yAa6xls9r6+mz6QSGl3dkaI8joYliv72luNOaaW/ou3E2LMtUMDCsJ5uyTUiYlOkz18ZWcal0JNPyqHS+bLrAX5qcm1MpYaNZzE3t0YSZTtnSrUrYWSMxW8XN+hHNpnolc2rTF6rabOzdnVdepOR50ZvufyVPy8FljMxCunCwog0J2yqQz8+y+iFMwKf6ebLpQFdlaxizi4awZRr+2d8xGJN7KlhsY/sZkx3CDIzJzpMVY25e+J6FMftDCqOu5AFlzLg5M7FnQwGvvWYkeygesxcjqToxAQup6LoLWu1DWrVm8NEaTQp2A3ajSWGlZCRdJRlT9fAuTKVtQ8JglowbRJpO0l0I01cZjyxDC/ZqPwJN+h/drXpsdVqQRVbLhTJR1yvb/slcQiKceRK91JoV6SbQcVYksulHX39uO+4G8U36CMsXElhksLAYYI0N52G8sahlvEb3c7TlU9eb6awwKZ2tuIqqNzdnDebAsCQZWECooOEwH/tM2YzDMro1OwXlKKbjUuV82XSBTviyFVxquZHl4Ufm0R3ey6rGMAOD7uBuFmf+uwNkU1Qad7QyYBlj0nAuXCnFP8fuVteRCfhKR+dd2OV2TM0Mg+EJg1pSVtRoQV+eMzYp4T9dW1ujF40jmk5BGufTpit0va3ibMsVXVZnIn7e4dVdN46ZGHgHV3mSnDHN77/Aelksbi4hwpbiQNoT7BvQOh/NVWVMzNZy4V+L9mT7KFIY0Rt5VSOjDk3bI2IUeNOjV3ZaBi2lCw3oRBZpC/aUmF+gtSOYQJS1c2S1lWyrzCbE/dPUJmbk4GRsONzatGdAHqs968UzyxV9mIB5FDTdJbZhVY9pmllpictCLG4JI2m1ZHx2kvZnQqaS0tqmfabifAfi/aXXzSMTKg4QQaWH4sPVW4dDcRGzhLHsmNZn7MdpliGrpW/A2E0WPjoVOPT2pBCly4Ma3Y2OzR1qU3/5Cjp6DNdF3MkiNCNbxBRkn9+AMo1iAo1lmi+r9ZDK5DCLvmpTYrWXadD2gvR8k3FKxUPaWjJ+lVVwYVp9gxLO3STN2jbOtRrKBOxrNYc2/aAT083Cw8dZcX9RVLWZbwVIGa/2QC78KSLeKZ5Udn8CPlTOyc7wXvek7c3AODou4YFVHDi8k+vGhAJ6CR+qGHw7+FA1golYUTU/Ns33deb2yF/CxxQ+fYLZ+q7JcmzzMgUm57yhusZPL9T0cNabWlf77bvRbR1Xuw1sOke+5Tw7+PTbirOxP37W7byGK7MhIEDKmLoHcmFiEfFOGQLK7k/Alco52QlDAPe+XzsGxtFxCQ+s4kAPQ0CKXsKHKgbfDj5UjWAiVlTNj03zfZ35DIEiy8xakIGSLutF5nRrnEW4U5pP2vUp1mLZHOyExsM9P8qrJxwFUAiJwlimoOBUfNaCuHIbjVhmGUoYeDt4TdLxibhNMhdWJh6Cn5XXfhQ1cVUlRbm4oThGxx6KOioepMFdOVHVlIIr5ey+HbxpGMpEfGqYO1uebWvNx7mwXKUVztDUjaR3+eOBqs/G9NWk/MvVcOJffWuakyEMMMIJoh2R5ODRzw9nIsbpM85qCbKjpl5iXmwzgHETpKSNVW0ZqXQVXchn14GdOnR0GtIEWtJpjm36M/tx5FlRNividjUyuAgq4+YByoV1Jaid+DRKQI66ExNwlpq4u8NGJA2yJR+xsEpG6hIzO3ISh3wmVpL3YipekhN4d5jphvzbPpmmnWwKUMlGzhxEI5WwD9W3rVszVf2fivEk82HT9KbWNiixlmsslEw75DHUV4tZxXxbyneSrk+r8Jj5sOa7LTC/KH4xW0nUgOObYBRyFfdJ+XpLWFAxhkltOHF+bJonFWZjxfadX8tIYhmwjBW7Jzvs2VCK2D6AOJL9puvFBIyko65N82zNmTnKuB9gwSJy0W76POR9n4zrdnLH0OeZ+o5T+vcveg95xVRcoq2ly1RGV/DJ5yZvUJN6bPu41GooEzCt1Rza9GP2VGXSkbSaz4mfWjGeinvb1iSsK9XZW8q3zCDmYlpm3mw6QSrMu7iTMB09j3JwyuXdNe6Px7s7LKjo+VQrvDgXu8RspnQnAuQIDLeLCU2UvZ+U7XYwecnH9K4+ATggAnV5CSq4+JnWyw0HqdjFUE/Gln0VF640NaNSizLuj3e33bJXE/Ce5TRYcaIUw+yMyRgRAwuZ+EVaS8eUvlajvkEJe6qkYH4dajWUCXlaO4c2/ejrbBcPf6dFzI2RmaqTcTPb6u4YovaDmYuppfNp0xmm4rxm69eihjZ7pA2c0mTFIM4mK4V3d1hT0fOpjFVxLrZ/j3QJn5D4XBQIQdXLj9H3rqskY0MJvAtDapvbKS+9zUgm4Fab+dsJD75sIHaGgLGmtdqT7n9cGvITmKCkRzhhJbk1pycSC6bKmel67ZHDujvLi7zjE8irfB62f3Hp+93umXtWMfEFA61jOldfnLwBWS4/BVdvDwtKhzAhJ0rnyKb9AcG84QV9xl67iBUOOmKwAY85JOldkNWs6slUtrOKxrY8td6CyJVLWDdljl+9gjY3I+TgcnOAgnSznKVN7JjNrBvDJNaybp52wk7edNpS76kqRL+0F1MBOlkmBWn2BJTtWnbc5IsMas9mNHXkVgoL7mapqJtSnx9SYxhtsbDo2SRmiHEqbHqxqTWjicyNxLhsKGuMzoS7uX4YhzEHv+7kKiKMwhRWoaowOqfuYqyFaRBzsOkORl6wufFMHCqFNmZO9E6XuJOMqR3BBFypnaMdYsmrNUzSu+72/1Fdl+ltU0NbFtXX1rCsvKIHCxt6sIMsbTei6Vjcbo53geXlI/m2xn/eKDhSubq745IaGBo0TsaGR3dkPmYrsZxfVAKGO4XF4s8bVp5FKYYtXUi0DO6n2/XknW3J0XbLWtbkoj+/xIWPffYVy4Zv/OWvxTO3FPbL8jW41+SHE2E1cuMhIQxmtQmGiuNlPOtw/gBlCvJ6mJaTYnWb5gTwBklM+gjLl+t0pclr64ZHQzgNCg+aWndIdveSHvhoXljPjk6nF1zn1KZndL25hV83PssNnQWKreD4Hd7fOQxrO0RjB3d6FqP6R4NKEGd8z9MgqaDxbIVoMB2SyAcz8DkXA1lHt4PjZXNq0zO63rbxvu8K4KH2IzD0Pin47dHqe6TK+6GYPXW2COZhcK07ThjjrrH8HN431/l2EIKtcbbxg/sBsmYYocCtjqypReYgJQRPBFHR90ctNiap3VrpsRrwfJJkxR8OUsWjmFu4nLYGtva/jxdtqyz5mc31vbDJb67Aap3BD8VTnhVAndlADh6ZuzjkMrdh38/ReUvelwm5S05pq9MApuZsHHadwhKNOoHMiyNKDpODyzhsgHThMQV6x+dPCJ/NvUbrhzIBi+qnyqYDdL0tYFCTI0KAHIEtd9G9oOz9pEy4uy4EKhy//WnpEVPV06zH6ksPFiuzsr1dYlbLsUy3xJtm0aYnTMUtYmd3Rp6OhX2YN6Ztqe7KLLy3D+pz2KmfpVmNs7ubr6k54LDiSa56EItquuJzrW0Lda95hHPIgpkF7HXyvNfl6qLEhlG6AuXL6XOyBPk9vAQ1PGlK1ETyoo4iNtWUxgzjSk7BwcZWpBuzru/jaGfrPk3AmdazYKetlWi2g0HJH26cyVSJz5Is+pl5UdqZqZlQSnAH7mPqz8Z2xyB5OM9RX5KHq+a2Ssq0jbU13iY2VZSxoKKOC1Mam92pK8a2o5mAt23n08WZtXVcbdqEGepNzNO76FOwHMuMDL2Du7ujJJO8267kYjm4jHkHSBd2VaB3PDiYn1X145iAQ/XztDOnBkd3d2mGvsAbU3IgAVLKkz2QE08KmCd/xE/ZhSk4SUVYm7bnzn5GXq90Mz7VVZQPlPouzpqmZnroe25L0Uz8nbAR0XgfkcR8QawP7uHNWVmsjHynqSN3idLgbg5QdUPTs51FbyZxThqJb9MLut62MN914cp6mxqjMh7VzOxsJ/ZleqYTyW7Th02tGbcQdfqIJudzcX9D/caTqdlHKOvINxMDiNt2Qt2KzIjjOr+F2wrjeCbZWxjnzso2ZKtuBfsaVaUMeCSG3U23o24EE/PmTpqOJ0uYPBQNH24vfFZnybVEIM2aK63rlEPXtnUZUwtj3Drudh3eBBzvOt9WUsBXnjF9edKUiBT3F+CFpPU/z1OM1/SQiqaWPJk5W8Etn7muMfuXRKLYtVadmYArrWbAqh9Uva3hwv7NHIFtbHlEhcCGN70eq7JsXsKtJtGYXym7jm4G9jfNt02X+LqzScPnIgFZ+i+46Pt48xnk9w32BqgYUF1FxvECtAuva5qScPfQ863javM4JuBj87zZdKKvMyPHWmztTFs6x62c7xZuK249zbR725Fd2ym5UYrq1KgGLPsouxUo62+3/4RJjYvgM5rvhHQM5HlREyx//17Bk6zEbFD9/rouG1FlYtRXsJZcX61ev2qLlXeABWbkkcEGLk5XIM2QZQ+SJV5G5FglgEb0/SVIGcbNXVL7Php6ZkTV9j9JikY+SrrciKxbdL/AellIR8gAmNEZoqGlLRij4F0btWrFFq0GmZl10ko5TX2ZEckJqOF9UaZQhqUrfDGPJk3qppTi6IpsCaLDxEBYkwe/95SWUCW2EjAzaiqBoRQnkzvSbuDaiWBhLOajhf8C8uYOEHLphIMGM6I24XRC1q9BUuYb1noDki5eQkq4IcTE1BHMAiopIGVmovcvYKnVHQthRojWP3xz7hFZAtKeMQDWxCYLrVwYOBAjyuOsuL8oKimuvsyIpLd0ZUg2Ww0TEmx0w6sa7/UuYUXMIClCCZwR+Vf4VKlUf19mlskiy47y6kkhikOpFSIVCmsmwLajjgPaEEFTT2C5SqsK2Wht3Jy0VxyM2QJ5RstyDrKjpl5iQ7PNGa1uQAdvbIzEzqg4eCi0Q3NdrNNEiYeU2iACKgx2vfhYFs1a2QtSakREHIcyHJ0X1nLl/Y6P6FsvjlyzSgDNavZjeocWwnJhxC4BtMeuQ2hHP5XCGArt0HwtaunohkIjGvENcjm9pG+VW6x5Kstq8/iyJRIVxdhnoo2jpR75lA+TeYPV2Df2JS15//gXz+zMM3lSfI2hpnqOwTQGTfJ96Xi0ryx4NWbfjC3xSLZ+JaVImnw7RJqktpoGtLmJ/Rp2aM22CRvczkilue0cOt+djxsaG7KnyDBTmWyMNnQh30121y+N5hK5D6jYGAxXLG068QUQJaHsS1duJswSbVIJTW/lJhwDYDbh5ddypBa96mqVw5bxGq7WGZAzpAzO1oHxokPMw1jrGA1ODsRsWMAcIo7VSiQPY9769jdWpHvfzWUiA5rvpQbNUGhm82QJF00Gr0H1IGVzqtw8tP4KhXRomzspJt6DoEL89BOm90upOcAA2KL7kCJ7pFKICQ9jZ7ebhE9yacLIxHSorJyH2bBkI7cNcWJyfqPC9+xREb++Hl0bWGpUBKs1SO+lxOvLLOaXkEKrpVgQK+fBZ1ijTappiuWQ5oHzgUdSCohxYq5oleu8KgLOaKnLzvtVexNFPIdjGza47XxN1AGvvMuSA3ljZzFDLTRHAyyEeQrLoqpQxUyDkoexGL1U+m2kHv2qVSZQW2S2fsCz1lO+KTfTW+mwkftqqINNw/HgzVmKLS+qgu6MsIXmT2A3h+LqSsOJ+zAy9XmlcMRr1UB/Bk81QJ1Y8ufoLIXcqHfDnixqacfCWg2MqWKgmzW1WKQSWnGnqTHpRc0Uc75ry3R0JVfWoEkwJgvS7Uioq5syD+Ky54s3wzmjSFEFpHp48goy2gnHoBqiKbBKKKVCF4FK/aphppIs14d2PFySj0hU4pJ4iFhjUKlfg3RcJMCox8CDymhCL4sacgioxmWX3sV/c7ReZylcXBd0P0WiaOHVo9JVkxGLip3Q0EqLVUI39RREodyGP23oNkC7jK+vFJNmA85xRW5oWB74oSGZtILFCGX1IhBOilZmiEnHGUvBsy+/qtW75oVYmRqWPwRrwRFmZDISsYE6sWgz6NDNVkNJHxHWOCyhioZOllpfiXlsLcY3bLYXBFD7UZktBk9yTWM00P5vneEghVMPRgYuIxEX2aUhjxTjJGYn0zIbaqZkKHUdIwMoq2pYzJ6MxkYkJNVij0RXs4xKwd0GapbVMEJOI7JsRN/NJazqEjE9XFABhSIVLWqpB2uuLKOpEJyoIadFC7JlYzPicLLSgY03QwCmhJJSQM3QZPBSenGxlzpySXGOTKE+r5iGNjyIegQcpIweVJCthhQ8oomIwMXBqknBAprHwU5tMFlYdBLi6LnOxw/RXwyiOirxRIhQGgeCACz1Rmwiu3XOCBGXhCpKIocQ5DjNMqTjhgBxDVU4UIvhsDUi0IdDOBGRujDwzTVADZUEWPOo+Co6Om2C1i3IJSCW6SHVBHjQSxZUvrnfKyGavoJ6gNp6MvIpwuI1NNQ3ISEkFb4fTMj+zoCWeCKQejQCrIxI1C0GDWFEVBMQ46RYkZOQzWUKOT0EOP04ePBgyZMildBHSWr/rcslfEzh0yeYre+aLMfakSnQ7GJMNY0bDgOCYKpaNqPRbqpmPMjdX3TRyqYIpB6dACujF3X1RkMoEdXIsokb7Pl9cwNITg8BTj8OHjyYi6RIJfRRktpHNoss0zIKC6ARARpO6ixob0PppIhBMTJjbO5x3bT3seRDp0H0PacgVcMfbpUZiECjkrlFZJT0JMGPoib2A8mmTt9tk5NDBa4fj6JWuNrV4FbQTTEFPtTj7svdcDf2JATU19CMU1tRym3ihT8dHfX4NctWN9Z4uz0jERWQFlszI9Ect3qTE0l3gVK79bOrqB6yVX0ZRQ1XRDVUtmty5O3icK9US10JlHpcIrCMbvRtVw2RJMimoAiJujSThAMzDIOFVhKlDwU1UYVDNwVZbuiLuwqa0DCGEVCgCmoAMxloJBIaMBeRYzJHdw9ayxktjNU8tmOJwxMtLjkxBIoGKQ36OrlObVBwNrJOjSWG6qDQqThETmAP2rQJMs0eXSmcejAycBlt+uvyGrpIUY3sxW3b1OlTDsLUfZ0WtabBVLpTllvgZpMWSR0OJq+gHpa2ni4cjE9gYBEbJm9DExs2GiW7TBCWZJRkHjaPj008PAIB2WTDRmb2FUHib1HSiwcxyM8GUimFZncZj2kaEmjCSkQgm85rQkicCTFNuEifQeTmAvV4CSq4+JnWSyojiEgaUxX14Aw1ZWSjsp9oqGZCrGKnWM5FWWKXm01yFjUN5RXMA5XW09HPQTPp25CQUjlHsSj5nZ5Qa3KytRzHy1Qek7BsQ6PrPZyfx6D6KRCDntpAKjVelyzIpPEoTGOSQJJQSGuOauHVQ9JVk1FKkQ9JQzRtCyPbsbK2jRJqruQ2WE+xccTrO1eecZvkQExJQg5CPS4WUBV7ab4CyeEZUzDphFo3mzRdaiKwgOYxMPA6kphNNDlKWeycisreW+c+DtboUeABTXtgDj5oP83jGtmpwGRPM2hzKaROQcgqyLUCm+NNq3WkSEdW2pvOm1lICWtxVmTBSI6nTxOzE58674ZOoS3TR2pwnQpR1pLrJiHln1Y/qZGrN5NMOvH4VNTJpRrYYZA66Qyk31QyKjSs8U8oYR3GpfFWBFJsGt8FG3NmviPEAWrCBGTwcWPnpiWRPLGlBckMFY2D1dfXXLVSJu00E9jQ5sjXrzSZSm9U+UUl4u2BRiOf7tikSkGftVWnIDw6IDOo7Zgiupzo08+6Co8Wmy936yk8oZhpO2I9pwqmCkgewCTpVU4ZA2YkAQ0dnDmAxqXWUW3/Y1FFkzPYNtuCNQojBWwxaSitz5xsngTrLkyX2UHXJfP6bVM7iCrmlXzMOZnUiNJ1hH3Ay2s6GBRBVKExzTQxTBekidKYB9HGmiIPCfEXCw9Z8KLzvFzft641X63reg9ea6iOQW2tYcrDjEj/9l1wRaHDXOjxOJNJi85hjvqUvu4Tpe+BetKMXBJgdFouC46631bB29mdM6nqmyuwWmdw86KkmjocpHlIbIVgCnHoRs5AO7wkwdy7kNFHAakekLyCjD70WxcaCikQTnBFZNOyZokXgWyGolnGncky6VJN+fnbn2brR1nFKBWqmhpp0xwxOLUwNTGdyOhDwDFJNxPRuEdtDadoLtUdBq/GYkVq8TFfF8prGp/sFA6/4oM4IF2B8uX0OVmC/B5eArRVG94JkriejZU0fl5TXXliq8KUMdmMV7rkbF5KiktK8oc1DVloy0EylWJQjUU4NrkUDzNpj4GNddQjNVWV5lhRPjOlyypiamjkI2JV+5olylTFfbCa5SoqUadZuoZHqYz2tgJSPTB5BWnWNurZLF3aNjnCCezt4X2rG03gkAikGQoPKyUL9eSWjiwCrpGDhISnr8yXhF1VmrqS8jKkvcRpkI+swNgHvm7OymKlI50OXGeLKWvJDT/uWTKtmadGPS3prgsHwlHA1mPb1IlMNArxyCSjXmy7EV5vkyl4NbhOKStryVU9/WadVtmr8cr0m/CAXVTy6ZhNCmc3MB2LeVFqsoBa6RNzN5JX7SQBtrZ11UO2RSGNWlO9o6cLx7VtT0Z2yXOAEcK+2Tfybs7ztE5BprmBoqugHrm2njwWXHjhTxsOrkM/7mUo6QuGN+Lrg2ZiKuvaD1yFwobEtpemLFuUUN04qb5JWun3GM0ZWuXQ6iGrKylzs/LPSGoIqsE+clI704pkuRKZViDjyjPGivPb2xYBDioGaQ7Loey3t/jB4hXoPvz2FoEkcF03IPtSLGBW9QX9y96bmt2XV1drkGB1/j+uXr96XmV59fvrZV2v//72bUVQV29WaVIWVXFXv0mK1VuwKN6+/+WX//n23bu3qxbH24TZ1/3G9XZoCckWmm2uFKdbX8CztKzqD6AGt6BCFD9ZrASwqxUo62+3/4RJTaKrnzld8ttA5b7B/kFC+rhSnDlchu2jvhb+3bn4cIvETfYGd+2N7lB2Q9EzNEisEMh4oeLcVKyOEFwh4QFlLzpd988XiBxF1qzyzd88/6lr43/Z+u0XewwfIPXML42IKXDAl1brDLy0OZw5jGyRM85upZeg7ErsMZ5XH+AdaLKaI/7ms4jrt7ccB/C89lZgNk4D8Bxsyd/SpyzDGF2C0ovjrfCMw/pU4zwirsgeZ6fCMIeKAiEU2uO9APWSRdZ+sceAn8Llh9l/cxAkNPucAJEvUyqcL+kKtvtxGsvm69YI3ibGI0TWVFEsFuKlrjqORPXtfWxSDg9bYo/xezVE0XwvMxYnX+beTwFlIL7jNAf4HRsZyr7MHmt3RUxkdabATQPkgvRtvtpjwhlI80rQb9Rnl4X0K05wzy6i5NPWyDHzRnOkZTNssZxKoC/KFG2Sa46lN18dmK8sVhzjkS9uGMTFY/PVHtN1weLAf7vUFnvRf7PHcgnX2QvfkeGjMx6xS0yBg9I54XTNiUvt4yRhq5MPDuZTQ7ZvnNnUf3ToR7HgeLb94kCHEoIaLr7l32tuSGyJw9iwym49TszoNp/dcEm6Rn12UObE+k5IakFeW/BlTj1c4LcMQZa9CJ2kSrZGydNDDdPyNCYPNa+vPo6ebxcVceo99tiiJmIK7PF9Ik8F0YjaLw6rV1FyGNovTuZnKZpMm68uG7iqeipKbpY2Xx3mKge3Gbyq+PnafHYzr1t/BdJqC8SNKcgq0cqWgGyN3Hbe9f5N0BDBZVB5SK6h/kgmGt3o1UtVQ4mVpARysfmTrFnABR0mdL6o+B2AAsijnfb5TXUTVLk7dvZ5WGUjEjCX/RvpIcGFd0WdU5qfbg2Yi08kT1fNirgxj1ZtemjWOyKWO2AHz3rsknJ77G2N/oVeNaF0cNujjowh4UEayoDdR2k5oxxHj206wONhSxz4qh+IwEh0gQc+EsigRDqUuvhALkp4BTOIH6jmfSFM0fbyeWTGjsHJ03lJSMM8EuqzqxgoMAqFLocd7dkif87Rf3Wy8xNxCdh8dcd0AcsETSiJYpDhpMunPGi4WqLtgvJ4Uyx1csUi1UpHN3EuWa7UYdeULuD1slnd5sKOjiuyx/kjrdJb/ix2+OggJ81tllZLXsVRn+c80Y3v8fm+XigwsiXbptSjqHJ/BT6x2sYjUajuvshlN1aikZFno0iMk3RdUMA4C+R5vkgf04XExyYF2BPV2WSZErFQ6GDdLVZp3j0xy1l2TIk7f8EV0keiFSopdqLv07f8E9pjXwjLJl/msM+DNfh3+PLU3ipidnhMiRtG5WwJhW54r9OaX5Sozw4zn2XF0+CxILk2udHLIRxaWK/L4hEuLgF+kPWq4U7CJMUOslrUBvRyCPfeXxc1yOT0kUJ4jUHdiBLI+XjpujhKONuILbHH+DldpTXuUH+5lkYqFDr09KHhOog/uHhs8uYOJHVTwhKtN/VXZPbxhpIKxr6Vj4ibWJztF5ed7+bNG3bbu/nu0J+ujmxJ58tcjlj/aNISfquXOEdHf4uUPWuVQTi3sDEG5PiZcgf5bZDeAvidWGQGHC0WHDZelo3QTkGSQ7IeLkpy+O4eZcPPLP3dwTjPs1Y8qUw8jIkuKXfymLbi9O1OgV8O4U6N0+d1WpJ4wg/gpZJThodxb4XclyIYZLKlhnLYuIKKz+/EbF7FYgdtytTkey+WOvUanwYe3ZcQipajWOp29DhUvMbB7MIZJFfsIpfD5RReMKkCF/3VVTp5STL4Geb3fLSqHMK3hQtYpoUwjyoYj1aIgUHQCJpYBuFCeXyk1J7VCkqRKXLBeYb4oD+q4pGyZS77oUWKJRlkfe2TJb6twu+NVFAu/b8Gz6fPaB8kBNNTBS74TiuBtuSTQ5AXeD5Bm7L7Ap8wcrFebJGTTYb2Y+f5I5JYVLk/UxSMMjmQUwx68iD393JFzu42Uv/oEaQZuE0zAb0ayq8l+SDkEE5npRrsYqnDbqB4asfe3S7mJ1dW7rRLSu9eiDfirCj7/h1DtDcVdkpqQIejCJA8FNiLim+KCUcRfKHjflud9kXYeNtniFG3SbzB3SG4fN7lEK4ttAfhuhZ4CEe6wUVXVQgklBQ7SR1ed46bl+OmroWbXEKpM+afabXM0qrWoOdBHCjT6poMIna/QPsw8VBADuFwOIB2Q6RqmvDB+EyJU2g1j8oZx7dsIUGz+ersqzwRYu6YAoc1CL/RADJJ79gSP4xXNSjxZVCIM+eLUbBaSL8WT/OFVXs8nAOHde7F0xxHicgYTQbgHCHEYIEy9tECOscMWbSnA3TaidG5VrltmC4NqxonWq9hJU1XLxmHEdhpLP3Zd3W0Xmcpv1eQAtjj/wnT+yUn6P03B+pI9nnuO7uf6YJH0n1yoJdkPJ+cxzOsEXr1ogHzaEunWJRAcx6TRz3EhxkUIp6Gj7t5dK8Z6/DYi+A/48rcw3pwygDxEjNb5mL5V7BbziSOCrHUA/MXCKqmhG2aeyl2BsKjBVmgqlDogRf/0OKmAVwDv8jhpejtEwqdA8pgiSPi5E4iBYhnG5gG+iYGCO9RbB6P1I6EBtuaIJth4Q67Fd7H27mH2airjhNng/8Niybpeyw9e+DKnDzsqshDrmhbQhr72jL1w5e5+As7O0bc2TAl9hg7e0XAR393Ph2tTopmjYP+F8JNV7HcwXZQYPXD1s8COfonxr+KX1kIx4iD9oytfTZOiDigC7dG63Uuc+yWClF7vefdQ+2pq26r2sPRbCKWzVcX4zNujqbjokabdSVWSbGLmzMFgmuTfHJx17VzrYq9k5UfwuT0uNqwVdWpmFjqgDklQUgCys1nl17ew6v0X8L9x/6rZ1hgdV20l3Dk+E2w7v3/JjsOEQod3c2X+BEMHiddMHcA6tiOr90JANxGN8t+37lQU4/cfv+RwqcvgpUoFG6NwdVpz8C7HC0Sn7scqprjGFtdc7IEXFyRy4mJa545pdqBhTz5FlPgEuGy9TmzunPDOFzI4PK/WDQ1T0a8FhrTRPJX4zN7zLqNfnj6UgnCAD+aFss4rNU3rXIu+GGjBnLZZFCVTMQC3OmQXe7PYgocdqZplmGfb58dhNuYCqUuFm8X4ChHLSl2cXG1SS2wrcjmTuFdXWo4n9YulBcOZBBeLbDpeVStcFA+LfUTIN05acD8ZokoA930DAAObtPnugRihl3q8/aoZOrEMlAXU5h8lLC2+rZ69lDdovwEn0muEN7vzBQ5L+tbkjd9XrMzkreZxebjdDZi2H7TU+Xx8/P1nVdnaGPfbC6UCfcV+OL951b6ImYUhqUR+jOtHsv2My7df8k1C6bswMBeDByPcwNZdg5eDTcDYh/L0VRQHX2pYA7HX3pch0Oq3TukOhzO7MvhzFxRK520dC9uRDHO2rwl/maZqv72G2QSVeyshtvRixGy9HcHbCQfDoep++Zy/SBb3zXZf8KK3Arn7yFwhc54vxZqtENZfJExcPd5hX9/u/tvQogWKzP/3SdUi0UxFa/3zQo7Xeq7w0ZhPbx7z3Rp89ll09GnPuJ3G5vvf07F7qiDj7Pivk/l5s6X2toj8WTbnKjwmAKH8xE0hIuiElPLUt9nnyVmpes0XY5FJnDR1KIadf1s21esoptCe7w/QdWNhkVJf599Hr/Cp8pf2rS1x5U20VBhS+aTX0wUWZJ0+vvs835RZNmPAptRlzDBz5t4yK0RxUjyito9yqsn0QpgS7ZuixIYV694+drBWJvaShMfmWRLnC4CRXrlJ8Y7SvFeCurrnBXlCkjSEPOl7pivAP8AMlvi4MiKnn43dlqpo7u7NEslHlWmwAEfTgLEu+i6b9O7j86rNn6nf3iMoxhX6BA1owgi8osW+gyQhSrfV3FFc+6GcFc+F/dpLr0EJ5a6Ye6TRymRCwBbs1Z1sxN4Kt/PsftSpaw5zkp1lpZVLbI+9dlt5kVUm6/TrlFIHa9B/iJYtO1HFzzSWDq/+Lwa8Tv69pjmiaCjhUKHPgqJvE5cE3e1bPeOX9f6r86Y3ksxvXfB9F/pGm/3QSbefOWKHKyCZZFDWaZppsBBfvoUuZz8bD5PoeXnsuuJDATfl20lycesV9Xc1sN0crxZdRG+kpPPTZErTnnWDL7M4RzkqfgM6xptJKtCFD+x1AHzsoRQh1tS7jBHDdpcpYkUM1/mcSfvB5A//NyVzHQ8G/1YNfRQeiZ9xD6FGaaVWFweysmEYFt1VOyAn/jceX6fI1K3SZz5kyu2yCWufZqnY8d4cHUuaaPt1UBho1H5yJq+/liO+Hgbgwimxe1tCR9TIMotW7JrS9RMzN2fNYbxdY/F8xxXXnUcbv4M8vsGp3XnsNDfpw2jOS4W3Ka2/eIaedi6ZaXPZQ1FDji7YIau7onoiZRDOOiCzSNS6kaUQA5zBO45orRfnNwZW52V688ZBTxWROnOuSd61RWmw3ssHjpcXXVbjf++xydNRtIQSJeCodDh+DJP/2jgFZTsyrkiB9dbBu7PV6g/OD2FOHRJsUPQZc25n8mH+WXwT22TtXdDr+qSRFxURVOG7jtkGH3k3ArNLthtfe9FcWJL3DFKrhFzRS4HwWdlsbrImnv+bUe2xOkgvmgSQa6oz1sjBX0UVRjn91g8Y97kVXeBw2PsTMjb0JzB235yWL2ajFti2i/zrAXbbskfdnK6drbP4v9z7sjmuqI/RH0GXv4a8HgGw6oqj7Mu4BZlAbBT75n6J3J/FDUve1zRHtvmmPDh3OfJd7tpiYRzXhug2GlNWeziUDSTVTFKAl6y4H9sYFUj6xxLlsQeYIvnPKzcdstqR4/66SPYONcKMKaAqwXy6tvq51O/xuz7FrMikN0rjB1V6sRNzG3Ll00dzN7HmZP5lkagtyVjh5/Ptc7DcpVWOCShvfMUuOZz2HzWfyOKbZXBuNcOhvRt7D5t+Lo1HHT6XONLS9lRUy9Ro2lCAhNicJMOswdnuaEbh8viXvePEVbfU+V8gWlyl/J2kqzcHXun4k2NSMDs2/qGJ/a6eICc04D+7ojtKElgValwMqUOFjmOa0JWp0pfyMq3RtrPirJZhQfSDGg85FhTdxyhvS7WacKjGD7OJfzi9W7Xe93nF/JsIRdbcaNt5xI3Eb4kbBFBNggeX+FQVB5HOkiLPIrh42zSgUkge7uRKXC+MSC9LODoXGy1J+9X7L7aY8Lvv3Bouk8uDrCqlmVmob+7Y1PNpKzcHTvJui3F25YcdJabzgLhyspXT02qoj6WRbOW6qmhZJevZXwd1h5es/Sf51BSWDSl5hNTcFBYljxzyLc5ktlGVEAEs43g8VWHisrb6u/a/otl28Tde3ZeQ+YiTGDa6XSXFUW9ccSENCbLCMAUOOIT00hRn12OIiXvAXm8ARR359Vdee98CELOR6HU5fi5PcZSoJYUO84LvnbYCHi5Ivf+ytGKpQ4uxPbtKjliodAZb3vFWemfVAG5c9xJU5YwT17EWwRyCJcW2nqXgI8nYEvc+8weWKpkRoRy2NmDWqZxqM+ufN3c1jhl83meZKhjMvbmITxbwBec9S0MEO4tkLTTw3ODurHIIQNb1I5NDunaYqcSNGPjITxb0IyFh/BsAdUVZU8O4amfkJ5PsY0JsjMIpSSzAI/RtpSYFuAx2paS2QLcKXgDVxGulvZfHflDznU+nNZLmwTdpsi1d2LWe/q7yzWZuyZfwIXsmVG+zAXrEygXF0Wa19VPWEI0t3xgnwLEYZ1bwuShaOqjui7T26aGyn2eHjKgxeo/VpmhqRbEffVWhXzKyh1CkSLn6Rws77XCIl87B1jifQFSumjji9TBCWIRmYmhh3QJXikXYqjX5qsbJtEE3Xx1xCQZs98Iv4DqAS701FTBuPX55PHxvdjj9qsbptPndVqSoJcvRV4vRaQCgC/+/4RAQmW+3I+DP6QlTOoP8Dblb/eogFxcUEO1Lu/spyKTuKNUUCEtyThIDeXV0jHIH8StlhTAG78orFIAP/znJ2rUuMwLa591UIV5KPfCfn4LePcoX+i+LhCbRJq5Wg7hIGkNshnL9F9ETK9LkFcgwT+FhU0DF96ayKR6yPAWL2HV8HnFTbAu2nGNMyxo6CmHCGlBNiI1lFMkxGDlaQakAXO5vFImS1BBpRdWCuCyr0rldy+YAnePX5cjUOrv68vcseINF0543NTtGq310llXcjnwiZP3fReOZeht1CVcgTQXblYoQOzb+ASqr/Cp26x/LXDEayLJ96YB25rjoH7D/b1Ce6dPaVWHP4QuQemTU9gOzTiHR4MHkpcZ6rujg0J6OOG4VOxa3qeP6R3ZP0VkLglKH+ayQzMOc/Vt81jo7w4atIKLn2m9lDKZUOiGV5Iqhvr8J2DcOLwawJ+TXeHvzDGKWyTvhqmh3LlfdgbHlznsDiTeWncv7XnV94BcRwSCzSQFcB872piuZXslWbmL5ZOk6xSbGoJNyRV54JTcWOLLHOximGOrXzR9qe+u2CQdZAocPISwqoRb8sNHF27akJ0YfyI3SQD2WKsOGiNC+JFnyixN3RHDkHCDitChTdH09uRFxOe6/9EAQmUW1earg+GRp/VFmSbyk2Gx1AOz9NxXLHWhpKq/vn1V99O3j9IDZ49j5X4P1C6v0kErQHzbkJJBAeJgMhiPSUOPRzXHot7HoR+KpzwrwEKSv4wrclmo+qpKs0cC4BIpm8C8gj0OIVhfLHboO9KfP2F6v+RfIaS+O4RANvkig3iV4YIfqe/O+vUE33iVadi2YLuW568kQVbw8ozR+C7P8rpjLs/hS+lXIfvRV7+ER9fF8ESuLJKeLt5jS5H20MbxG4kYfdxGVljG4dS4sd7tEDit1H1zxXKMSvBrLxJkQ5Gb30m2m6e/T7+X2zkJwqdIbSLWEKnpsXi+uiWvut2a/LoEyQMamOzQki9zwIrDEGV2ClPgeLII5UegfJnTOWH6CEv5a8FC4Z9AesKdFTSmACma0mUxtCk5B++/ezhA5LLp7D92dzTMZsPUTZlfwj9IBsxA44VC5WW2aOuPxEaRLrnFZqC4hlQ8v9clBFWRnxVlO1u8r50rdMFLph2SvTvv4hAKvfGqIzm0gO7zJk8+L5a6cCq4u/sqJo2mvzt4fRarNJeG+LElLpSmxFd+dVABspuhPbMt+gX58wQp3xgLP4vNa/E3odhuzX0Bys50EW+60iWu/jkZRrbExdjZ0Fh2JC0rn23THvG8ZgzfdD8qxMKwhAtyUCEfNwsxx2p70Hc931ytYTJEJm7mPiydsA61T25hN3zjqMWY4icfybe1NCDbAOt4G+cszZDwCUGxfJmTCn36lndkUL0vwBQ7e8V35/kN3WQFGhQazD7GhRO6kQwNaR/s+H/ypEn7wYlj8GA07tuhFFq7xg2d/iUPS0dY2REe/2VcWnnumZ53Xn6AMkVG7CAJJ8XqNs1B+Kphxu8/j05IR1pBHhpuscAfHCJya/7h0vaLwwkjyJs7kODbeSXa1kpvA6tgHMPBJHFgTmE4ML/nL4/33+yx/EwXPJLuk8P9KclB2Cf3YB1QQUIE2XGxUOiBF//Q4qYBHKzwqkrvc7T7TQlHnPMPMMrK3c/wcIpS4foSV+a+8cZBkjxWvswl8Ez2FNDm6/64RpAGTR7k3guuyHE3962pv90RFF1iR3FTJ4Js++o3ypIXb53bRYdDV0m5yZKVO4Q3wOcafRIfHaO+u12c+KNJS9l9if67hzifFHldFpnMy6uC2f8NQVyZiyBsk0vZUZYCQW2ST5NuKD1zMm+X4iY3Q0fR3u2d02gqXIFuVD3O90GhgmVgu8bNqG5RXv3RgBJWl/e33AELX+i4DTpa/LOpavF4XSh02NSQzYcKsVjqspZdlPAKZjCR3KpgiqZYa1QYiTjIFkamwOXGR/6Aj/ek9otQuIfBX9cp2uljfgxThgMaD82nqbv95mrsDOn4KVjVIXxfNscxtItfZ65zhPYFg6BjA/zT55RAXm9uV7EyAqDk3AXkgwPTV9lpDm4zfqGgvztgg0lTQqFP1GcHh534qNAn5xeFivticGlxKwJbNOdK+KleZcfF4oXvIv3dxQ7Ka8TYvd/tK6yfivKBN4fkME5KBAncC5GWPkm+qIXlMM6tnD4nS5DfQ5KeTN+YCnRrVFvXqdC7Zf3YvB6tV1XdViWne/nB78UH8Va6x5V0LOyfC1Qo5DBlilwth7OiXIG6FqJlxFIX4zjs4SClgDa3WVot+dWD+jynYt2mgDvlqAucDPA0X6AZ5eaFK9oaFUbYpPsUwUjrwHxtNWX1cbRZ2zyPY/PVFZOoHenv4+1e5tqkLuEKEncTsi0DN6o0Kp/Nqr7+OOxDGuUOLNpPUy6okiR7zgn2doThjkHycJ6To0g6y3AY6ymQejChNaZx2DHatYuIfpi4Fxh27h4wHbhzDVfI8Ak9KJNh9GBVOzTbuofAz51fAD6MaPN1j49dT9BE3RflSxxu4rH57ECNKA5ctHVc1AfSRmEiDllAXO+BhXaHhT7CHJZpEin+g8fmk/LYiGLbN5H/Dl/al8AZTJuvTpgEJIc9hZSPj5LsEiZFaK7uAY0H52rqbjvLxvV7jHPael6dL3i3bv9ta9jwexmFDQc0HmyoqfvnYsOrrOHc9e2XOQLTVc9W6p+rnMuZnCzhosngNageAp3JFCYfZ7K2+rZak1dI+nL+Nsfw0cEvKTzA6fr4pjSMwCeGoC7W3/LTsixKwQ7YFLhIA8lOU9aCA4gtccN4mi+k+Prvjv1rkgRWlbyHVJljH0UaUp+3RgMMz94GWlM9Gh9rSl13HME/WixKNKnCnYDNZ6fbV1FeWpMtP+rFZy7vKARVU8I2PDbQLUqj8vGH6utv7YpBnvNDm7snbLaxGpYtcgqnSAshngJ/2mNvRjf/H1LUZBV8pMRj82dIDYoDT+45T54VZbOKd84poPPgSgscI51tUm2KL+GIpXOdUBIC8aiGjw4mfLFOEx7P8HGPT0wvSvI+SJdiPfRggsbldS6hRzASr0c6xz8ri5WKu/kyF85U4WRLnGT7nzCpBZFuP7pdIhavD7teHAaSS8PA0d/YGezHL+1D4jxCodgL9/D2mxI9BbHHGoNsa1DB5yIwgJFC5OXE19QeaeO5aVJ6KV0sni1wR5bO2COT8S4zJ8YcjUGJQy+ISeUYRlrRRtgShG9UXJ2cs0X8rNYgvQ+0/nssXhE+qqpbuwWNZFHgC1sskvbLnLcWQm9/zOZgITZ0pCBIFpmXe8WAYVtZ+zhJyIPEnXeZZwBJ8S6KTbzz05YaCXnqUzhp5srmv4KFX5zGobkgy/gsX0zJ1oj1V/hUfYZ1Dct4jio5Tg8ht0U0kqxLWxedVzo4Rz6XsPd4h0bTLXk7Ekl2soTJQ9HESokloPMx3cw4tnWh2+aUcOSFPLxP6AKX5bjVUC79vgbPp89QIANT4EBV8NwH7AvuO7bIQW1seYK8eEbGtiiWCGnS5DhjqJhJU6MJrQv+KhnAlHrskHIsTHpne30xaUr8kskFeMGtxnpFWobV7yVpS0zjyB3fPI9NVm6PPdZbvDvnLubJFpfbIrDZZHr9JcmgLOE8U+CI7wKWabEQVgi2yOUktAYZqc05AJgCl20Omj75i8xMyRxulFhxied5Wqcgkwo4X7bHck7SCaX/Ilks8UBC1xUen8+KYoFjHFk/jXYNxO+yhBIbyfkkv5THl3lgVSB0xyW5rMcUbA3XX0Lsa+8zt4aubTQur5VNj2AcXr/ok2i84zcCm+8e2N4rsL3faxv9pCyqCu1GsigcxWPz2QsbUewvV822kgZG/fhF+0wY5YOa+gwfYSYsatR3F9dlUdZ9QCPnrqRLHMIMmyyTImQKHEzEdXd4yRFt83muKCb8+KiQD3f46LJ5voNlCUsBF1Mw54lL/NSIZyV+Wx5nKuXiUIfPLtFkJOPtJ1Dxm0O6YGtUFPqAU3wGXohtkfjchVXV3NaTnz9R8onNmUvoDpA6vfFJn6irva18snP2Krm/ETjNGIXPBMvrjTO1bUynOMH0dxeXUZI1C3ieX6WoNuA24mKp00EHqCoceIoKavlxhwjgYi+0lXmDof/q4GpMaz6DSfdpyqisL7AGXaQuZ5yxJW4YlS9XCYVueCU0oz7PH+t1CXOkno6qn+niHta8IciWORwLkhr/VeTc0Onvrth+lmDdmVYypEyxK26063iSzJRQ6Ir3uMDKnxdovszpGBct0vyTLZuvjrKMn7AWxZl8nX65OqqqIknJu8vCmoWWUhIfeXO0Xmcp5nTKYNEsVPp6/PLUQ6uMELRGLsTVX9nAzVXRlNJHj6xWuwG1bNnDxBz6EtjNa1Bi8fbsZk8sx27+9lY63yEsMfjfnBhiU0vFDgo3mhWZe+xbzQtDJ8M4oUMzNSOQADf0J1pWl8Xi5hJWdZliI+kEj9KkIWxqC3tZpk4LaKMszG0FsgnXQARmsehyoPpoqTc10/SutxvqioLuaRwRWnwDp4Xp/YNm2opYA6d/QBhh4iWdC5voDs9sE32cZhn6PLhvLWabr6Kacpe5ZnEG0pRDFnPaOdRhjOncMWTIL1I8n6/Oq69Nlv3++g5kFXQcfTDzXMBylVY48U2bkvKGTv+p5SFTTSHHAwdPg1uwl765wNkTkEfgM0OHA9cUCtds+saaVVQ1VNrGkTXk6LdxpdkXFriET6BcXBRpXlddQOzN9woufqb1snMG6yJKjJXFGBKhigVfGBsKnAEWVwQ+MXd4GxcpExniKZzeVHexcIQ6MUwcDmkgH/HYYmocHvc2MpB5/OFmTrdx7/6/Bvd620YGLiatIoUbGBsrRkQcarp4uSSsOxfFX4IwRV+hel8rdoiDNIclDzI4c7svw99V/wFPKLiHX4oFzKpNPZzTegXIiKo1SMgOfgHP0rLCoeHgFlSwBXn9CvX9MUVarz9y6xwuf2QnWZsOqgf4AvL0Dlb1dfEA899fv//l3fvXr46yFFQ4biC7e/3qeZXl1d8TIrcgz4uaDP3318u6Xv/97duKtFi9WaVJWVTFXf0mKVZvwaJ4i3D95e27d2/hYvWWr96htcLyy//ssVTVIqNnnDo47ea5f0H9e55yvPHbv0OB0/oZvoR3r1R65Le3fMXfJLyFu/D76xRTlkgjeYqERJcCfK87x1CQ9Oz1K6xu8KXQQeW81aJvT0vbBvJHUCZLgAyRL+C5vQPx++tff3HGyRyqWaOuSzEEQ8DMvpY7Bm7KjutI7jh6nCDtDjRZ3SO5TU1I6AMWAwPCBi7avBJ1DZKleGdmZzmRGhvXEi/efz/PF/D599f/F6n591fn/3HDVP63V2QS//7ql1f/t3M3Ou2IWYxmYB9OaN9o0jDpu19+cWbTs7R9n8SNPm0tFWGsxAOp+L5VNJbbNAfly39bgef/7orJqHLe/+Kuc76kK9i+QhCE2FoSPxRPeVaAxZ4IXz+cNi1I21CTp380MCUo71KsFB2Roh1Sj5dEnNqqQ3X3KDT9BHuxYI/vmHBxHLbuQhRkTOiFD4tsLhEVL2Snz3WX5zsGNrSpgU/jLm97IlebAA7/ZQTn0jXYOu76EiO1sP2cl6frInpXr4sxOnoJ19mLW28d0I7R45OT2BiPkyQ2yiGdW2Szp40ljKC72CsLLUJ85aBO8Yy5GotY4W8CEfzkGyMxdsdKyXP55txMRLZ2mA3NJJOLvkzQPd2TdaLLpaazXX/91d1sare0ZoObxW3Da5+KSi/kPv29KMo6RJKQwVnKTKbwjg0x1ZERt+mAr6og6xjb2a3LASk3woGo1ghy1+XoaCOG9kTwmDHRFwg0E/3XXzysmNNncpGAOf8/X1Sx19+hmTb6ytTCe4+luG+CjSAbYSzdGEh7eO9CdljP/NLm7CjI01WzIqvb0YosIf2yC5N0BTLsvUa/KuKGfvc3xHLY2Yhm3bX7aPATtdRi70P4/ChlrwXaw43jJl8gDkbyMqQ+QzvWmj9Q3FnFsBmfuylF1w0ypJiscv48z+bOC8PFpWiLv8jw7LUn/HTRZzdwZaahYhAntfT07gRXPagr/SlaCBf2oe5jadThhgAsEzThJMWAv4FmY1E4b7RxOgXNSZuvzxGxOZVgOGDQn9IFvF42q9uc2tr4IPqB5vM2C5qAi+Y2S6uli8Ia74AwqgeCzZfghMxVJe+XIsYthK2EF6BEXSAJuoY8T2EYO05H6jd9TBeO7pNwtWPn2xlF7yDo2DiPFqs0H96AioCwZ5zuTY+wqcZXT7/ln9BO8CJwcWHvRsddZIQr0hHISF2SjtvZoywrnobtNXxM4VPQAna0XpfFI1zgl2Dz+6tmFTLfX4s6Kr4eGckFyg02sH+xUHZHAdfFURK0/gt34P1RXT000UUE5M0dSOqmhCVaEeqvyOLZ2AexWvmIWCY2zvPqY3pXn4AyyCrqcYSvp937Bd/qJSwvmBu/fj3r30MYlma9evQ5lTpq8MapThO8VB8tFlyTQd0/r4YYkwiRE2FT8z3PWiHs0QWNDBG9lZJvdwI+r81gh+T0eZ2WZAf7AbyoMLqEh5A8xgRhOHd/AtUVQJYDjDGrLCb37TxfPyQwDA0Mn7sc3ZcQ0raW50nGBlH7um6UcJUhzXiYPumQMDnCQ/Qdje9iyBAeASOTITzE14d9/MOTlSG67AxNan9gEGSULdqLFSDrsZ0scay+jyPIsuvUQzghFDitgkjIPZ8TcAACcpyqOn9EIoaQ9ac3QZZeXSQPkdx62MVC8B09ghTVTTMKZ4DbRtpHr9UrzaON93Px1I61ezc3bBqQDZ/evZB971lR9v07hmhbFIL2GCQPJKMRvjESeBCBt2gY33lLQ/ZRv4BJIctXd7QXY2JafO0BXgx8ZOBw0aGiAoaimaKIzTHwcfNy3NT1Zq/uKTIY+mdaLbO0qsMRdrKcQcSXSDEzLlQffCfI3iao0iTML0wjiL50fMsW4zbQbTNOqFic6G1crREekHkPxOosg2pjeIvkOl3BCEFxNO7TfBERc+9qOs1rWFbBvNhpLwYrHJmBOg03aZtov3CdwlZ2g3Q+WjxhVVMv/61w9D5eSkZlVtT//nSw6hJthYyifUltNGqz25To6H+mixGxfxqXNsOqFFvnDIjjKpxYB5BxTkP7x5koFGrPg3uUwLackkpHnj7C8gXPqrvrha0d4nihbyP73Jika4f04xhUsFtegx0FA64vEFRNCclNa31YoXd3x43JG5rBP9imPDySbfxNm8RV4hYLPQrowntgiQOuYrhpGISYDDHxXS2L1vMDNuHiESPQhtii/Yh3MEYB+Fy37WkU7hf/XsE4QVbqkK3ohkPflL8GsXSr0c8yhtkOnSUSAVN3xlWdFM0aRxovgmZNxKLyiPiG8JHjY7IKhjHqBg9euh386taKR56den8Vj0/4EY4UckVsxS2Ro1yOixpZYNFjmnDqnNiC0rNdnMCmQzgSEx4Y58zmIiUBJh7B433FEAMfR6hdpf+CISNggrOq66K9QcBj9vLhdji+sacINqaOXdQfsuEvQX5v8Nn7hXBHigGM7JPawsitnfBZ7FuEuIyC5J7pjxQ+fZHYbBYa2D7qvFVde2IMdaOJmXDGKuXRXz0ivGGhyj3DoP6LT8jhOIljuoOwPWOZeW+MjWdzjKhLnZ083W52j/Lo9SPzcE0PNUNnjiftZZNB9eV6L+13tYajO2C6dwiGu/RBMVJ9uFoMZJvXWq4LNqFAgI95g/RCGTHtNVUUYjrbQmzkPYUVG4FA7J0RG0Th0+e6BHQixTHsJvqAaU9UmtHh45Gk9qTIivITfO6e/o2LfPvy1LqaUnvmi5zZllJ4gSza39QM6sB5dYa2lM3makqEiNqROZC+WHXgwhhcSFPUvQ9s7T8NN+4hG45yMBPdL0/R/XAyEfdk4nCaYOzd7p0mHJztu+1stw8T6J+L695E349FqR+Vh4k81AwzStbM+1rxZP686jMrBAXK7Cqb7hl/xn4hwZyw1uc2mDmfsA9WVRpcv3Q6HbKzolyBwMRJPa4rsHl2Z7uSB0W6Rnx0d5dmabApTO6bBtlJY6/u51V7XtCn+Q6JZtBk9dV2OSx77WdQ1co1Zf7U9bh7n4v7NI8UForx9deYLVC6nL/QDyS6mQYCgpCNi+y9RrfuiBjs+2O97kqfqd/ZZZe8Pxjt0BAzaTRk0jXW8+mg1Rrkkd63kJ4v2pjRfcUgGUHocZrYxzRPPBwMXPWQnpxQN/YDTQEiT+9iInsfBdl/peuLosKZXvxCsSR21LLIoTyDmV9exz7T09zrn/2upZWCPdGeRk/vOw9PL3G+Vd3SGmTMEkQxrptdPxWfISbWeVUY75K8d+W762UJoT3+v7jiRyICyzThcAelXPwBgkzmrcqX7O3YtBZ69iWLP4vsb8MpT7RHd+9zRL02FViQ63uiZ1oiPG1iz920UbUnzD2elTvjunp7W8LHFMiEK/SO14wK3ZpPj7PiHtuze8Kin0F+3+BMe848uqkZxKTSs2NBS9s5YmxeX3Q4uW0dq1Gyc3e4TjQJFuxEepMAOxbKa3Afx/G3nRfBD/EU8U/ep9ji9uplT/TsKGtxT6OTJiM3ivRHwu7nfuTg8AqOsFk9y8D9+Qp1Hd/hMtLGPfz4st6vK6Hj2jRtBPhVjZMyX8KqaMq9McFnt296ehqZ3CfBTY9cej3Az/TBSbCL1UXW3KeqZKqWJ8lFk6jZPuDo6Ct8qvboyb3ZOTSiBU6eXYqDCqdQiYMpigbeTuP2z7RP2Q779bDB6NFaX5Qpsuwor572JsYOD8gjKp3Uiu7P81OJ/cM2P4o67O2NsS9ZIaLtCdfMvszH4542VK3TeXFO9KMs0dESFZFl9WMDqxpZsVhGtuGAcTstkPGPPekzrj3RBea94K+/uhvMkd4uihIBjJB0fI9xKNjeysINjgHuY3QJ/4wUoKueuhDDCZartMLnrpcwwZp2f5k/ZB0aRZiGxAJhiK3n+vQZUxVkR029xHRNiDGwV/M++9WpeJGw/WydU3dqIqLtNGdk7N8wb10XDzDONpKgO0oSWFXxkJL4DzTBQVmYrIXurCib1R6d5V8X6zRxF6+uWljqkLmF2+oZTjt74cLmhqVPBuNduxtJ5INwx54ICBmQO4t21XZcQPA84pYDE8S1sbt636FHLqqvrSYOckb9CH0LHl+8wb0ITMHfYVFMuSc2kigtcLO+mxpon5TPx7Jo1p4aqKs7bkio1zMrkU8ovnarTpAsx1AoWPZkRtVBrYzi4dxN9UTEck901E6oh31jtzmc6i3x9oNpyVgiXuAk+KImUNHn5N2N/QObpCA0yUFgZ7gUBcE5DsIucZOa+P5Sw/fEc1gxcHVJrCOiau8dRk6QPqQJa8oS5slLtEviPcJLsDm+NaRe/5u3VLLHXWHU/gHq2MoMbdprJAvZeZ5kqKuW5PirnybuG8O3Bqdo7Bo3NjwKMNEImUanGWmnG6YZYdfYpCNDDTkIq3tjjBpDij/FawPIziAcm6bqlscmsLrlsand4Y9ztYzwyeiMODypO2orRHWM1gSy1Btk7SxGfnPkEj6BcnFRoAWu+glLiFgrMHHkEiYPRVMf1XWZ3jY1jL1rFBqo/mMVKS9SZwQoIvxcY8/i5M4brP51lDGSiDi8jcFvw5QQ6ZETNP+sneI17QgLHSEUNhG4S9EMU2F8gYnCqwe4UJEuuKcnj49xsjVhZKfP67QkO6cvRV4vR8D7nxDEGTvNlx9SpNzqD5DwYUi85oCmS+v4qcgWkeZKRB6RESjkxyB/iLaV4vBGEzEa7/lJbJR9jqzIaM9vQaQFqdPQxCiImcQVB+YggfhX+wp4CfIKJOzD4qOgj8ZuqgYuYdVESpx7Atb4wnR84oiII/Ya7TsHmyh+1y8aXLeCsd2pFyCNFWzOZcCKQtMOJd6r4ASXTesyHMXXNXY24u090KC3C5dwBdKcClL3iAr/BPATrd3m9muB3fIJk5Eo4lFJvyv8XiHb/lOKpmtvEi/O/ggnqereelctLCBrghwmH9M7YuzvIev0Q3OfvE3NoPn7XsHFz7ReerIQVz24K0wGhujulimZdU8YtDdnqFlGa7nHvV0FnpADw57U4YdFI7v5zqu+q+QeFuCtF0+lgbZm64gbhks02HWKLYFYltqAMd6dkSuYY7s6Vg9bdPG69wVWFXVrNvAVkc2MENtstjeF3OJh9iipzDCeqHEsM5prF/M+SvqPBnQT4a+rv+dpTV7WG/u4cWho9NPFKUYzyUjGPg3t90vtej02ydjWxqbdaEd28Y/qPhRPeVaARXAyovOqRxXFMPqMWDyvYI9TaRNarb5I6/+E6f3Syyy0aeG4yRcZ/ABqEMdB2L3lji9ixuFRt2X/K07wsU/L/iwL9FcqTUrYBcw+kq4Y3mbccuOR9m7ul5dn9qjjlqhBwasEwzHIAH5XIMR8q0aPqom5CYt7GED7PzyelOPrj/CgHD7IWe3PQ8MzavLrEiQPaX4f8QyQxLyNa5SQgzwY66TxA8zSR1javBG5LW+C9QKwR16MYUhe9zvamhHOp0S/8ejeAwfbo27K/BL+gbPV7cu0h1+XijRxs9s/MfxOlxBURX5WlC2vxDHSO46DZP9rsd/3QWobguB0z4hLlhz64snd3dciVpS77jlvPjmv+4sItKKIcStsW6JNHBbIgoT6nIByrxbJcG15AcrOcAjyPLV+Ib9jVrpu2PPXm0kOP16dXf/PfOwx3mUJJJ2wROyPnfuj7adjrJ47p+a6mb9aIxr2YXHDPO6JzptZLOS0/bZmo3Gt9ypabGHyi69HnKUZIndgVuA2uXZHvtD82iNnjdcRdE8EQD7EWLy3NZnmZ2GUPWGRnZmFTqlcg/s9przjm9auxPsByhTZOgMPo13kbZqDfdJ4D40LTa3CMOtU/4Sxz4s9IG/uQIIvAZVoW6W43hfairfZbPWkA+nXWNh/povxkH8aN+4BVJBQ3v8Y0KkZ/INtyucBhapK73MkgSlhStMr8e88XEv9YQnOJehxlYSpHbL377d7OP7NvR9s7ZB+nFfhr1bs3cYfrQfJQ4wNOdnTfGvqb3cEJRnkGCnyFCvrniynofzV/z/Q5eYLII63DQPe0HbjwI3v/L1gAfscEUNwtnn0iXokJzhg/o8mLcOCCCnjL6/LIgt3fyoN/wn45L1xWlwled9E+ChLQfRHCiLuGoOigUPVdHsfbz8mWjFEby0opZWqMKYen49jrY4miqwor/5oQAmry/vb2P1sdw6Lf6Jpog94ox96tGFWEzR0XiFMVzCDSWD0e4RlJgpLm5ccse+kofCV9nOaP+DTMJlRtj3BRtcpLFvXw14p1tmOkeKlhcaPG/ofUre1Y2y9g6IQIp4F2x8B4DnYE3aO4HeWHFmXwv4/GOdVlZ3mGD5o2biCSVNCx/5ZeRHpd0Oieck+F/fF4IQbZVfmiOdTvcqOi8VLrNRXaNeJGLd3532F9VNRPozg+V6B8oWITp/i20d/y7AERuoQlKfPaJT5PST5pEL7J0fm0E2HR5Zb7H8WTejxQpkuQz2L2z3udcwc9Z26+FxgBA5EsY/mOivKFZoyKsIkEnrvd1Ak4hnjhfn9f3nmQ4GTs53mCzSZoUugmw3WuQX3RAG1Ywxb51scoxh1zjsP+y3iEq4g2XAjVHsymWRMsQ0Z13m1wckkIVO93+WMdTxmOQbJw3lOjvHo3KZ7wjYxAvPndVDMHv4+xb1JOmLnGq7QAr83J0SjrB34lV3UNSEtfDDikcMMTxBN74vy5TDH+zvHndo7TPH+TjGha5rs22F+jA0DGkL7GG3sKUWI4/OfzFb1izQYz0A9SrJLmBR7kxR3y7elU5xmWR5tny82zrKIQYXfywNDTennyBq9T9IHaYzwXp+3wuz9ackSLpoMXoPqYU/4zCrIx/bUsMgXQSnFcM04nYlxCloX62/5aVkWQXnyPgOSFaKsI+TawLhO80UkTFdNksCqitUvmlBjO7aHt/z2RAq9n9uO8+q37P0c1xE4am57LxIEVVPCLsfZfky3cUl+57MkkzeV0MiesBUUG/sl5sCxj1LH2tp2PPQBqba82h8/+IGNpmWjs6JsVvt4nkINKeqzBrMfc5AZC9tEXRfrNJktoZeDg5YkS+8T3e4JY4Yf9J2VxcqfDdnaYTfbCv9u0HXDAqOb23/CxJADzyOEC1/bi7Nxwzf2QJAlel515uzxS/vgaSRkw9M7IfimUAXEFEefPhf7EvRDjQi34rFN4hHs+Om95aPG28iSxMezH2w5rqlstO7feyB19os5RAGs1iC93xebOKJfVL7m+iHD1wpmF3uJA9A3nthhC08M2z9bAIKPjB8nCXm+sPMNijmUdS1YPpdutCJ9LvJYMfdUeWJaEiayZ5ynEg7ZGUu+wGF1IMteRhCyr/Cp+gwxU++hl0M+uKj+DumroVaGIe5cJnTuhiC86bbBbIYAWoR/db8ZEy4gURcQ2U4/NtkiJj45WcLkoWj2LvPJKLECW5nTh7xqg+G7yMYYOM+ra/B8+gypkfqgQUj6kNqwhWfCvEWjR3r4i+Y+JawRBufhghBRRM9JHKwyDild4kqgw6tHSVPilOYX4AUTZL9eXeRH5y49IoYIz2Bt/eESP+o9YYeTlySDbFJerxnAaC5gmRbq94Utj4hqkBFsQVF0JNrM4n29yWIyI4QXnedpnYLM8/FGtvbWX5wjGQXSf5G0VaTtPZE3aUyzxfQJ9Lg5QbuJoskXQUnzFKHCcTr0V58OkUwS6ssmcXr2F8574GOfDT0dq5Pvo3XS+zqMw+qYEfloN5J7IqsX/T3ndyFL0YDl/fS7TvsdY1lUFbLNs8MMxplBh4VuXyIU0Eg+w0eYhRmAV8uirG3fKrcLf0LgMR8/P193p0qxz5TGjKmwSn+GKCTJeOdFJMSpsCxhGQvfLFmNbDp2VuJXT3F2s5DtU5ve7v9v70qa5LaV9F9x+DgHa3zXm4hWa7EiLLtfd8uKNxcGVYXuZphdrCBZWubXD3diyUwkWACXki+2upBAbh+TCRBI/BYXtiPTng6P3Im2pNZlRJ4gn5A3cYZYWif/UXy5wrIBzf7oC7F/u6GLtfWH9bI87NLTXrw/3CXVsPEwo5v2bekmLop6o1nVUJ69jNwP5kXP+6Q0CyBOGsnbDpAPooy7jXl+rhCvBzzv4gV4TH+287jN5FZUWVZ+VXxK9o/irG+Z7Qj/mx386NgO9ymPj13WgMjGH6u+flXxwXQtX2V1iD3zucyTLD+z3HejTn3po7vF2VG/eqk0O6POeQH3Y0TmmwCk73kB9PY3h8LMbYIhdT1v6ViW33GOM3YNUaS41/CMBRBXZ3astupLWXw3CcaeITzZbGupJjfVq+Up21/Xqk57ONWB2I9oy3CSVwGObpY1BjjzjMWoiuPDOvQMU1C8Xe7o12Em+LYfguvVjtUkryq8pi3snOtJWXw3CcaeITx5I/LnpKg3l7SVi+QyS1Pcqo/HfmglvpN8DDJ2jIrmEF6OaA06TYNe1z3kc3yu110f5rO9vYInev3e7d7yN2fdwI7nSBR5xWzaUzxvSoMK0Ms/SYa2c0CP3oovifj6m0iPD6f0MPEF7GHpi7PrxYs7WoUnO6TvfpYon+Kis3iADcOv0uyxP1B7qb7s9GMd02et01U2u8mKCRsox54hHtL6PMiP4ktvC4e+wVE74X0p9LorzOM8bc8gETxL07+y+tPfopVCZ4jclaJXh+LrlK/pct/gr9HL9cCy10v4iw2tn7yFhrr813iZ1aS79do84D+iaHZLexjqj8xxJAzrV0WR7ZLGsx2Hf5/ESezbk8RlGe+e6jgbvU2Mmd6bw/6nejZS3xP19ZBmYwWcO5E+/DL++OGUlskxTXYV/3/9/N+//PLrz/oj8+eh3W/9U71xuz64ch0Xu3hvmqNSY4+JAUquyIRQqAL+l8G02RtTf56N0+vsUJR5XBncfOqTwy45xqluFI2QGSBqXYch9ZbX4lh/7TqUpOYcxrVfYeYDD80BNmO8fCFhig21SD66jgJNIZIdqzao/gyPNgxjgZCFmyo4uljs9CoES2NLCmOoKuc59ocIaK4wWCymST0Xg1+/ltZe8Rt1/0cx17fLvh1+mwVrqsCqIFpTEHSBFgqDLE0fDkfpquZVwAn85m04E/LijwInyELrgdM41VoETsPWDI9xqcnrdd+NIw2bbuShxh+3HlPgPUWY+xeOJsOGkqtjZfJ6+10nfiKK6C475Ttirtf1Ved6w4+zBBdjIxckS2BsDSrPAC564xrCk97ctDjM7uO83qbpJVxcMMycXL4EzIgNjovBrHu9biqWQSmb0XYxkcwlPVtjIBsQZgljyyfiy+NrxlR8CrzIDSuzoqv/R1fWrV7v0HdqrDN2SQKD4ijtFxPDZK1c4tjSiwhR5fnki8i/39enZ1HfykSKU5UGpzmgQzT0hQtU1TDYcHqvSbItjYkhi0POxqwrMdeEhvB0QWm5rpFLVr4aXG1mxXJBUM2/Zum2arXwomVdQ/whblbO8hkXLmW2ynBqw9YXMBVttrCI2cFRQQWuxLkODRt0UJHA9iBQc/a/nwjkzFbusCrsbeYNtwKwzf+mcw9vC7/ttIOht6IaLakraLQnNRlfatQRFE/rTbPADz7mi4s1UASBoGaCGZDIOOaMMOaca14JJm2fdQCvI37+IVDogoLF4IcfkJ8Ld2U1T6nk+lKpKiJQ9HVhTJZXxZbasnlMKeo4YGkxKPWn4z2CyDJ/1GpPNiMNv20dAGBBh5W7ngDt+c/w6sDg/ojOCAlFuOV2w/Un/IfLB22pdd9DDQ/Dj7O8ZPSaKpAogeNMr/AMqCIryCAs6SoTCyHLkiA7BIiLxZWLjxeAFV5ZaG5UvUrStMro4apKkzBl28TrEve2iwYWL9X4y6OhKy4ZwUqs9OWlVcRURBnaLubl1Wvk8vJaDFftTSR3Zd7UHiiahCjqr59BwTUQyB4df5wFXJDkqjwgQRCYwQYLAzNQLQ5f+VKhRbDWF1jZBr56aRUZxh83j6NBlU1gp6+/sg3s9NIqMow/bh47gyqbwE5dOGYbuKklVT/WNj9sHi+NGpvBSltkKDKFdvVUQJS0MhoS9D+H+Z7P9aIHtHSKcLjV5MvhRa8OK1fwtK4w6r1VfxqN86CLqv1LyacShkGgbpI50MiuhYzhk1X8eAVgtX3Vx4BAOf4HBKkzQJYGqKXu8tzrnU4RdFXLXLYHZEbwzbrgNRVwqwPbhiLgGkE3V8Q7G3jLRro33+rL4OL06lQ+1SPumkbtlbzqiEdpoFbsIwk3HwFJ9VwAuRgW32b56blZlPUNPPz74sBTGUn6dfO4GHXZDgia2zLnRkF7RacBg+7ny8ABcA3pqoEQNf99l2enI4oCicRwXvfzLC+ihqEpQiDoYIYJCB4Wo1GuNYQQQG53j4XEywJBh+/LeSNOQ76C5AMT+xzXhYTQ7NmLo19nzV8asRYDUXMZQYBNclTuotxY3gzS/bL1vXGtGhxGqsEX9v4mJs3zgmbONJePmsUz3L4808cifhS/JZU0+fcIriu10jJcsuSgPCrBxRTiUtTi8F28EheINeBZcY8RPwDE+DFlKXw1Ei774mt2xK0ZUYOUpgQBt8LNhp1RkS0BZv01TJaBzYz1StyAs3SVknfJQ3kd5/vo5lRfsFaI/aekfEJ0mO5Gy7GkXgplsPHHcJGE7aczQTHowsIE6IrFIaLkOrBCU10aKNZAkoPyzJD0OCHAE9qc856+47qw9lF+FFaaDa0JarPlSJNxpnh02bTpj6wU68+zaylNCdpft42hUZH159m34muF9pusGqDog9Mm1icBwRVxwPbNr11CWm1iJRPCmdeXoCUdXw9cZgtDU7GiuGXZwn7N/ahrfpP1QhrF+gLeKzEbgAY91v8a60VtVoxguad6LTByjAUHtSFYnVG2Yz2BiL0sMXRY9iNtX5pyvkI2/3ym/1kz+oLZSnnKD/VlOiLAXuNA+bAkspbaKC0XkAPL+mwi+x0O8MwfVf4pj4WGlyVz26wR5DrO25Tl1emwTwX5eaL7rCJRAl+85FYnmOgSaSmJ3hjyixZmizAAMnTj8BxFXA+ENvGWWgPM5nxXTULX4q8rA1vr/wa/BmDN+EV+Eq6W/jDf8b87il3y0J0+vCrLPPl8KsUGMEbKD8mFUW4dfbR6W4AiLPqfx/rPiKOXHHrseOABIVRoJHRlSNkThlmJmg6hcyMopSxrMgEOsNLgytc2NHB+yNh8NtgWD9iUBktjvk8d7uNHew2ztWQRo8yQLHLrhWQLkkoOGcKC5ccAcFkq7tA+BZz5I0CM6/AlUVaRLw60v+I8iQ/lEFuvs+fPyaEhjPAr4+XzMDKRcg5GaXBaFrTLBkGLJA9zxAs1UFC0UYpypJDFXjP+NjM3Xz1Q53/vnovRpafqDHj++1S1VF76eEhwjCpEMhbUhosMj7iBVg09Wey14W+7MZEDyYuNflsOeT3k7EuSBiHg8rmXIVeLxlmXHT3AcjVrjboSf8XpaQAprWEYXMyL3EZdjpgdYUgMT8JTGCi32jrgWR9gaVgvnk5yUoZtJ4aby/6iu/j5mIrX2ddDmsX4EeGBQFl/GX5cORpg9ZZHgmr8xbBwn4i80m8nlDrs1v1WDRG3/nqDiSBvsUF6RRbp14sotj7qw2EmS7cCWK1/SrkMiGacNrrhZyUTxXE7areReP1AMiR32828PWCZKnGYKu5cEcy8AsyaAv2DEprp6vAxzOXeJmlZ17sNfrxhrjClaUYLaRBfzrEJq6786LbsMYoyy+vEK3mO8+9vvu2e4sOjuI1LcX3KKxa770R63xGoqX3/Iz/INSKo++naXwIl5JBeYUDS6sGLYKgD1gGN5o9/MLEAJhTLL3cbfLz7+/2hkmX3993pc7HLk3av+CZOXSHCq3fFYzSbP4OFaeayQLA63K1/hrc+0M2Yx5+DuaWz+atdCly463eZMxDmBtHVg/Pjrxexxjnqs5k1zquHhyStfhHRTHeeDAzVgcZft174YFSFw2zpgirNFT1BEyccCgZv8yqkC8t4TJ02ketU+n2pAP2hAmr8KKK3efY8H0pU5lrepDZtHh+aQhyOsjPWApD77B94rAQeoysWTFvL5Etl8t+zx0j6d+0oPNnQ6NSsUWubKYMduGLShMpdKJuFAZqsFCuLUUVcBdQ2sQC0HKrmjFuucFo8ZF0/id3f2UnfQWv8jGPLoFRAZrbOgjZYLVq0kHtkLfYMA0ZEQxYu9a4L1sHcnfJK48eb+HtTi/n9IanH9VSSGU+3dMZaQUu9cdt1lg19WDwlT6wGH31ld1ojX34OVkkVVIoULWzJ+GkA8QtKlwryet/F8Pl7tovT5P/Evpcx+j0+PJ6MWY3k/YFAdvf44ywINMRWhTFbg6AONlUYtJk6cZj2Ei6IL98TgHD7v/Xc/zJy/s3k+t1XvVvxJRFffxPp8eGUHuoixLVLxsGbVc8BU9XvZZ123WcR1t8Ku24MEH1Dm/OWTFMO4EszQMQ4AXMW5nqNZlkm43jEifeSOFQafkVhpZDhTl8MUn73CnTKrB1NSufl9qqk2eN19txMFJlRTeoydyCTWSt7UuTfLyhcoaZ2YjczjOp/32RFicejnsLwYfvjPFud3KHkKUwNiq4QQL1siwHpD/G1cIxHUpe545HMWh5S+f2C4hFqaid2M8Oo/nd9XgGPRz2F4cMZT61MgJKneDQoukIA9bItl3pnafpXViaHx25/JXfqp/Wbfcqn81fycqPxgmIUbXknnkvgq/7h6lB8FTkxnxtoDLf2P89z0u4ckPma9I1KrxVco4jrWEGYtHy16JoVf81i26HL0wLG7IDq/rKuQC1fvMAVT9s7xuIOonkPr7xpCkTVT1XVQ+T9Wn+2F2+TvChfx2X8OS7Mj311rztRAoWmfv6pbUULet3tnsRz/K+f95+zyvPx59QYwAhDOjdxEvs3z3GSXpVlvHtq03GALUgH8wdJLYKMZakM3mMTxG5s5atKK2hVy8qqVX63y06gMdVmiJlKYeHWfdf+IMqnDLKf1g7x00hsDK2lBUwZrF1Asay9XCXliMaUhcscZ0kysj8xSYEBbGwCn5ih1cLhOi7FY7ORxOAwNkEcxlabiZJdeapPkpsm6ltAE/WNPA8QXDQCwh9RRxR9iJvL7tj+qe8GTnKBBFaQivKaQmgTQblrweStNINMFQqetQnUGBSUvXsqtsG7jh/iw+khbnxFRCKVipJDpmTLYhHCzl2lsD2o+mzEfF51CvCx1YmYbAl+NCMrh+GspcFgaIHGHxptCtQPFBzf+hZQ/L7RMnx/wzP6ZtYJIGY6jY1nWT02FXS/VEk19Mxr7SBHlcTCcPy6ZfAamyA2Y6uFw7jfzeAwNkEcxlYbh3rDl7gr82b5o2gv7QK4gWQgZ5DSIsW4Lm9wHpsgbnWrPTpKa2hmUJQawVgotTP4IBzwsdmhpj2+j4abtpkKOS2FTQeRPydFUc3v+hU+Ux+DBNTNoLLNHL5Vae0hTq9O5VM9B22vuEOloMnBmQXZwyJdc5QXedilNohv01xErAe+ob3PjskO49M1Eow6Cg4njAk5fkfBGf9dnp2OGJOukeDUUVg4dYcaDCbd79D4XRMzjf1YH78cdpajeaxKRiWyKqVFinfJQ5U25nuLFDAZJAVMyZSC4Exz47kReQlIbag7WRPThvKPrIQiqdSGMmmbLUxuxddK4ZssOZQF7jCQCmIMEjLyL2TaNTZhORdrgtUTIh5TmylOLL/dimo6cKgngAIMwVo7bEaFxKqeflU9oKJOAqupU/Hmcti9uNisDqOn5nfIJcXcmR593bBpL5IctB3ZY5J0bLlcJOL6tLnjE3Ng00h4q2nn8SEvNsP4k50Iuch+0+TlC2lZt9Iu6nFdT2EIxJPEGSnI1TVcs3TkDl7relikkwrMG6JIbRBfqdk6j8/AFcvud3jenjHWRMcCoMAsqm+CZ1B9K0f0AWSwBkMzqggXpfdVf9E48jM4NdTaQa+oJLYFD6xMoLn+gVGCyyEYscNK4714PqYx+KTCZLaVx5GS+amAkMAkoT4dsDn3LwacsUFBvV+4bN+Jg6geZCo4miTg1MCgsq2JjgUEzVXRsQ1cFx2bLUw+5jgTqQ1iIjXbAkXVe39KxX1c/A0FCqUZDBQKhc1uY7k9025jG2i3sdn2NIq4qB6cTyJ5fIJSdK0dfP5UEh7D10k1iyjgMGSSEGwlKs7ahiUCAjTESodT3NMLXQGPvUpArUpppNYnUCpUAzyDUiv8FEoEfFZt3SeKXUthYdkSWcP58zFOHiGXjk1w+O5brbhtbE29sXQKGLUaEWON/XdRliK3IBcjxNbfIVqbkc2KOKa1TRrQ7CaZK3MsucYIWWLwEmq0fgWwwoFQwmsdCLGjOAw5eALwvkOpxRQM1gAN+gVKJbOqXT9Be3zXik4Aq6zS2FCYZ0VRDZ7iXE0SEHkGldXUUOxGYzYnVlf/KpEpT98CJjF9o22iE38jtlYoreAkRyawsUK+vRCfXXjfW/q1f0IRk4T6iBBdHY9pIvb3WUefCPun0L4zDjqDgidDR26XQP2oj29DQOjs+wRuRVGF4GZXMWMbRPdtFN9tYVBQn1g7IoYj9M+jlq+8NDnn+2tUk7IXwIb9MLyPz/yP0Eote9f1OM4yKnM1NRrpXKUASh9gwgCkhEwANWMHynCQ0FyEkVuxfSgDASN9xFkprViiyGVlnjIy7WuQYPsrVCoXD9vcyvClwVDaP2/ZiR69TepnSepA7UdvqfWN/uNJCX2PecUc3z+u9CS3yTfD8Ha9v1BVdzNLpO4KJ42i0uKKQTvVG32oHeiYaTCD+DWD5G+FBxckcievaq0EMeqe5mjY22zaB6HEldI2UjdqIHuxoSNKYHetybv6fQZnVx8+yQSd9TLlX436w65pwu8GjX+P6wl+0xGdf7irSeX/0V2339LUnNONeH9oJy7a9wdymgLsCZrFbAxrnvs4fxTgE8Hp5snnKzNPP3Nzwo7eKSRyoNhjtIU0jAtq9E7+Q+pCZgEO4RSkScAOIXECnDZSBqGOD01+2UbqOSH0VavSEcoA55ZaLYjzSFNxNV3t4T06hiZUdZM2RCBFjmDJ6nsMo7pq9lzLIA2WbM1kAuVwGJFygXT+0y7o2FnTmTxONtnz2tE4mQUKAbyPZ7UgVKADge1BzGR/SEDyYA/KzCZRl6mjfp1adIvbdPrO74yrDR/KazSmj9oRo2gL+MBg2JHBIAbEUzV+Z+LtBCiLqLcWk8kHGqNhXMA8IGEAU0CHNFsTkGcv3VXvvsVQSusk/tXVvis1/bAjutNV1EyHK6oSevfSjKoP35OGT25E8MSJCY9rJ7xblyOnt8GekAGMthCGwIMgTuzFj2sww6skTatAOoxMGEEjDWcCFobOULqv7zYOjWtt0IZ8BLSqDMoAWKkFdzNAR87HC2YAW9AdcLX04/iNPthRe7Unccy+HYVzbN7dNH2lAdIcJlEIE+jVEpqeaCUEd1X7QgGkqiZRCFX1cgZNz/HH8ydXWZqSaqoEIVSUax20cyaolsE01dpyC1E7IqycTHKmkEYPtVTE0A8pAjFBRX1njrwlhkpjeB0J5ZDaDq2KlnoN5EjQNiFwVLIWhXdT4okQr6P9BWcoTCm4ShOCG7NYybQj+jxkEzajz2MaRno9O5qWMhFVU4VMR3kdQ6CJU2emGc2pXoy76YaqMaSdAKoQRjHK2zRdpV/9qNtslbbrq5EFU1jZ7D1qDG/onqhyJNe6QfSVaSwiKxV1RpHBSjlmb7OjX892Q5JubWnOFnQZbzZPojws9cRKdB5Fn/m5bcreMFZVQDr/SypKsaemF1zLaaqiVGzSKEKEpXDqQbWnonF/Bb6RA+5A7GA4eyMHVOlKGYWsXOXJNJ3dmXYB7yh39+sqzDFU08JtoJP4VdyoBDb287SAMspPfJM2ifx/iQ6val9/Lbqp5mdPcSH2n5LySeJgKm7r4k0dpa9eYa7pilaPm24I5bkdx8fNAHfwpAjYE33iWaX7PJnmo+x3tn3UXn7jwlLmGSr/WQKiRBIgIMpVC8d+YEFCdxWBGoNkKkTSh0iMiJqKzSCcIol+zGJ9Luyd/KJjGdP05RvxZ0Kj8Ku0XuDyrt9F42l7r1ydMhrHxbVUCT0JDvY03q9kJc2pE6F+R5J1yqcTbmnOp9QEtQQ8kDJMqANqnXZPMlXC9IwFboazUVr//g69bUIvyRrJN9tATzhObp0RmPfvyHMD/Eod7cmHi9F2T7+lwKwHA1FPBk4c4uFY3BTEhBGl9T9vnNsMZJFhxsZuS0f/BmJVUZZHY1b2nYAgoogxUoEZBNeEYQj82O3CMwhjVLUgNDE2UtjZN1pp5q4QJkeb2VQrfQLMkivkLhecOliYMAvLyCPIrUGMQexTwamtSiHaAGqswyREIXHuKUv2EMSqu68DmIwi7LJFXcqoBzGx/SXO6R3sEd2aOdW7aCfZVBkCNxB0bW5jCuo63K2aeAJM58cmx1rhTUSmk+y+VuVJrXl54yrN2BRwjVC2bJPS48xiFM64ShFcanC4sO30RIgZKGePhmELKER38fMxFWMJNlxxjZJIXSYXeQur8nD1h7IvFlIZobQvJE3fOWtcadJ0x28rOUd94t1lEvl/W4VX1VjW7NZK7S9ttEuwl/bUlVkvZnEyyEWbQrvX3rIW79J9nrV5m0T00AaxhxP/WVPRL3mO8+9vvu2e4sOjuI2r9Hy4xAhYXLR2okKweqtSF37hG5PUNTD5oqd2sQu8x+lMIzR/sLVXqbelNnKREvn5xtonxFccy0VSzUDcW6H8mYkIyrYu/kPzsiYarkuypmwIZciUzbgGqv2yjN7wNEH9/tajiPgibhL5/xRu3NzU9kQvZZp4rIEdLQjqEHECvWjpbjjm4Bn46n1I0ds8e6bsQZGHMAh89VMXVMibnM42xX3mYAiJeOtmkC6QiozLpKB4iJNTIQ287KoLbOQNVtg42BieTUKBAqQLgYd51IbveIqAG6iA7VPcvoR5sEuzWjvZ7sGixzKX/5g3Wk3ZdKfeDRW9PyRlEqfEhlqqA67ktM208A1Yd+3+O8utVucbo98wbLKy2wXtG0hdciR4JzLvWrKJJYDkO7/s9X9galzBM4v/QHebtUNYryubYg46MAcPyHog9hOAu3mTcU9OVL8Xr7NDUeZxUl+GUqVhg359wav7LML6EytN/nnZzT2hahY05UTvKZLnoPY7hzy6SWn41cnqWlem8rjGqzagdC8TF27KVU7A+sV5I4bHLHCTVbvEQVxRdZ5h+9JjIA5hQlp8dnGzBRSXrt/i+l+5scu00JkjhkcUcGFZMwZ1E9l5hu0rvIGIgglp8dk15BZQXL9bjf1eNO5kA94Cvsae4V2L3FXXviJs9895MPtYmg5+oVL0tFpOdfCWNYr8Kp6UoFlzkWmjzpzr8dOds43c/WVP4kbKYJ+vPSr/8kU7SG36ys8iH9pevmhve+x+qP6spq7VzO9Dthdp0fz68sXtqer9LNq/XosieRyHeFmNeRDNvbTjoD3N+8ND1s//NIl6kr65v35DlPE+LuOrvEzqSwqq5l2VfTb3mDYrNfVFhp/F/v3hz1N5PJWVyuL5c6rMLl++oPm/fGHI/LI9eVD4UKESM6lUEH8eXp2SdD/I/TZOC21GjQ1xXVn/nah+b31ZPZylePw+jPRHdmAO1JnvtTiKw7566O7F87G+z7v483AXfxFTZPtYiN/FY7z7flOXS28WnrBB7I5Qzf7ydRI/5vFz0Y0x9q/+rDC8f/72P/8PLWKygARDCAA= + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 1d9b57ac77..4eefab19db 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -116,6 +116,7 @@ Properties\AssemblyVersionInfo.cs + @@ -289,6 +290,10 @@ 201506261756463_PrimaryStoreCurrencyMultiStore.cs + + + 201507132241575_QueuedEmailAttachments.cs + @@ -558,6 +563,9 @@ 201506261756463_PrimaryStoreCurrencyMultiStore.cs + + 201507132241575_QueuedEmailAttachments.cs + diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs index 4e53971a04..ce28526e6d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/EmailAccountController.cs @@ -187,7 +187,9 @@ public ActionResult SendTestEmail(EmailAccountModel model) string subject = _storeContext.CurrentStore.Name + ". Testing email functionality."; string body = "Email works fine."; - _emailSender.SendEmail(new SmtpContext(emailAccount), new EmailMessage(to, subject, body, from)); + var msg = new EmailMessage(to, subject, body, from); + + _emailSender.SendEmail(new SmtpContext(emailAccount), msg); NotifySuccess(_localizationService.GetResource("Admin.Configuration.EmailAccounts.SendTestEmail.Success"), false); } From 043545159c6256929f6026897fec347015d47045 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 14 Jul 2015 12:04:53 +0200 Subject: [PATCH 0242/1256] Web-API: Added OData endpoint for payment method --- .../OData/PaymentMethodsController.cs | 35 ++++++++++++++++++ src/Plugins/SmartStore.WebApi/Description.txt | 2 +- .../SmartStore.WebApi.csproj | 1 + .../WebApiConfigurationProvider.cs | 3 ++ src/Plugins/SmartStore.WebApi/changelog.md | 36 ++++++++++--------- 5 files changed, 60 insertions(+), 17 deletions(-) create mode 100644 src/Plugins/SmartStore.WebApi/Controllers/OData/PaymentMethodsController.cs diff --git a/src/Plugins/SmartStore.WebApi/Controllers/OData/PaymentMethodsController.cs b/src/Plugins/SmartStore.WebApi/Controllers/OData/PaymentMethodsController.cs new file mode 100644 index 0000000000..ccc87cfad6 --- /dev/null +++ b/src/Plugins/SmartStore.WebApi/Controllers/OData/PaymentMethodsController.cs @@ -0,0 +1,35 @@ +using System.Web.Http; +using SmartStore.Core.Domain.Payments; +using SmartStore.Services.Payments; +using SmartStore.Web.Framework.WebApi; +using SmartStore.Web.Framework.WebApi.OData; +using SmartStore.Web.Framework.WebApi.Security; + +namespace SmartStore.WebApi.Controllers.OData +{ + [WebApiAuthenticate(Permission = "ManagePaymentMethods")] + public class PaymentMethodsController : WebApiEntityController + { + protected override void Insert(PaymentMethod entity) + { + Service.InsertPaymentMethod(entity); + } + protected override void Update(PaymentMethod entity) + { + Service.UpdatePaymentMethod(entity); + } + protected override void Delete(PaymentMethod entity) + { + Service.DeletePaymentMethod(entity); + } + + [WebApiQueryable] + public SingleResult GetShippingMethod(int key) + { + return GetSingleResult(key); + } + + // navigation properties + + } +} diff --git a/src/Plugins/SmartStore.WebApi/Description.txt b/src/Plugins/SmartStore.WebApi/Description.txt index 53b6ca55d7..75af20211c 100644 --- a/src/Plugins/SmartStore.WebApi/Description.txt +++ b/src/Plugins/SmartStore.WebApi/Description.txt @@ -1,6 +1,6 @@ FriendlyName: SmartStore.NET Web Api SystemName: SmartStore.WebApi -Version: 2.2.0.2 +Version: 2.2.0.3 Group: Api MinAppVersion: 2.2.0 Author: SmartStore AG diff --git a/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj b/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj index 114a7f15ce..250694e7d7 100644 --- a/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj +++ b/src/Plugins/SmartStore.WebApi/SmartStore.WebApi.csproj @@ -204,6 +204,7 @@ + diff --git a/src/Plugins/SmartStore.WebApi/WebApiConfigurationProvider.cs b/src/Plugins/SmartStore.WebApi/WebApiConfigurationProvider.cs index 0c87fc0992..59d82d0e80 100644 --- a/src/Plugins/SmartStore.WebApi/WebApiConfigurationProvider.cs +++ b/src/Plugins/SmartStore.WebApi/WebApiConfigurationProvider.cs @@ -8,6 +8,7 @@ using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Domain.Payments; using SmartStore.Core.Domain.Seo; using SmartStore.Core.Domain.Shipping; using SmartStore.Core.Domain.Stores; @@ -72,6 +73,7 @@ public void Configure(WebApiConfigurationBroadcaster configData) m.EntitySet(WebApiOdataEntitySet.OrderNotes); m.EntitySet(WebApiOdataEntitySet.Orders); m.EntitySet(WebApiOdataEntitySet.OrderItems); + m.EntitySet(WebApiOdataEntitySet.PaymentMethods); m.EntitySet(WebApiOdataEntitySet.Pictures); m.EntitySet(WebApiOdataEntitySet.ProductAttributes); m.EntitySet(WebApiOdataEntitySet.ProductBundleItems); @@ -123,6 +125,7 @@ public static class WebApiOdataEntitySet public static string OrderNotes { get { return "OrderNotes"; } } public static string Orders { get { return "Orders"; } } public static string OrderItems { get { return "OrderItems"; } } + public static string PaymentMethods { get { return "PaymentMethods"; } } public static string Pictures { get { return "Pictures"; } } public static string ProductAttributes { get { return "ProductAttributes"; } } public static string ProductBundleItems { get { return "ProductBundleItems"; } } diff --git a/src/Plugins/SmartStore.WebApi/changelog.md b/src/Plugins/SmartStore.WebApi/changelog.md index 0ca6ad8919..f778ac4a79 100644 --- a/src/Plugins/SmartStore.WebApi/changelog.md +++ b/src/Plugins/SmartStore.WebApi/changelog.md @@ -1,32 +1,36 @@ -#Release Notes# +#Release Notes -##Web Api 2.2.0.2## -###Improvements### +##Web Api 2.2.0.3 +###New Features +* Added OData endpoint for payment method + +##Web Api 2.2.0.2 +###Improvements * WebApiAuthenticate attribute can be applied on methods too * Product image upload requires manage catalog permission -##Web Api 2.2.0.1## -###New Features### +##Web Api 2.2.0.1 +###New Features * #652 Support for file upload and multipart mime -##Web Api 1.32## -###New Features### +##Web Api 1.32 +###New Features * #618 Add endpoint for quantity units -##Web Api 1.31## -###Bugfixes### +##Web Api 1.31 +###Bugfixes * WebApiController requires more permission checks -##Web Api 1.23## -###New Features### +##Web Api 1.23 +###New Features * #431 Add support for localized properties -##Web Api 1.22## -###New Features### +##Web Api 1.22 +###New Features * #393 Implement OData actions for simpler working with product attributes -> added ProductsController.ManageAttributes and ProductsController.CreateAttributeCombinations. -##Web Api 1.21## -###Improvements### +##Web Api 1.21 +###Improvements * #384 Inserting sluged recources like products require an URL record -###Bugfixes### +###Bugfixes * PUT implementation was incomplete \ No newline at end of file From 0c37994babd7abe8bcf5b77d378dce841052d07d Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 14 Jul 2015 12:23:45 +0200 Subject: [PATCH 0243/1256] Moved BuildQueryString extension method into core --- .../Extensions/EnumerableExtensions.cs | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Extensions/EnumerableExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/EnumerableExtensions.cs index cd3fe2ffd1..e588f20f6a 100644 --- a/src/Libraries/SmartStore.Core/Extensions/EnumerableExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/EnumerableExtensions.cs @@ -1,10 +1,11 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Collections; -using System.Linq; -using System.Linq.Expressions; using System.Collections.Specialized; +using System.Linq; +using System.Text; +using System.Web; using SmartStore.Collections; namespace SmartStore @@ -186,6 +187,42 @@ public static void AddRange(this NameValueCollection initial, NameValueCollectio } } + /// + /// Builds an URL query string + /// + /// Namer value collection + /// Encoding type. Can be null. + /// Whether to encode keys and values + /// The query string without leading a question mark + public static string BuildQueryString(this NameValueCollection nvc, Encoding encoding, bool encode = true) + { + var sb = new StringBuilder(); + + foreach (string str in nvc) + { + if (sb.Length > 0) + sb.Append('&'); + + if (!encode) + sb.Append(str); + else if (encoding == null) + sb.Append(HttpUtility.UrlEncode(str)); + else + sb.Append(HttpUtility.UrlEncode(str, encoding)); + + sb.Append('='); + + if (!encode) + sb.Append(nvc[str]); + else if (encoding == null) + sb.Append(HttpUtility.UrlEncode(nvc[str])); + else + sb.Append(HttpUtility.UrlEncode(nvc[str], encoding)); + } + + return sb.ToString(); + } + #endregion #region AsSerializable From a900bd47412d34a54921976090d73d50054f0eb1 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 14 Jul 2015 13:38:00 +0200 Subject: [PATCH 0244/1256] Minor change --- src/Plugins/SmartStore.Shipping/Views/ByTotal/Configure.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugins/SmartStore.Shipping/Views/ByTotal/Configure.cshtml b/src/Plugins/SmartStore.Shipping/Views/ByTotal/Configure.cshtml index 779738d741..ae05d59b64 100644 --- a/src/Plugins/SmartStore.Shipping/Views/ByTotal/Configure.cshtml +++ b/src/Plugins/SmartStore.Shipping/Views/ByTotal/Configure.cshtml @@ -146,7 +146,7 @@ data: $(this.form).serialize(), dataType: 'json', success: function (data) { - alert('Saved'); + EventBroker.publish('message', { title: '@T("Admin.Common.DataEditSuccess")', type: 'success' }); }, error: function (xhr, ajaxOptions, thrownError) { alert('Failed to add record.'); From afc7e61c4ef4d60a5b496a14d639f8cfa5693752 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 14 Jul 2015 16:10:55 +0200 Subject: [PATCH 0245/1256] Resolves #727 Web-API: Option to deactivate TimestampOlderThanLastRequest validation --- .../SmartStore.WebApi/Localization/resources.de-de.xml | 6 ++++++ .../SmartStore.WebApi/Localization/resources.en-us.xml | 6 ++++++ .../SmartStore.WebApi/Models/WebApiConfigModel.cs | 5 +++++ .../SmartStore.WebApi/Views/WebApi/Configure.cshtml | 9 +++++++++ src/Plugins/SmartStore.WebApi/changelog.md | 5 ++++- .../WebApi/Caching/WebApiCachingControllingData.cs | 2 ++ .../WebApi/OData/WebApiQueryableAttribute.cs | 2 +- .../WebApi/Security/WebApiAuthenticateAttribute.cs | 8 ++++---- .../SmartStore.Web.Framework/WebApi/WebApiSettings.cs | 1 + 9 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/Plugins/SmartStore.WebApi/Localization/resources.de-de.xml b/src/Plugins/SmartStore.WebApi/Localization/resources.de-de.xml index 0159961db4..a7215f44e6 100644 --- a/src/Plugins/SmartStore.WebApi/Localization/resources.de-de.xml +++ b/src/Plugins/SmartStore.WebApi/Localization/resources.de-de.xml @@ -35,6 +35,12 @@ Jeder unauthorisierte Zugriff wird in der Ereignisliste gespeichert. + + Keine Zeitstempelprüfung + + + Legt fest, ob geprüft werden soll, ob der Zeitstempel der letzten Anfrage kleiner gleich der der aktuellen ist. Verhindert das Auftreten von HmacResult.TimestampOlderThanLastRequest. + Öffentlicher Schlüssel diff --git a/src/Plugins/SmartStore.WebApi/Localization/resources.en-us.xml b/src/Plugins/SmartStore.WebApi/Localization/resources.en-us.xml index 4b7f67b5bf..253bdb5938 100644 --- a/src/Plugins/SmartStore.WebApi/Localization/resources.en-us.xml +++ b/src/Plugins/SmartStore.WebApi/Localization/resources.en-us.xml @@ -35,6 +35,12 @@ Each unauthorized access will be saved in the log list. + + No timestamp validation + + + Specifies whether to validate that the timestamp of the previous request is less or equal than the one of the current. Prevents the occurrence of HmacResult.TimestampOlderThanLastRequest. + Public key diff --git a/src/Plugins/SmartStore.WebApi/Models/WebApiConfigModel.cs b/src/Plugins/SmartStore.WebApi/Models/WebApiConfigModel.cs index 0688b8f792..7dfb61fc69 100644 --- a/src/Plugins/SmartStore.WebApi/Models/WebApiConfigModel.cs +++ b/src/Plugins/SmartStore.WebApi/Models/WebApiConfigModel.cs @@ -15,6 +15,9 @@ public class WebApiConfigModel : ModelBase [SmartResourceDisplayName("Plugins.Api.WebApi.ValidMinutePeriod")] public int ValidMinutePeriod { get; set; } + [SmartResourceDisplayName("Plugins.Api.WebApi.NoRequestTimestampValidation")] + public bool NoRequestTimestampValidation { get; set; } + [SmartResourceDisplayName("Plugins.Api.WebApi.LogUnauthorized")] public bool LogUnauthorized { get; set; } @@ -25,11 +28,13 @@ public void Copy(WebApiSettings settings, bool fromSettings) if (fromSettings) { ValidMinutePeriod = settings.ValidMinutePeriod; + NoRequestTimestampValidation = settings.NoRequestTimestampValidation; LogUnauthorized = settings.LogUnauthorized; } else { settings.ValidMinutePeriod = ValidMinutePeriod; + settings.NoRequestTimestampValidation = NoRequestTimestampValidation; settings.LogUnauthorized = LogUnauthorized; } } diff --git a/src/Plugins/SmartStore.WebApi/Views/WebApi/Configure.cshtml b/src/Plugins/SmartStore.WebApi/Views/WebApi/Configure.cshtml index 222894529b..9e21e21993 100644 --- a/src/Plugins/SmartStore.WebApi/Views/WebApi/Configure.cshtml +++ b/src/Plugins/SmartStore.WebApi/Views/WebApi/Configure.cshtml @@ -98,6 +98,15 @@ @Html.ValidationMessageFor(model => model.ValidMinutePeriod) + + + @Html.SmartLabelFor(model => model.NoRequestTimestampValidation) + + + @Html.EditorFor(model => model.NoRequestTimestampValidation) + @Html.ValidationMessageFor(model => model.NoRequestTimestampValidation) + + @Html.SmartLabelFor(model => model.LogUnauthorized) diff --git a/src/Plugins/SmartStore.WebApi/changelog.md b/src/Plugins/SmartStore.WebApi/changelog.md index f778ac4a79..7d45bbd682 100644 --- a/src/Plugins/SmartStore.WebApi/changelog.md +++ b/src/Plugins/SmartStore.WebApi/changelog.md @@ -3,6 +3,9 @@ ##Web Api 2.2.0.3 ###New Features * Added OData endpoint for payment method +* #727 Option to deactivate TimestampOlderThanLastRequest validation +###Improvements +* Using header timestamp as last user request date rather than API server date ##Web Api 2.2.0.2 ###Improvements @@ -27,7 +30,7 @@ ##Web Api 1.22 ###New Features -* #393 Implement OData actions for simpler working with product attributes -> added ProductsController.ManageAttributes and ProductsController.CreateAttributeCombinations. +* #393 Implement OData actions for simpler working with product attributes -> added ProductsController.ManageAttributes and ProductsController.CreateAttributeCombinations ##Web Api 1.21 ###Improvements diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingControllingData.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingControllingData.cs index 0514ba29e0..d68ad50cef 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingControllingData.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/Caching/WebApiCachingControllingData.cs @@ -38,6 +38,7 @@ public static WebApiControllingCacheData Data() data = new WebApiControllingCacheData { ValidMinutePeriod = settings.ValidMinutePeriod, + NoRequestTimestampValidation = settings.NoRequestTimestampValidation, LogUnauthorized = settings.LogUnauthorized, ApiUnavailable = (plugin == null || !plugin.Installed), PluginVersion = (plugin == null ? "1.0" : plugin.Version.ToString()) @@ -55,6 +56,7 @@ public partial class WebApiControllingCacheData { public bool ApiUnavailable { get; set; } public int ValidMinutePeriod { get; set; } + public bool NoRequestTimestampValidation { get; set; } public bool LogUnauthorized { get; set; } public string PluginVersion { get; set; } diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/OData/WebApiQueryableAttribute.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/OData/WebApiQueryableAttribute.cs index 91f968700d..f3487d624a 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/OData/WebApiQueryableAttribute.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/OData/WebApiQueryableAttribute.cs @@ -21,7 +21,7 @@ protected virtual bool MissingClientPaging(HttpActionExecutedContext actionExecu bool singleResult = (responseContent != null && responseContent.Value is SingleResult); if (singleResult) - return false; + return false; // 'true' would result in a 500 'internal server error' var query = actionExecutedContext.Request.RequestUri.Query; diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs index 5878b455f7..06f25a322e 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs @@ -74,7 +74,7 @@ protected virtual void LogUnauthorized(HttpActionContext actionContext, HmacResu string strResult = result.ToString(); string description = localization.GetResource("Admin.WebApi.AuthResult." + strResult, 0, false, strResult); - var logContext = new LogContext() + var logContext = new LogContext { ShortMessage = localization.GetResource("Admin.WebApi.UnauthorizedRequest").FormatWith(strResult), FullMessage = "{0}\r\n{1}".FormatWith(description, actionContext.Request.Headers.ToString()), @@ -146,10 +146,10 @@ protected virtual HmacResult IsAuthenticated(HttpActionContext actionContext, Da if (!apiUser.Enabled) return HmacResult.UserDisabled; - if (apiUser.LastRequest.HasValue && headDateTime <= apiUser.LastRequest.Value) + if (!cacheControllingData.NoRequestTimestampValidation && apiUser.LastRequest.HasValue && headDateTime <= apiUser.LastRequest.Value) return HmacResult.TimestampOlderThanLastRequest; - var context = new WebApiRequestContext() + var context = new WebApiRequestContext { HttpMethod = request.HttpMethod, HttpAcceptType = request.Headers["Accept"], @@ -183,7 +183,7 @@ protected virtual HmacResult IsAuthenticated(HttpActionContext actionContext, Da //var headers = HttpContext.Current.Response.Headers; //headers.Add(ApiHeaderName.LastRequest, apiUser.LastRequest.HasValue ? apiUser.LastRequest.Value.ToString("o") : ""); - apiUser.LastRequest = now; + apiUser.LastRequest = headDateTime; return HmacResult.Success; } diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiSettings.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiSettings.cs index 5436f564c7..1f2207d94f 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiSettings.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiSettings.cs @@ -6,5 +6,6 @@ public class WebApiSettings : ISettings { public int ValidMinutePeriod { get; set; } public bool LogUnauthorized { get; set; } + public bool NoRequestTimestampValidation { get; set; } } } From 02527a354c42422c0db43a67e51aa1538ded7363 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 14 Jul 2015 18:06:05 +0200 Subject: [PATCH 0246/1256] Shipping by weight calculates wrong surcharge if attribute combination prices are set --- changelog.md | 3 ++- .../SmartStore.Services/Catalog/PriceCalculationService.cs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index fafe3b82cf..f6523321a6 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,4 @@ -# Release Notes +# Release Notes ## SmartStore.NET 2.2.2 @@ -25,6 +25,7 @@ * #186 Mobile: variant images do not refresh * #671 Bundle products: display base price according to applied discount * Weight adjustment of attributes weren't applied in shopping cart overview +* Shipping by weight calculates wrong surcharge if attribute combination prices are set ## SmartStore.NET 2.2.1 diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index 4a7ea62463..4028e6026b 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -750,6 +750,8 @@ public virtual decimal GetUnitPrice(OrganizedShoppingCartItem shoppingCartItem, } else { + product.MergeWithCombination(shoppingCartItem.Item.AttributesXml, _productAttributeParser); + decimal attributesTotalPrice = decimal.Zero; var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.Item.AttributesXml); From 0e81d9e8e581e70975c95da34aa74415918c1705 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 14 Jul 2015 18:49:49 +0200 Subject: [PATCH 0247/1256] Closes #646 Format the company information in message templates --- .../SmartStore.Services/Messages/MessageTokenProvider.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs index c91c6cf510..f4a5c24050 100644 --- a/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs +++ b/src/Libraries/SmartStore.Services/Messages/MessageTokenProvider.cs @@ -554,7 +554,7 @@ protected virtual string GetSupplierIdentification() sb.AppendLine(""); sb.AppendLine(""); - sb.AppendLine(" diff --git a/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/Index.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/Index.cshtml index 8ee7574be3..94fe748755 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/Index.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/Index.cshtml @@ -78,7 +78,7 @@ @Html.SmartLabelFor(model => model.BackgroundPictureId) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/_CreateOrUpdate.cshtml index e164727ae2..a518e17ef7 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/ContentSlider/_CreateOrUpdate.cshtml @@ -109,7 +109,7 @@ @Html.SmartLabelFor(model => model.PictureId) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Manufacturer/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Manufacturer/_CreateOrUpdate.cshtml index 68163284cf..25db45dfe1 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Manufacturer/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Manufacturer/_CreateOrUpdate.cshtml @@ -79,7 +79,7 @@ @Html.SmartLabelFor(model => model.PictureId) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml index 7021397e30..a90e6cf18e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/_CreateOrUpdate.cshtml @@ -131,7 +131,7 @@ @Html.SmartLabelFor(model => model.Locales[item].Attachment1FileId) @@ -140,7 +140,7 @@ @Html.SmartLabelFor(model => model.Locales[item].Attachment2FileId) @@ -149,7 +149,7 @@ @Html.SmartLabelFor(model => model.Locales[item].Attachment3FileId) @@ -202,7 +202,7 @@ @Html.SmartLabelFor(model => model.Attachment1FileId) @@ -211,7 +211,7 @@ @Html.SmartLabelFor(model => model.Attachment2FileId) @@ -220,7 +220,7 @@ @Html.SmartLabelFor(model => model.Attachment3FileId) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Pictures.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Pictures.cshtml index 346b925d83..7c08977c2b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Pictures.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.Pictures.cshtml @@ -78,7 +78,7 @@ @Html.SmartLabelFor(model => model.AddPictureModel.PictureId) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml index a10cd45bd9..84ac29f33b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml @@ -355,7 +355,7 @@ @Html.SmartLabelFor(model => model.PdfSettings.LogoPictureId) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download.cshtml index a3b33585b9..3e767879ca 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download.cshtml @@ -1,4 +1,4 @@ -@model int +@model int? @using SmartStore.Core; @using SmartStore.Web.Framework.UI; @using SmartStore.Utilities; @@ -8,7 +8,7 @@ var randomNumber = CommonHelper.GenerateRandomInteger(); var clientId = "download" + randomNumber; var downloadService = EngineContext.Current.Resolve(); - var download = downloadService.GetDownloadById(Model); + var download = downloadService.GetDownloadById(Model.GetValueOrDefault()); Html.AddScriptParts("~/bundles/fileupload"); Html.AddCssFileParts("~/css/fileupload"); @@ -174,7 +174,7 @@
    diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download2.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download2.cshtml new file mode 100644 index 0000000000..4e031002d0 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download2.cshtml @@ -0,0 +1,134 @@ +@model int? +@using SmartStore.Core; +@using SmartStore.Web.Framework.UI; +@using SmartStore.Utilities; + +@functions { + private bool MinimalMode + { + get + { + if (ViewData.ContainsKey("minimalMode")) + { + var x = ViewData["minimalMode"].Convert(); + return x; + } + return false; + } + } +} + +@{ + var randomNumber = CommonHelper.GenerateRandomInteger(); + var clientId = "download-editor-" + randomNumber; + var downloadService = EngineContext.Current.Resolve(); + var download = downloadService.GetDownloadById(Model.GetValueOrDefault()); + var initiallyShowUrlPanel = false; + var hasFile = false; + var downloadUrl = ""; + if (download != null) { + downloadUrl = Url.Action("DownloadFile", "Download", new { downloadId = download.Id }); + initiallyShowUrlPanel = !MinimalMode && download.UseDownloadUrl; + hasFile = !download.UseDownloadUrl; + } + + Html.AddScriptParts("~/bundles/fileupload"); + Html.AddCssFileParts("~/css/fileupload"); + Html.AddScriptParts(true, "~/Administration/Scripts/smartstore.download.js"); +} + + +
    + + @Html.HiddenFor(x => x, new { @class = "hidden" }) + + + @if (!MinimalMode) + { +
    +
    + + + + + +
    +
    + } + + +
    + + +
    + + + @if (hasFile) + { + + @download.Filename.Truncate(50, "...")@download.Extension + + } + + + + @if (hasFile) + { + + } + else + { + @T("Common.Fileuploader.Upload") + } + + + + + + +
    + +
    +
    +
    + +
     
    +
    +
    + + + @if (!MinimalMode) + { +
    +
    + @Html.TextBox("DownloadUrl", download != null ? download.DownloadUrl : "", new { style = "width: 330px" }) + +
    +
    + } + +
    +
    + + \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Picture.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Picture.cshtml index d60f7b8d8a..e1641c7b18 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Picture.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Picture.cshtml @@ -2,6 +2,22 @@ @using SmartStore.Core; @using SmartStore.Web.Framework.UI; @using SmartStore.Utilities; + +@functions { + private bool TransientUpload + { + get + { + if (ViewData.ContainsKey("transientUpload")) + { + var x = ViewData["transientUpload"].Convert(); + return x; + } + return false; + } + } +} + @{ //other variables @@ -15,7 +31,7 @@ Html.AddCssFileParts("~/css/fileupload"); } -
    +
    @Html.HiddenFor(x => x, new { @class = "hidden"} ) @@ -59,7 +75,7 @@ elRemove = el.find('.remove'); $('#@clientId').fileupload({ - url: '@(Url.Content("~/Admin/Picture/AsyncUpload"))', + url: el.data('upload-url'), dataType: 'json', //acceptFileTypes: /^image\/(gif|jpeg|jpg|png)$/, acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml index aac7dff4f0..11d1ce2f41 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Store/_CreateOrUpdate.cshtml @@ -27,7 +27,7 @@ @Html.SmartLabelFor(model => model.LogoPictureId)
    diff --git a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs index c070f2dd37..1dbdf48609 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs @@ -1349,7 +1349,7 @@ public ActionResult DownloadableProducts() null, null, null, true); foreach (var item in items) { - var itemModel = new CustomerDownloadableProductsModel.DownloadableProductsModel() + var itemModel = new CustomerDownloadableProductsModel.DownloadableProductsModel { OrderItemGuid = item.OrderItemGuid, OrderId = item.OrderId, @@ -1532,11 +1532,11 @@ public ActionResult UploadAvatar(CustomerAvatarModel model, HttpPostedFileBase u if (uploadedFile.ContentLength > avatarMaxSize) throw new SmartException(string.Format(_localizationService.GetResource("Account.Avatar.MaximumUploadedFileSize"), Prettifier.BytesToString(avatarMaxSize))); - byte[] customerPictureBinary = uploadedFile.GetPictureBits(); + byte[] customerPictureBinary = uploadedFile.InputStream.ToByteArray(); if (customerAvatar != null) customerAvatar = _pictureService.UpdatePicture(customerAvatar.Id, customerPictureBinary, uploadedFile.ContentType, null, true); else - customerAvatar = _pictureService.InsertPicture(customerPictureBinary, uploadedFile.ContentType, null, true); + customerAvatar = _pictureService.InsertPicture(customerPictureBinary, uploadedFile.ContentType, null, true, false); } int customerAvatarId = 0; diff --git a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs index 4a328185b2..604a4b8441 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs @@ -1084,11 +1084,11 @@ protected void ParseAndSaveCheckoutAttributes(List ca break; case AttributeControlType.FileUpload: { - var httpPostedFile = this.Request.Files[controlId]; - if ((httpPostedFile != null) && (!String.IsNullOrEmpty(httpPostedFile.FileName))) + var postedFile = this.Request.Files[controlId].ToPostedFileResult(); + if (postedFile != null && postedFile.FileName.HasValue()) { int fileMaxSize = _catalogSettings.FileUploadMaximumSizeBytes; - if (httpPostedFile.ContentLength > fileMaxSize) + if (postedFile.Size > fileMaxSize) { //TODO display warning //warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.MaximumUploadedFileSize"), (int)(fileMaxSize / 1024))); @@ -1096,21 +1096,20 @@ protected void ParseAndSaveCheckoutAttributes(List ca else { //save an uploaded file - var download = new Download() + var download = new Download { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = false, DownloadUrl = "", - DownloadBinary = httpPostedFile.GetDownloadBits(), - ContentType = httpPostedFile.ContentType, - Filename = System.IO.Path.GetFileNameWithoutExtension(httpPostedFile.FileName), - Extension = System.IO.Path.GetExtension(httpPostedFile.FileName), + DownloadBinary = postedFile.Buffer, + ContentType = postedFile.ContentType, + Filename = postedFile.FileTitle, + Extension = postedFile.FileExtension, IsNew = true }; _downloadService.InsertDownload(download); //save attribute - selectedAttributes = _checkoutAttributeParser.AddCheckoutAttribute(selectedAttributes, - attribute, download.DownloadGuid.ToString()); + selectedAttributes = _checkoutAttributeParser.AddCheckoutAttribute(selectedAttributes, attribute, download.DownloadGuid.ToString()); } } } @@ -1369,86 +1368,62 @@ public ActionResult UploadFileProductAttribute(int productId, int productAttribu { success = false, downloadGuid = Guid.Empty, - }, "text/plain"); + }); } - //ensure that this attribute belong to this product and has "file upload" type + + // ensure that this attribute belong to this product and has "file upload" type var pva = _productAttributeService .GetProductVariantAttributesByProductId(productId) .Where(pa => pa.ProductAttributeId == productAttributeId) .FirstOrDefault(); + if (pva == null || pva.AttributeControlType != AttributeControlType.FileUpload) { return Json(new { success = false, downloadGuid = Guid.Empty, - }, "text/plain"); - } - - //we process it distinct ways based on a browser - //find more info here http://stackoverflow.com/questions/4884920/mvc3-valums-ajax-file-upload - Stream stream = null; - var fileName = ""; - var contentType = ""; - if (String.IsNullOrEmpty(Request["qqfile"])) - { - // IE - HttpPostedFileBase httpPostedFile = Request.Files[0]; - if (httpPostedFile == null) - throw new ArgumentException("No file uploaded"); - stream = httpPostedFile.InputStream; - fileName = Path.GetFileName(httpPostedFile.FileName); - contentType = httpPostedFile.ContentType; - } - else - { - //Webkit, Mozilla - stream = Request.InputStream; - fileName = Request["qqfile"]; + }); } - var fileBinary = new byte[stream.Length]; - stream.Read(fileBinary, 0, fileBinary.Length); - - var fileExtension = Path.GetExtension(fileName); - if (!String.IsNullOrEmpty(fileExtension)) - fileExtension = fileExtension.ToLowerInvariant(); + var postedFile = Request.ToPostedFileResult(); + if (postedFile == null) + { + throw new ArgumentException("No file uploaded"); + } int fileMaxSize = _catalogSettings.FileUploadMaximumSizeBytes; - if (fileBinary.Length > fileMaxSize) + if (postedFile.Size > fileMaxSize) { - //when returning JSON the mime-type must be set to text/plain - //otherwise some browsers will pop-up a "Save As" dialog. return Json(new { success = false, message = string.Format(_localizationService.GetResource("ShoppingCart.MaximumUploadedFileSize"), (int)(fileMaxSize / 1024)), downloadGuid = Guid.Empty, - }, "text/plain"); + }); } - var download = new Download() + var download = new Download { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = false, DownloadUrl = "", - DownloadBinary = fileBinary, - ContentType = contentType, - //we store filename without extension for downloads - Filename = Path.GetFileNameWithoutExtension(fileName), - Extension = fileExtension, - IsNew = true + DownloadBinary = postedFile.Buffer, + ContentType = postedFile.ContentType, + // we store filename without extension for downloads + Filename = postedFile.FileTitle, + Extension = postedFile.FileExtension, + IsNew = true, + IsTransient = true }; _downloadService.InsertDownload(download); - //when returning JSON the mime-type must be set to text/plain - //otherwise some browsers will pop-up a "Save As" dialog. return Json(new { success = true, message = _localizationService.GetResource("ShoppingCart.FileUploaded"), downloadGuid = download.DownloadGuid, - }, "text/plain"); + }); } diff --git a/src/Presentation/SmartStore.Web/Extensions/ProductDetailsExtensions.cs b/src/Presentation/SmartStore.Web/Extensions/ProductDetailsExtensions.cs index 7b82ca9ec0..173ab96308 100644 --- a/src/Presentation/SmartStore.Web/Extensions/ProductDetailsExtensions.cs +++ b/src/Presentation/SmartStore.Web/Extensions/ProductDetailsExtensions.cs @@ -11,6 +11,7 @@ namespace SmartStore.Web { public static class ProductDetailsExtensions { + public static string UpdateProductDetailsUrl(this ProductDetailsModel model, string itemType = null) { var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext); @@ -24,10 +25,12 @@ public static string UpdateProductDetailsUrl(this ProductDetailsModel model, str return url; } + public static bool RenderBundleTitle(this ProductDetailsModel model) { return model.BundleTitleText.HasValue() && model.BundledItems.Where(x => x.BundleItem.Visible).Count() > 0; } + public static Picture GetAssignedPicture(this ProductDetailsModel model, IPictureService pictureService, IList pictures, int productId = 0) { if (model != null && model.CombinationSelected != null) @@ -51,6 +54,7 @@ public static Picture GetAssignedPicture(this ProductDetailsModel model, IPictur } return null; } + public static string GetAttributeValueInfo(this ProductDetailsModel.ProductVariantAttributeValueModel model) { string result = ""; @@ -77,6 +81,7 @@ public static bool ShouldBeRendered(this ProductDetailsModel.ProductVariantAttri return true; } } + public static bool ShouldBeRendered(this IEnumerable variantAttributes) { if (variantAttributes != null) diff --git a/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs b/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs index cd7ddaf22c..e03c3d4e35 100644 --- a/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs +++ b/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs @@ -2525,32 +2525,36 @@ protected override void Alter(IList entities) { base.Alter(entities); - entities.WithKey(x => x.Name) - .Alter("Send emails", x => + entities.WithKey(x => x.Type) + .Alter("SmartStore.Services.Messages.QueuedMessagesSendTask, SmartStore.Services", x => { x.Name = "E-Mail senden"; }) - .Alter("Clear email queue", x => + .Alter("SmartStore.Services.Messages.QueuedMessagesClearTask, SmartStore.Services", x => { x.Name = "E-Mail Queue bereinigen"; }) - .Alter("Keep alive", x => + .Alter("SmartStore.Services.Media.TransientMediaClearTask, SmartStore.Services", x => + { + x.Name = "Temporäre Uploads bereinigen"; + }) + .Alter("SmartStore.Services.Common.KeepAliveTask, SmartStore.Services", x => { x.Name = "Keep alive"; }) - .Alter("Delete guests", x => + .Alter("SmartStore.Services.Customers.DeleteGuestsTask, SmartStore.Services", x => { x.Name = "Gastbenutzer löschen"; }) - .Alter("Clear cache", x => + .Alter("SmartStore.Services.Caching.ClearCacheTask, SmartStore.Services", x => { x.Name = "Cache bereinigen"; }) - .Alter("Send emails", x => + .Alter("SmartStore.Services.Messages.QueuedMessagesSendTask, SmartStore.Services", x => { x.Name = "E-Mail senden"; }) - .Alter("Update currency exchange rates", x => + .Alter("SmartStore.Services.Directory.UpdateExchangeRateTask, SmartStore.Services", x => { x.Name = "Wechselkurse aktualisieren"; }); diff --git a/src/Presentation/SmartStore.Web/Views/Product/_Attributes.cshtml b/src/Presentation/SmartStore.Web/Views/Product/_Attributes.cshtml index 0f43e97628..bbe0a418d2 100644 --- a/src/Presentation/SmartStore.Web/Views/Product/_Attributes.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Product/_Attributes.cshtml @@ -117,20 +117,20 @@ case AttributeControlType.Datepicker: { @Html.DatePickerDropDowns(controlId + "_day", controlId + "_month", controlId + "_year", attribute.BeginYear, attribute.EndYear, attribute.SelectedDay, attribute.SelectedMonth, attribute.SelectedYear, true, attribute.IsDisabled) - } - break; - case AttributeControlType.FileUpload: + } + break; + case AttributeControlType.FileUpload: { Html.AddScriptParts("~/bundles/fileupload"); Html.AddCssFileParts("~/css/fileupload"); - var random = CommonHelper.GenerateRandomInteger(); - var clientId = "upload" + CommonHelper.GenerateRandomInteger(); + var random = CommonHelper.GenerateRandomInteger(); + var clientId = "upload" + CommonHelper.GenerateRandomInteger(); + + //ex. ['jpg', 'jpeg', 'png', 'gif'] or [] + var allowedFileExtensions = string.Join("|", attribute.AllowedFileExtensions.Select(x => x.Trim()).ToList()); - //ex. ['jpg', 'jpeg', 'png', 'gif'] or [] - var allowedFileExtensions = string.Join("|", attribute.AllowedFileExtensions.Select(x => x.Trim()).ToList()); -
    diff --git a/src/Tests/SmartStore.Data.Tests/Catalog/ProductPersistenceTests.cs b/src/Tests/SmartStore.Data.Tests/Catalog/ProductPersistenceTests.cs index c19d9250ea..003fca1619 100644 --- a/src/Tests/SmartStore.Data.Tests/Catalog/ProductPersistenceTests.cs +++ b/src/Tests/SmartStore.Data.Tests/Catalog/ProductPersistenceTests.cs @@ -303,7 +303,7 @@ public void Can_save_and_load_product_with_productPictures() new ProductPicture { DisplayOrder = 1, - Picture = new Picture() + Picture = new Picture { PictureBinary = new byte[] { 1, 2, 3 }, MimeType = "image/pjpeg", From 7b4408c8340ffc53e54cae1252e4030d8ca135a2 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Wed, 15 Jul 2015 10:43:32 +0200 Subject: [PATCH 0249/1256] Closes #619 Display base price according to applied tier price --- changelog.md | 3 ++- .../SmartStore.Web/Controllers/CatalogHelper.cs | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index f6523321a6..118f77786d 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,4 @@ -# Release Notes +# Release Notes ## SmartStore.NET 2.2.2 @@ -24,6 +24,7 @@ * #691 Product quantity not added to cart on mobile theme * #186 Mobile: variant images do not refresh * #671 Bundle products: display base price according to applied discount +* #619 Display base price according to applied tier price * Weight adjustment of attributes weren't applied in shopping cart overview * Shipping by weight calculates wrong surcharge if attribute combination prices are set diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index dceb88c312..bd9c4354af 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -842,9 +842,12 @@ public ProductDetailsModel PrepareProductDetailModel( model.ProductPrice.NoteWithoutDiscount = T(isBundle && product.BundlePerItemPricing ? "Products.Bundle.PriceWithoutDiscount.Note" : "Products.Price"); } - if (isBundle && product.BundlePerItemPricing && !string.IsNullOrWhiteSpace(model.ProductPrice.PriceWithDiscount)) + if ((isBundle && product.BundlePerItemPricing && !string.IsNullOrWhiteSpace(model.ProductPrice.PriceWithDiscount)) || product.HasTierPrices) { - model.ProductPrice.NoteWithDiscount = T("Products.Bundle.PriceWithDiscount.Note"); + if (!product.HasTierPrices) + { + model.ProductPrice.NoteWithDiscount = T("Products.Bundle.PriceWithDiscount.Note"); + } model.BasePriceInfo = product.GetBasePriceInfo(_localizationService, _priceFormatter, (product.Price - finalPriceWithDiscount) * (-1)); } } From 0a42324234a9d6daff8e967d1dbf0a96ad5fcfb3 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Wed, 15 Jul 2015 10:58:52 +0200 Subject: [PATCH 0250/1256] Closes #726 PAngV: basket displays wrong base price when attribute price adjustment has been set --- changelog.md | 1 + .../SmartStore.Web/Controllers/ShoppingCartController.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/changelog.md b/changelog.md index 118f77786d..9e22a2ad42 100644 --- a/changelog.md +++ b/changelog.md @@ -25,6 +25,7 @@ * #186 Mobile: variant images do not refresh * #671 Bundle products: display base price according to applied discount * #619 Display base price according to applied tier price +* #726 PAngV: basket displays wrong base price when attribute price adjustment has been set * Weight adjustment of attributes weren't applied in shopping cart overview * Shipping by weight calculates wrong surcharge if attribute combination prices are set diff --git a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs index ea2abd62de..cab4328a7b 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ShoppingCartController.cs @@ -367,6 +367,8 @@ private ShoppingCartModel.ShoppingCartItemModel PrepareShoppingCartItemModel(Org decimal shoppingCartItemDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemDiscountBase, _workContext.WorkingCurrency); model.Discount = _priceFormatter.FormatPrice(shoppingCartItemDiscount); } + + model.BasePrice = product.GetBasePriceInfo(_localizationService, _priceFormatter, (product.Price - shoppingCartItemSubTotalWithDiscount) * (-1)); } //picture From 29ce959915abeaed1a260356c462111195912bad Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Wed, 15 Jul 2015 11:50:46 +0200 Subject: [PATCH 0251/1256] Closes #521 Display bonus points in order export --- changelog.md | 1 + .../SmartStore.Services/ExportImport/ExportManager.cs | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index 9e22a2ad42..6bec688b1e 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,7 @@ * #716 Supporting of paged google-product data query for SQL-Server Compact Edition * #648 Add hint for * at mandatory form fields at address creation * Added link to imprint and disclaimer to footer in mobile theme +* #521 Display bonus points in order export ### Bugfixes * #694 Product variant attribute in product page should not be preselected implicitly diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs index 21cb3055a1..9a78698af3 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportManager.cs @@ -1342,7 +1342,9 @@ public virtual string ExportOrdersToXml(IList orders) xmlWriter.WriteElementString("Deleted", null, order.Deleted.ToString()); xmlWriter.WriteElementString("CreatedOnUtc", null, order.CreatedOnUtc.ToString()); xmlWriter.WriteElementString("UpdatedOnUtc", null, order.UpdatedOnUtc.ToString()); - xmlWriter.WriteElementString("RewardPointsRemaining", null, order.RewardPointsRemaining.HasValue ? order.RewardPointsRemaining.Value.ToString() : ""); + xmlWriter.WriteElementString("RewardPointsUsed", null, order.RedeemedRewardPointsEntry.Points != 0 ? (order.RedeemedRewardPointsEntry.Points * (-1)).ToString() : ""); + var remainingRewardPoints = order.Customer.GetRewardPointsBalance(); + xmlWriter.WriteElementString("RewardPointsRemaining", null, remainingRewardPoints > 0 ? remainingRewardPoints.ToString() : ""); xmlWriter.WriteElementString("HasNewPaymentNotification", null, order.HasNewPaymentNotification.ToString()); //products @@ -1458,6 +1460,7 @@ public virtual void ExportOrdersToXlsx(Stream stream, IList orders) "VatNumber", "CreatedOnUtc", "UpdatedOnUtc", + "RewardPointsUsed", "RewardPointsRemaining", "HasNewPaymentNotification", //billing address @@ -1589,7 +1592,11 @@ public virtual void ExportOrdersToXlsx(Stream stream, IList orders) worksheet.Cells[row, col].Value = order.UpdatedOnUtc.ToOADate(); col++; - worksheet.Cells[row, col].Value = (order.RewardPointsRemaining.HasValue ? order.RewardPointsRemaining.Value.ToString() : ""); + worksheet.Cells[row, col].Value = (order.RedeemedRewardPointsEntry.Points != 0 ? (order.RedeemedRewardPointsEntry.Points * (-1)).ToString() : ""); + col++; + + var remainingRewardPoints = order.Customer.GetRewardPointsBalance(); + worksheet.Cells[row, col].Value = (remainingRewardPoints > 0 ? remainingRewardPoints.ToString() : ""); col++; worksheet.Cells[row, col].Value = order.HasNewPaymentNotification; From aa42f9ebba604d7aa6e4daee0301bbc4d1322ce3 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 15 Jul 2015 20:43:13 +0200 Subject: [PATCH 0252/1256] Minor fixes --- .../Migrations/201403112331027_Initial.cs | 14 +++++++------- .../201504131412183_NewCategoryProperties.cs | 2 +- ...61756463_PrimaryStoreCurrencyMultiStore.cs | 19 ++++++++++--------- .../Setup/IDbMigrationExtensions.cs | 2 +- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201403112331027_Initial.cs b/src/Libraries/SmartStore.Data/Migrations/201403112331027_Initial.cs index 75a8e6b211..de838e8eca 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201403112331027_Initial.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201403112331027_Initial.cs @@ -1774,13 +1774,13 @@ public override void Up() #endregion #region Custom - - this.SqlFile("Indexes.sql"); + + this.SqlFileOrResource("Indexes.sql"); if (HostingEnvironment.IsHosted && DataSettings.Current.IsSqlServer) { // do not execute in unit tests - this.SqlFile("Indexes.SqlServer.sql"); - this.SqlFile("StoredProcedures.sql"); + this.SqlFileOrResource("Indexes.SqlServer.sql"); + this.SqlFileOrResource("StoredProcedures.sql"); } #endregion @@ -1790,12 +1790,12 @@ public override void Down() { #region Custom - this.SqlFile("Indexes.Inverse.sql"); + this.SqlFileOrResource("Indexes.Inverse.sql"); if (HostingEnvironment.IsHosted && DataSettings.Current.IsSqlServer) { // do not execute in unit tests - this.SqlFile("Indexes.SqlServer.Inverse.sql"); - this.SqlFile("StoredProcedures.Inverse.sql"); + this.SqlFileOrResource("Indexes.SqlServer.Inverse.sql"); + this.SqlFileOrResource("StoredProcedures.Inverse.sql"); } #endregion diff --git a/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.cs b/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.cs index 71f6b4076c..0ae7100ae6 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201504131412183_NewCategoryProperties.cs @@ -18,7 +18,7 @@ public override void Up() if (HostingEnvironment.IsHosted && DataSettings.Current.IsSqlServer) { - this.SqlFile("LatestProductLoadAllPaged.sql"); + this.SqlFileOrResource("LatestProductLoadAllPaged.sql"); } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs index 1903182830..b7862fafd5 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -2,6 +2,7 @@ namespace SmartStore.Data.Migrations { using System.Data.Entity.Migrations; using System.Linq; + using System.Web.Hosting; using SmartStore.Core.Data; using SmartStore.Core.Domain.Configuration; using SmartStore.Core.Domain.Directory; @@ -16,7 +17,7 @@ public override void Up() AddColumn("dbo.Store", "PrimaryExchangeRateCurrencyId", c => c.Int(nullable: false, defaultValue: 1)); // avoid conflicts with foreign key constraint - if (DataSettings.Current.IsSqlServer) + if (HostingEnvironment.IsHosted && DataSettings.Current.IsSqlServer) { // what sql-server compact does not support here: // - Update Set with a select sub-query @@ -28,8 +29,8 @@ public override void Up() Sql("Update dbo.Store Set PrimaryExchangeRateCurrencyId = (Select Min(Id) From dbo.Currency)"); } - CreateIndex("dbo.Store", "PrimaryStoreCurrencyId"); - CreateIndex("dbo.Store", "PrimaryExchangeRateCurrencyId"); + CreateIndex("dbo.Store", "PrimaryStoreCurrencyId"); + CreateIndex("dbo.Store", "PrimaryExchangeRateCurrencyId"); AddForeignKey("dbo.Store", "PrimaryExchangeRateCurrencyId", "dbo.Currency", "Id"); AddForeignKey("dbo.Store", "PrimaryStoreCurrencyId", "dbo.Currency", "Id"); @@ -37,14 +38,14 @@ public override void Up() public override void Down() { - DropForeignKey("dbo.Store", "PrimaryStoreCurrencyId", "dbo.Currency"); - DropForeignKey("dbo.Store", "PrimaryExchangeRateCurrencyId", "dbo.Currency"); + DropForeignKey("dbo.Store", "PrimaryStoreCurrencyId", "dbo.Currency"); + DropForeignKey("dbo.Store", "PrimaryExchangeRateCurrencyId", "dbo.Currency"); - DropIndex("dbo.Store", new[] { "PrimaryExchangeRateCurrencyId" }); - DropIndex("dbo.Store", new[] { "PrimaryStoreCurrencyId" }); + DropIndex("dbo.Store", new[] { "PrimaryExchangeRateCurrencyId" }); + DropIndex("dbo.Store", new[] { "PrimaryStoreCurrencyId" }); - DropColumn("dbo.Store", "PrimaryExchangeRateCurrencyId"); - DropColumn("dbo.Store", "PrimaryStoreCurrencyId"); + DropColumn("dbo.Store", "PrimaryExchangeRateCurrencyId"); + DropColumn("dbo.Store", "PrimaryStoreCurrencyId"); } public bool RollbackOnFailure diff --git a/src/Libraries/SmartStore.Data/Setup/IDbMigrationExtensions.cs b/src/Libraries/SmartStore.Data/Setup/IDbMigrationExtensions.cs index 70bebdd73d..44f470e318 100644 --- a/src/Libraries/SmartStore.Data/Setup/IDbMigrationExtensions.cs +++ b/src/Libraries/SmartStore.Data/Setup/IDbMigrationExtensions.cs @@ -16,7 +16,7 @@ namespace SmartStore.Data.Setup public static class IDbMigrationExtensions { - public static void SqlFile(this IDbMigration migration, string fileName, Assembly assembly = null, string location = null) + public static void SqlFileOrResource(this IDbMigration migration, string fileName, Assembly assembly = null, string location = null) { Guard.ArgumentNotEmpty(() => fileName); From cf4aa9387debc951c7e5dbd9513e7b0a980c32fb Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 15 Jul 2015 21:00:54 +0200 Subject: [PATCH 0253/1256] Updated EntityFramework to version 6.1.3 --- src/Libraries/SmartStore.Core/SmartStore.Core.csproj | 4 ++-- src/Libraries/SmartStore.Core/packages.config | 2 +- src/Libraries/SmartStore.Data/SmartStore.Data.csproj | 6 +++--- src/Libraries/SmartStore.Data/packages.config | 4 ++-- .../SmartStore.Services/SmartStore.Services.csproj | 7 ++++--- src/Libraries/SmartStore.Services/packages.config | 2 +- .../SmartStore.DevTools/SmartStore.DevTools.csproj | 12 ++++++------ src/Plugins/SmartStore.DevTools/packages.config | 2 +- .../SmartStore.GoogleMerchantCenter.csproj | 4 ++-- .../SmartStore.GoogleMerchantCenter/packages.config | 2 +- .../SmartStore.Shipping/SmartStore.Shipping.csproj | 4 ++-- src/Plugins/SmartStore.Shipping/packages.config | 2 +- .../SmartStore.ShippingByWeight.csproj | 6 ++---- .../SmartStore.ShippingByWeight/packages.config | 2 +- src/Plugins/SmartStore.Tax/SmartStore.Tax.csproj | 12 ++++++------ src/Plugins/SmartStore.Tax/packages.config | 2 +- .../SmartStore.Web.Framework.csproj | 4 ++-- .../SmartStore.Web.Framework/packages.config | 2 +- .../Administration/Controllers/ProductController.cs | 12 ++---------- .../SmartStore.Web/SmartStore.Web.csproj | 6 +++--- src/Presentation/SmartStore.Web/packages.config | 4 ++-- .../SmartStore.Data.Tests.csproj | 12 +++++++----- src/Tests/SmartStore.Data.Tests/packages.config | 4 ++-- 23 files changed, 55 insertions(+), 62 deletions(-) diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index f4d3363c1d..0ada459f9e 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -71,11 +71,11 @@ False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll False diff --git a/src/Libraries/SmartStore.Core/packages.config b/src/Libraries/SmartStore.Core/packages.config index 333eb7af85..923c1183a2 100644 --- a/src/Libraries/SmartStore.Core/packages.config +++ b/src/Libraries/SmartStore.Core/packages.config @@ -2,7 +2,7 @@ - + diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 4eefab19db..5ccd723030 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -67,15 +67,15 @@ False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll False - ..\..\packages\EntityFramework.SqlServerCompact.6.1.0\lib\net45\EntityFramework.SqlServerCompact.dll + ..\..\packages\EntityFramework.SqlServerCompact.6.1.3\lib\net45\EntityFramework.SqlServerCompact.dll True diff --git a/src/Libraries/SmartStore.Data/packages.config b/src/Libraries/SmartStore.Data/packages.config index 14cad35b89..8ae4db4807 100644 --- a/src/Libraries/SmartStore.Data/packages.config +++ b/src/Libraries/SmartStore.Data/packages.config @@ -1,8 +1,8 @@  - - + + diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index a14d1bc8d7..5f6e45b404 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -67,10 +67,11 @@ False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll - - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll + + False + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll False diff --git a/src/Libraries/SmartStore.Services/packages.config b/src/Libraries/SmartStore.Services/packages.config index 1d9b39f80e..dfad9d51e6 100644 --- a/src/Libraries/SmartStore.Services/packages.config +++ b/src/Libraries/SmartStore.Services/packages.config @@ -1,7 +1,7 @@  - + diff --git a/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj b/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj index 7b08208219..5ad4a77279 100644 --- a/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj +++ b/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj @@ -80,13 +80,13 @@ ..\..\packages\Autofac.Mvc5.3.3.1\lib\net45\Autofac.Integration.Mvc.dll - - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll - False + + False + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll - - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll - False + + False + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll ..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll diff --git a/src/Plugins/SmartStore.DevTools/packages.config b/src/Plugins/SmartStore.DevTools/packages.config index 5fb210cfc1..8a4fe05ffb 100644 --- a/src/Plugins/SmartStore.DevTools/packages.config +++ b/src/Plugins/SmartStore.DevTools/packages.config @@ -2,7 +2,7 @@ - + diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/SmartStore.GoogleMerchantCenter.csproj b/src/Plugins/SmartStore.GoogleMerchantCenter/SmartStore.GoogleMerchantCenter.csproj index 8ad761ecef..a5e760e9b6 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/SmartStore.GoogleMerchantCenter.csproj +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/SmartStore.GoogleMerchantCenter.csproj @@ -89,11 +89,11 @@ False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll ..\..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/packages.config b/src/Plugins/SmartStore.GoogleMerchantCenter/packages.config index 098fe232fa..769e9cee02 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/packages.config +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/packages.config @@ -2,7 +2,7 @@ - + diff --git a/src/Plugins/SmartStore.Shipping/SmartStore.Shipping.csproj b/src/Plugins/SmartStore.Shipping/SmartStore.Shipping.csproj index 59f1bdcdf0..3de6559bd2 100644 --- a/src/Plugins/SmartStore.Shipping/SmartStore.Shipping.csproj +++ b/src/Plugins/SmartStore.Shipping/SmartStore.Shipping.csproj @@ -89,11 +89,11 @@ False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll ..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll diff --git a/src/Plugins/SmartStore.Shipping/packages.config b/src/Plugins/SmartStore.Shipping/packages.config index 7605330a41..bbc22c8227 100644 --- a/src/Plugins/SmartStore.Shipping/packages.config +++ b/src/Plugins/SmartStore.Shipping/packages.config @@ -2,7 +2,7 @@ - + diff --git a/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj b/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj index 561149e08f..d3518bfcf0 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj +++ b/src/Plugins/SmartStore.ShippingByWeight/SmartStore.ShippingByWeight.csproj @@ -90,13 +90,11 @@ False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll - False + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll - False + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll ..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll diff --git a/src/Plugins/SmartStore.ShippingByWeight/packages.config b/src/Plugins/SmartStore.ShippingByWeight/packages.config index 7605330a41..bbc22c8227 100644 --- a/src/Plugins/SmartStore.ShippingByWeight/packages.config +++ b/src/Plugins/SmartStore.ShippingByWeight/packages.config @@ -2,7 +2,7 @@ - + diff --git a/src/Plugins/SmartStore.Tax/SmartStore.Tax.csproj b/src/Plugins/SmartStore.Tax/SmartStore.Tax.csproj index 4c9be02213..08e8670fa0 100644 --- a/src/Plugins/SmartStore.Tax/SmartStore.Tax.csproj +++ b/src/Plugins/SmartStore.Tax/SmartStore.Tax.csproj @@ -85,13 +85,13 @@ ..\..\packages\Autofac.3.4.1\lib\net40\Autofac.dll False - - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll - False + + False + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll - - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll - False + + False + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll ..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll diff --git a/src/Plugins/SmartStore.Tax/packages.config b/src/Plugins/SmartStore.Tax/packages.config index fa6b3ec07d..bce2006cf4 100644 --- a/src/Plugins/SmartStore.Tax/packages.config +++ b/src/Plugins/SmartStore.Tax/packages.config @@ -1,7 +1,7 @@  - + diff --git a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj index cd2f03fa0d..e839d52621 100644 --- a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj +++ b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj @@ -95,11 +95,11 @@ False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll False diff --git a/src/Presentation/SmartStore.Web.Framework/packages.config b/src/Presentation/SmartStore.Web.Framework/packages.config index 67afa8b56a..2f40cf1830 100644 --- a/src/Presentation/SmartStore.Web.Framework/packages.config +++ b/src/Presentation/SmartStore.Web.Framework/packages.config @@ -8,7 +8,7 @@ - + diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index feb12bf6c3..4a8f624b92 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -686,16 +686,8 @@ protected void PrepareProductModel(ProductModel model, Product product, bool set if (product != null) { - var result = new StringBuilder(); - var tags = product.ProductTags.ToList(); - for (int i = 0; i < product.ProductTags.Count; i++) - { - var pt = tags[i]; - result.Append(pt.Name); - if (i != product.ProductTags.Count - 1) - result.Append(", "); - } - model.ProductTags = result.ToString(); + //var tags = product.ProductTags; + model.ProductTags = string.Join(", ", product.ProductTags.Select(x => x.Name)); } //tax categories diff --git a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj index e4db2c4359..1d93356ba2 100644 --- a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj +++ b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj @@ -96,15 +96,15 @@ False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll False - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll False - ..\..\packages\EntityFramework.SqlServerCompact.6.1.0\lib\net45\EntityFramework.SqlServerCompact.dll + ..\..\packages\EntityFramework.SqlServerCompact.6.1.3\lib\net45\EntityFramework.SqlServerCompact.dll False diff --git a/src/Presentation/SmartStore.Web/packages.config b/src/Presentation/SmartStore.Web/packages.config index 2c48e0cba2..777a775b2c 100644 --- a/src/Presentation/SmartStore.Web/packages.config +++ b/src/Presentation/SmartStore.Web/packages.config @@ -7,8 +7,8 @@ - - + + diff --git a/src/Tests/SmartStore.Data.Tests/SmartStore.Data.Tests.csproj b/src/Tests/SmartStore.Data.Tests/SmartStore.Data.Tests.csproj index 894a358733..528660817e 100644 --- a/src/Tests/SmartStore.Data.Tests/SmartStore.Data.Tests.csproj +++ b/src/Tests/SmartStore.Data.Tests/SmartStore.Data.Tests.csproj @@ -62,15 +62,17 @@ MinimumRecommendedRules.ruleset - - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.dll + + False + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll - - ..\..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll + + False + ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll False - ..\..\packages\EntityFramework.SqlServerCompact.6.1.0\lib\net45\EntityFramework.SqlServerCompact.dll + ..\..\packages\EntityFramework.SqlServerCompact.6.1.3\lib\net45\EntityFramework.SqlServerCompact.dll False diff --git a/src/Tests/SmartStore.Data.Tests/packages.config b/src/Tests/SmartStore.Data.Tests/packages.config index 694797e037..a4f9326a28 100644 --- a/src/Tests/SmartStore.Data.Tests/packages.config +++ b/src/Tests/SmartStore.Data.Tests/packages.config @@ -1,7 +1,7 @@  - - + + \ No newline at end of file From 0961e3dbf2ccc1899901d8a1b1b6129e4784b707 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 16 Jul 2015 00:11:44 +0200 Subject: [PATCH 0254/1256] Implemented Entity Framework 2nd level cache for some unfrequently changed entities --- .../Caching/DefaultCacheManager.cs | 18 ++- .../SmartStore.Data/Caching/EfCacheImpl.cs | 118 ++++++++++++++++++ .../Caching/EfCachingPolicy.cs | 84 +++++++++++++ .../Setup/SeedData/InvariantSeedData.cs | 2 +- .../SmartStore.Data/SmartDbConfiguration.cs | 24 ++++ .../SmartStore.Data/SmartStore.Data.csproj | 6 + src/Libraries/SmartStore.Data/packages.config | 1 + .../Messages/QueuedEmailService.cs | 2 +- 8 files changed, 243 insertions(+), 12 deletions(-) create mode 100644 src/Libraries/SmartStore.Data/Caching/EfCacheImpl.cs create mode 100644 src/Libraries/SmartStore.Data/Caching/EfCachingPolicy.cs diff --git a/src/Libraries/SmartStore.Core/Caching/DefaultCacheManager.cs b/src/Libraries/SmartStore.Core/Caching/DefaultCacheManager.cs index bdf35da722..9ecc1425fa 100644 --- a/src/Libraries/SmartStore.Core/Caching/DefaultCacheManager.cs +++ b/src/Libraries/SmartStore.Core/Caching/DefaultCacheManager.cs @@ -34,21 +34,19 @@ public T Get(string key, Func acquirer, int? cacheTime = null) { return (T)_cache.Get(key); } - else + + using (EnterReadLock()) { - using (EnterReadLock()) + if (!_cache.Contains(key)) { - if (!_cache.Contains(key)) - { - var value = acquirer(); - this.Set(key, value, cacheTime); + var value = acquirer(); + this.Set(key, value, cacheTime); - return value; - } + return value; } - - return (T)_cache.Get(key); } + + return (T)_cache.Get(key); } public void Set(string key, object value, int? cacheTime = null) diff --git a/src/Libraries/SmartStore.Data/Caching/EfCacheImpl.cs b/src/Libraries/SmartStore.Data/Caching/EfCacheImpl.cs new file mode 100644 index 0000000000..e4b6debc8d --- /dev/null +++ b/src/Libraries/SmartStore.Data/Caching/EfCacheImpl.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using SmartStore.Collections; +using SmartStore.Core.Caching; +using SmartStore.Utilities.Threading; + +namespace SmartStore.Data.Caching +{ + + internal class EfCacheImpl : EFCache.ICache + { + private const string KEYPREFIX = "EfCache__"; + private readonly Multimap _entitySetToKey = new Multimap(() => new HashSet()); + + private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(); + private readonly ICache _cache; + + public EfCacheImpl(ICache innerCache) + { + this._cache = innerCache; + } + + public bool GetItem(string key, out object value) + { + value = null; + key = HashKey(key); + + if (_cache.Contains(key)) + { + value = _cache.Get(key); + return true; + } + + return false; + } + + public void PutItem(string key, object value, IEnumerable dependentEntitySets, TimeSpan slidingExpiration, DateTimeOffset absoluteExpiration) + { + key = HashKey(key); + + using (EnterWriteLock()) + { + var now = DateTimeOffset.Now; + var expiresInMinutes = Math.Max(1, Math.Min(int.MaxValue, (absoluteExpiration - now).TotalMinutes)); + _cache.Set(key, value, (int)expiresInMinutes); + + foreach (var s in dependentEntitySets) + { + _entitySetToKey[s].Add(key); + } + } + } + + public void InvalidateItem(string key) + { + key = HashKey(key); + + using (EnterWriteLock()) + { + _cache.Remove(key); + + foreach (var p in _entitySetToKey) + p.Value.Remove(key); + } + } + + public void InvalidateSets(IEnumerable entitySets) + { + var keysToRemove = new HashSet(); + + using (EnterWriteLock()) + { + foreach (var entitySet in entitySets) + { + if (_entitySetToKey.ContainsKey(entitySet)) + { + keysToRemove.AddRange(_entitySetToKey[entitySet]); + + } + } + + foreach (var k in keysToRemove) + _cache.Remove(k); + + foreach (var s in entitySets) + _entitySetToKey.RemoveAll(s); + } + } + + private static string HashKey(string key) + { + // Looking up large Keys can be expensive (comparing Large Strings), so if keys are large, hash them, otherwise if keys are short just use as-is + if (key.Length <= 128) + return KEYPREFIX + key; + + using (var sha = new SHA1CryptoServiceProvider()) + { + key = Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(key))); + return KEYPREFIX + key; + } + } + + private IDisposable EnterReadLock() + { + return _rwLock.GetUpgradeableReadLock(); + } + + public IDisposable EnterWriteLock() + { + return _rwLock.GetWriteLock(); + } + + } +} diff --git a/src/Libraries/SmartStore.Data/Caching/EfCachingPolicy.cs b/src/Libraries/SmartStore.Data/Caching/EfCachingPolicy.cs new file mode 100644 index 0000000000..38f748f6d4 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Caching/EfCachingPolicy.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Data.Entity.Core.Metadata.Edm; +using System.Diagnostics; +using System.Linq; +using System.Text; +using EFCache; +using SmartStore.Core.Domain.Catalog; +using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Domain.Directory; +using SmartStore.Core.Domain.Discounts; +using SmartStore.Core.Domain.Localization; +using SmartStore.Core.Domain.Logging; +using SmartStore.Core.Domain.Messages; +using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Domain.Security; +using SmartStore.Core.Domain.Stores; +using SmartStore.Core.Domain.Tax; +using SmartStore.Core.Domain.Themes; +using SmartStore.Core.Domain.Topics; + +namespace SmartStore.Data.Caching +{ + + /* TODO: (mc) + * ======================== + * 1. Let developers register custom caching policies for single entities (from plugins) + * 2. Caching policies should contain expiration info and cacheable rows count + * 3. Backend: Let users decide which entities to cache + * 4. Backend: Let users purge the cache + */ + + internal class EfCachingPolicy : CachingPolicy + { + private static readonly HashSet _cacheableSets = new HashSet + { + typeof(AclRecord).Name, + typeof(ActivityLogType).Name, + typeof(CategoryTemplate).Name, + typeof(CheckoutAttribute).Name, + typeof(CheckoutAttributeValue).Name, + typeof(Country).Name, + typeof(Currency).Name, + typeof(CustomerRole).Name, + typeof(DeliveryTime).Name, + typeof(Discount).Name, + typeof(DiscountRequirement).Name, + typeof(EmailAccount).Name, + typeof(Language).Name, + typeof(ManufacturerTemplate).Name, + typeof(MeasureDimension).Name, + typeof(MeasureWeight).Name, + typeof(MessageTemplate).Name, + typeof(PermissionRecord).Name, + typeof(ProductTemplate).Name, + typeof(QuantityUnit).Name, + typeof(StateProvince).Name, + typeof(Store).Name, + typeof(StoreMapping).Name, + typeof(TaxCategory).Name, + typeof(ThemeVariable).Name, + typeof(Topic).Name + }; + + protected override bool CanBeCached(ReadOnlyCollection affectedEntitySets, string sql, IEnumerable> parameters) + { + var entitySets = affectedEntitySets.Select(x => x.Name); + var result = entitySets.Any(x => _cacheableSets.Contains(x)); + return result; + } + + protected override void GetExpirationTimeout(ReadOnlyCollection affectedEntitySets, out TimeSpan slidingExpiration, out DateTimeOffset absoluteExpiration) + { + base.GetExpirationTimeout(affectedEntitySets, out slidingExpiration, out absoluteExpiration); + absoluteExpiration = DateTimeOffset.Now.AddHours(24); + } + + protected override void GetCacheableRows(ReadOnlyCollection affectedEntitySets, out int minCacheableRows, out int maxCacheableRows) + { + base.GetCacheableRows(affectedEntitySets, out minCacheableRows, out maxCacheableRows); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs index 3742c8b59e..8a1eb6ba78 100644 --- a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs +++ b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs @@ -4803,7 +4803,7 @@ public IList ScheduleTasks() new ScheduleTask { Name = "Clear cache", - Seconds = 600, + Seconds = 14400, // 4 hrs Type = "SmartStore.Services.Caching.ClearCacheTask, SmartStore.Services", Enabled = false, StopOnError = false, diff --git a/src/Libraries/SmartStore.Data/SmartDbConfiguration.cs b/src/Libraries/SmartStore.Data/SmartDbConfiguration.cs index 476f612085..f67db1a271 100644 --- a/src/Libraries/SmartStore.Data/SmartDbConfiguration.cs +++ b/src/Libraries/SmartStore.Data/SmartDbConfiguration.cs @@ -1,11 +1,15 @@ using System; using System.Collections.Generic; using System.Data.Entity; +using System.Data.Entity.Core.Common; using System.Data.Entity.Infrastructure; using System.Data.Entity.Infrastructure.DependencyResolution; using System.Linq; +using EFCache; using SmartStore.Core.Data; +using SmartStore.Core.Infrastructure; using SmartStore.Data.Setup; +using SmartStore.Data.Caching; namespace SmartStore.Data { @@ -24,6 +28,26 @@ public SmartDbConfiguration() if (provider != null) { base.SetDefaultConnectionFactory(provider.GetConnectionFactory()); + + // prepare EntityFramework 2nd level cache + ICache cache = null; + try + { + var innerCache = EngineContext.Current.Resolve>(); + cache = new EfCacheImpl(innerCache(typeof(SmartStore.Core.Caching.StaticCache))); + } + catch + { + cache = new InMemoryCache(); + } + + var transactionHandler = new CacheTransactionHandler(cache); + AddInterceptor(transactionHandler); + + Loaded += + (sender, args) => args.ReplaceService( + (s, _) => new CachingProviderServices(s, transactionHandler, + new EfCachingPolicy())); } } } diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 5ccd723030..a0525d3e01 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -65,6 +65,9 @@ ..\..\packages\Autofac.3.4.1\lib\net40\Autofac.dll + + ..\..\packages\EntityFramework.Cache.1.0.0\lib\net45\EFCache.dll + False ..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll @@ -115,6 +118,8 @@ Properties\AssemblyVersionInfo.cs + + @@ -584,6 +589,7 @@ + diff --git a/src/Libraries/SmartStore.Data/packages.config b/src/Libraries/SmartStore.Data/packages.config index 8ae4db4807..1101cadf32 100644 --- a/src/Libraries/SmartStore.Data/packages.config +++ b/src/Libraries/SmartStore.Data/packages.config @@ -2,6 +2,7 @@ + diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs index 68cf11d375..b03c247f39 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedEmailService.cs @@ -95,7 +95,7 @@ public virtual IList GetQueuedEmailsByIds(int[] queuedEmailIds) if (queuedEmailIds == null || queuedEmailIds.Length == 0) return new List(); - var query = from qe in _queuedEmailRepository.Table.Expand(x => x.EmailAccount) + var query = from qe in _queuedEmailRepository.Table where queuedEmailIds.Contains(qe.Id) select qe; From ddd534318d05aedaa55b7bee64dfc8764ee2c49b Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 16 Jul 2015 12:44:03 +0200 Subject: [PATCH 0255/1256] Resolves #731 Web-Api: allow deletion of product category and manufacturer assignments --- changelog.md | 2 + .../Controllers/OData/ProductsController.cs | 81 ++++++++++++---- src/Plugins/SmartStore.WebApi/changelog.md | 1 + .../WebApi/WebApiCore.cs | 73 ++++++++------- .../WebApi/WebApiEntityController.cs | 92 ++++++++++++------- .../WebApi/WebApiExtension.cs | 18 ++++ 6 files changed, 183 insertions(+), 84 deletions(-) diff --git a/changelog.md b/changelog.md index fe27596550..69001129fd 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,8 @@ * #718 ShopConnector: Import option for "Published" and "Disable buy\wishlist button" * #702 Facebook and Twitter external authentication suitable for multi-stores * #704 Make primary store currency suitable for multi-stores +* #727 Web-API: Option to deactivate TimestampOlderThanLastRequest validation +* #731 Web-API: Allow deletion and inserting of product category and manufacturer assignments ### Improvements * (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%. diff --git a/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs b/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs index e0a6d49da2..4e0e4044be 100644 --- a/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs +++ b/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; +using System.Net.Http; using System.Web.Http; using System.Web.Http.OData; using SmartStore.Core; @@ -24,17 +26,23 @@ public class ProductsController : WebApiEntityController _priceCalculationService; private readonly Lazy _urlRecordService; private readonly Lazy _productAttributeService; + private readonly Lazy _categoryService; + private readonly Lazy _manufacturerService; public ProductsController( Lazy workContext, Lazy priceCalculationService, Lazy urlRecordService, - Lazy productAttributeService) + Lazy productAttributeService, + Lazy categoryService, + Lazy manufacturerService) { _workContext = workContext; _priceCalculationService = priceCalculationService; _urlRecordService = urlRecordService; _productAttributeService = productAttributeService; + _categoryService = categoryService; + _manufacturerService = manufacturerService; } protected override IQueryable GetEntitySet() @@ -79,6 +87,60 @@ public SingleResult GetProduct(int key) // navigation properties + public HttpResponseMessage NavigationProductCategories(int key, int relatedKey) + { + var productCategories = _categoryService.Value.GetProductCategoriesByProductId(key, true); + var productCategory = productCategories.FirstOrDefault(x => x.CategoryId == relatedKey); + + if (Request.Method == HttpMethod.Post) + { + if (productCategory == null) + { + productCategory = new ProductCategory { ProductId = key, CategoryId = relatedKey }; + + _categoryService.Value.InsertProductCategory(productCategory); + + return Request.CreateResponse(HttpStatusCode.Created, productCategory); + } + } + else if (Request.Method == HttpMethod.Delete) + { + if (productCategory != null) + _categoryService.Value.DeleteProductCategory(productCategory); + + return Request.CreateResponse(HttpStatusCode.NoContent); + } + + return Request.CreateResponseForEntity(productCategory, relatedKey); + } + + public HttpResponseMessage NavigationProductManufacturers(int key, int relatedKey) + { + var productManufacturers = _manufacturerService.Value.GetProductManufacturersByProductId(key, true); + var productManufacturer = productManufacturers.FirstOrDefault(x => x.ManufacturerId == relatedKey); + + if (Request.Method == HttpMethod.Post) + { + if (productManufacturer == null) + { + productManufacturer = new ProductManufacturer { ProductId = key, ManufacturerId = relatedKey }; + + _manufacturerService.Value.InsertProductManufacturer(productManufacturer); + + return Request.CreateResponse(HttpStatusCode.Created, productManufacturer); + } + } + else if (Request.Method == HttpMethod.Delete) + { + if (productManufacturer != null) + _manufacturerService.Value.DeleteProductManufacturer(productManufacturer); + + return Request.CreateResponse(HttpStatusCode.NoContent); + } + + return Request.CreateResponseForEntity(productManufacturer, relatedKey); + } + public DeliveryTime GetDeliveryTime(int key) { return GetExpandedProperty(key, x => x.DeliveryTime); @@ -345,22 +407,5 @@ public IQueryable ManageAttributes(int key, ODataAction return entity.ProductVariantAttributes.AsQueryable(); } - - - //[HttpGet, WebApiQueryable] - //public IQueryable GetRelatedProducts(int key) - //{ - // if (!ModelState.IsValid) - // throw this.ExceptionInvalidModelState(); - - // var repository = EngineContext.Current.Resolve>(); - - // var query = - // from x in repository.Table - // where x.ProductId1 == key - // select x; - - // return query; - //} } } diff --git a/src/Plugins/SmartStore.WebApi/changelog.md b/src/Plugins/SmartStore.WebApi/changelog.md index 7d45bbd682..6c5bd87808 100644 --- a/src/Plugins/SmartStore.WebApi/changelog.md +++ b/src/Plugins/SmartStore.WebApi/changelog.md @@ -4,6 +4,7 @@ ###New Features * Added OData endpoint for payment method * #727 Option to deactivate TimestampOlderThanLastRequest validation +* #731 Allow deletion and inserting of product category and manufacturer assignments ###Improvements * Using header timestamp as last user request date rather than API server date diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCore.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCore.cs index 3c2517732b..9f97de2d1b 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCore.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCore.cs @@ -1,40 +1,8 @@ using System.Text; +using Microsoft.Data.OData; namespace SmartStore.Web.Framework.WebApi { - public class WebApiRequestContext - { - public string PublicKey { get; set; } - public string SecretKey { get; set; } - - public string Url { get; set; } - public string HttpMethod { get; set; } - public string HttpAcceptType { get; set; } - - public bool IsValid - { - get - { - return - !string.IsNullOrWhiteSpace(PublicKey) && !string.IsNullOrWhiteSpace(SecretKey) && - !string.IsNullOrWhiteSpace(Url) && - !string.IsNullOrWhiteSpace(HttpMethod) && !string.IsNullOrWhiteSpace(HttpAcceptType); - } - } - public override string ToString() - { - var sb = new StringBuilder(); - - sb.AppendLine(string.Format("PublicKey: ", PublicKey)); - sb.AppendLine(string.Format("Url: ", Url)); - sb.AppendLine(string.Format("HttpMethod: ", HttpMethod)); - sb.AppendLine(string.Format("HttpAcceptType: ", HttpAcceptType)); - - return sb.ToString(); - } - } - - public static class WebApiGlobal { public static int MaxApiVersion { get { return 1; } } @@ -45,6 +13,8 @@ public static class WebApiGlobal public static string MostRecentOdataPath { get { return "odata/v1"; } } public static string PluginSystemName { get { return "SmartStore.WebApi"; } } + public static ODataVersion ODataVersion { get { return ODataVersion.V3; } } + /// see http://tools.ietf.org/html/rfc6648 public static class Header { @@ -72,7 +42,9 @@ public static class Error { public static string PropertyNotFound { get { return "Entity does not own property '{0}'."; } } public static string PropertyNotExpanded { get { return "Property path '{0}' cannot be expanded."; } } - public static string NoKeyFromPath { get { return "Cannot retrieve entity key from OData path."; } } + public static string NoKeyFromPath { get { return "Cannot retrieve valid entity key from OData path."; } } + public static string NoRelatedKeyFromPath { get { return "Cannot retrieve valid related entity key from OData path."; } } + public static string NoNavigationFromPath { get { return "Cannot retrieve the navigation property from OData path."; } } public static string EntityNotFound { get { return "Entity with key '{0}' could not be found."; } } public static string NoDataToInsert { get { return "No data to be inserted."; } } } @@ -82,4 +54,37 @@ public static class QueryOption public static string Fulfill { get { return "SmNetFulfill"; } } } } + + + public class WebApiRequestContext + { + public string PublicKey { get; set; } + public string SecretKey { get; set; } + + public string Url { get; set; } + public string HttpMethod { get; set; } + public string HttpAcceptType { get; set; } + + public bool IsValid + { + get + { + return + !string.IsNullOrWhiteSpace(PublicKey) && !string.IsNullOrWhiteSpace(SecretKey) && + !string.IsNullOrWhiteSpace(Url) && + !string.IsNullOrWhiteSpace(HttpMethod) && !string.IsNullOrWhiteSpace(HttpAcceptType); + } + } + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("PublicKey: ", PublicKey)); + sb.AppendLine(string.Format("Url: ", Url)); + sb.AppendLine(string.Format("HttpMethod: ", HttpMethod)); + sb.AppendLine(string.Format("HttpAcceptType: ", HttpAcceptType)); + + return sb.ToString(); + } + } } diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs index 039d981db0..370b667b19 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiEntityController.cs @@ -1,19 +1,19 @@ -using SmartStore.Core; -using SmartStore.Core.Data; -using SmartStore.Core.Infrastructure; -using SmartStore.Services.Directory; -using SmartStore.Services.Localization; -using System; +using System; +using System.Data.Entity.Core.Metadata.Edm; +using System.Data.Entity.Infrastructure; using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Http; +using System.Reflection; using System.Web.Http; using System.Web.Http.OData; using System.Web.Http.OData.Routing; -using System.Reflection; -using System.Data.Entity.Infrastructure; -using System.Data.Entity.Core.Metadata.Edm; +using SmartStore.Core; +using SmartStore.Core.Data; +using SmartStore.Core.Infrastructure; +using SmartStore.Services.Directory; +using SmartStore.Services.Localization; namespace SmartStore.Web.Framework.WebApi { @@ -24,7 +24,7 @@ public abstract class WebApiEntityController : EntitySetContr protected internal HttpResponseException ExceptionEntityNotFound(TKey key) { var response = Request.CreateErrorResponse(HttpStatusCode.NotFound, - WebApiGlobal.Error.EntityNotFound.FormatWith(key)); + WebApiGlobal.Error.EntityNotFound.FormatInvariant(key)); return new HttpResponseException(response); } @@ -33,22 +33,32 @@ protected internal HttpResponseException ExceptionNotExpanded(Express { // NotFound cause of nullable properties var response = Request.CreateErrorResponse(HttpStatusCode.NotFound, - WebApiGlobal.Error.PropertyNotExpanded.FormatWith(path.ToString())); + WebApiGlobal.Error.PropertyNotExpanded.FormatInvariant(path.ToString())); return new HttpResponseException(response); } public override HttpResponseMessage HandleUnmappedRequest(ODataPath odataPath) { - if (Request.Method == HttpMethod.Get || Request.Method == HttpMethod.Post) + if (odataPath.PathTemplate.IsCaseInsensitiveEqual("~/entityset/key/property") || + odataPath.PathTemplate.IsCaseInsensitiveEqual("~/entityset/key/cast/property") || + odataPath.PathTemplate.IsCaseInsensitiveEqual("~/entityset/key/unresolved")) { - if (odataPath.PathTemplate.IsCaseInsensitiveEqual("~/entityset/key/property") || - odataPath.PathTemplate.IsCaseInsensitiveEqual("~/entityset/key/cast/property") || - odataPath.PathTemplate.IsCaseInsensitiveEqual("~/entityset/key/unresolved")) + if (Request.Method == HttpMethod.Get || Request.Method == HttpMethod.Post) { return UnmappedGetProperty(odataPath); } } + else if (odataPath.PathTemplate.IsCaseInsensitiveEqual("~/entityset/key/navigation/key")) + { + if (Request.Method == HttpMethod.Get || Request.Method == HttpMethod.Post || Request.Method == HttpMethod.Delete) + { + // we ignore standard odata path cause they differ: + // ~/entityset/key/$links/navigation (odata 3 "link"), ~/entityset/key/navigation/$ref (odata 4 "reference") + + return UnmappedGetNavigation(odataPath); + } + } return base.HandleUnmappedRequest(odataPath); } @@ -63,7 +73,7 @@ protected virtual internal HttpResponseMessage UnmappedGetProperty(ODataPath oda var entity = GetEntityByKey(key); if (entity == null) - return Request.CreateErrorResponse(HttpStatusCode.NotFound, WebApiGlobal.Error.EntityNotFound.FormatWith(key)); + return Request.CreateErrorResponse(HttpStatusCode.NotFound, WebApiGlobal.Error.EntityNotFound.FormatInvariant(key)); PropertyInfo pi = null; string propertyName = null; @@ -88,7 +98,40 @@ protected virtual internal HttpResponseMessage UnmappedGetProperty(ODataPath oda protected virtual internal HttpResponseMessage UnmappedGetProperty(TEntity entity, string propertyName) { - return Request.CreateErrorResponse(HttpStatusCode.BadRequest, WebApiGlobal.Error.PropertyNotFound.FormatWith(propertyName)); + return Request.CreateErrorResponse(HttpStatusCode.BadRequest, WebApiGlobal.Error.PropertyNotFound.FormatInvariant(propertyName)); + } + + protected virtual internal HttpResponseMessage UnmappedGetNavigation(ODataPath odataPath) + { + int key, relatedKey; + + if (!odataPath.GetNormalizedKey(1, out key)) + return Request.CreateErrorResponse(HttpStatusCode.BadRequest, WebApiGlobal.Error.NoKeyFromPath); + + var navigationProperty = odataPath.GetNavigation(2); + + if (navigationProperty.IsEmpty()) + return Request.CreateErrorResponse(HttpStatusCode.BadRequest, WebApiGlobal.Error.NoNavigationFromPath); + + if (!odataPath.GetNormalizedKey(3, out relatedKey)) + return Request.CreateErrorResponse(HttpStatusCode.BadRequest, WebApiGlobal.Error.NoRelatedKeyFromPath); + + var methodName = string.Concat("Navigation", navigationProperty); + var methodInfo = this.GetType().GetMethods().FirstOrDefault(x => x.Name == methodName); + + if (methodInfo != null) + { + HttpResponseMessage response = null; + + this.ProcessEntity(() => + { + response = (HttpResponseMessage)methodInfo.Invoke(this, new object[] { key, relatedKey }); + return null; + }); + + return response; + } + return base.HandleUnmappedRequest(odataPath); } //protected virtual IRepository CreateRepository() @@ -378,20 +421,5 @@ protected internal virtual TEntity FulfillPropertiesOn(TEntity entity) } return entity; } - - //protected internal IQueryable GenericAttributes(int key, string keyGroup) - //{ - // if (!ModelState.IsValid) - // throw this.ExceptionInvalidModelState(); - - // var repository = EngineContext.Current.Resolve>(); - - // var query = - // from x in repository.Table - // where x.EntityId == key && x.KeyGroup == keyGroup && x.Key != WebApiUserCacheData.Key - // select x; - - // return query; - //} } } diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiExtension.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiExtension.cs index 28f430b974..9051894b20 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiExtension.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiExtension.cs @@ -25,6 +25,13 @@ public static HttpResponseMessage CreateResponse(this HttpRequestMessage request { return _createResponse.MakeGenericMethod(type).Invoke(null, new[] { request, status, value }) as HttpResponseMessage; } + public static HttpResponseMessage CreateResponseForEntity(this HttpRequestMessage request, object entity, int key) + { + if (entity == null) + return request.CreateResponse(HttpStatusCode.NotFound, WebApiGlobal.Error.EntityNotFound.FormatInvariant(key)); + + return request.CreateResponse(HttpStatusCode.OK, entity.GetType(), entity); + } public static HttpResponseException ExceptionInvalidModelState(this ApiController apiController) { @@ -98,6 +105,17 @@ public static bool GetNormalizedKey(this ODataPath odataPath, int segmentIndex, return false; } + public static string GetNavigation(this ODataPath odataPath, int segmentIndex) + { + if (odataPath.Segments.Count > segmentIndex) + { + string navigationProperty = (odataPath.Segments[segmentIndex] as NavigationPathSegment).NavigationPropertyName; + + return navigationProperty; + } + return null; + } + public static void DeleteLocalFiles(this MultipartFormDataStreamProvider provider) { try From e45963b8c02b2afc235b938e51e507b883dfa0e1 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 16 Jul 2015 13:19:08 +0200 Subject: [PATCH 0256/1256] Removed odd extension method --- .../Catalog/ManufacturerExtensions.cs | 29 ------------------- .../SmartStore.Services.csproj | 1 - .../Controllers/ManufacturerController.cs | 18 ++++++------ 3 files changed, 9 insertions(+), 39 deletions(-) delete mode 100644 src/Libraries/SmartStore.Services/Catalog/ManufacturerExtensions.cs diff --git a/src/Libraries/SmartStore.Services/Catalog/ManufacturerExtensions.cs b/src/Libraries/SmartStore.Services/Catalog/ManufacturerExtensions.cs deleted file mode 100644 index 9d29a61c29..0000000000 --- a/src/Libraries/SmartStore.Services/Catalog/ManufacturerExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; -using SmartStore.Core.Domain.Catalog; - -namespace SmartStore.Services.Catalog -{ - /// - /// Extensions - /// - public static class ManufacturerExtensions - { - /// - /// Returns a ProductManufacturer that has the specified values - /// - /// Source - /// Product identifier - /// Manufacturer identifier - /// A ProductManufacturer that has the specified values; otherwise null - public static ProductManufacturer FindProductManufacturer(this IList source, - int productId, int manufacturerId) - { - foreach (var productManufacturer in source) - if (productManufacturer.ProductId == productId && productManufacturer.ManufacturerId == manufacturerId) - return productManufacturer; - - return null; - } - - } -} diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index 5f6e45b404..226ed5fa15 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -210,7 +210,6 @@ - diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs index 178d046379..9160edaad3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs @@ -641,16 +641,16 @@ public ActionResult ProductAddPopup(string btnId, string formId, ManufacturerMod if (product != null) { var existingProductmanufacturers = _manufacturerService.GetProductManufacturersByManufacturerId(model.ManufacturerId, 0, int.MaxValue, true); - if (existingProductmanufacturers.FindProductManufacturer(id, model.ManufacturerId) == null) + + if (!existingProductmanufacturers.Any(x => x.ProductId == id && x.ManufacturerId == model.ManufacturerId)) { - _manufacturerService.InsertProductManufacturer( - new ProductManufacturer() - { - ManufacturerId = model.ManufacturerId, - ProductId = id, - IsFeaturedProduct = false, - DisplayOrder = 1 - }); + _manufacturerService.InsertProductManufacturer(new ProductManufacturer + { + ManufacturerId = model.ManufacturerId, + ProductId = id, + IsFeaturedProduct = false, + DisplayOrder = 1 + }); } } } From d617a32d81a23d37a5dcce13dea63077b2100e6d Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 16 Jul 2015 14:14:09 +0200 Subject: [PATCH 0257/1256] Price tab threw an exception. Looks like it's not a good idea to use ICommonServices.Cache in a service class. --- ...61756463_PrimaryStoreCurrencyMultiStore.cs | 6 +++ .../Catalog/ProductService.cs | 16 ++++--- .../Controllers/ProductController.cs | 45 ++++++++++++------- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs index b7862fafd5..e61acfd677 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -144,6 +144,12 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Specifies the maximum news age in days. Older blog posts are not exported in the RSS feed.", "Legt das maximale Blog-Alter in Tagen fest. ltere Blog-Eintrge werden im RSS-Feed nicht exportiert."); + + builder.AddOrUpdate("Admin.Common.Deleted", + "Deleted", + "Gelscht"); + + builder.Delete("Admin.Configuration.Currencies.CantDeletePrimary"); builder.Delete("Admin.Configuration.Currencies.CantDeleteExchange"); builder.Delete("Admin.Configuration.Currencies.Fields.MarkAsPrimaryStoreCurrency"); diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs index 5618ba86ad..8dc0d5f73c 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs @@ -6,6 +6,7 @@ using System.ServiceModel.Syndication; using System.Web.Mvc; using SmartStore.Core; +using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Common; @@ -55,6 +56,7 @@ public partial class ProductService : IProductService private readonly IWorkflowMessageService _workflowMessageService; private readonly IDataProvider _dataProvider; private readonly IDbContext _dbContext; + private readonly ICacheManager _cacheManager; private readonly LocalizationSettings _localizationSettings; private readonly CommonSettings _commonSettings; private readonly ICommonServices _services; @@ -108,6 +110,7 @@ public ProductService( IWorkflowMessageService workflowMessageService, IDataProvider dataProvider, IDbContext dbContext, + ICacheManager cacheManager, LocalizationSettings localizationSettings, CommonSettings commonSettings, ICommonServices services, @@ -132,6 +135,7 @@ public ProductService( this._workflowMessageService = workflowMessageService; this._dataProvider = dataProvider; this._dbContext = dbContext; + this._cacheManager = cacheManager; this._localizationSettings = localizationSettings; this._commonSettings = commonSettings; this._services = services; @@ -272,7 +276,7 @@ public virtual Product GetProductById(int productId) return null; string key = string.Format(PRODUCTS_BY_ID_KEY, productId); - return _services.Cache.Get(key, () => + return _cacheManager.Get(key, () => { return _productRepository.GetById(productId); }); @@ -314,7 +318,7 @@ public virtual void InsertProduct(Product product) _productRepository.Insert(product); //clear cache - _services.Cache.RemoveByPattern(PRODUCTS_PATTERN_KEY); + _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); //event notification _services.EventPublisher.EntityInserted(product); @@ -339,7 +343,7 @@ public virtual void UpdateProduct(Product product, bool publishEvent = true) _productRepository.Update(product); // cache - _services.Cache.RemoveByPattern(PRODUCTS_PATTERN_KEY); + _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); // event notification if (publishEvent && modified) @@ -1588,7 +1592,7 @@ public virtual void DeleteTierPrice(TierPrice tierPrice) _tierPriceRepository.Delete(tierPrice); - _services.Cache.RemoveByPattern(PRODUCTS_PATTERN_KEY); + _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); //event notification _services.EventPublisher.EntityDeleted(tierPrice); @@ -1619,7 +1623,7 @@ public virtual void InsertTierPrice(TierPrice tierPrice) _tierPriceRepository.Insert(tierPrice); - _services.Cache.RemoveByPattern(PRODUCTS_PATTERN_KEY); + _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); //event notification _services.EventPublisher.EntityInserted(tierPrice); @@ -1636,7 +1640,7 @@ public virtual void UpdateTierPrice(TierPrice tierPrice) _tierPriceRepository.Update(tierPrice); - _services.Cache.RemoveByPattern(PRODUCTS_PATTERN_KEY); + _cacheManager.RemoveByPattern(PRODUCTS_PATTERN_KEY); //event notification _services.EventPublisher.EntityUpdated(tierPrice); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index 4a8f624b92..efd7a9f60c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -3394,34 +3394,49 @@ public ActionResult TierPriceList(GridCommand command, int productId) if (product == null) throw new ArgumentException("No product variant found with the specified id"); + var allStores = _services.StoreService.GetAllStores(); + var allCustomerRoles = _customerService.GetAllCustomerRoles(true); + string allRolesString = T("Admin.Catalog.Products.TierPrices.Fields.CustomerRole.AllRoles"); + string allStoresString = T("Admin.Common.StoresAll"); + string deletedString = "[{0}]".FormatInvariant(T("Admin.Common.Deleted")); + var tierPricesModel = product.TierPrices .OrderBy(x => x.StoreId) .ThenBy(x => x.Quantity) .ThenBy(x => x.CustomerRoleId) .Select(x => { - var storeName = ""; - if (x.StoreId > 0) - { - var store = _storeService.GetStoreById(x.StoreId); - storeName = store != null ? store.Name : "[Deleted]"; - } - else - { - storeName = _localizationService.GetResource("Admin.Common.StoresAll"); - } - return new ProductModel.TierPriceModel() + var tierPriceModel = new ProductModel.TierPriceModel { Id = x.Id, StoreId = x.StoreId, - Store = storeName, - CustomerRole = x.CustomerRoleId.HasValue ? _customerService.GetCustomerRoleById(x.CustomerRoleId.Value).Name : - _localizationService.GetResource("Admin.Catalog.Products.TierPrices.Fields.CustomerRole.AllRoles"), ProductId = x.ProductId, - CustomerRoleId = x.CustomerRoleId.HasValue ? x.CustomerRoleId.Value : 0, + CustomerRoleId = x.CustomerRoleId ?? 0, Quantity = x.Quantity, Price1 = x.Price }; + + if (x.CustomerRoleId.HasValue) + { + var role = allCustomerRoles.FirstOrDefault(r => r.Id == x.CustomerRoleId.Value); + tierPriceModel.CustomerRole = (role == null ? allRolesString : role.Name); + } + else + { + tierPriceModel.CustomerRole = allRolesString; + } + + if (x.StoreId > 0) + { + var store = allStores.FirstOrDefault(s => s.Id == x.StoreId); + tierPriceModel.Store = (store == null ? deletedString : store.Name); + } + else + { + tierPriceModel.Store = allStoresString; + } + + return tierPriceModel; }) .ToList(); From 83c8a71b42d98b156b8476ab84c92c6c618249ee Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 16 Jul 2015 18:00:02 +0200 Subject: [PATCH 0258/1256] The ProductOverviewModel does not require a Product.FullDescription --- src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs | 1 - src/Presentation/SmartStore.Web/Controllers/HomeController.cs | 1 - .../SmartStore.Web/Models/Catalog/ProductOverviewModel.cs | 1 - 3 files changed, 3 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index 3049beedef..4ee0f016c0 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -1015,7 +1015,6 @@ public IEnumerable PrepareProductOverviewModels( Id = product.Id, Name = product.GetLocalized(x => x.Name).EmptyNull(), ShortDescription = product.GetLocalized(x => x.ShortDescription), - FullDescription = product.GetLocalized(x => x.FullDescription), SeName = product.GetSeName() }; diff --git a/src/Presentation/SmartStore.Web/Controllers/HomeController.cs b/src/Presentation/SmartStore.Web/Controllers/HomeController.cs index 8c1f8fc125..6b65cfaf2d 100644 --- a/src/Presentation/SmartStore.Web/Controllers/HomeController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/HomeController.cs @@ -248,7 +248,6 @@ public ActionResult Sitemap() Id = product.Id, Name = product.GetLocalized(x => x.Name).EmptyNull(), ShortDescription = product.GetLocalized(x => x.ShortDescription), - FullDescription = product.GetLocalized(x => x.FullDescription), SeName = product.GetSeName(), }).ToList(); } diff --git a/src/Presentation/SmartStore.Web/Models/Catalog/ProductOverviewModel.cs b/src/Presentation/SmartStore.Web/Models/Catalog/ProductOverviewModel.cs index eb39ca78ee..5561ae3617 100644 --- a/src/Presentation/SmartStore.Web/Models/Catalog/ProductOverviewModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Catalog/ProductOverviewModel.cs @@ -22,7 +22,6 @@ public ProductOverviewModel() public string Name { get; set; } public string ShortDescription { get; set; } - public string FullDescription { get; set; } public string SeName { get; set; } public int ThumbDimension { get; set; } From a94b15221d0684c296fecdc42578179c23aab44e Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 16 Jul 2015 18:36:59 +0200 Subject: [PATCH 0259/1256] GetLowestPrice: Not necessary to fetch the lowest (non-zero) combination price from database. Product.LowestAttributeCombinationPrice sufficient. --- .../SmartStore.Services/Catalog/PriceCalculationService.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index e28b08d053..b254da8051 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -478,11 +478,7 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa if (lowestPrice == decimal.Zero && product.Price == decimal.Zero) { - var combination = product.ProductVariantAttributeCombinations.OrderBy(x => x.Price).FirstOrDefault(x => x.Price > decimal.Zero); - if (combination != null) - { - lowestPrice = combination.Price ?? decimal.Zero; - } + lowestPrice = product.LowestAttributeCombinationPrice ?? decimal.Zero; } return lowestPrice; From 6965a6a36b0d14b1185efa56dc79942a8a106936 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 16 Jul 2015 21:01:56 +0200 Subject: [PATCH 0260/1256] UI: optimized image gallery (white background & nicer animations) + enhanced modal dialog fade animations --- .../Content/bootstrap/custom/custom.less | 69 ++++++---------- .../css/blueimp-gallery-custom.css | 80 +++++++++++++++++-- .../Scripts/public.product-detail.js | 2 +- .../Scripts/smartstore.smartgallery.js | 22 +++-- 4 files changed, 116 insertions(+), 57 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Content/bootstrap/custom/custom.less b/src/Presentation/SmartStore.Web/Content/bootstrap/custom/custom.less index 4100e82a92..6ca430239d 100644 --- a/src/Presentation/SmartStore.Web/Content/bootstrap/custom/custom.less +++ b/src/Presentation/SmartStore.Web/Content/bootstrap/custom/custom.less @@ -417,51 +417,6 @@ th label { } -/*.ui-menu { - padding: 5px 0; - margin: 2px 0 0; // override default ul - background-color: @dropdownBackground; - border: 1px solid #ccc; // Fallback for IE7-8 - border: 1px solid @dropdownBorder; - *border-right-width: 2px; - *border-bottom-width: 2px; - border-top: none; - .border-radius(6px); - .box-shadow(0 5px 10px rgba(0,0,0,.2)); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} - -.ui-autocomplete { - border-color: @inputBorder; // goes nice with textboxes - .box-shadow(0 5px 10px rgba(0,0,0,.12)); - border-top: none !important; -} -.ui-autocomplete.ui-corner-all { - .border-radius(0 0 @inputBorderRadius @inputBorderRadius); -} - -.ui-autocomplete-loading { - background-image: url('images/throbber-progress-black-16.gif'); - background-repeat: no-repeat; - background-position: 98% center; -} - -.ui-autocomplete .ui-menu-item a { - .border-radius(0); - padding: 3px 16px; - font-family: @baseFontFamily; - font-weight: normal; - color: @dropdownLinkColor; - .small(); - - &:hover, - &.ui-state-hover { - color: @dropdownLinkColorHover !important; - background: @dropdownLinkBackgroundHover !important; - } -}*/ // MVC UI adaptation // ------------------------- @@ -513,4 +468,28 @@ th label { .note-editable { background-color: #fff; +} + + +// NICER MODAL FADE +// ------------------------------ + +.modal.fade { + top: 50%; + .transition(~'opacity 0.12s linear, transform 0.12s ease-out'); + .transform(~'translate(0, -40px) scale(0.9, 0.9)'); +} + +.modal.fade.in { + .transform(none); +} + +.modal-backdrop, +.modal-backdrop.fade.in { + .opacity(60); +} + +.modal-header .close { + font-size: 30px; + text-shadow: none; } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Content/image-gallery/css/blueimp-gallery-custom.css b/src/Presentation/SmartStore.Web/Content/image-gallery/css/blueimp-gallery-custom.css index 20597a70b8..94214b65b8 100644 --- a/src/Presentation/SmartStore.Web/Content/image-gallery/css/blueimp-gallery-custom.css +++ b/src/Presentation/SmartStore.Web/Content/image-gallery/css/blueimp-gallery-custom.css @@ -1,8 +1,62 @@  +.smartgallery-overlay, +.blueimp-gallery { + -webkit-transition: opacity 0.2s linear, transform 0.2s ease-out; + transition: opacity 0.2s linear, transform 0.2s ease-out; +} + +.smartgallery-overlay { + position: fixed; + z-index: 999998; + background: #000; + left: 0; + top: 0; + width: 100%; + height: 100%; + opacity: 0; +} +.smartgallery-overlay.in { + opacity: 0.3; +} + + +.blueimp-gallery { + left: 40px; + right: 40px; + top: 40px; + bottom: 40px; + background: #fff; + border: 1px solid rgba(0,0,0, 0.25); + border-radius: 4px; + border-top-right-radius: 0; + xtransition-delay: 0.2s; + -webkit-box-shadow: 0px 4px 20px rgba(0,0,0, 0.35); + box-shadow: 0px 4px 20px rgba(0,0,0, 0.35); + -webkit-transform: translate(0, -75px) scale(0.9, 0.9); + -moz-transform: translate(0, -75px) scale(0.9, 0.9); + -ms-transform: translate(0, -75px) scale(0.9, 0.9); + transform: translate(0, -75px) scale(0.9, 0.9); +} + +.blueimp-gallery-display { + -webkit-transform: none; + -moz-transform: none; + -ms-transform: none; + transform: none; +} + + +.blueimp-gallery > .prev, +.blueimp-gallery > .next, +.blueimp-gallery > .close { + -webkit-transition: all 0.1s ease-in-out; + transition: all 0.1s ease-in-out; +} + .blueimp-gallery > .prev, .blueimp-gallery > .next { border: none; - border-radius: none; + border-radius: 0; text-shadow: none; font-family: initial; background: transparent; @@ -12,25 +66,36 @@ color: #bbb; opacity: 1; } +.blueimp-gallery > .prev { left: 0; } +.blueimp-gallery > .next { right: 0; } + .blueimp-gallery > .prev:hover, .blueimp-gallery > .next:hover { - color: #08c; + color: #888; + background-color: #f5f5f5; +} +.blueimp-gallery > .prev:active, +.blueimp-gallery > .next:active { + background-color: #eaeaea; } .blueimp-gallery > .close { text-shadow: none; opacity: 1 !important; - color: #aaa; padding: 8px 12px; - padding-top: 4px; + padding-top: 2px; border-bottom-left-radius: 6px; - background-color: #fff; + background-color: #c5c5c5; + color: #fff; margin: 0; top: 0; right: 0; } .blueimp-gallery > .close:hover { - color: #333; + background-color: #ee5f5b; +} +.blueimp-gallery > .close:active { + background-color: #ea3d38; } .blueimp-gallery > .indicator { @@ -39,6 +104,7 @@ right: 0; bottom: 0; background-color: #fff; + background-color: rgba(255,255,255, 0.5); opacity: 0.95; padding: 10px 0; -webkit-transition: all 0.4s ease-in-out; @@ -82,3 +148,5 @@ height: 25px; } } + + diff --git a/src/Presentation/SmartStore.Web/Scripts/public.product-detail.js b/src/Presentation/SmartStore.Web/Scripts/public.product-detail.js index c86e55904f..bcc3df45d8 100644 --- a/src/Presentation/SmartStore.Web/Scripts/public.product-detail.js +++ b/src/Presentation/SmartStore.Web/Scripts/public.product-detail.js @@ -169,7 +169,7 @@ zoomType: opts.zoomType }, box: { - enabled: true + enabled: true } }); } diff --git a/src/Presentation/SmartStore.Web/Scripts/smartstore.smartgallery.js b/src/Presentation/SmartStore.Web/Scripts/smartstore.smartgallery.js index 0552e31a90..fe3305017b 100644 --- a/src/Presentation/SmartStore.Web/Scripts/smartstore.smartgallery.js +++ b/src/Presentation/SmartStore.Web/Scripts/smartstore.smartgallery.js @@ -410,6 +410,7 @@ initBox: function() { var self = this; + var gov; var getWidget = function (id) { var widget = $('#' + id); @@ -462,10 +463,18 @@ widget = getWidget(id == 'default' ? 'image-gallery-default' : id), container = (widget.length && widget) || $(Gallery.prototype.options.container), callbacks = { - onopen: function () { - container.data('gallery', this).trigger('open'); + onopen: function () { + if (!gov || (gov = $('.smartgallery-overlay')).length == 0) { + gov = $('').insertBefore(widget[0]); + gov.on('click', function (e) { + widget.data('gallery').close(); + }); + } + + gov.show().addClass("in"); + container.data('gallery', this).trigger('open'); }, - onopened: function () { + onopened: function () { container.trigger('opened'); }, onslide: function () { @@ -478,9 +487,11 @@ container.trigger('slidecomplete', arguments); }, onclose: function () { - container.trigger('close'); + gov.removeClass("in"); + container.trigger('close'); }, onclosed: function () { + gov.css('display', 'none'); container.trigger('closed').removeData('gallery'); } }, @@ -494,7 +505,7 @@ event: e }, callbacks, - self.options + self.options.box || {} ), // Select all links with the same data-gallery attribute: links = $('[data-gallery="' + id + '"]').not($(this)); @@ -862,6 +873,7 @@ // full size image box options box: { enabled: true, + closeOnSlideClick: false /* {...} blueimp image gallery options are passed through */ }, callbacks: { From fb832f981df764c74c1931ebb79c198d39ed2b2c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 16 Jul 2015 22:40:13 +0200 Subject: [PATCH 0261/1256] GetLowestPrice: Load the id of products with price adjustments for all products of a page in one go --- .../Catalog/IProductAttributeService.cs | 10 ++++-- .../Catalog/PriceCalculationService.cs | 12 ------- .../Catalog/ProductAttributeService.cs | 33 ++++++++++++++----- .../Controllers/CatalogHelper.cs | 11 +++++++ 4 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs index c23e5de26e..c150159c83 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using SmartStore.Core.Domain.Catalog; -using SmartStore.Core.Domain.Media; namespace SmartStore.Services.Catalog { @@ -66,7 +65,6 @@ public partial interface IProductAttributeService /// Product variant attribute mapping ProductVariantAttribute GetProductVariantAttributeById(int productVariantAttributeId); - // codehint: sm-add /// /// Gets multiple product variant attribute mappings by their keys /// @@ -110,7 +108,6 @@ public partial interface IProductAttributeService /// Product variant attribute value ProductVariantAttributeValue GetProductVariantAttributeValueById(int productVariantAttributeValueId); - // codehint: sm-add /// /// Gets multiple product variant attribute value /// @@ -130,6 +127,13 @@ public partial interface IProductAttributeService /// The product variant attribute value void UpdateProductVariantAttributeValue(ProductVariantAttributeValue productVariantAttributeValue); + /// + /// Gets a list of product identifiers which have price adjustments + /// + /// Array of product identifiers + /// List of product identifiers + IList GetProductIdsWithPriceAdjustments(int[] productIds); + #endregion #region Product variant attribute combinations (ProductVariantAttributeCombination) diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index b254da8051..b5fc552c0f 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -464,18 +464,6 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa displayFromMessage = true; } - if (!displayFromMessage) - { - foreach (var attribute in product.ProductVariantAttributes) - { - if (attribute.ProductVariantAttributeValues.Any(x => x.PriceAdjustment != decimal.Zero)) - { - displayFromMessage = true; - break; - } - } - } - if (lowestPrice == decimal.Zero && product.Price == decimal.Zero) { lowestPrice = product.LowestAttributeCombinationPrice ?? decimal.Zero; diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs index cda03df832..66a1dc876d 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs @@ -6,11 +6,6 @@ using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Events; using SmartStore.Services.Media; -using SmartStore.Core.Infrastructure; -using SmartStore.Data; -using System.Text; -using System.Linq.Expressions; -using SmartStore.Core.Domain.Media; namespace SmartStore.Services.Catalog { @@ -234,7 +229,6 @@ public virtual ProductVariantAttribute GetProductVariantAttributeById(int produc }); } - // codehint: sm-add public virtual IEnumerable GetProductVariantAttributesByIds(params int[] ids) { if (ids == null || ids.Length == 0) @@ -245,7 +239,6 @@ public virtual IEnumerable GetProductVariantAttributesB return _productVariantAttributeRepository.GetMany(ids); } - // codehint: sm-add public virtual IEnumerable GetProductVariantAttributeValuesByIds(params int[] productVariantAttributeValueIds) { if (productVariantAttributeValueIds == null || productVariantAttributeValueIds.Length == 0) @@ -391,6 +384,30 @@ public virtual void UpdateProductVariantAttributeValue(ProductVariantAttributeVa _eventPublisher.EntityUpdated(productVariantAttributeValue); } + /// + /// Gets a list of product identifiers which have price adjustments + /// + /// Array of product identifiers + /// List of product identifiers + public virtual IList GetProductIdsWithPriceAdjustments(int[] productIds) + { + var queryMappings = + from m in _productVariantAttributeRepository.TableUntracked + where productIds.Contains(m.ProductId) + select new { m.Id, m.ProductId }; + + var query = + from v in _productVariantAttributeValueRepository.TableUntracked + join m in queryMappings on v.ProductVariantAttributeId equals m.Id + where v.PriceAdjustment != 0 + group v by m.ProductId into grp + select grp.Key; + + var result = query.ToList(); + + return result; + } + #endregion #region Product variant attribute combinations (ProductVariantAttributeCombination) @@ -488,7 +505,6 @@ public virtual void InsertProductVariantAttributeCombination(ProductVariantAttri if (combination == null) throw new ArgumentNullException("combination"); - // codehint: sm-add //if (combination.IsDefaultCombination) //{ // EnsureSingleDefaultVariant(combination); @@ -509,7 +525,6 @@ public virtual void UpdateProductVariantAttributeCombination(ProductVariantAttri if (combination == null) throw new ArgumentNullException("combination"); - // codehint: sm-add //if (combination.IsDefaultCombination) //{ // EnsureSingleDefaultVariant(combination); diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index 4ee0f016c0..3401491470 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -1004,6 +1004,9 @@ public IEnumerable PrepareProductOverviewModels( { "Common.AdditionalShippingSurcharge", T("Common.AdditionalShippingSurcharge") } }; + int[] productIds = products.Select(x => x.Id).ToArray(); + IList productIdsWithPriceAdjustments = null; + var models = new List(); foreach (var product in products) @@ -1134,6 +1137,14 @@ public IEnumerable PrepareProductOverviewModels( bool displayFromMessage = false; decimal minPossiblePrice = _priceCalculationService.GetLowestPrice(product, out displayFromMessage); + if (!displayFromMessage) + { + if (productIdsWithPriceAdjustments == null) + productIdsWithPriceAdjustments = _productAttributeService.GetProductIdsWithPriceAdjustments(productIds); + + displayFromMessage = productIdsWithPriceAdjustments.Contains(product.Id); + } + decimal taxRate = decimal.Zero; decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate); decimal finalPriceBase = _taxService.GetProductPrice(product, minPossiblePrice, out taxRate); From 69e63f59979f0ff8b84f3499700d34d98b5fcc0c Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 17 Jul 2015 02:24:54 +0200 Subject: [PATCH 0262/1256] Minor CSS fix --- .../Content/image-gallery/css/blueimp-gallery-custom.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web/Content/image-gallery/css/blueimp-gallery-custom.css b/src/Presentation/SmartStore.Web/Content/image-gallery/css/blueimp-gallery-custom.css index 94214b65b8..bc6725bd86 100644 --- a/src/Presentation/SmartStore.Web/Content/image-gallery/css/blueimp-gallery-custom.css +++ b/src/Presentation/SmartStore.Web/Content/image-gallery/css/blueimp-gallery-custom.css @@ -29,7 +29,6 @@ border: 1px solid rgba(0,0,0, 0.25); border-radius: 4px; border-top-right-radius: 0; - xtransition-delay: 0.2s; -webkit-box-shadow: 0px 4px 20px rgba(0,0,0, 0.35); box-shadow: 0px 4px 20px rgba(0,0,0, 0.35); -webkit-transform: translate(0, -75px) scale(0.9, 0.9); From a163a5801df24ba56fbede5e52a1662eb1f08b3e Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 17 Jul 2015 17:50:11 +0200 Subject: [PATCH 0263/1256] DevTools: option to display widget zones --- .../Controllers/DevToolsController.cs | 15 ++ .../Settings/ProfilerSettings.cs | 3 + .../SmartStore.DevTools.csproj | 4 + .../Views/DevTools/Configure.cshtml | 9 + .../Views/DevTools/WidgetZone.cshtml | 3 + .../Widgets/ShowZonesWidget.cs | 220 ++++++++++++++++++ .../GoogleAnalyticPlugin.cs | 29 ++- 7 files changed, 268 insertions(+), 15 deletions(-) create mode 100644 src/Plugins/SmartStore.DevTools/Views/DevTools/WidgetZone.cshtml create mode 100644 src/Plugins/SmartStore.DevTools/Widgets/ShowZonesWidget.cs diff --git a/src/Plugins/SmartStore.DevTools/Controllers/DevToolsController.cs b/src/Plugins/SmartStore.DevTools/Controllers/DevToolsController.cs index 42d23e84a8..89a261690f 100644 --- a/src/Plugins/SmartStore.DevTools/Controllers/DevToolsController.cs +++ b/src/Plugins/SmartStore.DevTools/Controllers/DevToolsController.cs @@ -71,5 +71,20 @@ public ActionResult MiniProfiler() return View(); } + public ActionResult WidgetZone(string widgetZone) + { + var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); + var settings = _settingService.LoadSetting(storeScope); + + if (settings.DisplayWidgetZones) + { + ViewData["widgetZone"] = widgetZone; + + return View(); + } + + return new EmptyResult(); + } + } } \ No newline at end of file diff --git a/src/Plugins/SmartStore.DevTools/Settings/ProfilerSettings.cs b/src/Plugins/SmartStore.DevTools/Settings/ProfilerSettings.cs index be2df2e227..88da20c658 100644 --- a/src/Plugins/SmartStore.DevTools/Settings/ProfilerSettings.cs +++ b/src/Plugins/SmartStore.DevTools/Settings/ProfilerSettings.cs @@ -9,5 +9,8 @@ namespace SmartStore.DevTools public class ProfilerSettings : ISettings { public bool EnableMiniProfilerInPublicStore { get; set; } + + public bool DisplayWidgetZones { get; set; } + } } \ No newline at end of file diff --git a/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj b/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj index e1c88f8d2c..2db1f156da 100644 --- a/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj +++ b/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj @@ -155,6 +155,7 @@ + @@ -198,6 +199,9 @@ Designer PreserveNewest + + PreserveNewest + diff --git a/src/Plugins/SmartStore.DevTools/Views/DevTools/Configure.cshtml b/src/Plugins/SmartStore.DevTools/Views/DevTools/Configure.cshtml index ebeb4a5ae8..7f1bdc6101 100644 --- a/src/Plugins/SmartStore.DevTools/Views/DevTools/Configure.cshtml +++ b/src/Plugins/SmartStore.DevTools/Views/DevTools/Configure.cshtml @@ -14,6 +14,15 @@ @Html.SettingEditorFor(model => model.EnableMiniProfilerInPublicStore) @Html.ValidationMessageFor(model => model.EnableMiniProfilerInPublicStore) + +
    + + + +
    "); + sb.AppendLine(""); sb.AppendLine(String.Format("{0}
    ", _companyInfoSettings.CompanyName )); @@ -597,7 +597,7 @@ protected virtual string GetSupplierIdentification() sb.AppendLine("
    "); - sb.AppendLine(""); + sb.AppendLine(""); if (!String.IsNullOrEmpty(_storeContext.CurrentStore.Url)) { @@ -618,7 +618,7 @@ protected virtual string GetSupplierIdentification() sb.AppendLine(""); - sb.AppendLine(""); + sb.AppendLine(""); if (!String.IsNullOrEmpty(_bankConnectionSettings.Bankname)) { From f07f5ed7405c2f0eaf1ecfd8d83963a153f7d8dd Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 14 Jul 2015 22:23:12 +0200 Subject: [PATCH 0248/1256] Lots of new stuff and enhancements: * Transient media records (pictures & downloads). Prevents database to be flooded with orphaned records. * Added ToPostedFileResult() extension method for much easier handling of uploaded files (much less code now) * Added new scheduled task 'Clear Transient Uploads' * Added SmartStore.Services.Media.MediaHelper utility class (helps to update media records transient states) * E-mail attachments: MessageTemplates can now reference up to 3 attachments. * Began enhancing the uploader UI for 'Download' * (Perf) several enhancements on database level * Added ShrinkDatabase() extension method to IDbContext --- changelog.md | 4 +- src/Libraries/SmartStore.Core/BaseEntity.cs | 8 +- .../SmartStore.Core/Domain/Catalog/Product.cs | 2 +- .../SmartStore.Core/Domain/Media/Download.cs | 18 +- .../SmartStore.Core/Domain/Media/Picture.cs | 18 +- .../Extensions/ConversionExtensions.cs | 62 +----- .../Extensions/MiscExtensions.cs | 12 +- src/Libraries/SmartStore.Core/ITransient.cs | 9 + .../SmartStore.Core/SmartStore.Core.csproj | 2 +- .../Utilities/FileSystemHelper.cs | 2 +- .../Extensions/IDbContextExtensions.cs | 20 ++ .../Mapping/Customers/CustomerMap.cs | 7 +- ...507072138058_MessageTemplateAttachments.cs | 22 ++- ...507092146153_DownloadGuidIndex.Designer.cs | 29 +++ .../201507092146153_DownloadGuidIndex.cs | 18 ++ .../201507092146153_DownloadGuidIndex.resx | 126 ++++++++++++ ...201507102159496_TransientMedia.Designer.cs | 29 +++ .../201507102159496_TransientMedia.cs | 51 +++++ .../201507102159496_TransientMedia.resx | 126 ++++++++++++ ...507141647299_CustomerTablePerf.Designer.cs | 29 +++ .../201507141647299_CustomerTablePerf.cs | 35 ++++ .../201507141647299_CustomerTablePerf.resx | 126 ++++++++++++ .../Setup/SeedData/InvariantSeedData.cs | 8 + .../SmartStore.Data/SmartStore.Data.csproj | 21 ++ .../Catalog/CopyProductService.cs | 10 +- .../Configuration/SettingService.cs | 2 +- .../Customers/CustomerService.cs | 159 +-------------- .../ExportImport/ImportManager.cs | 4 +- .../NameValueCollectionExtensions.cs | 29 ++- .../Logging/DefaultLogger.cs | 15 +- .../Media/DownloadService.cs | 4 + .../SmartStore.Services/Media/Extensions.cs | 39 ---- .../Media/IDownloadService.cs | 2 + .../Media/IPictureService.cs | 21 +- .../Media/MediaExtensions.cs | 187 ++++++++++++++++++ .../Media/PictureService.cs | 150 ++------------ .../Media/TransientMediaClearTask.cs | 70 +++++++ .../Messages/QueuedMessagesClearTask.cs | 3 + .../Orders/OrderProcessingService.cs | 4 +- .../SmartStore.Services.csproj | 3 +- .../Controllers/Api/UploadsController.cs | 2 +- .../Controllers/SmartController.cs | 2 +- .../Extensions/HtmlExtensions.cs | 8 +- ...ContextExtensions.cs => HttpExtensions.cs} | 80 +++++--- .../Extensions/PostedFileResult.cs | 179 +++++++++++++++++ .../SmartStore.Web.Framework.csproj | 3 +- .../Controllers/CategoryController.cs | 20 +- .../Controllers/ContentSliderController.cs | 3 + .../Controllers/DownloadController.cs | 83 ++++---- .../Controllers/LanguageController.cs | 7 +- .../Controllers/ManufacturerController.cs | 13 +- .../Controllers/MediaController.cs | 29 +-- .../Controllers/MessageTemplateController.cs | 26 ++- .../Controllers/OrderController.cs | 12 +- .../Controllers/PackagingController.cs | 8 +- .../Controllers/PictureController.cs | 71 +------ .../Controllers/ProductController.cs | 14 +- .../Controllers/SettingController.cs | 3 +- .../Controllers/StoreController.cs | 5 + .../Controllers/ThemeController.cs | 6 +- .../Scripts/smartstore.download.js | 95 +++++++++ .../Administration/SmartStore.Admin.csproj | 4 + .../Views/Category/_CreateOrUpdate.cshtml | 2 +- .../Views/ContentSlider/Index.cshtml | 2 +- .../ContentSlider/_CreateOrUpdate.cshtml | 2 +- .../Views/Manufacturer/_CreateOrUpdate.cshtml | 2 +- .../MessageTemplate/_CreateOrUpdate.cshtml | 12 +- .../Product/_CreateOrUpdate.Pictures.cshtml | 2 +- .../Views/Setting/GeneralCommon.cshtml | 2 +- .../Shared/EditorTemplates/Download.cshtml | 6 +- .../Shared/EditorTemplates/Download2.cshtml | 134 +++++++++++++ .../Shared/EditorTemplates/Picture.cshtml | 20 +- .../Views/Store/_CreateOrUpdate.cshtml | 2 +- .../Controllers/CustomerController.cs | 6 +- .../Controllers/ShoppingCartController.cs | 85 +++----- .../Extensions/ProductDetailsExtensions.cs | 5 + .../Installation/DeDESeedData.cs | 20 +- .../Views/Product/_Attributes.cshtml | 16 +- .../Catalog/ProductPersistenceTests.cs | 2 +- 79 files changed, 1734 insertions(+), 745 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/ITransient.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.resx create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.resx create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.resx delete mode 100644 src/Libraries/SmartStore.Services/Media/Extensions.cs create mode 100644 src/Libraries/SmartStore.Services/Media/MediaExtensions.cs create mode 100644 src/Libraries/SmartStore.Services/Media/TransientMediaClearTask.cs rename src/Presentation/SmartStore.Web.Framework/Extensions/{HttpContextExtensions.cs => HttpExtensions.cs} (75%) create mode 100644 src/Presentation/SmartStore.Web.Framework/Extensions/PostedFileResult.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Scripts/smartstore.download.js create mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/Download2.cshtml diff --git a/changelog.md b/changelog.md index 96936ed74e..ac3fd65818 100644 --- a/changelog.md +++ b/changelog.md @@ -9,10 +9,12 @@ * #526 Min\max amount option for which the payment method should be offered during checkout * #718 ShopConnector: Import option for "Published" and "Disable buy\wishlist button" * #702 Facebook and Twitter external authentication suitable for multi-stores +* New scheduled task: clear e-mail queue +* New scheduled task: clear uploadeded transient media files ### Improvements * (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%. -* #721 Message Queue: implement "Delete all" +* #721 Message Queue: implemented "Delete all" ## SmartStore.NET 2.2.2 diff --git a/src/Libraries/SmartStore.Core/BaseEntity.cs b/src/Libraries/SmartStore.Core/BaseEntity.cs index 9ff517f329..f555ef1e8d 100644 --- a/src/Libraries/SmartStore.Core/BaseEntity.cs +++ b/src/Libraries/SmartStore.Core/BaseEntity.cs @@ -36,9 +36,9 @@ public Type GetUnproxiedType() /// Transient objects are not associated with an item already in storage. For instance, /// a Product entity is transient if its Id is 0. /// - public virtual bool IsTransient + public virtual bool IsTransientRecord() { - get { return Id == 0; } + return Id == 0; } public override bool Equals(object obj) @@ -66,7 +66,7 @@ protected virtual bool Equals(BaseEntity other) public override int GetHashCode() { - if (this.IsTransient) + if (this.IsTransientRecord()) { return base.GetHashCode(); } @@ -95,7 +95,7 @@ public override int GetHashCode() private bool HasSameNonDefaultIds(BaseEntity other) { - return !this.IsTransient && !other.IsTransient && this.Id == other.Id; + return !this.IsTransientRecord() && !other.IsTransientRecord() && this.Id == other.Id; } } } diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs index 61f332eb11..a238d094f7 100644 --- a/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs +++ b/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs @@ -246,7 +246,7 @@ public string Gtin public bool AutomaticallyAddRequiredProducts { get; set; } /// - /// Gets or sets a value indicating whether the product is download + /// Gets or sets a value indicating whether the product is a download /// [DataMember] public bool IsDownload { get; set; } diff --git a/src/Libraries/SmartStore.Core/Domain/Media/Download.cs b/src/Libraries/SmartStore.Core/Domain/Media/Download.cs index 933790f578..88fb804395 100644 --- a/src/Libraries/SmartStore.Core/Domain/Media/Download.cs +++ b/src/Libraries/SmartStore.Core/Domain/Media/Download.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations.Schema; using System.Runtime.Serialization; namespace SmartStore.Core.Domain.Media @@ -7,12 +8,13 @@ namespace SmartStore.Core.Domain.Media /// Represents a download /// [DataContract] - public partial class Download : BaseEntity + public partial class Download : BaseEntity, ITransient { /// /// Gets or sets a GUID /// [DataMember] + [Index] public Guid DownloadGuid { get; set; } /// @@ -55,5 +57,19 @@ public partial class Download : BaseEntity /// [DataMember] public bool IsNew { get; set; } + + /// + /// Gets or sets a value indicating whether the entity transient/preliminary + /// + [DataMember] + [Index("IX_UpdatedOn_IsTransient", 1)] + public bool IsTransient { get; set; } + + /// + /// Gets or sets the date and time of instance update + /// + [DataMember] + [Index("IX_UpdatedOn_IsTransient", 0)] + public DateTime UpdatedOnUtc { get; set; } } } diff --git a/src/Libraries/SmartStore.Core/Domain/Media/Picture.cs b/src/Libraries/SmartStore.Core/Domain/Media/Picture.cs index 45d8e80069..c47fc53836 100644 --- a/src/Libraries/SmartStore.Core/Domain/Media/Picture.cs +++ b/src/Libraries/SmartStore.Core/Domain/Media/Picture.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using SmartStore.Core.Domain.Catalog; using System.Runtime.Serialization; +using System; +using System.ComponentModel.DataAnnotations.Schema; namespace SmartStore.Core.Domain.Media { @@ -8,7 +10,7 @@ namespace SmartStore.Core.Domain.Media /// Represents a picture /// [DataContract] - public partial class Picture : BaseEntity + public partial class Picture : BaseEntity, ITransient { private ICollection _productPictures; /// @@ -34,6 +36,20 @@ public partial class Picture : BaseEntity [DataMember] public bool IsNew { get; set; } + /// + /// Gets or sets a value indicating whether the entity transient/preliminary + /// + [DataMember] + [Index("IX_UpdatedOn_IsTransient", 1)] + public bool IsTransient { get; set; } + + /// + /// Gets or sets the date and time of instance update + /// + [DataMember] + [Index("IX_UpdatedOn_IsTransient", 0)] + public DateTime UpdatedOnUtc { get; set; } + /// /// Gets or sets the product pictures /// diff --git a/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs index 35781072ef..d7d8629f56 100644 --- a/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/ConversionExtensions.cs @@ -3,9 +3,7 @@ using System.Linq; using System.Text; using System.IO; -using System.Drawing; using System.ComponentModel; -using System.Drawing.Imaging; using System.Globalization; using System.Collections; using System.Reflection; @@ -512,13 +510,20 @@ public static byte[] ToByteArray(this Stream stream) } } - public static string AsString(this Stream stream) + public static string AsString(this Stream stream) + { + return stream.AsString(Encoding.UTF8); + } + + public static string AsString(this Stream stream, Encoding encoding) { - // convert stream to string + Guard.ArgumentNotNull(() => encoding); + + // convert stream to string string result; stream.Position = 0; - using (StreamReader sr = new StreamReader(stream)) + using (StreamReader sr = new StreamReader(stream, encoding)) { result = sr.ReadToEnd(); } @@ -546,14 +551,6 @@ public static object ToObject(this byte[] bytes) } } - public static Image ToImage(this byte[] bytes) - { - using (var stream = new MemoryStream(bytes)) - { - return Image.FromStream(stream); - } - } - public static Stream ToStream(this byte[] bytes) { return new MemoryStream(bytes); @@ -600,45 +597,6 @@ public static string Hash(this byte[] value, bool toBase64 = false) #endregion - #region Image/Bitmap - - public static byte[] ToByteArray(this Image image) - { - Guard.ArgumentNotNull(() => image); - - byte[] bytes; - - ImageConverter converter = new ImageConverter(); - bytes = (byte[])converter.ConvertTo(image, typeof(byte[])); - return bytes; - } - - internal static byte[] ToByteArray(this Image image, ImageFormat format) - { - Guard.ArgumentNotNull(() => image); - Guard.ArgumentNotNull(() => format); - - using (var stream = new MemoryStream()) - { - image.Save(stream, format); - return stream.ToArray(); - } - } - - internal static Image ConvertTo(this Image image, ImageFormat format) - { - Guard.ArgumentNotNull(() => image); - Guard.ArgumentNotNull(() => format); - - using (var stream = new MemoryStream()) - { - image.Save(stream, format); - return Image.FromStream(stream); - } - } - - #endregion - #region Enumerable: Collections/List/Dictionary... public static T ToObject(this IDictionary values) where T : class diff --git a/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs index da7f1483e3..3e871038fe 100644 --- a/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs @@ -21,15 +21,17 @@ public static void Dump(this Exception exc) catch { } } - public static string ToAllMessages(this Exception exc) + public static string ToAllMessages(this Exception exception) { var sb = new StringBuilder(); - while (exc != null) + while (exception != null) { - if (!sb.ToString().EmptyNull().Contains(exc.Message)) - sb.Grow(exc.Message, " "); - exc = exc.InnerException; + if (!sb.ToString().EmptyNull().Contains(exception.Message)) + { + sb.Grow(exception.Message, " * "); + } + exception = exception.InnerException; } return sb.ToString(); } diff --git a/src/Libraries/SmartStore.Core/ITransient.cs b/src/Libraries/SmartStore.Core/ITransient.cs new file mode 100644 index 0000000000..761dcee833 --- /dev/null +++ b/src/Libraries/SmartStore.Core/ITransient.cs @@ -0,0 +1,9 @@ +using System; + +namespace SmartStore +{ + public interface ITransient + { + bool IsTransient { get; set; } + } +} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 4251026394..630ff48dba 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -101,7 +101,6 @@ - ..\..\packages\System.Linq.Dynamic.1.0.0\lib\net40\System.Linq.Dynamic.dll @@ -171,6 +170,7 @@ + diff --git a/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs b/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs index bac48f33cd..18f56f51fb 100644 --- a/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs +++ b/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs @@ -72,7 +72,7 @@ public static bool Delete(string path) { if (Directory.Exists(path)) { - throw new MemberAccessException("Deleting folders cause of security reasons not possible: {0}".FormatWith(path)); + throw new MemberAccessException("Deleting folders due to security reasons not possible: {0}".FormatWith(path)); } File.Delete(path); // no exception, if file doesn't exists diff --git a/src/Libraries/SmartStore.Data/Extensions/IDbContextExtensions.cs b/src/Libraries/SmartStore.Data/Extensions/IDbContextExtensions.cs index a24674703a..102709b1fb 100644 --- a/src/Libraries/SmartStore.Data/Extensions/IDbContextExtensions.cs +++ b/src/Libraries/SmartStore.Data/Extensions/IDbContextExtensions.cs @@ -80,5 +80,25 @@ public static T LoadOriginalCopy(this IDbContext context, T currentCopy) wher { return InnerGetCopy(context, currentCopy, e => e.OriginalValues); } + + /// + /// Executes the DBCC SHRINKDATABASE(0) command against the SQL Server (Express) database + /// + /// The context + /// true, when the operation completed successfully. + public static bool ShrinkDatabase(this IDbContext context) + { + if (DataSettings.Current.IsSqlServer) + { + try + { + context.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); + return true; + } + catch { } + } + + return false; + } } } \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Mapping/Customers/CustomerMap.cs b/src/Libraries/SmartStore.Data/Mapping/Customers/CustomerMap.cs index a130708ccb..6004f3a520 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Customers/CustomerMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Customers/CustomerMap.cs @@ -10,9 +10,12 @@ public CustomerMap() { this.ToTable("Customer"); this.HasKey(c => c.Id); - this.Property(u => u.Username).HasMaxLength(1000); - this.Property(u => u.Email).HasMaxLength(1000); + this.Property(u => u.Username).HasMaxLength(500); + this.Property(u => u.Email).HasMaxLength(500); this.Property(u => u.SystemName).HasMaxLength(500); + this.Property(u => u.Password).HasMaxLength(500); + this.Property(u => u.PasswordSalt).HasMaxLength(500); + this.Property(u => u.LastIpAddress).HasMaxLength(100); this.Ignore(u => u.PasswordFormat); diff --git a/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs b/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs index 0a48be7f37..448a071417 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs @@ -2,8 +2,9 @@ namespace SmartStore.Data.Migrations { using System; using System.Data.Entity.Migrations; - - public partial class MessageTemplateAttachments : DbMigration + using SmartStore.Data.Setup; + + public partial class MessageTemplateAttachments : DbMigration, ILocaleResourcesProvider, IDataSeeder { public override void Up() { @@ -18,5 +19,22 @@ public override void Down() DropColumn("dbo.MessageTemplate", "Attachment2FileId"); DropColumn("dbo.MessageTemplate", "Attachment1FileId"); } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Common.Replace", + "Replace", + "Ersetzen"); + } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.Designer.cs new file mode 100644 index 0000000000..0693d8660f --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class DownloadGuidIndex : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(DownloadGuidIndex)); + + string IMigrationMetadata.Id + { + get { return "201507092146153_DownloadGuidIndex"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.cs b/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.cs new file mode 100644 index 0000000000..ff65fd3814 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.cs @@ -0,0 +1,18 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class DownloadGuidIndex : DbMigration + { + public override void Up() + { + CreateIndex("dbo.Download", "DownloadGuid"); + } + + public override void Down() + { + DropIndex("dbo.Download", new[] { "DownloadGuid" }); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.resx b/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.resx new file mode 100644 index 0000000000..457d21844b --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.Designer.cs new file mode 100644 index 0000000000..d738e053cf --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class TransientMedia : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(TransientMedia)); + + string IMigrationMetadata.Id + { + get { return "201507102159496_TransientMedia"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.cs b/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.cs new file mode 100644 index 0000000000..509169153e --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.cs @@ -0,0 +1,51 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + using SmartStore.Core.Domain.Tasks; + using SmartStore.Data.Setup; + + public partial class TransientMedia : DbMigration, IDataSeeder + { + public override void Up() + { + AddColumn("dbo.Download", "IsTransient", c => c.Boolean(nullable: false)); + AddColumn("dbo.Download", "UpdatedOnUtc", c => c.DateTime(nullable: false)); + AddColumn("dbo.Picture", "IsTransient", c => c.Boolean(nullable: false)); + AddColumn("dbo.Picture", "UpdatedOnUtc", c => c.DateTime(nullable: false)); + CreateIndex("dbo.Download", new[] { "UpdatedOnUtc", "IsTransient" }, name: "IX_UpdatedOn_IsTransient"); + CreateIndex("dbo.Picture", new[] { "UpdatedOnUtc", "IsTransient" }, name: "IX_UpdatedOn_IsTransient"); + } + + public override void Down() + { + DropIndex("dbo.Picture", "IX_UpdatedOn_IsTransient"); + DropIndex("dbo.Download", "IX_UpdatedOn_IsTransient"); + DropColumn("dbo.Picture", "UpdatedOnUtc"); + DropColumn("dbo.Picture", "IsTransient"); + DropColumn("dbo.Download", "UpdatedOnUtc"); + DropColumn("dbo.Download", "IsTransient"); + } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.Set().AddOrUpdate(x => x.Type, + new ScheduleTask + { + Name = "Clear transient uploads", + Seconds = 43200, // 12 hours + Type = "SmartStore.Services.Media.TransientMediaClearTask, SmartStore.Services", + Enabled = true, + StopOnError = false, + } + ); + + context.SaveChanges(); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.resx b/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.resx new file mode 100644 index 0000000000..11d76add9f --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.Designer.cs new file mode 100644 index 0000000000..c12151b6d9 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.0-30225")] + public sealed partial class CustomerTablePerf : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(CustomerTablePerf)); + + string IMigrationMetadata.Id + { + get { return "201507141647299_CustomerTablePerf"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.cs b/src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.cs new file mode 100644 index 0000000000..982225727d --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.cs @@ -0,0 +1,35 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class CustomerTablePerf : DbMigration + { + public override void Up() + { + // without dropping the indexes we cannot adjust column lengths + DropIndex("dbo.Customer", "IX_Customer_Email"); + DropIndex("dbo.Customer", "IX_Customer_Username"); + + AlterColumn("dbo.Customer", "Username", c => c.String(maxLength: 500)); + AlterColumn("dbo.Customer", "Email", c => c.String(maxLength: 500)); + AlterColumn("dbo.Customer", "Password", c => c.String(maxLength: 500)); + AlterColumn("dbo.Customer", "PasswordSalt", c => c.String(maxLength: 500)); + AlterColumn("dbo.Customer", "LastIpAddress", c => c.String(maxLength: 100)); + + // recreate previously dropped indexes + CreateIndex("dbo.Customer", "Email", name: "IX_Customer_Email"); + CreateIndex("dbo.Customer", "Username", name: "IX_Customer_Username"); + } + + public override void Down() + { + //// INFO: (mc) Unnecessary + //AlterColumn("dbo.Customer", "LastIpAddress", c => c.String()); + //AlterColumn("dbo.Customer", "PasswordSalt", c => c.String()); + //AlterColumn("dbo.Customer", "Password", c => c.String()); + //AlterColumn("dbo.Customer", "Email", c => c.String(maxLength: 1000)); + //AlterColumn("dbo.Customer", "Username", c => c.String(maxLength: 1000)); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.resx b/src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.resx new file mode 100644 index 0000000000..5e18dcfce7 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507141647299_CustomerTablePerf.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs index ab25464ca0..0e6186a316 100644 --- a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs +++ b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs @@ -4813,6 +4813,14 @@ public IList ScheduleTasks() StopOnError = false, }, new ScheduleTask + { + Name = "Clear transient uploads", + Seconds = 43200, // 12 hours + Type = "SmartStore.Services.Media.TransientMediaClearTask, SmartStore.Services", + Enabled = true, + StopOnError = false, + }, + new ScheduleTask { Name = "Clear email queue", Seconds = 86400, // 1 day diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 0cdc69b343..075c5ac68c 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -290,6 +290,18 @@ 201507072138058_MessageTemplateAttachments.cs + + + 201507092146153_DownloadGuidIndex.cs + + + + 201507102159496_TransientMedia.cs + + + + 201507141647299_CustomerTablePerf.cs + @@ -559,6 +571,15 @@ 201507072138058_MessageTemplateAttachments.cs + + 201507092146153_DownloadGuidIndex.cs + + + 201507102159496_TransientMedia.cs + + + 201507141647299_CustomerTablePerf.cs + diff --git a/src/Libraries/SmartStore.Services/Catalog/CopyProductService.cs b/src/Libraries/SmartStore.Services/Catalog/CopyProductService.cs index 9f84b9a8de..13f10f4e47 100644 --- a/src/Libraries/SmartStore.Services/Catalog/CopyProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/CopyProductService.cs @@ -91,7 +91,7 @@ public virtual Product CopyProduct(Product product, string newName, bool isPubli var download = _downloadService.GetDownloadById(product.DownloadId); if (download != null) { - var downloadCopy = new Download() + var downloadCopy = new Download { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = download.UseDownloadUrl, @@ -111,7 +111,7 @@ public virtual Product CopyProduct(Product product, string newName, bool isPubli var sampleDownload = _downloadService.GetDownloadById(product.SampleDownloadId.GetValueOrDefault()); if (sampleDownload != null) { - var sampleDownloadCopy = new Download() + var sampleDownloadCopy = new Download { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = sampleDownload.UseDownloadUrl, @@ -275,8 +275,10 @@ public virtual Product CopyProduct(Product product, string newName, bool isPubli _pictureService.LoadPictureBinary(picture), picture.MimeType, _pictureService.GetPictureSeName(newName), - true); - _productService.InsertProductPicture(new ProductPicture() + true, + false, + false); + _productService.InsertProductPicture(new ProductPicture { ProductId = productCopy.Id, PictureId = pictureCopy.Id, diff --git a/src/Libraries/SmartStore.Services/Configuration/SettingService.cs b/src/Libraries/SmartStore.Services/Configuration/SettingService.cs index c0c153badb..f48835151b 100644 --- a/src/Libraries/SmartStore.Services/Configuration/SettingService.cs +++ b/src/Libraries/SmartStore.Services/Configuration/SettingService.cs @@ -384,7 +384,7 @@ public virtual void SetSetting(string key, T value, int storeId = 0, bool cle else { //insert - var setting = new Setting() + var setting = new Setting { Name = key, Value = valueStr, diff --git a/src/Libraries/SmartStore.Services/Customers/CustomerService.cs b/src/Libraries/SmartStore.Services/Customers/CustomerService.cs index 7641b6bd45..25b20c2721 100644 --- a/src/Libraries/SmartStore.Services/Customers/CustomerService.cs +++ b/src/Libraries/SmartStore.Services/Customers/CustomerService.cs @@ -17,6 +17,7 @@ using SmartStore.Core.Domain.Polls; using SmartStore.Core.Domain.Shipping; using SmartStore.Core.Events; +using SmartStore.Core.Infrastructure; using SmartStore.Core.Localization; using SmartStore.Services.Common; using SmartStore.Services.Localization; @@ -33,6 +34,7 @@ public partial class CustomerService : ICustomerService private const string CUSTOMERROLES_ALL_KEY = "SmartStore.customerrole.all-{0}"; private const string CUSTOMERROLES_BY_SYSTEMNAME_KEY = "SmartStore.customerrole.systemname-{0}"; private const string CUSTOMERROLES_PATTERN_KEY = "SmartStore.customerrole."; + #endregion #region Fields @@ -49,15 +51,6 @@ public partial class CustomerService : ICustomerService #region Ctor - /// - /// Ctor - /// - /// Cache manager - /// Customer repository - /// Customer role repository - /// Generic attribute repository - /// Generic attribute service - /// Event published public CustomerService(ICacheManager cacheManager, IRepository customerRepository, IRepository customerRoleRepository, @@ -89,26 +82,6 @@ public CustomerService(ICacheManager cacheManager, #region Customers - /// - /// Gets all customers - /// - /// Customer registration from; null to load all customers - /// Customer registration to; null to load all customers - /// A list of customer role identifiers to filter by (at least one match); pass null or empty list in order to load all customers; - /// Email; null to load all customers - /// Username; null to load all customers - /// First name; null to load all customers - /// Last name; null to load all customers - /// Day of birth; 0 to load all customers - /// Month of birth; 0 to load all customers - /// Company; null to load all customers - /// Phone; null to load all customers - /// Phone; null to load all customers - /// Value indicating whther to load customers only with shopping cart - /// Value indicating what shopping cart type to filter; userd when 'loadOnlyWithShoppingCart' param is 'true' - /// Page index - /// Page size - /// Customer collection public virtual IPagedList GetAllCustomers(DateTime? registrationFrom, DateTime? registrationTo, int[] customerRoleIds, string email, string username, string firstName, string lastName, int dayOfBirth, int monthOfBirth, @@ -241,13 +214,6 @@ public virtual IPagedList GetAllCustomers(DateTime? registrationFrom, return customers; } - /// - /// Gets all customers by affiliate identifier - /// - /// Affiliate identifier - /// Page index - /// Page size - /// Customers public virtual IPagedList GetAllCustomers(int affiliateId, int pageIndex, int pageSize) { var query = _customerRepository.Table; @@ -259,11 +225,6 @@ public virtual IPagedList GetAllCustomers(int affiliateId, int pageInd return customers; } - /// - /// Gets all customers by customer format (including deleted ones) - /// - /// Password format - /// Customers public virtual IList GetAllCustomersByPasswordFormat(PasswordFormat passwordFormat) { int passwordFormatId = (int)passwordFormat; @@ -275,14 +236,6 @@ public virtual IList GetAllCustomersByPasswordFormat(PasswordFormat pa return customers; } - /// - /// Gets online customers - /// - /// Customer last activity date (from) - /// A list of customer role identifiers to filter by (at least one match); pass null or empty list in order to load all customers; - /// Page index - /// Page size - /// Customer collection public virtual IPagedList GetOnlineCustomers(DateTime lastActivityFromUtc, int[] customerRoleIds, int pageIndex, int pageSize) { @@ -297,10 +250,6 @@ public virtual IPagedList GetOnlineCustomers(DateTime lastActivityFrom return customers; } - /// - /// Delete a customer - /// - /// Customer public virtual void DeleteCustomer(Customer customer) { if (customer == null) @@ -313,11 +262,6 @@ public virtual void DeleteCustomer(Customer customer) UpdateCustomer(customer); } - /// - /// Gets a customer - /// - /// Customer identifier - /// A customer public virtual Customer GetCustomerById(int customerId) { if (customerId == 0) @@ -327,11 +271,6 @@ public virtual Customer GetCustomerById(int customerId) return customer; } - /// - /// Get customers by identifiers - /// - /// Customer identifiers - /// Customers public virtual IList GetCustomersByIds(int[] customerIds) { if (customerIds == null || customerIds.Length == 0) @@ -352,11 +291,6 @@ where customerIds.Contains(c.Id) return sortedCustomers; } - /// - /// Gets a customer by GUID - /// - /// Customer GUID - /// A customer public virtual Customer GetCustomerByGuid(Guid customerGuid) { if (customerGuid == Guid.Empty) @@ -370,11 +304,6 @@ orderby c.Id return customer; } - /// - /// Get customer by email - /// - /// Email - /// Customer public virtual Customer GetCustomerByEmail(string email) { if (string.IsNullOrWhiteSpace(email)) @@ -388,29 +317,19 @@ orderby c.Id return customer; } - /// - /// Get customer by system name - /// - /// System name - /// Customer public virtual Customer GetCustomerBySystemName(string systemName) { if (string.IsNullOrWhiteSpace(systemName)) return null; - var query = from c in _customerRepository.Table - orderby c.Id - where c.SystemName == systemName - select c; - var customer = query.FirstOrDefault(); - return customer; + var query = from c in _customerRepository.Table + orderby c.Id + where c.SystemName == systemName + select c; + var customer = query.FirstOrDefault(); + return customer; } - /// - /// Get customer by username - /// - /// Username - /// Customer public virtual Customer GetCustomerByUsername(string username) { if (string.IsNullOrWhiteSpace(username)) @@ -425,10 +344,6 @@ orderby c.Id return customer; } - /// - /// Insert a guest customer - /// - /// Customer public virtual Customer InsertGuestCustomer() { var customer = new Customer @@ -450,10 +365,6 @@ public virtual Customer InsertGuestCustomer() return customer; } - /// - /// Insert a customer - /// - /// Customer public virtual void InsertCustomer(Customer customer) { if (customer == null) @@ -465,10 +376,6 @@ public virtual void InsertCustomer(Customer customer) _eventPublisher.EntityInserted(customer); } - /// - /// Updates the customer - /// - /// Customer public virtual void UpdateCustomer(Customer customer) { if (customer == null) @@ -480,16 +387,6 @@ public virtual void UpdateCustomer(Customer customer) _eventPublisher.EntityUpdated(customer); } - /// - /// Reset data required for checkout - /// - /// Customer - /// Store identifier - /// A value indicating whether to clear coupon code - /// A value indicating whether to clear selected checkout attributes - /// A value indicating whether to clear "Use reward points" flag - /// A value indicating whether to clear selected shipping method - /// A value indicating whether to clear selected payment method public virtual void ResetCheckoutData(Customer customer, int storeId, bool clearCouponCodes = false, bool clearCheckoutAttributes = false, bool clearRewardPoints = true, bool clearShippingMethod = true, @@ -533,13 +430,6 @@ public virtual void ResetCheckoutData(Customer customer, int storeId, UpdateCustomer(customer); } - /// - /// Delete guest customer records - /// - /// Customer registration from; null to load all customers - /// Customer registration to; null to load all customers - /// A value indicating whether to delete customers only without shopping cart - /// Number of deleted customers public virtual int DeleteGuestCustomers(DateTime? registrationFrom, DateTime? registrationTo, bool onlyWithoutShoppingCart, int maxItemsToDelete = 5000) { var ctx = _customerRepository.Context; @@ -674,10 +564,6 @@ from inner in c_inner.DefaultIfEmpty() #region Customer roles - /// - /// Delete a customer role - /// - /// Customer role public virtual void DeleteCustomerRole(CustomerRole customerRole) { if (customerRole == null) @@ -694,11 +580,6 @@ public virtual void DeleteCustomerRole(CustomerRole customerRole) _eventPublisher.EntityDeleted(customerRole); } - /// - /// Gets a customer role - /// - /// Customer role identifier - /// Customer role public virtual CustomerRole GetCustomerRoleById(int customerRoleId) { if (customerRoleId == 0) @@ -707,11 +588,6 @@ public virtual CustomerRole GetCustomerRoleById(int customerRoleId) return _customerRoleRepository.GetById(customerRoleId); } - /// - /// Gets a customer role - /// - /// Customer role system name - /// Customer role public virtual CustomerRole GetCustomerRoleBySystemName(string systemName) { if (String.IsNullOrWhiteSpace(systemName)) @@ -729,11 +605,6 @@ orderby cr.Id }); } - /// - /// Gets all customer roles - /// - /// A value indicating whether to show hidden records - /// Customer role collection public virtual IList GetAllCustomerRoles(bool showHidden = false) { string key = string.Format(CUSTOMERROLES_ALL_KEY, showHidden); @@ -748,10 +619,6 @@ orderby cr.Name }); } - /// - /// Inserts a customer role - /// - /// Customer role public virtual void InsertCustomerRole(CustomerRole customerRole) { if (customerRole == null) @@ -765,10 +632,6 @@ public virtual void InsertCustomerRole(CustomerRole customerRole) _eventPublisher.EntityInserted(customerRole); } - /// - /// Updates the customer role - /// - /// Customer role public virtual void UpdateCustomerRole(CustomerRole customerRole) { if (customerRole == null) @@ -786,12 +649,6 @@ public virtual void UpdateCustomerRole(CustomerRole customerRole) #region Reward points - /// - /// Add or remove reward points for a product review - /// - /// The customer - /// The product - /// Whether to add or remove points public virtual void RewardPointsForProductReview(Customer customer, Product product, bool add) { if (_rewardPointsSettings.Enabled && _rewardPointsSettings.PointsForProductReview > 0) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs index 2dd762b398..0fbc43bd1c 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs @@ -718,10 +718,10 @@ private void ProcessProductPictures(ICollection> batch, Impor if (pictureBinary != null && pictureBinary.Length > 0) { // no equal picture found in sequence - var newPicture = _pictureService.InsertPicture(pictureBinary, "image/jpeg", _pictureService.GetPictureSeName(row.EntityDisplayName), true, true); + var newPicture = _pictureService.InsertPicture(pictureBinary, "image/jpeg", _pictureService.GetPictureSeName(row.EntityDisplayName), true, false, false); if (newPicture != null) { - var mapping = new ProductPicture() + var mapping = new ProductPicture { ProductId = row.Entity.Id, PictureId = newPicture.Id, diff --git a/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs b/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs index 99ee1e5744..96f04e9f7f 100644 --- a/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs +++ b/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs @@ -57,9 +57,16 @@ public static void ConvertAttributeQueryData(this NameValueCollection collection /// Takes selected elements from collection and creates a attribute XML string from it. /// how the name of the controls are formatted. frontend includes productId, backend does not. - public static string CreateSelectedAttributesXml(this NameValueCollection collection, int productId, IList variantAttributes, - IProductAttributeParser productAttributeParser, ILocalizationService localizationService, IDownloadService downloadService, CatalogSettings catalogSettings, - HttpRequestBase request, List warnings, bool formatWithProductId = true, int bundleItemId = 0) + public static string CreateSelectedAttributesXml(this NameValueCollection collection, + int productId, + IList variantAttributes, + IProductAttributeParser productAttributeParser, + ILocalizationService localizationService, + IDownloadService downloadService, + CatalogSettings catalogSettings, + HttpRequestBase request, List warnings, + bool formatWithProductId = true, + int bundleItemId = 0) { if (collection == null) return ""; @@ -142,16 +149,18 @@ public static string CreateSelectedAttributesXml(this NameValueCollection collec var download = downloadService.GetDownloadByGuid(downloadGuid); if (download != null) { + download.IsTransient = false; + downloadService.UpdateDownload(download); selectedAttributes = productAttributeParser.AddProductAttribute(selectedAttributes, attribute, download.DownloadGuid.ToString()); } } else { - var httpPostedFile = request.Files[controlId]; - if (httpPostedFile != null && httpPostedFile.FileName.HasValue()) + var postedFile = request.Files[controlId]; + if (postedFile != null && postedFile.FileName.HasValue()) { int fileMaxSize = catalogSettings.FileUploadMaximumSizeBytes; - if (httpPostedFile.ContentLength > fileMaxSize) + if (postedFile.ContentLength > fileMaxSize) { warnings.Add(string.Format(localizationService.GetResource("ShoppingCart.MaximumUploadedFileSize"), (int)(fileMaxSize / 1024))); } @@ -163,10 +172,10 @@ public static string CreateSelectedAttributesXml(this NameValueCollection collec DownloadGuid = Guid.NewGuid(), UseDownloadUrl = false, DownloadUrl = "", - DownloadBinary = httpPostedFile.GetDownloadBits(), - ContentType = httpPostedFile.ContentType, - Filename = System.IO.Path.GetFileNameWithoutExtension(httpPostedFile.FileName), - Extension = System.IO.Path.GetExtension(httpPostedFile.FileName), + DownloadBinary = postedFile.InputStream.ToByteArray(), + ContentType = postedFile.ContentType, + Filename = System.IO.Path.GetFileNameWithoutExtension(postedFile.FileName), + Extension = System.IO.Path.GetExtension(postedFile.FileName), IsNew = true }; downloadService.InsertDownload(download); diff --git a/src/Libraries/SmartStore.Services/Logging/DefaultLogger.cs b/src/Libraries/SmartStore.Services/Logging/DefaultLogger.cs index d952288f74..8ca87875a8 100644 --- a/src/Libraries/SmartStore.Services/Logging/DefaultLogger.cs +++ b/src/Libraries/SmartStore.Services/Logging/DefaultLogger.cs @@ -7,6 +7,7 @@ using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Logging; using SmartStore.Core.Logging; +using SmartStore.Data; namespace SmartStore.Services.Logging { @@ -93,14 +94,7 @@ public virtual void ClearLog() } } - if (DataSettings.Current.IsSqlServer) - { - try - { - _dbContext.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); - } - catch { } - } + _dbContext.ShrinkDatabase(); } public virtual void ClearLog(DateTime toUtc, LogLevel logLevel) @@ -115,10 +109,7 @@ public virtual void ClearLog(DateTime toUtc, LogLevel logLevel) break; } - if (DataSettings.Current.IsSqlServer) - { - _dbContext.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); - } + _dbContext.ShrinkDatabase(); } catch { } } diff --git a/src/Libraries/SmartStore.Services/Media/DownloadService.cs b/src/Libraries/SmartStore.Services/Media/DownloadService.cs index 25d9bc9b2c..b7f03930e8 100644 --- a/src/Libraries/SmartStore.Services/Media/DownloadService.cs +++ b/src/Libraries/SmartStore.Services/Media/DownloadService.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; +using SmartStore.Core; using SmartStore.Core.Data; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Media; @@ -89,6 +91,7 @@ public virtual void InsertDownload(Download download) if (download == null) throw new ArgumentNullException("download"); + download.UpdatedOnUtc = DateTime.UtcNow; _downloadRepository.Insert(download); _eventPubisher.EntityInserted(download); @@ -99,6 +102,7 @@ public virtual void UpdateDownload(Download download) if (download == null) throw new ArgumentNullException("download"); + download.UpdatedOnUtc = DateTime.UtcNow; _downloadRepository.Update(download); _eventPubisher.EntityUpdated(download); diff --git a/src/Libraries/SmartStore.Services/Media/Extensions.cs b/src/Libraries/SmartStore.Services/Media/Extensions.cs deleted file mode 100644 index fcc6269049..0000000000 --- a/src/Libraries/SmartStore.Services/Media/Extensions.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.IO; -using System.Web; - -namespace SmartStore.Services.Media -{ - /// - /// Extensions - /// - public static class Extensions - { - /// - /// Gets the download binary array - /// - /// Posted file - /// Download binary array - public static byte[] GetDownloadBits(this HttpPostedFileBase postedFile) - { - Stream fs = postedFile.InputStream; - int size = postedFile.ContentLength; - byte[] binary = new byte[size]; - fs.Read(binary, 0, size); - return binary; - } - - /// - /// Gets the picture binary array - /// - /// Posted file - /// Picture binary array - public static byte[] GetPictureBits(this HttpPostedFileBase postedFile) - { - Stream fs = postedFile.InputStream; - int size = postedFile.ContentLength; - byte[] img = new byte[size]; - fs.Read(img, 0, size); - return img; - } - } -} diff --git a/src/Libraries/SmartStore.Services/Media/IDownloadService.cs b/src/Libraries/SmartStore.Services/Media/IDownloadService.cs index 70282f56a4..80faf7f50a 100644 --- a/src/Libraries/SmartStore.Services/Media/IDownloadService.cs +++ b/src/Libraries/SmartStore.Services/Media/IDownloadService.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq.Expressions; +using SmartStore.Core; using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Orders; diff --git a/src/Libraries/SmartStore.Services/Media/IPictureService.cs b/src/Libraries/SmartStore.Services/Media/IPictureService.cs index f86c307925..216e7ee061 100644 --- a/src/Libraries/SmartStore.Services/Media/IPictureService.cs +++ b/src/Libraries/SmartStore.Services/Media/IPictureService.cs @@ -137,16 +137,17 @@ string GetPictureUrl(Picture picture, /// Pictures IList GetPicturesByProductId(int productId, int recordsToReturn = 0); - /// - /// Inserts a picture - /// - /// The picture binary - /// The picture MIME type - /// The SEO filename - /// A value indicating whether the picture is new - /// A value indicating whether to validated provided picture binary - /// Picture - Picture InsertPicture(byte[] pictureBinary, string mimeType, string seoFilename, bool isNew, bool validateBinary = true); + /// + /// Inserts a picture + /// + /// The picture binary + /// The picture MIME type + /// The SEO filename + /// A value indicating whether the picture is new + /// A value indicating whether the picture is initially in transient state + /// A value indicating whether to validated provided picture binary + /// Picture + Picture InsertPicture(byte[] pictureBinary, string mimeType, string seoFilename, bool isNew, bool isTransient = true, bool validateBinary = true); /// /// Updates the picture diff --git a/src/Libraries/SmartStore.Services/Media/MediaExtensions.cs b/src/Libraries/SmartStore.Services/Media/MediaExtensions.cs new file mode 100644 index 0000000000..e3beb9ece1 --- /dev/null +++ b/src/Libraries/SmartStore.Services/Media/MediaExtensions.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +using SmartStore.Core; +using SmartStore.Core.Data; +using SmartStore.Core.Domain.Media; +using SmartStore.Core.Infrastructure; + +namespace SmartStore.Services.Media +{ + + public static class MediaHelper + { + + public static void UpdateDownloadTransientStateFor(TEntity entity, Expression> downloadIdProp, bool save = false) where TEntity : BaseEntity + { + Guard.ArgumentNotNull(() => entity); + Guard.ArgumentNotNull(() => downloadIdProp); + + var propName = downloadIdProp.ExtractMemberInfo().Name; + int currentDownloadId = downloadIdProp.Compile().Invoke(entity); + var rs = EngineContext.Current.Resolve>(); + + UpdateTransientStateForEntityInternal(entity, propName, currentDownloadId, rs, null, save); + } + + public static void UpdateDownloadTransientStateFor(TEntity entity, Expression> downloadIdProp, bool save = false) where TEntity : BaseEntity + { + Guard.ArgumentNotNull(() => entity); + Guard.ArgumentNotNull(() => downloadIdProp); + + var propName = downloadIdProp.ExtractMemberInfo().Name; + int currentDownloadId = downloadIdProp.Compile().Invoke(entity).GetValueOrDefault(); + var rs = EngineContext.Current.Resolve>(); + + UpdateTransientStateForEntityInternal(entity, propName, currentDownloadId, rs, null, save); + } + + public static void UpdatePictureTransientStateFor(TEntity entity, Expression> pictureIdProp, bool save = false) where TEntity : BaseEntity + { + Guard.ArgumentNotNull(() => entity); + Guard.ArgumentNotNull(() => pictureIdProp); + + var propName = pictureIdProp.ExtractMemberInfo().Name; + int currentPictureId = pictureIdProp.Compile().Invoke(entity); + var rs = EngineContext.Current.Resolve>(); + + UpdateTransientStateForEntityInternal(entity, propName, currentPictureId, rs, GetPictureDeleteAction(), save); + } + + public static void UpdatePictureTransientStateFor(TEntity entity, Expression> pictureIdProp, bool save = false) where TEntity : BaseEntity + { + Guard.ArgumentNotNull(() => entity); + Guard.ArgumentNotNull(() => pictureIdProp); + + var propName = pictureIdProp.ExtractMemberInfo().Name; + int currentPictureId = pictureIdProp.Compile().Invoke(entity).GetValueOrDefault(); + var rs = EngineContext.Current.Resolve>(); + + UpdateTransientStateForEntityInternal(entity, propName, currentPictureId, rs, GetPictureDeleteAction(), save); + } + + public static void UpdateDownloadTransientState(int? prevDownloadId, int? currentDownloadId, bool save = false) + { + var rs = EngineContext.Current.Resolve>(); + UpdateTransientStateCore(prevDownloadId.GetValueOrDefault(), currentDownloadId.GetValueOrDefault(), rs, null, save); + } + + public static void UpdateDownloadTransientState(int prevDownloadId, int currentDownloadId, bool save = false) + { + var rs = EngineContext.Current.Resolve>(); + UpdateTransientStateCore(prevDownloadId, currentDownloadId, rs, null, save); + } + + public static void UpdatePictureTransientState(int? prevPictureId, int? currentPictureId, bool save = false) + { + var rs = EngineContext.Current.Resolve>(); + UpdateTransientStateCore(prevPictureId.GetValueOrDefault(), currentPictureId.GetValueOrDefault(), rs, GetPictureDeleteAction(), save); + } + + public static void UpdatePictureTransientState(int prevPictureId, int currentPictureId, bool save = false) + { + var rs = EngineContext.Current.Resolve>(); + UpdateTransientStateCore(prevPictureId, currentPictureId, rs, GetPictureDeleteAction(), save); + } + + private static Action GetPictureDeleteAction() + { + Action deleteAction = pic => + { + var svc = EngineContext.Current.Resolve(); + svc.DeletePicture((Picture)pic); + }; + + return deleteAction; + } + + internal static void UpdateTransientStateForEntityInternal( + TEntity entity, + string propName, + int currentMediaId, + IRepository rs, + Action deleteAction, + bool save) where TEntity : BaseEntity where TMedia : BaseEntity + { + bool editMode = !entity.IsTransientRecord(); + var modifiedProperties = editMode ? rs.Context.GetModifiedProperties(entity) : new Dictionary(); + + object obj = null; + int prevMediaId = 0; + if (modifiedProperties.TryGetValue(propName, out obj)) + { + prevMediaId = ((int?)obj).GetValueOrDefault(); + } + + UpdateTransientStateCore(prevMediaId, currentMediaId, rs, deleteAction, save); + } + + internal static void UpdateTransientStateCore( + int prevMediaId, + int currentMediaId, + IRepository rs, + Action deleteAction, + bool save) + where TMedia : BaseEntity + { + var autoCommit = rs.AutoCommitEnabled; + rs.AutoCommitEnabled = false; + + try + { + TMedia media = null; + bool shouldSave = false; + + bool isModified = prevMediaId != currentMediaId; + + if (currentMediaId > 0 && isModified) + { + // new entity with a media or media replaced + media = rs.GetById(currentMediaId); + if (media != null) + { + var transient = media as ITransient; + if (transient != null) + { + transient.IsTransient = false; + shouldSave = true; + } + } + } + + if (prevMediaId > 0) + { + // ID changed, so delete old record + media = rs.GetById(prevMediaId); + if (media != null) + { + if (deleteAction == null) + { + rs.Delete(media); + } + else + { + deleteAction(media); + } + shouldSave = true; + } + } + + if (save && shouldSave) + { + rs.Context.SaveChanges(); + } + } + finally + { + rs.AutoCommitEnabled = autoCommit; + } + } + + + } + +} diff --git a/src/Libraries/SmartStore.Services/Media/PictureService.cs b/src/Libraries/SmartStore.Services/Media/PictureService.cs index bc11e71a36..dc767d2808 100644 --- a/src/Libraries/SmartStore.Services/Media/PictureService.cs +++ b/src/Libraries/SmartStore.Services/Media/PictureService.cs @@ -15,6 +15,7 @@ using SmartStore.Core.Logging; using SmartStore.Services.Configuration; using SmartStore.Utilities; +using SmartStore.Data; namespace SmartStore.Services.Media { @@ -51,16 +52,7 @@ public partial class PictureService : IPictureService #region Ctor - /// - /// Ctor - /// - /// Picture repository - /// Product picture repository - /// Setting service - /// Web helper - /// Logger - /// Event publisher - /// Media settings + public PictureService( IRepository pictureRepository, IRepository productPictureRepository, @@ -147,12 +139,6 @@ private string GetDefaultImageFileName(PictureType defaultPictureType = PictureT return defaultImageFileName; } - /// - /// Validates input picture dimensions and prevents that the image size exceeds global max size - /// - /// Picture binary - /// MIME type - /// Picture binary or throws an exception public virtual byte[] ValidatePicture(byte[] pictureBinary) { Size originalSize = this.GetPictureSize(pictureBinary); @@ -169,25 +155,11 @@ public virtual byte[] ValidatePicture(byte[] pictureBinary) } } - /// - /// Finds an equal picture by comparing the binary buffer - /// - /// The picture to find a duplicate for - /// The sequence of product pictures to seek within for duplicates - /// Id of equal picture if any - /// The picture binary for path when no picture equals in the sequence, null otherwise. public byte[] FindEqualPicture(string path, IEnumerable productPictures, out int equalPictureId) { return FindEqualPicture(File.ReadAllBytes(path), productPictures, out equalPictureId); } - /// - /// Finds an equal picture by comparing the binary buffer - /// - /// Binary picture data - /// The sequence of product pictures to seek within for duplicates - /// Id of equal picture if any - /// The picture binary for path when no picture equals in the sequence, null otherwise. public byte[] FindEqualPicture(byte[] pictureBinary, IEnumerable productPictures, out int equalPictureId) { equalPictureId = 0; @@ -220,23 +192,11 @@ public byte[] FindEqualPicture(byte[] pictureBinary, IEnumerable produc #region Methods - /// - /// Get picture SEO friendly name - /// - /// Name - /// Result public virtual string GetPictureSeName(string name) { return SeoHelper.GetSeName(name, true, false); } - /// - /// Get a picture local path - /// - /// Picture instance - /// The target picture size (longest side) - /// A value indicating whether the default picture is shown - /// public virtual string GetThumbLocalPath(Picture picture, int targetSize = 0, bool showDefaultPicture = true) { // 'GetPictureUrl' takes care of creating the thumb when not created already @@ -271,13 +231,6 @@ public virtual string GetThumbLocalPath(Picture picture, int targetSize = 0, boo } - /// - /// Gets the default picture URL - /// - /// The target picture size (longest side) - /// Default picture type - /// Store location URL; null to use determine the current store location automatically - /// Picture URL public virtual string GetDefaultPictureUrl(int targetSize = 0, PictureType defaultPictureType = PictureType.Entity, string storeLocation = null) { string defaultImageFileName = GetDefaultImageFileName(defaultPictureType); @@ -387,22 +340,11 @@ private byte[] LoadPictureFromFile(int pictureId, string mimeType, out string fi return File.ReadAllBytes(filePath); } - /// - /// Gets the loaded picture binary depending on picture storage settings - /// - /// Picture - /// Picture binary public virtual byte[] LoadPictureBinary(Picture picture) { return LoadPictureBinary(picture, this.StoreInDb); } - /// - /// Gets the loaded picture binary depending on picture storage settings - /// - /// Picture - /// Load from database; otherwise, from file system - /// Picture binary public virtual byte[] LoadPictureBinary(Picture picture, bool fromDb) { if (picture == null) @@ -462,15 +404,6 @@ internal Size GetPictureSize(byte[] pictureBinary) return size; } - /// - /// Get a picture URL - /// - /// Picture identifier - /// The target picture size (longest side) - /// A value indicating whether the default picture is shown - /// Store location URL; null to use determine the current store location automatically - /// Default picture type - /// Picture URL public virtual string GetPictureUrl( int pictureId, int targetSize = 0, @@ -482,15 +415,6 @@ public virtual string GetPictureUrl( return GetPictureUrl(picture, targetSize, showDefaultPicture, storeLocation, defaultPictureType); } - /// - /// Get a picture URL - /// - /// Picture instance - /// The target picture size (longest side) - /// A value indicating whether the default picture is shown - /// Store location URL; null to use determine the current store location automatically - /// Default picture type - /// Picture URL public virtual string GetPictureUrl( Picture picture, int targetSize = 0, @@ -580,37 +504,27 @@ public virtual Picture GetPictureById(int pictureId) return picture; } - /// - /// Deletes a picture - /// - /// Picture public virtual void DeletePicture(Picture picture) { if (picture == null) throw new ArgumentNullException("picture"); - //delete thumbs + // delete thumbs _imageCache.DeleteCachedImages(picture); - //delete from file system + // delete from file system if (!this.StoreInDb) { DeletePictureOnFileSystem(picture); } - //delete from database + // delete from database _pictureRepository.Delete(picture); - //event notification + // event notification _eventPublisher.EntityDeleted(picture); } - /// - /// Gets a collection of pictures - /// - /// Current page - /// Items on each page - /// Paged list of pictures public virtual IPagedList GetPictures(int pageIndex, int pageSize) { var query = from p in _pictureRepository.Table @@ -620,12 +534,6 @@ orderby p.Id descending return pics; } - /// - /// Gets pictures by product identifier - /// - /// Product identifier - /// Number of records to return. 0 if you want to get all items - /// Pictures public virtual IList GetPicturesByProductId(int productId, int recordsToReturn = 0) { if (productId == 0) @@ -644,16 +552,7 @@ orderby pp.DisplayOrder return pics; } - /// - /// Inserts a picture - /// - /// The picture binary - /// The picture MIME type - /// The SEO filename - /// A value indicating whether the picture is new - /// A value indicating whether to validated provided picture binary - /// Picture - public virtual Picture InsertPicture(byte[] pictureBinary, string mimeType, string seoFilename, bool isNew, bool validateBinary = true) + public virtual Picture InsertPicture(byte[] pictureBinary, string mimeType, string seoFilename, bool isNew, bool isTransient = true, bool validateBinary = true) { mimeType = mimeType.EmptyNull(); mimeType = mimeType.Truncate(20); @@ -670,6 +569,8 @@ public virtual Picture InsertPicture(byte[] pictureBinary, string mimeType, stri picture.MimeType = mimeType; picture.SeoFilename = seoFilename; picture.IsNew = isNew; + picture.IsTransient = isTransient; + picture.UpdatedOnUtc = DateTime.UtcNow; _pictureRepository.Insert(picture); @@ -684,16 +585,6 @@ public virtual Picture InsertPicture(byte[] pictureBinary, string mimeType, stri return picture; } - /// - /// Updates the picture - /// - /// The picture identifier - /// The picture binary - /// The picture MIME type - /// The SEO filename - /// A value indicating whether the picture is new - /// A value indicating whether to validated provided picture binary - /// Picture public virtual Picture UpdatePicture(int pictureId, byte[] pictureBinary, string mimeType, string seoFilename, bool isNew, bool validateBinary = true) { mimeType = mimeType.EmptyNull().Truncate(20); @@ -718,6 +609,7 @@ public virtual Picture UpdatePicture(int pictureId, byte[] pictureBinary, string picture.MimeType = mimeType; picture.SeoFilename = seoFilename; picture.IsNew = isNew; + picture.UpdatedOnUtc = DateTime.UtcNow; _pictureRepository.Update(picture); @@ -732,22 +624,15 @@ public virtual Picture UpdatePicture(int pictureId, byte[] pictureBinary, string return picture; } - /// - /// Updates a SEO filename of a picture - /// - /// The picture identifier - /// The SEO filename - /// Picture public virtual Picture SetSeoFilename(int pictureId, string seoFilename) { var picture = GetPictureById(pictureId); if (picture == null) throw new ArgumentException("No picture found with the specified id"); - //update if it has been changed + // update if it has been changed if (seoFilename != picture.SeoFilename) { - //update picture picture = UpdatePicture(picture.Id, LoadPictureBinary(picture), picture.MimeType, seoFilename, true, false); } return picture; @@ -757,10 +642,6 @@ public virtual Picture SetSeoFilename(int pictureId, string seoFilename) #region Properties - - /// - /// Gets or sets a value indicating whether the images should be stored in data base. - /// public virtual bool StoreInDb { get @@ -854,6 +735,7 @@ protected int MovePictures(bool toDb) } // explicitly attach modified entity to context, because we disabled AutoCommit + picture.UpdatedOnUtc = DateTime.UtcNow; _pictureRepository.Update(picture); i++; @@ -898,13 +780,9 @@ protected int MovePictures(bool toDb) } // shrink database (only when DB > FS and success) - if (!toDb && !failed && DataSettings.Current.IsSqlServer) + if (!toDb && !failed) { - try - { - ctx.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); - } - catch { } + ctx.ShrinkDatabase(); } } diff --git a/src/Libraries/SmartStore.Services/Media/TransientMediaClearTask.cs b/src/Libraries/SmartStore.Services/Media/TransientMediaClearTask.cs new file mode 100644 index 0000000000..4392ca231a --- /dev/null +++ b/src/Libraries/SmartStore.Services/Media/TransientMediaClearTask.cs @@ -0,0 +1,70 @@ +using System; +using System.Linq; +using System.Linq.Expressions; +using SmartStore.Core.Data; +using SmartStore.Core.Domain.Media; +using SmartStore.Services.Tasks; + +namespace SmartStore.Services.Media +{ + /// + /// Represents a task for deleting transient media from the database + /// (pictures and downloads which have been uploaded but never assigned to an entity) + /// + public partial class TransientMediaClearTask : ITask + { + private readonly IPictureService _pictureService; + private readonly IRepository _pictureRepository; + private readonly IRepository _downloadRepository; + + public TransientMediaClearTask( + IPictureService pictureService, + IRepository pictureRepository, + IRepository downloadRepository) + { + this._pictureService = pictureService; + this._pictureRepository = pictureRepository; + this._downloadRepository = downloadRepository; + } + + public void Execute(TaskExecutionContext ctx) + { + // delete all media records which are in transient state since at least 3 hours + var olderThan = DateTime.UtcNow.AddHours(-3); + + // delete Downloads + _downloadRepository.DeleteAll(x => x.IsTransient && x.UpdatedOnUtc < olderThan); + + // delete Pictures + var autoCommit = _pictureRepository.AutoCommitEnabled; + _pictureRepository.AutoCommitEnabled = false; + + try + { + using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, hooksEnabled: false)) + { + var pictures = _pictureRepository.Where(x => x.IsTransient && x.UpdatedOnUtc < olderThan).ToList(); + foreach (var picture in pictures) + { + _pictureService.DeletePicture(picture); + } + + _pictureRepository.Context.SaveChanges(); + + if (DataSettings.Current.IsSqlServer) + { + try + { + _pictureRepository.Context.ExecuteSqlCommand("DBCC SHRINKDATABASE(0)", true); + } + catch { } + } + } + } + finally + { + _pictureRepository.AutoCommitEnabled = autoCommit; + } + } + } +} diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesClearTask.cs b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesClearTask.cs index a51b84a925..b31f3b4ce3 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesClearTask.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesClearTask.cs @@ -3,6 +3,7 @@ using System.Linq.Expressions; using SmartStore.Core.Data; using SmartStore.Core.Domain.Messages; +using SmartStore.Data; using SmartStore.Services.Tasks; namespace SmartStore.Services.Messages @@ -23,6 +24,8 @@ public void Execute(TaskExecutionContext ctx) { var olderThan = DateTime.UtcNow.AddDays(-14); _qeRepository.DeleteAll(x => x.SentOnUtc.HasValue && x.CreatedOnUtc < olderThan); + + _qeRepository.Context.ShrinkDatabase(); } } } diff --git a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs index d955f22aab..61470258eb 100644 --- a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs +++ b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs @@ -1096,7 +1096,7 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR var itemWeight = _shippingService.GetShoppingCartItemWeight(sc); //save order item - var orderItem = new OrderItem() + var orderItem = new OrderItem { OrderItemGuid = Guid.NewGuid(), Order = order, @@ -1149,7 +1149,7 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR for (int i = 0; i < sc.Item.Quantity; i++) { - var gc = new GiftCard() + var gc = new GiftCard { GiftCardType = sc.Item.Product.GiftCardType, PurchasedWithOrderItem = orderItem, diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index 8c64d2273a..c63c12ccc2 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -161,6 +161,8 @@ + + @@ -316,7 +318,6 @@ - diff --git a/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs b/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs index 232860f3c8..8cc5b1ecaf 100644 --- a/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs +++ b/src/Plugins/SmartStore.WebApi/Controllers/Api/UploadsController.cs @@ -120,7 +120,7 @@ public async Task> PostProductImages() { var seoName = _pictureService.Value.GetPictureSeName(Path.GetFileNameWithoutExtension(image.FileName)); - var newPicture = _pictureService.Value.InsertPicture(pictureBinary, image.MediaType, seoName, true, false); + var newPicture = _pictureService.Value.InsertPicture(pictureBinary, image.MediaType, seoName, true, false, false); if (newPicture != null) { diff --git a/src/Presentation/SmartStore.Web.Framework/Controllers/SmartController.cs b/src/Presentation/SmartStore.Web.Framework/Controllers/SmartController.cs index 5e69151979..2e5378e75c 100644 --- a/src/Presentation/SmartStore.Web.Framework/Controllers/SmartController.cs +++ b/src/Presentation/SmartStore.Web.Framework/Controllers/SmartController.cs @@ -77,7 +77,7 @@ protected virtual void NotifyError(Exception exception, bool durable = true, boo LogException(exception); } - _notifier.Value.Error(exception.Message, durable); + _notifier.Value.Error(exception.ToAllMessages(), durable); } protected virtual ActionResult RedirectToReferrer() diff --git a/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlExtensions.cs b/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlExtensions.cs index 0b7020875a..02f7f9cf9e 100644 --- a/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlExtensions.cs +++ b/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlExtensions.cs @@ -564,11 +564,13 @@ public static MvcHtmlString SettingOverrideCheckbox(this HtmlHel return MvcHtmlString.Empty; } - public static MvcHtmlString SettingEditorFor(this HtmlHelper helper, - Expression> expression, string parentSelector = null) + public static MvcHtmlString SettingEditorFor(this HtmlHelper helper, + Expression> expression, + string parentSelector = null, + object additionalViewData = null) { var checkbox = helper.SettingOverrideCheckbox(expression, parentSelector); - var editor = helper.EditorFor(expression); + var editor = helper.EditorFor(expression, additionalViewData); return MvcHtmlString.Create(checkbox.ToString() + editor.ToString()); } diff --git a/src/Presentation/SmartStore.Web.Framework/Extensions/HttpContextExtensions.cs b/src/Presentation/SmartStore.Web.Framework/Extensions/HttpExtensions.cs similarity index 75% rename from src/Presentation/SmartStore.Web.Framework/Extensions/HttpContextExtensions.cs rename to src/Presentation/SmartStore.Web.Framework/Extensions/HttpExtensions.cs index 9862599a4c..f01379faec 100644 --- a/src/Presentation/SmartStore.Web.Framework/Extensions/HttpContextExtensions.cs +++ b/src/Presentation/SmartStore.Web.Framework/Extensions/HttpExtensions.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.IO; using System.Web; using System.Web.Mvc; @@ -8,7 +10,7 @@ namespace SmartStore { - public static class HttpContextExtensions + public static class HttpExtensions { public static bool IsAdminArea(this HttpRequest request) @@ -70,31 +72,63 @@ public static bool IsPublicArea(this HttpRequestBase request) } } - public static Stream ToFileStream(this HttpRequestBase request, out string fileName, out string contentType, string paramName = "qqfile") { - fileName = contentType = ""; - Stream stream = null; + public static PostedFileResult ToPostedFileResult(this HttpRequestBase httpRequest) + { + if (httpRequest != null && httpRequest.Files.Count > 0) + { + return httpRequest.Files[0].ToPostedFileResult(); + } - if (request[paramName].HasValue()) - { - stream = request.InputStream; - fileName = request[paramName]; - } - else - { - if (request.Files.Count > 0) - { - stream = request.Files[0].InputStream; - contentType = request.Files[0].ContentType; - fileName = Path.GetFileName(request.Files[0].FileName); - } - } + return null; + } - if (contentType.IsEmpty()) - { - contentType = SmartStore.Core.IO.MimeTypes.MapNameToMimeType(fileName); - } + public static PostedFileResult ToPostedFileResult(this HttpPostedFile httpFile) + { + if (httpFile != null && httpFile.ContentLength > 0) + { + return new PostedFileResult(new HttpPostedFileWrapper(httpFile)); + } - return stream; + return null; + } + + public static PostedFileResult ToPostedFileResult(this HttpPostedFileBase httpFile) + { + if (httpFile != null && httpFile.ContentLength > 0) + { + return new PostedFileResult(httpFile); + } + + return null; + } + + public static IEnumerable ToPostedFileResults(this HttpFileCollection httpFileCollection) + { + if (httpFileCollection != null && httpFileCollection.Count > 0) + { + return new HttpFileCollectionWrapper(httpFileCollection).ToPostedFileResults(); + } + + return Enumerable.Empty(); + } + + public static IEnumerable ToPostedFileResults(this HttpFileCollectionBase httpFileCollection) + { + if (httpFileCollection == null) + yield break; + + var batchId = Guid.NewGuid(); + + for (var i = 0; i < httpFileCollection.Count; i++) + { + var httpFile = httpFileCollection[i]; + var result = httpFile.ToPostedFileResult(); + if (result != null) + { + result.BatchId = batchId; + yield return result; + } + } } public static RouteData GetRouteData(this HttpContextBase httpContext) diff --git a/src/Presentation/SmartStore.Web.Framework/Extensions/PostedFileResult.cs b/src/Presentation/SmartStore.Web.Framework/Extensions/PostedFileResult.cs new file mode 100644 index 0000000000..9ba2b0ed2d --- /dev/null +++ b/src/Presentation/SmartStore.Web.Framework/Extensions/PostedFileResult.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Web; +using SmartStore.Core.IO; + +namespace SmartStore +{ + public class PostedFileResult + { + private static readonly Regex s_ImageTypes = new Regex(@"(.*?)\.(gif|jpg|jpeg|jpe|jfif|pjpeg|pjp|png|tiff|tif|bmp|ico|svg)", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private readonly HttpPostedFileBase _httpFile; + + private string _contentType; + private string _fileName; + private string _fileTitle; + private string _fileExt; + private bool? _isImage; + + public PostedFileResult(HttpPostedFileBase httpFile) + { + Guard.ArgumentNotNull(() => httpFile); + + this._httpFile = httpFile; + + this.TimeStamp = DateTime.UtcNow; + this.BatchId = Guid.NewGuid(); + } + + public HttpPostedFileBase File + { + get { return _httpFile; } + } + + public DateTime TimeStamp + { + get; + private set; + } + + public Guid BatchId + { + get; + internal set; + } + + public string FileName + { + get + { + if (_fileName == null) + { + _fileName = Path.GetFileName(_httpFile.FileName); + } + return _fileName; + } + } + + public string FileTitle + { + get + { + if (_fileTitle == null) + { + _fileTitle = Path.GetFileNameWithoutExtension(this.FileName); + } + return _fileTitle; + } + } + + public string FileExtension + { + get + { + if (_fileExt == null) + { + _fileExt = Path.GetExtension(this.FileName).EmptyNull(); + } + return _fileExt; + } + } + + public string ContentType + { + get + { + if (_contentType == null) + { + var contentType = _httpFile.ContentType; + + if (contentType == null && this.FileExtension.HasValue()) + { + contentType = MimeTypes.MapNameToMimeType(this.FileExtension); + + // ContentType is not always available. + // That's why we manually update it here + if (contentType.IsEmpty()) + { + switch (this.FileExtension.ToLowerInvariant()) + { + case ".bmp": + contentType = "image/bmp"; + break; + case ".gif": + contentType = "image/gif"; + break; + case ".jpeg": + case ".jpg": + case ".jpe": + case ".jfif": + case ".pjpeg": + case ".pjp": + contentType = "image/jpeg"; + break; + case ".png": + contentType = "image/png"; + break; + case ".tiff": + case ".tif": + contentType = "image/tiff"; + break; + case ".svg": + contentType = "image/svg+xml"; + break; + case ".ico": + contentType = "image/x-icon"; + break; + default: + break; + } + } + } + + _contentType = contentType.EmptyNull(); + } + return _contentType; + } + } + + public bool IsImage + { + get + { + if (!_isImage.HasValue) + { + _isImage = s_ImageTypes.IsMatch(FileExtension); + } + return _isImage.Value; + } + } + + public int Size + { + get { return _httpFile.ContentLength; } + } + + public Stream Stream + { + get { return _httpFile.InputStream; } + } + + public byte[] Buffer + { + get + { + return _httpFile.InputStream.ToByteArray(); + } + } + + public bool FileNameMatches(string pattern) + { + return Regex.IsMatch(_httpFile.FileName, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); + } + } +} diff --git a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj index cd2f03fa0d..26765a39af 100644 --- a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj +++ b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj @@ -239,10 +239,11 @@ - + + diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs index ceda143ff6..94dddf36f5 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs @@ -519,6 +519,9 @@ public ActionResult Create(CategoryModel model, bool continueEditing, FormCollec var category = model.ToEntity(); category.CreatedOnUtc = DateTime.UtcNow; category.UpdatedOnUtc = DateTime.UtcNow; + + MediaHelper.UpdatePictureTransientStateFor(category, c => c.PictureId); + _categoryService.InsertCategory(category); //search engine name @@ -634,15 +637,20 @@ public ActionResult Edit(CategoryModel model, bool continueEditing, FormCollecti if (ModelState.IsValid) { - int prevPictureId = category.PictureId.GetValueOrDefault(); category = model.ToEntity(category); + + MediaHelper.UpdatePictureTransientStateFor(category, c => c.PictureId); + category.UpdatedOnUtc = DateTime.UtcNow; _categoryService.UpdateCategory(category); + //search engine name model.SeName = category.ValidateSeName(model.SeName, category.Name, true); _urlRecordService.SaveSlug(category, model.SeName, 0); + //locales UpdateLocales(category, model); + //discounts var allDiscounts = _discountService.GetAllDiscounts(DiscountType.AssignedToCategories, null, true); foreach (var discount in allDiscounts) @@ -665,14 +673,6 @@ public ActionResult Edit(CategoryModel model, bool continueEditing, FormCollecti //update "HasDiscountsApplied" property _categoryService.UpdateHasDiscountsApplied(category); - //delete an old picture (if deleted or updated) - if (prevPictureId > 0 && prevPictureId != category.PictureId) - { - var prevPicture = _pictureService.GetPictureById(prevPictureId); - if (prevPicture != null) - _pictureService.DeletePicture(prevPicture); - } - //update picture seo file name UpdatePictureSeoNames(category); @@ -718,7 +718,7 @@ public ActionResult Delete(int id, string deleteType) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); - + var category = _categoryService.GetCategoryById(id); if (category == null) return RedirectToAction("List"); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ContentSliderController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ContentSliderController.cs index 2469fe3fb6..85215e2d65 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ContentSliderController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ContentSliderController.cs @@ -134,6 +134,8 @@ public ActionResult Index(ContentSliderSettingsModel model) _contentSliderSettings.AutoPlay = model.AutoPlay; _contentSliderSettings.AutoPlayDelay = model.AutoPlayDelay; + MediaHelper.UpdatePictureTransientState(0, model.BackgroundPictureId, true); + _settingService.SaveSetting(_contentSliderSettings); var viewModel = PrepareContentSliderSettingsModel(model); @@ -174,6 +176,7 @@ public ActionResult CreateSlide(ContentSliderSlideModel model) model.PictureUrl = _pictureService.GetPictureUrl(model.PictureId); model.LanguageName = _languageService.GetLanguageByCulture(model.LanguageCulture).Name; _contentSliderSettings.Slides.Add(model.ToEntity()); + MediaHelper.UpdatePictureTransientState(0, model.PictureId, true); _settingService.SaveSetting(_contentSliderSettings); NotifySuccess(_localizationService.GetResource("Admin.Configuration.ContentSlider.Slide.Added")); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/DownloadController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/DownloadController.cs index b152f65b46..fd60c0768c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/DownloadController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/DownloadController.cs @@ -45,14 +45,14 @@ public ActionResult DownloadFile(int downloadId) [ValidateInput(false)] public ActionResult SaveDownloadUrl(string downloadUrl) { - //insert - var download = new Download() - { - DownloadGuid = Guid.NewGuid(), - UseDownloadUrl = true, - DownloadUrl = downloadUrl, - IsNew = true - }; + var download = new Download + { + DownloadGuid = Guid.NewGuid(), + UseDownloadUrl = true, + DownloadUrl = downloadUrl, + IsNew = true, + IsTransient = true + }; _downloadService.InsertDownload(download); return Json(new { downloadId = download.Id }, JsonRequestBehavior.AllowGet); @@ -61,59 +61,48 @@ public ActionResult SaveDownloadUrl(string downloadUrl) [HttpPost] public ActionResult AsyncUpload() { - //we process it distinct ways based on a browser - //find more info here http://stackoverflow.com/questions/4884920/mvc3-valums-ajax-file-upload - Stream stream = null; - var fileName = ""; - var contentType = ""; - if (String.IsNullOrEmpty(Request["qqfile"])) - { - // IE - HttpPostedFileBase httpPostedFile = Request.Files[0]; - if (httpPostedFile == null) - throw new ArgumentException("No file uploaded"); - stream = httpPostedFile.InputStream; - fileName = Path.GetFileName(httpPostedFile.FileName); - contentType = httpPostedFile.ContentType; - } - else - { - //Webkit, Mozilla - stream = Request.InputStream; - fileName = Request["qqfile"]; - } - - var fileBinary = new byte[stream.Length]; - stream.Read(fileBinary, 0, fileBinary.Length); - - var fileExtension = Path.GetExtension(fileName); - if (!String.IsNullOrEmpty(fileExtension)) - fileExtension = fileExtension.ToLowerInvariant(); + var postedFile = Request.ToPostedFileResult(); + if (postedFile == null) + { + throw new ArgumentException("No file uploaded"); + } - var download = new Download() + var download = new Download { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = false, DownloadUrl = "", - DownloadBinary = fileBinary, - ContentType = contentType, + DownloadBinary = postedFile.Buffer, + ContentType = postedFile.ContentType, //we store filename without extension for downloads - Filename = Path.GetFileNameWithoutExtension(fileName), - Extension = fileExtension, - IsNew = true + Filename = postedFile.FileTitle, + Extension = postedFile.FileExtension, + IsNew = true, + IsTransient = true }; _downloadService.InsertDownload(download); - //when returning JSON the mime-type must be set to text/plain - //otherwise some browsers will pop-up a "Save As" dialog. return Json(new { success = true, downloadId = download.Id, - fileName = download.Filename + download.Extension, + fileName = download.Filename.Truncate(50, "...") + download.Extension, downloadUrl = Url.Action("DownloadFile", new { downloadId = download.Id }) - }, - "text/plain"); + }); } + + [HttpPost] + public ActionResult DeleteDownload(int downloadId) + { + var download = _downloadService.GetDownloadById(downloadId); + if (download == null) + { + NotifyError("No download record found with the specified id"); + return Json(new { success = false }); + } + + _downloadService.DeleteDownload(download); + return Json(new { success = true }); + } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/LanguageController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/LanguageController.cs index 0ab3fdcb3d..d13971d7c3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/LanguageController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/LanguageController.cs @@ -486,12 +486,7 @@ public ActionResult ImportXml(int id, FormCollection form, ImportModeFlags mode, var file = Request.Files["importxmlfile"]; if (file != null && file.ContentLength > 0) { - using (var sr = new StreamReader(file.InputStream, Encoding.UTF8)) - { - string content = sr.ReadToEnd(); - _localizationService.ImportResourcesFromXml(language, content, mode: mode, updateTouchedResources: updateTouched); - } - + _localizationService.ImportResourcesFromXml(language, file.InputStream.AsString(), mode: mode, updateTouchedResources: updateTouched); } else { diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs index 178d046379..677af26b67 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ManufacturerController.cs @@ -311,6 +311,8 @@ public ActionResult Create(ManufacturerModel model, bool continueEditing) var manufacturer = model.ToEntity(); manufacturer.CreatedOnUtc = DateTime.UtcNow; manufacturer.UpdatedOnUtc = DateTime.UtcNow; + + MediaHelper.UpdatePictureTransientStateFor(manufacturer, m => m.PictureId); _manufacturerService.InsertManufacturer(manufacturer); @@ -381,10 +383,9 @@ public ActionResult Edit(ManufacturerModel model, bool continueEditing) if (ModelState.IsValid) { - int prevPictureId = manufacturer.PictureId.GetValueOrDefault(); manufacturer = model.ToEntity(manufacturer); + MediaHelper.UpdatePictureTransientStateFor(manufacturer, m => m.PictureId); manufacturer.UpdatedOnUtc = DateTime.UtcNow; - _manufacturerService.UpdateManufacturer(manufacturer); //search engine name @@ -394,14 +395,6 @@ public ActionResult Edit(ManufacturerModel model, bool continueEditing) //locales UpdateLocales(manufacturer, model); - //delete an old picture (if deleted or updated) - if (prevPictureId > 0 && prevPictureId != manufacturer.PictureId.GetValueOrDefault()) - { - var prevPicture = _pictureService.GetPictureById(prevPictureId); - if (prevPicture != null) - _pictureService.DeletePicture(prevPicture); - } - //update picture seo file name UpdatePictureSeoNames(manufacturer); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/MediaController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/MediaController.cs index ceac9c3ccc..aa64078b5f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/MediaController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/MediaController.cs @@ -12,7 +12,6 @@ namespace SmartStore.Admin.Controllers public partial class MediaController : AdminControllerBase { - private static readonly Regex s_allowedImageTypes = new Regex(@"(.*?)\.(gif|jpg|jpeg|png|bmp|ico|svg)", RegexOptions.Compiled | RegexOptions.IgnoreCase); private readonly IPermissionService _permissionService; private readonly IWebHelper _webHelper; @@ -51,46 +50,34 @@ public ActionResult UploadImageAjax() private UploadFileResult UploadImageInternal() { - if (Request.Files.Count == 0) + var postedFile = Request.ToPostedFileResult(); + if (postedFile == null) { return new UploadFileResult { Message = "No file uploaded" }; } - var uploadFile = Request.Files[0]; - if (uploadFile == null) - { - return new UploadFileResult { Message = "No file name provided" }; - } - - var fileName = Path.GetFileName(uploadFile.FileName); - if (fileName.IsEmpty()) + if (postedFile.FileName.IsEmpty()) { return new UploadFileResult { Message = "No file name provided" }; } var directory = "~/Media/Uploaded/"; - var filePath = Path.Combine(_webHelper.MapPath(directory), fileName); + var filePath = Path.Combine(_webHelper.MapPath(directory), postedFile.FileName); - if (!IsAllowedImageType(fileName)) + if (!!postedFile.IsImage) { - return new UploadFileResult { Message = "Files with extension '{0}' cannot be uploaded".FormatInvariant(Path.GetExtension(filePath)) }; + return new UploadFileResult { Message = "Files with extension '{0}' cannot be uploaded".FormatInvariant(postedFile.FileExtension) }; } - uploadFile.SaveAs(filePath); + postedFile.File.SaveAs(filePath); return new UploadFileResult { Success = true, - Url = this.Url.Content(string.Format("{0}{1}", directory, fileName)) + Url = this.Url.Content(string.Format("{0}{1}", directory, postedFile.FileName)) }; } - [NonAction] - protected virtual bool IsAllowedImageType(string path) - { - return s_allowedImageTypes.IsMatch(path); - } - public class UploadFileResult { public bool Success { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/MessageTemplateController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/MessageTemplateController.cs index c330b410b5..78f290f01f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/MessageTemplateController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/MessageTemplateController.cs @@ -5,6 +5,7 @@ using SmartStore.Collections; using SmartStore.Core.Domain.Messages; using SmartStore.Services.Localization; +using SmartStore.Services.Media; using SmartStore.Services.Messages; using SmartStore.Services.Security; using SmartStore.Services.Stores; @@ -91,13 +92,19 @@ public void UpdateLocales(MessageTemplate mt, MessageTemplateModel model) { foreach (var localized in model.Locales) { - _localizedEntityService.SaveLocalizedValue(mt, x => x.BccEmailAddresses, localized.BccEmailAddresses, localized.LanguageId); - _localizedEntityService.SaveLocalizedValue(mt, x => x.Subject, localized.Subject, localized.LanguageId); - _localizedEntityService.SaveLocalizedValue(mt,x => x.Body, localized.Body, localized.LanguageId); - _localizedEntityService.SaveLocalizedValue(mt, x => x.EmailAccountId, localized.EmailAccountId, localized.LanguageId); - _localizedEntityService.SaveLocalizedValue(mt, x => x.Attachment1FileId, localized.Attachment1FileId, localized.LanguageId); - _localizedEntityService.SaveLocalizedValue(mt, x => x.Attachment2FileId, localized.Attachment2FileId, localized.LanguageId); - _localizedEntityService.SaveLocalizedValue(mt, x => x.Attachment3FileId, localized.Attachment3FileId, localized.LanguageId); + int lid = localized.LanguageId; + + MediaHelper.UpdateDownloadTransientState(mt.GetLocalized(x => x.Attachment1FileId, lid, false, false), localized.Attachment1FileId, true); + MediaHelper.UpdateDownloadTransientState(mt.GetLocalized(x => x.Attachment2FileId, lid, false, false), localized.Attachment2FileId, true); + MediaHelper.UpdateDownloadTransientState(mt.GetLocalized(x => x.Attachment3FileId, lid, false, false), localized.Attachment3FileId, true); + + _localizedEntityService.SaveLocalizedValue(mt, x => x.BccEmailAddresses, localized.BccEmailAddresses, lid); + _localizedEntityService.SaveLocalizedValue(mt, x => x.Subject, localized.Subject, lid); + _localizedEntityService.SaveLocalizedValue(mt, x => x.Body, localized.Body, lid); + _localizedEntityService.SaveLocalizedValue(mt, x => x.EmailAccountId, localized.EmailAccountId, lid); + _localizedEntityService.SaveLocalizedValue(mt, x => x.Attachment1FileId, localized.Attachment1FileId, lid); + _localizedEntityService.SaveLocalizedValue(mt, x => x.Attachment2FileId, localized.Attachment2FileId, lid); + _localizedEntityService.SaveLocalizedValue(mt, x => x.Attachment3FileId, localized.Attachment3FileId, lid); } } @@ -221,6 +228,11 @@ public ActionResult Edit(MessageTemplateModel model, bool continueEditing) if (ModelState.IsValid) { messageTemplate = model.ToEntity(messageTemplate); + + MediaHelper.UpdateDownloadTransientStateFor(messageTemplate, x => x.Attachment1FileId); + MediaHelper.UpdateDownloadTransientStateFor(messageTemplate, x => x.Attachment2FileId); + MediaHelper.UpdateDownloadTransientStateFor(messageTemplate, x => x.Attachment3FileId); + _messageTemplateService.UpdateMessageTemplate(messageTemplate); // Stores diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs index c4157b9b0a..2f50f21a74 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs @@ -470,7 +470,7 @@ protected void PrepareOrderDetailsModel(OrderModel model, Order order) hasDownloadableItems = true; orderItem.Product.MergeWithCombination(orderItem.AttributesXml); - var orderItemModel = new OrderModel.OrderItemModel() + var orderItemModel = new OrderModel.OrderItemModel { Id = orderItem.Id, ProductId = orderItem.ProductId, @@ -496,7 +496,7 @@ protected void PrepareOrderDetailsModel(OrderModel model, Order order) foreach (var bundleItem in bundleData) { - var bundleItemModel = new OrderModel.BundleItemModel() + var bundleItemModel = new OrderModel.BundleItemModel { ProductId = bundleItem.ProductId, Sku = bundleItem.Sku, @@ -1642,7 +1642,7 @@ public ActionResult UploadLicenseFilePopup(int id, int orderItemId) if (!orderItem.Product.IsDownload) throw new ArgumentException("Product is not downloadable"); - var model = new OrderModel.UploadLicenseModel() + var model = new OrderModel.UploadLicenseModel { LicenseDownloadId = orderItem.LicenseDownloadId.HasValue ? orderItem.LicenseDownloadId.Value : 0, OrderId = order.Id, @@ -1673,6 +1673,9 @@ public ActionResult UploadLicenseFilePopup(string btnId, string formId, OrderMod orderItem.LicenseDownloadId = model.LicenseDownloadId; else orderItem.LicenseDownloadId = null; + + MediaHelper.UpdateDownloadTransientStateFor(orderItem, x => x.LicenseDownloadId); + _orderService.UpdateOrder(order); //success @@ -1701,6 +1704,7 @@ public ActionResult DeleteLicenseFilePopup(string btnId, string formId, OrderMod //attach license orderItem.LicenseDownloadId = null; + MediaHelper.UpdateDownloadTransientStateFor(orderItem, x => x.LicenseDownloadId); _orderService.UpdateOrder(order); //success @@ -1877,7 +1881,7 @@ public ActionResult AddProductToOrderDetails(int orderId, int productId, bool ad string attributeDescription = _productAttributeFormatter.FormatAttributes(product, attributes, order.Customer); //save item - var orderItem = new OrderItem() + var orderItem = new OrderItem { OrderItemGuid = Guid.NewGuid(), Order = order, diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PackagingController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PackagingController.cs index ac947d3c8c..4f67cb74c4 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PackagingController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PackagingController.cs @@ -52,8 +52,8 @@ public ActionResult UploadPackage(FormCollection form, string returnUrl = "") try { - var file = Request.Files["packagefile"]; - if (file != null && file.ContentLength > 0) + var file = Request.Files["packagefile"].ToPostedFileResult(); + if (file != null) { var requiredPermission = (isTheme = PackagingUtils.IsTheme(file.FileName)) ? StandardPermissionProvider.ManageThemes @@ -64,7 +64,7 @@ public ActionResult UploadPackage(FormCollection form, string returnUrl = "") return AccessDeniedView(); } - if (!Path.GetExtension(file.FileName).IsCaseInsensitiveEqual(".nupkg")) + if (!file.FileExtension.IsCaseInsensitiveEqual(".nupkg")) { NotifyError(T("Admin.Packaging.NotAPackage")); return Redirect(returnUrl); @@ -79,7 +79,7 @@ public ActionResult UploadPackage(FormCollection form, string returnUrl = "") _themeRegistry.Value.StopMonitoring(); } - var packageInfo = _packageManager.Install(file.InputStream, location, appPath); + var packageInfo = _packageManager.Install(file.Stream, location, appPath); if (isTheme) { diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PictureController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PictureController.cs index 6eac36619a..ae3a699877 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PictureController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PictureController.cs @@ -22,82 +22,21 @@ public PictureController(IPictureService pictureService, } [HttpPost] - public ActionResult AsyncUpload() + public ActionResult AsyncUpload(bool isTransient = false) { if (!_permissionService.Authorize(StandardPermissionProvider.UploadPictures)) - return Json(new { success = false, error = "You do not have required permissions" }, "text/plain"); + return Json(new { success = false, error = "You do not have the required permissions" }); - //we process it distinct ways based on a browser - //find more info here http://stackoverflow.com/questions/4884920/mvc3-valums-ajax-file-upload - Stream stream = null; - var fileName = ""; - var contentType = ""; - if (String.IsNullOrEmpty(Request["qqfile"])) - { - // IE - HttpPostedFileBase httpPostedFile = Request.Files[0]; - if (httpPostedFile == null) - throw new ArgumentException("No file uploaded"); - stream = httpPostedFile.InputStream; - fileName = Path.GetFileName(httpPostedFile.FileName); - contentType = httpPostedFile.ContentType; - } - else - { - //Webkit, Mozilla - stream = Request.InputStream; - fileName = Request["qqfile"]; - } + var postedFile = Request.ToPostedFileResult(); - var fileBinary = new byte[stream.Length]; - stream.Read(fileBinary, 0, fileBinary.Length); + var picture = _pictureService.InsertPicture(postedFile.Buffer, postedFile.ContentType, null, true, isTransient); - var fileExtension = Path.GetExtension(fileName); - if (!String.IsNullOrEmpty(fileExtension)) - fileExtension = fileExtension.ToLowerInvariant(); - //contentType is not always available - //that's why we manually update it here - //http://www.sfsu.edu/training/mimetype.htm - if (String.IsNullOrEmpty(contentType)) - { - switch (fileExtension) - { - case ".bmp": - contentType = "image/bmp"; - break; - case ".gif": - contentType = "image/gif"; - break; - case ".jpeg": - case ".jpg": - case ".jpe": - case ".jfif": - case ".pjpeg": - case ".pjp": - contentType = "image/jpeg"; - break; - case ".png": - contentType = "image/png"; - break; - case ".tiff": - case ".tif": - contentType = "image/tiff"; - break; - default: - break; - } - } - - var picture = _pictureService.InsertPicture(fileBinary, contentType, null, true); - //when returning JSON the mime-type must be set to text/plain - //otherwise some browsers will pop-up a "Save As" dialog. return Json( new { success = true, pictureId = picture.Id, imageUrl = _pictureService.GetPictureUrl(picture, 100) - }, - "text/plain"); + }); } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index c5fe38faec..938076253c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -228,7 +228,7 @@ protected void UpdateProductGeneralInfo(Product product, ProductModel model) p.IsGiftCard = m.IsGiftCard; p.GiftCardTypeId = m.GiftCardTypeId; - + p.IsDownload = m.IsDownload; p.DownloadId = m.DownloadId; p.UnlimitedDownloads = m.UnlimitedDownloads; @@ -553,6 +553,10 @@ private void UpdateDataOfExistingProduct(Product product, ProductModel model, bo var nameChanged = modifiedProperties.ContainsKey("Name"); var seoTabLoaded = m.LoadedTabs.Contains("SEO", StringComparer.OrdinalIgnoreCase); + // Handle Download transiency + MediaHelper.UpdateDownloadTransientStateFor(p, x => x.DownloadId); + MediaHelper.UpdateDownloadTransientStateFor(p, x => x.SampleDownloadId); + // SEO m.SeName = p.ValidateSeName(m.SeName, p.Name, true); _urlRecordService.SaveSlug(p, m.SeName, 0); @@ -2457,12 +2461,16 @@ public ActionResult ProductPictureAdd(int pictureId, int displayOrder, int produ if (product == null) throw new ArgumentException("No product found with the specified id"); - _productService.InsertProductPicture(new ProductPicture() + var productPicture = new ProductPicture { PictureId = pictureId, ProductId = productId, DisplayOrder = displayOrder, - }); + }; + + MediaHelper.UpdatePictureTransientStateFor(productPicture, pp => pp.PictureId); + + _productService.InsertProductPicture(productPicture); _pictureService.SetSeoFilename(pictureId, _pictureService.GetPictureSeName(product.Name)); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs index 90b04c7bfc..66f598883b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs @@ -1230,10 +1230,11 @@ public ActionResult GeneralCommon(GeneralCommonSettingsModel model, FormCollecti NotifyError(_localizationService.GetResource("Admin.Configuration.Settings.GeneralCommon.CaptchaEnabledNoKeys")); } - //PDF settings + // PDF settings var pdfSettings = _settingService.LoadSetting(storeScope); pdfSettings.Enabled = model.PdfSettings.Enabled; pdfSettings.LetterPageSizeEnabled = model.PdfSettings.LetterPageSizeEnabled; + MediaHelper.UpdatePictureTransientState(pdfSettings.LogoPictureId, model.PdfSettings.LogoPictureId, true); pdfSettings.LogoPictureId = model.PdfSettings.LogoPictureId; pdfSettings.AttachOrderPdfToOrderPlacedEmail = model.PdfSettings.AttachOrderPdfToOrderPlacedEmail; pdfSettings.AttachOrderPdfToOrderCompletedEmail = model.PdfSettings.AttachOrderPdfToOrderCompletedEmail; diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs index b29282d610..dcd050ea05 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/StoreController.cs @@ -8,6 +8,7 @@ using SmartStore.Services.Configuration; using SmartStore.Services.Directory; using SmartStore.Services.Localization; +using SmartStore.Services.Media; using SmartStore.Services.Security; using SmartStore.Services.Stores; using SmartStore.Web.Framework.Controllers; @@ -103,6 +104,7 @@ public ActionResult Create(StoreModel model, bool continueEditing) if (ModelState.IsValid) { var store = model.ToEntity(); + MediaHelper.UpdatePictureTransientStateFor(store, s => s.LogoPictureId); //ensure we have "/" at the end store.Url = store.Url.EnsureEndsWith("/"); _storeService.InsertStore(store); @@ -144,6 +146,9 @@ public ActionResult Edit(StoreModel model, bool continueEditing) if (ModelState.IsValid) { store = model.ToEntity(store); + + MediaHelper.UpdatePictureTransientStateFor(store, s => s.LogoPictureId); + //ensure we have "/" at the end store.Url = store.Url.EnsureEndsWith("/"); _storeService.UpdateStore(store); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs index 55c6cee336..e8e46d95aa 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ThemeController.cs @@ -393,11 +393,7 @@ public ActionResult ImportVariables(string theme, int storeId, FormCollection fo if (file != null && file.ContentLength > 0) { int importedCount = 0; - using (var sr = new StreamReader(file.InputStream, Encoding.UTF8)) - { - string content = sr.ReadToEnd(); - importedCount = _themeVarService.ImportVariables(theme, storeId, content); - } + importedCount = _themeVarService.ImportVariables(theme, storeId, file.InputStream.AsString()); // activity log try diff --git a/src/Presentation/SmartStore.Web/Administration/Scripts/smartstore.download.js b/src/Presentation/SmartStore.Web/Administration/Scripts/smartstore.download.js new file mode 100644 index 0000000000..493fbed959 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Scripts/smartstore.download.js @@ -0,0 +1,95 @@ +; + +// Unobtrusive handler for 'Download' editor template +(function ($, window, document, undefined) { + + var pluginName = 'downloadEditor'; + + function DownloadEditor(element, options) { + var self = this; + + // to access the DOM elem from outside of this constructor + this.element = element; + var el = this.el = $(element); + + // 'this.options' ensures we can reference the merged instance options from outside + var opts = this.options = $.extend({}, options); + + this.togglePanel = function (useUrl) { + if (useUrl && el.hasClass("minimal")) + return; + + if (useUrl == el.data("use-url")) + return; + + if (useUrl) { + el.find('.panel-upload').hide(); + el.find('.panel-url').show(); + el.find('.toggle-file').parent().removeClass("disabled"); + el.find('.toggle-url').parent().addClass("disabled"); + } + else { + el.find('.panel-url').hide(); + el.find('.panel-upload').show(); + el.find('.toggle-file').parent().addClass("disabled"); + el.find('.toggle-url').parent().removeClass("disabled"); + } + + el.data("use-url", useUrl); + }; + + this.init = function () { + var elHidden = el.find('.hidden'), + elRemove = el.find('.remove'); + + // handle panel switcher buttons + el.find('.toggle-file').on('click', function (e) { e.preventDefault(); self.togglePanel(false); }); + el.find('.toggle-url').on('click', function (e) { e.preventDefault(); self.togglePanel(true); }); + + // init file uploader + el.find('.fileupload').fileupload({ + url: el.data('upload-url'), + dataType: 'json', + + done: function (e, data) { + var result = data.result; + if (result.success) { + // >>>>>> $('#@(clientId + "downloadurl")').html('@T("Admin.Download.DownloadUploadedFile"): ' + result.fileName + ''); + elHidden.val(result.downloadId); + elRemove.show(); + } + }, + + error: function (jqXHR, textStatus, errorThrown) { + if (errorThrown === 'abort') { + //alert('File Upload has been canceled'); + } + } + }); + + // Download removal + elRemove.click(function (e) { + // >>>>>> $('#@(clientId + "downloadurl")').html(" "); + elHidden.val(0); + $(this).hide(); + e.preventDefault(); + }); + }; + + this.initialized = false; + this.init(); + this.initialized = true; + } + + $[pluginName] = { defaults: { } }; + + $.fn[pluginName] = function (options) { + return this.each(function () { + if (!$.data(this, pluginName)) { + options = $.extend({}, $[pluginName].defaults, options); + $.data(this, pluginName, new DownloadEditor(this, options)); + } + }); + } + +})(jQuery, window, document); \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index 60c5ff77f0..209e12c89f 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -466,6 +466,9 @@ + + Always + Always @@ -494,6 +497,7 @@ + diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml index dc94281687..6ac00a03c9 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Category/_CreateOrUpdate.cshtml @@ -133,7 +133,7 @@ @Html.SmartLabelFor(model => model.PictureId) - @Html.EditorFor(model => model.PictureId) + @Html.EditorFor(model => model.PictureId, new { transientUpload = true }) @Html.ValidationMessageFor(model => model.PictureId)
    - @Html.EditorFor(model => model.BackgroundPictureId, "Picture") + @Html.EditorFor(model => model.BackgroundPictureId, "Picture", new { transientUpload = true }) @Html.ValidationMessageFor(model => model.BackgroundPictureId)
    - @Html.EditorFor(model => model.PictureId, "Picture") + @Html.EditorFor(model => model.PictureId, "Picture", new { transientUpload = true }) @Html.ValidationMessageFor(model => model.PictureId)
    - @Html.EditorFor(model => model.PictureId) + @Html.EditorFor(model => model.PictureId, new { transientUpload = true }) @Html.ValidationMessageFor(model => model.PictureId)
    - @Html.EditorFor(model => Model.Locales[item].Attachment1FileId) + @Html.EditorFor(model => Model.Locales[item].Attachment1FileId, "Download") @Html.ValidationMessageFor(model => model.Locales[item].Attachment1FileId)
    - @Html.EditorFor(model => Model.Locales[item].Attachment2FileId) + @Html.EditorFor(model => Model.Locales[item].Attachment2FileId, "Download") @Html.ValidationMessageFor(model => model.Locales[item].Attachment2FileId)
    - @Html.EditorFor(model => Model.Locales[item].Attachment3FileId) + @Html.EditorFor(model => Model.Locales[item].Attachment3FileId, "Download") @Html.ValidationMessageFor(model => model.Locales[item].Attachment3FileId)
    - @Html.EditorFor(model => Model.Attachment1FileId) + @Html.EditorFor(model => Model.Attachment1FileId, "Download2") @Html.ValidationMessageFor(model => model.Attachment1FileId)
    - @Html.EditorFor(model => Model.Attachment2FileId) + @Html.EditorFor(model => Model.Attachment2FileId, "Download2") @Html.ValidationMessageFor(model => model.Attachment2FileId)
    - @Html.EditorFor(model => Model.Attachment3FileId) + @Html.EditorFor(model => Model.Attachment3FileId, "Download2", new { minimalMode = false }) @Html.ValidationMessageFor(model => model.Attachment3FileId)
    - @Html.EditorFor(model => model.AddPictureModel.PictureId) + @Html.EditorFor(model => model.AddPictureModel.PictureId, new { transientUpload = true }) @Html.ValidationMessageFor(model => model.AddPictureModel.PictureId)
    - @Html.SettingEditorFor(model => model.PdfSettings.LogoPictureId, "#pdf-logo-picture") + @Html.SettingEditorFor(model => model.PdfSettings.LogoPictureId, "#pdf-logo-picture", new { transientUpload = true }) @Html.ValidationMessageFor(model => model.PdfSettings.LogoPictureId)
    - @Html.EditorFor(model => model.LogoPictureId, "#store-logo-picture") + @Html.EditorFor(model => model.LogoPictureId, "#store-logo-picture", new { transientUpload = true }) @Html.ValidationMessageFor(model => model.LogoPictureId)
    + @Html.SmartLabelFor(model => model.DisplayWidgetZones) + + @Html.SettingEditorFor(model => model.DisplayWidgetZones) + @Html.ValidationMessageFor(model => model.DisplayWidgetZones) +
    diff --git a/src/Plugins/SmartStore.DevTools/Views/DevTools/WidgetZone.cshtml b/src/Plugins/SmartStore.DevTools/Views/DevTools/WidgetZone.cshtml new file mode 100644 index 0000000000..2dcf0c42a0 --- /dev/null +++ b/src/Plugins/SmartStore.DevTools/Views/DevTools/WidgetZone.cshtml @@ -0,0 +1,3 @@ + + Widget Zone + diff --git a/src/Plugins/SmartStore.DevTools/Widgets/ShowZonesWidget.cs b/src/Plugins/SmartStore.DevTools/Widgets/ShowZonesWidget.cs new file mode 100644 index 0000000000..f9834ae0d6 --- /dev/null +++ b/src/Plugins/SmartStore.DevTools/Widgets/ShowZonesWidget.cs @@ -0,0 +1,220 @@ +using System.Collections.Generic; +using System.Web; +using System.Web.Routing; +using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Plugins; +using SmartStore.Services; +using SmartStore.Services.Cms; +using SmartStore.Services.Common; + +namespace SmartStore.DevTools.Widgets +{ + [SystemName("Widgets.ShowZones")] + [FriendlyName("Show Zones")] + public class ShowZonesWidget : IWidget + { + private readonly ICommonServices _services; + private readonly HttpContextBase _httpContext; + + public ShowZonesWidget(ICommonServices services, + HttpContextBase httpContext, + IGenericAttributeService genericAttributeService) + { + _services = services; + _httpContext = httpContext; + } + + public IList GetWidgetZones() + { + return new List() + { + //Blogs + "blogpost_page_before_body", "mobile_blogpost_page_before_body", + "blogpost_page_before_comments", "mobile_blogpost_page_before_comments", + "blogpost_page_inside_comment", "mobile_blogpost_page_inside_comment", + "blogpost_page_after_comments", "mobile_blogpost_page_after_comments", + "bloglist_page_before_posts", "mobile_bloglist_page_before_posts", + "bloglist_page_inside_post", "mobile_bloglist_page_inside_post", + "bloglist_page_after_posts", "mobile_bloglist_page_after_posts", + + //Categories + "categorydetails_after_breadcrumb", + "categorydetails_top", "mobile_categorydetails_top", + "categorydetails_before_subcategories", "mobile_categorydetails_before_subcategories", + "categorydetails_before_featured_products", "mobile_categorydetails_before_featured_products", + "categorydetails_after_featured_products", + "categorydetails_before_product_list", "mobile_categorydetails_before_product_list", + "categorydetails_bottom", "mobile_categorydetails_bottom", + "categorydetails_before_filters", + + //Products + "productbox_add_info", + "productsbytag_before_product_list", + "productreviews_page_inside_review", + "productdetails_overview_top", + "productdetails_overview_bottom", + "productsbytag_top", "mobile_productsbytag_top", + "productsbytag_bottom", "mobile_productsbytag_bottom", + "productdetails_add_info", "mobile_productdetails_add_info", + "productdetails_top", "mobile_productdetails_top", + "productdetails_before_pictures", "mobile_productdetails_before_pictures", + "productdetails_after_pictures", "mobile_productdetails_after_pictures", + "productdetails_bottom", "mobile_productdetails_bottom", + + //Navigation + "productbreadcrumb_before", + "productbreadcrumb_after", + "header_menu_before", + "header_menu_after", + "megamenu_before_first_item", + "megamenu_after_last_item", + "account_dropdown_before", + "account_dropdown_after", + "header_links_before", "mobile_header_links_before", + "header_links_after", "mobile_header_links_after", + "infoblock_before", "mobile_infoblock_before", + "infoblock_after", "mobile_infoblock_after", + "account_navigation_before", "mobile_account_navigation_before", + "account_navigation_after", "mobile_account_navigation_after", + + //Checkout + "checkout_progress_before", + "checkout_progress_after", + "checkout_billing_address_top", "mobile_checkout_billing_address_top", + "checkout_billing_address_middle", "mobile_checkout_billing_address_middle", + "checkout_billing_address_bottom", "mobile_checkout_billing_address_bottom", + "checkout_completed_top", "mobile_checkout_completed_top", + "checkout_completed_bottom", "mobile_checkout_completed_bottom", + "checkout_confirm_top", "mobile_checkout_confirm_top", + "checkout_confirm_before_summary", "mobile_checkout_confirm_before_summary", + "checkout_confirm_bottom", "mobile_checkout_confirm_bottom", + "checkout_payment_method_top", "mobile_checkout_payment_method_top", + "checkout_payment_method_bottom", "mobile_checkout_payment_method_bottom", + "checkout_shipping_address_top", "mobile_checkout_shipping_address_top", + "checkout_shipping_address_middle", "mobile_checkout_shipping_address_middle", + "checkout_shipping_address_bottom", "mobile_checkout_shipping_address_bottom", + "checkout_shipping_method_top", "mobile_checkout_shipping_method_top", + "checkout_shipping_method_bottom", "mobile_checkout_shipping_method_bottom", + + //PDF + "invoice_footer_before", + "invoice_footer_after", + "invoice_header_before", + "invoice_header_right", + "invoice_header_after", + "invoice_top", + "invoice_orderinfo_top", + "invoice_orderinfotable_after", + "invoice_orderinfo_bottom", + "invoice_lines_before", + "invoice_checkoutattributes_before", + "invoice_ordertotals_before", + "invoice_ordernotes_before", + "invoice_bottom", + "pdfcatalog_cover_top", + "pdfcatalog_cover_logo_after", + "pdfcatalog_cover_storename_after", + "pdfcatalog_productdetail_top", + "pdfcatalog_productdetail_fulldescription_before", + "pdfcatalog_productdetail_picture_before", + "pdfcatalog_productdetail_specificationattributes_before", + "pdfcatalog_productdetail_bundleditems_before", + "pdfcatalog_productdetail_associatedproducts_before", + + //Manufacturer + "manufacturerdetails_top", "mobile_manufacturerdetails_top", + "manufacturerdetails_before_featured_products", "mobile_manufacturerdetails_before_featured_products", + "manufacturerdetails_after_featured_products", + "manufacturerdetails_before_filters", + "manufacturerdetails_before_product_list", "mobile_manufacturerdetails_before_product_list", + "manufacturerdetails_bottom", "mobile_manufacturerdetails_bottom", + + //Misc + "compareproducts_row", "mobile_compareproducts_row", + "productsearch_page_advanced", + "productsearch_page_basic", + "productsearch_page_advanced", + "searchbox", "mobile_searchbox", + "footer", "mobile_footer", + "contactus_top", "mobile_contactus_top", + "contactus_bottom", "mobile_contactus_bottom", + "productreviews_page_top", "mobile_productreviews_page_top", + "productreviews_page_inside_review", "mobile_productreviews_page_inside_review", + "productreviews_page_bottom", "mobile_productreviews_page_bottom", + "profile_page_info_userdetails", "mobile_profile_page_info_userdetails", + "profile_page_info_userstats", "mobile_profile_page_info_userstats", + "notifications", "mobile_notifications", + "shipmentdetails_top", + "shipmentdetails_orderinfo_top", + "shipmentdetails_orderinfotable_after", + "shipmentdetails_orderinfo_bottom", + "shipmentdetails_lines_before", + + //Global + "home_page_top", "mobile_home_page_top", + "home_page_bottom", "mobile_home_page_bottom", + "main_column_before", + "main_column_after", + "left_side_column_before", + "left_side_column_after_category_navigation", + "left_side_column_after_manufacturer_navigation", + "left_side_column_after_tags", + "left_side_column_after_info", + "left_side_column_after_poll", + "left_side_column_after", + "right_side_column_before", + "right_side_column_after_recentlyviewed", + "right_side_column_after_poll", + "right_side_column_after", + "body_start_html_tag_after", "mobile_body_start_html_tag_after", + "content_before", "mobile_content_before", + "content_after", "mobile_content_after", + "body_end_html_tag_before", "mobile_body_end_html_tag_after", + "head_html_tag", "mobile_head_html_tag", + "admin_navbar_before", + "admin_navbar_after", + "admin_breadcrumb", + "admin_content_before", + "admin_content_after", + "admin_menu_before", + + //News + "newslist_page_before_items", "mobile_newslist_page_before_items", + "newslist_page_inside_item", "mobile_newslist_page_inside_item", + "newslist_page_after_items", "mobile_newslist_page_after_items", + "newsitem_page_before_body", "mobile_newsitem_page_before_body", + "newsitem_page_before_comments", "mobile_newsitem_page_before_comments", + "newsitem_page_inside_comment", "mobile_newsitem_page_inside_comment", + "newsitem_page_after_comments", "mobile_newsitem_page_after_comments", + + //Orders + "orderdetails_page_top", "mobile_orderdetails_page_top", + "orderdetails_page_overview", "mobile_orderdetails_page_overview", + "orderdetails_page_beforeproducts", "mobile_orderdetails_page_beforeproducts", + "orderdetails_page_afterproducts", "mobile_orderdetails_page_afterproducts", + "orderdetails_page_aftertotal", "mobile_orderdetails_page_aftertotal", + "orderdetails_page_bottom", "mobile_orderdetails_page_bottom", + + //Shopping Cart + "mini_shopping_cart_bottom", + "order_summary_content_before", "mobile_order_summary_content_before", + "order_summary_content_totals_left", "mobile_order_summary_content_totals_left", + "order_summary_content_deals", "mobile_order_summary_content_deals", + "order_summary_content_totals_bottom", "mobile_order_summary_content_totals_bottom", + "order_summary_content_after", "mobile_order_summary_content_after" + }; + } + + public void GetDisplayWidgetRoute(string widgetZone, object model, int storeId, out string actionName, out string controllerName, out RouteValueDictionary routeValues) + { + controllerName = "DevTools"; + actionName = "WidgetZone"; + routeValues = new RouteValueDictionary() + { + { "Namespaces", "SmartStore.DevTools.Controllers" }, + { "area", "SmartStore.DevTools" }, + { "widgetZone", widgetZone } + }; + } + } +} \ No newline at end of file diff --git a/src/Plugins/SmartStore.GoogleAnalytics/GoogleAnalyticPlugin.cs b/src/Plugins/SmartStore.GoogleAnalytics/GoogleAnalyticPlugin.cs index fe48664ee6..0c798730ff 100644 --- a/src/Plugins/SmartStore.GoogleAnalytics/GoogleAnalyticPlugin.cs +++ b/src/Plugins/SmartStore.GoogleAnalytics/GoogleAnalyticPlugin.cs @@ -46,7 +46,7 @@ public void GetConfigurationRoute(out string actionName, out string controllerNa { actionName = "Configure"; controllerName = "WidgetsGoogleAnalytics"; - routeValues = new RouteValueDictionary() { /*{ "Namespaces", "SmartStore.GoogleAnalytics.Controllers" },*/ { "area", "SmartStore.GoogleAnalytics" } }; + routeValues = new RouteValueDictionary() { { "area", "SmartStore.GoogleAnalytics" } }; } /// @@ -62,7 +62,6 @@ public void GetDisplayWidgetRoute(string widgetZone, object model, int storeId, controllerName = "WidgetsGoogleAnalytics"; routeValues = new RouteValueDictionary() { - //{"Namespaces", "SmartStore.GoogleAnalytics.Controllers"}, {"area", "SmartStore.GoogleAnalytics"}, {"widgetZone", widgetZone} }; @@ -78,20 +77,20 @@ public override void Install() GoogleId = "UA-0000000-0", //TrackingScript = " ", TrackingScript = @" -", + ", EcommerceScript = @"_gaq.push(['_addTrans', '{ORDERID}', '{SITE}', '{TOTAL}', '{TAX}', '{SHIP}', '{CITY}', '{STATEPROVINCE}', '{COUNTRY}']); -{DETAILS} -_gaq.push(['_trackTrans']); ", + {DETAILS} + _gaq.push(['_trackTrans']); ", EcommerceDetailScript = @"_gaq.push(['_addItem', '{ORDERID}', '{PRODUCTSKU}', '{PRODUCTNAME}', '{CATEGORYNAME}', '{UNITPRICE}', '{QUANTITY}' ]); ", }; From cd55dd589c405a7ae51216e3cd1013231c70cf4b Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 18 Jul 2015 11:46:57 +0200 Subject: [PATCH 0264/1256] Resolves #523 Redirecting to payment provider performed by core instead of plugin --- changelog.md | 3 ++ src/Libraries/SmartStore.Core/IWebHelper.cs | 11 ------ src/Libraries/SmartStore.Core/WebHelper.cs | 23 ------------ .../Payments/PostProcessPaymentRequest.cs | 5 +++ src/Plugins/SmartStore.PayPal/Description.txt | 2 +- .../Providers/PayPalStandardProvider.cs | 6 +--- src/Plugins/SmartStore.PayPal/changelog.md | 12 ++++--- .../Controllers/CheckoutController.cs | 36 +++++++------------ .../Controllers/OrderController.cs | 33 ++++++++--------- 9 files changed, 44 insertions(+), 87 deletions(-) diff --git a/changelog.md b/changelog.md index 69001129fd..2b5005170b 100644 --- a/changelog.md +++ b/changelog.md @@ -19,6 +19,9 @@ * #725 Prevent LowestProductPrice being 0 * #709 News feed produced invalid RSS feed. Added content:encoded. Added maximum news age setting for feed export. +### Bugfixes +* #523 Redirecting to payment provider performed by core instead of plugin + ## SmartStore.NET 2.2.2 diff --git a/src/Libraries/SmartStore.Core/IWebHelper.cs b/src/Libraries/SmartStore.Core/IWebHelper.cs index d1fda9b4e8..03b4f128c8 100644 --- a/src/Libraries/SmartStore.Core/IWebHelper.cs +++ b/src/Libraries/SmartStore.Core/IWebHelper.cs @@ -118,16 +118,5 @@ public partial interface IWebHelper /// Redirect URL; empty string if you want to redirect to the current page URL /// Usually true after a new plugin was installed (nukes the MVC cache) void RestartAppDomain(bool makeRedirect = false, string redirectUrl = "", bool aggressive = false); - - /// - /// Gets a value that indicates whether the client is being redirected to a new location - /// - bool IsRequestBeingRedirected { get; } - - /// - /// Gets or sets a value that indicates whether the client is being redirected to a new location using POST - /// - bool IsPostBeingDone { get; set; } - } } diff --git a/src/Libraries/SmartStore.Core/WebHelper.cs b/src/Libraries/SmartStore.Core/WebHelper.cs index 71c23110e5..f7bee23a4c 100644 --- a/src/Libraries/SmartStore.Core/WebHelper.cs +++ b/src/Libraries/SmartStore.Core/WebHelper.cs @@ -474,29 +474,6 @@ internal static bool OptimizedCompilationsEnabled } } - public virtual bool IsRequestBeingRedirected - { - get - { - var response = _httpContext.Response; - return response.IsRequestBeingRedirected; - } - } - - public virtual bool IsPostBeingDone - { - get - { - if (_httpContext.Items["sm.IsPOSTBeingDone"] == null) - return false; - return Convert.ToBoolean(_httpContext.Items["sm.IsPOSTBeingDone"]); - } - set - { - _httpContext.Items["sm.IsPOSTBeingDone"] = value; - } - } - /// /// Finds the trust level of the running application (http://blogs.msdn.com/dmitryr/archive/2007/01/23/finding-out-the-current-trust-level-in-asp-net.aspx) /// diff --git a/src/Libraries/SmartStore.Services/Payments/PostProcessPaymentRequest.cs b/src/Libraries/SmartStore.Services/Payments/PostProcessPaymentRequest.cs index 1ca115635f..f14a6cc6aa 100644 --- a/src/Libraries/SmartStore.Services/Payments/PostProcessPaymentRequest.cs +++ b/src/Libraries/SmartStore.Services/Payments/PostProcessPaymentRequest.cs @@ -16,5 +16,10 @@ public partial class PostProcessPaymentRequest /// Whether the customer clicked the button to re-post the payment process /// public bool IsRePostProcessPayment { get; set; } + + /// + /// URL to a payment provider to fulfill the payment. The .NET core will redirect to it. + /// + public string RedirectUrl { get; set; } } } diff --git a/src/Plugins/SmartStore.PayPal/Description.txt b/src/Plugins/SmartStore.PayPal/Description.txt index 84e4594446..c921d9b989 100644 --- a/src/Plugins/SmartStore.PayPal/Description.txt +++ b/src/Plugins/SmartStore.PayPal/Description.txt @@ -2,7 +2,7 @@ Description: Provides the PayPal payment methods PayPal Express, PayPal Standard and PayPal Direct. SystemName: SmartStore.PayPal Group: Payment -Version: 2.2.0.1 +Version: 2.2.0.2 MinAppVersion: 2.2.0 DisplayOrder: 1 FileName: SmartStore.PayPal.dll diff --git a/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs b/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs index 609a7192e5..f6e333e66c 100644 --- a/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs +++ b/src/Plugins/SmartStore.PayPal/Providers/PayPalStandardProvider.cs @@ -18,7 +18,6 @@ using SmartStore.PayPal.Services; using SmartStore.PayPal.Settings; using SmartStore.Services; -using SmartStore.Services.Directory; using SmartStore.Services.Localization; using SmartStore.Services.Orders; using SmartStore.Services.Payments; @@ -34,18 +33,15 @@ namespace SmartStore.PayPal public partial class PayPalStandardProvider : PaymentPluginBase, IConfigurable { private readonly IOrderTotalCalculationService _orderTotalCalculationService; - private readonly HttpContextBase _httpContext; private readonly ICommonServices _services; private readonly ILogger _logger; public PayPalStandardProvider( - HttpContextBase httpContext, IOrderTotalCalculationService orderTotalCalculationService, ICommonServices services, ILogger logger) { _orderTotalCalculationService = orderTotalCalculationService; - _httpContext = httpContext; _services = services; _logger = logger; } @@ -280,7 +276,7 @@ public override void PostProcessPayment(PostProcessPaymentRequest postProcessPay builder.AppendFormat("&zip={0}", HttpUtility.UrlEncode(address.ZipPostalCode)); builder.AppendFormat("&email={0}", HttpUtility.UrlEncode(address.Email)); - _httpContext.Response.Redirect(builder.ToString()); + postProcessPaymentRequest.RedirectUrl = builder.ToString(); } /// diff --git a/src/Plugins/SmartStore.PayPal/changelog.md b/src/Plugins/SmartStore.PayPal/changelog.md index cf618f7d59..62451fa42c 100644 --- a/src/Plugins/SmartStore.PayPal/changelog.md +++ b/src/Plugins/SmartStore.PayPal/changelog.md @@ -1,13 +1,17 @@ #Release Notes# +##PayPal 2.2.0.2 +###Improvements +* Redirecting to payment provider performed by core instead of plugin + ##Paypal 2.2.0.1 ### New Features * Supports order list label for new incoming IPNs -##Paypal 1.22## -###Bugfixes### +##Paypal 1.22 +###Bugfixes * PayPal Standard provider now using shipping rather than billing address if shipping is required -##Paypal 1.21## -###Improvements### +##Paypal 1.21 +###Improvements * Multistore configuration \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs index 16f05a20d0..2112acc435 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs @@ -793,7 +793,6 @@ public ActionResult ConfirmOrder(FormCollection form) if ((_workContext.CurrentCustomer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed)) return new HttpUnauthorizedResult(); - //model var model = new CheckoutConfirmModel(); try @@ -827,12 +826,13 @@ public ActionResult ConfirmOrder(FormCollection form) if (placeOrderResult.Success) { + var postProcessPaymentRequest = new PostProcessPaymentRequest + { + Order = placeOrderResult.PlacedOrder + }; + if (isPaymentPaymentWorkflowRequired) { - var postProcessPaymentRequest = new PostProcessPaymentRequest() - { - Order = placeOrderResult.PlacedOrder - }; _paymentService.PostProcessPayment(postProcessPaymentRequest); } @@ -840,22 +840,16 @@ public ActionResult ConfirmOrder(FormCollection form) _httpContext.Session["OrderPaymentInfo"] = null; _httpContext.RemoveCheckoutState(); - if (_webHelper.IsRequestBeingRedirected || _webHelper.IsPostBeingDone) - { - //redirection or POST has been done in PostProcessPayment - return Content("Redirected"); - } - else - { - //if no redirection has been done (to a third-party payment page) - //theoretically it's not possible - return RedirectToAction("Completed"); - } + if (postProcessPaymentRequest.RedirectUrl.HasValue()) + { + return Redirect(postProcessPaymentRequest.RedirectUrl); + } + + return RedirectToAction("Completed"); } else { - foreach (var error in placeOrderResult.Errors) - model.Warnings.Add(error); + model.Warnings.AddRange(placeOrderResult.Errors); } } catch (Exception exc) @@ -864,12 +858,6 @@ public ActionResult ConfirmOrder(FormCollection form) model.Warnings.Add(exc.Message); } - //If we got this far, something failed, redisplay form - - //if (model.Warnings.Count > 0) - // TempData["ConfirmOrderWarnings"] = model.Warnings; - - //return RedirectToRoute("CheckoutConfirm"); return View(model); } diff --git a/src/Presentation/SmartStore.Web/Controllers/OrderController.cs b/src/Presentation/SmartStore.Web/Controllers/OrderController.cs index bf25af3aaa..05788c95f7 100644 --- a/src/Presentation/SmartStore.Web/Controllers/OrderController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/OrderController.cs @@ -611,27 +611,22 @@ public ActionResult RePostPayment(int id) if (IsUnauthorizedOrder(order)) return new HttpUnauthorizedResult(); - if (!_paymentService.CanRePostProcessPayment(order)) - return RedirectToAction("Details", "Order", new { id = order.Id }); + if (_paymentService.CanRePostProcessPayment(order)) + { + var postProcessPaymentRequest = new PostProcessPaymentRequest + { + Order = order, + IsRePostProcessPayment = true + }; - var postProcessPaymentRequest = new PostProcessPaymentRequest() - { - Order = order, - IsRePostProcessPayment = true - }; - _paymentService.PostProcessPayment(postProcessPaymentRequest); + _paymentService.PostProcessPayment(postProcessPaymentRequest); - if (_services.WebHelper.IsRequestBeingRedirected || _services.WebHelper.IsPostBeingDone) - { - //redirection or POST has been done in PostProcessPayment - return Content("Redirected"); - } - else - { - //if no redirection has been done (to a third-party payment page) - //theoretically it's not possible - return RedirectToAction("Details", "Order", new { id = order.Id }); - } + if (postProcessPaymentRequest.RedirectUrl.HasValue()) + { + return Redirect(postProcessPaymentRequest.RedirectUrl); + } + } + return RedirectToAction("Details", "Order", new { id = order.Id }); } [RequireHttpsByConfigAttribute(SslRequirement.Yes)] From bd2645ed6c4d3aa74ea98c36925a586f65205619 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 18 Jul 2015 12:13:04 +0200 Subject: [PATCH 0265/1256] Resolves #735 Include SKUs of attribute combinations when filtering the backend product list --- changelog.md | 1 + .../Catalog/IProductAttributeService.cs | 9 ++++++++- .../Catalog/ProductAttributeService.cs | 17 ++++++++++++++++- .../Catalog/ProductService.cs | 3 +-- .../Controllers/ProductController.cs | 14 +++++++++++--- 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/changelog.md b/changelog.md index 2b5005170b..c36e803c30 100644 --- a/changelog.md +++ b/changelog.md @@ -18,6 +18,7 @@ * #721 Message Queue: implement "Delete all" * #725 Prevent LowestProductPrice being 0 * #709 News feed produced invalid RSS feed. Added content:encoded. Added maximum news age setting for feed export. +* #735 Include SKUs of attribute combinations when filtering the backend product list ### Bugfixes * #523 Redirecting to payment provider performed by core instead of plugin diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs index c150159c83..0d9f8a46ab 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs @@ -159,12 +159,19 @@ public partial interface IProductAttributeService decimal? GetLowestCombinationPrice(int productId); /// - /// Gets a product variant attribute combination + /// Gets a product variant attribute combination by identifier /// /// Product variant attribute combination identifier /// Product variant attribute combination ProductVariantAttributeCombination GetProductVariantAttributeCombinationById(int productVariantAttributeCombinationId); + /// + /// /// Gets a product variant attribute combination by SKU + /// + /// SKU + /// Product variant attribute combination + ProductVariantAttributeCombination GetProductVariantAttributeCombinationBySku(string sku); + /// /// Inserts a product variant attribute combination /// diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs index 66a1dc876d..97ce41336e 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs @@ -483,7 +483,7 @@ orderby pvac.Price ascending } /// - /// Gets a product variant attribute combination + /// Gets a product variant attribute combination by identifier /// /// Product variant attribute combination identifier /// Product variant attribute combination @@ -496,6 +496,21 @@ public virtual ProductVariantAttributeCombination GetProductVariantAttributeComb return combination; } + + /// + /// /// Gets a product variant attribute combination by SKU + /// + /// SKU + /// Product variant attribute combination + public virtual ProductVariantAttributeCombination GetProductVariantAttributeCombinationBySku(string sku) + { + if (sku.IsEmpty()) + return null; + + var combination = _productVariantAttributeCombinationRepository.Table.FirstOrDefault(x => x.Sku == sku); + return combination; + } + /// /// Inserts a product variant attribute combination /// diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs index 8dc0d5f73c..5401657dd8 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs @@ -1028,8 +1028,7 @@ public virtual Product GetProductBySku(string sku) var query = from p in _productRepository.Table orderby p.DisplayOrder, p.Id - where !p.Deleted && - p.Sku == sku + where !p.Deleted && p.Sku == sku select p; var product = query.FirstOrDefault(); return product; diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index efd7a9f60c..612c11b7ac 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -948,9 +948,17 @@ public ActionResult ProductList(GridCommand command, ProductListModel model) public ActionResult GoToSku(ProductListModel model) { string sku = model.GoDirectlyToSku; - var product = _productService.GetProductBySku(sku); - if (product != null) - return RedirectToAction("Edit", "Product", new { id = product.Id }); + + if (sku.HasValue()) + { + var product = _productService.GetProductBySku(sku); + if (product != null) + return RedirectToAction("Edit", "Product", new { id = product.Id }); + + var combination = _productAttributeService.GetProductVariantAttributeCombinationBySku(sku); + if (combination != null && combination.Product != null && !combination.Product.Deleted) + return RedirectToAction("Edit", "Product", new { id = combination.Product.Id }); + } //not found return List(model); From 5f28e47bb1f359be846f17c794a37c9d8b8c9ff5 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 18 Jul 2015 19:16:18 +0200 Subject: [PATCH 0266/1256] #709 Forum active discussions RSS feed improvements --- .../Forums/ForumService.cs | 121 ++++++++++++------ .../Forums/IForumService.cs | 9 ++ .../Controllers/BoardsController.cs | 38 +----- 3 files changed, 93 insertions(+), 75 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs index 4f5ca20ce4..c5fdea7347 100644 --- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs +++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.ServiceModel.Syndication; +using System.Web.Mvc; using SmartStore.Core; using SmartStore.Core.Caching; using SmartStore.Core.Data; @@ -11,6 +13,8 @@ using SmartStore.Services.Common; using SmartStore.Services.Customers; using SmartStore.Services.Messages; +using SmartStore.Services.Seo; +using SmartStore.Utilities; namespace SmartStore.Services.Forums { @@ -41,11 +45,9 @@ public partial class ForumService : IForumService private readonly ICacheManager _cacheManager; private readonly IGenericAttributeService _genericAttributeService; private readonly ICustomerService _customerService; - private readonly IWorkContext _workContext; private readonly IWorkflowMessageService _workflowMessageService; - private readonly IEventPublisher _eventPublisher; - private readonly IStoreContext _storeContext; private readonly IRepository _storeMappingRepository; + private readonly ICommonServices _services; #endregion @@ -62,11 +64,9 @@ public ForumService(ICacheManager cacheManager, IRepository customerRepository, IGenericAttributeService genericAttributeService, ICustomerService customerService, - IWorkContext workContext, IWorkflowMessageService workflowMessageService, - IEventPublisher eventPublisher, - IStoreContext storeContext, - IRepository storeMappingRepository) + IRepository storeMappingRepository, + ICommonServices services) { _cacheManager = cacheManager; _forumGroupRepository = forumGroupRepository; @@ -79,11 +79,9 @@ public ForumService(ICacheManager cacheManager, _customerRepository = customerRepository; _genericAttributeService = genericAttributeService; _customerService = customerService; - _workContext = workContext; _workflowMessageService = workflowMessageService; - _eventPublisher = eventPublisher; - _storeContext = storeContext; _storeMappingRepository = storeMappingRepository; + _services = services; } public DbQuerySettings QuerySettings { get; set; } @@ -263,7 +261,7 @@ public virtual void DeleteForumGroup(ForumGroup forumGroup) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityDeleted(forumGroup); + _services.EventPublisher.EntityDeleted(forumGroup); } /// @@ -292,7 +290,7 @@ public virtual IList GetAllForumGroups(bool showHidden = false) if (!showHidden && !QuerySettings.IgnoreMultiStore) { - var currentStoreId = _storeContext.CurrentStore.Id; + var currentStoreId = _services.StoreContext.CurrentStore.Id; query = from fg in query @@ -332,7 +330,7 @@ public virtual void InsertForumGroup(ForumGroup forumGroup) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityInserted(forumGroup); + _services.EventPublisher.EntityInserted(forumGroup); } /// @@ -353,7 +351,7 @@ public virtual void UpdateForumGroup(ForumGroup forumGroup) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityUpdated(forumGroup); + _services.EventPublisher.EntityUpdated(forumGroup); } /// @@ -378,7 +376,7 @@ where queryTopicIds.Contains(fs.TopicId) { _forumSubscriptionRepository.Delete(fs); //event notification - _eventPublisher.EntityDeleted(fs); + _services.EventPublisher.EntityDeleted(fs); } //delete forum subscriptions (forum) @@ -389,7 +387,7 @@ where queryTopicIds.Contains(fs.TopicId) { _forumSubscriptionRepository.Delete(fs2); //event notification - _eventPublisher.EntityDeleted(fs2); + _services.EventPublisher.EntityDeleted(fs2); } //delete forum @@ -399,7 +397,7 @@ where queryTopicIds.Contains(fs.TopicId) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityDeleted(forum); + _services.EventPublisher.EntityDeleted(forum); } /// @@ -451,7 +449,7 @@ public virtual void InsertForum(Forum forum) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityInserted(forum); + _services.EventPublisher.EntityInserted(forum); } /// @@ -471,7 +469,7 @@ public virtual void UpdateForum(Forum forum) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityUpdated(forum); + _services.EventPublisher.EntityUpdated(forum); } /// @@ -500,7 +498,7 @@ public virtual void DeleteTopic(ForumTopic forumTopic) { _forumSubscriptionRepository.Delete(fs); //event notification - _eventPublisher.EntityDeleted(fs); + _services.EventPublisher.EntityDeleted(fs); } //update stats @@ -511,7 +509,7 @@ public virtual void DeleteTopic(ForumTopic forumTopic) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityDeleted(forumTopic); + _services.EventPublisher.EntityDeleted(forumTopic); } /// @@ -613,7 +611,7 @@ from ft in _forumTopicRepository.Table if (!QuerySettings.IgnoreMultiStore) { - var currentStoreId = _storeContext.CurrentStore.Id; + var currentStoreId = _services.StoreContext.CurrentStore.Id; query = from ft in query @@ -659,14 +657,14 @@ public virtual void InsertTopic(ForumTopic forumTopic, bool sendNotifications) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityInserted(forumTopic); + _services.EventPublisher.EntityInserted(forumTopic); //send notifications if (sendNotifications) { var forum = forumTopic.Forum; var subscriptions = GetAllSubscriptions(0, forum.Id, 0, 0, int.MaxValue); - var languageId = _workContext.WorkingLanguage.Id; + var languageId = _services.WorkContext.WorkingLanguage.Id; foreach (var subscription in subscriptions) { @@ -700,7 +698,7 @@ public virtual void UpdateTopic(ForumTopic forumTopic) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityUpdated(forumTopic); + _services.EventPublisher.EntityUpdated(forumTopic); } /// @@ -715,7 +713,7 @@ public virtual ForumTopic MoveTopic(int forumTopicId, int newForumId) if (forumTopic == null) return forumTopic; - if (this.IsCustomerAllowedToMoveTopic(_workContext.CurrentCustomer, forumTopic)) + if (this.IsCustomerAllowedToMoveTopic(_services.WorkContext.CurrentCustomer, forumTopic)) { int previousForumId = forumTopic.ForumId; var newForum = GetForumById(newForumId); @@ -783,7 +781,7 @@ public virtual void DeletePost(ForumPost forumPost) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityDeleted(forumPost); + _services.EventPublisher.EntityDeleted(forumPost); } @@ -887,7 +885,7 @@ public virtual void InsertPost(ForumPost forumPost, bool sendNotifications) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityInserted(forumPost); + _services.EventPublisher.EntityInserted(forumPost); //notifications if (sendNotifications) @@ -895,7 +893,7 @@ public virtual void InsertPost(ForumPost forumPost, bool sendNotifications) var forum = forumTopic.Forum; var subscriptions = GetAllSubscriptions(0, 0, forumTopic.Id, 0, int.MaxValue); - var languageId = _workContext.WorkingLanguage.Id; + var languageId = _services.WorkContext.WorkingLanguage.Id; int friendlyTopicPageIndex = CalculateTopicPageIndex(forumPost.TopicId, _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 10, forumPost.Id) + 1; @@ -932,7 +930,7 @@ public virtual void UpdatePost(ForumPost forumPost) _cacheManager.RemoveByPattern(FORUM_PATTERN_KEY); //event notification - _eventPublisher.EntityUpdated(forumPost); + _services.EventPublisher.EntityUpdated(forumPost); } /// @@ -949,7 +947,7 @@ public virtual void DeletePrivateMessage(PrivateMessage privateMessage) _forumPrivateMessageRepository.Delete(privateMessage); //event notification - _eventPublisher.EntityDeleted(privateMessage); + _services.EventPublisher.EntityDeleted(privateMessage); } /// @@ -1028,7 +1026,7 @@ public virtual void InsertPrivateMessage(PrivateMessage privateMessage) _forumPrivateMessageRepository.Insert(privateMessage); //event notification - _eventPublisher.EntityInserted(privateMessage); + _services.EventPublisher.EntityInserted(privateMessage); var customerTo = _customerService.GetCustomerById(privateMessage.ToCustomerId); if (customerTo == null) @@ -1042,7 +1040,7 @@ public virtual void InsertPrivateMessage(PrivateMessage privateMessage) //Email notification if (_forumSettings.NotifyAboutPrivateMessages) { - _workflowMessageService.SendPrivateMessageNotification(customerTo, privateMessage, _workContext.WorkingLanguage.Id); + _workflowMessageService.SendPrivateMessageNotification(customerTo, privateMessage, _services.WorkContext.WorkingLanguage.Id); } } @@ -1059,13 +1057,13 @@ public virtual void UpdatePrivateMessage(PrivateMessage privateMessage) { _forumPrivateMessageRepository.Delete(privateMessage); //event notification - _eventPublisher.EntityDeleted(privateMessage); + _services.EventPublisher.EntityDeleted(privateMessage); } else { _forumPrivateMessageRepository.Update(privateMessage); //event notification - _eventPublisher.EntityUpdated(privateMessage); + _services.EventPublisher.EntityUpdated(privateMessage); } } @@ -1083,7 +1081,7 @@ public virtual void DeleteSubscription(ForumSubscription forumSubscription) _forumSubscriptionRepository.Delete(forumSubscription); //event notification - _eventPublisher.EntityDeleted(forumSubscription); + _services.EventPublisher.EntityDeleted(forumSubscription); } /// @@ -1151,7 +1149,7 @@ public virtual void InsertSubscription(ForumSubscription forumSubscription) _forumSubscriptionRepository.Insert(forumSubscription); //event notification - _eventPublisher.EntityInserted(forumSubscription); + _services.EventPublisher.EntityInserted(forumSubscription); } /// @@ -1168,7 +1166,7 @@ public virtual void UpdateSubscription(ForumSubscription forumSubscription) _forumSubscriptionRepository.Update(forumSubscription); //event notification - _eventPublisher.EntityUpdated(forumSubscription); + _services.EventPublisher.EntityUpdated(forumSubscription); } /// @@ -1477,7 +1475,52 @@ public virtual int CalculateTopicPageIndex(int forumTopicId, int pageSize, int p return pageIndex; } - + + /// + /// Creates a RSS feed with active discussions + /// + /// UrlHelper to generate URLs + /// SmartSyndicationFeed object + public virtual SmartSyndicationFeed CreateActiveDiscussionsRssFeed(UrlHelper urlHelper, int forumId) + { + if (urlHelper == null) + throw new ArgumentNullException("urlHelper"); + + var protocol = _services.WebHelper.IsCurrentConnectionSecured() ? "https" : "http"; + var selfLink = urlHelper.Action("ActiveDiscussionsRSS", "Boards", null, protocol); + var discussionLink = urlHelper.Action("ActiveDiscussions", "Boards", null, protocol); + + var title = "{0} - {1}".FormatInvariant(_services.StoreContext.CurrentStore.Name, _services.Localization.GetResource("Forum.ActiveDiscussionsFeedTitle")); + + var feed = new SmartSyndicationFeed(new Uri(discussionLink), title, _services.Localization.GetResource("Forum.ActiveDiscussionsFeedDescription")); + + feed.AddNamespaces(false); + feed.Init(selfLink, _services.WorkContext.WorkingLanguage); + + if (!_forumSettings.ActiveDiscussionsFeedEnabled) + return feed; + + var items = new List(); + var topics = GetActiveTopics(forumId, _forumSettings.ActiveDiscussionsFeedCount); + + var viewsText = _services.Localization.GetResource("Forum.Views"); + var repliesText = _services.Localization.GetResource("Forum.Replies"); + + foreach (var topic in topics) + { + string topicUrl = urlHelper.RouteUrl("TopicSlug", new { id = topic.Id, slug = topic.GetSeName() }, "http"); + var synopsis = "{0}: {1}, {2}: {3}".FormatInvariant(repliesText, topic.NumReplies, viewsText, topic.Views); + + var item = feed.CreateItem(topic.Subject, synopsis, topicUrl, topic.LastPostTime ?? topic.UpdatedOnUtc); + + items.Add(item); + } + + feed.Items = items; + + return feed; + } + #endregion } } diff --git a/src/Libraries/SmartStore.Services/Forums/IForumService.cs b/src/Libraries/SmartStore.Services/Forums/IForumService.cs index 46e0f2f428..0d74f8dab0 100644 --- a/src/Libraries/SmartStore.Services/Forums/IForumService.cs +++ b/src/Libraries/SmartStore.Services/Forums/IForumService.cs @@ -1,7 +1,9 @@ using System.Collections.Generic; +using System.Web.Mvc; using SmartStore.Core; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Forums; +using SmartStore.Utilities; namespace SmartStore.Services.Forums { @@ -344,5 +346,12 @@ IPagedList GetAllSubscriptions(int customerId, int forumId, /// Post identifier /// Page index int CalculateTopicPageIndex(int forumTopicId, int pageSize, int postId); + + /// + /// Creates a RSS feed with active discussions + /// + /// UrlHelper to generate URLs + /// SmartSyndicationFeed object + SmartSyndicationFeed CreateActiveDiscussionsRssFeed(UrlHelper urlHelper, int forumId); } } diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs index d9dcc8baaa..7d52cd5133 100644 --- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs @@ -266,45 +266,11 @@ public ActionResult ActiveDiscussions(int forumId = 0) public ActionResult ActiveDiscussionsRss(int forumId = 0) { if (!_forumSettings.ForumsEnabled) - { - return HttpNotFound(); - } - - if (!_forumSettings.ActiveDiscussionsFeedEnabled) - { return HttpNotFound(); - } - - int topicLimit = _forumSettings.ActiveDiscussionsFeedCount; - var topics = _forumService.GetActiveTopics(forumId, topicLimit); - string url = Url.Action("ActiveDiscussionsRSS", null, (object)null, "http"); - var feedTitle = _localizationService.GetResource("Forum.ActiveDiscussionsFeedTitle"); - var feedDescription = _localizationService.GetResource("Forum.ActiveDiscussionsFeedDescription"); - - var feed = new SyndicationFeed( - string.Format(feedTitle, _storeContext.CurrentStore.Name), - feedDescription, - new Uri(url), - "ActiveDiscussionsRSS", - DateTime.UtcNow); - - var items = new List(); - - var viewsText = _localizationService.GetResource("Forum.Views"); - var repliesText = _localizationService.GetResource("Forum.Replies"); - - foreach (var topic in topics) - { - string topicUrl = Url.RouteUrl("TopicSlug", new { id = topic.Id, slug = topic.GetSeName() }, "http"); - string content = String.Format("{2}: {0}, {3}: {1}", topic.NumReplies.ToString(), topic.Views.ToString(), repliesText, viewsText); - - items.Add(new SyndicationItem(topic.Subject, content, new Uri(topicUrl), - String.Format("Topic:{0}", topic.Id), (topic.LastPostTime ?? topic.UpdatedOnUtc))); - } - feed.Items = items; + var feed = _forumService.CreateActiveDiscussionsRssFeed(Url, forumId); - return new RssActionResult() { Feed = feed }; + return new RssActionResult { Feed = feed }; } public ActionResult ForumGroup(int id) From b68157ddc09e3a980ced82b6dfd24074338c1784 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sun, 19 Jul 2015 11:57:35 +0200 Subject: [PATCH 0267/1256] #709 Forum topics RSS feed improvements --- ...61756463_PrimaryStoreCurrencyMultiStore.cs | 1 + .../Forums/ForumService.cs | 56 ++++++++++++++++++- .../Forums/IForumService.cs | 7 +++ .../Controllers/BoardsController.cs | 55 ++---------------- 4 files changed, 68 insertions(+), 51 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs index e61acfd677..f243d50dc2 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506261756463_PrimaryStoreCurrencyMultiStore.cs @@ -154,6 +154,7 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.Delete("Admin.Configuration.Currencies.CantDeleteExchange"); builder.Delete("Admin.Configuration.Currencies.Fields.MarkAsPrimaryStoreCurrency"); builder.Delete("Admin.Configuration.Currencies.Fields.MarkAsPrimaryExchangeRateCurrency"); + builder.Delete("Forum.ForumFeedTitle"); } } } diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs index c5fdea7347..c9f9e63dbd 100644 --- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs +++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs @@ -12,6 +12,7 @@ using SmartStore.Core.Events; using SmartStore.Services.Common; using SmartStore.Services.Customers; +using SmartStore.Services.Localization; using SmartStore.Services.Messages; using SmartStore.Services.Seo; using SmartStore.Utilities; @@ -1486,6 +1487,7 @@ public virtual SmartSyndicationFeed CreateActiveDiscussionsRssFeed(UrlHelper url if (urlHelper == null) throw new ArgumentNullException("urlHelper"); + var language = _services.WorkContext.WorkingLanguage; var protocol = _services.WebHelper.IsCurrentConnectionSecured() ? "https" : "http"; var selfLink = urlHelper.Action("ActiveDiscussionsRSS", "Boards", null, protocol); var discussionLink = urlHelper.Action("ActiveDiscussions", "Boards", null, protocol); @@ -1495,7 +1497,7 @@ public virtual SmartSyndicationFeed CreateActiveDiscussionsRssFeed(UrlHelper url var feed = new SmartSyndicationFeed(new Uri(discussionLink), title, _services.Localization.GetResource("Forum.ActiveDiscussionsFeedDescription")); feed.AddNamespaces(false); - feed.Init(selfLink, _services.WorkContext.WorkingLanguage); + feed.Init(selfLink, language); if (!_forumSettings.ActiveDiscussionsFeedEnabled) return feed; @@ -1521,6 +1523,58 @@ public virtual SmartSyndicationFeed CreateActiveDiscussionsRssFeed(UrlHelper url return feed; } + /// + /// Creates a RSS feed with forum topics + /// + /// UrlHelper to generate URLs + /// SmartSyndicationFeed object + public virtual SmartSyndicationFeed CreateForumRssFeed(UrlHelper urlHelper, int forumId) + { + if (urlHelper == null) + throw new ArgumentNullException("urlHelper"); + + var language = _services.WorkContext.WorkingLanguage; + var protocol = _services.WebHelper.IsCurrentConnectionSecured() ? "https" : "http"; + var selfLink = urlHelper.Action("ForumRSS", "Boards", null, protocol); + var forumLink = urlHelper.Action("Forum", "Boards", new { id = forumId }, protocol); + + var feed = new SmartSyndicationFeed(new Uri(forumLink), _services.StoreContext.CurrentStore.Name, _services.Localization.GetResource("Forum.ForumFeedDescription")); + + feed.AddNamespaces(false); + feed.Init(selfLink, language); + + if (!_forumSettings.ForumFeedsEnabled) + return feed; + + var forum = GetForumById(forumId); + + if (forum == null) + return feed; + + feed.Title = new TextSyndicationContent("{0} - {1}".FormatInvariant(_services.StoreContext.CurrentStore.Name, forum.GetLocalized(x => x.Name, language.Id))); + + var items = new List(); + var topics = GetAllTopics(forumId, 0, string.Empty, ForumSearchType.All, 0, 0, _forumSettings.ForumFeedCount); + + var viewsText = _services.Localization.GetResource("Forum.Views"); + var repliesText = _services.Localization.GetResource("Forum.Replies"); + + foreach (var topic in topics) + { + string topicUrl = urlHelper.RouteUrl("TopicSlug", new { id = topic.Id, slug = topic.GetSeName() }, "http"); + var synopsis = "{0}: {1}, {2}: {3}".FormatInvariant(repliesText, topic.NumReplies, viewsText, topic.Views); + + var item = feed.CreateItem(topic.Subject, synopsis, topicUrl, topic.LastPostTime ?? topic.UpdatedOnUtc); + + items.Add(item); + } + + feed.Items = items; + + return feed; + } + + #endregion } } diff --git a/src/Libraries/SmartStore.Services/Forums/IForumService.cs b/src/Libraries/SmartStore.Services/Forums/IForumService.cs index 0d74f8dab0..efcd21fa32 100644 --- a/src/Libraries/SmartStore.Services/Forums/IForumService.cs +++ b/src/Libraries/SmartStore.Services/Forums/IForumService.cs @@ -353,5 +353,12 @@ IPagedList GetAllSubscriptions(int customerId, int forumId, /// UrlHelper to generate URLs /// SmartSyndicationFeed object SmartSyndicationFeed CreateActiveDiscussionsRssFeed(UrlHelper urlHelper, int forumId); + + /// + /// Creates a RSS feed with forum topics + /// + /// UrlHelper to generate URLs + /// SmartSyndicationFeed object + SmartSyndicationFeed CreateForumRssFeed(UrlHelper urlHelper, int forumId); } } diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs index 7d52cd5133..6e2dd867cf 100644 --- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.ServiceModel.Syndication; using System.Web.Mvc; using SmartStore.Core; using SmartStore.Core.Domain.Customers; @@ -18,6 +17,7 @@ using SmartStore.Services.Seo; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Controllers; +using SmartStore.Web.Framework.Mvc; using SmartStore.Web.Framework.Security; using SmartStore.Web.Models.Boards; @@ -34,7 +34,6 @@ public partial class BoardsController : PublicControllerBase private readonly ICountryService _countryService; private readonly IWebHelper _webHelper; private readonly IWorkContext _workContext; - private readonly IStoreContext _storeContext; private readonly ForumSettings _forumSettings; private readonly CustomerSettings _customerSettings; private readonly MediaSettings _mediaSettings; @@ -50,7 +49,6 @@ public BoardsController(IForumService forumService, ICountryService countryService, IWebHelper webHelper, IWorkContext workContext, - IStoreContext storeContext, ForumSettings forumSettings, CustomerSettings customerSettings, MediaSettings mediaSettings, @@ -62,7 +60,6 @@ public BoardsController(IForumService forumService, this._countryService = countryService; this._webHelper = webHelper; this._workContext = workContext; - this._storeContext = storeContext; this._forumSettings = forumSettings; this._customerSettings = customerSettings; this._mediaSettings = mediaSettings; @@ -263,6 +260,7 @@ public ActionResult ActiveDiscussions(int forumId = 0) return View(model); } + [Compress] public ActionResult ActiveDiscussionsRss(int forumId = 0) { if (!_forumSettings.ForumsEnabled) @@ -345,58 +343,15 @@ public ActionResult Forum(int id, int page = 1) return RedirectToRoute("Boards"); } + [Compress] public ActionResult ForumRss(int id) { if (!_forumSettings.ForumsEnabled) - { - return HttpNotFound(); - } - - if (!_forumSettings.ForumFeedsEnabled) - { return HttpNotFound(); - } - - int topicLimit = _forumSettings.ForumFeedCount; - var forum = _forumService.GetForumById(id); - - if (forum != null) - { - //Order by newest topic posts & limit the number of topics to return - var topics = _forumService.GetAllTopics(forum.Id, 0, string.Empty, ForumSearchType.All, 0, 0, topicLimit); - - string url = Url.Action("ForumRSS", null, new { id = forum.Id }, "http"); - var feedTitle = _localizationService.GetResource("Forum.ForumFeedTitle"); - var feedDescription = _localizationService.GetResource("Forum.ForumFeedDescription"); - - var feed = new SyndicationFeed( - string.Format(feedTitle, _storeContext.CurrentStore.Name, forum.GetLocalized(x => x.Name)), - feedDescription, - new Uri(url), - string.Format("ForumRSS:{0}", forum.Id), - DateTime.UtcNow); - - var items = new List(); - - var viewsText = _localizationService.GetResource("Forum.Views"); - var repliesText = _localizationService.GetResource("Forum.Replies"); - - foreach (var topic in topics) - { - string topicUrl = Url.RouteUrl("TopicSlug", new { id = topic.Id, slug = topic.GetSeName() }, "http"); - string content = string.Format("{2}: {0}, {3}: {1}", topic.NumReplies.ToString(), topic.Views.ToString(), repliesText, viewsText); - - items.Add(new SyndicationItem(topic.Subject, content, new Uri(topicUrl), String.Format("Topic:{0}", topic.Id), - (topic.LastPostTime ?? topic.UpdatedOnUtc))); - } - - feed.Items = items; - - return new RssActionResult() { Feed = feed }; - } + var feed = _forumService.CreateForumRssFeed(Url, id); - return new RssActionResult() { Feed = new SyndicationFeed() }; + return new RssActionResult { Feed = feed }; } [HttpPost] From 1e663bc8a44d8dfeaac767ec66ab88b9ffc42d7c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 20 Jul 2015 10:23:43 +0200 Subject: [PATCH 0268/1256] Minor changes --- .../Controllers/ProductController.cs | 35 +++--- .../Models/Catalog/BulkEditListModel.cs | 8 ++ .../Views/Product/BulkEdit.cshtml | 110 ++++++++++-------- .../Administration/Views/Product/List.cshtml | 30 ++--- 4 files changed, 108 insertions(+), 75 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index 612c11b7ac..13c457c0d2 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -867,7 +867,6 @@ public ActionResult List(ProductListModel model) model.GridPageSize = _adminAreaSettings.GridPageSize; model.StoreCount = allStores.Count; - //categories var allCategories = _categoryService.GetAllCategories(showHidden: true); var mappedCategories = allCategories.ToDictionary(x => x.Id); foreach (var c in allCategories) @@ -875,22 +874,17 @@ public ActionResult List(ProductListModel model) model.AvailableCategories.Add(new SelectListItem { Text = c.GetCategoryNameWithPrefix(_categoryService, mappedCategories), Value = c.Id.ToString() }); } - //manufacturers foreach (var m in _manufacturerService.GetAllManufacturers(true)) { model.AvailableManufacturers.Add(new SelectListItem { Text = m.Name, Value = m.Id.ToString() }); } - //stores - model.AvailableStores.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" }); foreach (var s in allStores) { model.AvailableStores.Add(new SelectListItem { Text = s.Name, Value = s.Id.ToString() }); } - //product types model.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList(); - model.AvailableProductTypes.Insert(0, new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" }); return View(model); } @@ -3277,25 +3271,30 @@ public ActionResult BulkEdit() if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); + var allStores = _services.StoreService.GetAllStores(); + var model = new BulkEditListModel(); + model.GridPageSize = _adminAreaSettings.GridPageSize; + model.StoreCount = allStores.Count; - //categories var allCategories = _categoryService.GetAllCategories(showHidden: true); var mappedCategories = allCategories.ToDictionary(x => x.Id); foreach (var c in allCategories) { - model.AvailableCategories.Add(new SelectListItem() { Text = c.GetCategoryNameWithPrefix(_categoryService, mappedCategories), Value = c.Id.ToString() }); + model.AvailableCategories.Add(new SelectListItem { Text = c.GetCategoryNameWithPrefix(_categoryService, mappedCategories), Value = c.Id.ToString() }); } - //manufacturers foreach (var m in _manufacturerService.GetAllManufacturers(true)) { - model.AvailableManufacturers.Add(new SelectListItem() { Text = m.Name, Value = m.Id.ToString() }); + model.AvailableManufacturers.Add(new SelectListItem { Text = m.Name, Value = m.Id.ToString() }); + } + + foreach (var s in allStores) + { + model.AvailableStores.Add(new SelectListItem { Text = s.Name, Value = s.Id.ToString() }); } - //product types model.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList(); - model.AvailableProductTypes.Insert(0, new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" }); return View(model); } @@ -3306,9 +3305,9 @@ public ActionResult BulkEditSelect(GridCommand command, BulkEditListModel model) if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); - var searchContext = new ProductSearchContext() + var searchContext = new ProductSearchContext { - CategoryIds = new List() { model.SearchCategoryId }, + StoreId = model.SearchStoreId, ManufacturerId = model.SearchManufacturerId, Keywords = model.SearchProductName, SearchSku = !_catalogSettings.SuppressSkuSearch, @@ -3318,6 +3317,9 @@ public ActionResult BulkEditSelect(GridCommand command, BulkEditListModel model) ProductType = model.SearchProductTypeId > 0 ? (ProductType?)model.SearchProductTypeId : null }; + if (model.SearchCategoryId > 0) + searchContext.CategoryIds.Add(model.SearchCategoryId); + var products = _productService.SearchProducts(searchContext); var gridModel = new GridModel(); @@ -3339,7 +3341,9 @@ public ActionResult BulkEditSelect(GridCommand command, BulkEditListModel model) return productModel; }); + gridModel.Total = products.TotalCount; + return new JsonResult { Data = gridModel @@ -3369,15 +3373,16 @@ public ActionResult BulkEditSave(GridCommand command, product.OldPrice = pModel.OldPrice; product.StockQuantity = pModel.StockQuantity; product.Published = pModel.Published; + _productService.UpdateProduct(product); } } } + if (deletedProducts != null) { foreach (var pModel in deletedProducts) { - //delete var product = _productService.GetProductById(pModel.Id); if (product != null) { diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/BulkEditListModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/BulkEditListModel.cs index 711cc2d322..1850853370 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/BulkEditListModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/BulkEditListModel.cs @@ -11,6 +11,7 @@ public BulkEditListModel() { AvailableCategories = new List(); AvailableManufacturers = new List(); + AvailableStores = new List(); AvailableProductTypes = new List(); } @@ -24,11 +25,18 @@ public BulkEditListModel() [SmartResourceDisplayName("Admin.Catalog.BulkEdit.List.SearchManufacturer")] public int SearchManufacturerId { get; set; } + [SmartResourceDisplayName("Admin.Common.Store.SearchFor")] + public int SearchStoreId { get; set; } + [SmartResourceDisplayName("Admin.Catalog.Products.List.SearchProductType")] public int SearchProductTypeId { get; set; } public IList AvailableProductTypes { get; set; } + + public int GridPageSize { get; set; } + public int StoreCount { get; set; } public IList AvailableCategories { get; set; } public IList AvailableManufacturers { get; set; } + public IList AvailableStores { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/BulkEdit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/BulkEdit.cshtml index 868d78e99f..6eb786b6ba 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/BulkEdit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/BulkEdit.cshtml @@ -1,7 +1,7 @@ @model BulkEditListModel @using Telerik.Web.Mvc.UI @{ - var gridPageSize = EngineContext.Current.Resolve().GridPageSize; + var allString = T("Admin.Common.All").Text; //page title ViewBag.Title = T("Admin.Catalog.BulkEdit").Text; @@ -20,51 +20,63 @@
    @T("Admin.Catalog.BulkEdit.Info")
    - - - - - - - - - - - - - - - - - - - + +
    - @Html.SmartLabelFor(model => model.SearchProductName) - - @Html.EditorFor(model => Model.SearchProductName) -
    - @Html.SmartLabelFor(model => model.SearchCategoryId) - - @Html.DropDownList("SearchCategoryId", Model.AvailableCategories, T("Admin.Common.All").Text) -
    - @Html.SmartLabelFor(model => model.SearchManufacturerId) - - @Html.DropDownList("SearchManufacturerId", Model.AvailableManufacturers, T("Admin.Common.All").Text) -
    - @Html.SmartLabelFor(model => model.SearchProductTypeId) - - @Html.DropDownList("SearchProductTypeId", Model.AvailableProductTypes) -
    + + + + + + + + + @if (Model.StoreCount > 1) + { + + + + + } + + + + + + + + + - - -
    + @Html.SmartLabelFor(model => model.SearchProductName) + + @Html.EditorFor(model => Model.SearchProductName) +
    + @Html.SmartLabelFor(model => model.SearchProductTypeId) + + @Html.DropDownList("SearchProductTypeId", Model.AvailableProductTypes, allString) +
    + @Html.SmartLabelFor(model => model.SearchStoreId) + + @Html.DropDownList("SearchStoreId", Model.AvailableStores, allString) +
    + @Html.SmartLabelFor(model => model.SearchCategoryId) + + @Html.DropDownList("SearchCategoryId", Model.AvailableCategories, allString) +
    + @Html.SmartLabelFor(model => model.SearchManufacturerId) + + @Html.DropDownList("SearchManufacturerId", Model.AvailableManufacturers, allString) +
      - -
    -

    -

    +
    + +
    + +

    + @@ -56,7 +56,7 @@ @Html.SmartLabelFor(model => model.Description) From 6f727e3b90c9637648f846b6240caf758030e5af Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 22 Jul 2015 03:04:58 +0200 Subject: [PATCH 0280/1256] WebScheduler 2 --- .../Domain/Tasks/ScheduleTask.cs | 9 +- .../201507210153338_WebScheduler.resx | 126 ---------------- ... 201507211743009_WebScheduler.Designer.cs} | 2 +- ...ler.cs => 201507211743009_WebScheduler.cs} | 4 + .../201507211743009_WebScheduler.resx | 126 ++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../ServiceCacheConsumer.cs | 6 +- .../SmartStore.Services.csproj | 5 + .../Tasks/ChangeTaskSweeperBaseUrlConsumer.cs | 44 ++++++ .../Tasks/IScheduleTaskService.cs | 15 +- .../Tasks/ITaskExecutor.cs | 10 ++ .../SmartStore.Services/Tasks/ITaskSweeper.cs | 45 ++++++ .../Tasks/InitializeSchedulerFilter.cs | 16 +-- .../SmartStore.Services/Tasks/Job.cs | 4 +- .../Tasks/ScheduleTaskService.cs | 44 ++---- .../Tasks/TaskExecutionContext.cs | 3 + .../SmartStore.Services/Tasks/TaskExecutor.cs | 98 +++++++++++++ .../SmartStore.Services/Tasks/TaskManager.cs | 94 ------------ .../SmartStore.Services/Tasks/TaskSweeper.cs | 135 ++++++++++++++++++ .../DependencyRegistrar.cs | 3 +- .../Controllers/ScheduleTaskController.cs | 2 +- .../Controllers/TaskSchedulerController.cs | 114 ++++----------- 22 files changed, 549 insertions(+), 366 deletions(-) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201507210153338_WebScheduler.resx rename src/Libraries/SmartStore.Data/Migrations/{201507210153338_WebScheduler.Designer.cs => 201507211743009_WebScheduler.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201507210153338_WebScheduler.cs => 201507211743009_WebScheduler.cs} (67%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.resx create mode 100644 src/Libraries/SmartStore.Services/Tasks/ChangeTaskSweeperBaseUrlConsumer.cs create mode 100644 src/Libraries/SmartStore.Services/Tasks/ITaskExecutor.cs create mode 100644 src/Libraries/SmartStore.Services/Tasks/ITaskSweeper.cs create mode 100644 src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs create mode 100644 src/Libraries/SmartStore.Services/Tasks/TaskSweeper.cs diff --git a/src/Libraries/SmartStore.Core/Domain/Tasks/ScheduleTask.cs b/src/Libraries/SmartStore.Core/Domain/Tasks/ScheduleTask.cs index 1bcfa83e4c..8338a2e671 100644 --- a/src/Libraries/SmartStore.Core/Domain/Tasks/ScheduleTask.cs +++ b/src/Libraries/SmartStore.Core/Domain/Tasks/ScheduleTask.cs @@ -13,6 +13,11 @@ public class ScheduleTask : BaseEntity /// public string Name { get; set; } + /// + /// Gets or sets the task alias (an optional key for advanced customization) + /// + public string Alias { get; set; } + /// /// Gets or sets the run period (in seconds) /// @@ -45,8 +50,10 @@ public class ScheduleTask : BaseEntity public string LastError { get; set; } + public bool IsHidden { get; set; } + /// - /// Gets the value indicating whether a task is running + /// Gets a value indicating whether a task is running /// public bool IsRunning { diff --git a/src/Libraries/SmartStore.Data/Migrations/201507210153338_WebScheduler.resx b/src/Libraries/SmartStore.Data/Migrations/201507210153338_WebScheduler.resx deleted file mode 100644 index 54d5c87a9d..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201507210153338_WebScheduler.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201507210153338_WebScheduler.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201507210153338_WebScheduler.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.Designer.cs index d6760e5a26..765d3e0a62 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507210153338_WebScheduler.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class WebScheduler : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201507210153338_WebScheduler"; } + get { return "201507211743009_WebScheduler"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201507210153338_WebScheduler.cs b/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.cs similarity index 67% rename from src/Libraries/SmartStore.Data/Migrations/201507210153338_WebScheduler.cs rename to src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.cs index 441edbc747..d8ba5eb70b 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507210153338_WebScheduler.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.cs @@ -7,14 +7,18 @@ public partial class WebScheduler : DbMigration { public override void Up() { + AddColumn("dbo.ScheduleTask", "Alias", c => c.String(maxLength: 4000)); AddColumn("dbo.ScheduleTask", "NextRunUtc", c => c.DateTime()); + AddColumn("dbo.ScheduleTask", "IsHidden", c => c.Boolean(nullable: false)); CreateIndex("dbo.ScheduleTask", new[] { "NextRunUtc", "Enabled" }, name: "IX_NextRun_Enabled"); } public override void Down() { DropIndex("dbo.ScheduleTask", "IX_NextRun_Enabled"); + DropColumn("dbo.ScheduleTask", "IsHidden"); DropColumn("dbo.ScheduleTask", "NextRunUtc"); + DropColumn("dbo.ScheduleTask", "Alias"); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.resx b/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.resx new file mode 100644 index 0000000000..af5dcde47c --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 85284e4a90..f828c8a076 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -303,9 +303,9 @@ 201507200832223_SortFilterHomepageProducts.cs - - - 201507210153338_WebScheduler.cs + + + 201507211743009_WebScheduler.cs @@ -582,8 +582,8 @@ 201507200832223_SortFilterHomepageProducts.cs - - 201507210153338_WebScheduler.cs + + 201507211743009_WebScheduler.cs diff --git a/src/Libraries/SmartStore.Services/ServiceCacheConsumer.cs b/src/Libraries/SmartStore.Services/ServiceCacheConsumer.cs index 702c0e504e..e3fd3f18b8 100644 --- a/src/Libraries/SmartStore.Services/ServiceCacheConsumer.cs +++ b/src/Libraries/SmartStore.Services/ServiceCacheConsumer.cs @@ -6,6 +6,8 @@ using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; +using SmartStore.Services.Tasks; +using SmartStore.Services.Stores; namespace SmartStore.Services { @@ -20,7 +22,7 @@ public class ServiceCacheConsumer : private readonly ICacheManager _cacheManager; - public ServiceCacheConsumer(Func cache) + public ServiceCacheConsumer(Func cache) { this._cacheManager = cache("static"); } @@ -49,5 +51,5 @@ public void HandleEvent(EntityDeleted eventMessage) { _cacheManager.Remove(STORE_LANGUAGE_MAP_KEY); } - } + } } diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index 36b2cef32b..ebf6732394 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -440,13 +440,18 @@ + + + + + diff --git a/src/Libraries/SmartStore.Services/Tasks/ChangeTaskSweeperBaseUrlConsumer.cs b/src/Libraries/SmartStore.Services/Tasks/ChangeTaskSweeperBaseUrlConsumer.cs new file mode 100644 index 0000000000..c02821c5f7 --- /dev/null +++ b/src/Libraries/SmartStore.Services/Tasks/ChangeTaskSweeperBaseUrlConsumer.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using SmartStore.Core.Domain.Stores; +using SmartStore.Core.Events; +using SmartStore.Services.Stores; + +namespace SmartStore.Services.Tasks +{ + public class ChangeTaskSweeperBaseUrlConsumer : + IConsumer>, + IConsumer>, + IConsumer> + { + private readonly ITaskSweeper _taskSweeper; + private readonly IStoreService _storeService; + private readonly HttpContextBase _httpContext; + + public ChangeTaskSweeperBaseUrlConsumer(ITaskSweeper taskSweeper, IStoreService storeService, HttpContextBase httpContext) + { + this._taskSweeper = taskSweeper; + this._storeService = storeService; + this._httpContext = httpContext; + } + + public void HandleEvent(EntityInserted eventMessage) + { + _taskSweeper.SetBaseUrl(_storeService, _httpContext); + } + + public void HandleEvent(EntityUpdated eventMessage) + { + _taskSweeper.SetBaseUrl(_storeService, _httpContext); + } + + public void HandleEvent(EntityDeleted eventMessage) + { + _taskSweeper.SetBaseUrl(_storeService, _httpContext); + } + } +} diff --git a/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs b/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs index fcd853d341..0d53aa9010 100644 --- a/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs +++ b/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs @@ -35,6 +35,12 @@ public partial interface IScheduleTaskService /// Tasks IList GetAllTasks(bool showHidden = false); + /// + /// Gets all pending tasks + /// + /// Tasks + IList GetPendingTasks(); + /// /// Inserts a task /// @@ -47,10 +53,11 @@ public partial interface IScheduleTaskService /// Task void UpdateTask(ScheduleTask task); - /// - /// Ensures that a task is not marked as running - /// - /// Task identifier + /// + /// Ensures that a task is not marked as running (normalize last start and end date). + /// + /// Task identifier + /// Problem can be reproduced by inserting a news object without a language identifier. void EnsureTaskIsNotRunning(int taskId); } } diff --git a/src/Libraries/SmartStore.Services/Tasks/ITaskExecutor.cs b/src/Libraries/SmartStore.Services/Tasks/ITaskExecutor.cs new file mode 100644 index 0000000000..b14c0e7c22 --- /dev/null +++ b/src/Libraries/SmartStore.Services/Tasks/ITaskExecutor.cs @@ -0,0 +1,10 @@ +using System; +using SmartStore.Core.Domain.Tasks; + +namespace SmartStore.Services.Tasks +{ + public interface ITaskExecutor + { + void Execute(ScheduleTask task, bool throwOnError = false); + } +} diff --git a/src/Libraries/SmartStore.Services/Tasks/ITaskSweeper.cs b/src/Libraries/SmartStore.Services/Tasks/ITaskSweeper.cs new file mode 100644 index 0000000000..87b90bfdbf --- /dev/null +++ b/src/Libraries/SmartStore.Services/Tasks/ITaskSweeper.cs @@ -0,0 +1,45 @@ +using System; +using System.Web; +using System.Linq; +using SmartStore.Core; +using SmartStore.Services.Stores; + +namespace SmartStore.Services.Tasks +{ + public interface ITaskSweeper + { + TimeSpan Interval { get; set; } + string BaseUrl { get; set; } + bool IsRunning { get; } + + void Start(); + void Stop(); + void ExecuteSingleTask(int scheduleTaskId); + bool VerifyAuthToken(string authToken); + } + + public static class ITaskSweeperExtensions + { + internal static void SetBaseUrl(this ITaskSweeper sweeper, IStoreService storeService, HttpContextBase httpContext) + { + var path = VirtualPathUtility.ToAbsolute("~/TaskScheduler"); + string url = ""; + + if (!httpContext.Request.IsLocal) + { + var defaultStore = storeService.GetAllStores().FirstOrDefault(x => storeService.IsStoreDataValid(x)); + if (defaultStore != null) + { + url = defaultStore.Url; + } + } + + if (url.IsEmpty()) + { + url = WebHelper.GetAbsoluteUrl(path, httpContext.Request); + } + + sweeper.BaseUrl = url; + } + } +} diff --git a/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs b/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs index a7aa3228ed..fa4b435ab8 100644 --- a/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs +++ b/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs @@ -34,20 +34,12 @@ public void OnAuthorization(AuthorizationContext filterContext) taskService.UpdateTask(task); } - var urlHelper = new UrlHelper(filterContext.RequestContext); - var path = urlHelper.Action("Sweep", "TaskScheduler"); + var taskSweeper = EngineContext.Current.Resolve(); - var request = filterContext.HttpContext.Request; + taskSweeper.SetBaseUrl(EngineContext.Current.Resolve(), filterContext.HttpContext); - var taskManager = EngineContext.Current.Resolve(); - var url = WebHelper.GetAbsoluteUrl(path, request); - - if (!request.IsLocal) - { - // TODO: get default store url - } - - taskManager.Start(url, 15 /* seconds */); + taskSweeper.Interval = TimeSpan.FromSeconds(10); + taskSweeper.Start(); var eventPublisher = EngineContext.Current.Resolve(); eventPublisher.Publish(new AppInitScheduledTasksEvent { ScheduledTasks = tasks }); diff --git a/src/Libraries/SmartStore.Services/Tasks/Job.cs b/src/Libraries/SmartStore.Services/Tasks/Job.cs index c38203e95c..ce7c13043b 100644 --- a/src/Libraries/SmartStore.Services/Tasks/Job.cs +++ b/src/Libraries/SmartStore.Services/Tasks/Job.cs @@ -35,7 +35,7 @@ public Job(ScheduleTask task) this.StopOnError = task.StopOnError; this.Name = task.Name; this.LastError = task.LastError; - this.IsRunning = task.IsRunning; //task.LastStartUtc.GetValueOrDefault() > task.LastEndUtc.GetValueOrDefault(); + this.IsRunning = task.IsRunning; } private ITask CreateTask(ILifetimeScope scope) @@ -101,7 +101,7 @@ public void Execute( scheduleTaskService.UpdateTask(scheduleTask); } - //execute task + // execute task var ctx = new TaskExecutionContext { LifetimeScope = scope, diff --git a/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs b/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs index 25f8fe6f98..480da73574 100644 --- a/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs +++ b/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs @@ -28,10 +28,6 @@ public ScheduleTaskService(IRepository taskRepository) #region Methods - /// - /// Deletes a task - /// - /// Task public virtual void DeleteTask(ScheduleTask task) { if (task == null) @@ -40,11 +36,6 @@ public virtual void DeleteTask(ScheduleTask task) _taskRepository.Delete(task); } - /// - /// Gets a task - /// - /// Task identifier - /// Task public virtual ScheduleTask GetTaskById(int taskId) { if (taskId == 0) @@ -53,11 +44,6 @@ public virtual ScheduleTask GetTaskById(int taskId) return _taskRepository.GetById(taskId); } - /// - /// Gets a task by its type - /// - /// Task type - /// Task public virtual ScheduleTask GetTaskByType(string type) { try @@ -80,11 +66,6 @@ public virtual ScheduleTask GetTaskByType(string type) return null; } - /// - /// Gets all tasks - /// - /// A value indicating whether to show hidden records - /// Tasks public virtual IList GetAllTasks(bool showHidden = false) { var query = _taskRepository.Table; @@ -98,10 +79,18 @@ public virtual IList GetAllTasks(bool showHidden = false) return tasks; } - /// - /// Inserts a task - /// - /// Task + public virtual IList GetPendingTasks() + { + var now = DateTime.UtcNow; + + var query = from t in _taskRepository.Table + where t.Enabled && t.NextRunUtc.HasValue && t.NextRunUtc <= now + orderby t.Seconds + select t; + + return query.ToList(); + } + public virtual void InsertTask(ScheduleTask task) { if (task == null) @@ -110,10 +99,6 @@ public virtual void InsertTask(ScheduleTask task) _taskRepository.Insert(task); } - /// - /// Updates the task - /// - /// Task public virtual void UpdateTask(ScheduleTask task) { if (task == null) @@ -122,11 +107,6 @@ public virtual void UpdateTask(ScheduleTask task) _taskRepository.Update(task); } - /// - /// Ensures that a task is not marked as running (normalize last start and end date). - /// - /// Task identifier - /// Problem can be reproduced by inserting a news object without a language identifier. public virtual void EnsureTaskIsNotRunning(int taskId) { try diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs b/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs index 074a7e619a..7b2074f2f2 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading; using Autofac; +using SmartStore.Core.Domain.Tasks; namespace SmartStore.Services.Tasks { @@ -22,5 +23,7 @@ public class TaskExecutionContext /// You can use ThrowIfCancellationRequested() for a hard or IsCancellationRequested for a soft break. /// public CancellationToken CancellationToken { get; internal set; } + + public ScheduleTask ScheduleTask { get; set; } } } diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs b/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs new file mode 100644 index 0000000000..57c7f675b8 --- /dev/null +++ b/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs @@ -0,0 +1,98 @@ +using SmartStore.Core.Data; +using SmartStore.Core.Domain.Tasks; +using SmartStore.Core.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SmartStore.Services.Tasks +{ + + public class TaskExecutor : ITaskExecutor + { + private readonly IScheduleTaskService _scheduledTaskService; + private readonly Func _taskResolver; + + public TaskExecutor(IScheduleTaskService scheduledTaskService, Func taskResolver) + { + this._scheduledTaskService = scheduledTaskService; + this._taskResolver = taskResolver; + + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + public void Execute(ScheduleTask task, bool throwOnError = false) + { + if (task.IsRunning) + return; // TODO: Really? + + bool faulted = false; + string lastError = null; + ITask instance = null; + + try + { + instance = CreateTaskInstance(task); + + task.LastStartUtc = DateTime.UtcNow; + task.LastEndUtc = null; + task.NextRunUtc = null; + _scheduledTaskService.UpdateTask(task); + + var ctx = new TaskExecutionContext + { + ScheduleTask = task + // TODO: Remove obsolete properties + }; + + instance.Execute(ctx); + } + catch (Exception ex) + { + faulted = true; + Logger.Error(string.Format("Error while running scheduled task '{0}'. {1}", task.Name, ex.Message), ex); + lastError = ex.Message.Truncate(995, "..."); + if (throwOnError) + { + throw; + } + } + finally + { + var now = DateTime.UtcNow; + task.LastError = lastError; + task.LastEndUtc = now; + + if (faulted) + { + if (task.StopOnError || instance == null) + { + task.Enabled = false; + } + } + else + { + task.LastSuccessUtc = now; + } + + if (task.Enabled) + { + task.NextRunUtc = task.LastStartUtc.Value.AddSeconds(task.Seconds); + } + + _scheduledTaskService.UpdateTask(task); + } + } + + private ITask CreateTaskInstance(ScheduleTask task) + { + var type = Type.GetType(task.Type); + return _taskResolver(type); + } + } + +} diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs b/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs index 4b1b3a9c5d..d570445604 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs @@ -4,104 +4,10 @@ using SmartStore.Core.Events; using SmartStore.Core.Infrastructure; using SmartStore.Core.Plugins; -using System.Threading; -using System.Net; -using System; namespace SmartStore.Services.Tasks { - - public class DefaultTaskManager : DisposableObject - { - private bool _isInitialized; - private bool _isSuspended; - private string _url; - private Timer _timer; - private bool _disposed; - - public void Start(string url, int interval) - { - Guard.ArgumentNotEmpty(() => url); - Guard.ArgumentNotZero(interval, "interval"); - - this._url = url; - this._timer = new Timer(new TimerCallback(this.CallEndpoint), null, interval * 1000, interval * 1000); - } - - public void ChangeUrl(string url) - { - Guard.ArgumentNotEmpty(() => url); - - this._url = url; - } - - public void ChangeInterval(int interval) - { - this._timer.Change(interval * 1000, interval * 1000); - } - - public void Suspend() - { - _isSuspended = true; - } - - public void Resume() - { - _isSuspended = false; - } - - public bool IsInitialized - { - get { return _isInitialized; } - } - public bool IsRunning - { - get { return _isInitialized && !_isSuspended; } - } - - public bool VerifyAuthToken(string authToken) - { - // TODO: Verify! - return true; - } - - private void CallEndpoint(object state) - { - var req = (HttpWebRequest)WebRequest.Create(_url); - req.UserAgent = "SmartStore.NET"; - req.Headers.Add("X-AUTH-TOKEN", Guid.NewGuid().ToString()); - req.Method = "POST"; - req.ContentType = "text/plain"; - req.ContentLength = 0; - - req.GetResponseAsync().ContinueWith(t => t.Result.Dispose()); - - //using (var resp = (HttpWebResponse)req.GetResponse()) - //{ - // //using (var stream = resp.GetResponseStream()) - // //{ - // //} - //} - } - - protected override void OnDispose(bool disposing) - { - if (disposing) - { - if ((this._timer != null) && !this._disposed) - { - lock (this) - { - this._timer.Dispose(); - this._timer = null; - this._disposed = true; - } - } - } - } - } - /// /// Represents task manager /// diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskSweeper.cs b/src/Libraries/SmartStore.Services/Tasks/TaskSweeper.cs new file mode 100644 index 0000000000..372bd34e92 --- /dev/null +++ b/src/Libraries/SmartStore.Services/Tasks/TaskSweeper.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using System.Timers; + +namespace SmartStore.Services.Tasks +{ + + public class TaskSweeper : DisposableObject, ITaskSweeper + { + private string _baseUrl; + private Timer _timer; + private readonly ConcurrentDictionary _authTokens = new ConcurrentDictionary(); + + public TaskSweeper() + { + _timer = new Timer(TimeSpan.FromMinutes(1).TotalMilliseconds); + _timer.Elapsed += Elapsed; + } + + public TimeSpan Interval + { + get { return TimeSpan.FromMilliseconds(_timer.Interval); } + set { _timer.Interval = value.TotalMilliseconds; } + } + + public string BaseUrl + { + get { return _baseUrl; } + set + { + CheckUrl(value); + _baseUrl = value.TrimEnd('/', '\\'); + } + } + + public void Start() + { + lock (_timer) + { + CheckUrl(_baseUrl); + _timer.Start(); + } + } + + public void Stop() + { + lock (_timer) + { + _timer.Stop(); + } + } + + public bool IsRunning + { + get { return _timer.Enabled; } + } + + public bool VerifyAuthToken(string authToken) + { + if (authToken.IsEmpty()) + return false; + + bool val = false; + return _authTokens.TryRemove(authToken, out val); + } + + public void ExecuteSingleTask(int scheduleTaskId) + { + CallEndpoint(_baseUrl + "/Execute/{0}".FormatInvariant(scheduleTaskId)); + } + + private void Elapsed(object sender, ElapsedEventArgs e) + { + if (!System.Threading.Monitor.TryEnter(_timer)) + return; + + try + { + if (_timer.Enabled) + { + CallEndpoint(_baseUrl + "/Sweep"); + } + } + finally + { + System.Threading.Monitor.Exit(_timer); + } + } + + private void CallEndpoint(string url) + { + var req = (HttpWebRequest)WebRequest.Create(url); + req.UserAgent = "SmartStore.NET"; + req.Method = "POST"; + req.ContentType = "text/plain"; + req.ContentLength = 0; + + string authToken = Guid.NewGuid().ToString(); + _authTokens.TryAdd(authToken, true); + req.Headers.Add("X-AUTH-TOKEN", authToken); + + req.GetResponseAsync().ContinueWith(t => + { + if (t.IsFaulted) + { + // TODO: Now what?! Disable timer? + } + t.Result.Dispose(); + }); + } + + private void CheckUrl(string url) + { + if (!url.IsWebUrl()) + { + throw Error.InvalidOperation("A valid base url is required for the background task scheduler."); + } + } + + protected override void OnDispose(bool disposing) + { + if (disposing) + { + _timer.Dispose(); + } + } + + } + +} diff --git a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs index 68d016338e..c61afef079 100644 --- a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs +++ b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs @@ -939,7 +939,8 @@ protected override void Load(ContainerBuilder builder) if (!DataSettings.DatabaseIsInstalled()) return; - builder.RegisterInstance(new DefaultTaskManager()).SingleInstance(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().InstancePerRequest(); var taskTypes = _typeFinder.FindClassesOfType(ignoreInactivePlugins: true).ToList(); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs index d5d6110dee..c2ab804116 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs @@ -72,7 +72,7 @@ protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) LastEndUtc = task.LastEndUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastEndUtc.Value, DateTimeKind.Utc).ToString("G") : "", LastSuccessUtc = task.LastSuccessUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastSuccessUtc.Value, DateTimeKind.Utc).ToString("G") : "", LastError = task.LastError.EmptyNull(), - IsRunning = task.IsRunning, //task.LastStartUtc.GetValueOrDefault() > task.LastEndUtc.GetValueOrDefault(), + IsRunning = task.IsRunning, Duration = "" }; diff --git a/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs b/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs index 91d8493ad3..8c664c376a 100644 --- a/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs @@ -1,124 +1,68 @@ -using SmartStore.Core.Data; -using SmartStore.Core.Domain.Tasks; -using SmartStore.Core.Localization; -using SmartStore.Core.Logging; -using SmartStore.Services; -using SmartStore.Services.Tasks; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; +using SmartStore.Core.Domain.Tasks; +using SmartStore.Services.Tasks; +using SmartStore.Web.Framework.Controllers; +using SmartStore.Services.Security; +using SmartStore.Services; namespace SmartStore.Web.Controllers { public class TaskSchedulerController : Controller { - private readonly DefaultTaskManager _taskManager; - private readonly IRepository _tasksRepository; - private readonly Func _taskResolver; + private readonly ITaskSweeper _taskSweeper; + private readonly IScheduleTaskService _scheduledTaskService; + private readonly ITaskExecutor _taskExecutor; private readonly ICommonServices _services; public TaskSchedulerController( - DefaultTaskManager taskManager, - IRepository tasksRepository, - Func taskResolver, + ITaskSweeper taskSweeper, + IScheduleTaskService scheduledTaskService, + ITaskExecutor taskExecutor, ICommonServices services) { - this._taskManager = taskManager; - this._tasksRepository = tasksRepository; - this._taskResolver = taskResolver; + this._taskSweeper = taskSweeper; + this._scheduledTaskService = scheduledTaskService; + this._taskExecutor = taskExecutor; this._services = services; - - T = NullLocalizer.Instance; - Logger = NullLogger.Instance; } - public Localizer T { get; set; } - - public ILogger Logger { get; set; } - [HttpPost] public ActionResult Sweep() { - var authToken = Request.Headers["X-AUTH-TOKEN"]; - if (authToken.IsEmpty()) - return new HttpUnauthorizedResult(); - - if (!_taskManager.VerifyAuthToken(authToken)) + if (!_taskSweeper.VerifyAuthToken(Request.Headers["X-AUTH-TOKEN"])) return new HttpUnauthorizedResult(); - var pendingTasks = GetPendingTasks(); + var pendingTasks = _scheduledTaskService.GetPendingTasks(); foreach (var task in pendingTasks) { - var instance = CreateTaskInstance(task); - ExecuteTask(instance, task); + _taskExecutor.Execute(task); } return Content("{0} tasks executed".FormatInvariant(pendingTasks.Count)); } - private ICollection GetPendingTasks() - { - var now = DateTime.UtcNow; - - var query = from t in _tasksRepository.Table - where t.Enabled && t.NextRunUtc.HasValue && t.NextRunUtc <= now - orderby t.Seconds - select t; - - return query.ToList(); - } - - private ITask CreateTaskInstance(ScheduleTask task) - { - var type = Type.GetType(task.Type); - return _taskResolver(type); - } - - private void ExecuteTask(ITask instance, ScheduleTask task) + [HttpPost] + public ActionResult Execute(int id /* taskId */) { - bool faulted = false; - string lastError = null; + if (!_taskSweeper.VerifyAuthToken(Request.Headers["X-AUTH-TOKEN"])) + return new HttpUnauthorizedResult(); - try - { - task.NextRunUtc = null; - task.LastStartUtc = DateTime.UtcNow; - _tasksRepository.Update(task); + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageScheduleTasks)) + return new HttpUnauthorizedResult(); - // EXECUTE - } - catch (Exception ex) - { - Logger.Error(string.Format("Error while running the '{0}' schedule task. {1}", task.Name, ex.Message), ex); - faulted = true; - lastError = ex.Message.Truncate(995, "..."); - } - finally - { - var now = DateTime.UtcNow; - task.LastError = lastError; - task.LastEndUtc = now; - - if (faulted) - { - task.Enabled = task.StopOnError; - } - else - { - task.LastSuccessUtc = now; - } + var task = _scheduledTaskService.GetTaskById(id); + if (task == null) + return HttpNotFound(); - if (task.Enabled) - { - task.NextRunUtc = task.LastStartUtc.Value.AddSeconds(task.Seconds); - } + _taskExecutor.Execute(task); - _tasksRepository.Update(task); - } + return Content("Task '{0}' executed".FormatCurrent(task.Name)); } } From 20b93a25e13a6eb6f5ecc6b2e71b58497bae0b97 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 22 Jul 2015 04:38:32 +0200 Subject: [PATCH 0281/1256] WebScheduler 3 --- .../Common/KeepAliveTask.cs | 38 +--- .../SmartStore.Services.csproj | 3 - .../SmartStore.Services/Tasks/ITaskSweeper.cs | 3 +- .../Tasks/InitializeSchedulerFilter.cs | 2 - .../SmartStore.Services/Tasks/Job.cs | 205 ------------------ .../Tasks/TaskExecutionContext.cs | 20 +- .../SmartStore.Services/Tasks/TaskManager.cs | 120 ---------- .../SmartStore.Services/Tasks/TaskSweeper.cs | 12 + .../SmartStore.Services/Tasks/TaskThread.cs | 177 --------------- .../StaticFileGenerationTask.cs | 16 +- .../Plugins/FeedPluginHelper.cs | 49 +---- .../Controllers/ScheduleTaskController.cs | 51 +---- .../Models/Tasks/ScheduleTaskModel.cs | 3 + .../Views/ScheduleTask/List.cshtml | 4 +- .../Controllers/KeepAliveController.cs | 12 - .../Controllers/TaskSchedulerController.cs | 3 - .../SmartStore.Web/Global.asax.cs | 4 - .../SmartStore.Web/SmartStore.Web.csproj | 1 - 18 files changed, 55 insertions(+), 668 deletions(-) delete mode 100644 src/Libraries/SmartStore.Services/Tasks/Job.cs delete mode 100644 src/Libraries/SmartStore.Services/Tasks/TaskManager.cs delete mode 100644 src/Libraries/SmartStore.Services/Tasks/TaskThread.cs delete mode 100644 src/Presentation/SmartStore.Web/Controllers/KeepAliveController.cs diff --git a/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs b/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs index 74a382ccae..a7ae21aa9a 100644 --- a/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs +++ b/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs @@ -1,5 +1,6 @@ using System; using System.Net; +using System.Threading.Tasks; using SmartStore.Core; using SmartStore.Services.Tasks; @@ -10,45 +11,10 @@ namespace SmartStore.Services.Common /// public partial class KeepAliveTask : ITask { - private readonly IStoreContext _storeContext; - - public KeepAliveTask(IStoreContext storeContext) - { - this._storeContext = storeContext; - } public void Execute(TaskExecutionContext ctx) { - var storeUrl = _storeContext.CurrentStore.Url.TrimEnd('\\').EnsureEndsWith("/"); - string url = storeUrl + "keepalive/index"; - - try - { - using (var wc = new WebClient()) - { - // FAKE a user-agent - wc.Headers.Add("user-agent", @"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"); - if (!url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && !url.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) - { - url = "http://" + url; - } - wc.DownloadString(url); - } - } - catch (WebException ex) - { - if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null) - { - var resp = (HttpWebResponse)ex.Response; - if (resp.StatusCode == HttpStatusCode.NotFound) // HTTP 404 - { - // the page was not found (as it can be expected with some webservers) - return; - } - } - // throw any other exception - this should not occur - throw; - } + // do absolutely nothing } } } diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index ebf6732394..d7056f00dc 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -447,12 +447,9 @@ - - - diff --git a/src/Libraries/SmartStore.Services/Tasks/ITaskSweeper.cs b/src/Libraries/SmartStore.Services/Tasks/ITaskSweeper.cs index 87b90bfdbf..57b0ea4b09 100644 --- a/src/Libraries/SmartStore.Services/Tasks/ITaskSweeper.cs +++ b/src/Libraries/SmartStore.Services/Tasks/ITaskSweeper.cs @@ -3,10 +3,11 @@ using System.Linq; using SmartStore.Core; using SmartStore.Services.Stores; +using System.Web.Hosting; namespace SmartStore.Services.Tasks { - public interface ITaskSweeper + public interface ITaskSweeper : IRegisteredObject { TimeSpan Interval { get; set; } string BaseUrl { get; set; } diff --git a/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs b/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs index fa4b435ab8..0c38de3322 100644 --- a/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs +++ b/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs @@ -37,8 +37,6 @@ public void OnAuthorization(AuthorizationContext filterContext) var taskSweeper = EngineContext.Current.Resolve(); taskSweeper.SetBaseUrl(EngineContext.Current.Resolve(), filterContext.HttpContext); - - taskSweeper.Interval = TimeSpan.FromSeconds(10); taskSweeper.Start(); var eventPublisher = EngineContext.Current.Resolve(); diff --git a/src/Libraries/SmartStore.Services/Tasks/Job.cs b/src/Libraries/SmartStore.Services/Tasks/Job.cs deleted file mode 100644 index ce7c13043b..0000000000 --- a/src/Libraries/SmartStore.Services/Tasks/Job.cs +++ /dev/null @@ -1,205 +0,0 @@ -using System; -using System.Threading; -using Autofac; -using SmartStore.Core.Domain.Tasks; -using SmartStore.Core.Infrastructure; -using SmartStore.Core.Logging; - -namespace SmartStore.Services.Tasks -{ - /// - /// Task - /// - /// - /// Formerly Task. Had to rename to Job in order to prevent naming conflicts with System.Threading.Tasks.Task - /// - public partial class Job - { - - /// - /// Ctor for Task - /// - private Job() - { - this.Enabled = true; - } - - /// - /// Ctor for Task - /// - /// Task - public Job(ScheduleTask task) - { - this.Type = task.Type; - this.Enabled = task.Enabled; - this.StopOnError = task.StopOnError; - this.Name = task.Name; - this.LastError = task.LastError; - this.IsRunning = task.IsRunning; - } - - private ITask CreateTask(ILifetimeScope scope) - { - ITask task = null; - if (this.Enabled) - { - var type2 = System.Type.GetType(this.Type); - if (type2 != null) - { - object instance; - if (!EngineContext.Current.ContainerManager.TryResolve(type2, scope, out instance)) - { - // not resolved - instance = EngineContext.Current.ContainerManager.ResolveUnregistered(type2, scope); - } - task = instance as ITask; - } - } - return task; - } - - /// - /// Executes the task - /// - /// - /// The caller is responsible for disposing the lifetime scope - /// - public void Execute(ILifetimeScope scope = null, bool throwOnError = false) - { - Execute(CancellationToken.None, scope, throwOnError); - } - - /// - /// Executes the task - /// - /// - /// The caller is responsible for disposing the lifetime scope - /// - public void Execute( - CancellationToken cancellationToken, - ILifetimeScope scope = null, - bool throwOnError = false) - { - this.IsRunning = true; - var faulted = false; - scope = scope ?? EngineContext.Current.ContainerManager.Scope(); - - try - { - var task = this.CreateTask(scope); - if (task != null) - { - this.LastStartUtc = DateTime.UtcNow; - - var scheduleTaskService = scope.Resolve(); - var scheduleTask = scheduleTaskService.GetTaskByType(this.Type); - - if (scheduleTask != null) - { - //update appropriate datetime properties - scheduleTask.LastStartUtc = this.LastStartUtc; - scheduleTaskService.UpdateTask(scheduleTask); - } - - // execute task - var ctx = new TaskExecutionContext - { - LifetimeScope = scope, - CancellationToken = cancellationToken - }; - - task.Execute(ctx); - - ctx.CancellationToken.ThrowIfCancellationRequested(); - this.LastEndUtc = this.LastSuccessUtc = DateTime.UtcNow; - this.LastError = null; - } - else - { - faulted = true; - this.LastError = "Could not create task instance"; - } - } - catch (Exception ex) - { - faulted = true; - this.Enabled = !this.StopOnError; - this.LastEndUtc = DateTime.UtcNow; - this.LastError = ex.Message.Truncate(995, "..."); - - //log error - var logger = scope.Resolve(); - logger.Error(string.Format("Error while running the '{0}' schedule task. {1}", this.Name, ex.Message), ex); - if (throwOnError) - { - throw; - } - } - finally - { - var scheduleTaskService = scope.Resolve(); - var scheduleTask = scheduleTaskService.GetTaskByType(this.Type); - - if (scheduleTask != null) - { - // update appropriate properties - scheduleTask.LastError = this.LastError; - scheduleTask.LastEndUtc = this.LastEndUtc; - if (!faulted) - { - scheduleTask.LastSuccessUtc = this.LastSuccessUtc; - } - - scheduleTaskService.UpdateTask(scheduleTask); - } - - this.IsRunning = false; - } - } - - /// - /// A value indicating whether a task is running - /// - public bool IsRunning { get; private set; } - - /// - /// Datetime of the last start - /// - public DateTime? LastStartUtc { get; private set; } - - /// - /// Datetime of the last end - /// - public DateTime? LastEndUtc { get; private set; } - - /// - /// Datetime of the last success - /// - public DateTime? LastSuccessUtc { get; private set; } - - /// - /// Message of the last error - /// - public string LastError { get; private set; } - - /// - /// A value indicating type of the task - /// - public string Type { get; private set; } - - /// - /// A value indicating whether to stop task on error - /// - public bool StopOnError { get; private set; } - - /// - /// Get the task name - /// - public string Name { get; private set; } - - /// - /// A value indicating whether the task is enabled - /// - public bool Enabled { get; set; } - } -} diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs b/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs index 7b2074f2f2..6012a4dbb7 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs @@ -12,17 +12,17 @@ namespace SmartStore.Services.Tasks /// public class TaskExecutionContext { - /// - /// The shared instance created - /// before the execution of the task's background thread. - /// - public object LifetimeScope { get; internal set; } + /// + /// The shared instance created + /// before the execution of the task's background thread. + /// + public object LifetimeScope { get; internal set; } - /// - /// A cancellation token for the running task. - /// You can use ThrowIfCancellationRequested() for a hard or IsCancellationRequested for a soft break. - /// - public CancellationToken CancellationToken { get; internal set; } + /// + /// A cancellation token for the running task. + /// You can use ThrowIfCancellationRequested() for a hard or IsCancellationRequested for a soft break. + /// + public CancellationToken CancellationToken { get; internal set; } public ScheduleTask ScheduleTask { get; set; } } diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs b/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs deleted file mode 100644 index d570445604..0000000000 --- a/src/Libraries/SmartStore.Services/Tasks/TaskManager.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using SmartStore.Core.Events; -using SmartStore.Core.Infrastructure; -using SmartStore.Core.Plugins; - -namespace SmartStore.Services.Tasks -{ - - /// - /// Represents task manager - /// - public partial class TaskManager - { - private static readonly TaskManager _taskManager = new TaskManager(); - private readonly List _taskThreads = new List(); - - private TaskManager() - { - } - - /// - /// Initializes the task manager with the property values specified in the configuration file. - /// - public void Initialize() - { - this._taskThreads.Clear(); - - var taskService = EngineContext.Current.Resolve(); - var scheduleTasks = taskService.GetAllTasks(); - - var eventPublisher = EngineContext.Current.Resolve(); - eventPublisher.Publish(new AppInitScheduledTasksEvent { - ScheduledTasks = scheduleTasks - }); - - // group by threads with the same seconds - foreach (var scheduleTaskGrouped in scheduleTasks.GroupBy(x => x.Seconds)) - { - // create a thread - var taskThread = new TaskThread(); - taskThread.Seconds = scheduleTaskGrouped.Key; - - foreach (var scheduleTask in scheduleTaskGrouped) - { - var taskType = System.Type.GetType(scheduleTask.Type); - if (taskType != null) - { - var isActiveModule = PluginManager.IsActivePluginAssembly(taskType.Assembly); - if (isActiveModule) - { - var job = new Job(scheduleTask); - taskThread.AddJob(job); - } - } - } - - if (taskThread.HasJobs) - { - this._taskThreads.Add(taskThread); - } - } - - - //one thread, one task - //foreach (var scheduleTask in scheduleTasks) - //{ - // var taskThread = new TaskThread(scheduleTask); - // this._taskThreads.Add(taskThread); - // var task = new Task(scheduleTask); - // taskThread.AddTask(task); - //} - } - - /// - /// Starts the task manager - /// - public void Start() - { - foreach (var taskThread in this._taskThreads) - { - taskThread.InitTimer(); - } - } - - /// - /// Stops the task manager - /// - public void Stop() - { - foreach (var taskThread in this._taskThreads) - { - taskThread.Dispose(); - } - } - - /// - /// Gets the task mamanger instance - /// - public static TaskManager Instance - { - get - { - return _taskManager; - } - } - - /// - /// Gets a list of task threads of this task manager - /// - public IList TaskThreads - { - get - { - return new ReadOnlyCollection(this._taskThreads); - } - } - } -} diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskSweeper.cs b/src/Libraries/SmartStore.Services/Tasks/TaskSweeper.cs index 372bd34e92..babbbedfef 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskSweeper.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskSweeper.cs @@ -6,6 +6,7 @@ using System.Text; using System.Threading.Tasks; using System.Timers; +using System.Web.Hosting; namespace SmartStore.Services.Tasks { @@ -14,12 +15,15 @@ public class TaskSweeper : DisposableObject, ITaskSweeper { private string _baseUrl; private Timer _timer; + private bool _shuttingDown; private readonly ConcurrentDictionary _authTokens = new ConcurrentDictionary(); public TaskSweeper() { _timer = new Timer(TimeSpan.FromMinutes(1).TotalMilliseconds); _timer.Elapsed += Elapsed; + + HostingEnvironment.RegisterObject(this); } public TimeSpan Interval @@ -94,6 +98,9 @@ private void Elapsed(object sender, ElapsedEventArgs e) private void CallEndpoint(string url) { + if (_shuttingDown) + return; + var req = (HttpWebRequest)WebRequest.Create(url); req.UserAgent = "SmartStore.NET"; req.Method = "POST"; @@ -130,6 +137,11 @@ protected override void OnDispose(bool disposing) } } + void IRegisteredObject.Stop(bool immediate) + { + _shuttingDown = true; + HostingEnvironment.UnregisterObject(this); + } } } diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs b/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs deleted file mode 100644 index b165daaeec..0000000000 --- a/src/Libraries/SmartStore.Services/Tasks/TaskThread.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using SmartStore.Core.Async; -using SmartStore.Core.Domain.Tasks; - -namespace SmartStore.Services.Tasks -{ - /// - /// Represents task thread - /// - public partial class TaskThread : IDisposable - { - private Timer _timer; - private bool _disposed; - private DateTime _startedUtc; - private bool _isRunning; - private readonly Dictionary _jobs; - private int _seconds; - - internal TaskThread() - { - this._jobs = new Dictionary(); - this._seconds = 10 * 60; - } - - internal TaskThread(ScheduleTask scheduleTask) - { - this._jobs = new Dictionary(); - this._seconds = scheduleTask.Seconds; - this._isRunning = false; - } - - private void Run() - { - if (_seconds <=0) - return; - - this._startedUtc = DateTime.UtcNow; - this._isRunning = true; - - var jobs = _jobs.Values - .Select(job => AsyncRunner.Run((c, ct) => job.Execute(ct, c))) - .ToArray(); - - try - { - Task.WaitAll(jobs); - } - catch { } - - this._isRunning = false; - } - - private void TimerHandler(object state) - { - this._timer.Change(-1, -1); - this.Run(); - this._timer.Change(this.Interval, this.Interval); - } - - /// - /// Disposes the instance - /// - public void Dispose() - { - if ((this._timer != null) && !this._disposed) - { - lock (this) - { - this._timer.Dispose(); - this._timer = null; - this._disposed = true; - } - } - } - - /// - /// Inits a timer - /// - public void InitTimer() - { - if (this._timer == null) - { - this._timer = new Timer(new TimerCallback(this.TimerHandler), null, this.Interval, this.Interval); - } - } - - /// - /// Adds a job to the thread - /// - /// The task to be added - public void AddJob(Job job) - { - if (!this._jobs.ContainsKey(job.Name)) - { - this._jobs.Add(job.Name, job); - } - } - - - /// - /// Gets or sets the interval in seconds at which to run the jobs - /// - public int Seconds - { - get - { - return this._seconds; - } - internal set - { - this._seconds = value; - } - } - - /// - /// Get a datetime when thread has been started - /// - public DateTime Started - { - get - { - return this._startedUtc; - } - } - - /// - /// Get a value indicating whether thread is running - /// - public bool IsRunning - { - get - { - return this._isRunning; - } - } - - /// - /// Get a list of jobs - /// - public IList Jobs - { - get - { - var list = new List(); - foreach (var jobs in this._jobs.Values) - { - list.Add(jobs); - } - return new ReadOnlyCollection(list); - } - } - - public bool HasJobs - { - get { return _jobs.Count > 0; } - } - - /// - /// Gets the interval at which to run the jobs - /// - public int Interval - { - get - { - if (_seconds > (Int32.MaxValue / 1000)) - return Int32.MaxValue; - - return this._seconds * 1000; - } - } - } -} diff --git a/src/Plugins/SmartStore.GoogleMerchantCenter/StaticFileGenerationTask.cs b/src/Plugins/SmartStore.GoogleMerchantCenter/StaticFileGenerationTask.cs index 2cc1cfca3b..5b0c3e456a 100644 --- a/src/Plugins/SmartStore.GoogleMerchantCenter/StaticFileGenerationTask.cs +++ b/src/Plugins/SmartStore.GoogleMerchantCenter/StaticFileGenerationTask.cs @@ -5,13 +5,17 @@ namespace SmartStore.GoogleMerchantCenter { public class StaticFileGenerationTask : ITask - { - public void Execute(TaskExecutionContext context) + { + private readonly IGoogleFeedService _feedService; + + public StaticFileGenerationTask(IGoogleFeedService feedService) + { + this._feedService = feedService; + } + + public void Execute(TaskExecutionContext context) { - var scope = context.LifetimeScope as ILifetimeScope; - var googleService = scope.Resolve(); - - googleService.CreateFeed(context); + _feedService.CreateFeed(context); } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs index 9acc2ee0b5..50fbda7636 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs @@ -609,53 +609,12 @@ public bool RunScheduleTask() return true; } - string scheduleTaskType = ScheduleTaskType; + var taskSweeper = _ctx.Resolve(); + taskSweeper.ExecuteSingleTask(ScheduleTask.Id); - var task = AsyncRunner.Run((container, ct) => - { - int taskId = 0; - try - { - var svc = container.Resolve(); - - var scheduleTask = svc.GetTaskByType(scheduleTaskType); + Notifier.Information(GetResource("Admin.System.ScheduleTasks.RunNow.Progress")); - if (scheduleTask == null) - throw new Exception("Schedule task cannot be loaded"); - - taskId = scheduleTask.Id; - - var job = new Job(scheduleTask); - job.Enabled = true; - job.Execute(ct, container, false); - } - catch (Exception) - { - _scheduleTaskService.EnsureTaskIsNotRunning(taskId); - } - }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); - - task.Wait(100); - - if (task.IsCompleted) - { - if (!task.IsFaulted) - { - Notifier.Success(GetResource("Admin.System.ScheduleTasks.RunNow.Completed")); - } - else - { - var exc = task.Exception.Flatten().InnerException; - Notifier.Error(exc.Message); - Logger.Error(exc.Message, exc); - } - } - else - { - Notifier.Information(GetResource("Admin.System.ScheduleTasks.RunNow.Progress")); - return true; - } - return false; + return true; } public string GetProgressInfo(bool checkIfRunnning = false) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs index c2ab804116..e935d249f6 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs @@ -30,6 +30,7 @@ public partial class ScheduleTaskController : AdminControllerBase #region Fields private readonly IScheduleTaskService _scheduleTaskService; + private readonly ITaskSweeper _taskSweeper; private readonly IPermissionService _permissionService; private readonly IDateTimeHelper _dateTimeHelper; @@ -37,9 +38,14 @@ public partial class ScheduleTaskController : AdminControllerBase #region Constructors - public ScheduleTaskController(IScheduleTaskService scheduleTaskService, IPermissionService permissionService, IDateTimeHelper dateTimeHelper) + public ScheduleTaskController( + IScheduleTaskService scheduleTaskService, + ITaskSweeper taskSweeper, + IPermissionService permissionService, + IDateTimeHelper dateTimeHelper) { this._scheduleTaskService = scheduleTaskService; + this._taskSweeper = taskSweeper; this._permissionService = permissionService; this._dateTimeHelper = dateTimeHelper; } @@ -61,7 +67,7 @@ private bool IsTaskInstalled(ScheduleTask task) [NonAction] protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) { - var model = new ScheduleTaskModel() + var model = new ScheduleTaskModel { Id = task.Id, Name = task.Name, @@ -71,6 +77,7 @@ protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) LastStartUtc = task.LastStartUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastStartUtc.Value, DateTimeKind.Utc).ToString("G") : "", LastEndUtc = task.LastEndUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastEndUtc.Value, DateTimeKind.Utc).ToString("G") : "", LastSuccessUtc = task.LastSuccessUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastSuccessUtc.Value, DateTimeKind.Utc).ToString("G") : "", + NextRunUtc = task.NextRunUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.NextRunUtc.Value, DateTimeKind.Utc).ToString("G") : "", LastError = task.LastError.EmptyNull(), IsRunning = task.IsRunning, Duration = "" @@ -163,45 +170,9 @@ public ActionResult RunJob(int id, string returnUrl = "") returnUrl = returnUrl.NullEmpty() ?? Request.UrlReferrer.ToString(); - var t = AsyncRunner.Run((c, ct) => - { - var svc = c.Resolve(); - - try - { - var scheduleTask = svc.GetTaskById(id); - if (scheduleTask == null) - throw new Exception("Schedule task cannot be loaded"); - - var job = new Job(scheduleTask); - job.Enabled = true; - job.Execute(ct, c, false); - } - catch - { - svc.EnsureTaskIsNotRunning(id); - } - }); - - // wait only 100 ms. - t.Wait(100); - - if (t.IsCompleted) - { - if (!t.IsFaulted) - { - NotifySuccess(T("Admin.System.ScheduleTasks.RunNow.Completed")); - } - else - { - NotifyError(t.Exception.Flatten().InnerException); - } - } - else - { - NotifyInfo(T("Admin.System.ScheduleTasks.RunNow.Progress")); - } + _taskSweeper.ExecuteSingleTask(id); + NotifyInfo(T("Admin.System.ScheduleTasks.RunNow.Progress")); return Redirect(returnUrl); } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs index bf8c17662b..fd312654d3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs @@ -31,6 +31,9 @@ public partial class ScheduleTaskModel : EntityModelBase [SmartResourceDisplayName("Admin.System.ScheduleTasks.LastSuccess")] public string LastSuccessUtc { get; set; } + [SmartResourceDisplayName("Admin.System.ScheduleTasks.NextRun")] + public string NextRunUtc { get; set; } + [SmartResourceDisplayName("Common.Error")] public string LastError { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml index c2c9ea2581..e0ec668528 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml @@ -40,11 +40,9 @@ .ClientTemplate(@Html.SymbolForBool("StopOnError")) .Centered() .Width(100); - //columns.Bound(x => x.LastStartUtc).ReadOnly(); - //columns.Bound(x => x.LastEndUtc).ReadOnly(); - //columns.Bound(x => x.LastSuccessUtc).ReadOnly(); columns.Bound(x => x.Id) .ClientTemplate("<# if (LastStartUtc.length) {#>
    " + @T("Admin.System.ScheduleTasks.LastStart") + ": <#= LastStartUtc #>
    <# } #>" + + //"<# if (NextRunUtc) {#>
    " + @T("Admin.System.ScheduleTasks.NextRun") + ": <#= NextRunUtc #>
    <# } #>" + "<# if (!LastEndUtc && !IsRunning) {#>
    " + @T("Admin.System.ScheduleTasks.LastStart") + ": " + @T("Common.Never") + "
    <# } #>" + "<# if (Duration.length) {#>
    " + @T("Common.Duration") + ": <#= Duration #>
    <# } #>" + "<# if (LastError.length) {#>
    " + @T("Common.Error") + ": <#= LastError #>
    <# } #>" + diff --git a/src/Presentation/SmartStore.Web/Controllers/KeepAliveController.cs b/src/Presentation/SmartStore.Web/Controllers/KeepAliveController.cs deleted file mode 100644 index 3093193eb9..0000000000 --- a/src/Presentation/SmartStore.Web/Controllers/KeepAliveController.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Web.Mvc; - -namespace SmartStore.Web.Controllers -{ - public partial class KeepAliveController : Controller - { - public ActionResult Index() - { - return Content("I am alive!"); - } - } -} diff --git a/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs b/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs index 8c664c376a..bcaaadd658 100644 --- a/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs @@ -52,9 +52,6 @@ public ActionResult Execute(int id /* taskId */) { if (!_taskSweeper.VerifyAuthToken(Request.Headers["X-AUTH-TOKEN"])) return new HttpUnauthorizedResult(); - - if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageScheduleTasks)) - return new HttpUnauthorizedResult(); var task = _scheduledTaskService.GetTaskById(id); if (task == null) diff --git a/src/Presentation/SmartStore.Web/Global.asax.cs b/src/Presentation/SmartStore.Web/Global.asax.cs index 0db44b9ae3..1ab1679bc0 100644 --- a/src/Presentation/SmartStore.Web/Global.asax.cs +++ b/src/Presentation/SmartStore.Web/Global.asax.cs @@ -115,10 +115,6 @@ protected void Application_Start() HostingEnvironment.RegisterVirtualPathProvider(new PluginDebugViewVirtualPathProvider()); } - // start scheduled tasks - TaskManager.Instance.Initialize(); - TaskManager.Instance.Start(); - // Install filter GlobalFilters.Filters.Add(new InitializeSchedulerFilter()); } diff --git a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj index 6bf75736ec..30f870100e 100644 --- a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj +++ b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj @@ -253,7 +253,6 @@ - From 368daab9c76a5fb303814f9b18186767890a3f3a Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 22 Jul 2015 11:59:16 +0200 Subject: [PATCH 0282/1256] There was no payment redirect if only one payment method is available in checkout --- changelog.md | 3 ++- .../Controllers/CheckoutController.cs | 15 +++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/changelog.md b/changelog.md index 242e7ca78c..6e8c2f90ad 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,4 @@ -# Release Notes +# Release Notes ## SmartStore.NET 2.2.2 @@ -36,6 +36,7 @@ * Weight adjustment of attributes weren't applied in shopping cart overview * Shipping by weight calculates wrong surcharge if attribute combination prices are set * Don't let database hooks call other hooks. +* There was no payment redirect if only one payment method is available in checkout ## SmartStore.NET 2.2.1 diff --git a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs index 8b1e37d65e..1702e3b5c3 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs @@ -797,13 +797,11 @@ public ActionResult ConfirmOrder(FormCollection form) var model = new CheckoutConfirmModel(); try { - bool isPaymentPaymentWorkflowRequired = IsPaymentWorkflowRequired(cart); - var processPaymentRequest = _httpContext.Session["OrderPaymentInfo"] as ProcessPaymentRequest; if (processPaymentRequest == null) { //Check whether payment workflow is required - if (isPaymentPaymentWorkflowRequired) + if (IsPaymentWorkflowRequired(cart)) return RedirectToAction("PaymentMethod"); processPaymentRequest = new ProcessPaymentRequest(); @@ -826,14 +824,11 @@ public ActionResult ConfirmOrder(FormCollection form) if (placeOrderResult.Success) { - if (isPaymentPaymentWorkflowRequired) + var postProcessPaymentRequest = new PostProcessPaymentRequest { - var postProcessPaymentRequest = new PostProcessPaymentRequest() - { - Order = placeOrderResult.PlacedOrder - }; - _paymentService.PostProcessPayment(postProcessPaymentRequest); - } + Order = placeOrderResult.PlacedOrder + }; + _paymentService.PostProcessPayment(postProcessPaymentRequest); _httpContext.Session["PaymentData"] = null; _httpContext.Session["OrderPaymentInfo"] = null; From 13e536d4918aa15913bafc92a2e15b2ed42766fc Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 22 Jul 2015 12:03:39 +0200 Subject: [PATCH 0283/1256] There was no payment redirect if only one payment method is available in checkout --- .../SmartStore.Web/Controllers/CheckoutController.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs index eb18e5bdae..0a960e58d8 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs @@ -806,13 +806,11 @@ public ActionResult ConfirmOrder(FormCollection form) var model = new CheckoutConfirmModel(); try { - bool isPaymentPaymentWorkflowRequired = IsPaymentWorkflowRequired(cart); - var processPaymentRequest = _httpContext.Session["OrderPaymentInfo"] as ProcessPaymentRequest; if (processPaymentRequest == null) { //Check whether payment workflow is required - if (isPaymentPaymentWorkflowRequired) + if (IsPaymentWorkflowRequired(cart)) return RedirectToAction("PaymentMethod"); processPaymentRequest = new ProcessPaymentRequest(); @@ -840,10 +838,7 @@ public ActionResult ConfirmOrder(FormCollection form) Order = placeOrderResult.PlacedOrder }; - if (isPaymentPaymentWorkflowRequired) - { - _paymentService.PostProcessPayment(postProcessPaymentRequest); - } + _paymentService.PostProcessPayment(postProcessPaymentRequest); _httpContext.Session["PaymentData"] = null; _httpContext.Session["OrderPaymentInfo"] = null; From fb22049ed517bcf0b2c1809b56a5f8d3b8c68993 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Wed, 22 Jul 2015 16:10:59 +0200 Subject: [PATCH 0284/1256] Placed initialization of DataSegmenter in try catch block and added errors to result log --- .../ExportImport/ImportManager.cs | 258 +++++++++--------- 1 file changed, 132 insertions(+), 126 deletions(-) diff --git a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs index 2dd762b398..b48dcf007a 100644 --- a/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs +++ b/src/Libraries/SmartStore.Services/ExportImport/ImportManager.cs @@ -152,134 +152,140 @@ public virtual ImportResult ImportProductsFromExcel( using (var scope = new DbContextScope(ctx: _rsProduct.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false)) { - using (var segmenter = new DataSegmenter(stream)) - { - result.TotalRecords = segmenter.TotalRows; - - while (segmenter.ReadNextBatch() && !cancellationToken.IsCancellationRequested) - { - var batch = segmenter.CurrentBatch; - - // Perf: detach all entities - _rsProduct.Context.DetachAll(); - - // Update progress for calling thread - if (progress != null) - { - progress.Report(new ImportProgressInfo - { - TotalRecords = result.TotalRecords, - TotalProcessed = segmenter.CurrentSegmentFirstRowIndex - 1, - NewRecords = result.NewRecords, - ModifiedRecords = result.ModifiedRecords, - ElapsedTime = DateTime.UtcNow - result.StartDateUtc, - TotalWarnings = result.Messages.Count(x => x.MessageType == ImportMessageType.Warning), - TotalErrors = result.Messages.Count(x => x.MessageType == ImportMessageType.Error), - }); - } - - // =========================================================================== - // 1.) Import products - // =========================================================================== - try - { - saved = ProcessProducts(batch, result); - } - catch (Exception ex) - { - result.AddError(ex, segmenter.CurrentSegment, "ProcessProducts"); - } - - // reduce batch to saved (valid) products. - // No need to perform import operations on errored products. - batch = batch.Where(x => x.Entity != null && !x.IsTransient).AsReadOnly(); - - // update result object - result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient); - result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient); - - // =========================================================================== - // 2.) Import SEO Slugs - // IMPORTANT: Unlike with Products AutoCommitEnabled must be TRUE, - // as Slugs are going to be validated against existing ones in DB. - // =========================================================================== - if (batch.Any(x => x.IsNew || (x.ContainsKey("SeName") || x.NameChanged))) - { - try - { - _rsProduct.Context.AutoDetectChangesEnabled = true; - ProcessSlugs(batch, result); - } - catch (Exception ex) - { - result.AddError(ex, segmenter.CurrentSegment, "ProcessSeoSlugs"); - } - finally - { - _rsProduct.Context.AutoDetectChangesEnabled = false; - } - } - - // =========================================================================== - // 3.) Import Localizations - // =========================================================================== - try - { - ProcessLocalizations(batch, result); - } - catch (Exception ex) - { - result.AddError(ex, segmenter.CurrentSegment, "ProcessLocalizations"); - } - - // =========================================================================== - // 4.) Import product category mappings - // =========================================================================== - if (batch.Any(x => x.ContainsKey("CategoryIds"))) - { - try - { - ProcessProductCategories(batch, result); - } - catch (Exception ex) - { - result.AddError(ex, segmenter.CurrentSegment, "ProcessProductCategories"); - } - } - - // =========================================================================== - // 5.) Import product manufacturer mappings - // =========================================================================== - if (batch.Any(x => x.ContainsKey("ManufacturerIds"))) - { - try - { - ProcessProductManufacturers(batch, result); - } - catch (Exception ex) - { - result.AddError(ex, segmenter.CurrentSegment, "ProcessProductManufacturers"); - } - } + try { + using (var segmenter = new DataSegmenter(stream)) + { + result.TotalRecords = segmenter.TotalRows; + + while (segmenter.ReadNextBatch() && !cancellationToken.IsCancellationRequested) + { + var batch = segmenter.CurrentBatch; + + // Perf: detach all entities + _rsProduct.Context.DetachAll(); + + // Update progress for calling thread + if (progress != null) + { + progress.Report(new ImportProgressInfo + { + TotalRecords = result.TotalRecords, + TotalProcessed = segmenter.CurrentSegmentFirstRowIndex - 1, + NewRecords = result.NewRecords, + ModifiedRecords = result.ModifiedRecords, + ElapsedTime = DateTime.UtcNow - result.StartDateUtc, + TotalWarnings = result.Messages.Count(x => x.MessageType == ImportMessageType.Warning), + TotalErrors = result.Messages.Count(x => x.MessageType == ImportMessageType.Error), + }); + } + + // =========================================================================== + // 1.) Import products + // =========================================================================== + try + { + saved = ProcessProducts(batch, result); + } + catch (Exception ex) + { + result.AddError(ex, segmenter.CurrentSegment, "ProcessProducts"); + } + + // reduce batch to saved (valid) products. + // No need to perform import operations on errored products. + batch = batch.Where(x => x.Entity != null && !x.IsTransient).AsReadOnly(); + + // update result object + result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient); + result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient); + + // =========================================================================== + // 2.) Import SEO Slugs + // IMPORTANT: Unlike with Products AutoCommitEnabled must be TRUE, + // as Slugs are going to be validated against existing ones in DB. + // =========================================================================== + if (batch.Any(x => x.IsNew || (x.ContainsKey("SeName") || x.NameChanged))) + { + try + { + _rsProduct.Context.AutoDetectChangesEnabled = true; + ProcessSlugs(batch, result); + } + catch (Exception ex) + { + result.AddError(ex, segmenter.CurrentSegment, "ProcessSeoSlugs"); + } + finally + { + _rsProduct.Context.AutoDetectChangesEnabled = false; + } + } + + // =========================================================================== + // 3.) Import Localizations + // =========================================================================== + try + { + ProcessLocalizations(batch, result); + } + catch (Exception ex) + { + result.AddError(ex, segmenter.CurrentSegment, "ProcessLocalizations"); + } + + // =========================================================================== + // 4.) Import product category mappings + // =========================================================================== + if (batch.Any(x => x.ContainsKey("CategoryIds"))) + { + try + { + ProcessProductCategories(batch, result); + } + catch (Exception ex) + { + result.AddError(ex, segmenter.CurrentSegment, "ProcessProductCategories"); + } + } + + // =========================================================================== + // 5.) Import product manufacturer mappings + // =========================================================================== + if (batch.Any(x => x.ContainsKey("ManufacturerIds"))) + { + try + { + ProcessProductManufacturers(batch, result); + } + catch (Exception ex) + { + result.AddError(ex, segmenter.CurrentSegment, "ProcessProductManufacturers"); + } + } - // =========================================================================== - // 6.) Import product picture mappings - // =========================================================================== - if (batch.Any(x => x.ContainsKey("Picture1") || x.ContainsKey("Picture2") || x.ContainsKey("Picture3"))) - { - try - { - ProcessProductPictures(batch, result); - } - catch (Exception ex) - { - result.AddError(ex, segmenter.CurrentSegment, "ProcessProductPictures"); - } - } - - } - } + // =========================================================================== + // 6.) Import product picture mappings + // =========================================================================== + if (batch.Any(x => x.ContainsKey("Picture1") || x.ContainsKey("Picture2") || x.ContainsKey("Picture3"))) + { + try + { + ProcessProductPictures(batch, result); + } + catch (Exception ex) + { + result.AddError(ex, segmenter.CurrentSegment, "ProcessProductPictures"); + } + } + + } + } + } + catch (Exception ex) + { + result.AddError(ex, null, "ReadFile"); + } } result.EndDateUtc = DateTime.UtcNow; From 5e96c4ddfe055da8f79d62e0495ce69e64167dcb Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 22 Jul 2015 16:46:12 +0200 Subject: [PATCH 0285/1256] Minor migration fix --- .../201507202149123_Merge2.Designer.cs | 29 ++++ .../Migrations/201507202149123_Merge2.cs | 16 +++ .../Migrations/201507202149123_Merge2.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 7 + 4 files changed, 178 insertions(+) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.resx diff --git a/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.Designer.cs new file mode 100644 index 0000000000..7bb45d2585 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")] + public sealed partial class Merge2 : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(Merge2)); + + string IMigrationMetadata.Id + { + get { return "201507202149123_Merge2"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.cs b/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.cs new file mode 100644 index 0000000000..a26a4dfe70 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.cs @@ -0,0 +1,16 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class Merge2 : DbMigration + { + public override void Up() + { + } + + public override void Down() + { + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.resx b/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.resx new file mode 100644 index 0000000000..19402f07d2 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index ee035dc982..7a713af0ec 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -319,6 +319,10 @@ 201507200832223_SortFilterHomepageProducts.cs + + + 201507202149123_Merge2.cs + @@ -606,6 +610,9 @@ 201507200832223_SortFilterHomepageProducts.cs + + 201507202149123_Merge2.cs + From 269aa5ffda784d0cb78b1629975c3f8919351177 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 22 Jul 2015 20:07:18 +0200 Subject: [PATCH 0286/1256] Minor widget improvements --- .../Extensions/HtmlExtensions.cs | 3 +- .../SmartStore.Web.Framework.csproj | 1 + .../UI/WidgetZoneModel.cs | 13 + .../Controllers/WidgetController.cs | 23 -- .../Models/Cms/RenderWidgetModel.cs | 12 - .../Administration/SmartStore.Admin.csproj | 4 - .../Administration/Views/Home/Index.cshtml | 4 +- .../Shared/EditorTemplates/WidgetZone.cshtml | 290 +++++++++--------- .../Views/Topic/_CreateOrUpdate.cshtml | 2 +- .../Views/Widget/WidgetsByZone.cshtml | 4 - .../Controllers/WidgetController.cs | 4 +- .../Infrastructure/DefaultWidgetSelector.cs | 1 - .../Views/Widget/WidgetsByZone.cshtml | 4 +- 13 files changed, 172 insertions(+), 193 deletions(-) create mode 100644 src/Presentation/SmartStore.Web.Framework/UI/WidgetZoneModel.cs delete mode 100644 src/Presentation/SmartStore.Web/Administration/Models/Cms/RenderWidgetModel.cs delete mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Widget/WidgetsByZone.cshtml diff --git a/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlExtensions.cs b/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlExtensions.cs index 0b7020875a..433d1804c5 100644 --- a/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlExtensions.cs +++ b/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlExtensions.cs @@ -406,7 +406,8 @@ public static MvcHtmlString Widget(this HtmlHelper helper, string widgetZone, ob var widgets = widgetSelector.GetWidgets(widgetZone, model).ToArray(); if (widgets.Any()) { - var result = helper.Action("WidgetsByZone", "Widget", new { widgets = widgets, model = model, area = "" }); + var zoneModel = new WidgetZoneModel { Widgets = widgets, WidgetZone = widgetZone, Model = model }; + var result = helper.Action("WidgetsByZone", "Widget", new { zoneModel = zoneModel, model = model, area = "" }); return result; } } diff --git a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj index cd2f03fa0d..796666721b 100644 --- a/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj +++ b/src/Presentation/SmartStore.Web.Framework/SmartStore.Web.Framework.csproj @@ -332,6 +332,7 @@ + diff --git a/src/Presentation/SmartStore.Web.Framework/UI/WidgetZoneModel.cs b/src/Presentation/SmartStore.Web.Framework/UI/WidgetZoneModel.cs new file mode 100644 index 0000000000..f043fded2f --- /dev/null +++ b/src/Presentation/SmartStore.Web.Framework/UI/WidgetZoneModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using SmartStore.Web.Framework.Mvc; + +namespace SmartStore.Web.Framework.UI +{ + public class WidgetZoneModel : ModelBase + { + public IEnumerable Widgets { get; set; } + public string WidgetZone { get; set; } + public object Model { get; set; } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/WidgetController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/WidgetController.cs index f6dd962c6c..e3c54ac30c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/WidgetController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/WidgetController.cs @@ -100,29 +100,6 @@ public ActionResult ActivateProvider(string systemName, bool activate) return RedirectToAction("Providers"); } - - [ChildActionOnly] - public ActionResult WidgetsByZone(string widgetZone) - { - var model = new List(); - - var widgets = _widgetService.LoadActiveWidgetsByWidgetZone(widgetZone); - foreach (var widget in widgets) - { - var widgetModel = new RenderWidgetModel(); - - string actionName; - string controllerName; - RouteValueDictionary routeValues; - widget.Value.GetDisplayWidgetRoute(widgetZone, null, 0, out actionName, out controllerName, out routeValues); - widgetModel.ActionName = actionName; - widgetModel.ControllerName = controllerName; - widgetModel.RouteValues = routeValues; - - model.Add(widgetModel); - } - return PartialView(model); - } #endregion } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Cms/RenderWidgetModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Cms/RenderWidgetModel.cs deleted file mode 100644 index 5591035fc2..0000000000 --- a/src/Presentation/SmartStore.Web/Administration/Models/Cms/RenderWidgetModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Web.Routing; -using SmartStore.Web.Framework.Mvc; - -namespace SmartStore.Admin.Models.Cms -{ - public class RenderWidgetModel : ModelBase - { - public string ActionName { get; set; } - public string ControllerName { get; set; } - public RouteValueDictionary RouteValues { get; set; } - } -} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index fd2aa999ac..c3fc4b644c 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -235,7 +235,6 @@ - @@ -1089,9 +1088,6 @@ - - - diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Home/Index.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Home/Index.cshtml index cc01d61e3e..8842c7648b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Home/Index.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Home/Index.cshtml @@ -11,7 +11,7 @@
    - @Html.Action("WidgetsByZone", "Widget", new { widgetZone = "admin_dashboard_top" }) + @Html.Widget("admin_dashboard_top")
    @@ -39,6 +39,6 @@
    - @Html.Action("WidgetsByZone", "Widget", new { widgetZone = "admin_dashboard_bottom" }) + @Html.Widget("admin_dashboard_bottom")
    diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/WidgetZone.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/WidgetZone.cshtml index 819aa95a63..5368dd5aa0 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/WidgetZone.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/WidgetZone.cshtml @@ -11,7 +11,7 @@ } } - + @@ -72,3 +73,14 @@
    @@ -121,8 +133,9 @@ }) .ClientEvents(events => events.OnDataBinding("Grid_onDataBinding").OnError("Grid_onError").OnSubmitChanges("Grid_onSubmitChanges")) .Editable(editing => editing.Mode(GridEditMode.InCell)) - .Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both)) + .Pageable(settings => settings.PageSize(Model.GridPageSize).Position(GridPagerPosition.Both)) ) + From 6bdb32a22b6293b61a62740ffe03925d1d827e15 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 21 Jul 2015 14:29:34 +0200 Subject: [PATCH 0277/1256] Resolves #607 HTML capable full description for payment methods displayed in checkout --- changelog.md | 1 + .../Domain/Payments/PaymentMethod.cs | 9 +- .../Mapping/Payments/PaymentMethodMap.cs | 2 + ...52098_PaymentMethodDescription.Designer.cs | 29 ++++ ...01507210952098_PaymentMethodDescription.cs | 44 ++++++ ...507210952098_PaymentMethodDescription.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 7 + .../Controllers/PaymentController.cs | 37 +++-- .../Models/Payments/PaymentMethodEditModel.cs | 42 +++++- .../Administration/Views/Payment/Edit.cshtml | 20 ++- .../Controllers/CheckoutController.cs | 11 +- .../Checkout/CheckoutPaymentMethodModel.cs | 2 + .../Themes/Alpha/Content/checkout.less | 3 +- .../Themes/Mobile/Content/styles.css | 2 +- .../Checkout/PaymentMethod.Mobile.cshtml | 17 ++- .../Views/Checkout/PaymentMethod.cshtml | 11 +- 16 files changed, 341 insertions(+), 22 deletions(-) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.resx diff --git a/changelog.md b/changelog.md index 69536b51f9..6012ba57f4 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,7 @@ * #727 Web-API: Option to deactivate TimestampOlderThanLastRequest validation * #731 Web-API: Allow deletion and inserting of product category and manufacturer assignments * #733 Option to set a display order for homepage products +* #607 HTML capable full description for payment methods displayed in checkout ### Improvements * (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%. diff --git a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs index 0567ad5dfe..5b81853884 100644 --- a/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs +++ b/src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs @@ -1,5 +1,6 @@ using System.Runtime.Serialization; using SmartStore.Core.Domain.Common; +using SmartStore.Core.Domain.Localization; namespace SmartStore.Core.Domain.Payments { @@ -7,7 +8,7 @@ namespace SmartStore.Core.Domain.Payments /// Represents a payment method /// [DataContract] - public partial class PaymentMethod : BaseEntity + public partial class PaymentMethod : BaseEntity, ILocalizedEntity { /// /// Gets or sets the payment method system name @@ -88,5 +89,11 @@ public AmountRestrictionContextType AmountRestrictionContext this.AmountRestrictionContextId = (int)value; } } + + /// + /// Gets or sets the full description + /// + [DataMember] + public string FullDescription { get; set; } } } diff --git a/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs b/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs index c009204c13..59821c61a8 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Payments/PaymentMethodMap.cs @@ -19,6 +19,8 @@ public PaymentMethodMap() this.Property(x => x.MinimumOrderAmount).HasPrecision(18, 4); this.Property(x => x.MaximumOrderAmount).HasPrecision(18, 4); + this.Property(x => x.FullDescription).HasMaxLength(4000); + this.Ignore(x => x.CountryExclusionContext); this.Ignore(x => x.AmountRestrictionContext); } diff --git a/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.Designer.cs new file mode 100644 index 0000000000..4412803c98 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")] + public sealed partial class PaymentMethodDescription : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(PaymentMethodDescription)); + + string IMigrationMetadata.Id + { + get { return "201507210952098_PaymentMethodDescription"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs b/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs new file mode 100644 index 0000000000..9cc272131b --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs @@ -0,0 +1,44 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + using SmartStore.Data.Setup; + + public partial class PaymentMethodDescription : DbMigration, ILocaleResourcesProvider, IDataSeeder + { + public override void Up() + { + AddColumn("dbo.PaymentMethod", "FullDescription", c => c.String(maxLength: 4000)); + } + + public override void Down() + { + DropColumn("dbo.PaymentMethod", "FullDescription"); + } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.ShortDescription", + "Short description", + "Kurzbeschreibung", + "Specifies a short description of the payment method.", + "Legt eine Kurzbeschreibung der Zahlungsmethode fest."); + + builder.AddOrUpdate("Admin.Configuration.Payment.Methods.FullDescription", + "Full description", + "Langtext", + "Specifies a full description of the payment method. It appears in the payment list in checkout.", + "Legt eine vollstndige Beschreibung der Zahlungsmethode fest. Sie erscheint in der Zahlungsliste im Kassenbereich."); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.resx b/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.resx new file mode 100644 index 0000000000..04f8e677a2 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + H4sIAAAAAAAEAOy92XIcObIo+D5m8w8yPd07dq5UUneZ9W2rmmskRUq0o4VNUtI554UGRoLMaEZGZMXCpcfmy+ZhPml+YQDEktj3iMjMyhcpGXA4AIe7w+FwOP6//+f//e1/Pa+yV4+wrNIi//31uze/vH4F86RYpPn976+b+u5//O31//o///f/7bfTxer51Y8e7i8YDtXMq99fL+t6/fe3b6tkCVegerNKk7Koirv6TVKs3oJF8fb9L7/8z7fv3r2FCMVrhOvVq98um7xOV5D8gf48KfIErusGZF+KBcyq7jsquSJYX30FK1itQQJ/f321AmV9VRclfPMB1OD1q6MsBagbVzC7e/0K5HlRgxp18u/fK3hVl0V+f7VGH0B2/bKGCO4OZBXsOv/3DbjtOH55j8fxdlOxR5U0VV2sHBG++0tHmLd8dS/yvh4Ih0h3ikhcv+BRE/L9/vofDSCfvudp/foV3+DfT7ISAzMUPiFkRmBp/uZDWsIEfX15QyP6t1cc+L8NXPL+zfs3v7z55d9enTRZ3ZTw9xw2dQmyf3t10dxmafLv8OW6eID573mTZXTXUedRGfMBfbooizUs65dLeNcN6Hzx+tVbtt5bvuJQjarTDvM8r//y/vWrr6hxcJvBgTMokpBRfYQ5LEENFxegrmGZYxyQjF9onWsL/9u3hlgRidTrV1/A82eY39fL31//imToLH2Gi/5D1wFEViSAqE5dNlDSQX2jH2CVlOm65aHQtg1NpdU6Ay+fiwRkEQZq1di3cgFL0xTqMZ1XH+AdQDzZozkuigyC3IDot7cbiTLIGWzg4hQJTXZU1yBZrhC7eAjcF1hV4B5Wb6QID4KnbosimLlZPSrcEzQJmMcZkUKrzRtuRgRQx6bQMJcaKXr3yy8x5OgszaBAFIPokXW2k5U0B+UL0zH0U96vIO343nK0jkT+gswO3OYELX8Fj+k9YQXJFLx+dQkzUlgt03XHUFJBv2nBz8pidVlkKv1CoG6uiqZM8NgKI+g1KO9hbd9pCpVD35lapiFQXy1HQteQDchaZ38onvKsAAsvNb1IwZsewUEta/RIR6OPTTq02v52FGJk2ve4vpeZ2zKu7haFSqIVlFrOzYrp2urVaGylinZSNZoMg4aLMxasRnK9Eo/T0OkzGlOlN2jjtHRefYVP45uFkYzBg65Rt3VRpkVJ4EKsP7xiaTc2o9gouFXj3jGGLXhdTD+462KSoV3CdfYSZXxW7UwyppOT0Zs4TpLR27hqbv8Jk3r8rc5xsXgZfck4KSFWUN/y7/VAOrRhgtfpyl04rvDaXaawCty0IjSKDhlWWmJfJ0nR5HXwzhnmiy8gb0CWvTibaMptyMb4r6bYhvSbCvttSL9xsR0QTXLTiG5YYOlAGBjdNooFDNo9sd3yt21oPAfjxiCmOg/Gr7+O4lpuXbAmx41l4/q2PhWVboUYaYQXRVmHaT20NS0Nm6Kx+g6q6qkoF9O3fJpj4KsqeCeO9/Wtax6tqkQWUK2RtmMX4AXr7i+wXhY+bp+ufvWGQXTQWjoGpQh19VLV0LTL+autHejKsM9J1izg4oRMOizx2ni+qEa3fId28QJXvuibfB/HCO7bvEIWxRq10ZJ/itF2oyQdwBJAfFPPwXbllzRPV82KHAQerVqTo7NyYZKuANJCFyX61UU0/O31qyt8Pom4yYgZPI+EucV2CStE66SOR4szBG534GstSn7KtCwWTVIfN/kCSRISbGQcl+ltU8OzNKvxga2zfj0BNciK+zcm1AeNq25rQ7RQRhuIHg3RD5A1wdjOKySQaJcEE0SeeJvMDd2kOzITS97Q9TebNIdqwr7NpW7QVk5oKKboHmRV3VZHrFCJaIkdCVkf6BWGBW0bk5iLaY/vAiIRyWtwD0P3HWYzNIbbc4k2l3aLdbTzOcSCg6Jw3EhJtuTpAl4vm9VtTnkffJH9QBN/mwXPHFEO1dJD+Y8WXhbVIfx9vQhApvOi0quH3JU6wTLHu1d9lki3Rb1rwW7AN1wdzSBZUPP6zcG7RuO4DcNqAPZd13Xa1dAINy8ORoVGPbYkws2F2gIXoERtfiyLZo06Ese+6BaB83yRPqYLv5OicZZy17Ouydd2641/nPaOFqs0PylWbSjzyI31XAtXaEkO33KiyXn6ln8qVvAigq3Y44lnMHyBNUBKA/vudU65OFYobmxKxsHtXae19n5AnJEdZVnxNHh04WMKn4JN3qP1uiwe4eISaeP8/qpZhc3016KOjLFHd40WjIwbdHAf4yHtQj6ui6MkeOfwOV2lNe4cWRuDp/jqoRlf6EDe3IEEmyAlWkfrr2gTtdEaozX7EbHY6I2cVx/Tu/oElMFbsB5PDGvlEv7RpCX8Vi8RxdvlJJhTOpwb40enrSOFMB012Dau0wTbRkeLBdeH4DGdV5vI9zhR1KEz9z3PWgHvEQaPEc1KK3Df7gScnh6tDs3p8zotiaH+AbzwOO1QHCV1+khQxGD7T6C6AshqgrFmlcXmeG8I9QaHQxzdlxDShmNAeMAG2TV8Ht8SPa8uYdKULfZQ7dEhOnlJMth2KlTH0RgvYJkWwdI34CRrP0EcKCvnFT55bkNEgtnxvDpD098fZQdbd4tFiiUPZD3GkyV2adg7qp27fw2eT5/RviZYFs6r0yqYnKg3J2iDdV/gWITATQzI0aboPH9EoonQ9VEGgWZjXSQP0Q4h8HaNYDx6BCmqm2YU1kC/sbSn3gtWmkcc+efiqR01XmkQttBJQRuE9O6FOATOirLv4zFEu6/AoyuQPBR4O42TQASfM+PdIMZ43tIS7UCGTW+wRUE2/V0cSpxJajG28SdxMBICwEWHjAopH89YRbKAO3jcvBw3db1xLgTIFob+mVbLLK3qOEg74c8gYl6k1xn/jS/OE2SdE3RpEn6iRSOJvgJ9yxbjNtBtTE6o8N3obVytER6QOQ7EHudVjfbo/Smbxy0KGtdpvgjA1LuzTnN8SheFvzq1xWCGIzNFp9gmbRNtPq5T2MpksMJHayis6uEw8qRY3aZ5dy4XkQlRn/vghupovc7ScIv5J0zvl+OJIruPiY7+Z7oYEfuncWkzrDSh+mRAFKZM4p1YxIu6gBn0idzb3pALcYDpIyxfcGVH7wmdZcux6jGoYLf6RNl2D/i+QFA1JWwziCnNySj5noY240ZiD2jxDxa1HWlJGAQ50TJ4oOK417swEVjiyItYjg8GKaZGbJxXy6L1p4DS3dOhjlpql8RhiZRGv/SlNx30dbHxlW/CX9RQQkySBtQ1BInWBrrQnRsWUIjaYcpVATsskGeA0SbqxzJGzD9kyhgLpgixchxR5/AiG2L1gHq3mCZ0igdRDUCA8+w4fYio7TsNqOm/DEw1Bims5zguUoJHO4QORtN7DkLVcR7Ms8/DIbi6yy2IpscsgKrDHJRnf8kO9C5tE9HREcDq/suraMajr6Aan6GW53ivwb12cDcMnKhPqWKlOqVhPLXpD1CmyKiT7SO13dfU00yQRS3VLNlU9ZwqHrXTwB1G6zpE73GxaXU1PMgCikxIlyu5kAFyZUP+bFjTWR5U7C4LoewwB+baZdqHI+nuUCzjDKFQ4AURQjb79lkEh5suHtmVO6N2+HWIa1a3ZYjyHSl3aD8zMSI1vld4rxTp/pL6RlR0p1bflOuu3Pnkt3OZ+SQxar1kHjW76KrqpGjW+I72InhmREzy47c4p29kZkh8JJGyUB7dYMLEc40DMW3jrwvDVkzceNMVdHv5DZywLGmBXRcniYthDI+EeQyC88LaI9Gh6jhfnVdraFNeQzIOGaB6KFLooAtG/b474IZRj+KwFKvbMizFI124wfdfIrVscuBPd1fiuKgRn056rQe/nTL6ytSLUawLPYcLM1FG1t7oixUA2HnaHE+q8E2qq/RfMKxt5upPdV20GUF43N4ROR2eb2zwWMC+wyIC6BLk99qYrWhJCWLejYsfv7DFN4e27RR8L1MYCKQi6QF/pPDpi35T5amNYx8+emxZzAeQkv2NtRe2VdPS3m9OqnqgTY/5MsGSFwDCsgP0PfB8jqOrfzDcNeqrJdFYL1FYPLTz13Hu4sPC4mWKv0S6/Oj8XkTsE1JRVOUQxhNSTq79xJbBGZ7b4yDGU+UNU5nv09kgXkuWtzQojqtUQuMowXFjG0x9jZGOR+J/i3KKReE7SLFWbqI8uiAh+2WTQatsy3H8F1drOPrp0HGaZTi6sE+jHHjLsL/8GQddn+WXGOpMgmknz8gGzaDhde6AOJNHNUon656y4X42zN6W2C13fgHHeTp9RoqKfiFzgr3oJs5gvJMa5S5Ue67jt/Yw0a4BD1PTiA6rjbotw0IwzsPUJ0VWlJ/gM0n8PHnrO/FWtes+K8IRJ4fpIDXqtiLttGIduJxXZxDgiegNhBn9x8qVasOhFrH2G2B1sP3wQ7EpEgFH2ML53A4w9TfKLu5CDNcP1w00toN+GF0/0OT+U+gIllst77WwlfSXW5g/FHKorjCC/gi5oWPT/yi6JJISOWiPbY6jmjSyheKEQyjQdoUCHYJ3djB45xDPsnvxLF6nXOziLp5xycoFQ0EKFGO30V5ZDd9ntHii2QivcIaHrn0S3dKpGPL0Xl6/nsKWN2nvWC5sTLhJEqK2acvDiPIJZuu7JvtPWJEko1GQfS18cIXY8K73vRV2u+JWuGNHWywdLXJYVUhWTSkOhDo3nDwrRqSsob/Srq4WdHbQS7WP+ultjuHXYX+ibqun0ccmHVptf3tkcTYEZ0XKR2l6Jj1SMxYPb0d6F6Vr6KwoVyA84qfDdgWy8deNSd+PiZhm+ejuLs3SCBtVkn03eDcTybI+r9qAkKOEeZjRO0bfJrokzpvSn0FVn6+PFgu03xk/NiDqvgF3/XNxn+ael5Nx/T6HsxKF/6XclqQKk6FX/jcUGBUbLpSK0eEiiKup0wX9DHOv6yYPK+krC6LuMAfn2mt+16Hrdgdzs7FpxH7zMILRpQR0vSlAxy4ZyM2BSqjNQKiJzYK50vr0GZs0IDtq6iU2atokQ5cwab2DkhHoakinwaqCMCd2tVwnCJkBzeqiqBR3UYZi6UDEUqHXEhCvLl4X6zTR9JGUqzvJFst7ycG4dpO4mOQ9JEXSzrElQr+4YtcuXUK0y8hxjBVUTTADIu2iHELoqgLMvctPoFxcFGleV5/SqlYd+0vgFL1Xw0nGoAF2HUkfg2i11gjAEvXHwagVIA/onOGJSrypztrIQ0nJrwQSaK+GDNraDwR139mjjUaRv+kQHHb16rbO0rKqJ4kLx+brJA2Zdv2RtgbFag3ylwnakQelG3ZkiDtwotTHNE9cT/VOqKdHRvQHENF8N1VD70dv6L/SNbaVQGZI9hTJFbQscmh8RjLSW8P9+3lbvt9W72RaGZIuhf1CO8BsFkCuSFi0+XLntZoWUm3nOEixiwyAsqMsVFhypZ5cAdH6HY7D8qxuy7Bg2qbn8YnIqDrHR7AHlSCLlbn++qn4DDERz6vCoGjfR1BI18sSQtsG/xKhQaRoYZkmXGOBjy7/AMEu3nixIdGCOkKjXzT7WP4u2nALTrqXomFuNpVb9cYl/jBDS3ZXxirO+1t6IVAMi1krJKujFEDsvBQqaFvI0sNjBeoRcFN3WIc0amnvg1Pj6aXz+xzRun1JNjgm7/Q5yZoFknXmIrHu5CvOOVsnqaR5LALkNOHZ/czZQslSenIK9cobxw4a2U9dsbZ7gL3MYDpoKyPzBj90O4/xfXtbwscUGLRenMyc22DWeW3bPc0TQfi1RkxQQNpw4BshLq3DdZB5jcx3pAq+MWcRXBLnpsA5TpGJWG+vnj80RhPED4BQnaUpIyW8xPo4K+6H+DVnkca1qzcUju2Icu86M0nkOB48dpDHMyF7jFKWomh9swHcsJOsXGAlKVAwG7VdCeAhjOCwFqjb+gzy+wbcB8dsxrq94ZrdqljEOIDzuobXMnvwtrVf2Tp8J5JnVl2N8aKOj7R9Dm5kxTfPUzaHi7HbeMVypANOap2Se1G8VkPel6tdMm272utmZTcJ1g0U20emULpcsxBBa/WmE85rNUkzlf6LAL/p8RyWbHVb8/ha+pnpqK7d8o3RPqr9RwOv4BRHmWcZuD9focHi5NjGuxoxrorW+/tgwwjerjYzXTsZl7Aiqk2uzGWQUo2pBRTUux466MhOhjpYq0pwHjSsWddFSG9LaG1QISM9wdm3bkoiOdIm6bzC0nWRNfdpLigR46XEoklkyieK6RRJKfAmlZ0K8VIKF4rb4bESSVAot8PbxvQuVAx/gqobYLzAlwv2/v+UqQO02RHMGQe8GPArfKr8Xbq49hsKxXbwWO/RnSTvyJTuY0xpfLcknvu4xyhldGpibzaAG7aWlQtMLAUKZtm2K/78iusfDCV1WzvuPb5aFmUMcXRs9oyorqlbjbajm8dJ+2f0uW+VR/XgNI8yMr8ty7AkyrYpQqF0dWUhXC/gUOuz3NPiZQXwfhWtqeC3cyqy7EdRky1ZQhIPOVsDGEX1hke0HTYs7tVRXj15BPOotzYDTvm+hiPEDQ1PbWbUYOIORgMbtm+muhYw7y2KgyGo58ORY0hHMova65rf7hD/bVbYLXrQr8AqQiGGnYi0MKzoUUVScaPLnRMpcuKqSJ0YrieEJIkWOsVbTwRpiINuULcVa5M4j35oE7Z1lu74d9WjbdKiPlZPNl8fSXqd6wJryu252jjPbnS0C5XaXQDR1rIdAFMg1ff+lv9Gx6r1vOVCJNPnsoUq6DIBRh3lJgFGdNDr6rZMp5q//jqK86yEMNoN+VipTxGiTqNhPNwUGFRrlGSnfZbSlvkDlw6bFKW2s2utZWC5SqvKkIOQh1JnU9RDippIDx5mXHK4fa5hw6QpEVaBAAf95K2fRrUX59GNm0cBR285IBVqNCEW7Bw7mfcSYl1a0iBrQ4f4IN0aXo90iXGaFHj9LLeju0snSBDWN9kZJhO2/A3zMuG+aZo6ShJYVdM0eIEvQKNNq5Waj/2WufZi6Ej5mXkl65bV2UvXDsmUPRQrqVttEjofVKi6LZIJOviJ5kh6OFJklOu+6cJ8hT1O+oidv3junCOd1xyaNOq2HdwkMDd0kQaUdZLKhK7uJgUUrs+6zgQpNILjoNHUbREqbY1Gw7OFEYQi6pIT6mJRLG8huZ+Ndm8mhHT/RwqfAlHghNheCREUeGJNcY+v1btuRwj7sSC4PUgh1bWKRyuc1gRTBzsgae/IT13XWoDwJSBQ+x8Uv7otQqCPZdGsRz5lHumu1pTBjV83z8wEESrK4oA1aJR9yD4uEX+uV503MqzW5jc0EKfNqTK5NqcBwrV514kglU5wHPS6RsnsvTbeSxmfKlqmlaVwdSF9KE2mT7zURTe3zpqifWqt/e+gJNRtEQJN9OwKaSv4XWcy4G3xU7CvdgY7K9hX2RwfVCLkxZlmm2gdiYPtArzgWylRkbVptMc8SVJwzElTljBPXiZ5fqlv7BJswkY/wCRdgez1q4sS/SJa7PW7v71+dYUzKPz++m/essAGYoXO0w9QT6lWrprbGqnE7DxPsmuM1opYf3UeFtMYTls/RWPXuDE0N+QV7alGyDQ6zUg7rTPNCLvGJh0ZashBlN0bY5QjWkVSbCKA7AzCsWmqbnlsAqtbHpvaHf7xU3sSHhqdSXtZH7cVolZGawIZ3k2+gIuj1agjoV8B/glLiNguQnr1JUweiqY+qhEf3TY1nHIrLTRe/cdqgtdNO9Mj1jWno7u7NEuRTEbbH6xHpwG5H4Q3Nfhl4xIi/XWCeIu1nbxZCmGio+rHm0jc5UnMcIE24yUyANUDXKimZNQRnjw+jv+SLG7o9HmdlsSR8KXI6+XEbf4nBOPTk5av9pGjD/A2Db62QqE6Ssi6+anIFhPwh9jwRIxJNXwM8odJNsBcm5OoGLrN85MpmxveF5quyfNbMIFx0a2mxAAcUuGNLfcN2hCUXRrX6xLkFUjwz41pMHnTk4iMqvFLWDXZ+GQ/AWvsSJ+W4GKjE432qrkdbPRph3zRlMkSVHBKB/4FSH0vffOvqY49L11zeH+OFM66aU9LJvcaf4AZrPfq5S3NTvgS4qM36m6x1bHFJ1B9hU+dF+drge/ZJMyrhOFHnewpjfTIk4jRDQ+4OfaUlQuRElIg15g8bdxg24IsZJAtUXTNO1Cw9w19r9Au/VNa1YXiwUQZ4E13iLvprBpKOE7WgLq+CfIxvSMbOeMgZIA33yu4+JnWS2EwZmhhUBZVXAdHauGcbxr+JinhhP5zRUJn+XKvnn1tU0SpeoaLFT3bFMl7RpW79uwSLiBcwQWtxE6Vb4HSUEamMAILgzHXcH5+HfVdnXSwLxXJzpZIH4qnin16tbbSxgIkr+04AIXS46GCwtfkitDjteUWTSVVmIeAFXVbwzFooIe31WqhbuJx3tnanMTYrrCbGoZFtv8oyIoe2tVe6HTKGAaCVcdZzeUl6XJrwTcQTYbtIObqtnp6hUoos4LGQMa8CBP9YHEkhdJT097a3dQwGLr9R0Eu9dCuCoUztKYw2q0GJLfpghROuJI5KBZ1W73fjNIKsuc+7LRTjEC5kUMVzqu+syRbGojgjeoRnhTNeiKn9iUixjrFDqIpvHZDa9MkuLmCOd7HTjGytqlphvUFbbao/KmjtXNebbiDuA/n9reO5IByX5Kt3E7CAm47Grkm1Y7nRlVHHJECVLkqq+CDlmSqh0E3UA5vIdlsxhGRgm+HRLHzL9rH30LR/KMB3eiDNh15Wl+UaTJ6CO/Q0OgRu1OMZpKRjB1h3Ps2WhtxbJKxrY1Nu1nCXKcNb/1QPOVZARYRnrM6r3pk0cz4z0hA8gr2eB23QFhb/4Tp/dJh62K4S9fkiwwiMwuMH8jQKvgTkicvFn8rDaWjqioSHJW86I0V+alHRCtJZfmZrKpw/67DQaP0uEZyEGltkLazaujWACXrWFeo6VoPEW5XfiVvQQTZlRjFwa5UtxXFGvxKvdkxXXbF/ipmsQn22Mo9rUET2B3sS8VNcvDvJWySg/WgrNMSfAcZ1PBdpKv2LcFj4DgGGcgTGLgtq0a/ZTaVA20kzaANZJNFu8jC2nRwgtrQAsc/cYocEGQzmojHTX0Yj8+TGl1EzRBDdNB/6rai2CDXJUgeEMUnCvQml3Tj7u4Iz0Df8PEPMEsfYfniWX1y28c6uI4XekXsnWvInzoQlIa42egAsYMMgDIIkIUKSvVEo4yhlA5Od7NEEjpFiaSTHaJP4y83CkNMOVDJq1xaPPcriB3zS/gHfjPS30HAoDnIgUYOYiQUiyYEsbZLcQ6fLiGoivysKFtumt4N0vEvJG7vKAcEYR3QX56ym9ruBuz4eWOuanB397WYIkXN0WKV5uarvX/9JcqDIIxui5NXbouu2PnuqCmaKPbSMgjJvlMKFrjZLIhxdoIWobB4Ch7TYWXTyX+Ele0ClJ1943hC2J7neVSkpzhGhGU0D2ScsJB5UiwhkYQl4iEcFjGaxzKO0bELqnjD3IrdBaulbmh4eo+hBJPsNNSwUe8YCw3J1hIlkLnf3h5Z3fmu0IrkmFcFY+5ylEPfDsnVGslaf8d90AU+J1KgBllx/0aL97A8jq7P5YT/tmYTgXiuFTh51VmaoYFFeLMd8fXTt7wb9gV1tOSfBMs7Ab+XlGtZXSbyVhXEx5Ctajn7ZjV84jFaPTpbEuiwONJFiyps96Adqrfi1KE96E1XhTfy41HjhtmMocHkZFK86z63qPPnOxG0RphelFt52nYVeCgD0L26aBt64BhB+UVXeweF92dQTTruVZwXTy9ywllzgNiG7NSuwX34tgwhOYiWt2j9NdIjZaa1Wrsq32ymspIst3Sxah1lYGLw5g9QpiDfpGs/KVa3aQ4CLWIz8gMvq9u6emgisLLh7n2d6g5B4zTyBeTNHUjwJJYXaLaNUWdxmnX0TRtuN5GOxML2M13EQ/Yp7rUpUEFCOddoZEu0+AeL2uoQ56iq0vscSVFK+Oh8oTuDfhfnWLiPEsS+fcczp/7kAl+Cdb0JV5ErecHOtJ08XkIqM3mIc+xDfJ3fmvrbHUHanvc6E1WdVI1iDt1qr1n8blgcgiVgW1XlWLOuH/PkxKJttWPVopbPYH1drLQU+w6WxeE0Yrqqz7CZ+jHOmvjG4puGB3twdIXeoYnmaL2GzzX6tFqPnx4fp+b5o0nL8MvqlLzkdVlkMeJCZjq94kXIQb266lRvRcrznM94pP4g2zquI9Q7Wy2GyiMmeR61bgFpjRul5jXSQFtf5VhwQxLD8xBxMTmsIharyFGWAsPeKYKmnsnFPVrql1BLqUvzGttcImgP3K5uS0G38DiaHRIiQ3RkkRXl1R8NKGF1eX87+qBa39Lin0gS6OD+6LGj7XXTCRo6rxAmtJDDJEISpQAbksNEVEMMs/Zzmj/gQN85c9i5WlvbY2dZ2p12xprXinSdwrJzhXsvPwOOw1qj02xx4j9j3LLog6Ix03m6rkO9DFEvBhhDz/FApVI/sO4NC7qRazmEILkKsJi+000Tkj28UKjpoW6fbh8phBnR5+Y8/lK1/x30hbqtiWIVuFa/l7pTnJEavaqy0xzDBxtIVzBBvBJnEIZj1aLS3qmNdMj4ubgvhkPN2RyQ/NjrVXZcLF6meGu1yGskL/151FdYPxXlwxTBAUgxvRARPmnKEubJS7hnneA8fU6WIL+H5LFQX9Sa9UPZiDzgDo/wRluLCq8zAYvxq8Ya7gukODPmkXHgiiExUPqxsKBBC+mmWx4Pu+GntYvy5U2P5LCiqtsyrKi/jrK29RNjeLjk11GySdhnC/+b73LyucAIwslqs2E5K8oVmnTqbtpY7X1OVyliseuitVaDg22wgFXLbXIAbdG1Z36MRLed5gs0s9EtLLftzRdAbuYG7nI6LAfVrG6rJX+ohdVimWfj5OGXsffRLeEKErffbeaz5Sb1qzcMmgM3qtsihBp9jxGJTy38/JpW3sfZpo7J/ccgeTjPSZTmVXNLHeF6+6sVGA8iEXWCR3OBx8qwM0cmagXrSbOemGCFHaqxQkxvtKoxiW/aAGo9jih+a/q6yTVcIXM6KLhIhu6gSNRtzWOd/UjhE+rqcvqWfXds9u4jNA33RfkSgZd5VAc+PvDxZHzcKfcIbMxhOnDxgYsn42IyFWkSFLZcrFZF/obHdGBjdVtx3EdoRB/LollPz5ao5Rmk0OAaGCkKe0xXwVGSXcKkwK9Wu3tscegAQvdmQHKQuLElbk6HrTYGzjnI93yxOQQLvz1sDFsbeFQZtiaHELbaCrCgHfb3MkQKizdD/YMA7rMAXmWN7hx3pFZj5U/4DPL7BtyPtZJdJUu4aDJ4DaoHnxMfVK16QyM5yJK6rUg3adxjFYt8EfjGJK47fddjRWvWxfpbflqWRfB7s58BeZqjrD1eSsF1T/OFZ82rJklgVfm2Sw9+8iCHo7u7NEv9vC1D3Wrz86Bk1G0dLRYl4pPgKF6YwQg3yTwXQfWr8+3o5MZqzx43AxRlp/KFookqQISd/0BQIf7r35sMiLlkMB1YX92WYX21vTnqurq8VDVcITo8ka3I1M1fYtKNHX05niOzY+4PaB3LK79wC0FSBmQHYTkIyz4Jy1lRNqvA4CSCo3ojoDrIioZrKTp9bNKh5fb3TGFFZAaD02YV6zTZxQAngX+loU1qKMH804AGJq1LHxEtviCDkrxN4yuwLJ6DtGqkNUYMIeahWJJ6XcTChPjznzDRvkU6zvUinF5vev8PzrQHgveg51W3mT1+OWrqZbgTiEJ4iSyHdUoldvHFOZIOpdlYkY6EVis3LDyddUQJJkkuooZ1jQzdiI5N72loZd83QKaeU5BBSwBxgqBPnwufKz6o1j2StzcUloP2V7dFkQk3uTVB4MZXpEfSoSMpFo7MitPjAeZGgKePkJVgknNkNWzU90LphmRKRVau7W10VdKSMYY6wfAHlaJua2anhcFT836cVr3O3hyiyVdrkN77ODC61bl60+M4sK4374x15GzcpozUMM4Ws2tLLH9aG5ISwMHtToQoIAp+EEMO1UEavaVxJE1+nCSnaMqy7lgT6pId2HYhVP4jpa2KJO/ThHK1k5Ak+NWh8HSoUROHXMF8gW8Ygix7GUnjfIVP1WeIBSbwAGNQPHKMB/2j0T9SigWfaBDG1imVX0dJOxRHKqMu3mNeOjhZwuShaIKeKmifn3ojoDoIjUZoZola3sn3bK6W6XqN4burkbHwnlfX4Pn0GVLU8EWFEPXXj6O9Sbcdr/fEslrU/jJea2hek5HD3kh02MalZltHeDXGumLQSzHyViIq4cMzGqalmqdYqLTNo9oPb0+MpAHtNdf0Oos/GnBWdl466xJfNsV8fQFeMAt8SiscKOmvtBQID1pL3RZPslClRWZiS0O2+LFK5UzBQzdi5Y2c2dYR5My6YlQ5iydgB8nSMPFLkkH2SXRPacCILmCZFovwWK8aZARf4I07cssMi2QMv0QsF2akW0HneVqnINtmTUZ30UqL3bA11KqLATTqKxbaNcRBuf5PrZb5LZuzPvdSyyRpePov8m4YIYtXvATBQYDfCAgP6lndVpzUAX4X4CV4SAL5+XLvDO3P1fRUeXiUyqifSan2ESTrZgO+0TdqKEGRakADTb2MSEOfftQ7fRyL6KBI1G1d9Pl834WpgAHP+3mctPauxrKoKiQWWTiX8agOfLatfOZg1YSEkR/Cxw1r5f1n+Aiz4Js6y6Ksh0tfU0eknSHweI0bNnPrId3CyGFFylh8gzgiKuif6otDCMTksCxhOUVbEz6rY7onB/9o2mfFwq5HkPf3PoFKn63Vh3R+FwBUgf/agP94gf5XsHuAyiOva36X3jdlu2Pt8BxUvrqteaIy9zAtKhVb4ZVL7vkNheHAsd4cu6tJrUkyAh/OwfWq9r8D22hkn9xjinQlxOThT7JmAc/zqxQ1CQZ/m38E2AWoKnz/ChXUUQINeoSj0+I6rbUvV8ZpZZJQ+C+wBt09OJ25H6+xD5AKFZ+gvWnmKnL0/iXMkUo+qn6mi/aQJQhbi+W/inx8OrRN/SzBurP/hb7b1Edb7Sdm3sJGflzgBS6CfinToiRaOeg8GQ/sGugyGPvMhXpNblbUitxeWalrkCzxaRxmV7SZxq71ViLPq7MM3FdDi/6XOfQtRVvVEU3Q5GYviIb0rLBT8AWubmHZ69WsuH39iljrv7/+RZguBvYszSDxAqANMRwqvdNXal8o6WDfi9PUTgj98aiqiiQlhOlw/KOBDVxwNLzB3eGGdpovXrVbVXWVza62nTm8G5ZCIy5ENE/XiMqIlX5//X8IA7Vqbjgb3jT3oXjKswKnfmFb+OXNm3eveUPsW96GJbzCMQ44mPEEVAlYiKKFiLlgv3SThQ/YkQaqEN+keS0aemmepGuQWQ+Fw2BpLOIeDm3xJR/gGmv5vLaePptOYHh5R4b2OBKaKPbbW4o7rZn2hr4bZ8OyTAUDw3qyKduEhEmZPnNtbBWXSkcyLY9K58umC/ylybk5lRI2msXc1B5NmOmULd2qhJ01ErNV3Kwf0WyqVzKnNn2hqs3G3t155UVKnhe96f5X8rQcXMbILKQLByvakLCtAvn8LKsfwgR8qp8nmw50VbaGMbtoCFum4Z/9HYMxuaeCxTa2nzHZIczAmOw8WTHm5oXvWRizP6Qw6koeUMaMmzMTezYU8NprRrKH4jF7MZKqExOwkIquu6DVPqRVawYfrdGkYDdgN5oUVkpG0lWSMVUP78JU2jYkDGbJuEGk6STdhTB9lfHIMrRgr/Yj0KT/0d2qx1anBVlktVwoE3W9su2fzCUkwpkn0UutWZFuAh1nRSKbfvT157bjbhDfpI+wfCGBRQYLiwHW2HAexhuLWsZrdD9HWz51vZnOCpPS2YqrqHpzc9ZgDgxLkoEFhAoaDvOxz5TNOCyjW7NTUI5iOi5VzpdNF+iEL1vBpZYbWR5+ZB7d4b2sagwzMOgO7mZx5r87QDZFpXFHKwOWMSYN58KVUvxz7G51HZmAr3R03oVdbsfUzDAYnjCoJWVFjRb05TljkxL+07W1NXrROKLpFKRxPm26QtfbKs62XNFldSbi5x1e3XXjmImBd3CVJ8kZ0/z+C6yXxeLmEiJsKQ6kPcG+Aa3z0VxVxsRsLRf+tWhPto8ihRG9kVc1MurQtD0iRoE3PXplp2XQUrrQgE5kkbZgT4n5BVo7gglEWTtHVlvJtspsQtw/TW1iRg5OxobDrU17BuSx2rNePLNc0YcJmEdB011iG1b1mKaZlZa4LMTiljCSVkvGZydpfyZkKimtbdpnKs53IN5fet08MqHiABFUeig+XL11OBQXMUsYy45pfcZ+nGYZslr6BozdZOGjU4FDb08KUbo8qNHd6NjcoTb1l6+go8dwXcSdLEIzskVMQfb5DSjTKCbQWKb5sloPqUwOs+irNiVWe5kGbS9IzzcZp1Q8pK0l41dZBRem1Tco4dxN0qxt41yroUzAvlZzaNMPOjHdLDx8nBX3F0VVm/lWgJTxag/kwp8i4p3iSWX3J+BD5ZzsDO91T9reDIyj4xIeWMWBwzu5bkwooJfwoYrBt4MPVSOYiBVV82PTfF9nbo/8JXxM4dMnmK3vmizHNi9TYHLOG6pr/PRCTQ9nval1td++G93WcbXbwKZz5FvOs4NPv604G/vjZ93Oa7gyGwICpIypeyAXJhYR75QhoOz+BFypnJOdMARw7/u1Y2AcHZfwwCoO9DAEpOglfKhi8O3gQ9UIJmJF1fzYNN/Xmc8QKLLMrAUZKOmyXmROt8ZZhDul+aRdn2Itls3BTmg83POjvHrCUQCFkCiMZQoKTsVnLYgrt9GIZZahhIG3g9ckHZ+I2yRzYWXiIfhZee1HURNXVVKUixuKY3Tsoaij4kEa3JUTVU0puFLO7tvBm4ahTMSnhrmz5dm21nycC8tVWuEMTd1Iepc/Hqj6bExfTcq/XA0n/tW3pjkZwgAjnCDaEUkOHv38cCZinD7jrJYgO2rqJebFNgMYN0FK2ljVlpFKV9GFfHYd2KlDR6chTaAlnebYpj+zH0eeFWWzIm5XI4OLoDJuHqBcWFeC2olPowTkqDsxAWepibs7bETSIFvyEQurZKQuMbMjJ3HIZ2IleS+m4iU5gXeHmW7Iv+2TadrJpgCVbOTMQTRSCftQfdu6NVPV/6kYTzIfNk1vam2DEmu5xkLJtEMeQ321mFXMt6V8J+n6tAqPmQ9rvtsC84viF7OVRA04vglGIVdxn5Svt4QFFWOY1IYT58emeVJhNlZs3/m1jCSWActYsXuyw54NpYjtA4gj2W+6XkzASDrq2jTP1pyZo4z7ARYsIhftps9D3vfJuG4ndwx9nqnvOKV//6L3kFdMxSXaWrpMZXQFn3xu8gY1qce2j0uthjIB01rNoU0/Zk9VJh1Jq/mc+KkV46m4t21NwrpSnb2lfMsMYi6mZebNphOkwryLOwnT0fMoB6dc3l3j/ni8u8OCip5PtcKLc7FLzGZKdyJAjsBwu5jQRNn7SdluB5OXfEzv6hOAAyJQl5eggoufab3ccJCKXQz1ZGzZV3HhSlMzKrUo4/54d9stezUB71lOgxUnSjHMzpiMETGwkIlfpLV0TOlrNeoblLCnSgrm16FWQ5mQp7VzaNOPvs528fB3WsTcGJmpOhk3s63ujiFqP5i5mFo6nzadYSrOa7Z+LWpos0fawClNVgzibLJSeHeHNRU9n8pYFedi+/dIl/AJic9FgRBUvfwYfe+6SjI2lMC7MKS2uZ3y0tuMZAJutZm/nfDgywZiZwgYa1qrPen+x6UhP4EJSnqEE1aSW3N6IrFgqpyZrtceOay7s7zIOz6BvMrnYfsXl77f7Z65ZxUTXzDQOqZz9cXJG5Dl8lNw9fawoHQIE3KidI5s2h8QzBte0GfstYtY4aAjBhvwmEOS3gVZzaqeTGU7q2hsy1PrLYhcuYR1U+b41StoczNCDi43ByhIN8tZ2sSO2cy6MUxiLevmaSfs5E2nLfWeqkL0S3sxFaCTZVKQZk9A2a5lx02+yKD2bEZTR26lsOBuloq6KfX5ITWG0RYLi55NYoYYp8KmF5taM5rI3EiMy4ayxuhMuJvrh3EYc/DrTq4iwihMYRWqCqNz6i7GWpgGMQeb7mDkBZsbz8ShUmhj5kTvdIk7yZjaEUzAldo52iGWvFrDJL3rbv8f1XWZ3jY1tGVRfW0Ny8orerCwoQc7yNJ2I5qOxe3meBdYXj6Sb2v8542CI5WruzsuqYGhQeNkbHh0R+ZjthLL+UUlYLhTWCz+vGHlWZRi2NKFRMvgfrpdT97Zlhxtt6xlTS7680tc+NhnX7Fs+MZf/lo8c0thvyxfg3tNfjgRViM3HhLCYFabYKg4XsazDucPUKYgr4dpOSlWt2lOAG+QxKSPsHy5TleavLZueDSE06DwoKl1h2R3L+mBj+aF9ezodHrBdU5tekbXm1v4deOz3NBZoNgKjt/h/Z3DsLZDNHZwp2cxqn80qARxxvc8DZIKGs9WiAbTIYl8MAOfczGQdXQ7OF42pzY9o+ttG+/7rgAeaj8CQ++Tgt8erb5HqrwfitlTZ4tgHgbXuuOEMe4ay8/hfXOdbwch2BpnGz+4HyBrhhEK3OrImlpkDlJC8EQQFX1/1GJjktqtlR6rAc8nSVb84SBVPIq5hctpa2Br//t40bbKkp/ZXN8Lm/zmCqzWGfxQPOVZAdSZDeTgkbmLQy5zG/b9HJ235H2ZkLvklLY6DWBqzsZh1yks0agTyLw4ouQwObiMwwZIFx5ToHd8/oTw2dxrtH4oE7CofqpsOkDX2wIGNTkiBMgR2HIX3QvK3k/KhLvrQqDC8duflh4xVT3Neqy+9GCxMivb2yVmtRzLdEu8aRZtesJU3CJ2dmfk6VjYh3lj2pbqrszCe/ugPoed+lma1Ti7u/mamgMOK57kqgexqKYrPtfatlD3mkc4hyyYWcBeJ897Xa4uSmwYpStQvpw+J0uQ38NLUMOTpkRNJC/qKGJTTWnMMK7kFBxsbEW6Mev6Po52tu7TBJxpPQt22lqJZjsYlPzhxplMlfgsyaKfmRelnZmaCaUEd+A+pv5sbHcMkofzHPUlebhqbqukTNtYW+NtYlNFGQsq6rgwpbHZnbpibDuaCXjbdj5dnFlbx9WmTZih3sQ8vYs+BcuxzMjQO7i7O0oyybvtSi6Wg8uYd4B0YVcFeseDg/lZVT+OCThUP087c2pwdHeXZugLvDElBxIgpTzZAznxpIB58kf8lF2YgpNUhLVpe+7sZ+T1SjfjU11F+UCp7+KsaWqmh77nthTNxN8JGxGN9xFJzBfE+uAe3pyVxcrId5o6cpcoDe7mAFU3ND3bWfRmEuekkfg2vaDrbQvzXReurLepMSrjUc3MznZiX6ZnOpHsNn3Y1JpxC1Gnj2hyPhf3N9RvPJmafYSyjnwzMYC4bSfUrciMOK7zW7itMI5nkr2Fce6sbEO26lawr1FVyoBHYtjddDvqRjAxb+6k6XiyhMlD0fDh9sJndZZcSwTSrLnSuk45dG1blzG1MMat427X4U3A8a7zbSUFfOUZ05cnTYlIcX8BXkha//M8xXhND6loasmTmbMV3PKZ6xqzf0kkil1r1ZkJuNJqBqz6QdXbGi7s38wR2MaWR1QIbHjT67Eqy+Yl3GoSjfmVsuvoZmB/03zbdImvO5s0fC4SkKX/gou+jzefQX7fYG+AigHVVWQcL0C78LqmKQl3Dz3fOq42j2MCPjbPm00n+jozcqzF1s60pXPcyvlu4bbi1tNMu7cd2bWdkhulqE6NasCyj7JbgbL+dvtPmNS4CD6j+U5Ix0CeFzXB8vfvFTzJSswG1e+v67IRVSZGfQVryfXV6vWrtlh5B1hgRh4ZbODidAXSDFn2IFniZUSOVQJoRN9fgpRh3Nwlte+joWdGVG3/k6Ro5KOky43IukX3C6yXhXSEDIAZnSEaWtqCMQretVGrVmzRapCZWSetlNPUlxmRnIAa3hdlCmVYusIX82jSpG5KKY6uyJYgOkwMhDV58HtPaQlVYisBM6OmEhhKcTK5I+0Grp0IFsZiPlr4LyBv7gAhl044aDAjahNOJ2T9GiRlvmGtNyDp4iWkhBtCTEwdwSygkgJSZiZ6/wKWWt2xEGaEaP3DN+cekSUg7RkDYE1sstDKhYEDMaI8zor7i6KS4urLjEh6S1eGZLPVMCHBRje8qvFe7xJWxAySIpTAGZF/hU+VSvX3ZWaZLLLsKK+eFKI4lFohUqGwZgJsO+o4oA0RNPUElqu0qpCN1sbNSXvFwZgtkGe0LOcgO2rqJTY025zR6gZ08MbGSOyMioOHQjs018U6TZR4SKkNIqDCYNeLj2XRrJW9IKVGRMRxKMPReWEtV97v+Ii+9eLINasE0KxmP6Z3aCEsF0bsEkB77DqEdvRTKYyh0A7N16KWjm4oNKIR3yCX00v6VrnFmqeyrDaPL1siUVGMfSbaOFrqkU/5MJk3WI19Y1/SkvePf/HMzjyTJ8XXGGqq5xhMY9Ak35eOR/vKgldj9s3YEo9k61dSiqTJt0OkSWqraUCbm9ivYYfWbJuwwe2MVJrbzqHz3fm4obEhe4oMM5XJxmhDF/LdZHf90mgukfuAio3BcMXSphNfAFESyr505WbCLNEmldD0Vm7CMQBmE15+LUdq0auuVjlsGa/hap0BOUPK4GwdGC86xDyMtY7R4ORAzIYFzCHiWK1E8jDmrW9/Y0W6991cJjKg+V5q0AyFZjZPlnDRZPAaVA9SNqfKzUPrr1BIh7a5k2LiPQgqxE8/YXq/lJoDDIAtug8pskcqhZjwMHZ2u0n4JJcmjExMh8rKeZgNSzZy2xAnJuc3KnzPHhXx6+vRtYGlRkWwWoP0Xkq8vsxifgkptFqKBbFyHnyGNdqkmqZYDmkeOB94JKWAGCfmila5zqsi4IyWuuy8X7U3UcRzOLZhg9vO10Qd8Mq7LDmQN3YWM9RCczTAQpinsCyqClXMNCh5GIvRS6XfRurRr1plArVFZusHPGs95ZtyM72VDhu5r4Y62DQcD96cpdjyoirozghbaP4EdnMorq40nLgPI1OfVwpHvFYN9GfwVAPUiSV/js5SyI16N+zJopZ2LKzVwJgqBrpZU4tFKqEVd5oak17UTDHnu7ZMR1dyZQ2aBGOyIN2OhLq6KfMgLnu+eDOcM4oUVUCqhyevIKOdcAyqIZoCq4RSKnQRqNSvGmYqyXJ9aMfDJfmIRCUuiYeINQaV+jVIx0UCjHoMPKiMJvSyqCGHgGpcduld/DdH63WWwsV1QfdTJIoWXj0qXTUZsajYCQ2ttFgldFNPQRTKbfjThm4DtMv4+koxaTbgHFfkhoblgR8akkkrWIxQVi8C4aRoZYaYdJyxFDz78qtavWteiJWpYflDsBYcYUYmIxEbqBOLNoMO3Ww1lPQRYY3DEqpo6GSp9ZWYx9ZifMNme0EAtR+V2WLwJNc0RgPt/9YZDlI49WBk4DIScZFdGvJIMU5idjIts6FmSoZS1zEygLKqhsXsyWhsREJSLfZIdDXLqBTcbaBmWQ0j5DQiy0b03VzCqi4R08MFFVAoUtGilnqw5soymgrBiRpyWrQgWzY2Iw4nKx3YeDMEYEooKQXUDE0GL6UXF3upI5cU58gU6vOKaWjDg6hHwEHK6EEF2WpIwSOaiAhcHKyaFCygeRzs1AaThUUnIY6e63z8EP3FIKqjEk+ECKVxIAjAUm/EJrJb54wQcUmooiRyCEGO0yxDOm4IENdQhQO1GA5bIwJ9OIQTEakLA99cA9RQSYA1j4qvoqPTJmjdglwCYpkeUk2AB71kQeWb+70SoukrqAeorScjnyIsXkNDfRMSQlLh+8GE7O8MaIknAqlHI8DKiETdYtAQRkQ1ATFOihU5CdlcppDTQ4DTj4MHD5Y8KVIJfZSk9t+6XMLHFD59gtn6rslyrB2ZAs0uxlTTuOEwIAimqmUzGu2masaD3P1FF61sikDq0QmwMnpRV280hBJRjSybuMGe3zc3gOT0EOD04+DBg7lIilRCHyWpfWSzyDIto7AAGhGg4aTOgvY2lE6KGBQjM8bmHtdNex9LPnQaRN9zClI1/OFWmYEINCqZW0RGSU8S/ChqYj+QbOr03TY5OVTg+vEoaoWrXQ1uBd0UU+BDPe6+3A13Y09CQH0NzTi1FaXcJl7409FRj1+zbHVjjbfbMxJRAWmxNTMSzXGrNzmRdBcotVs/u4rqIVvVl1HUcEVUQ2W7JkfeLg73SrXUlUCpxyUCy+hG33bVEEmCbAqKkKhLM0k4MMMwWGglUfpQUBNVOHRTkOWGvriroAkNYxgBBaqgBjCTgUYioQFzETkmc3T3oLWc0cJYzWM7ljg80eKSE0OgaJDSoK+T69QGBWcj69RYYqgOCp2KQ+QE9qBNmyDT7NGVwqkHIwOX0aa/Lq+hixTVyF7ctk2dPuUgTN3XaVFrGkylO2W5BW42aZHU4WDyCuphaevpwsH4BAYWsWHyNjSxYaNRsssEYUlGSeZh8/jYxMMjEJBNNmxkZl8RJP4WJb14EIP8bCCVUmh2l/GYpiGBJqxEBLLpvCaExJkQ04SL9BlEbi5Qj5eggoufab2kMoKIpDFVUQ/OUFNGNir7iYZqJsQqdorlXJQldrnZJGdR01BewTxQaT0d/Rw0k74NCSmVcxSLkt/pCbUmJ1vLcbxM5TEJyzY0ut7D+XkMqp8CMeipDaRS43XJgkwaj8I0JgkkCYW05qgWXj0kXTUZpRT5kDRE07Ywsh0ra9sooeZKboP1FBtHvL5z5Rm3SQ7ElCTkINTjYgFVsZfmK5AcnjEFk06odbNJ06UmAgtoHgMDryOJ2USTo5TFzqmo7L117uNgjR4FHtC0B+bgg/bTPK6RnQpM9jSDNpdC6hSErIJcK7A53rRaR4p0ZKW96byZhZSwFmdFFozkePo0MTvxqfNu6BTaMn2kBtepEGUtuW4SUv5p9ZMauXozyaQTj09FnVyqgR0GqZPOQPpNJaNCwxr/hBLWYVwab0UgxabxXbAxZ+Y7QhygJkxABh83dm5aEskTW1qQzFDROFh9fc1VK2XSTjOBDW2OfP1Kk6n0RpVfVCLeHmg08umOTaoU9FlbdQrCowMyg9qOKaLLiT79rKvwaLH5creewhOKmbYj1nOqYKqA5AFMkl7llDFgRhLQ0MGZA2hcah3V9j8WVTQ5g22zLVijMFLAFpOG0vrMyeZJsO7CdJkddF0yr982tYOoYl7Jx5yTSY0oXUfYB7y8poNBEUQVGtNME8N0QZoojXkQbawp8pAQf7HwkAUvOs/L9X3rWvPVuq734LWG6hjU1hqmPMyI9G/fBVcUOsyFHo8zmbToHOaoT+nrPlH6HqgnzcglAUan5bLgqPttFbyd3TmTqr65Aqt1BjcvSqqpw0Gah8RWCKYQh27kDLTDSxLMvQsZfRSQ6gHJK8joQ791oaGQAuEEV0Q2LWuWeBHIZiiaZdyZLJMu1ZSfv/1ptn6UVYxSoaqpkTbNEYNTC1MT04mMPgQck3QzEY171NZwiuZS3WHwaixWpBYf83WhvKbxyU7h8Cs+iAPSFShfTp+TJcjv4SVAW7XhnSCJ69lYSePnNdWVJ7YqTBmTzXilS87mpaS4pCR/WNOQhbYcJFMpBtVYhGOTS/Ewk/YY2FhHPVJTVWmOFeUzU7qsIqaGRj4iVrWvWaJMVdwHq1muohJ1mqVreJTKaG8rINUDk1eQZm2jns3SpW2TI5zA3h7et7rRBA6JQJqh8LBSslBPbunIIuAaOUhIePrKfEnYVaWpKykvQ9pLnAb5yAqMfeDr5qwsVjrS6cB1tpiyltzw454l05p5atTTku66cCAcBWw9tk2dyESjEI9MMurFthvh9TaZgleD65SyspZc1dNv1mmVvRqvTL8JD9hFJZ+O2aRwdgPTsZgXpSYLqJU+MXcjedVOEmBrW1c9ZFsU0qg11Tt6unBc2/ZkZJc8Bxgh7Jt9I+/mPE/rFGSaGyi6CuqRa+vJY8GFF/604eA69ONehpK+YHgjvj5oJqayrv3AVShsSGx7acqyRQnVjZPqm6SVfo/RnKFVDq0esrqSMjcr/4ykhqAa7CMntTOtSJYrkWkFMq48Y6w4v71tEeCgYpDmsBzKfnuLHyxege7Db28RSALXdQOyL8UCZlVf0L/svanZfXl1tQYJVuf/4+r1q+dVlle/v17W9frvb99WBHX1ZpUmZVEVd/WbpFi9BYvi7ftffvmfb9+9e7tqcbxNmH3db1xvh5aQbKHZ5kpxuvUFPEvLqv4AanALKkTxk8VKALtagbL+dvtPmNQkuvqZ0yW/DVTuG+wfJKSPK8WZw2XYPupr4d+diw+3SNxkb3DX3ugOZTcUPUODxAqBjBcqzk3F6gjBFRIeUPai03X/fIHIUWTNKt/8zfOfujb+l63ffrHH8AFSz/zSiJgCB3xptc7AS5vDmcPIFjnj7FZ6CcquxB7jefUB3oEmqznibz6LuH57y3EAz2tvBWbjNADPwZb8LX3KMozRJSi9ON4KzzisTzXOI+KK7HF2KgxzqCgQQqE93gtQL1lk7Rd7DPgpXH6Y/TcHQUKzzwkQ+TKlwvmSrmC7H6exbL5ujeBtYjxCZE0VxWIhXuqq40hU397HJuXwsCX2GL9XQxTN9zJjcfJl7v0UUAbiO05zgN+xkaHsy+yxdlfERFZnCtw0QC5I3+arPSacgTSvBP1GfXZZSL/iBPfsIko+bY0cM280R1o2wxbLqQT6okzRJrnmWHrz1YH5ymLFMR754oZBXDw2X+0xXRcsDvy3S22xF/03eyyXcJ298B0ZPjrjEbvEFDgonRNO15y41D5OErY6+eBgPjVk+8aZTf1Hh34UC45n2y8OdCghqOHiW/695obEljiMDavs1uPEjG7z2Q2XpGvUZwdlTqzvhKQW5LUFX+bUwwV+yxBk2YvQSapka5Q8PdQwLU9j8lDz+urj6Pl2URGn3mOPLWoipsAe3yfyVBCNqP3isHoVJYeh/eJkfpaiybT56rKBq6qnouRmafPVYa5ycJvBq4qfr81nN/O69VcgrbZA3JiCrBKtbAnI1sht513v3wQNEVwGlYfkGuqPZKLRjV69VDWUWElKIBebP8maBVzQYULni4rfASiAPNppn99UN0GVu2Nnn4dVNiIBc9m/kR4SXHhX1Dml+enWgLn4RPJ01ayIG/No1aaHZr0jYrkDdvCsxy4pt8fe1uhf6FUTSgfnsI1oskzpshYKt0fNGUPNgzSfAbuPMnRGOY5+3HSAx8OWOPBrPxCBQekCD3wkQEKJdCh18a1clPAKZhA/fM37WJii7eXzyIwdg5On876Qhnkk1GdXMVBgFApdDlHaM0v+/KT/6rR/SMSlZfPVHdMFLBM0oSQ6QoaTLp/yAONqibYhyjVILHVy8SLVSkdNca5ertRhN5Yu4PWyWd3mwk6RK7LH+SOt0lv+jHf46CAnzW2WVktexVGf5zwpju9J+r5eKDCyJdum1KOocn8FPrHaxiNRqO6+yGWXV6KRkeeoSOyUdF1QwDgL5Hm+SB/ThcR3JwXYE9UZuC9QWneLVZp3T9dylh1T4s5fcIX0kWiFSoqd6Pv0Lf+E9u4XwrLJl7m48to6auUqh3DYocIa/Dt8eWrvQzF7U6bEDaOSH4RCN7zXac0ve9RnB97KsuJp8LWQLKHc6OUQDi2s12XxCBeXAD8le9VwZ3iSYgdtUNQG9HII995fFzXI5PSRQniNQd2IEsj5YOy6OEo464stscf4OV2lNe5Qfy2YRioUOvT0oeE6iD+4+Jry5g4kdVPCEq1o9VdkWPLaQgVj38pHxE0szvaLy95681oPu7HefHfoT1dHZjTwZS6Hw380aQm/1UucXaS//8qeEssgnFvYmBty/Ey5g/w2SG8B/MItMjSOFgsOGy/LRmin8M4hzRAX3zl8d48P4meW/u5g/udZK55UDiFmEyApd/L1tuL07U6BXw7hTo3T53VakkjID+ClklOGh3Fvhdz0IhhksqWGcrBuQMVnpmJMG7HYQZsyNfnei6VOvcbnmEf3JYSibSqWuh2aDhWvcRi+cHrKFbvI5XCthhdMqsBFf3WVTl6SDH6G+T0fZyuH8G3hApZpIcyjCsajFWJgEDSCJpZBuFAeH4a1p8yCUmSKXHCeIT7oD9l4pGyZy45rkWJJBllf+2SJ79nwuy8VlEv/r8Hz6TPaaQnXAKgCF3ynlUBb8skhPA08n6Bt332Bz0a5KDW2yMkmQ3uz8/wRSSyq3J+GCkaZHMgpej55kHuUuSJnhx6pf/QI0gzcppmAXg3l15J8EHIIp1NeDXax1GE3UDy1Y+/uRfOTKyt32iWldy/E33FWlH3/jiHamwo7JTWgw2EHSB4K7ELAd9yEww6+0HG/rU5YI2y87XPbqNskrpDu+F4+73II1xbaI3xdCzyEI93goqsqhEBKip2kDq87x83LcVPXwh00odQZ88+0WmZpVWvQ8yAOlGl1TQYRu1+gfZjoGZNDOBw/oN0QqZom/DUCpsQpKJxH5YzjW7aQoNl8dfaGngjRgkyBwxqEX5cAmaR3bIkfxqsalPgaK8Q5/8X4XS2kX4un+cKqPR7OgcM69+JpjuNQZIwmA3CObWKwQBn7aAGdo50s2tMBOu3E6Cyx3DZMl0BWjROt17CSJtqXjMMI7DSW/nS9Olqvs5TfK0gB7PH/hOn9khP0/psDdST7PPed3c90wSPpPjnQSzKeT87jGdYIvXrRgHm0pVMsSqA5D+KjhgnADAoxVcPH3QwO0Ix1eKZG8J9xZe6BQzjZgXj9mi1zsfwr2C1nEkeFWOqB+QsEVVPCNkG/FDsD4dGCLMRWKPTAi39ocdMArqFl5PBS9PYJhc4ha7DEMXdyJ5ECxLMNTAN9EwOE9yg2z15qR0KDbU0Yz7Bwh91n7yP63AN51FXHieTB/4bFq/Q9lp49cGVOHnZVbCNXtC1Bk31tmfrhy1z8hZ0dI+5smBJ7jJ29IuCjvzufjlYnRbPG1xUWwh1dsdzBdlBg9cPWzwI5+ifGv4pfWQjHiIP2jK198E6IOKALt0brdS5z7JYKUXu9591D7amrbqvaw/FyIpbNVxfjM252qeOiRpt1JVZJsYubMwWCa5N8cnHXtXOtiu6TlR/C5PS42sBY1amYWOqAOSVBSALKzWeXXt7Dq/Rfws3N/qtnWGB1XbTXfOT4TbDu/f8mOw4RCh3dzZf4+Q4eJ10we4jryI6v3QkA3EY3y37f6lBTj9zb/5HCpy+ClSgUbo3B1WnPwNsiLRKf2yKqmuMYW11zstRhXJHLiYlrhjyl2oGFPG0YU+AS4bL12b66c8M4XMjg8r+6NDVPRrx4GtNE8lfjM3vMuo1+eOJVCcIAP5oWyzis1Tetci74YaMGctlkUJUGxQLc6ZBd7s9iChx2pmmWYZ9vn9eE25gKpS4WbxfgKEctKXZxcbXpOLCtyGZ94V1dajif1i6UFw5kEF4tsImFVK1wUD4t9RMg3TlpwPxmiSgD3fQMAA5u0+e6BGJuYOrz9qhk6sQyUBdTmHyUsLb6tnr2UN2i/ASfSTYS3u/MFDkv61uS8X1eszOSt5nF5uN0NmLYftNT5fHz8/WdV2doY99sLpQJ9xX44v3nVvoiZhSGpRH6M60ey/YzLt1/yTULpuzAwF4MHI9zA1l2Dl4NNwNiH8vRVFAdfalgDsdfelyHQ6rdO6Q6HM7sy+HMXFErnbR0b4VEMc7avCX+Zpmq/vYbZBJV7KyG29GLEbL0dwdsJB8Oh6n75nL9IFvfNdl/worcCufvIXCFzni/Fmq0Q1l8kTFw93mFf3+7+29CiBYrM//dJ1SLRTEVr/fNCjtd6rvDRmF91L58z3Vp89ll09GnPuJ3G5vvf07F7qiDj7Pivk8W586X2toj8WTbnKjwmAKH8xE0hIuiEpPXUt9nnyVmpes0XY5FJnDR1KIadf1s21esoptCe7w/QdWNhkVJf599Hr/Cp8pf2rS1x5U20VBhS+aTX0wUWRp2+vvs835RZNmPAptRlzDBD7N4yK0RxUjyito9yqsn0QpgS7ZuixIYV694s9vBWJvaShOfx2RLnC4CRXqfKMYLUPHeOOrrnBXlCkgSHfOl7pivAP90M1vi4MiKnuA3dlqpo7u7NEslHlWmwAEfTgLEu+i6b9O7j86rNn6nfzKNoxhX6BA1owgi8osW+gyQhSrfV3FFc+6GcFc+F/dpLr0EJ5a6Ye6TRymRCwBbs1Z1sxN4Kt/PsftSpaw5zkp1lpZVLbI+9dlt5kVUm6/TrlFIHa9B/iJYtO1HFzzSWDq/+Lwa8Tv69pjmiaCjhUKHPgqJvE5cE3e1bPeOX9f6r86Y3ksxvXfB9F/pGm/3QSbefOWKHKyCZZFDWaZppsBBfvoUuZz8bD5PoeXnsuuJDATfl20lycesV9Xc1sN0crxZdRG+kpPPTZErTnnWDL7M4RzkqfgM6xptJKtCFD+x1AHzsoRQh1tS7jBHDdpcpYkUM1/mcSfvB5A/Wd2VzHQ8G/1YNfRQeiZ9xD7iGaaVWFweysmEYFt1VOyAn/jceX6fI1K3SZz5kyu2yCWufZpHb8d4KnYuaaPt1UBho1H5yJq+/liO+Hgbgwimxe1tCR9TIMotW7JrS9RMzN2fNYbxdY/F8xxXXnUcbv4M8vsGp3XnsNDfpw2jOS4W3Ka2/eIaedi6ZaXPZQ1FDji7YIau7onoiZRDOOiCzSNS6kaUQA5zBO45orRfnNwZW52V688ZBTxWROnOuSd61RWmw3ssHjpcXXVbjf++xydNRtIQSJeCodDh+DJP/2jgFZTsyrkiB9dbBu7PV6g/OD2FOHRJsUPQZc25n8mH+WXwT22TtXdDr+qSRFxURVOG7jtkGH3k3ArNLthtfe9FcWJL3DFKrhFzRS4HwWdlsbrImnv+bUe2xOkgvmgSQa6oz1sjBX0UVRjn91g8Y97kVXeBw2PsTMjr05zB235yWL2ajFti2i/zrAXbbskfdnK6drbP4v9z7sjmuqI/RH0GXv4a8HgGw6oqj7Mu4BZlAbBT75n6J3J/FDUve1zRHtvmmPDh3OfJd7tpiYRzXhug2GlNWeziUDSTVTFKAl6y4H9sYFUj6xxLlsQeYIvnPKzcdstqR4/66SPYONcKMKaAqwXy6tvq51O/xuz7FrMikN0rjB1V6sRNzG3Ll00dzN7HmZP5lkagtyVjh5/Ptc7DcpVWOCShvfMUuOZz2HzWfyOKbZXBuNcOhvRt7D5t+Lo1HHT6XONLS9lRUy9Ro2lCAhNicJMOswdnuaEbh8viXvePEVbfU+V8gWlyl/J2kqzcHXun4k2NSMDs2/qGJ/a6eICc04D+7ojtKElgValwMqUOFjmOa0JWp0pfyMq3RtrPirJZhQfSDGg85FhTdxyhvS7WacKjGD7OJfzi9W7Xe93nF/JsIRdbcaNt5xI3Eb4kbBFBNggeX+FQVB5HOkiLPIrh42zSgUkge7uRKXC+MSC9LODoXGy1J+9X7L7aY8Lvv3Bouk8uDrCqlmVmob+7Y1PNpKzcHTvJui3F25YcdJabzgLhyspXT02qoj6WRbOW6qmhZJevZXwd1h5es/Sf51BSWDSl5hNTcFBYljxzyLc5ktlGVEAEs43g8VWHisrb6u/a/otl28Tde3ZeQ+YiTGDa6XSXFUW9ccSENCbLCMAUOOIT00hRn12OIiXvAXm8ARR359Vdee98CELOR6HU5fi5PcZSoJYUO84LvnbYCHi5Ivf+ytGKpQ4uxPbtKjliodAZb3vFWemfVAG5c9xJU5YwT17EWwRyCJcW2nqXgI8nYEvc+8weWKpkRoRy2NmDWqZxqM+ufN3c1jhl83meZKhjMvbmITxbwBec9S0MEO4tkLTTw3ODurHIIQNb1I5NDunaYqcSNGPjITxb0IyFh/BsAdUVZU8O4amfkJ5PsY0JsjMIpSSzAI/RtpSYFuAx2paS2QLcKXgDVxGulvZfHflDznU+nNZLmwTdpsi1d2LWe/q7yzWZuyZfwIXsmVG+zAXrEygXF0Wa19VPWEI0t3xgnwLEYZ1bwuShaOqjui7T26aGyn2eHjKgxeo/VpmhqRbEffVWhXzKyh1CkSLn6Rws77XCIl87B1jifQFSumjji9TBCWIRmYmhh3QJXikXYqjX5qsbJtEE3Xx1xCQZs98Iv4DqAS701FTBuPX55PHxvdjj9qsbptPndVqSoJcvRV4vRaQCgC/+/4RAQmW+3I+DP6QlTOoP8Dblb/eogFxcUEO1Lu/spyKTuKNUUCEtyThIDeXV0jHIH8StlhTAG78orFIAP/znJ2rUuMwLa591UIV5KPfCfn4LePcoX+i+LhCbRJq5Wg7hIGkNshnL9F9ETK9LkFcgwT+FhU0DF96ayKR6yPAWL2HV8HnFTbAu2nGNMyxo6CmHCGlBNiI1lFMkxGDlaQakAXO5vFImS1BBpRdWCuCyr0rldy+YAnePX5cjUOrv68vcseINF0543NTtGq310llXcjnwiZP3fReOZeht1CVcgTQXblYoQOzb+ASqr/Cp26x/LXDEayLJ96YB25rjoH7D/b1Ce6dPaVWHP4QuQemTU9gOzTiHR4MHkpcZ6rujg0J6OOG4VOxa3qeP6R3ZP0VkLglKH+ayQzMOc/Vt81jo7w4atIKLn2m9lDKZUOiGV5Iqhvr8J2DcOLwawJ+TXeHvzDGKWyTvhqmh3LlfdgbHlznsDiTeWncv7XnV94BcRwSCzSQFcB872piuZXslWbmL5ZOk6xSbGoJNyRV54JTcWOLLHOximGOrXzR9qe+u2CQdZAocPISwqoRb8sNHF27akJ0YfyI3SQD2WKsOGiNC+JFnyixN3RHDkHCDitChTdH09uRFxOe6/9EAQmUW1earg+GRp/VFmSbyk2Gx1AOz9NxXLHWhpKq/vn1V99O3j9IDZ49j5X4P1C6v0kErQHzbkJJBAeJgMhiPSUOPRzXHot7HoR+KpzwrwEKSv4wrclmo+qpKs0cC4BIpm8C8gj0OIVhfLHboO9KfP2F6v+RfIaS+O4RANvkig3iV4YIfqe/O+vUE33iVadi2YLuW568kQVbw8ozR+C7P8rpjLs/hS+lXIfvRV7+ER9fF8ESuLJKeLt5jS5H20MbxG4kYfdxGVljG4dS4sd7tEDit1H1zxXKMSvBrLxJkQ5Gb30m2m6e/T7+X2zkJwqdIbSLWEKnpsXi+uiWvut2a/LoEyQMamOzQki9zwIrDEGV2ClPgeLII5UegfJnTOWH6CEv5a8FC4Z9AesKdFTSmACma0mUxtCk5B++/ezhA5LLp7D92dzTMZsPUTZlfwj9IBsxA44VC5WW2aOuPxEaRLrnFZqC4hlQ8v9clBFWRnxVlO1u8r50rdMFLph2SvTvv4hAKvfGqIzm0gO7zJk8+L5a6cCq4u/sqJo2mvzt4fRarNJeG+LElLpSmxFd+dVABspuhPbMt+gX58wQp3xgLP4vNa/E3odhuzX0Bys50EW+60iWu/jkZRrbExdjZ0Fh2JC0rn23THvG8ZgzfdD8qxMKwhAtyUCEfNwsxx2p70Hc931ytYTJEJm7mPiydsA61T25hN3zjqMWY4icfybe1NCDbAOt4G+cszZDwCUGxfJmTCn36lndkUL0vwBQ7e8V35/kN3WQFGhQazD7GhRO6kQwNaR/s+H/ypEn7wYlj8GA07tuhFFq7xg2d/iUPS0dY2REe/2VcWnnumZ53Xn6AMkVG7CAJJ8XqNs1B+Kphxu8/j05IR1pBHhpuscAfHCJya/7h0vaLwwkjyJs7kODbeSXa1kpvA6tgHMPBJHFgTmE4ML/nL4/33+yx/EwXPJLuk8P9KclB2Cf3YB1QQUIE2XGxUOiBF//Q4qYBHKzwqkrvc7T7TQlHnPMPMMrK3c/wcIpS4foSV+a+8cZBkjxWvswl8Ez2FNDm6/64RpAGTR7k3guuyHE3962pv90RFF1iR3FTJ4Js++o3ypIXb53bRYdDV0m5yZKVO4Q3wOcafRIfHaO+u12c+KNJS9l9if67hzifFHldFpnMy6uC2f8NQVyZiyBsk0vZUZYCQW2ST5NuKD1zMm+X4iY3Q0fR3u2d02gqXIFuVD3O90GhgmVgu8bNqG5RXv3RgBJWl/e33AELX+i4DTpa/LOpavF4XSh02NSQzYcKsVjqspZdlPAKZjCR3KpgiqZYa1QYiTjIFkamwOXGR/6Aj/ek9otQuIfBX9cp2uljfgxThgMaD82nqbv95mrsDOn4KVjVIXxfNscxtItfZ65zhPYFg6BjA/zT55RAXm9uV7EyAqDk3AXkgwPTV9lpDm4zfqGgvztgg0lTQqFP1GcHh534qNAn5xeFivticGlxKwJbNOdK+KleZcfF4oXvIv3dxQ7Ka8TYvd/tK6yfivKBN4fkME5KBAncC5GWPkm+qIXlMM6tnD4nS5DfQ5KeTN+YCnRrVFvXqdC7Zf3YvB6tV1XdViWne/nB78UH8Va6x5V0LOyfC1Qo5DBlilwth7OiXIG6FqJlxFIX4zjs4SClgDa3WVot+dWD+jynYt2mgDvlqAucDPA0X6AZ5eaFK9oaFUbYpPsUwUjrwHxtNWX1cbRZ2zyPY/PVFZOoHenv4+1e5tqkLuEKEncTsi0DN6o0Kp/Nqr7+OOxDGuUOLNpPUy6okiR7zgn2doThjkHycJ6To0g6y3AY6ymQejChNaZx2DHatYuIfpi4Fxh27h4wHbhzDVfI8Ak9KJNh9GBVOzTbuofAz51fAD6MaPN1j49dT9BE3RflSxxu4rH57ECNKA5ctHVc1AfSRmEiDllAXO+BhXaHhT7CHJZpEin+g8fmk/LYiGLbN5H/Dl/al8AZTJuvTpgEJIc9hZSPj5LsEiZFaK7uAY0H52rqbjvLxvV7jHPael6dL3i3bv9ta9jwexmFDQc0HmyoqfvnYsOrrOHc9e2XOQLTVc9W6p+rnMuZnCzhosngNageAp3JFCYfZ7K2+rZak1dI+nL+Nsfw0cEvKTzA6fr4pjSMwCeGoC7W3/LTsixKwQ7YFLhIA8lOU9aCA4gtccN4mi+k+Prvjv1rkgRWlbyHVJljH0UaUp+3RgMMz94GWlM9Gh9rSl13HME/WixKNKnCnYDNZ6fbV1FeWpMtP+rFZy7vKARVU8I2PDbQLUqj8vGH6utv7YpBnvNDm7snbLaxGpYtcgqnSAshngJ/2mNvRjf/H1LUZBV8pMRj82dIDYoDT+45T54VZbOKd84poPPgSgscI51tUm2KL+GIpXOdUBIC8aiGjw4mfLFOEx7P8HGPT0wvSvI+SJdiPfRggsbldS6hRzASr0c6xz8ri5WKu/kyF85U4WRLnGT7nzCpBZFuP7pdIhavD7teHAaSS8PA0d/YGezHL+1D4jxCodgL9/D2mxI9BbHHGoNsa1DB5yIwgJFC5OXE19QeaeO5aVJ6KV0sni1wR5bO2COT8S4zJ8YcjUGJQy+ISeUYRlrRRtgShG9UXJ2cs0X8rNYgvQ+0/nssXhE+qqpbuwWNZFHgC1sskvbLnLcWQm9/zOZgITZ0pCBIFpmXe8WAYVtZ+zhJyIPEnXeZZwBJ8S6KTbzz05YaCXnqUzhp5srmv4KFX5zGobkgy/gsX0zJ1oj1V/hUfYZ1Dct4jio5Tg8ht0U0kqxLWxedVzo4Rz6XsPd4h0bTLXk7Ekl2soTJQ9HESokloPMx3cw4tnWh2+aUcOSFPLxP6AKX5bjVUC79vgbPp89QIANT4EBV8NwH7AvuO7bIQW1seYK8eEbGtiiWCGnS5DhjqJhJU6MJrQv+KhnAlHrskHIsTHpne30xaUr8kskFeMGtxnpFWobV7yVpS0zjyB3fPI9NVm6PPdZbvDvnLubJFpfbIrDZZHr9JcmgLOE8U+CI7wKWabEQVgi2yOUktAYZqc05AJgCl20Omj75i8xMyRxulFhxied5Wqcgkwo4X7bHck7SCaX/Ilks8UBC1xUen8+KYoFjHFk/jXYNxO+yhBIbyfkkv5THl3lgVSB0xyW5rMcUbA3XX0Lsa+8zt4aubTQur5VNj2AcXr/ok2i84zcCm+8e2N4rsL3faxv9pCyqCu1GsigcxWPz2QsbUewvV822kgZG/fhF+0wY5YOa+gwfYSYsatR3F9dlUdZ9QCPnrqRLHMIMmyyTImQKHEzEdXd4yRFt83muKCb8+KiQD3f46LJ5voNlCUsBF1Mw54lL/NSIZyV+Wx5nKuXiUIfPLtFkJOPtJ1Dxm0O6YGtUFPqAU3wGXohtkfjchVXV3NaTnz9R8onNmUvoDpA6vfFJn6irva18snP2Krm/ETjNGIXPBMvrjTO1bUynOMH0dxeXUZI1C3ieX6WoNuA24mKp00EHqCoceIoKavlxhwjgYi+0lXmDof/q4GpMaz6DSfdpyqisL7AGXaQuZ5yxJW4YlS9XCYVueCU0oz7PH+t1CXOkno6qn+niHta8IciWORwLkhr/VeTc0Onvrth+lmDdmVYypEyxK26063iSzJRQ6Ir3uMDKnxdovszpGBct0vyTLZuvjrKMn7AWxZl8nX65OqqqIknJu8vCmoWWUhIfeXO0Xmcp5nTKYNEsVPp6/PLUQ6uMELRGLsTVX9nAzVXRlNJHj6xWuwG1bNnDxBz6EtjNa1Bi8fbsZk8sx27+9lY63yEsMfjfnBhiU0vFDgo3mhWZe+xbzQtDJ8M4oUMzNSOQADf0J1pWl8Xi5hJWdZliI+kEj9KkIWxqC3tZpk4LaKMszG0FsgnXQARmsehyoPpoqTc10/SutxvqioLuaRwRWnwDp4Xp/YNm2opYA6d/QBhh4iWdC5voDs9sE32cZhn6PLhvLWabr6Kacpe5ZnEG0pRDFnPaOdRhjOncMWTIL1I8n6/Oq69Nlv3++g5kFXQcfTDzXMBylVY48U2bkvKGTv+p5SFTTSHHAwdPg1uwl765wNkTkEfgM0OHA9cUCtds+saaVVQ1VNrGkTXk6LdxpdkXFriET6BcXBRpXlddQOzN9woufqb1snMG6yJKjJXFGBKhigVfGBsKnAEWVwQ+MXd4GxcpExniKZzeVHexcIQ6MUwcDmkgH/HYYmocHvc2MpB5/OFmTrdx7/6/Bvd620YGLiatIoUbGBsrRkQcarp4uSSsOxfFX4IwRV+hel8rdoiDNIclDzI4c7svw99V/wFPKLiHX4oFzKpNPZzTegXIiKo1SMgOfgHP0rLCoeHgFlSwBXn9CvX9MUVarz9y6xwuf2QnWZsOqgf4AvL0Dlb1dfEA899fv//l3fvXr46yFFQ4biC7e/3qeZXl1d8TIrcgz4uaDP3318u6Xv/97duKtFi9WaVJWVTFXf0mKVZvwaJ4i3D95e27d2/hYvWWr96htcLyy//ssVTVIqNnnDo47ea5f0H9e55yvPHbv0OB0/oZvoR3r1R65Le3fMXfJLyFu/D76xRTlkgjeYqERJcCfK87x1CQ9Oz1K6xu8KXQQeW81aJvT0vbBvJHUCZLgAyRL+C5vQPx++tff3HGyRyqWaOuSzEEQ8DMvpY7Bm7KjutI7jh6nCDtDjRZ3SO5TU1I6AMWAwPCBi7avBJ1DZKleGdmZzmRGhvXEi/efz/PF/D599f/F6n591fn/3HDVP63V2QS//7ql1f/t3M3Ou2IWYxmYB9OaN9o0jDpu19+cWbTs7R9n8SNPm0tFWGsxAOp+L5VNJbbNAfly39bgef/7orJqHLe/+Kuc76kK9i+QhCE2FoSPxRPeVaAxZ4IXz+cNi1I21CTp380MCUo71KsFB2Roh1Sj5dEnNqqQ3X3KDT9BHuxYI/vmHBxHLbuQhRkTOiFD4tsLhEVL2Snz3WX5zsGNrSpgU/jLm97IlebAA7/ZQTn0jXYOu76EiO1sP2cl6frInpXr4sxOnoJ19mLW28d0I7R45OT2BiPkyQ2yiGdW2Szp40ljKC72CsLLUJ85aBO8Yy5GotY4W8CEfzkGyMxdsdKyXP55txMRLZ2mA3NJJOLvkzQPd2TdaLLpaazXX/91d1sare0ZoObxW3Da5+KSi/kPv29KMo6RJKQwVnKTKbwjg0x1ZERt+mAr6og6xjb2a3LASk3woGo1ghy1+XoaCOG9kTwmDHRFwg0E/3XXzysmNNncpGAOf8/X1Sx19+hmTb6ytTCe4+luG+CjSAbYSzdGEh7eO9CdljP/NLm7CjI01WzIqvb0YosIf2yC5N0BTLsvUa/KuKGfvc3xHLY2Yhm3bX7aPATtdRi70P4YlEK36+1deXyIiH22l7LtIcnx02+QBKC5HFIrYZ2xDV/YLmzimczPndTja4bZKgxWev8OYXNzReGi0sBF38R49lrT/jpos+e4MpMQ8UgTmrp6d0JrnpQV/pTuhAu7EPpx9LYww0EWCZowkkKA38D0MZicd7I43QNGvXv69NEbE4lMA4Y9Kd0Aa+Xzeo2p7ZOPoh+oPm8zYIm4KK5zdJq6aKwxjuAjOrhYPMxOCFzVcn7pYhxC2Er4QUoURdIArAhj1QYxo7TkfpNH9OFo3smXO3Y+Y5G0Tt6U9YL59FilebDG1MREPaM070ZEjbV+Grrt/wT2mleBC4uPY5Y6om9yx130RKudEeYFupSd9zOHmVZ8TS4A+BjCp+CFsSj9bosHuECv1yb3181q5BZ+lrUUfH1yEjuUm6wgf2LhbI7urgujpIge0K4s++P6uqhiS4iIG/uQFI3JSzRClN/RRbURqBjtfIRsUxsnOfVx/SuPgFlkJXV4whfn7v3Fr7VS1heMDeU/XrWv98wLPV69ehzinbU4I1YnSZ46T9aLLgmg7p/Xg0xMREiPcKm5nuetULYowsaGSJ6KyXf7gR8XpvLDsnp8zotyY74A3hRYXQJZyF5lwnCcO7+BKorgCwRGGNWWUzu7gG+fkggGxoYPic6ui8hpG03z5OXDaL2NeAo4TVDWvQwfdIhYXKah+g7Gt/FkNE8AkYmo3mI7xCfSQxPbIbosjM0qf0BR5BRtmgvgoCsx3ayxHcLfBxLll2nHu4JocBpFURC7rmfgP0CyHFq7fwRiRhC1p82BVl6dZE8RHIT4j0RwXf0CFJUN80onAFuIGkfvVavNI823s/FUzvW7p3fsGlANnx690L20WdF2ffvGKJtUQjaY5A8kAxM+IZL4MEG3qJhfOctDdlHCAMmhSxf3VFkjIlp8bUHjjHwkYHDRYeKCnCKZooiNsfAx83LcVPXm726p8hg6J9ptczSqg5H2MlyBhFfIsXM+Dx88J0ge5ugSpMwPzONIPrS8S1bjNtAt804oWKHordxtUZ4QOY9EKuzEaqN4e2U63QFIwTx0bhP80VEzL2r6TSvYVkF82KnvRiscGQG6jTcpG2i/cJ1ClvZDdL5aPGEVU29VLjCtw3wUjIqs6L+96eNVZcYLGQU7ctvo1Gb3aZER/8zXYyI/dO4tBlWpdg6Z0AcV+HEOjGIc7raPyZFoVB7HtyjDrbl1FU68vQRli94Vt1dL2ztEMcLfXva54YnXTukH8eggt3yGuwoGHB9gaBqSkhuhuvDIL27O24M4dAM/sE25eGRbON52qSzErdY6FFAFy4ESxzAFcNNwyDEZIiJ72pZtJ4fsAlvjxjRNsQq7Uf8hDGqwOd6cE+jcL/49wrGCdpSh4BFNxz6pvw1iKVbjX5GMsx26CyRCJi6M67qpGjWODJ6ETRrIhaVR8Q3JJAcH5NVMIxRN3jw0u3gV7dWPPJs2vureHzCmXDkkStiK26JHOVyXNTIAoseI4VT/cQWlJ7t4gRKHcKRmHDDOGc2FykJMPEIRu8rhhj4OFrtKv0XDBkBE5xVXRftjQQes5cPt8PxjT1FsDF17KIIkQ1/CfJ7g8/eLyQ8VkxhXJ/UFkZu7YTPYt8izmUUJPdif6Tw6YvEZrPQwPZR7K3q2hNjqBtNzAQ5Vima/uoRMQ4LVa4cBvVffEIOx0l00x2E7RnLzHsDbTybY0Rd6uzk6Xaze5T3rx+Zh2t6qBk6czxpL5sMqpMBeGm/qzUc3QHTvZsw3P0PipHqw9ViINu8LnNdsAkQAnzMG6QXyohpr6miENPZIWIj7yms2AgEYu+M2CAKnz7XJaATP45hN9EHTHui0owOH4+kuidFVpSf4HP3VHFc5NuXV9fVlNozX+TMtpTCC2TR/qZmUAfOqzO0pWw2V1MiRNSOzIH0xaoDF8bgQpqi7n1ga/9puHEP2XCUg5nofnmK7oeTibgnE4fTBGPvdu804eBs321nu32YQP+8XfeG+34sSv2oPEzkoWaYUbJm3gOLJ/PnVZ9ZIShQZlfZdM/4M/aLDuYEuz63wcz5j32wqtL2+qXn6ZCdFeUKBCZi6nFdgc0zQduVjCjSNeKju7s0S4NNYXLfNMhOGnt1P6/a84I+LXlINIMmC7G2y2HZdj+DqlauKfOn2sfd+1zcp3mksFCMr7/GbIHS5fyFftDRzTQQEIRsXGTvS7p1R8Rg3x/rdbfnuP1Ydsl7idEODTGTRkMmXWM9nzparUEe6T0O6fmijRndVwySEYQep519TPPEw8HAVQ/pyQl1Yz/QFCDy9C4msvdRkP1Xur4oKpzpxS8US2JHLYscyjOY+eWJ7DM9zb3+2e9aWinYE+1p9PS+8/D0Eudb1S2tQcYsQRTjutn1U/EZYmKdV4XxLsl7V767XpYQ2uP/iyt+JCKwTBMOd1DKxR8gyGTeqvzL3o5Na6FnX974s8j+NpzyRHsk+D5H1GtTgQW5vid6VibCUyz23E0bVXvC3ONZuTOuq7e3JXxMgUy4Qu94zajQrfn0OCvusT27Jyz6GeT3Dc6058yjm5pBTCo9Oxa0tJ0jxua1SIeT29axGiU7d4frRJNgwU6kNwmwY6G8BvdxHH/beRH8EE8R/+R9ii1ur172RM+Oshb3NDppMnKjSH8k7H7uRw4Or+AIm9WzDNyfr1DX8R0uI23cw48v6/26EjquTdNGgF/VOCnzJayKptwbE3x2+6anp5HJfRLc9Mil1wP8TB+cBLtYXWTNfapKpmp5klw0iZrtA46OvsKnao+e8JudQyNa4OQZpziocAqVOJiiaODtNG7/TPuU7bBfDxuMHq31RZkiy47y6mlvYuzwgDyi0kmt6P48P5XYP2zzo6jD3t4Y+5IVItqecM3sy3w87mlD1TqdF+dEP8oSHS1REVlWPzawqpEVi2VkGw4Yt9MCGf/Ykz7j2hNdYN4L/vqru8Ec6e2iKBHACEnH9xiHgu2tLNzgGOA+Rpfwz0gBuuqpCzGcYLlKK3zuegkTrGn3l/lD1qFRhGlILBCG2HquT58xVUF21NRLTNeEGAN7Ne+zX52KFwnbz9Y5dacmItpOc0bG/g3z1nXxAONsIwm6oySBVRUPKYn/QBMclIXJWujOirJZ7dFZ/nWxThN38eqqhaUOmVu4rZ7htLMXLmxuWPpkMN61u5FEPgh37ImAkAG5s2hXbccFBM8jbjkwQVwbu6v3HXrkovraauIgZ9SP0Lfg8cUb3IvAFPwdFsWUe2IjidICN+u7qYH2Sfl8LItm7amBurrjhoR6PbMS+YTia7fqBMlyDIWCZU9mVB3Uyigezt1UT0Qs90RH7YR62Dd2m8Op3hJvP5iWjCXiBU6CL2oCFX1O3t3YP7BJCkKTHAR2hktREJzjIOwSN6mJ7y81fE88hxUDV5fEOiKq9t5h5ATpQ5qwpixhnrxEuyTeI7wEm+NbQ+r1v3lLJXvcFUbtH6COrczQpr1GspCd50mGumpJjr/6aeK+MXxrcIrGrnFjw6MAE42QaXSakXa6YZoRdo1NOjLUkIOwujfGqDGk+FO8NoDsDMKxaapueWwCq1sem9od/jhXywifjM6Iw5O6o7ZCVMdoTSBLvUHWzmLkN0cu4RMoFxcFWuCqn7CEiLUCE0cuYfJQNPVRXZfpbVPD2LtGoYHqP1aR8iJ1RoAiws819ixO7rzB6l9HGSOJiMPbGPw2TAmRHjlB88/aKV7TjrDQEUJhE4G7FM0wFcYXmCi8eoALFemCe3ry+BgnWxNGdvq8Tkuyc/pS5PVyBLz/CUGcsdN8+SFFyq3+AAkfhsRrDmi6tI6fimwRaa5E5BEZgUJ+DPKHaFspDm80EaPxnp/ERtnnyIqM9vwWRFqQOg1NjIKYSVxxYA4SiH+1r4CXIK9Awj4sPgr6aOymauASVk2kxLknYI0vTMcnjog4Yq/RvnOwieJ3/aLBdSsY2516AdJYweZcBqwoNO1Q4r0KTnDZtC7DUXxdY2cj3t4DDXq7cAlXIM2pIHWPqPBPAD/R2m1uvxbYLZ8wGYkiHpX0u8LvFbLtP6VouvYm8eLsj3CSqu6td9XCArImyGHyMb0jxv4esk4/NPfJ29QMmr/vFVz8TOulJwtx1YO7wmRgiO5umZJZ94RBe3OGmmW0lnvc21XgCTkw7Ekdflg0spvvvOq7Su5hAd568VQaaGu2jrhhuESDXafYEohlqQ0Y490ZuYI5tqtj9bBFF697X2BVUbdmA18R2cwIsc1me1PILR5mj5LKDOOJGscyo7l2Me+jpP9oQDcR/rr6e57W5GW9sY8bh4ZGP12cYjSTjGTs09B+v9Su12OTjG1tbNqNdmQX/6juQ/GUZwVYBCcjOq96VFEMo8+IxfMK9jiVNqHV6ou0/k+Y3i+9zEKbFo6bfJHBD6AGcRyE3Vvu+CJmHB51W/a/4gQf+7Tsz7JAf6XSpIRdwOwj6YrhbcYtNx5p7+Z+eXlmjzpuiRoUvEowHIMM4HcFQsy3avSompibsLiHAbT/w+NJOb7+CA/K4YOc1f48NDyjJr8uQfKQ5vcRzwBJzNu4Rgk5yIOxTho/wCx9hKXNG5Hb8iZYLwB75MUYhuR1v6OtGeF8SvQbj+49cLA96qbML+EfOFvdvkx7+HWpSBM3u/0Tw+90CUFV5GdF2fJKHCO94zhI9r8W+30fpLYhCE73jLhkyaEvntzdfS1iRbnrnvPmk/O6v4hAK4oYt8K2JdrEYYEsSKjPCSj3apEM15YXoOwMhyDPU+sX8jtmpeuGPX+9meTw49XZ9f/Mxx7jXZZA0glLxP7YuT/afjrG6rlzaq6b+as1omEfFjfM457ovJnFQk7bb2s2Gtd6r6LFFia/+HrEWZohcgdmBW6Ta3fkC82vPXLWeB1B90QA5EOMxXtbk2l+FkbZExbZmVnolMo1uN9jyju+ae1KvB+gTJGtM/Aw2kXepjnYJ4330LjQ1CoMs071Txj7vNgD8uYOJPgSUIm2VYrrfaGteJvNVk86kH6Nhf1nuhgP+adx4x5ABQnl/Y8BnZrBP9imfB5QqKr0PkcSmBKmNL0S/87DtdQfluBcgh5XSZjaIXv/fruH49/c+8HWDunHeRX+asXebfzRepA8xNiQkz3Nt6b+dkdQkkGOkSJPsbLuyXIayl/9/wNdbr4A4njbMOANbTcO3PjO3wsWsM8RMQRnm0efqEdyggPm/2jSMiyIkDL+8rossnD3p9Lwn4BP3hunxVWS902Ej7IURH+kIOKuMSgaOFRNt/fx9mOiFUP01oJSWqkKY+rx+TjW6miiyIry6o8GlLC6vL+N3c9257D4J5om+oA3+qFHG2Y1QUPnFcJ0BTOYBEa/R1hmorC0eckR+04aCl9pP6f5Az4Nkxll2xNsdJ3CsnU97JVine0YKV5aaPy4of8hdVs7xtY7KAoh4lmw/REAnoM9YecIfmfJkXUp7P+DcV5V2WmO4YOWjSuYNCV07J+VF5F+NySal+xzcV8MTrhRdmWOeD7Vq+y4WLzESn2Fdp2IcXt33ldYPxXlwwie7xUoX4jo9Cm+ffS3DEtgpA5BefqMRpnfQ5JPKrR/cmQO3XR4ZLnF/mfRhB4vlOky1LO43eNex8xR36mLzwVG4EAU+2ius6JcoSmjIkwiofd+B0UinjFemN//l2c+FDg522m+QJMZugS62WCdW3BPFFA7xrB1vsUxilHnvPOw3yIu4QqSDTdCtSeTScYU25BxnVcbnEwSMtX7Xc5Yx2OWY5A8nOfkGI/ObbonbBMjMH9eB8Xs4e9T3JukI3au4Qot8HtzQjTK2oFf2UVdE9LCByMeOczwBNH0vihfDnO8v3Pcqb3DFO/vFBO6psm+HebH2DCgIbSP0caeUoQ4Pv/JbFW/SIPxDNSjJLuESbE3SXG3fFs6xWmW5dH2+WLjLIsYVPi9PDDUlH6OrNH7JH2Qxgjv9XkrzN6flizhosngNage9oTPrIJ8bE8Ni3wRlFIM14zTmRinoHWx/paflmURlCfvMyBZIco6Qq4NjOs0X0TCdNUkCayqWP2iCTW2Y3t4y29PpND7ue04r37L3s9xHYGj5rb3IkFQNSXscpztx3Qbl+R3PksyeVMJjewJW0GxsV9iDhz7KHWsrW3HQx+Qasur/fGDH9hoWjY6K8pmtY/nKdSQoj5rMPsxB5mxsE3UdbFOk9kSejk4aEmy9D7R7Z4wZvhB31lZrPzZkK0ddrOt8O8GXTcsMLq5/SdMDDnwPEK48LW9OBs3fGMPBFmi51Vnzh6/tA+eRkI2PL0Tgm8KVUBMcfTpc7EvQT/UiHArHtskHsGOn95bPmq8jSxJfDz7wZbjmspG6/69B1Jnv5hDFMBqDdL7fbGJI/pF5WuuHzJ8rWB2sZc4AH3jiR228MSw/bMFIPjI+HGSkOcLO9+gmENZ14Llc+lGK9LnIo8Vc0+VJ6YlYSJ7xnkq4ZCdseQLHFYHsuxlBCH7Cp+qzxAz9R56OeSDi+rvkL4aamUY4s5lQuduCMKbbhvMZgigRfhX95sx4QISdQGR7fRjky1i4pOTJUweimbvMp+MEiuwlTl9yKs2GL6LbIyB87y6Bs+nz5AaqQ8ahKQPqQ1beCbMWzR6pIe/aO5TwhphcB4uCBFF9JzEwSrjkNIlrgQ6vHqUNCVOaX4BXjBB9uvVRX507tIjYojwDNbWHy7xo94Tdjh5STLIJuX1mgGM5gKWaaF+X9jyiKgGGcEWFEVHos0s3tebLCYzQnjReZ7WKcg8H29ka2/9xTmSUSD9F0lbRdreE3mTxjRbTJ9Aj5sTtJsomnwRlDRPESocp0N/9ekQySShvmwSp2d/4bwHPvbZ0NOxOvk+Wie9r8M4rI4ZkY92I7knsnrR33N+F7IUDVjeT7/rtN8xlkVVIds8O8xgnBl0WOj2JUIBjeQzfIRZmAF4tSzK2vatcrvwJwQe8/Hz8/+/vSt7jttm8v9KKo/7EO+++9sqWT7iKjvRJ8lx7b6w6BlIYoUaTpEcH/vXL2/i6G40OACPcV4Sa9BAXz80cTaO3a6S7z2lkGcqWOnPKgsBGe8mGalCqshzkftqb5GsRhzB3ub1q6d1drNzpk9tervf48J2ZdrT5ZE70abUuozIE2QLeRN3iKV18p/FlytMG9Ccj74Q+7cHulhHf1gfy8MuPe3F+8NdUjUbDzO6aXtLN3FR1AfNqoLy7GXkvjEvet4npZkAcVJL3k6AfBRl3B3M8/OEeN3geQ8vwG36s53HYya3ohpl5VfF52T/KM7ay2xb+N/s4EfHtrnPeXzsRg2IbPy26udXFR9M1/JVVofYM/tlnmT5mem+G3XqRx/dLc6O+tVHpTkZdc4HuG8jMr8EIH3PC6C3fzkUZm4TDKnqeUvHsvyOc5yxaogkxb2GZyyAuDqzY7VVX8riu0kw1gzhyeZYSzW5qT4tT9n+ulZ1WudUG2J30ZbhJK8CHN0sazRw5h2LURXHzjrUDJNQvF3u6NdhJvi2b4Lr1Y7VJK8qvKYt7JzrSVl8NwnGmiE8eSPy56SoD5e0mYvkNEtT3Kq3x+60Et9JPgYZO0ZFswkvV7QGnaZBr6sesh+f63XXzny2t1fQo9fv3e4rf3PWC+z4GIkir5hN68XzDmlQAXr5J8nQVg7o0VvxNRHffhfp8eGUHiZ+gD0sfXFOvXhxR6vwZIf01c8S5XNcdBYPcGD4VZo99hdqL9WXnX6sa/qsdbrKZjdZMeEA5VgzRCet74P8LL70tnDoGxy1E96XQs+7wrzO09YMEsGzNP0rq7f+Fs0UOkPkrhS9OhTfpuymy3WDf0Yv1wPLPi/hLza0fvIWGur0X+NjVpPe1mvHAf8jiua0tIem/sgcW8KwflUU2S5pPNtx+PdJnMS+vUlclvHuqY6z0dvEmOm9Oex/qWcj9TtR3w5pNmbAuRPpw2/jjx9PaZkc02RX8f/Xr//522//9aveZf48tOetf6kPbtcXV67jYhfvTXNUauwxMUDJFZkQClXA/zCYNmdj6u3ZOL3ODkWZx5XBzV6fHHbJMU51o2iEzABR6zo0qZe8Fsd6t+tQkppzGNd+hZkPPDQH2Izx8oWEKTbUIvnqOgo0hUh2rFqg+jM82jCMBUIWbqrg6GKx07MQLI0tKYyhqpzn2J8ioLnCYLGYJtVcDH79Wlr7xG/U/R/FXF8u+3b4bRasqQKrgmhFQdAFWigMsjR9OBylp5pXASdwz9twJuTFnwVOkIXWA6dxqrUInIajGR7jUjOu1303tjQcupGbGn/cekyBzxRh7l84mgwHSq6Olcnr43ed+IkoorvslO+IuV5XV53rDT/OElyMg1yQLIGxNag8A7jog2sIT/pw0+Iwu4/z+piml3BxwTBzcvkSMCMOOC4Gs+7zuqlYBg3ZjLKLiWQuw7M1BrIBYZYwtvxAfHl8zTgUnwIv8sDKrOjq/9GldavXO/STGuuMXZLAoDhK+cXEMFkrlzi29CJCVHk++SryH/f17VnUtzKR4lSlwGkO6BANfeECVTUMNpy+a5JsS2NiGMUhd2PWNTDXhIbwdEHDcl0jl1H5anC1mRXLBUE1/5ql26rVwouWdQ7xh7hZOctnXLiU2SrNqQVbX8BUtNnCImYHRwUVuBLnOjRs0EFFAsuDQM3Z/34ikDNbucKqsLeZL9wKwDb/l849vC38tdMuht6KqrWkzqDR3tRk7NSoLSie1otmgR98zRcXa6AIAkHNBDMgkXHNGWHMude8EkzatnUAryN+/ilQ6IKCxeCHX5CfC3dlNU+p5PpaqSoiUPR1YUyWV8WWWrJ5TCnqOGBpMSj1t+M9gsgyf9RyTzYtDb9tHQBgQoeVu54A7fl9eHVgcO+iM0JCEW6503D9Df/h8UHb0LqvoYaH4cdZPjJ6ThVIlMBxpld4BlSRGWQQlnSWiYWQZRkgOwSIi8WVi48XgBWeWWhuVL1K0rQa0cNZlSZhynaI1yXubRcNLF6q8ZdHQ5dcMoKVWOnHS8uIqYgylF3Mx6vXyOXjtRiu2pdI7sq8yT1QNAOiqH9+BgXXQCB7dPxxFnBBkqvygARBYAYbLAzMQLU4fOVHhRbBWp9gZRv46qVVZBh/3DyOBlU2gZ0+/8o2sNNLq8gw/rh57AyqbAI7deKYbeCmllTdrG1+2DxeGjU2g5U2yVBkCu3qqYAoaWU0JOh/DrOfz/WiB7R0inC41eTL4UXPDitn8LSuMOq1VX8ahfOgi8r9S8mnEoZBoG6SOdDIzoWM4ZOV/HgFYLXt6mNAoBz/E4LUGSBLA9SSd3nu9U6nCLqqZS5bB5kRfLMueE0F3OrAtqEIuEbQzRXxzgbespHuzff6Mbg4vTqVT3WLu6ZQ+ySvOuJRGqgZ+0jCzUdAUj0XQC6GxbdZfnpuFmV9Aw/fXxx4Ki1Jv24eF6Mu2wFB81rm3Chon+g0YND9fBk4AJ4hXTUQoua/7/LsdERRIJEYzut+nuVD1DA0RQgEHcwwAcHDYjTKtYYQAsjt7rGQeFkg6PB9OW/EachXMPjAxD7HdSEhNPvoxdGvs45fGrEWA1HzGEGAQ3LU2EV5sbxppPtl62fjWjU4jFSDL+z9TUya5wXNnMNcPmoWH+H26Zk+FfGj+D2ppMl/RHBeqZWm4ZIlB+VRCS4mEZeiFofv4pm4QKwBfcU9RvwEEOPHlKXw1Ui47IevORG3ZkQNUpoSBDwKNxt2RkW2BJj15zBZBjYz5itxA87SWUreJQ/ldZzvo5tT/cBaIfafk/IJ0WG6Gy3XknoplMbGH8NFErafzgTFoAsLE6ArFoeIMtaBFZrq0kCxBpIclGeGQY8TAjyhzXnc01dcF9Y+yV1hpaOhNUFttjHSZJwpHl122PRHVor1j7NrKU0J2l+3jaFRkfWPs2/FtwrtN1nVQNEHp02sTwKCK+KA5Ztfu4S02sRKJoQzrx9By3B8PXCZLQxNxYrilmUT+zXvo675S9YLaSTrC/iuxGwAGvRY/2esF7VZMYLlnuq1wMgxFhzUgmB5RtmO9QQi9rLEUGHZTdo+NeV8iWz+2ab/VTP6gqOV8pQf6sd0RICzxoHGw5LI2tBGKbmAMbCszyZGv8MFnvmjyj/psdDwsuTYNmsEuY7zdsjy6nTYp4Lcnui2VSRKYMdLLnWCiS6RNiTRC0PuaGG2CAMgQzcOz1HE9UBoE1+pNcBszm/VJHQt/rkysLX+Pfg1AGvGHflJuFp6Y77jf3cUu+Shu314VZZ58uVUig1gjJQfkguj3Dr6aPW2AEVY9D+P9Z8RRy859NjxwANCqNBI6MqQsicMsxI1HULnRlBKWdZkAmxgpcGVr21o4PyUsflssC0esCkNlsZ8P3S4jx/tOczWMooYZYZkkUsvZLQgqeQwQlgw/RgALkvGHdqngDN/BohxHb4kyiryxYH2V5wn8aEcYut19vwlOTSEEf5kvHwfRiZS7sEoBU7LgnbZIGiR5GGueKEGCoo2SlGOFLLYa8bfZubmqwfq/N/dczG69FSdAc9/n6qSykufDgmOUYVIxoJacJHhETfQqqEni702/G03JnIgebHRb8shr4ecfUnSIARcPvcy5GrROOuyowdYrmatUVfirzg9DSClNQyDi3mR26jLEbMjDInhSXgKA+VWWwc86w0sDevFh5OcIcO2B4abG/1Fd/HzMRWvs2+HNIvxK8IDgbL+Mvy4cjTA6i2PBNX4i2HhPhF5pd9OKHnYreetGiJu/vUGE0G+YoP0iizSrxeRbH3Uh8NMlm4FsFr/lHIZEM04bXTDz0omiuNx1O4g8fqBZEjudpp5e8AyVeIwVdy5Iph5BZh1CPQPSmimq8PHMJd7m6Rlne82+PWGucKUphktpEF8OdcmrLryo9uy1yjKLK8HXslznP948333FB8exW1ciutTXrHY/SCG9x2BOrTvf+QHuUYE9Txd+0ugATmkVxiQtHrwIhjqgHVAo/njH0wsgAnF8su9Bh/v/n5/qGTZ/X13+lLs8qQ9K76JW1eI8Opb8RjN5u9gYZq5LBCsDnfrn+GtD3QzjuPPwdzSo/mrXQo8uOt3mTMQ5gbR1Yvz468XscY56rOZNc6rh4ckrX4R0UxvngwM1YbGX7ee+GBUhcNs6YQqzRM9QQdOOBQM3uZTSBc24jF12sRYp9LvawXojxVQ40cRvc2z5/lQojLXxk1q0ebxoSnE4Sg7Yy0Auc/+gcdK4DG6YsFha5l8rUz+IXuMpH/XjsIHGxqdOmrUymYawQ5cMWlCjV0om4UBmqwUaxSjirgKqG1iAWg5VM0Zt1zhtHjIun4Su7+zk36C1vgZx5ZBqYDMLJ0FbbBatGghz8ha7BkGjIiGLFzqVRfMg7k75ZXGjzfxjyYX8/tDUrfrKSUzPtzSGWsJLfXCbedZNvRh8ZQ8sRp89JndaY18+TlYJlVQKVK0sCnjpwHELyhdMsjrdRfD54dsF6fJ/4l9L2P0IT48noxZjeT9gUB29/jjLAg0xFaFMUuDoA42VRi0mTpxmPYSLogv3xOAcOe/9bH/ZYz5NzPW73b1bsXXRHz7XaTHh1N6qJMQ1y4ZG29WPQdMVb+X9bDrPouw+lbYdW2A6BvKnI9kmnIAO80AEeMGzFmY6zWaZZmM4xEn3kviUCmwnSvoqFCfL4Yov0cFIGOsEExK5eWOqqTZ43X23MwTmUFNqjJ3HJNZK0dS5N8vKFqhpnZiNzOM6n/fZPorD5oXGwLdhe2P8xx0ckeSpygFm2cd+OllWwxHf4hvhWM4kqrMHY5k1nKTyu8XFI5QUzuxmxlG9b/JSywDge7CGa+sTECSp3AEm2cd+OllW27cnaXpX1mZHB67w5XceZ9Wb/b5ns5fGZUbhRcUomjLO/FcAl/1D1eH4huxMiWR6F7tf57nlt05GPM140PMtSJsjSKuY/Vg0tLVoutV/AWLbUcuT6sXswNq/bdaJsJpezdY3DE0772VN01uqLpTVTVE3i/zZ3vxNsmL8nVcxl/iwtznq2vdiRLIMfXrL20pmsvrbvcknuN//br/klWej7+kRgNGFNK5iZPYv3mOk/SqLOPdUzsYB9iCdDB/kNQiyJiRyuA9FkHsxlK+qrSCVrWsrFrld7vsBBpTLYaYqRQWbt2W9kdRPmWQ/bRyiJ9GYmNozSpgymCtAoplreUqKUc0pixc5jhLkpG9xyQFBrCxCOwxQ6mFw3VcisfmDInBYSyCOIylNhMlu/JUXyI3TdSXgCbqC3keILhoBIQ/oo4o+hg379yx/VM/C5zkAgmsIBXlNYXQJoLyzILJWykGmSoUPGsTqDEoKHv3VGyDdxU/xofTQ9z4iohEKhUlh0zJlsUihJ27SmHrqPpkxOyvOgXYbXUiJluCH83IymG4ZmkwGEqg9odCmwJ1h4LjW18Cit8XWprvH3dGv8w6AcRMp7HxLKtuU0H3azWohvq8Vg5yVEksDMetLYPXWASxGUstHMajbgaHsQjiMJbaONRnvcRdmTerH0X7XhfADSQDOYOUFinGVXmD81gEcatL7dFRWkIzg6JUCMZCqZzBB+GAt80ONe3NfTTctMVUyGkpbDqI/Dkpimp+1y/wmfoYJKBuBpVt5vC9GtYe4vTqVD7Vc9D2dTtUCpocnFmQNSzSNbd4kc4ulUF8m+IiYnX4hvY+OyY7jE9XSDDqKDicMCZk+x0Fp/13eXY6Yky6QoJTR2Hh1N1nMJh0v0Ptd0XMYeyn+ublcKgcHceqZNRAVqW0SPEueaiGjfneIgVMBkkBUzKlIDjT3HhuRD4CUhnqTtbEtKH8IyuhSCqVoUzaYguTW/GtUvgmSw5lgTsMpIIYg4SM8Rcy7RqLsDEXa4LVEyIeU4spTiy/3YpqOnCoJ4ACDMFaOWxGhcSqnv5KPaCiTgKrqVPx5nLYk7jYrA6jp+Z3yPvE3Jke/dKwaS+SHLQdWWOSdGy5XCTi+rR53hNzYFNIeKsp5/Eh3zTD+JOVCLnIetPk5QtpWbfS3uhxXU9hCMSTxBkpyKs1XLN05A5e62pYpJNyyxuiSGUQX6nYOo/PwBXL7nd43p4x1kTH3J/ALKovgmdQfSlH9AFksAZDMaoIF6X3VX3ROPILODXUykGvqCS2BQ8sQ6C5/oFRgsshGLHDSuO9eD6mMdhTYTLbyuNIydwqICQwSaitAzbn/sOAMzYoqO8Ll+07cRBVR6aCo0kCTg0MKtua6Jg70FwVHcvAddGx2MLkU44zkcogJlKxLVBUtfenVNzHxd9QoFCKwUChUNjsNmbaM+02loF2G4ttvVHERdVxPovk8QkaomvlYP9TSXgMXyfVLKKAw5BJQrCVqDhrG5YICNAQKx1OcU/PcQV0e5WAWpXSSK09UMpRA/RBqRTuhRIBn1Wb8oli11JYWLZE1nD+fIyTR8ilYxEcvvtSK24bW1NfLJ0CRq1GxFhj/yDKUuQW5GKE2Po7RGszspkMx7S2SQOa3SRzZY4NrjFClhi8ATWaugJY4UAo4bUOhNhRHIYcPAF4+1BqHgWDNUCD7kCpZFa16x60x0+t6ASwyiqNDYV5VhRV4ynO1SQBkWdQWU0NxW40ZnNidfWvEpny9CXgIKYvtE104u/E0QqlFJzkyAQ2VsjeC7Htwttv6df+CUVMEmoTIbo6HtNE7O+zjj4R9q3QvjIOOoOCJ0NHbpdA3dTHjyEgdPZzAreiqEJwc6qYcQyi2xvFT1sYFNQWa0fEcIS+PWrZ5aXJOfuvUU3KXgAbzsPwNp/5m9BKGnvX9TjOMipzNTUa6VylANIeYMIApIRMADXjBMpwjdBchJFLsXMoAwFj+IizUkqxgSKXlXnJyLSvQYKdr1CpXDxscyvDlwZD6fy85SR69Dap+5JUgTqP3lLrB/3HmxL6GfOKOX5+XKlJHpNvmuGden+hqu5mlkg9FU4aRaXFFYNOqjf6UCfQMdNgBvFrBsnfCg8uSORKXtVaCWLUM83RcLbZtA9CiSulHaRu1EDOYkNXlMDqWpF39fsRnF19+CYTdNfLlH816g+npgm/GzT+Pa4P8JuK6PzDXU1q/B/ddectTc051Yjvh3bjov1+ILcpwJqgWczCsOa5j/NHAfYITjVPPl+ZefqZmxN29EohkQPFHqMspGFcUKNX8h9SFzILcAmnIE0CVgiJE+C2kdIIdX1o8sc2Uu8JoZ9alY5QBri31GpB3Eeaiqvpag/f0TE0oaqbtCECKXIFS1bfYxjVVbOPtQzSYIOtmUygXA4jhlwgnf9hF3TtrKlMXieb7HntapzMAoUAXsezWhAq0IbA8iBmsncSkDxYR5nZJOoyddSvU4tucZsevvMr42rDl/IajemrdkQr2gI+0Bh2ZTCIAfGhGr8y8XUClEXUW4vJ5AuN0dAuYB6QMIApoEuarQnIu5fuqnd7MZTSOol/dbV9paYedkV3uoqa6XBFVULvXppR9WE/adhyI4InTkx4XLvh3bocub0N1oQMYJSFMAQeBHFiL35cgxleJWlaBdKhZcIIGmk4E7AwdIbSfXq3sWlca4M2ZBfQsjIoDWCpFtzNAF05H9+WAWxBV8DV0q/jN/pgV+3VmsQ1+7YVzrV5d9P0mQZIc5hEIUygZ0toaqKZENxV7RMFkKqaRCFU1dMZNDXHH8+fXGVpSqqpEoRQUc510M6ZoFwG01Rr0y1EbYuwcjLJmUIaNdRUEUM9JAnEBBX1kznykRhqGMOrSCiH5HZoVbTkayBbgo4Jga2SuSi8mxIfCPEq2j9whsKUgqs0IXgwizWYdkSfh9GEzejzmIYxvJ4dTUuZiMqpQg5HeRVDoImTZ6ZpzSlfjLvphqwxpJ0AqhBGMdLbNFWlX/2o2xyVtuurkQVTWDnsPWoMH+ieqHIk57pB9JVpLCIrGXVGkcFMOWZts6Jfz3ZNkm5tac4WdBlvNj1RbpbqsRKdR9Fn7rdN2hvGqgpI539JRUn21NSCczlNVZSKTRpFiLAUTj0o91Q0nq/AD3LAFYgTDGcf5IAyXSmtkJmrPJmmszvTLuDz5O5+XYU5hmxauA10Er+KG5nAxnqeFlBG+Yk9aZPI/050eFX7/GvRTTU/e4oLsf+clE8SB1NxWxVv6ih19QxzTVU0e9x0Qyj9dmwfNwNcwZMiYE20x7NS93kyzSfZ72z7qLX8xoWlzDNk/rMERIkkQECUsxaO9cCEhO4qAjkGyaEQSR9iYETkVGwa4SRJ9GMWa7+wV/KLjmVM06dvxPuERuFXaT3B5V1/isbT8V45O2U0totrqRJ6EhysaXxfyUyaUydC/Ykk65RPJ9zSnE/JCWoJeCBlmFAH5DrtejKVwvSMBW6Gs1Fa//4OfWxCT8kayS/bQD0cJ7fOCMz3d+S5Af6kjtbz4WS0Xe+3JJj1YCCqZ+DEITrH4qYgJoworf9549xmIJMMMw52Wyr6NxAri7LcGjOz7wQEEUmMkQzMILgmNEPgx24XnkEYraoJoYm2kcTOvtFKM3eFMNnazKZaaQ8wU66Qp1xw6mBhwkwsI7cglwYxBnFOBae2KoVoA6ixDpMQicS5tyzZTRCr7r4uYDKSsMsWdUmjHsTE9o84p3awLro1c6pv0U6yqdIEbiDo2dzGFNRzuFs18QSYzo9NjrXCm4gcTrLrWpUnteaNG1dpxiaBa4SyZZuUbmcWo3DaVZLgUo3DiW2nD4SYgXL2aBg2gUJ0Fz8fUzGmYMMV1yiJocvkJG9hVR6e/lDOxUIqI5T2haTpJ2eNJ02a6vhrJeeoT3y7TCL/X6vwqhrLmt1aqf2jjVYJ9tGeujLrxSxOBrloU2jv2lvW4l2qz7M2b5OIbtog9nDjP2sy+iXPcf7jzffdU3x4FLdxNTwfHjECFhetlagQrL6q1IVf+MUkdQ1MfuipXewC33E60wjNH2ztVeptqY08pERu31jrhNjFsTwk1TTEfRXKn5mIoGyr4j80L2ui4bkk65ANoQw5ZDOegWp3ltEXniao3796FBE74iaR/61w4+Wmtib6KNPEaw3saEFQh4gT6ENLd8M1B8/AV99Dit7m2TNlD4o8hEHgp5+6oEK+5HS2Ke4zB0NIxFs3g/SAVGQ8JgXFQ5ycCmngY1ddYCNfsMLawdrwbBIKFCBdCDzMozb8xlMEvEAFHJ/i1iXMgz2a1drJ9g4W3Za5/Md80WrKoTv1bajo/SEpkzglDtRSFXAlpx2mhV/AumvP31letTrfGP2BYZOV3S5o3UDqki3BJ5F5z5JNTAEkv/llz/8DU+MKnpn8B3rbrG3C+lzZFHPQgTl4QNYDsZ8A3M2bjHdyovq7eJ0dijKPk/oxlGoYNujXJ7y6zyKsPrHS5J+X3dwTsmZBU070nSJ5Dmp/c8ijm5QCJ6OrNZmq4/qu2nzSq0xcsCkPOQGrF+e1GB6xwDtW7QIH8UDVeYYdE4/R5hroaOHZic0WUFt6eovrfeW1LtNAZ7YYHk/AY2VNG9QrZOcZdszuRptroKOFZ2ePW0Bt/VU19hfReI0N+AD4anuGryzySl37ebC9POfB7HJSOoYlJXJaKaf8d8uaRP4ITxqYWQch01qdeYzHH+icbWT7xrVGGGzT2qPqL1+0jdSGr7ws8qHs5Yv2jcfuh+rPasJazfc+ZnuRFs2vL1/cnqraz6L967UoksexiZdVmwfRvEY7NtrTvD88ZP2sT5OoJ+mL+0c3RBnv4zK+ysukfpqgKt5Vo87m9dJmfaZ+vvCL2L8//Hkqj6eyUlk8f0mVOeXLFzT/ly8MmV+29w0KHypUYiaVCuLPw6tTku4Hud/GaaHNo7EmrivrvxPV760vq65ZiscfQ0t/ZAdmQ535XoujOOyrLncvno/1K97Fn4e7+KuYItunQnwQj/Hux02dJL1ZbsIasTtCNfvL10n8mMfPRdfGWL/6s8Lw/vn7f/8/PCXSAiJFCAA= + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 134b800074..487120fe46 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -303,6 +303,10 @@ 201507200832223_SortFilterHomepageProducts.cs + + + 201507210952098_PaymentMethodDescription.cs + @@ -578,6 +582,9 @@ 201507200832223_SortFilterHomepageProducts.cs + + 201507210952098_PaymentMethodDescription.cs + diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs index f0bc5d51cd..e0abb761b8 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PaymentController.cs @@ -14,6 +14,7 @@ using SmartStore.Services.Shipping; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Controllers; +using SmartStore.Web.Framework.Mvc; using SmartStore.Web.Framework.Plugins; namespace SmartStore.Admin.Controllers @@ -32,6 +33,7 @@ public partial class PaymentController : AdminControllerBase private readonly ICustomerService _customerService; private readonly IShippingService _shippingService; private readonly ICountryService _countryService; + private readonly ILocalizedEntityService _localizedEntityService; #endregion @@ -46,7 +48,8 @@ public PaymentController( ILanguageService languageService, ICustomerService customerService, IShippingService shippingService, - ICountryService countryService) + ICountryService countryService, + ILocalizedEntityService localizedEntityService) { this._services = services; this._paymentService = paymentService; @@ -57,6 +60,7 @@ public PaymentController( this._customerService = customerService; this._shippingService = shippingService; this._countryService = countryService; + this._localizedEntityService = localizedEntityService; } #endregion @@ -102,6 +106,8 @@ private void PreparePaymentMethodEditModel(PaymentMethodEditModel model, Payment model.CountryExclusionContext = paymentMethod.CountryExclusionContext; model.AmountRestrictionContext = paymentMethod.AmountRestrictionContext; + + model.FullDescription = paymentMethod.FullDescription; } } @@ -165,12 +171,23 @@ public ActionResult Edit(string systemName) var provider = _paymentService.LoadPaymentMethodBySystemName(systemName); var paymentMethod = _paymentService.GetPaymentMethodBySystemName(systemName); - var model = _pluginMediator.ToProviderModel(provider, true); + var model = new PaymentMethodEditModel(); + var providerModel = _pluginMediator.ToProviderModel(provider, true); + + model.SystemName = providerModel.SystemName; + model.IconUrl = providerModel.IconUrl; + model.FriendlyName = providerModel.FriendlyName; + model.Description = providerModel.Description; AddLocales(_languageService, model.Locales, (locale, languageId) => { locale.FriendlyName = _pluginMediator.GetLocalizedFriendlyName(provider.Metadata, languageId, false); locale.Description = _pluginMediator.GetLocalizedDescription(provider.Metadata, languageId, false); + + if (paymentMethod != null) + { + locale.FullDescription = paymentMethod.GetLocalized(x => x.FullDescription, languageId, false, false); + } }); PreparePaymentMethodEditModel(model, paymentMethod); @@ -191,12 +208,6 @@ public ActionResult Edit(string systemName, bool continueEditing, PaymentMethodE _pluginMediator.SetSetting(provider.Metadata, "FriendlyName", model.FriendlyName); _pluginMediator.SetSetting(provider.Metadata, "Description", model.Description); - foreach (var localized in model.Locales) - { - _pluginMediator.SaveLocalizedValue(provider.Metadata, localized.LanguageId, "FriendlyName", localized.FriendlyName); - _pluginMediator.SaveLocalizedValue(provider.Metadata, localized.LanguageId, "Description", localized.Description); - } - var paymentMethod = _paymentService.GetPaymentMethodBySystemName(systemName); if (paymentMethod == null) @@ -212,11 +223,21 @@ public ActionResult Edit(string systemName, bool continueEditing, PaymentMethodE paymentMethod.CountryExclusionContext = model.CountryExclusionContext; paymentMethod.AmountRestrictionContext = model.AmountRestrictionContext; + paymentMethod.FullDescription = model.FullDescription; + if (paymentMethod.Id == 0) _paymentService.InsertPaymentMethod(paymentMethod); else _paymentService.UpdatePaymentMethod(paymentMethod); + foreach (var localized in model.Locales) + { + _pluginMediator.SaveLocalizedValue(provider.Metadata, localized.LanguageId, "FriendlyName", localized.FriendlyName); + _pluginMediator.SaveLocalizedValue(provider.Metadata, localized.LanguageId, "Description", localized.Description); + + _localizedEntityService.SaveLocalizedValue(paymentMethod, x => x.FullDescription, localized.FullDescription, localized.LanguageId); + } + NotifySuccess(_services.Localization.GetResource("Admin.Common.DataEditSuccess")); return (continueEditing ? diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs index 12abe357ea..1a84067969 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Payments/PaymentMethodEditModel.cs @@ -2,12 +2,27 @@ using System.Web.Mvc; using SmartStore.Core.Domain.Common; using SmartStore.Web.Framework; +using SmartStore.Web.Framework.Localization; using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Models.Payments { - public class PaymentMethodEditModel : ProviderModel + public class PaymentMethodEditModel : EntityModelBase, ILocalizedModel { + public PaymentMethodEditModel() + { + Locales = new List(); + } + + public IList Locales { get; set; } + public string IconUrl { get; set; } + + [SmartResourceDisplayName("Common.SystemName")] + public string SystemName { get; set; } + + [SmartResourceDisplayName("Common.FriendlyName")] + public string FriendlyName { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.ExcludedCustomerRole")] public string[] ExcludedCustomerRoleIds { get; set; } public List AvailableCustomerRoles { get; set; } @@ -33,5 +48,30 @@ public class PaymentMethodEditModel : ProviderModel [SmartResourceDisplayName("Admin.Configuration.Restrictions.AmountRestrictionContext")] public AmountRestrictionContextType AmountRestrictionContext { get; set; } public List AvailableAmountRestrictionContextTypes { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.ShortDescription")] + [AllowHtml] + public string Description { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.FullDescription")] + [AllowHtml] + public string FullDescription { get; set; } + } + + + public class PaymentMethodLocalizedModel : ILocalizedModelLocal + { + public int LanguageId { get; set; } + + [SmartResourceDisplayName("Common.FriendlyName")] + public string FriendlyName { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.ShortDescription")] + [AllowHtml] + public string Description { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Payment.Methods.FullDescription")] + [AllowHtml] + public string FullDescription { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml index c891471a5d..6151ad6e0d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Payment/Edit.cshtml @@ -35,7 +35,7 @@ @helper TabGeneral() { - @(Html.LocalizedEditor("paymentmethod-general-localized", + @(Html.LocalizedEditor("paymentmethod-general-localized", @ + + + + + + + +
    @@ -55,6 +55,15 @@ @Html.ValidationMessageFor(model => model.Locales[item].Description)
    + @Html.SmartLabelFor(model => model.Locales[item].FullDescription) + + @Html.EditorFor(model => model.Locales[item].FullDescription, Html.RichEditorFlavor()) + @Html.ValidationMessageFor(model => model.Locales[item].FullDescription) +
    @Html.HiddenFor(model => model.Locales[item].LanguageId) @@ -81,6 +90,15 @@ @Html.ValidationMessageFor(model => model.Description)
    + @Html.SmartLabelFor(model => model.FullDescription) + + @Html.EditorFor(x => x.FullDescription, Html.RichEditorFlavor()) + @Html.ValidationMessageFor(model => model.FullDescription) +
    )) } diff --git a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs index 2112acc435..eb18e5bdae 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs @@ -282,12 +282,16 @@ protected CheckoutPaymentMethodModel PreparePaymentMethodModel(IList x.PaymentMethodSystemName.IsCaseInsensitiveEqual(pm.Metadata.SystemName)); - var pmModel = new CheckoutPaymentMethodModel.PaymentMethodModel() + var pmModel = new CheckoutPaymentMethodModel.PaymentMethodModel { Name = _pluginMediator.GetLocalizedFriendlyName(pm.Metadata), Description = _pluginMediator.GetLocalizedDescription(pm.Metadata), @@ -295,6 +299,11 @@ protected CheckoutPaymentMethodModel PreparePaymentMethodModel(IList x.FullDescription, _workContext.WorkingLanguage.Id); + } pmModel.BrandUrl = _pluginMediator.GetBrandImageUrl(pm.Metadata); diff --git a/src/Presentation/SmartStore.Web/Models/Checkout/CheckoutPaymentMethodModel.cs b/src/Presentation/SmartStore.Web/Models/Checkout/CheckoutPaymentMethodModel.cs index 585658b0ad..8c54334466 100644 --- a/src/Presentation/SmartStore.Web/Models/Checkout/CheckoutPaymentMethodModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Checkout/CheckoutPaymentMethodModel.cs @@ -24,12 +24,14 @@ public partial class PaymentMethodModel : ModelBase public string PaymentMethodSystemName { get; set; } public string Name { get; set; } public string Description { get; set; } + public string FullDescription { get; set; } public string BrandUrl { get; set; } public string Fee { get; set; } public bool Selected { get; set; } public RouteInfo PaymentInfoRoute { get; set; } public bool RequiresInteraction { get; set; } } + #endregion } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Themes/Alpha/Content/checkout.less b/src/Presentation/SmartStore.Web/Themes/Alpha/Content/checkout.less index ea2111083c..b826ee8add 100644 --- a/src/Presentation/SmartStore.Web/Themes/Alpha/Content/checkout.less +++ b/src/Presentation/SmartStore.Web/Themes/Alpha/Content/checkout.less @@ -21,7 +21,8 @@ background-color: #f9f9f9; border-color: #f9f9f9; } - .opt-info { + .opt-info, + .opt-info-item { margin-top: 6px; margin-left: 32px; } diff --git a/src/Presentation/SmartStore.Web/Themes/Mobile/Content/styles.css b/src/Presentation/SmartStore.Web/Themes/Mobile/Content/styles.css index bbc2b1f597..41fe197f5b 100644 --- a/src/Presentation/SmartStore.Web/Themes/Mobile/Content/styles.css +++ b/src/Presentation/SmartStore.Web/Themes/Mobile/Content/styles.css @@ -156,7 +156,7 @@ img { max-width: 100% } .checkout-data .use-reward-points{margin:0;padding:10px;background:#F7F5E8;border:dotted 1px #d3d3d3;} .checkout-data .payment-methods{text-align:left;height:auto;} .checkout-data .payment-methods .payment-method-item{text-align:left;vertical-align:text-top;} -.checkout-data .payment-methods .payment-method-item .payment-method-desc{margin:0 0 14px 46px;} +.checkout-data .payment-methods .payment-method-item .payment-method-description{margin:0 0 15px 15px;} .checkout-data .payment-methods .select-button{text-align:left;} .checkout-data .payment-methods .message-error{text-align:left;} .checkout-data .payment-info{text-align:left;height:auto;} diff --git a/src/Presentation/SmartStore.Web/Views/Checkout/PaymentMethod.Mobile.cshtml b/src/Presentation/SmartStore.Web/Views/Checkout/PaymentMethod.Mobile.cshtml index 5bc4697448..df97ab4bae 100644 --- a/src/Presentation/SmartStore.Web/Views/Checkout/PaymentMethod.Mobile.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Checkout/PaymentMethod.Mobile.cshtml @@ -47,13 +47,13 @@ - @if (!String.IsNullOrWhiteSpace(paymentMethod.Description)) - { -
    - @Html.Raw(paymentMethod.Description) -
    - } + @if (paymentMethod.FullDescription.HasValue()) + { +
    + @Html.Raw(paymentMethod.FullDescription) +
    + } @if (!paymentMethod.RequiresInteraction || (paymentMethod.Selected && infoRoute != null)) {
    } - @Html.Action(infoRoute.Action, infoRoute.Controller, infoRoute.RouteValues) + @if (!(paymentMethod.FullDescription.HasValue() && !paymentMethod.RequiresInteraction)) + { + @Html.Action(infoRoute.Action, infoRoute.Controller, infoRoute.RouteValues) + }
    } diff --git a/src/Presentation/SmartStore.Web/Views/Checkout/PaymentMethod.cshtml b/src/Presentation/SmartStore.Web/Views/Checkout/PaymentMethod.cshtml index 0d8df1ae8a..569189379a 100644 --- a/src/Presentation/SmartStore.Web/Views/Checkout/PaymentMethod.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Checkout/PaymentMethod.cshtml @@ -57,6 +57,12 @@ + @if (paymentMethod.FullDescription.HasValue()) + { +
    + @Html.Raw(paymentMethod.FullDescription) +
    + } @if (!paymentMethod.RequiresInteraction || (paymentMethod.Selected && infoRoute != null)) {
    } - @Html.Action(infoRoute.Action, infoRoute.Controller, infoRoute.RouteValues) + @if(!(paymentMethod.FullDescription.HasValue() && !paymentMethod.RequiresInteraction)) + { + @Html.Action(infoRoute.Action, infoRoute.Controller, infoRoute.RouteValues) + }
    } From e2677c6b01b5eaefaec5427463a1c801c6cc3621 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 21 Jul 2015 17:22:48 +0200 Subject: [PATCH 0278/1256] Added headlines to widget zone chooser --- .../Shared/EditorTemplates/WidgetZone.cshtml | 188 +++++++++++++++++- 1 file changed, 178 insertions(+), 10 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/WidgetZone.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/WidgetZone.cshtml index bab1deb472..819aa95a63 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/WidgetZone.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/EditorTemplates/WidgetZone.cshtml @@ -23,16 +23,184 @@ } else { zones = [ - "head_html_tag", "body_start_html_tag_after", "header", "left_side_column_before", "left_side_column_after_category_navigation", - "left_side_column_after", "main_column_before", "content_before", "content_after", "main_column_after", "right_side_column_before", - "right_side_column_after", "footer", "body_end_html_tag_before", - "categorydetails_after_breadcrumb", "categorydetails_top", "categorydetails_before_subcategories", "categorydetails_before_featured_products", "categorydetails_after_featured_products", "categorydetails_before_product_list", "categorydetails_bottom", "categorydetails_before_filters", - "productdetails_top", "productdetails_before_pictures", "productdetails_after_pictures", "productdetails_overview_top", "productdetails_overview_bottom", "productdetails_bottom", - "order_summary_content_before", "order_summary_content_deals", "order_summary_content_after", "order_summary_content_totals_left", "order_summary_content_totals_bottom", - "orderdetails_page_aftertotal", - "checkout_billing_address_top", "checkout_billing_address_middle", "checkout_billing_address_bottom", "checkout_shipping_address_top", "checkout_shipping_address_middle", "checkout_shipping_address_bottom", - "checkout_payment_method_top", "checkout_payment_method_bottom", "checkout_shipping_method_top", "checkout_shipping_method_bottom", "checkout_payment_info_top", "checkout_payment_info_bottom", "checkout_confirm_top", "checkout_confirm_before_summary", "checkout_confirm_bottom", "checkout_completed_top", "checkout_completed_bottom", "checkout_progress_before", "checkout_progress_after", - "contactus_top", "contactus_bottom", "home_page_top", "home_page_bottom", "mini_shopping_cart_bottom" + { + text: "@T("Admin.ContentManagement.Blog")", children: [ + { id: 0, text: 'blogpost_page_before_body' }, + { id: 1, text: 'blogpost_page_before_comments' }, + { id: 2, text: 'blogpost_page_inside_comment' }, + { id: 3, text: 'blogpost_page_after_comments' }, + { id: 4, text: 'bloglist_page_before_posts' }, + { id: 5, text: 'bloglist_page_inside_post' }, + { id: 6, text: 'bloglist_page_after_posts' } + ] + }, + { + text: "@T("Admin.Catalog.Categories")", children: [ + { id: 7, text: 'categorydetails_after_breadcrumb' }, + { id: 8, text: 'categorydetails_top' }, + { id: 9, text: 'categorydetails_before_subcategories' }, + { id: 10, text: 'categorydetails_before_featured_products' }, + { id: 11, text: 'categorydetails_after_featured_products' }, + { id: 12, text: 'categorydetails_before_product_list' }, + { id: 13, text: 'categorydetails_bottom' }, + { id: 14, text: 'categorydetails_before_filters' } + ] + }, + { + text: "@T("Admin.Catalog.Products")", children: [ + { id: 15, text: 'productbox_add_info' }, + { id: 16, text: 'productsbytag_before_product_list' }, + { id: 17, text: 'productreviews_page_inside_review' }, + { id: 18, text: 'productdetails_overview_top' }, + { id: 19, text: 'productdetails_overview_bottom' }, + { id: 20, text: 'productsbytag_top' }, + { id: 21, text: 'productsbytag_bottom' }, + { id: 22, text: 'productdetails_add_info' }, + { id: 23, text: 'productdetails_top' }, + { id: 24, text: 'productdetails_before_pictures' }, + { id: 25, text: 'productdetails_after_pictures' }, + { id: 26, text: 'productdetails_bottom' } + ] + }, + { + text: "Navigation", children: [ + { id: 27, text: 'productbreadcrumb_before' }, + { id: 28, text: 'productbreadcrumb_after' }, + { id: 29, text: 'header_menu_before' }, + { id: 30, text: 'header_menu_after' }, + { id: 31, text: 'megamenu_before_first_item' }, + { id: 32, text: 'megamenu_after_last_item' }, + { id: 33, text: 'account_dropdown_before' }, + { id: 34, text: 'account_dropdown_after' }, + { id: 35, text: 'header_links_before' }, + { id: 36, text: 'header_links_after' }, + { id: 37, text: 'infoblock_before' }, + { id: 38, text: 'infoblock_after' }, + { id: 39, text: 'account_navigation_before' }, + { id: 40, text: 'account_navigation_after' }, + ] + }, + { + text: "PDF", children: [ + { id: 41, text: 'invoice_footer_before' }, + { id: 42, text: 'invoice_footer_after' }, + { id: 43, text: 'invoice_header_before' }, + { id: 44, text: 'invoice_header_right' }, + { id: 45, text: 'invoice_header_after' }, + { id: 46, text: 'invoice_top' }, + { id: 47, text: 'invoice_orderinfo_top' }, + { id: 48, text: 'invoice_orderinfotable_after' }, + { id: 49, text: 'invoice_orderinfo_bottom' }, + { id: 50, text: 'invoice_lines_before' }, + { id: 51, text: 'invoice_checkoutattributes_before' }, + { id: 52, text: 'invoice_ordertotals_before' }, + { id: 53, text: 'invoice_ordernotes_before' }, + { id: 54, text: 'invoice_bottom' }, + { id: 55, text: 'pdfcatalog_cover_top' }, + { id: 56, text: 'pdfcatalog_cover_logo_after' }, + { id: 57, text: 'pdfcatalog_cover_storename_after' }, + { id: 58, text: 'pdfcatalog_productdetail_top' }, + { id: 59, text: 'pdfcatalog_productdetail_fulldescription_before' }, + { id: 60, text: 'pdfcatalog_productdetail_picture_before' }, + { id: 61, text: 'pdfcatalog_productdetail_specificationattributes_before' }, + { id: 62, text: 'pdfcatalog_productdetail_bundleditems_before' }, + { id: 63, text: 'pdfcatalog_productdetail_associatedproducts_before' } + ] + }, + { + text: "@T("Admin.Catalog.Manufacturers")", children: [ + { id: 64, text: 'manufacturerdetails_top' }, + { id: 65, text: 'manufacturerdetails_before_featured_products' }, + { id: 66, text: 'manufacturerdetails_after_featured_products' }, + { id: 67, text: 'manufacturerdetails_before_filters' }, + { id: 68, text: 'manufacturerdetails_before_product_list' }, + { id: 69, text: 'manufacturerdetails_bottom' } + ] + }, + { + text: "@T("Common.Misc")", children: [ + { id: 70, text: 'compareproducts_row' }, + { id: 71, text: 'productsearch_page_advanced' }, + { id: 72, text: 'productsearch_page_basic' }, + { id: 73, text: 'productsearch_page_advanced' }, + { id: 74, text: 'searchbox' }, + { id: 75, text: 'footer' }, + { id: 76, text: 'contactus_top' }, + { id: 77, text: 'contactus_bottom' }, + { id: 78, text: 'productreviews_page_top' }, + { id: 79, text: 'productreviews_page_inside_review' }, + { id: 80, text: 'productreviews_page_bottom' }, + { id: 81, text: 'profile_page_info_userdetails' }, + { id: 82, text: 'profile_page_info_userstats' }, + { id: 83, text: 'notifications' }, + { id: 84, text: 'shipmentdetails_top' }, + { id: 85, text: 'shipmentdetails_orderinfo_top' }, + { id: 86, text: 'shipmentdetails_orderinfotable_after' }, + { id: 87, text: 'shipmentdetails_orderinfo_bottom' }, + { id: 88, text: 'shipmentdetails_lines_before' } + ] + }, + { + text: "Global", children: [ + { id: 89, text: 'home_page_top' }, + { id: 90, text: 'home_page_bottom' }, + { id: 91, text: 'main_column_before' }, + { id: 92, text: 'main_column_after' }, + { id: 93, text: 'left_side_column_before' }, + { id: 94, text: 'left_side_column_after_category_navigation' }, + { id: 95, text: 'left_side_column_after_manufacturer_navigation' }, + { id: 96, text: 'left_side_column_after_tags' }, + { id: 97, text: 'left_side_column_after_info' }, + { id: 98, text: 'left_side_column_after_poll' }, + { id: 99, text: 'left_side_column_after' }, + { id: 100, text: 'right_side_column_before' }, + { id: 101, text: 'right_side_column_after_recentlyviewed' }, + { id: 102, text: 'right_side_column_after_poll' }, + { id: 103, text: 'right_side_column_after' }, + { id: 104, text: 'body_start_html_tag_after' }, + { id: 105, text: 'content_before' }, + { id: 106, text: 'content_after' }, + { id: 107, text: 'body_end_html_tag_before' }, + { id: 108, text: 'head_html_tag' }, + { id: 109, text: 'admin_navbar_before' }, + { id: 110, text: 'admin_navbar_after' }, + { id: 111, text: 'admin_breadcrumb' }, + { id: 112, text: 'admin_content_before' }, + { id: 113, text: 'admin_content_after' }, + { id: 114, text: 'admin_menu_before' } + ] + }, + { + text: "@T("Admin.ContentManagement.News")", children: [ + { id: 115, text: 'newslist_page_before_items' }, + { id: 116, text: 'newslist_page_inside_item' }, + { id: 117, text: 'newslist_page_after_items' }, + { id: 118, text: 'newsitem_page_before_body' }, + { id: 119, text: 'newsitem_page_before_comments' }, + { id: 120, text: 'newsitem_page_inside_comment' }, + { id: 121, text: 'newsitem_page_after_comments' } + ] + }, + { + text: "@T("Admin.Orders")", children: [ + { id: 122, text: 'orderdetails_page_top' }, + { id: 123, text: 'orderdetails_page_overview' }, + { id: 124, text: 'orderdetails_page_beforeproducts' }, + { id: 125, text: 'orderdetails_page_afterproducts' }, + { id: 126, text: 'orderdetails_page_aftertotal' }, + { id: 127, text: 'orderdetails_page_bottom' } + ] + }, + { + text: "@T("Shoppingcart")", children: [ + { id: 128, text: 'mini_shopping_cart_bottom' }, + { id: 129, text: 'order_summary_content_before' }, + { id: 130, text: 'order_summary_content_totals_left' }, + { id: 131, text: 'order_summary_content_deals' }, + { id: 132, text: 'order_summary_content_totals_bottom' }, + { id: 133, text: 'order_summary_content_after' } + ] + } ]; } From f3e8bb80621cfe48b48f47757e04a44473b0ee92 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 21 Jul 2015 20:17:43 +0200 Subject: [PATCH 0279/1256] Resolves #715 HTML editor for shipping method description --- .../Views/Shipping/_CreateOrUpdateMethod.cshtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml index 9163a2f8db..3639eef59c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/_CreateOrUpdateMethod.cshtml @@ -30,7 +30,7 @@ @Html.SmartLabelFor(model => model.Locales[item].Description)
    - @Html.TextAreaFor(model => model.Locales[item].Description) + @Html.EditorFor(model => model.Locales[item].Description, Html.RichEditorFlavor()) @Html.ValidationMessageFor(model => model.Locales[item].Description)
    - @Html.TextAreaFor(model => model.Description) + @Html.EditorFor(model => model.Description, Html.RichEditorFlavor()) @Html.ValidationMessageFor(model => model.Description)
    + + diff --git a/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs b/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs index bcaaadd658..eef3ac94e0 100644 --- a/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs @@ -3,29 +3,32 @@ using System.Linq; using System.Web; using System.Web.Mvc; +using System.Web.SessionState; using SmartStore.Core.Domain.Tasks; using SmartStore.Services.Tasks; using SmartStore.Web.Framework.Controllers; using SmartStore.Services.Security; using SmartStore.Services; + namespace SmartStore.Web.Controllers { - + + [SessionState(SessionStateBehavior.ReadOnly)] public class TaskSchedulerController : Controller { - private readonly ITaskSweeper _taskSweeper; + private readonly ITaskScheduler _taskScheduler; private readonly IScheduleTaskService _scheduledTaskService; private readonly ITaskExecutor _taskExecutor; private readonly ICommonServices _services; public TaskSchedulerController( - ITaskSweeper taskSweeper, + ITaskScheduler taskScheduler, IScheduleTaskService scheduledTaskService, ITaskExecutor taskExecutor, ICommonServices services) { - this._taskSweeper = taskSweeper; + this._taskScheduler = taskScheduler; this._scheduledTaskService = scheduledTaskService; this._taskExecutor = taskExecutor; this._services = services; @@ -34,23 +37,41 @@ public TaskSchedulerController( [HttpPost] public ActionResult Sweep() { - if (!_taskSweeper.VerifyAuthToken(Request.Headers["X-AUTH-TOKEN"])) + if (!_taskScheduler.VerifyAuthToken(Request.Headers["X-AUTH-TOKEN"])) return new HttpUnauthorizedResult(); var pendingTasks = _scheduledTaskService.GetPendingTasks(); + var prevTaskStart = DateTime.UtcNow; + var count = 0; foreach (var task in pendingTasks) { - _taskExecutor.Execute(task); + var elapsedSincePrevTask = DateTime.UtcNow - prevTaskStart; + if (elapsedSincePrevTask >= _taskScheduler.SweepInterval) + { + // the previous Task execution in this loop took longer + // than the scheduler's sweep interval. Most likely a subsequent + // Sweep call executed it already in another HTTP request. + // To be able to determine this, we need to reload the entity from the database. + // The TaskExecutor will exit when the task should be in running state then. + _services.DbContext.ReloadEntity(task); + } + + if (task.IsPending) + { + prevTaskStart = DateTime.UtcNow; + _taskExecutor.Execute(task); + count++; + } } - return Content("{0} tasks executed".FormatInvariant(pendingTasks.Count)); + return Content("{0} tasks executed".FormatInvariant(count)); } [HttpPost] public ActionResult Execute(int id /* taskId */) { - if (!_taskSweeper.VerifyAuthToken(Request.Headers["X-AUTH-TOKEN"])) + if (!_taskScheduler.VerifyAuthToken(Request.Headers["X-AUTH-TOKEN"])) return new HttpUnauthorizedResult(); var task = _scheduledTaskService.GetTaskById(id); From 3c586efde97f3e33dc4b50fd50bda2bc7acc1628 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 24 Jul 2015 03:31:11 +0200 Subject: [PATCH 0295/1256] WebScheduler 7 --- src/Libraries/SmartStore.Core/Async/AsyncState.cs | 8 ++++++-- .../SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Async/AsyncState.cs b/src/Libraries/SmartStore.Core/Async/AsyncState.cs index 6ecbb7959a..64d4e91e14 100644 --- a/src/Libraries/SmartStore.Core/Async/AsyncState.cs +++ b/src/Libraries/SmartStore.Core/Async/AsyncState.cs @@ -76,6 +76,7 @@ private T Get(out CancellationTokenSource cancelTokenSource, string name = nu public void Set(T state, string name = null, bool neverExpires = false) { + Guard.ArgumentNotNull(() => state); this.Set(state, null, name, neverExpires); } @@ -112,14 +113,17 @@ private void Set(T state, CancellationTokenSource cancelTokenSource, string n if (value != null) { // exists already, so update - value.Progress = state; + if (state != null) + { + value.Progress = state; + } if (cancelTokenSource != null && value.CancellationTokenSource == null) { value.CancellationTokenSource = cancelTokenSource; } } - var policy = new CacheItemPolicy { SlidingExpiration = neverExpires ? TimeSpan.FromHours(24) : TimeSpan.FromMinutes(15) }; + var policy = new CacheItemPolicy { SlidingExpiration = neverExpires ? TimeSpan.Zero : TimeSpan.FromMinutes(15) }; _cache.Set( key, diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs index 872ff47290..b16a8aa604 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs @@ -395,7 +395,7 @@ public void StartCreatingFeeds(Func createFeed, s stores.AddRange(storeService.GetAllStores()); } - var context = new FeedFileCreationContext() + var context = new FeedFileCreationContext { StoreCount = stores.Count, Progress = new Progress(x => From 4e6cc3ce4da417ad79360ca0c5a9246e54c0f01a Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Fri, 24 Jul 2015 15:06:00 +0200 Subject: [PATCH 0296/1256] Resolves #732 Product list: Option to display the pre-selected price instead of the lowest price --- .../Domain/Catalog/CatalogSettings.cs | 5 + .../Domain/Catalog/PriceDisplayType.cs | 29 ++ .../SmartStore.Core/SmartStore.Core.csproj | 1 + ...01507210952098_PaymentMethodDescription.cs | 22 ++ .../Catalog/IPriceCalculationService.cs | 3 +- .../Catalog/PriceCalculationService.cs | 184 +++-------- .../Controllers/OData/ProductsController.cs | 2 +- .../Controllers/SettingController.cs | 1 + .../Infrastructure/AutoMapperStartupTask.cs | 1 + .../Models/Settings/CatalogSettingsModel.cs | 4 + .../Views/Setting/Catalog.cshtml | 12 +- .../Controllers/CatalogHelper.cs | 299 ++++++++---------- 12 files changed, 255 insertions(+), 308 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Domain/Catalog/PriceDisplayType.cs diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs index dd7d67edea..979fa85969 100644 --- a/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs @@ -353,6 +353,11 @@ public CatalogSettings() ///
    public string DefaultPageSizeOptions { get; set; } + /// + /// Gets or sets the price display type for prices in product lists + /// + public PriceDisplayType PriceDisplayType { get; set; } + /// /// Gets or sets a value indicating whether to include "Short description" in compare products /// diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/PriceDisplayType.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/PriceDisplayType.cs new file mode 100644 index 0000000000..aeb4c24250 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/Catalog/PriceDisplayType.cs @@ -0,0 +1,29 @@ + +namespace SmartStore.Core.Domain.Catalog +{ + /// + /// Represents types of product prices to display + /// + public enum PriceDisplayType + { + /// + /// The lowest possible price of a product (default) + /// + LowestPrice = 0, + + /// + /// The product price initially displayed on the product detail page + /// + PreSelectedPrice = 10, + + /// + /// The product price without associated data like discounts, tier prices, attributes or attribute combinations + /// + PriceWithoutDiscountsAndAttributes = 20, + + /// + /// Do not display a product price + /// + Hide = 30 + } +} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 6035969f75..24da2a6e8d 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -157,6 +157,7 @@ + diff --git a/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs b/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs index 9cc272131b..75e57c5d4b 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs @@ -39,6 +39,28 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Langtext", "Specifies a full description of the payment method. It appears in the payment list in checkout.", "Legt eine vollstndige Beschreibung der Zahlungsmethode fest. Sie erscheint in der Zahlungsliste im Kassenbereich."); + + builder.AddOrUpdate("Admin.Configuration.Settings.Catalog.PriceDisplayType", + "Price display", + "Preisanzeige", + "Specifies whether or what type of price to be displayed in product lists.", + "Legt fest, ob bzw. welcher Typ von Preis in Produktlisten angezeigt werden soll."); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Catalog.PriceDisplayType.LowestPrice", + "Minimum feasible price", + "Minimal realisierbarer Preis"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Catalog.PriceDisplayType.PreSelectedPrice", + "Preselected price", + "Vorgewhlter Preis"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Catalog.PriceDisplayType.PriceWithoutDiscountsAndAttributes", + "Price without discounts and attributes", + "Preis ohne Rabatte und Attribute"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Catalog.PriceDisplayType.Hide", + "No price indication", + "Keine Preisanzeige"); } } } diff --git a/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs index e2004625fd..3ae7d2bb7e 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs @@ -92,9 +92,10 @@ decimal GetFinalPrice(Product product, IEnumerable bundle /// Get the lowest possible price for a product. ///
    /// Product + /// Object with cargo data for better performance /// Whether to display the from message. /// The lowest price. - decimal GetLowestPrice(Product product, out bool displayFromMessage); + decimal GetLowestPrice(Product product, PriceCalculationContext context, out bool displayFromMessage); /// /// Get the lowest price of a grouped product. diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index e7be1e33d7..0c965dceb1 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -243,104 +243,13 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC return result; } - //protected virtual decimal GetPreselectedPriceOld(Product product, ProductBundleItemData bundleItem, IList bundleItems) - //{ - // var taxRate = decimal.Zero; - // var attributesTotalPriceBase = decimal.Zero; - // var preSelectedPriceAdjustmentBase = decimal.Zero; - // var isBundle = (product.ProductType == ProductType.BundledProduct); - // var isBundleItemPricing = (bundleItem != null && bundleItem.Item.BundleProduct.BundlePerItemPricing); - // var isBundlePricing = (bundleItem != null && !bundleItem.Item.BundleProduct.BundlePerItemPricing); - // var bundleItemId = (bundleItem == null ? 0 : bundleItem.Item.Id); - // var attributes = (isBundle ? new List() : _productAttributeService.GetProductVariantAttributesByProductId(product.Id)); - // var selectedAttributes = new NameValueCollection(); - // List selectedAttributeValues = null; - - // foreach (var attribute in attributes) - // { - // int preSelectedValueId = 0; - // ProductVariantAttributeValue defaultValue = null; - - // if (attribute.ShouldHaveValues()) - // { - // var pvaValues = _productAttributeService.GetProductVariantAttributeValues(attribute.Id); - // if (pvaValues.Count == 0) - // continue; - - // foreach (var pvaValue in pvaValues) - // { - // ProductBundleItemAttributeFilter attributeFilter = null; - - // if (bundleItem.FilterOut(pvaValue, out attributeFilter)) - // continue; - - // if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) - // preSelectedValueId = attributeFilter.AttributeValueId; - - // if (!isBundlePricing && pvaValue.IsPreSelected) - // { - // decimal attributeValuePriceAdjustment = GetProductVariantAttributeValuePriceAdjustment(pvaValue); - // decimal priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, out taxRate); - - // preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); - // } - // } - - // // value pre-selected by a bundle item filter discards the default pre-selection - // if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) - // defaultValue.IsPreSelected = true; - - // if (defaultValue == null) - // defaultValue = pvaValues.FirstOrDefault(x => x.IsPreSelected); - - // if (defaultValue == null && attribute.IsRequired) - // defaultValue = pvaValues.First(); - - // if (defaultValue != null) - // selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); - // } - // } - - // if (!isBundle && selectedAttributes.Count > 0) - // { - // string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _services.Localization, - // _downloadService, _catalogSettings, _httpRequestBase, new List(), true, bundleItemId); - - // selectedAttributeValues = _productAttributeParser.ParseProductVariantAttributeValues(attributeXml).ToList(); - - // var combinations = _productAttributeService.GetAllProductVariantAttributeCombinations(product.Id); - - // var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml)); - - // if (selectedCombination != null && selectedCombination.IsActive) - // product.MergeWithCombination(selectedCombination); - // } - - // if (_catalogSettings.EnableDynamicPriceUpdate && !isBundlePricing) - // { - // if (selectedAttributeValues != null) - // { - // selectedAttributeValues.Each(x => attributesTotalPriceBase += GetProductVariantAttributeValuePriceAdjustment(x)); - // } - // else - // { - // attributesTotalPriceBase = preSelectedPriceAdjustmentBase; - // } - // } - - // if (bundleItem != null) - // { - // bundleItem.AdditionalCharge = attributesTotalPriceBase; - // } - - // var result = GetFinalPrice(product, bundleItems, _services.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem); - // return result; - //} - public virtual PriceCalculationContext CreatePriceCalculationContext(IEnumerable productIds = null) { var context = new PriceCalculationContext(); + if (_catalogSettings.PriceDisplayType == PriceDisplayType.Hide || _catalogSettings.PriceDisplayType == PriceDisplayType.PriceWithoutDiscountsAndAttributes) + return context; + context.Attributes = new LazyMultimap(x => { "load {0}".FormatInvariant(string.Join(";", x)).Dump(); @@ -349,11 +258,14 @@ public virtual PriceCalculationContext CreatePriceCalculationContext(IEnumerable return result; }, productIds); - context.AttributeCombinations = new LazyMultimap(x => + if (_catalogSettings.PriceDisplayType == PriceDisplayType.PreSelectedPrice) { - var result = _productAttributeService.GetProductVariantAttributeCombinations(x); - return result; - }, productIds); + context.AttributeCombinations = new LazyMultimap(x => + { + var result = _productAttributeService.GetProductVariantAttributeCombinations(x); + return result; + }, productIds); + } return context; } @@ -527,9 +439,10 @@ public virtual decimal GetFinalPrice( /// Get the lowest possible price for a product. /// /// Product + /// Object with cargo data for better performance /// Whether to display the from message. /// The lowest price. - public virtual decimal GetLowestPrice(Product product, out bool displayFromMessage) + public virtual decimal GetLowestPrice(Product product, PriceCalculationContext context, out bool displayFromMessage) { if (product == null) throw new ArgumentNullException("product"); @@ -537,38 +450,16 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa if (product.ProductType == ProductType.GroupedProduct) throw Error.InvalidOperation("Choose the other override for products of type grouped product."); - displayFromMessage = false; + if (context == null) + context = CreatePriceCalculationContext(null); - IList bundleItems = null; bool isBundlePerItemPricing = (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing); - if (isBundlePerItemPricing) - { - bundleItems = _productService.GetBundleItems(product.Id); + displayFromMessage = isBundlePerItemPricing; - // sepcial case: one bundle item with one attribute and one attribute value and one attribute combination - if (bundleItems.Count == 1) - { - var firstBundleItem = bundleItems.First(); - if (firstBundleItem.Item.Product.ProductVariantAttributes.Count == 1) - { - var firstAttribute = firstBundleItem.Item.Product.ProductVariantAttributes.First(); - if (firstAttribute.ProductVariantAttributeValues.Count == 1) - { - var firstAttributeValue = firstAttribute.ProductVariantAttributeValues.First(); - firstBundleItem.AdditionalCharge = firstAttributeValue.PriceAdjustment; - - var combinations = _productAttributeService.GetAllProductVariantAttributeCombinations(firstBundleItem.Item.ProductId); - if (combinations.Count == 1) - { - firstBundleItem.Item.Product.MergeWithCombination(combinations.First()); - } - } - } - } - } + // TODO(?): attribute price adjustments were not regarded here cause of performance - decimal lowestPrice = GetFinalPrice(product, bundleItems, _services.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); + decimal lowestPrice = GetFinalPrice(product, null, _services.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); if (product.LowestAttributeCombinationPrice.HasValue && product.LowestAttributeCombinationPrice.Value < lowestPrice) { @@ -581,6 +472,24 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa lowestPrice = product.LowestAttributeCombinationPrice ?? decimal.Zero; } + if (!displayFromMessage && product.ProductType != ProductType.BundledProduct) + { + var attributes = context.Attributes.Ensure(product.Id); + displayFromMessage = attributes.Any(x => x.ProductVariantAttributeValues.Any(y => y.PriceAdjustment != decimal.Zero)); + } + + if (!displayFromMessage && product.HasTierPrices && !isBundlePerItemPricing) + { + var tierPrices = product.TierPrices + .OrderBy(tp => tp.Quantity) + .FilterByStore(_services.StoreContext.CurrentStore.Id) + .FilterForCustomer(_services.WorkContext.CurrentCustomer) + .ToList() + .RemoveDuplicatedQuantities(); + + displayFromMessage = (tierPrices.Count > 0 && !(tierPrices.Count == 1 && tierPrices.First().Quantity <= 1)); + } + return lowestPrice; } @@ -602,7 +511,7 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa if (product.ProductType != ProductType.GroupedProduct) throw Error.InvalidOperation("Choose the other override for products not of type grouped product."); - lowestPriceProduct = product; + lowestPriceProduct = null; decimal? lowestPrice = null; foreach (var associatedProduct in associatedProducts) @@ -620,6 +529,10 @@ public virtual decimal GetLowestPrice(Product product, out bool displayFromMessa lowestPriceProduct = associatedProduct; } } + + if (lowestPriceProduct == null) + lowestPriceProduct = associatedProducts.FirstOrDefault(); + return lowestPrice; } @@ -660,23 +573,6 @@ public virtual decimal GetPreselectedPrice(Product product, PriceCalculationCont result = GetPreselectedPrice(product, context, null, null); } - //if (product.ProductType == ProductType.BundledProduct) - //{ - // var bundleItems = _productService.GetBundleItems(product.Id); - - // foreach (var bundleItem in bundleItems.Where(x => x.Item.Product.CanBeBundleItem())) - // { - // // fetch bundleItems.AdditionalCharge for all bundle items - // var unused = GetPreselectedPriceOld(bundleItem.Item.Product, bundleItem, bundleItems); - // } - - // result = GetPreselectedPriceOld(product, null, bundleItems); - //} - //else - //{ - // result = GetPreselectedPriceOld(product, null, null); - //} - return result; } diff --git a/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs b/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs index 24347a2f31..aec30f45cd 100644 --- a/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs +++ b/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs @@ -266,7 +266,7 @@ public IQueryable GetProductBundleItems(int key) else { bool displayFromMessage; - result = _priceCalculationService.Value.GetLowestPrice(entity, out displayFromMessage); + result = _priceCalculationService.Value.GetLowestPrice(entity, null, out displayFromMessage); } } else diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs index 355f948bac..8f13a6c95a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/SettingController.cs @@ -558,6 +558,7 @@ public ActionResult Catalog() StoreDependingSettings.GetOverrideKeys(catalogSettings, model, storeScope, _services.Settings); model.AvailableSubCategoryDisplayTypes = catalogSettings.SubCategoryDisplayType.ToSelectList(); + model.AvailablePriceDisplayTypes = catalogSettings.PriceDisplayType.ToSelectList(); model.AvailableDefaultViewModes.Add( new SelectListItem { Value = "grid", Text = _services.Localization.GetResource("Common.Grid"), Selected = model.DefaultViewMode.IsCaseInsensitiveEqual("grid") } diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index 35c6c808e1..40fd048a32 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -618,6 +618,7 @@ public void Execute() .ForMember(dest => dest.ReturnValidOptionsIfThereAreAny, mo => mo.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.AvailableSubCategoryDisplayTypes, mo => mo.Ignore()) + .ForMember(dest => dest.AvailablePriceDisplayTypes, mo => mo.Ignore()) .ForMember(dest => dest.AvailableDefaultViewModes, mo => mo.Ignore()) .ForMember(dest => dest.AvailableDeliveryTimes, mo => mo.Ignore()); Mapper.CreateMap() diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs index ba76a185ea..46de364573 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs @@ -115,6 +115,10 @@ public CatalogSettingsModel() [SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.DefaultPageSizeOptions")] public string DefaultPageSizeOptions { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.PriceDisplayType")] + public PriceDisplayType PriceDisplayType { get; set; } + public SelectList AvailablePriceDisplayTypes { get; set; } + #endregion #region Products diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml index a55ae23614..33f3b5ea30 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml @@ -163,8 +163,8 @@ { x.Add().Text(T("Admin.Configuration.Settings.Catalog.MiscSettings").Text).Content(@TabMiscSettings()).Selected(true); x.Add().Text(T("Admin.Configuration.Settings.Catalog.ProductListSettings").Text).Content(@TabProductListSettings()); - x.Add().Text(T("Admin.Configuration.Settings.Catalog.UserSettings").Text).Content(@TabUserSettings()); x.Add().Text(T("Admin.Configuration.Settings.Catalog.ProductDetailSettings").Text).Content(@TabProductDetailSettings()); + x.Add().Text(T("Admin.Configuration.Settings.Catalog.UserSettings").Text).Content(@TabUserSettings()); x.Add().Text(T("Admin.Configuration.Settings.Catalog.ProductSearchSettings").Text).Content(@TabProductSearchSettings()); })) @@ -453,6 +453,16 @@ @Html.ValidationMessageFor(model => model.DefaultPageSizeOptions) + + + @Html.SmartLabelFor(model => model.PriceDisplayType) + + + @Html.SettingOverrideCheckbox(model => Model.PriceDisplayType) + @Html.DropDownListFor(model => model.PriceDisplayType, Model.AvailablePriceDisplayTypes) + @Html.ValidationMessageFor(model => model.PriceDisplayType) + + diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index 2c76aa8069..16e7022c43 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -985,14 +985,18 @@ public IEnumerable PrepareProductOverviewModels( throw new ArgumentNullException("products"); // PERF!! + var currentStore = _services.StoreContext.CurrentStore; + var currentCustomer = _services.WorkContext.CurrentCustomer; + var workingCurrency = _services.WorkContext.WorkingCurrency; var displayPrices = _services.Permissions.Authorize(StandardPermissionProvider.DisplayPrices); var enableShoppingCart = _services.Permissions.Authorize(StandardPermissionProvider.EnableShoppingCart); var enableWishlist = _services.Permissions.Authorize(StandardPermissionProvider.EnableWishlist); - var currentCustomer = _services.WorkContext.CurrentCustomer; - var taxDisplayType = _services.WorkContext.GetTaxDisplayTypeFor(currentCustomer, _services.StoreContext.CurrentStore.Id); + var taxDisplayType = _services.WorkContext.GetTaxDisplayTypeFor(currentCustomer, currentStore.Id); string taxInfo = T(taxDisplayType == TaxDisplayType.IncludingTax ? "Tax.InclVAT" : "Tax.ExclVAT"); string shippingInfoLink = _urlHelper.RouteUrl("Topic", new { SystemName = "shippinginfo" }); var cachedManufacturerModels = new Dictionary(); + PriceCalculationContext priceCalculationContext = null; + var res = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Products.CallForPrice", T("Products.CallForPrice") }, @@ -1004,14 +1008,13 @@ public IEnumerable PrepareProductOverviewModels( { "Common.AdditionalShippingSurcharge", T("Common.AdditionalShippingSurcharge") } }; - int[] productIds = products.Select(x => x.Id).ToArray(); - IList productIdsWithPriceAdjustments = null; + int[] productIds = products.Select(x => x.Id).ToArray(); var models = new List(); foreach (var product in products) { - var minPriceProduct = product; + var contextProduct = product; var model = new ProductOverviewModel { @@ -1026,181 +1029,156 @@ public IEnumerable PrepareProductOverviewModels( { #region Prepare product price + if (priceCalculationContext == null) + priceCalculationContext = _priceCalculationService.CreatePriceCalculationContext(productIds); + var priceModel = new ProductOverviewModel.ProductPriceModel { ForceRedirectionAfterAddingToCart = forceRedirectionAfterAddingToCart, ShowDiscountSign = _catalogSettings.ShowDiscountSign }; - switch (product.ProductType) + if (product.ProductType == ProductType.GroupedProduct) { - case ProductType.GroupedProduct: - { - #region Grouped product + #region Grouped product - var searchContext = new ProductSearchContext - { - StoreId = _services.StoreContext.CurrentStore.Id, - ParentGroupedProductId = product.Id, - PageSize = int.MaxValue, - VisibleIndividuallyOnly = false - }; + priceModel.DisableBuyButton = true; + priceModel.DisableWishListButton = true; + priceModel.AvailableForPreOrder = false; - var associatedProducts = _productService.SearchProducts(searchContext); + var searchContext = new ProductSearchContext + { + StoreId = currentStore.Id, + ParentGroupedProductId = product.Id, + PageSize = int.MaxValue, + VisibleIndividuallyOnly = false + }; - if (associatedProducts.Count <= 0) + var associatedProducts = _productService.SearchProducts(searchContext); + + if (associatedProducts.Count > 0) + { + contextProduct = associatedProducts.First(); + + if (displayPrices && _catalogSettings.PriceDisplayType != PriceDisplayType.Hide) + { + decimal? displayPrice = null; + + if (_catalogSettings.PriceDisplayType == PriceDisplayType.PreSelectedPrice) { - priceModel.OldPrice = null; - priceModel.Price = null; - priceModel.DisableBuyButton = true; - priceModel.DisableWishListButton = true; - priceModel.AvailableForPreOrder = false; + displayPrice = _priceCalculationService.GetPreselectedPrice(contextProduct, null); + } + else if (_catalogSettings.PriceDisplayType == PriceDisplayType.PriceWithoutDiscountsAndAttributes) + { + displayPrice = _priceCalculationService.GetFinalPrice(contextProduct, null, currentCustomer, decimal.Zero, false, 1, null); } else { - priceModel.DisableBuyButton = true; - priceModel.DisableWishListButton = true; - priceModel.AvailableForPreOrder = false; + displayPrice = _priceCalculationService.GetLowestPrice(product, associatedProducts, out contextProduct); + } - if (displayPrices) + if (contextProduct != null && !contextProduct.CustomerEntersPrice) + { + if (contextProduct.CallForPrice) { - decimal? minPossiblePrice = _priceCalculationService.GetLowestPrice(product, associatedProducts, out minPriceProduct); - - if (minPriceProduct != null && !minPriceProduct.CustomerEntersPrice) - { - if (minPriceProduct.CallForPrice) - { - priceModel.OldPrice = null; - priceModel.Price = res["Products.CallForPrice"]; - } - else if (minPossiblePrice.HasValue) - { - //calculate prices - decimal taxRate = decimal.Zero; - decimal oldPriceBase = _taxService.GetProductPrice(minPriceProduct, minPriceProduct.OldPrice, out taxRate); - decimal finalPriceBase = _taxService.GetProductPrice(minPriceProduct, minPossiblePrice.Value, out taxRate); - decimal finalPrice = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, _services.WorkContext.WorkingCurrency); - - priceModel.OldPrice = null; - priceModel.Price = String.Format(res["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice)); - priceModel.HasDiscount = finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero; - } - else - { - //Actually it's not possible (we presume that minimalPrice always has a value) - //We never should get here - Debug.WriteLine(string.Format("Cannot calculate minPrice for product #{0}", product.Id)); - } - } + priceModel.OldPrice = null; + priceModel.Price = res["Products.CallForPrice"]; } - else + else if (displayPrice.HasValue) { - //hide prices + //calculate prices + decimal taxRate = decimal.Zero; + decimal oldPriceBase = _taxService.GetProductPrice(contextProduct, contextProduct.OldPrice, out taxRate); + decimal finalPriceBase = _taxService.GetProductPrice(contextProduct, displayPrice.Value, out taxRate); + decimal finalPrice = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workingCurrency); + priceModel.OldPrice = null; - priceModel.Price = null; + priceModel.Price = String.Format(res["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice)); + priceModel.HasDiscount = finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero; + } + else + { + // Actually it's not possible (we presume that displayPrice always has a value). We never should get here + Debug.WriteLine(string.Format("Cannot calculate displayPrice for product #{0}", product.Id)); } } + } + } + + #endregion + } + else + { + #region Simple product - #endregion + //add to cart button + priceModel.DisableBuyButton = product.DisableBuyButton || !enableShoppingCart || !displayPrices; + + //add to wishlist button + priceModel.DisableWishListButton = product.DisableWishlistButton || !enableWishlist || !displayPrices; + + //pre-order + priceModel.AvailableForPreOrder = product.AvailableForPreOrder; + + //prices + if (displayPrices && _catalogSettings.PriceDisplayType != PriceDisplayType.Hide && !product.CustomerEntersPrice) + { + if (product.CallForPrice) + { + //call for price + priceModel.OldPrice = null; + priceModel.Price = res["Products.CallForPrice"]; } - break; - case ProductType.SimpleProduct: - default: + else { - #region Simple product + //calculate prices + bool displayFromMessage = false; + decimal displayPrice = decimal.Zero; + + if (_catalogSettings.PriceDisplayType == PriceDisplayType.PreSelectedPrice) + { + displayPrice = _priceCalculationService.GetPreselectedPrice(product, priceCalculationContext); + } + else if (_catalogSettings.PriceDisplayType == PriceDisplayType.PriceWithoutDiscountsAndAttributes) + { + displayPrice = _priceCalculationService.GetFinalPrice(product, null, currentCustomer, decimal.Zero, false, 1, null); + } + else + { + displayPrice = _priceCalculationService.GetLowestPrice(product, priceCalculationContext, out displayFromMessage); + } - //add to cart button - priceModel.DisableBuyButton = product.DisableBuyButton || !enableShoppingCart || !displayPrices; + decimal taxRate = decimal.Zero; + decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate); + decimal finalPriceBase = _taxService.GetProductPrice(product, displayPrice, out taxRate); - //add to wishlist button - priceModel.DisableWishListButton = product.DisableWishlistButton || !enableWishlist || !displayPrices; + decimal oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, workingCurrency); + decimal finalPrice = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workingCurrency); - //pre-order - priceModel.AvailableForPreOrder = product.AvailableForPreOrder; + priceModel.HasDiscount = (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero); - //prices - if (displayPrices) + if (displayFromMessage) { - if (!product.CustomerEntersPrice) - { - if (product.CallForPrice) - { - //call for price - priceModel.OldPrice = null; - priceModel.Price = res["Products.CallForPrice"]; - } - else - { - //calculate prices - bool isBundlePerItemPricing = (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing); - - bool displayFromMessage = false; - decimal minPossiblePrice = _priceCalculationService.GetLowestPrice(product, out displayFromMessage); - - if (!displayFromMessage) - { - if (productIdsWithPriceAdjustments == null) - productIdsWithPriceAdjustments = _productAttributeService.GetProductIdsWithPriceAdjustments(productIds); - - displayFromMessage = productIdsWithPriceAdjustments.Contains(product.Id); - } - - decimal taxRate = decimal.Zero; - decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate); - decimal finalPriceBase = _taxService.GetProductPrice(product, minPossiblePrice, out taxRate); - - decimal oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _services.WorkContext.WorkingCurrency); - decimal finalPrice = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, _services.WorkContext.WorkingCurrency); - - priceModel.HasDiscount = (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero); - - // check tier prices - if (product.HasTierPrices && !isBundlePerItemPricing && !displayFromMessage) - { - var tierPrices = new List(); - - tierPrices.AddRange(product.TierPrices - .OrderBy(tp => tp.Quantity) - .FilterByStore(_services.StoreContext.CurrentStore.Id) - .FilterForCustomer(_services.WorkContext.CurrentCustomer) - .ToList() - .RemoveDuplicatedQuantities()); - - // When there is just one tier (with qty 1), there are no actual savings in the list. - displayFromMessage = (tierPrices.Count > 0 && !(tierPrices.Count == 1 && tierPrices[0].Quantity <= 1)); - } - - if (displayFromMessage) - { - priceModel.OldPrice = null; - priceModel.Price = String.Format(res["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice)); - } - else - { - if (priceModel.HasDiscount) - { - priceModel.OldPrice = _priceFormatter.FormatPrice(oldPrice); - priceModel.Price = _priceFormatter.FormatPrice(finalPrice); - } - else - { - priceModel.OldPrice = null; - priceModel.Price = _priceFormatter.FormatPrice(finalPrice); - } - } - } - } + priceModel.OldPrice = null; + priceModel.Price = String.Format(res["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice)); } else { - //hide prices - priceModel.OldPrice = null; - priceModel.Price = null; + if (priceModel.HasDiscount) + { + priceModel.OldPrice = _priceFormatter.FormatPrice(oldPrice); + priceModel.Price = _priceFormatter.FormatPrice(finalPrice); + } + else + { + priceModel.OldPrice = null; + priceModel.Price = _priceFormatter.FormatPrice(finalPrice); + } } - - #endregion } - break; + } + + #endregion } model.ProductPrice = priceModel; @@ -1219,7 +1197,7 @@ public IEnumerable PrepareProductOverviewModels( //prepare picture model var defaultProductPictureCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_DEFAULTPICTURE_MODEL_KEY, product.Id, pictureSize, true, - _services.WorkContext.WorkingLanguage.Id, _services.WebHelper.IsCurrentConnectionSecured(), _services.StoreContext.CurrentStore.Id); + _services.WorkContext.WorkingLanguage.Id, _services.WebHelper.IsCurrentConnectionSecured(), currentStore.Id); model.DefaultPictureModel = _services.Cache.Get(defaultProductPictureCacheKey, () => { @@ -1243,15 +1221,15 @@ public IEnumerable PrepareProductOverviewModels( model.SpecificationAttributeModels = PrepareProductSpecificationModel(product); } - model.MinPriceProductId = minPriceProduct.Id; + model.MinPriceProductId = contextProduct.Id; model.ShowSku = _catalogSettings.ShowProductSku; model.ShowWeight = _catalogSettings.ShowWeight; model.ShowDimensions = _catalogSettings.ShowDimensions; - model.Sku = minPriceProduct.Sku; + model.Sku = contextProduct.Sku; model.Dimensions = res["Products.DimensionsValue"].Text.FormatCurrent( - minPriceProduct.Width.ToString("F2"), - minPriceProduct.Height.ToString("F2"), - minPriceProduct.Length.ToString("F2") + contextProduct.Width.ToString("F2"), + contextProduct.Height.ToString("F2"), + contextProduct.Length.ToString("F2") ); model.DimensionMeasureUnit = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId).Name; model.ThumbDimension = _mediaSettings.ProductThumbPictureSize; @@ -1263,9 +1241,9 @@ public IEnumerable PrepareProductOverviewModels( model.ShowDeliveryTimes = _catalogSettings.ShowDeliveryTimesInProductLists; model.InvisibleDeliveryTime = (product.ProductType == ProductType.GroupedProduct); - model.IsShipEnabled = minPriceProduct.IsShipEnabled; - model.DisplayDeliveryTimeAccordingToStock = minPriceProduct.DisplayDeliveryTimeAccordingToStock(_catalogSettings); - model.StockAvailablity = minPriceProduct.FormatStockMessage(_localizationService); + model.IsShipEnabled = contextProduct.IsShipEnabled; + model.DisplayDeliveryTimeAccordingToStock = contextProduct.DisplayDeliveryTimeAccordingToStock(_catalogSettings); + model.StockAvailablity = contextProduct.FormatStockMessage(_localizationService); model.DisplayBasePrice = _catalogSettings.ShowBasePriceInProductLists; model.CompareEnabled = _catalogSettings.CompareProductsEnabled; @@ -1273,7 +1251,7 @@ public IEnumerable PrepareProductOverviewModels( if (model.ShowDeliveryTimes) { - var deliveryTime = _deliveryTimeService.GetDeliveryTime(minPriceProduct); + var deliveryTime = _deliveryTimeService.GetDeliveryTime(contextProduct); if (deliveryTime != null) { model.DeliveryTimeName = deliveryTime.GetLocalized(x => x.Name); @@ -1288,20 +1266,19 @@ public IEnumerable PrepareProductOverviewModels( if (_catalogSettings.ShowBasePriceInProductLists) { - model.BasePriceInfo = minPriceProduct.GetBasePriceInfo(_localizationService, _priceFormatter); + model.BasePriceInfo = contextProduct.GetBasePriceInfo(_localizationService, _priceFormatter); } - var addShippingPrice = _currencyService.ConvertCurrency(minPriceProduct.AdditionalShippingCharge, - _services.StoreContext.CurrentStore.PrimaryStoreCurrency, _services.WorkContext.WorkingCurrency); + var addShippingPrice = _currencyService.ConvertCurrency(contextProduct.AdditionalShippingCharge, currentStore.PrimaryStoreCurrency, workingCurrency); if (addShippingPrice > 0 && displayPrices) { model.TransportSurcharge = res["Common.AdditionalShippingSurcharge"].Text.FormatWith(_priceFormatter.FormatPrice(addShippingPrice, true, false)); } - if (minPriceProduct.Weight > 0) + if (contextProduct.Weight > 0) { - model.Weight = "{0} {1}".FormatCurrent(minPriceProduct.Weight.ToString("F2"), _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name); + model.Weight = "{0} {1}".FormatCurrent(contextProduct.Weight.ToString("F2"), _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name); } // IsNew From 7a3418f0797117a5e034a6840353d7ee2e014cb9 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 24 Jul 2015 15:43:46 +0200 Subject: [PATCH 0297/1256] New options for manufacturer display on the homepage --- changelog.md | 3 +- .../Domain/Catalog/CatalogSettings.cs | 12 ++++++ .../201506181858349_AclRecordCustomerRole.cs | 12 ++++++ .../Infrastructure/AutoMapperStartupTask.cs | 1 - .../Models/Settings/CatalogSettingsModel.cs | 9 ++++ .../Views/Setting/Catalog.cshtml | 43 +++++++++++++++++++ .../Controllers/CatalogController.cs | 7 ++- .../Catalog/ManufacturerNavigationModel.cs | 8 +++- .../Themes/Alpha/Content/pages.less | 14 ++++++ .../Catalog/ManufacturerNavigation.cshtml | 20 ++++++++- 10 files changed, 123 insertions(+), 6 deletions(-) diff --git a/changelog.md b/changelog.md index 6e8c2f90ad..438a5a59e4 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,4 @@ -# Release Notes +# Release Notes ## SmartStore.NET 2.2.2 @@ -8,6 +8,7 @@ * Added zip code to shipping by weight computation method * Skrill payment plugin (distributed via Marketplace) * (Dev) DevTool plugin: added option to display all widget zones in public store +* New options for manufacturer display on the homepage ### Improvements * (Perf) several minor optimizations for faster app startup and page rendering diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs index dd7d67edea..d365513cb3 100644 --- a/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs @@ -38,6 +38,8 @@ public CatalogSettings() ProductSearchAutoCompleteNumberOfProducts = 10; ProductSearchTermMinimumLength = 3; NumberOfBestsellersOnHomepage = 6; + ShowManufacturersOnHomepage = true; + ShowManufacturerPictures = false; SearchPageProductsPerPage = 6; ProductsAlsoPurchasedEnabled = true; ProductsAlsoPurchasedNumber = 6; @@ -283,6 +285,16 @@ public CatalogSettings() ///
    public int NumberOfBestsellersOnHomepage { get; set; } + /// + /// Gets or sets a value indicating whether to show manufacturers on home page + /// + public bool ShowManufacturersOnHomepage { get; set; } + + /// + /// Gets or sets a value indicating whether to show manufacturer pictures or names on home page + /// + public bool ShowManufacturerPictures { get; set; } + /// /// Gets or sets a number of products per page on search products page /// diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs index 9126926fe2..153e8be49e 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs @@ -119,6 +119,18 @@ before you can assign them to all subcategories and products.
    builder.AddOrUpdate("Admin.Configuration.Payment.Methods.Fields.RecurringPaymentType", "Recurring payments", "Wiederkehrende Zahlungen"); + + builder.AddOrUpdate("Admin.Configuration.Settings.Catalog.ShowManufacturersOnHomepage", + "Show manufacturers on homepage", + "Zeige Hersteller auf der Homepage", + "Specifies whether manufacturers will be displayed on the homepage.", + "Bestimmt ob Hersteller auf der Homepage angezeigt werden."); + + builder.AddOrUpdate("Admin.Configuration.Settings.Catalog.ShowManufacturerPictures", + "Show manufacturer pictures on homepage", + "Zeige Herstellerbilder auf der Homepage", + "Specifies whether manufacturers will be displayed as images or textual links on the homepage.", + "Bestimmt ob Hersteller auf der Homepage als Bilder oder textuelle Links angezeigt werden."); } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs index d9331cdd05..60384337d9 100644 --- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs +++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs @@ -616,7 +616,6 @@ public void Execute() .ForMember(dest => dest.FileUploadMaximumSizeBytes, mo => mo.Ignore()) .ForMember(dest => dest.FileUploadAllowedExtensions, mo => mo.Ignore()) .ForMember(dest => dest.ProductSearchPageSize, mo => mo.Ignore()) - .ForMember(dest => dest.ManufacturersBlockItemsToDisplay, mo => mo.Ignore()) .ForMember(dest => dest.MostRecentlyUsedCategoriesMaxSize, mo => mo.Ignore()) .ForMember(dest => dest.MostRecentlyUsedManufacturersMaxSize, mo => mo.Ignore()); Mapper.CreateMap() diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs index ba76a185ea..14b966406f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Settings/CatalogSettingsModel.cs @@ -63,6 +63,15 @@ public CatalogSettingsModel() [SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.ShowDefaultQuantityUnit")] public bool ShowDefaultQuantityUnit { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.ShowManufacturersOnHomepage")] + public bool ShowManufacturersOnHomepage { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.ManufacturersBlockItemsToDisplay")] + public int ManufacturersBlockItemsToDisplay { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.ShowManufacturerPictures")] + public bool ShowManufacturerPictures { get; set; } + #endregion #region Product lists diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml index a55ae23614..f8bdcda4bf 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/Catalog.cshtml @@ -23,6 +23,7 @@ $("#@Html.FieldIdFor(model => model.RecentlyViewedProductsEnabled)").click(toggleRecentlyViewedProducts); $("#@Html.FieldIdFor(model => model.RecentlyAddedProductsEnabled)").click(toggleRecentlyAddedProducts); $("#@Html.FieldIdFor(model => model.ShowBestsellersOnHomepage)").click(toggleBestsellersOnHomepage); + $("#@Html.FieldIdFor(model => model.ShowManufacturersOnHomepage)").click(toggleManufacturersOnHomepage); $("#@Html.FieldIdFor(model => model.ProductsAlsoPurchasedEnabled)").click(toggleProductsAlsoPurchasedNumber); $("#@Html.FieldIdFor(model => model.ProductsByTagAllowCustomersToSelectPageSize)").click(toggleTagPageSize); $("#@Html.FieldIdFor(model => model.ProductSearchAllowCustomersToSelectPageSize)").click(toggleSearchPageSize); @@ -43,6 +44,7 @@ toggleCompareProducts(); toggleHtmlTextCollapsedHeight(); toggleFilterEnabled(); + toggleManufacturersOnHomepage(); }); function toggleShowCategoryProductNumberIncludingSubcategories() { @@ -90,6 +92,17 @@ } } + function toggleManufacturersOnHomepage() { + if ($('#@Html.FieldIdFor(model => model.ShowManufacturersOnHomepage)').is(':checked')) { + $('#pnlShowManufacturerPictures').show(); + $('#pnlManufacturersBlockItemsToDisplay').show(); + } + else { + $('#pnlShowManufacturerPictures').hide(); + $('#pnlManufacturersBlockItemsToDisplay').hide(); + } + } + function toggleProductsAlsoPurchasedNumber() { if ($('#@Html.FieldIdFor(model => model.ProductsAlsoPurchasedEnabled)').is(':checked')) { $('#pnlProductsAlsoPurchasedNumber').show(); @@ -290,6 +303,36 @@ @Html.ValidationMessageFor(model => model.NumberOfBestsellersOnHomepage) + + + + @Html.SmartLabelFor(model => model.ShowManufacturersOnHomepage) + + + @Html.SettingEditorFor(model => model.ShowManufacturersOnHomepage) + @Html.ValidationMessageFor(model => model.ShowManufacturersOnHomepage) + + + + + @Html.SmartLabelFor(model => model.ManufacturersBlockItemsToDisplay) + + + @Html.SettingEditorFor(model => model.ManufacturersBlockItemsToDisplay) + @Html.ValidationMessageFor(model => model.ManufacturersBlockItemsToDisplay) + + + + + @Html.SmartLabelFor(model => model.ShowManufacturerPictures) + + + @Html.SettingEditorFor(model => model.ShowManufacturerPictures) + @Html.ValidationMessageFor(model => model.ShowManufacturerPictures) + + + + @Html.SmartLabelFor(model => model.EnableHtmlTextCollapser) diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs index 191bdc64fc..91410424af 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogController.cs @@ -606,7 +606,7 @@ private PictureModel PrepareManufacturerPictureModel(Manufacturer manufacturer, [ChildActionOnly] public ActionResult ManufacturerNavigation(int currentManufacturerId) { - if (_catalogSettings.ManufacturersBlockItemsToDisplay == 0) + if (_catalogSettings.ManufacturersBlockItemsToDisplay == 0 || _catalogSettings.ShowManufacturersOnHomepage == false) return Content(""); string cacheKey = string.Format(ModelCacheEventConsumer.MANUFACTURER_NAVIGATION_MODEL_KEY, currentManufacturerId, _services.WorkContext.WorkingLanguage.Id, _services.StoreContext.CurrentStore.Id); @@ -617,7 +617,9 @@ public ActionResult ManufacturerNavigation(int currentManufacturerId) var manufacturers = _manufacturerService.GetAllManufacturers(); var model = new ManufacturerNavigationModel() { - TotalManufacturers = manufacturers.Count + TotalManufacturers = manufacturers.Count, + DisplayManufacturers = _catalogSettings.ShowManufacturersOnHomepage, + DisplayImages = _catalogSettings.ShowManufacturerPictures }; foreach (var manufacturer in manufacturers.Take(_catalogSettings.ManufacturersBlockItemsToDisplay)) @@ -627,6 +629,7 @@ public ActionResult ManufacturerNavigation(int currentManufacturerId) Id = manufacturer.Id, Name = manufacturer.GetLocalized(x => x.Name), SeName = manufacturer.GetSeName(), + PictureUrl = _pictureService.GetPictureUrl(manufacturer.PictureId.GetValueOrDefault(), _mediaSettings.ManufacturerThumbPictureSize), IsActive = currentManufacturer != null && currentManufacturer.Id == manufacturer.Id, }; model.Manufacturers.Add(modelMan); diff --git a/src/Presentation/SmartStore.Web/Models/Catalog/ManufacturerNavigationModel.cs b/src/Presentation/SmartStore.Web/Models/Catalog/ManufacturerNavigationModel.cs index dcbefd212d..1c03322e45 100644 --- a/src/Presentation/SmartStore.Web/Models/Catalog/ManufacturerNavigationModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Catalog/ManufacturerNavigationModel.cs @@ -13,6 +13,10 @@ public ManufacturerNavigationModel() public IList Manufacturers { get; set; } public int TotalManufacturers { get; set; } + + public bool DisplayManufacturers { get; set; } + + public bool DisplayImages { get; set; } } public partial class ManufacturerBriefInfoModel : EntityModelBase @@ -20,7 +24,9 @@ public partial class ManufacturerBriefInfoModel : EntityModelBase public string Name { get; set; } public string SeName { get; set; } - + + public string PictureUrl { get; set; } + public bool IsActive { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Themes/Alpha/Content/pages.less b/src/Presentation/SmartStore.Web/Themes/Alpha/Content/pages.less index 4b7f87e7bf..11a472e78c 100644 --- a/src/Presentation/SmartStore.Web/Themes/Alpha/Content/pages.less +++ b/src/Presentation/SmartStore.Web/Themes/Alpha/Content/pages.less @@ -167,3 +167,17 @@ vertical-align: top; } +/* Manufacturers on homepage +================================================ */ + +.block-manufacturer-navigation .manufacturer-pic { + float: left; + width: 50px; + height: 50px; + margin: 0 0 10px 10px; + + img { + max-width: 50px; + max-height: 50px; + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Views/Catalog/ManufacturerNavigation.cshtml b/src/Presentation/SmartStore.Web/Views/Catalog/ManufacturerNavigation.cshtml index f408a7bf41..e5d653f039 100644 --- a/src/Presentation/SmartStore.Web/Views/Catalog/ManufacturerNavigation.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Catalog/ManufacturerNavigation.cshtml @@ -13,10 +13,28 @@ + + @if (Model.DisplayImages) + { +
     
    + } + @if (Model.TotalManufacturers > Model.Manufacturers.Count) {
    From 5dd82b10215cf736ff59b3da7f865b4155258111 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Fri, 24 Jul 2015 20:53:21 +0200 Subject: [PATCH 0298/1256] WebScheduler 8 --- .../DependencyManagement/ContainerManager.cs | 8 +++--- .../Tasks/TaskExecutionContext.cs | 25 +++++++++++++++---- .../SmartStore.Services/Tasks/TaskExecutor.cs | 7 ++++-- .../Controllers/ScheduleTaskController.cs | 7 ++++-- .../Models/Tasks/ScheduleTaskModel.cs | 2 ++ 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs index 7bac9acb62..e15832df7f 100644 --- a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs +++ b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs @@ -21,9 +21,9 @@ public IContainer Container get { return _container; } } - public T Resolve(string key = "", ILifetimeScope scope = null) where T : class + public T Resolve(object key = null, ILifetimeScope scope = null) where T : class { - if (string.IsNullOrEmpty(key)) + if (key == null) { return (scope ?? Scope()).Resolve(); } @@ -45,9 +45,9 @@ public object ResolveNamed(string name, Type type, ILifetimeScope scope = null) return (scope ?? Scope()).ResolveNamed(name, type); } - public T[] ResolveAll(string key = "", ILifetimeScope scope = null) + public T[] ResolveAll(object key = null, ILifetimeScope scope = null) { - if (string.IsNullOrEmpty(key)) + if (key == null) { return (scope ?? Scope()).Resolve>().ToArray(); } diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs b/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs index 97824c3416..eb87adc407 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs @@ -13,11 +13,26 @@ namespace SmartStore.Services.Tasks ///
    public class TaskExecutionContext { - /// - /// The shared instance created - /// before the execution of the task's background thread. - /// - public object LifetimeScope { get; internal set; } + private readonly IComponentContext _componentContext; + + internal TaskExecutionContext(IComponentContext componentContext) + { + this._componentContext = componentContext; + } + + public T Resolve(object key = null) where T : class + { + if (key == null) + { + return _componentContext.Resolve(); + } + return _componentContext.ResolveKeyed(key); + } + + public T ResolveNamed(string name) where T : class + { + return _componentContext.ResolveNamed(name); + } /// /// A cancellation token for the running task. diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs b/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs index d94abd4b1b..7101c1d242 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs @@ -9,6 +9,7 @@ using SmartStore.Core.Async; using System.Threading; using SmartStore.Core.Plugins; +using Autofac; namespace SmartStore.Services.Tasks { @@ -18,11 +19,13 @@ public class TaskExecutor : ITaskExecutor private readonly IScheduleTaskService _scheduledTaskService; private readonly IDbContext _dbContext; private readonly Func _taskResolver; + private readonly IComponentContext _componentContext; - public TaskExecutor(IScheduleTaskService scheduledTaskService, IDbContext dbContext, Func taskResolver) + public TaskExecutor(IScheduleTaskService scheduledTaskService, IDbContext dbContext, IComponentContext componentContext, Func taskResolver) { this._scheduledTaskService = scheduledTaskService; this._dbContext = dbContext; + this._componentContext = componentContext; this._taskResolver = taskResolver; Logger = NullLogger.Instance; @@ -80,7 +83,7 @@ public void Execute(ScheduleTask task, bool throwOnError = false) }; AsyncState.Current.Set(taskProgressInfo, stateName, true); - var ctx = new TaskExecutionContext + var ctx = new TaskExecutionContext(_componentContext) { ScheduleTask = task.Clone(), CancellationToken = cts.Token diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs index 0c058cdda2..55814bf825 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs @@ -80,15 +80,17 @@ protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) } var nextRunStr = ""; + bool isOverdue = false; if (dueIn.HasValue) { if (dueIn.Value.TotalSeconds > 0) { - nextRunStr = dueIn.Value.Prettify(); + nextRunStr = "{0}".FormatCurrent(dueIn.Value.Prettify()); } else { - nextRunStr = T("Common.Waiting") + "..."; + nextRunStr = "{0}".FormatCurrent(T("Common.Waiting") + "..."); + isOverdue = true; } } @@ -107,6 +109,7 @@ protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) IsRunning = task.IsRunning, CancelUrl = task.IsRunning ? Url.Action("CancelJob", new { id = task.Id }) : "", ProgressInfo = task.IsRunning ? T("Admin.System.ScheduleTasks.RunNow.IsRunning").Text : "", + IsOverdue = isOverdue, Duration = "" }; diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs index 070618b167..1e33efda3a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs @@ -34,6 +34,8 @@ public partial class ScheduleTaskModel : EntityModelBase [SmartResourceDisplayName("Admin.System.ScheduleTasks.NextRun")] public string NextRunUtc { get; set; } + public bool IsOverdue { get; set; } + [SmartResourceDisplayName("Common.Error")] public string LastError { get; set; } From 80e8123c72f53bf21aa738a906f0d00621ac0110 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Sat, 25 Jul 2015 02:24:31 +0200 Subject: [PATCH 0299/1256] WebScheduler final --- .../Domain/Tasks/ScheduleTask.cs | 15 ++- .../Mapping/Tasks/ScheduleTaskMap.cs | 3 +- .../201507211743009_WebScheduler.resx | 126 ------------------ ... 201507242008201_WebScheduler.Designer.cs} | 2 +- ...ler.cs => 201507242008201_WebScheduler.cs} | 14 +- .../201507242008201_WebScheduler.resx | 126 ++++++++++++++++++ .../Setup/Builder/LocaleResourcesMigrator.cs | 2 +- .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../SmartStore.Services.csproj | 1 - .../Tasks/IScheduleTaskService.cs | 19 +++ .../Tasks/ITaskScheduler.cs | 38 +----- .../Tasks/ScheduleTaskService.cs | 45 ++++++- .../Tasks/TaskExecutionContext.cs | 36 +++-- .../SmartStore.Services/Tasks/TaskExecutor.cs | 24 ++-- .../Tasks/TaskProgressInfo.cs | 49 ------- .../Tasks/TaskScheduler.cs | 24 +--- .../Administration/Content/admin.less | 35 +++++ .../Controllers/ScheduleTaskController.cs | 51 +++---- .../Models/Tasks/ScheduleTaskModel.cs | 3 +- .../Administration/Scripts/admin.common.js | 63 ++++++++- .../Views/ScheduleTask/List.cshtml | 33 ++++- 21 files changed, 414 insertions(+), 305 deletions(-) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.resx rename src/Libraries/SmartStore.Data/Migrations/{201507211743009_WebScheduler.Designer.cs => 201507242008201_WebScheduler.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201507211743009_WebScheduler.cs => 201507242008201_WebScheduler.cs} (77%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507242008201_WebScheduler.resx delete mode 100644 src/Libraries/SmartStore.Services/Tasks/TaskProgressInfo.cs diff --git a/src/Libraries/SmartStore.Core/Domain/Tasks/ScheduleTask.cs b/src/Libraries/SmartStore.Core/Domain/Tasks/ScheduleTask.cs index 7cfff3c974..5aa4f04e23 100644 --- a/src/Libraries/SmartStore.Core/Domain/Tasks/ScheduleTask.cs +++ b/src/Libraries/SmartStore.Core/Domain/Tasks/ScheduleTask.cs @@ -26,6 +26,7 @@ public class ScheduleTask : BaseEntity, ICloneable /// /// Gets or sets the type of appropriate ITask class /// + [Index("IX_Type")] public string Type { get; set; } /// @@ -42,8 +43,10 @@ public class ScheduleTask : BaseEntity, ICloneable [Index("IX_NextRun_Enabled", 0)] public DateTime? NextRunUtc { get; set; } + [Index("IX_LastStart_LastEnd", 0)] public DateTime? LastStartUtc { get; set; } + [Index("IX_LastStart_LastEnd", 1)] public DateTime? LastEndUtc { get; set; } public DateTime? LastSuccessUtc { get; set; } @@ -52,6 +55,16 @@ public class ScheduleTask : BaseEntity, ICloneable public bool IsHidden { get; set; } + /// + /// Gets or sets a value indicating the current percentual progress for a running task + /// + public int? ProgressPercent { get; set; } + + /// + /// Gets or sets the current progress message for a running task + /// + public string ProgressMessage { get; set; } + /// /// Gets a value indicating whether a task is running /// @@ -59,7 +72,7 @@ public bool IsRunning { get { - var result = (LastStartUtc.HasValue && LastStartUtc.Value > LastEndUtc.GetValueOrDefault()); + var result = LastStartUtc.HasValue && LastStartUtc.Value > LastEndUtc.GetValueOrDefault(); return result; } } diff --git a/src/Libraries/SmartStore.Data/Mapping/Tasks/ScheduleTaskMap.cs b/src/Libraries/SmartStore.Data/Mapping/Tasks/ScheduleTaskMap.cs index b23b152152..8d06abd923 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Tasks/ScheduleTaskMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Tasks/ScheduleTaskMap.cs @@ -10,9 +10,10 @@ public ScheduleTaskMap() this.ToTable("ScheduleTask"); this.HasKey(t => t.Id); this.Property(t => t.Name).HasMaxLength(500).IsRequired(); - this.Property(t => t.Type).HasMaxLength(1000).IsRequired(); + this.Property(t => t.Type).HasMaxLength(800).IsRequired(); this.Property(t => t.Alias).HasMaxLength(500); this.Property(t => t.LastError).HasMaxLength(1000); + this.Property(t => t.ProgressMessage).HasMaxLength(1000).IsOptional(); this.Ignore(t => t.IsRunning); this.Ignore(t => t.IsPending); diff --git a/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.resx b/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.resx deleted file mode 100644 index af5dcde47c..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201507242008201_WebScheduler.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201507242008201_WebScheduler.Designer.cs index 765d3e0a62..d9e3e0bca9 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507242008201_WebScheduler.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class WebScheduler : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201507211743009_WebScheduler"; } + get { return "201507242008201_WebScheduler"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.cs b/src/Libraries/SmartStore.Data/Migrations/201507242008201_WebScheduler.cs similarity index 77% rename from src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.cs rename to src/Libraries/SmartStore.Data/Migrations/201507242008201_WebScheduler.cs index d49a775776..d9a437cb3c 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507211743009_WebScheduler.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507242008201_WebScheduler.cs @@ -8,15 +8,27 @@ public partial class WebScheduler : DbMigration, ILocaleResourcesProvider, IData { public override void Up() { - AddColumn("dbo.ScheduleTask", "Alias", c => c.String(maxLength: 4000)); + AddColumn("dbo.ScheduleTask", "Alias", c => c.String(maxLength: 500)); AddColumn("dbo.ScheduleTask", "NextRunUtc", c => c.DateTime()); AddColumn("dbo.ScheduleTask", "IsHidden", c => c.Boolean(nullable: false)); + AddColumn("dbo.ScheduleTask", "ProgressPercent", c => c.Int()); + AddColumn("dbo.ScheduleTask", "ProgressMessage", c => c.String(maxLength: 1000)); + AlterColumn("dbo.ScheduleTask", "Name", c => c.String(nullable: false, maxLength: 500)); + AlterColumn("dbo.ScheduleTask", "Type", c => c.String(nullable: false, maxLength: 800)); + CreateIndex("dbo.ScheduleTask", "Type"); CreateIndex("dbo.ScheduleTask", new[] { "NextRunUtc", "Enabled" }, name: "IX_NextRun_Enabled"); + CreateIndex("dbo.ScheduleTask", new[] { "LastStartUtc", "LastEndUtc" }, name: "IX_LastStart_LastEnd"); } public override void Down() { + DropIndex("dbo.ScheduleTask", "IX_LastStart_LastEnd"); DropIndex("dbo.ScheduleTask", "IX_NextRun_Enabled"); + DropIndex("dbo.ScheduleTask", new[] { "Type" }); + //AlterColumn("dbo.ScheduleTask", "Type", c => c.String(nullable: false)); + //AlterColumn("dbo.ScheduleTask", "Name", c => c.String(nullable: false)); + DropColumn("dbo.ScheduleTask", "ProgressMessage"); + DropColumn("dbo.ScheduleTask", "ProgressPercent"); DropColumn("dbo.ScheduleTask", "IsHidden"); DropColumn("dbo.ScheduleTask", "NextRunUtc"); DropColumn("dbo.ScheduleTask", "Alias"); diff --git a/src/Libraries/SmartStore.Data/Migrations/201507242008201_WebScheduler.resx b/src/Libraries/SmartStore.Data/Migrations/201507242008201_WebScheduler.resx new file mode 100644 index 0000000000..7795c02827 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507242008201_WebScheduler.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Setup/Builder/LocaleResourcesMigrator.cs b/src/Libraries/SmartStore.Data/Setup/Builder/LocaleResourcesMigrator.cs index cdef6d5f8d..9a1d698396 100644 --- a/src/Libraries/SmartStore.Data/Setup/Builder/LocaleResourcesMigrator.cs +++ b/src/Libraries/SmartStore.Data/Setup/Builder/LocaleResourcesMigrator.cs @@ -102,7 +102,7 @@ public void Migrate(IEnumerable entries, bool updateTouched toUpdate.Each(x => _ctx.Entry(x).State = System.Data.Entity.EntityState.Modified); // save now - _ctx.SaveChanges(); + int affectedRows = _ctx.SaveChanges(); } } diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index f828c8a076..fe9dcc8e8a 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -303,9 +303,9 @@ 201507200832223_SortFilterHomepageProducts.cs - - - 201507211743009_WebScheduler.cs + + + 201507242008201_WebScheduler.cs @@ -582,8 +582,8 @@ 201507200832223_SortFilterHomepageProducts.cs - - 201507211743009_WebScheduler.cs + + 201507242008201_WebScheduler.cs diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index d1392d9548..0c76cbc078 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -449,7 +449,6 @@ - diff --git a/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs b/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs index a8391c3064..2de26a49ad 100644 --- a/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs +++ b/src/Libraries/SmartStore.Services/Tasks/IScheduleTaskService.cs @@ -41,6 +41,25 @@ public partial interface IScheduleTaskService /// Tasks IList GetPendingTasks(); + /// + /// Gets a value indicating whether at least one task is running currently. + /// + /// + bool HasRunningTasks(); + + /// + /// Gets a value indicating whether a task is currently running + /// + /// A identifier + /// true if the task is running, false otherwise + bool IsTaskRunning(int taskId); + + /// + /// Gets a list of currently running instances. + /// + /// Tasks + IList GetRunningTasks(); + /// /// Inserts a task /// diff --git a/src/Libraries/SmartStore.Services/Tasks/ITaskScheduler.cs b/src/Libraries/SmartStore.Services/Tasks/ITaskScheduler.cs index 5a1b753ed0..99a5d554c5 100644 --- a/src/Libraries/SmartStore.Services/Tasks/ITaskScheduler.cs +++ b/src/Libraries/SmartStore.Services/Tasks/ITaskScheduler.cs @@ -31,28 +31,6 @@ public interface ITaskScheduler /// bool IsActive { get; } - /// - /// Gets a value indicating whether a task is currently running - /// - /// A identifier - /// true if the task is running, false otherwise - bool IsTaskRunning(int scheduleTaskId); - - /// - /// Gets a sequence of instances containing - /// metadata and progress information about currently running tasks. - /// - /// A sequence of task info objects if any task is running, an empty enumerable otherwise. - IEnumerable GetAllRunningTasks(); - - /// - /// Gets a instance containing - /// metadata and progress information about a currently running task. - /// - /// A identifier - /// A task info object if the task is running, null otherwise - TaskProgressInfo GetRunningTask(int scheduleTaskId); - /// /// Gets a instance used /// to signal a task cancellation request. @@ -93,22 +71,7 @@ public interface ITaskScheduler public static class ITaskSchedulerExtensions { - ///// The type of the task (must implement ) - //public static bool IsTaskRunning(this ITaskScheduler scheduler) where TTask : ITask - //{ - // return scheduler.IsTaskRunning(typeof(TTask)); - //} - - //public static TaskProgressInfo GetRunningTask(this ITaskScheduler scheduler) where TTask : ITask - //{ - // return scheduler.GetRunningTask(typeof(TTask)); - //} - //public static CancellationTokenSource GetCancelTokenSourceFor(this ITaskScheduler scheduler) where TTask : ITask - //{ - // return scheduler.GetCancelTokenSourceFor(typeof(TTask)); - //} - internal static void SetBaseUrl(this ITaskScheduler scheduler, IStoreService storeService, HttpContextBase httpContext) { var path = VirtualPathUtility.ToAbsolute("~/TaskScheduler"); @@ -130,5 +93,6 @@ internal static void SetBaseUrl(this ITaskScheduler scheduler, IStoreService sto scheduler.BaseUrl = url; } + } } diff --git a/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs b/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs index 87c17389c9..bd6e295107 100644 --- a/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs +++ b/src/Libraries/SmartStore.Services/Tasks/ScheduleTaskService.cs @@ -89,13 +89,45 @@ public virtual IList GetPendingTasks() var now = DateTime.UtcNow; var query = from t in _taskRepository.Table - where t.Enabled && t.NextRunUtc.HasValue && t.NextRunUtc <= now + where t.NextRunUtc.HasValue && t.NextRunUtc <= now && t.Enabled orderby t.NextRunUtc, t.Seconds select t; return query.ToList(); } + public virtual bool HasRunningTasks() + { + var query = GetRunningTasksQuery(); + return query.Any(); + } + + public virtual bool IsTaskRunning(int taskId) + { + if (taskId <= 0) + return false; + + var query = GetRunningTasksQuery(); + query.Where(t => t.Id == taskId); + return query.Any(); + } + + public virtual IList GetRunningTasks() + { + return GetRunningTasksQuery().ToList(); + } + + private IQueryable GetRunningTasksQuery() + { + var query = from t in _taskRepository.Table + where t.LastStartUtc.HasValue && t.LastStartUtc.Value > (t.LastEndUtc ?? DateTime.MinValue) + orderby t.LastStartUtc + select t; + + return query; + } + + public virtual void InsertTask(ScheduleTask task) { if (task == null) @@ -122,10 +154,15 @@ public void CalculateNextRunTimes(IEnumerable tasks, bool isAppSta foreach (var task in tasks) { task.NextRunUtc = task.Enabled ? now.AddSeconds(task.Seconds) : (DateTime?)null; - if (isAppStart && task.LastEndUtc.GetValueOrDefault() < task.LastStartUtc) + if (isAppStart) { - task.LastEndUtc = task.LastStartUtc; - task.LastError = T("Admin.System.ScheduleTasks.AbnormalAbort"); + task.ProgressPercent = null; + task.ProgressMessage = null; + if (task.LastEndUtc.GetValueOrDefault() < task.LastStartUtc) + { + task.LastEndUtc = task.LastStartUtc; + task.LastError = T("Admin.System.ScheduleTasks.AbnormalAbort"); + } } this.UpdateTask(task); } diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs b/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs index eb87adc407..7113794245 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskExecutionContext.cs @@ -4,6 +4,7 @@ using System.Threading; using Autofac; using SmartStore.Core.Async; +using SmartStore.Core.Data; using SmartStore.Core.Domain.Tasks; namespace SmartStore.Services.Tasks @@ -14,10 +15,12 @@ namespace SmartStore.Services.Tasks public class TaskExecutionContext { private readonly IComponentContext _componentContext; + private readonly ScheduleTask _originalTask; - internal TaskExecutionContext(IComponentContext componentContext) + internal TaskExecutionContext(IComponentContext componentContext, ScheduleTask originalTask) { this._componentContext = componentContext; + this._originalTask = originalTask; } public T Resolve(object key = null) where T : class @@ -42,18 +45,35 @@ public T ResolveNamed(string name) where T : class public ScheduleTask ScheduleTask { get; set; } - public void SetProgress(float? progress, string message) + /// + /// Persists a task's progress information information to the database + /// + /// Percentual progress. Can be null or a value between 0 and 100. + /// Progress message. Can be null. + /// if true, saves the updated task entity immediately, or lazily with the next database commit otherwise. + public void SetProgress(int? progress, string message, bool immediately = false) { if (progress.HasValue) Guard.ArgumentInRange(progress.Value, 0, 100, "progress"); - var stateName = ScheduleTask.Id.ToString(); + // update cloned entity + ScheduleTask.ProgressPercent = progress; + ScheduleTask.ProgressMessage = message; - AsyncState.Current.Update(x => - { - x.Progress = progress; - x.Message = message; - }, stateName); + // update attached entity + _originalTask.ProgressPercent = progress; + _originalTask.ProgressMessage = message; + + if (immediately) + { + try // dont't let this abort the task on failure + { + var dbContext = _componentContext.Resolve(); + dbContext.ChangeState(_originalTask, System.Data.Entity.EntityState.Modified); + dbContext.SaveChanges(); + } + catch { } + } } } } diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs b/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs index 7101c1d242..86e695a704 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskExecutor.cs @@ -42,6 +42,7 @@ public void Execute(ScheduleTask task, bool throwOnError = false) return; bool faulted = false; + bool canceled = false; string lastError = null; ITask instance = null; string stateName = null; @@ -73,21 +74,12 @@ public void Execute(ScheduleTask task, bool throwOnError = false) // create & set a composite CancellationTokenSource which also contains the global app shoutdown token var cts = CancellationTokenSource.CreateLinkedTokenSource(AsyncRunner.AppShutdownCancellationToken, new CancellationTokenSource().Token); - AsyncState.Current.SetCancelTokenSource(cts, stateName); + AsyncState.Current.SetCancelTokenSource(cts, stateName); - // tell AsyncState about a new running task - var taskProgressInfo = new TaskProgressInfo - { - ScheduleTaskId = task.Id, - TaskType = instance.GetType() - }; - AsyncState.Current.Set(taskProgressInfo, stateName, true); - - var ctx = new TaskExecutionContext(_componentContext) + var ctx = new TaskExecutionContext(_componentContext, task) { ScheduleTask = task.Clone(), CancellationToken = cts.Token - // TODO: Remove LifetimeScope }; instance.Execute(ctx); @@ -95,6 +87,7 @@ public void Execute(ScheduleTask task, bool throwOnError = false) catch (Exception ex) { faulted = true; + canceled = ex is OperationCanceledException; Logger.Error(string.Format("Error while running scheduled task '{0}'. {1}", task.Name, ex.Message), ex); lastError = ex.Message.Truncate(995, "..."); if (throwOnError) @@ -107,16 +100,19 @@ public void Execute(ScheduleTask task, bool throwOnError = false) // remove from AsyncState if (stateName.HasValue()) { - AsyncState.Current.Remove(stateName); + AsyncState.Current.Remove(stateName); } - + + task.ProgressPercent = null; + task.ProgressMessage = null; + var now = DateTime.UtcNow; task.LastError = lastError; task.LastEndUtc = now; if (faulted) { - if (task.StopOnError || instance == null) + if ((!canceled && task.StopOnError) || instance == null) { task.Enabled = false; } diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskProgressInfo.cs b/src/Libraries/SmartStore.Services/Tasks/TaskProgressInfo.cs deleted file mode 100644 index b07d1fd830..0000000000 --- a/src/Libraries/SmartStore.Services/Tasks/TaskProgressInfo.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; - -namespace SmartStore.Services.Tasks -{ - /// - /// Contains information about a task's progress - /// - [Serializable] - public class TaskProgressInfo : ICloneable - { - /// - /// The ScheduleTask identifier - /// - public int ScheduleTaskId { get; set; } - - /// - /// The type of the concrete implementation currently running - /// - public Type TaskType { get; set; } - - /// - /// Gets the current progress percentage of the task - /// - public float? Progress { get; set; } - - /// - /// Gets the current progress message of the task - /// - public string Message { get; set; } - - public string StateName - { - get - { - return ScheduleTaskId.ToString(); - } - } - - public TaskProgressInfo Clone() - { - return (TaskProgressInfo)this.MemberwiseClone(); - } - - object ICloneable.Clone() - { - return this.MemberwiseClone(); - } - } -} diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs b/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs index 4422c99008..ff1b736ffb 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using System.Web.Hosting; using SmartStore.Core.Async; +using SmartStore.Core.Domain.Tasks; namespace SmartStore.Services.Tasks { @@ -66,30 +67,9 @@ public bool IsActive get { return _timer.Enabled; } } - public IEnumerable GetAllRunningTasks() - { - var tasks = AsyncState.Current.GetAll(); - return tasks.Select(x => x.Clone()); - } - - public bool IsTaskRunning(int scheduleTaskId) - { - var exists = AsyncState.Current.Exists(scheduleTaskId.ToString()); - return exists; - } - - public TaskProgressInfo GetRunningTask(int scheduleTaskId) - { - var info = AsyncState.Current.Get(scheduleTaskId.ToString()); - if (info != null) - return info.Clone(); - - return null; - } - public CancellationTokenSource GetCancelTokenSourceFor(int scheduleTaskId) { - var cts = AsyncState.Current.GetCancelTokenSource(scheduleTaskId.ToString()); + var cts = AsyncState.Current.GetCancelTokenSource(scheduleTaskId.ToString()); return cts; } diff --git a/src/Presentation/SmartStore.Web/Administration/Content/admin.less b/src/Presentation/SmartStore.Web/Administration/Content/admin.less index c3bf87312d..75d3bfcdb8 100644 --- a/src/Presentation/SmartStore.Web/Administration/Content/admin.less +++ b/src/Presentation/SmartStore.Web/Administration/Content/admin.less @@ -326,6 +326,41 @@ header { to {left: 0; width: 100%;} } +.loading-bar { + height: 4px; + width: 100%; + position: relative; + overflow: hidden; + background-color: #ddd; +} +.loading-bar:before { + display: block; + position: absolute; + content: ""; + left: -200px; + width: 200px; + height: 4px; + background-color: #2980b9; + animation: loadingbar 2s linear infinite; + -webkit-animation: loadingbar 2s linear infinite; +} +@keyframes loadingbar { + from {left: -200px; width: 30%;} + 50% {width: 30%;} + 70% {width: 70%;} + 80% { left: 50%;} + 95% {left: 120%;} + to {left: 100%;} +} +@-webkit-keyframes loadingbar { + from {left: -200px; width: 30%;} + 50% {width: 30%;} + 70% {width: 70%;} + 80% { left: 50%;} + 95% {left: 120%;} + to {left: 100%;} +} + #content { position: relative; height: auto; diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs index 55814bf825..0de794588b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs @@ -94,6 +94,8 @@ protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) } } + var isRunning = task.IsRunning; + var model = new ScheduleTaskModel { Id = task.Id, @@ -106,9 +108,10 @@ protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) LastSuccessUtc = task.LastSuccessUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastSuccessUtc.Value, DateTimeKind.Utc).ToString("G") : "", NextRunUtc = nextRunStr, LastError = task.LastError.EmptyNull(), - IsRunning = task.IsRunning, - CancelUrl = task.IsRunning ? Url.Action("CancelJob", new { id = task.Id }) : "", - ProgressInfo = task.IsRunning ? T("Admin.System.ScheduleTasks.RunNow.IsRunning").Text : "", + IsRunning = isRunning, + CancelUrl = isRunning ? Url.Action("CancelJob", new { id = task.Id }) : "", + ProgressPercent = task.ProgressPercent, + ProgressMessage = task.ProgressMessage, IsOverdue = isOverdue, Duration = "" }; @@ -149,30 +152,11 @@ public ActionResult List(GridCommand command) var models = _scheduleTaskService.GetAllTasks(true) .Where(IsTaskVisible) .Select(PrepareScheduleTaskModel) + .OrderByDescending(x => x.IsRunning) + .ThenByDescending(x => x.IsOverdue) + .ThenBy(x => x.Seconds) .ToList(); - foreach (var item in models) - { - if (!item.IsRunning) - continue; - - TaskProgressInfo info; - info = _taskScheduler.GetRunningTask(item.Id); - if (info == null) - continue; - - if (info.Progress.HasValue || info.Message.HasValue()) - { - var tokens = new List(); - if (info.Progress.HasValue) - tokens.Add(string.Format("{0:p0}", (info.Progress.Value / 100))); - if (info.Message.HasValue()) - tokens.Add(info.Message.ToString()); - - item.ProgressInfo += " ({0})".FormatCurrent(string.Join(" - ", tokens)); - } - } - var model = new GridModel { Data = models, @@ -235,6 +219,23 @@ public ActionResult TaskUpdate(ScheduleTaskModel model, GridCommand command) return List(command); } + [HttpPost] + public ActionResult GetRunningTasks() + { + if (!_scheduleTaskService.HasRunningTasks()) + return Json(null); + + var runningTasks = from t in _scheduleTaskService.GetRunningTasks() + select new + { + id = t.Id, + percent = t.ProgressPercent, + message = t.ProgressMessage, + }; + + return Json(runningTasks.ToArray()); + } + public ActionResult RunJob(int id, string returnUrl = "") { if (!_permissionService.Authorize(StandardPermissionProvider.ManageScheduleTasks)) diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs index 1e33efda3a..b303fbb6ee 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs @@ -42,8 +42,9 @@ public partial class ScheduleTaskModel : EntityModelBase public string Duration { get; set; } public bool IsRunning { get; set; } + public int? ProgressPercent { get; set; } + public string ProgressMessage { get; set; } public string CancelUrl { get; set; } - public string ProgressInfo { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js index 5451a1ad70..4958bcdf53 100644 --- a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js +++ b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js @@ -54,7 +54,68 @@ var Admin = { } } }); - } + }, + + TaskWatcher: (function () { + var interval; + + return { + startWatching: function (opts) { + function poll() { + $.ajax({ + cache: false, + type: 'POST', + global: false, + url: opts.pollUrl, + dataType: 'json', + success: function (data) { + data = data || []; + var runningElements = []; + $.each(data, function (i, task) { + var el = $(opts.elementsSelector + '[data-task-id=' + task.id + ']'); + if (el.length) { + runningElements.push(el[0]); + if (el.data('running')) { + // already running + el.find('.text').text(task.message || opts.defaultProgressMessage); + el.find('.percent').text(task.percent >> 0 ? task.percent + ' %' : ""); + } + else { + // new task + var row1 = $('
    ').appendTo(el); + row1.append($('
    ' + (task.message || opts.defaultProgressMessage) + '
    ')); + row1.append($('
    ' + (task.percent >> 0 ? task.percent + ' %' : "") + '
    ')); + var row2 = $('
    ').appendTo(el); + el.attr('data-running', 'true').data('running', true); + if (_.isFunction(opts.onTaskStarted)) { + opts.onTaskStarted(task, el); + } + el.removeClass('hide'); + } + } + }); + + // remove runningElements for finished tasks (the ones currently running but are not in 'runningElements' + var currentlyRunningElements = opts.context.find(opts.elementsSelector + '[data-running=true]'); + $.each(currentlyRunningElements, function (i, el) { + var shouldRun = _.find(runningElements, function (val) { return val == el; }); + if (!shouldRun) { + // restore element to it's init state + var jel = $(el); + jel.addClass('hide').html('').attr('data-running', 'false').data('running', false); + if (_.isFunction(opts.onTaskCompleted)) { + opts.onTaskCompleted(jel.data('task-id'), jel); + } + } + }); + } + }); + } + window.setTimeout(poll, 500); + interval = window.setInterval(poll, 1000); + } + } + })() }; diff --git a/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml index e79ee6d5a7..b6ec8f00be 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml @@ -37,14 +37,15 @@ .Width(100); columns.Bound(x => x.Id) .ClientTemplate( - "<# if (LastStartUtc.length) {#>
    " + @T("Admin.System.ScheduleTasks.LastStart") + ": <#= LastStartUtc #>
    <# } #>" + - "<# if (NextRunUtc) {#>
    " + @T("Admin.System.ScheduleTasks.NextRun") + ": <#= NextRunUtc #>
    <# } #>" + + "<# if (LastStartUtc.length) {#>
    " + @T("Admin.System.ScheduleTasks.LastStart") + ": <#= LastStartUtc #>
    <# } #>" + + "<# if (NextRunUtc) {#>
    " + @T("Admin.System.ScheduleTasks.NextRun") + ": <#= NextRunUtc #>
    <# } #>" + "<# if (!LastEndUtc && !IsRunning) {#>
    " + @T("Admin.System.ScheduleTasks.LastStart") + ": " + @T("Common.Never") + "
    <# } #>" + - "<# if (Duration.length) {#>
    " + @T("Common.Duration") + ": <#= Duration #>
    <# } #>" + + "<# if (Duration.length) {#>
    " + @T("Common.Duration") + ": <#= Duration #>
    <# } #>" + "<# if (LastError.length) {#>
    " + @T("Common.Error") + ": <#= LastError #>
    <# } #>" + - "<# if (LastSuccessUtc != LastEndUtc) {#>
    " + @T("Admin.System.ScheduleTasks.LastSuccess") + ": <#= LastSuccessUtc #>
    <# } #>" + - "<# if (!IsRunning) {#> " + @T("Admin.System.ScheduleTasks.RunNow") + "<# } #>" + - "<# if (IsRunning) {#>
     <#= ProgressInfo #>" + @T("Common.Cancel") + "
    <# } #>") + "<# if (LastSuccessUtc != LastEndUtc) {#>
    " + @T("Admin.System.ScheduleTasks.LastSuccess") + ": <#= LastSuccessUtc #>
    <# } #>" + + "' data-task-id='<#= Id #>' style='margin-top: 12px'> " + @T("Admin.System.ScheduleTasks.RunNow") + "" + + "' data-task-id='<#= Id #>' style='margin-top: 12px'>" + @T("Common.Cancel") + "" + + "
    ") .Title(T("Common.Execution").Text) .ReadOnly(); columns.Command(commands => @@ -75,12 +76,30 @@ From 113591587ecd33c9b76c342cd39b4b22262685e8 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Sat, 25 Jul 2015 02:35:37 +0200 Subject: [PATCH 0300/1256] Minor fix --- .../SmartStore.Web/Administration/Scripts/admin.common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js index 4958bcdf53..1387de0d25 100644 --- a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js +++ b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js @@ -112,7 +112,7 @@ var Admin = { }); } window.setTimeout(poll, 500); - interval = window.setInterval(poll, 1000); + interval = window.setInterval(poll, 5000); } } })() From 993b31ddbdab4341f8d8b7cd11c19e7132013399 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Sat, 25 Jul 2015 03:11:20 +0200 Subject: [PATCH 0301/1256] Fixed migration errors --- ...507072138058_MessageTemplateAttachments.cs | 6 +- .../201507092146153_DownloadGuidIndex.cs | 2 +- .../201507102159496_TransientMedia.cs | 12 +- .../Migrations/201507202149123_Merge2.resx | 126 ------------------ ....cs => 201507250039446_Merge2.Designer.cs} | 2 +- ...23_Merge2.cs => 201507250039446_Merge2.cs} | 0 .../Migrations/201507250039446_Merge2.resx | 126 ++++++++++++++++++ .../Migrations/MigrationsConfiguration.cs | 1 + .../SmartStore.Data/SmartStore.Data.csproj | 14 +- 9 files changed, 145 insertions(+), 144 deletions(-) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.resx rename src/Libraries/SmartStore.Data/Migrations/{201507202149123_Merge2.Designer.cs => 201507250039446_Merge2.Designer.cs} (93%) rename src/Libraries/SmartStore.Data/Migrations/{201507202149123_Merge2.cs => 201507250039446_Merge2.cs} (100%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507250039446_Merge2.resx diff --git a/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs b/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs index 448a071417..d83d2520df 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507072138058_MessageTemplateAttachments.cs @@ -15,9 +15,9 @@ public override void Up() public override void Down() { - DropColumn("dbo.MessageTemplate", "Attachment3FileId"); - DropColumn("dbo.MessageTemplate", "Attachment2FileId"); - DropColumn("dbo.MessageTemplate", "Attachment1FileId"); + DropColumn("dbo.MessageTemplate", "Attachment3FileId"); + DropColumn("dbo.MessageTemplate", "Attachment2FileId"); + DropColumn("dbo.MessageTemplate", "Attachment1FileId"); } public bool RollbackOnFailure diff --git a/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.cs b/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.cs index ff65fd3814..803e4557f6 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507092146153_DownloadGuidIndex.cs @@ -12,7 +12,7 @@ public override void Up() public override void Down() { - DropIndex("dbo.Download", new[] { "DownloadGuid" }); + DropIndex("dbo.Download", new[] { "DownloadGuid" }); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.cs b/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.cs index 509169153e..52ac730bf1 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507102159496_TransientMedia.cs @@ -19,12 +19,12 @@ public override void Up() public override void Down() { - DropIndex("dbo.Picture", "IX_UpdatedOn_IsTransient"); - DropIndex("dbo.Download", "IX_UpdatedOn_IsTransient"); - DropColumn("dbo.Picture", "UpdatedOnUtc"); - DropColumn("dbo.Picture", "IsTransient"); - DropColumn("dbo.Download", "UpdatedOnUtc"); - DropColumn("dbo.Download", "IsTransient"); + DropIndex("dbo.Picture", "IX_UpdatedOn_IsTransient"); + DropIndex("dbo.Download", "IX_UpdatedOn_IsTransient"); + DropColumn("dbo.Picture", "UpdatedOnUtc"); + DropColumn("dbo.Picture", "IsTransient"); + DropColumn("dbo.Download", "UpdatedOnUtc"); + DropColumn("dbo.Download", "IsTransient"); } public bool RollbackOnFailure diff --git a/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.resx b/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.resx deleted file mode 100644 index 19402f07d2..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201507250039446_Merge2.Designer.cs similarity index 93% rename from src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201507250039446_Merge2.Designer.cs index 7bb45d2585..8830d1f8ac 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507250039446_Merge2.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class Merge2 : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201507202149123_Merge2"; } + get { return "201507250039446_Merge2"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.cs b/src/Libraries/SmartStore.Data/Migrations/201507250039446_Merge2.cs similarity index 100% rename from src/Libraries/SmartStore.Data/Migrations/201507202149123_Merge2.cs rename to src/Libraries/SmartStore.Data/Migrations/201507250039446_Merge2.cs diff --git a/src/Libraries/SmartStore.Data/Migrations/201507250039446_Merge2.resx b/src/Libraries/SmartStore.Data/Migrations/201507250039446_Merge2.resx new file mode 100644 index 0000000000..483dbdf042 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201507250039446_Merge2.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs index ea5109256d..49ae7dd7a8 100644 --- a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs +++ b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs @@ -10,6 +10,7 @@ public sealed class MigrationsConfiguration : DbMigrationsConfiguration 201507200832223_SortFilterHomepageProducts.cs - - - 201507202149123_Merge2.cs - 201507210952098_PaymentMethodDescription.cs @@ -331,6 +327,10 @@ 201507242008201_WebScheduler.cs + + + 201507250039446_Merge2.cs + @@ -618,15 +618,15 @@ 201507200832223_SortFilterHomepageProducts.cs - - 201507202149123_Merge2.cs - 201507210952098_PaymentMethodDescription.cs 201507242008201_WebScheduler.cs + + 201507250039446_Merge2.cs + From fe8e8ff7441fc58f4101dacf40b4e1e8c86aed85 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 25 Jul 2015 12:16:49 +0200 Subject: [PATCH 0302/1256] Reduce database round trips initiated by AreProductAttributesEqual --- ...01507210952098_PaymentMethodDescription.cs | 4 +- .../Catalog/IProductAttributeParser.cs | 27 ++-- .../Catalog/IProductAttributeService.cs | 21 +-- .../Catalog/PriceCalculationService.cs | 2 +- .../Catalog/ProductAttributeParser.cs | 147 +++++++----------- .../Catalog/ProductAttributeService.cs | 53 +++---- .../Orders/ShoppingCartService.cs | 2 +- .../Controllers/ProductController.cs | 4 +- .../Controllers/CatalogHelper.cs | 4 +- 9 files changed, 114 insertions(+), 150 deletions(-) diff --git a/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs b/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs index 75e57c5d4b..b71dd98ac0 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201507210952098_PaymentMethodDescription.cs @@ -51,8 +51,8 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Minimal realisierbarer Preis"); builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Catalog.PriceDisplayType.PreSelectedPrice", - "Preselected price", - "Vorgewhlter Preis"); + "Price preselected on detail page", + "Auf der Detailseite vorgewhlter Preis"); builder.AddOrUpdate("Enums.SmartStore.Core.Domain.Catalog.PriceDisplayType.PriceWithoutDiscountsAndAttributes", "Price without discounts and attributes", diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs index 21fd8bcdc7..69a506fc8c 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs @@ -25,13 +25,6 @@ public partial interface IProductAttributeParser /// Selected product variant attributes IList ParseProductVariantAttributes(string attributes); - /// - /// Gets selected product variant attributes - /// - /// The attribute ids - /// Selected product variant attributes - IEnumerable ParseProductVariantAttributes(ICollection ids); - /// /// Get product variant attribute values /// @@ -59,19 +52,29 @@ public partial interface IProductAttributeParser /// /// Are attributes equal /// - /// The attributes of the first product - /// The attributes of the second product + /// The attributes of the first product + /// The attributes of the second product + /// Collection of already loaded product attribute mappings to reduce database rountrips /// Result - bool AreProductAttributesEqual(string attributes1, string attributes2); + bool AreProductAttributesEqual(string attributeXml1, string attributeXml2, IEnumerable attributes = null); /// /// Finds a product variant attribute combination by attributes stored in XML /// /// Product /// Attributes in XML format + /// Collection of already loaded product attribute mappings to reduce database rountrips /// Found product variant attribute combination - ProductVariantAttributeCombination FindProductVariantAttributeCombination(Product product, string attributesXml); - ProductVariantAttributeCombination FindProductVariantAttributeCombination(int productId, string attributesXml); + ProductVariantAttributeCombination FindProductVariantAttributeCombination(Product product, string attributesXml, IEnumerable attributes = null); + + /// + /// Finds a product variant attribute combination by attributes stored in XML + /// + /// Product identifier + /// Attributes in XML format + /// Collection of already loaded product attribute mappings to reduce database rountrips + /// Found product variant attribute combination + ProductVariantAttributeCombination FindProductVariantAttributeCombination(int productId, string attributesXml, IEnumerable attributes = null); /// /// Deserializes attribute data from an URL query string diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs index 732eacbb59..ce0394d014 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs @@ -74,12 +74,14 @@ public partial interface IProductAttributeService /// Product variant attribute mapping ProductVariantAttribute GetProductVariantAttributeById(int productVariantAttributeId); - /// - /// Gets multiple product variant attribute mappings by their keys - /// - /// a list of keys - /// Product variant attribute mappings - IEnumerable GetProductVariantAttributesByIds(params int[] ids); + + /// + /// Gets a product variant attribute mappings + /// + /// Enumerable of product variant attribute mapping identifiers + /// Collection of already loaded product attribute mappings to reduce database rountrips + /// List of product variant attribute mapping + IList GetProductVariantAttributesByIds(IEnumerable productVariantAttributeIds, IEnumerable attributes = null); /// /// Inserts a product variant attribute mapping @@ -136,13 +138,6 @@ public partial interface IProductAttributeService /// The product variant attribute value void UpdateProductVariantAttributeValue(ProductVariantAttributeValue productVariantAttributeValue); - /// - /// Gets a list of product identifiers which have price adjustments - /// - /// Array of product identifiers - /// List of product identifiers - IList GetProductIdsWithPriceAdjustments(int[] productIds); - #endregion #region Product variant attribute combinations (ProductVariantAttributeCombination) diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index 0c965dceb1..acf2e3c933 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -214,7 +214,7 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC var combinations = context.AttributeCombinations.Ensure(product.Id); - var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml)); + var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml, attributes)); if (selectedCombination != null && selectedCombination.IsActive && selectedCombination.Price.HasValue) { diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs index 1546a5e9d7..aa190121c6 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs @@ -1,12 +1,12 @@ using System; -using System.Linq; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; +using System.Web; using System.Xml; -using SmartStore.Core.Domain.Catalog; -using SmartStore.Collections; using Newtonsoft.Json; -using System.Web; +using SmartStore.Collections; +using SmartStore.Core.Domain.Catalog; namespace SmartStore.Services.Catalog { @@ -104,33 +104,9 @@ public virtual Multimap DeserializeProductVariantAttributes(string /// Selected product variant attributes public virtual IList ParseProductVariantAttributes(string attributes) { - var pvaCollection = new List(); - - // codehint: sm-edit var ids = ParseProductVariantAttributeIds(attributes); - return this.ParseProductVariantAttributes(ids.ToList()).ToList(); - } - - public virtual IEnumerable ParseProductVariantAttributes(ICollection ids) - { - if (ids != null) - { - if (ids.Count == 1) - { - var pva = _productAttributeService.GetProductVariantAttributeById(ids.ElementAt(0)); - if (pva != null) - { - return new ProductVariantAttribute[] { pva }; - } - } - else - { - return _productAttributeService.GetProductVariantAttributesByIds(ids.ToArray()).ToList(); - } - } - - return Enumerable.Empty(); + return _productAttributeService.GetProductVariantAttributesByIds(ids); } /// @@ -143,17 +119,20 @@ public virtual IEnumerable ParseProductVariantAttr var pvaValues = Enumerable.Empty(); var attrs = DeserializeProductVariantAttributes(attributes); - var pvaCollection = ParseProductVariantAttributes(attrs.Keys); + var pvaCollection = _productAttributeService.GetProductVariantAttributesByIds(attrs.Keys); foreach (var pva in pvaCollection) { if (!pva.ShouldHaveValues()) continue; - var pvaValuesStr = attrs[pva.Id]; //ParseValues(attributes, pva.Id); - var ids = from id in pvaValuesStr - where id.HasValue() - select id.ToInt(); + var pvaValuesStr = attrs[pva.Id]; + + var ids = + from id in pvaValuesStr + where id.HasValue() + select id.ToInt(); + var values = _productAttributeService.GetProductVariantAttributeValuesByIds(ids.ToArray()); pvaValues = pvaValues.Concat(values); @@ -218,82 +197,72 @@ public virtual string AddProductAttribute(string attributes, ProductVariantAttri return pva.AddProductAttribute(attributes, value); } - /// - /// Are attributes equal - /// - /// The attributes of the first product - /// The attributes of the second product - /// Result - public virtual bool AreProductAttributesEqual(string attributes1, string attributes2) + public virtual bool AreProductAttributesEqual(string attributeXml1, string attributeXml2, IEnumerable attributes = null) { - var attrs1 = DeserializeProductVariantAttributes(attributes1); - var attrs2 = DeserializeProductVariantAttributes(attributes2); + if (attributeXml1.IsCaseInsensitiveEqual(attributeXml2)) + return true; - if (attrs1.Count == attrs2.Count) - { - var pva1Collection = ParseProductVariantAttributes(attrs2.Keys); - var pva2Collection = ParseProductVariantAttributes(attrs1.Keys); - foreach (var pva1 in pva1Collection) - { - foreach (var pva2 in pva2Collection) - { - if (pva1.Id == pva2.Id) - { - var pvaValues1Str = attrs2[pva1.Id]; // ParseValues(attributes2, pva1.Id); - var pvaValues2Str = attrs1[pva2.Id]; // ParseValues(attributes1, pva2.Id); - if (pvaValues1Str.Count == pvaValues2Str.Count) - { - foreach (string str1 in pvaValues1Str) - { - bool hasAttribute = pvaValues2Str.Any(x => x.IsCaseInsensitiveEqual(str1)); - if (!hasAttribute) - { - return false; - } - } - } - else - { - return false; - } - } - } - } - } - else - { - return false; - } + var attributes1 = DeserializeProductVariantAttributes(attributeXml1); + var attributes2 = DeserializeProductVariantAttributes(attributeXml2); + + if (attributes1.Count != attributes2.Count) + return false; + + IEnumerable pvaCollection1 = null; + IEnumerable pvaCollection2 = null; + + pvaCollection1 = _productAttributeService.GetProductVariantAttributesByIds(attributes2.Keys, attributes); + + if (attributes2.Keys.SequenceEqual(attributes1.Keys)) // often the case + pvaCollection2 = pvaCollection1; + else + pvaCollection2 = _productAttributeService.GetProductVariantAttributesByIds(attributes1.Keys, attributes); + + foreach (var pva1 in pvaCollection1) + { + foreach (var pva2 in pvaCollection2) + { + if (pva1.Id == pva2.Id) + { + var pvaValues1 = attributes2[pva1.Id]; + var pvaValues2 = attributes1[pva2.Id]; + + if (pvaValues1.Count != pvaValues2.Count) + return false; + + foreach (string value1 in pvaValues1) + { + string str1 = value1.TrimSafe(); + + if (!pvaValues2.Any(x => x.TrimSafe().IsCaseInsensitiveEqual(str1))) + return false; + } + } + } + } return true; } - /// - /// Finds a product variant attribute combination by attributes stored in XML - /// - /// Product - /// Attributes in XML format - /// Found product variant attribute combination - public virtual ProductVariantAttributeCombination FindProductVariantAttributeCombination(Product product, string attributesXml) + public virtual ProductVariantAttributeCombination FindProductVariantAttributeCombination(Product product, string attributesXml, IEnumerable attributes = null) { if (product == null) throw new ArgumentNullException("product"); - return FindProductVariantAttributeCombination(product.Id, attributesXml); + return FindProductVariantAttributeCombination(product.Id, attributesXml, attributes); } - public virtual ProductVariantAttributeCombination FindProductVariantAttributeCombination(int productId, string attributesXml) + public virtual ProductVariantAttributeCombination FindProductVariantAttributeCombination(int productId, string attributesXml, IEnumerable attributes = null) { if (attributesXml.HasValue()) { - //existing combinations var combinations = _productAttributeService.GetAllProductVariantAttributeCombinations(productId); if (combinations.Count == 0) return null; foreach (var combination in combinations) { - bool attributesEqual = AreProductAttributesEqual(combination.AttributesXml, attributesXml); + bool attributesEqual = AreProductAttributesEqual(combination.AttributesXml, attributesXml, attributes); if (attributesEqual) return combination; } diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs index 95cad54978..9d05fa4d4e 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs @@ -210,20 +210,36 @@ public virtual ProductVariantAttribute GetProductVariantAttributeById(int produc return null; string key = string.Format(PRODUCTVARIANTATTRIBUTES_BY_ID_KEY, productVariantAttributeId); - return _cacheManager.Get(key, () => { + + return _cacheManager.Get(key, () => + { return _productVariantAttributeRepository.GetById(productVariantAttributeId); }); } - public virtual IEnumerable GetProductVariantAttributesByIds(params int[] ids) - { - if (ids == null || ids.Length == 0) - { - return Enumerable.Empty(); - } + public virtual IList GetProductVariantAttributesByIds(IEnumerable productVariantAttributeIds, IEnumerable attributes = null) + { + var result = new List(); - return _productVariantAttributeRepository.GetMany(ids); - } + if (productVariantAttributeIds != null) + { + foreach (var id in productVariantAttributeIds) + { + ProductVariantAttribute pva = null; + + if (attributes != null) + pva = attributes.FirstOrDefault(x => x.Id == id); + + if (pva == null) + pva = GetProductVariantAttributeById(id); + + if (pva != null) + result.Add(pva); + } + } + + return result; + } public virtual IEnumerable GetProductVariantAttributeValuesByIds(params int[] productVariantAttributeValueIds) { @@ -340,25 +356,6 @@ public virtual void UpdateProductVariantAttributeValue(ProductVariantAttributeVa _eventPublisher.EntityUpdated(productVariantAttributeValue); } - public virtual IList GetProductIdsWithPriceAdjustments(int[] productIds) - { - var queryMappings = - from m in _productVariantAttributeRepository.TableUntracked - where productIds.Contains(m.ProductId) - select new { m.Id, m.ProductId }; - - var query = - from v in _productVariantAttributeValueRepository.TableUntracked - join m in queryMappings on v.ProductVariantAttributeId equals m.Id - where v.PriceAdjustment != 0 - group v by m.ProductId into grp - select grp.Key; - - var result = query.ToList(); - - return result; - } - #endregion #region Product variant attribute combinations (ProductVariantAttributeCombination) diff --git a/src/Libraries/SmartStore.Services/Orders/ShoppingCartService.cs b/src/Libraries/SmartStore.Services/Orders/ShoppingCartService.cs index 5882bda05e..847cce099d 100644 --- a/src/Libraries/SmartStore.Services/Orders/ShoppingCartService.cs +++ b/src/Libraries/SmartStore.Services/Orders/ShoppingCartService.cs @@ -548,7 +548,7 @@ public virtual IList GetShoppingCartItemAttributeWarnings(Customer custo { var combination = product .ProductVariantAttributeCombinations - .FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, selectedAttributes)); + .FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, selectedAttributes, pva1Collection)); if (combination != null && !combination.IsActive) { diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index 2a973ca37d..49c2a5a928 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -4280,7 +4280,7 @@ public ActionResult AttributeCombinationCreatePopup(string btnId, string formId, warnings.AddRange(_shoppingCartService.GetShoppingCartItemAttributeWarnings(_workContext.CurrentCustomer, ShoppingCartType.ShoppingCart, product, attributeXml)); - if (null != _productAttributeParser.FindProductVariantAttributeCombination(product, attributeXml)) + if (null != _productAttributeParser.FindProductVariantAttributeCombination(product, attributeXml, variantAttributes)) { warnings.Add(_localizationService.GetResource("Admin.Catalog.Products.ProductVariantAttributes.AttributeCombinations.CombiExists")); } @@ -4411,7 +4411,7 @@ public ActionResult CombinationExistenceNote(int productId, FormCollection form) string attributeXml = form.CreateSelectedAttributesXml(productId, attributes, _productAttributeParser, _localizationService, _downloadService, _catalogSettings, this.Request, warnings, false); - bool exists = (null != _productAttributeParser.FindProductVariantAttributeCombination(productId, attributeXml)); + bool exists = (null != _productAttributeParser.FindProductVariantAttributeCombination(productId, attributeXml, attributes)); if (!exists) { diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index 16e7022c43..4fe5dcaa57 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -591,7 +591,7 @@ public ProductDetailsModel PrepareProductDetailModel( } model.CombinationSelected = model.Combinations - .FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml)); + .FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml, variantAttributes)); if (model.CombinationSelected != null && model.CombinationSelected.IsActive == false) { @@ -1050,7 +1050,7 @@ public IEnumerable PrepareProductOverviewModels( { StoreId = currentStore.Id, ParentGroupedProductId = product.Id, - PageSize = int.MaxValue, + PageSize = (_catalogSettings.PriceDisplayType == PriceDisplayType.LowestPrice ? int.MaxValue : 1), VisibleIndividuallyOnly = false }; From 8a855d00265ca64dfe1ff8fce089ba1f0ee20be9 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 25 Jul 2015 19:06:16 +0200 Subject: [PATCH 0303/1256] Changed some things of last commit Preselected price was wrong for product attributes with multiple preselected values (same on product detail page) --- .../Catalog/IProductAttributeParser.cs | 50 ++++--- .../Catalog/IProductAttributeService.cs | 7 +- .../Catalog/PriceCalculationService.cs | 34 +++-- .../Catalog/ProductAttributeParser.cs | 90 ++++++------- .../Catalog/ProductAttributeService.cs | 61 ++++++--- .../Controllers/ProductController.cs | 4 +- .../Controllers/CatalogHelper.cs | 125 +++++++++--------- 7 files changed, 209 insertions(+), 162 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs index 69a506fc8c..4ac7e9b945 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs @@ -14,47 +14,47 @@ public partial interface IProductAttributeParser /// /// Gets selected product variant attributes as a map of integer ids with their corresponding values. /// - /// Attributes XML + /// XML formatted attributes /// The deserialized map - Multimap DeserializeProductVariantAttributes(string attributes); + Multimap DeserializeProductVariantAttributes(string attributesXml); - /// - /// Gets selected product variant attributes - /// - /// Attributes - /// Selected product variant attributes - IList ParseProductVariantAttributes(string attributes); + /// + /// Gets selected product variant attributes + /// + /// XML formatted attributes + /// Selected product variant attributes + IList ParseProductVariantAttributes(string attributesXml); /// /// Get product variant attribute values /// - /// Attributes + /// XML formatted attributes /// Product variant attribute values - IEnumerable ParseProductVariantAttributeValues(string attributes); + IEnumerable ParseProductVariantAttributeValues(string attributesXml); /// /// Gets selected product variant attribute value /// - /// Attributes + /// XML formatted attributes /// Product variant attribute identifier /// Product variant attribute value - IList ParseValues(string attributes, int productVariantAttributeId); + IList ParseValues(string attributesXml, int productVariantAttributeId); /// /// Adds an attribute /// - /// Attributes + /// XML formatted attributes /// Product variant attribute /// Value /// Attributes - string AddProductAttribute(string attributes, ProductVariantAttribute pva, string value); + string AddProductAttribute(string attributesXml, ProductVariantAttribute pva, string value); /// /// Are attributes equal /// /// The attributes of the first product /// The attributes of the second product - /// Collection of already loaded product attribute mappings to reduce database rountrips + /// Collection of already loaded product attribute mappings to reduce database round trips /// Result bool AreProductAttributesEqual(string attributeXml1, string attributeXml2, IEnumerable attributes = null); @@ -62,19 +62,17 @@ public partial interface IProductAttributeParser /// Finds a product variant attribute combination by attributes stored in XML /// /// Product - /// Attributes in XML format - /// Collection of already loaded product attribute mappings to reduce database rountrips + /// XML formatted attributes /// Found product variant attribute combination - ProductVariantAttributeCombination FindProductVariantAttributeCombination(Product product, string attributesXml, IEnumerable attributes = null); + ProductVariantAttributeCombination FindProductVariantAttributeCombination(Product product, string attributesXml); /// /// Finds a product variant attribute combination by attributes stored in XML /// /// Product identifier - /// Attributes in XML format - /// Collection of already loaded product attribute mappings to reduce database rountrips + /// XML formatted attributes /// Found product variant attribute combination - ProductVariantAttributeCombination FindProductVariantAttributeCombination(int productId, string attributesXml, IEnumerable attributes = null); + ProductVariantAttributeCombination FindProductVariantAttributeCombination(int productId, string attributesXml); /// /// Deserializes attribute data from an URL query string @@ -87,7 +85,7 @@ public partial interface IProductAttributeParser /// Serializes attribute data /// /// Product identifier - /// Attribute XML string + /// XML formatted attributes /// Whether to URL encode /// Json string with attribute data string SerializeQueryData(int productId, string attributesXml, bool urlEncode = true); @@ -99,26 +97,26 @@ public partial interface IProductAttributeParser /// /// Add gift card attrbibutes /// - /// Attributes + /// XML formatted attributes /// Recipient name /// Recipient email /// Sender name /// Sender email /// Message /// Attributes - string AddGiftCardAttribute(string attributes, string recipientName, + string AddGiftCardAttribute(string attributesXml, string recipientName, string recipientEmail, string senderName, string senderEmail, string giftCardMessage); /// /// Get gift card attrbibutes /// - /// Attributes + /// XML formatted attributes /// Recipient name /// Recipient email /// Sender name /// Sender email /// Message - void GetGiftCardAttribute(string attributes, out string recipientName, + void GetGiftCardAttribute(string attributesXml, out string recipientName, out string recipientEmail, out string senderName, out string senderEmail, out string giftCardMessage); diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs index ce0394d014..36874a566a 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeService.cs @@ -74,13 +74,12 @@ public partial interface IProductAttributeService /// Product variant attribute mapping ProductVariantAttribute GetProductVariantAttributeById(int productVariantAttributeId); - /// - /// Gets a product variant attribute mappings + /// Gets product variant attribute mappings /// /// Enumerable of product variant attribute mapping identifiers - /// Collection of already loaded product attribute mappings to reduce database rountrips - /// List of product variant attribute mapping + /// Collection of already loaded product attribute mappings to reduce database round trips + /// IList GetProductVariantAttributesByIds(IEnumerable productVariantAttributeIds, IEnumerable attributes = null); /// diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index acf2e3c933..a343b360be 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -164,7 +164,7 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC var bundleItemId = (bundleItem == null ? 0 : bundleItem.Item.Id); var selectedAttributes = new NameValueCollection(); - List selectedAttributeValues = null; + var selectedAttributeValues = new List(); var attributes = context.Attributes.Ensure(product.Id); // 1. fill selectedAttributes with initially selected attributes @@ -172,6 +172,7 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC { int preSelectedValueId = 0; ProductVariantAttributeValue defaultValue = null; + var selectedValueIds = new List(); var pvaValues = attribute.ProductVariantAttributeValues; foreach (var pvaValue in pvaValues) @@ -193,15 +194,30 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC } } - // value pre-selected by a bundle item filter discards the default pre-selection - if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) - defaultValue.IsPreSelected = true; + //if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) + // defaultValue.IsPreSelected = true; - if (defaultValue == null) - defaultValue = pvaValues.FirstOrDefault(x => x.IsPreSelected); + //if (defaultValue == null) + // defaultValue = pvaValues.FirstOrDefault(x => x.IsPreSelected); - if (defaultValue != null) + //if (defaultValue != null) + // selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); + + // value pre-selected by a bundle item filter discards the default pre-selection + if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) + { + //defaultValue.IsPreSelected = true; + selectedAttributeValues.Add(defaultValue); selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); + } + else + { + foreach (var value in pvaValues.Where(x => x.IsPreSelected)) + { + selectedAttributeValues.Add(value); + selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, value.Id, product.Id, bundleItemId); + } + } } // 2. find attribute combination for selected attributes and merge it @@ -210,8 +226,6 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _services.Localization, _downloadService, _catalogSettings, _httpRequestBase, new List(), true, bundleItemId); - selectedAttributeValues = _productAttributeParser.ParseProductVariantAttributeValues(attributeXml).ToList(); - var combinations = context.AttributeCombinations.Ensure(product.Id); var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml, attributes)); @@ -224,7 +238,7 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC if (_catalogSettings.EnableDynamicPriceUpdate && !isBundlePricing) { - if (selectedAttributeValues != null) + if (selectedAttributeValues.Count > 0) { selectedAttributeValues.Each(x => attributesTotalPriceBase += GetProductVariantAttributeValuePriceAdjustment(x)); } diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs index aa190121c6..3d454b3822 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs @@ -22,23 +22,23 @@ public ProductAttributeParser(IProductAttributeService productAttributeService) this._productAttributeService = productAttributeService; } - #region Product attributes + #region Product attributes - /// + /// /// Gets selected product variant attribute identifiers /// - /// Attributes + /// Attributes /// Selected product variant attribute identifiers - private IEnumerable ParseProductVariantAttributeIds(string attributes) + private IEnumerable ParseProductVariantAttributeIds(string attributesXml) { var ids = new List(); - if (String.IsNullOrEmpty(attributes)) + if (String.IsNullOrEmpty(attributesXml)) yield break; try { var xmlDoc = new XmlDocument(); - xmlDoc.LoadXml(attributes); + xmlDoc.LoadXml(attributesXml); var nodeList = xmlDoc.SelectNodes(@"//Attributes/ProductVariantAttribute"); foreach (var node in nodeList.Cast()) @@ -55,19 +55,18 @@ private IEnumerable ParseProductVariantAttributeIds(string attributes) } } finally { } - } - public virtual Multimap DeserializeProductVariantAttributes(string attributes) + public virtual Multimap DeserializeProductVariantAttributes(string attributesXml) { var attrs = new Multimap(); - if (String.IsNullOrEmpty(attributes)) + if (String.IsNullOrEmpty(attributesXml)) return attrs; try { var xmlDoc = new XmlDocument(); - xmlDoc.LoadXml(attributes); + xmlDoc.LoadXml(attributesXml); var nodeList1 = xmlDoc.SelectNodes(@"//Attributes/ProductVariantAttribute"); foreach (var node1 in nodeList1.Cast()) @@ -100,26 +99,22 @@ public virtual Multimap DeserializeProductVariantAttributes(string /// /// Gets selected product variant attributes /// - /// Attributes + /// Attributes /// Selected product variant attributes - public virtual IList ParseProductVariantAttributes(string attributes) - { - var ids = ParseProductVariantAttributeIds(attributes); + public virtual IList ParseProductVariantAttributes(string attributesXml) + { + var ids = ParseProductVariantAttributeIds(attributesXml); - return _productAttributeService.GetProductVariantAttributesByIds(ids); - } + return _productAttributeService.GetProductVariantAttributesByIds(ids.ToList()); + } - /// - /// Get product variant attribute values - /// - /// Attributes - /// Product variant attribute values - public virtual IEnumerable ParseProductVariantAttributeValues(string attributes) + public virtual IEnumerable ParseProductVariantAttributeValues(string attributeXml) { - var pvaValues = Enumerable.Empty(); + //var pvaValues = Enumerable.Empty(); - var attrs = DeserializeProductVariantAttributes(attributes); - var pvaCollection = _productAttributeService.GetProductVariantAttributesByIds(attrs.Keys); + var allIds = new List(); + var attrs = DeserializeProductVariantAttributes(attributeXml); + var pvaCollection = _productAttributeService.GetProductVariantAttributesByIds(attrs.Keys); foreach (var pva in pvaCollection) { @@ -133,27 +128,32 @@ from id in pvaValuesStr where id.HasValue() select id.ToInt(); - var values = _productAttributeService.GetProductVariantAttributeValuesByIds(ids.ToArray()); + allIds.AddRange(ids); - pvaValues = pvaValues.Concat(values); + //var values = _productAttributeService.GetProductVariantAttributeValuesByIds(ids.ToArray()); + //pvaValues = pvaValues.Concat(values); } - return pvaValues; + int[] allDistinctIds = allIds.Distinct().ToArray(); + + var values = _productAttributeService.GetProductVariantAttributeValuesByIds(allDistinctIds); + + return values; } /// /// Gets selected product variant attribute value /// - /// Attributes + /// Attributes /// Product variant attribute identifier /// Product variant attribute value - public virtual IList ParseValues(string attributes, int productVariantAttributeId) + public virtual IList ParseValues(string attributesXml, int productVariantAttributeId) { var selectedProductVariantAttributeValues = new List(); try { var xmlDoc = new XmlDocument(); - xmlDoc.LoadXml(attributes); + xmlDoc.LoadXml(attributesXml); var nodeList1 = xmlDoc.SelectNodes(@"//Attributes/ProductVariantAttribute"); foreach (XmlNode node1 in nodeList1) @@ -188,13 +188,13 @@ public virtual IList ParseValues(string attributes, int productVariantAt /// /// Adds an attribute /// - /// Attributes + /// Attributes /// Product variant attribute /// Value /// Attributes - public virtual string AddProductAttribute(string attributes, ProductVariantAttribute pva, string value) + public virtual string AddProductAttribute(string attributesXml, ProductVariantAttribute pva, string value) { - return pva.AddProductAttribute(attributes, value); + return pva.AddProductAttribute(attributesXml, value); } public virtual bool AreProductAttributesEqual(string attributeXml1, string attributeXml2, IEnumerable attributes = null) @@ -244,15 +244,15 @@ public virtual bool AreProductAttributesEqual(string attributeXml1, string attri return true; } - public virtual ProductVariantAttributeCombination FindProductVariantAttributeCombination(Product product, string attributesXml, IEnumerable attributes = null) + public virtual ProductVariantAttributeCombination FindProductVariantAttributeCombination(Product product, string attributesXml) { if (product == null) throw new ArgumentNullException("product"); - return FindProductVariantAttributeCombination(product.Id, attributesXml, attributes); + return FindProductVariantAttributeCombination(product.Id, attributesXml); } - public virtual ProductVariantAttributeCombination FindProductVariantAttributeCombination(int productId, string attributesXml, IEnumerable attributes = null) + public virtual ProductVariantAttributeCombination FindProductVariantAttributeCombination(int productId, string attributesXml) { if (attributesXml.HasValue()) { @@ -262,7 +262,7 @@ public virtual ProductVariantAttributeCombination FindProductVariantAttributeCom foreach (var combination in combinations) { - bool attributesEqual = AreProductAttributesEqual(combination.AttributesXml, attributesXml, attributes); + bool attributesEqual = AreProductAttributesEqual(combination.AttributesXml, attributesXml); if (attributesEqual) return combination; } @@ -328,14 +328,14 @@ public virtual string SerializeQueryData(int productId, string attributesXml, bo /// /// Add gift card attrbibutes /// - /// Attributes + /// Attributes /// Recipient name /// Recipient email /// Sender name /// Sender email /// Message /// Attributes - public string AddGiftCardAttribute(string attributes, string recipientName, + public string AddGiftCardAttribute(string attributesXml, string recipientName, string recipientEmail, string senderName, string senderEmail, string giftCardMessage) { string result = string.Empty; @@ -347,14 +347,14 @@ public string AddGiftCardAttribute(string attributes, string recipientName, senderEmail = senderEmail.Trim(); var xmlDoc = new XmlDocument(); - if (String.IsNullOrEmpty(attributes)) + if (String.IsNullOrEmpty(attributesXml)) { var element1 = xmlDoc.CreateElement("Attributes"); xmlDoc.AppendChild(element1); } else { - xmlDoc.LoadXml(attributes); + xmlDoc.LoadXml(attributesXml); } var rootElement = (XmlElement)xmlDoc.SelectSingleNode(@"//Attributes"); @@ -398,13 +398,13 @@ public string AddGiftCardAttribute(string attributes, string recipientName, /// /// Get gift card attrbibutes /// - /// Attributes + /// Attributes /// Recipient name /// Recipient email /// Sender name /// Sender email /// Message - public void GetGiftCardAttribute(string attributes, out string recipientName, + public void GetGiftCardAttribute(string attributesXml, out string recipientName, out string recipientEmail, out string senderName, out string senderEmail, out string giftCardMessage) { @@ -417,7 +417,7 @@ public void GetGiftCardAttribute(string attributes, out string recipientName, try { var xmlDoc = new XmlDocument(); - xmlDoc.LoadXml(attributes); + xmlDoc.LoadXml(attributesXml); var recipientNameElement = (XmlElement)xmlDoc.SelectSingleNode(@"//Attributes/GiftCardInfo/RecipientName"); var recipientEmailElement = (XmlElement)xmlDoc.SelectSingleNode(@"//Attributes/GiftCardInfo/RecipientEmail"); diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs index 9d05fa4d4e..47dafa0dfc 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeService.cs @@ -71,14 +71,36 @@ public ProductAttributeService(ICacheManager cacheManager, #endregion - //// Autowired Dependency (is a proptery dependency to avoid circularity) - //public virtual IProductAttributeParser AttributeParser { get; set; } + #region Utilities - #region Methods + private IList GetSwitchedLoadedAttributeMappings(ICollection productVariantAttributeIds) + { + if (productVariantAttributeIds != null && productVariantAttributeIds.Count > 0) + { + if (productVariantAttributeIds.Count == 1) + { + var pva = GetProductVariantAttributeById(productVariantAttributeIds.ElementAt(0)); + if (pva != null) + { + return new List { pva }; + } + } + else + { + return _productVariantAttributeRepository.GetMany(productVariantAttributeIds).ToList(); + } + } - #region Product attributes + return new List(); + } + + #endregion - public virtual void DeleteProductAttribute(ProductAttribute productAttribute) + #region Methods + + #region Product attributes + + public virtual void DeleteProductAttribute(ProductAttribute productAttribute) { if (productAttribute == null) throw new ArgumentNullException("productAttribute"); @@ -219,26 +241,33 @@ public virtual ProductVariantAttribute GetProductVariantAttributeById(int produc public virtual IList GetProductVariantAttributesByIds(IEnumerable productVariantAttributeIds, IEnumerable attributes = null) { - var result = new List(); - if (productVariantAttributeIds != null) { - foreach (var id in productVariantAttributeIds) + if (attributes != null) { - ProductVariantAttribute pva = null; + var ids = new List(); + var result = new List(); - if (attributes != null) - pva = attributes.FirstOrDefault(x => x.Id == id); + foreach (var id in productVariantAttributeIds) + { + var pva = attributes.FirstOrDefault(x => x.Id == id); + if (pva == null) + ids.Add(id); + else + result.Add(pva); + } - if (pva == null) - pva = GetProductVariantAttributeById(id); + var newLoadedMappings = GetSwitchedLoadedAttributeMappings(ids); - if (pva != null) - result.Add(pva); + result.AddRange(newLoadedMappings); + + return result; } + + return GetSwitchedLoadedAttributeMappings(productVariantAttributeIds.ToList()); } - return result; + return new List(); } public virtual IEnumerable GetProductVariantAttributeValuesByIds(params int[] productVariantAttributeValueIds) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index 49c2a5a928..2a973ca37d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -4280,7 +4280,7 @@ public ActionResult AttributeCombinationCreatePopup(string btnId, string formId, warnings.AddRange(_shoppingCartService.GetShoppingCartItemAttributeWarnings(_workContext.CurrentCustomer, ShoppingCartType.ShoppingCart, product, attributeXml)); - if (null != _productAttributeParser.FindProductVariantAttributeCombination(product, attributeXml, variantAttributes)) + if (null != _productAttributeParser.FindProductVariantAttributeCombination(product, attributeXml)) { warnings.Add(_localizationService.GetResource("Admin.Catalog.Products.ProductVariantAttributes.AttributeCombinations.CombiExists")); } @@ -4411,7 +4411,7 @@ public ActionResult CombinationExistenceNote(int productId, FormCollection form) string attributeXml = form.CreateSelectedAttributesXml(productId, attributes, _productAttributeParser, _localizationService, _downloadService, _catalogSettings, this.Request, warnings, false); - bool exists = (null != _productAttributeParser.FindProductVariantAttributeCombination(productId, attributeXml, attributes)); + bool exists = (null != _productAttributeParser.FindProductVariantAttributeCombination(productId, attributeXml)); if (!exists) { diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index 4fe5dcaa57..8d70852acd 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -443,9 +443,7 @@ public ProductDetailsModel PrepareProductDetailModel( { foreach (var attribute in variantAttributes) { - int preSelectedValueId = 0; - - var pvaModel = new ProductDetailsModel.ProductVariantAttributeModel() + var pvaModel = new ProductDetailsModel.ProductVariantAttributeModel { Id = attribute.Id, ProductId = attribute.ProductId, @@ -470,76 +468,74 @@ public ProductDetailsModel PrepareProductDetailModel( } } - if (attribute.ShouldHaveValues()) - { - var pvaValues = _productAttributeService.GetProductVariantAttributeValues(attribute.Id); + int preSelectedValueId = 0; + var pvaValues = (attribute.ShouldHaveValues() ? _productAttributeService.GetProductVariantAttributeValues(attribute.Id) : new List()); - foreach (var pvaValue in pvaValues) - { - ProductBundleItemAttributeFilter attributeFilter = null; + foreach (var pvaValue in pvaValues) + { + ProductBundleItemAttributeFilter attributeFilter = null; - if (productBundleItem.FilterOut(pvaValue, out attributeFilter)) - continue; + if (productBundleItem.FilterOut(pvaValue, out attributeFilter)) + continue; - if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) - preSelectedValueId = attributeFilter.AttributeValueId; + if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) + preSelectedValueId = attributeFilter.AttributeValueId; - var linkedProduct = _productService.GetProductById(pvaValue.LinkedProductId); + 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; + 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 (linkedProduct != null && linkedProduct.VisibleIndividually) + pvaValueModel.SeName = linkedProduct.GetSeName(); - if (hasSelectedAttributes) - pvaValueModel.IsPreSelected = false; // explicitly selected always discards pre-selected by merchant + 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, _services.WorkContext.WorkingCurrency); - - 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); - } + // 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, _services.WorkContext.WorkingCurrency); - if (_catalogSettings.ShowLinkedAttributeValueQuantity && pvaValue.ValueType == ProductVariantAttributeValueType.ProductLinkage) - { - pvaValueModel.QuantityInfo = pvaValue.Quantity; - } + if (priceAdjustmentBase > decimal.Zero) + pvaValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment, true, false); + else if (priceAdjustmentBase < decimal.Zero) + pvaValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment, true, false); - pvaValueModel.PriceAdjustmentValue = priceAdjustment; - } - - if (!_catalogSettings.ShowVariantCombinationPriceAdjustment) + if (pvaValueModel.IsPreSelected) { - pvaValueModel.PriceAdjustment = ""; + preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); + preSelectedWeightAdjustment = decimal.Add(preSelectedWeightAdjustment, pvaValue.WeightAdjustment); } - if (_catalogSettings.ShowLinkedAttributeValueImage && pvaValue.ValueType == ProductVariantAttributeValueType.ProductLinkage) + if (_catalogSettings.ShowLinkedAttributeValueQuantity && pvaValue.ValueType == ProductVariantAttributeValueType.ProductLinkage) { - var linkagePicture = _pictureService.GetPicturesByProductId(pvaValue.LinkedProductId, 1).FirstOrDefault(); - if (linkagePicture != null) - pvaValueModel.ImageUrl = _pictureService.GetPictureUrl(linkagePicture, _mediaSettings.AutoCompleteSearchThumbPictureSize, false); + pvaValueModel.QuantityInfo = pvaValue.Quantity; } - pvaModel.Values.Add(pvaValueModel); + 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.AutoCompleteSearchThumbPictureSize, false); } + + pvaModel.Values.Add(pvaValueModel); } // we need selected attributes to get initially displayed combination images @@ -552,14 +548,25 @@ public ProductDetailsModel PrepareProductDetailModel( 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) - defaultValue = pvaModel.Values.FirstOrDefault(v => v.IsPreSelected); + { + 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); + //if (defaultValue != null) + // selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); } model.ProductVariantAttributes.Add(pvaModel); From 474d6a037864c783b32a7d18fc055553f82d62fb Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 25 Jul 2015 20:49:55 +0200 Subject: [PATCH 0304/1256] Updated changelog --- changelog.md | 2 ++ .../Extensions/NameValueCollectionExtensions.cs | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index d3059c982a..f1153fdf11 100644 --- a/changelog.md +++ b/changelog.md @@ -16,6 +16,7 @@ * #731 Web-API: Allow deletion and inserting of product category and manufacturer assignments * #733 Option to set a display order for homepage products * #607 HTML capable full description for payment methods displayed in checkout +* #732 Product list: Option to display the pre-selected price instead of the lowest price ### Improvements * (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%. @@ -30,6 +31,7 @@ ### Bugfixes * #523 Redirecting to payment provider performed by core instead of plugin +* Preselected price was wrong for product attributes with multiple preselected values (same on product detail page) ## SmartStore.NET 2.2.2 diff --git a/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs b/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs index d4846ddf04..68d8f8dda6 100644 --- a/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs +++ b/src/Libraries/SmartStore.Services/Extensions/NameValueCollectionExtensions.cs @@ -67,9 +67,6 @@ public static string CreateSelectedAttributesXml(this NameValueCollection collec HttpRequestBase request, List warnings, bool formatWithProductId = true, int bundleItemId = 0) - public static string CreateSelectedAttributesXml(this NameValueCollection collection, int productId, IEnumerable variantAttributes, - IProductAttributeParser productAttributeParser, ILocalizationService localizationService, IDownloadService downloadService, CatalogSettings catalogSettings, - HttpRequestBase request, List warnings, bool formatWithProductId = true, int bundleItemId = 0) { if (collection == null) return ""; From 0afb4e7fb47cadb40c6aaa94d6d7a4b660e2cf45 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sun, 26 Jul 2015 18:04:06 +0200 Subject: [PATCH 0305/1256] Reduce database round trips initiated by price calculation --- .../Collections/LazyMultimap.cs | 85 +++++++--- .../SmartStore.Core/Domain/Catalog/Product.cs | 2 +- .../Catalog/IPriceCalculationService.cs | 30 ++-- .../Catalog/IProductService.cs | 11 ++ .../Catalog/PriceCalculationContext.cs | 84 +++++++++- .../Catalog/PriceCalculationService.cs | 148 ++++++++---------- .../Catalog/ProductService.cs | 28 ++++ .../Controllers/OData/ProductsController.cs | 2 +- .../Controllers/CatalogHelper.cs | 102 ++++++------ 9 files changed, 312 insertions(+), 180 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs b/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs index e3c4ea8d35..803ff63ded 100644 --- a/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs +++ b/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs @@ -6,28 +6,72 @@ namespace SmartStore.Collections { /// - /// Structure that combines early and lazy data loading + /// Structure that manages data keys and offers the combination of early and lazy data loading /// public class LazyMultimap : Multimap { private Func> _load; - private List _loaded; // to avoid database rountrips with empty results + private List _loaded; // to avoid database round trips with empty results + private List _collect; + private int _roundTripCount; - public LazyMultimap(Func> load, IEnumerable initial = null) + /// + /// Constructor + /// + /// int[] keys like Entity.Id, Multimap> delegate to load data + /// Keys of early loaded data + public LazyMultimap(Func> load, IEnumerable collect = null) { _load = load; _loaded = new List(); - Load(initial); + if (collect == null) + _collect = new List(); + else + _collect = new List(collect); } - public virtual ICollection Ensure(int key) + protected virtual void Load(IEnumerable keys) { - if (!_loaded.Contains(key)) + if (keys != null) { - if (typeof(T).Name == "ProductVariantAttribute") - "lazy load {0}".FormatInvariant(key).Dump(); + var loadKeys = (_collect.Count == 0 ? keys : _collect.Concat(keys)) + .Distinct() + .Except(_loaded) + .ToArray(); + + _collect.Clear(); // invalidate, do not load again + + if (loadKeys.Any()) + { + ++_roundTripCount; + + Debug.WriteLine("Round trip {0} of {1}: {2}", _roundTripCount, typeof(T).Name, string.Join(",", loadKeys.OrderBy(x => x))); + + var items = _load(loadKeys); + + _loaded.AddRange(loadKeys); + + if (items != null) + { + foreach (var range in items) + { + base.AddRange(range.Key, range.Value); + } + } + } + } + } + /// + /// Get data. Load it if not already loaded yet. + /// + /// Data key + /// Collection of data + public virtual ICollection Load(int key) + { + if (!_loaded.Contains(key)) + { Load(new int[] { key }); } @@ -39,26 +83,15 @@ public virtual ICollection Ensure(int key) return result; } - protected virtual void Load(IEnumerable keys) + /// + /// Collect keys for combined loading + /// + /// Data keys + public virtual void Collect(IEnumerable keys) { - if (keys != null) + if (keys != null && keys.Any()) { - var loadKeys = keys.Distinct().Except(_loaded).ToArray(); - - if (loadKeys.Any()) - { - var items = _load(loadKeys); - - //if (typeof(T).Name == "ProductVariantAttribute") - // "call load {0}".FormatInvariant(string.Join(";", loadKeys)).Dump(); - - _loaded.AddRange(loadKeys); - - foreach (var range in items) - { - base.AddRange(range.Key, range.Value); - } - } + _collect = _collect.Union(keys).ToList(); } } } diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs index 1d142e5e09..a815e7d4b8 100644 --- a/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs +++ b/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs @@ -565,7 +565,7 @@ public decimal Price /// Gets or sets a value indicating whether this product has tier prices configured /// The same as if we run this.TierPrices.Count > 0 /// We use this property for performance optimization: - /// if this property is set to false, then we do not need to load tier prices navifation property + /// if this property is set to false, then we do not need to load tier prices navigation property /// /// [DataMember] diff --git a/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs index 3ae7d2bb7e..090a301e8d 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs @@ -14,9 +14,9 @@ public partial interface IPriceCalculationService /// /// Creates a price calculation context /// - /// Product identifieres. null to lazy load data if required. - /// - PriceCalculationContext CreatePriceCalculationContext(IEnumerable productIds = null); + /// Products. null to lazy load data if required. + /// Price calculation context + PriceCalculationContext CreatePriceCalculationContext(IEnumerable products = null); /// /// Get product special price (is valid) @@ -66,13 +66,15 @@ decimal GetFinalPrice(Product product, /// A value indicating whether include discounts or not for final price computation /// Shopping cart item quantity /// A product bundle item + /// Object with cargo data for better performance /// Final price decimal GetFinalPrice(Product product, Customer customer, decimal additionalCharge, bool includeDiscounts, int quantity, - ProductBundleItemData bundleItem = null); + ProductBundleItemData bundleItem = null, + PriceCalculationContext context = null); /// /// Gets the final price including bundle per-item pricing @@ -84,9 +86,16 @@ decimal GetFinalPrice(Product product, /// A value indicating whether include discounts or not for final price computation /// Shopping cart item quantity /// A product bundle item + /// Object with cargo data for better performance /// Final price - decimal GetFinalPrice(Product product, IEnumerable bundleItems, - Customer customer, decimal additionalCharge, bool includeDiscounts, int quantity, ProductBundleItemData bundleItem = null); + decimal GetFinalPrice(Product product, + IEnumerable bundleItems, + Customer customer, + decimal additionalCharge, + bool includeDiscounts, + int quantity, + ProductBundleItemData bundleItem = null, + PriceCalculationContext context = null); /// /// Get the lowest possible price for a product. @@ -100,11 +109,12 @@ decimal GetFinalPrice(Product product, IEnumerable bundle /// /// Get the lowest price of a grouped product. /// - /// Grouped product. - /// Products associated to product. - /// The associated product with the lowest price. + /// Grouped product + /// Object with cargo data for better performance + /// Products associated to product + /// The associated product with the lowest price /// The lowest price. - decimal? GetLowestPrice(Product product, IEnumerable associatedProducts, out Product lowestPriceProduct); + decimal? GetLowestPrice(Product product, PriceCalculationContext context, IEnumerable associatedProducts, out Product lowestPriceProduct); /// /// Get the initial price including preselected attributes diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductService.cs b/src/Libraries/SmartStore.Services/Catalog/IProductService.cs index e080a437b5..2ae693aa22 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IProductService.cs @@ -3,8 +3,10 @@ using System.Linq; using System.Linq.Expressions; using System.Web.Mvc; +using SmartStore.Collections; using SmartStore.Core; using SmartStore.Core.Domain.Catalog; +using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Orders; using SmartStore.Utilities; @@ -273,6 +275,15 @@ public partial interface IProductService /// Tier price TierPrice GetTierPriceById(int tierPriceId); + /// + /// Gets tier prices by product identifiers + /// + /// Product identifiers + /// Filter tier prices by customer + /// Filter tier prices by store + /// Map of tier prices + Multimap GetTierPrices(int[] productIds, Customer customer = null, int storeId = 0); + /// /// Inserts a tier price /// diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationContext.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationContext.cs index 41f5025c95..0f594e6fdc 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationContext.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationContext.cs @@ -1,11 +1,89 @@ -using SmartStore.Collections; +using System; +using System.Collections.Generic; +using System.Linq; +using SmartStore.Collections; using SmartStore.Core.Domain.Catalog; namespace SmartStore.Services.Catalog { + /// + /// Cargo data to reduce database round trips during price calculation + /// public class PriceCalculationContext { - public LazyMultimap Attributes { get; set; } - public LazyMultimap AttributeCombinations { get; set; } + private List _productIds; + private List _productIdsTierPrices; + + private Func> _funcAttributes; + private Func> _funcAttributeCombinations; + private Func> _funcTierPrices; + + private LazyMultimap _attributes; + private LazyMultimap _attributeCombinations; + private LazyMultimap _tierPrices; + + public PriceCalculationContext(IEnumerable products, + Func> attributes, + Func> attributeCombinations, + Func> tierPrices) + { + if (products == null) + { + _productIds = new List(); + _productIdsTierPrices = new List(); + } + else + { + _productIds = new List(products.Select(x => x.Id)); + _productIdsTierPrices = new List(products.Where(x => x.HasTierPrices).Select(x => x.Id)); + } + + _funcAttributes = attributes; + _funcAttributeCombinations = attributeCombinations; + _funcTierPrices = tierPrices; + } + + public LazyMultimap Attributes + { + get + { + if (_attributes == null) + { + _attributes = new LazyMultimap(keys => _funcAttributes(keys), _productIds); + } + return _attributes; + } + } + + public LazyMultimap AttributeCombinations + { + get + { + if (_attributeCombinations == null) + { + _attributeCombinations = new LazyMultimap(keys => _funcAttributeCombinations(keys), _productIds); + } + return _attributeCombinations; + } + } + + public LazyMultimap TierPrices + { + get + { + if (_tierPrices == null) + { + _tierPrices = new LazyMultimap(keys => _funcTierPrices(keys), _productIdsTierPrices); + } + return _tierPrices; + } + } + + public void Collect(IEnumerable productIds) + { + Attributes.Collect(productIds); + AttributeCombinations.Collect(productIds); + TierPrices.Collect(productIds); + } } } diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index a343b360be..aaa8825d56 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -123,20 +123,33 @@ protected virtual IList GetAllowedDiscounts(Product product, Customer /// Customer /// Quantity /// Price - protected virtual decimal? GetMinimumTierPrice(Product product, Customer customer, int quantity) + protected virtual decimal? GetMinimumTierPrice(Product product, Customer customer, int quantity, PriceCalculationContext context = null) { if (!product.HasTierPrices) return decimal.Zero; - var tierPrices = product.TierPrices - .OrderBy(tp => tp.Quantity) - .FilterByStore(_services.StoreContext.CurrentStore.Id) - .FilterForCustomer(customer) - .ToList() - .RemoveDuplicatedQuantities(); + IEnumerable tierPrices = null; + + if (context == null) + { + tierPrices = product.TierPrices + .OrderBy(tp => tp.Quantity) + .FilterByStore(_services.StoreContext.CurrentStore.Id) + .FilterForCustomer(customer) + .ToList() + .RemoveDuplicatedQuantities(); + } + else + { + tierPrices = context.TierPrices.Load(product.Id); + } + + if (tierPrices == null) + return decimal.Zero; int previousQty = 1; decimal? previousPrice = null; + foreach (var tierPrice in tierPrices) { //check quantity @@ -165,7 +178,7 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC var selectedAttributes = new NameValueCollection(); var selectedAttributeValues = new List(); - var attributes = context.Attributes.Ensure(product.Id); + var attributes = context.Attributes.Load(product.Id); // 1. fill selectedAttributes with initially selected attributes foreach (var attribute in attributes.Where(x => x.ProductVariantAttributeValues.Count > 0 && x.ShouldHaveValues())) @@ -226,7 +239,7 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _services.Localization, _downloadService, _catalogSettings, _httpRequestBase, new List(), true, bundleItemId); - var combinations = context.AttributeCombinations.Ensure(product.Id); + var combinations = context.AttributeCombinations.Load(product.Id); var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml, attributes)); @@ -253,33 +266,17 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC bundleItem.AdditionalCharge = attributesTotalPriceBase; } - var result = GetFinalPrice(product, bundleItems, _services.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem); + var result = GetFinalPrice(product, bundleItems, _services.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem, context); return result; } - public virtual PriceCalculationContext CreatePriceCalculationContext(IEnumerable productIds = null) + public virtual PriceCalculationContext CreatePriceCalculationContext(IEnumerable products = null) { - var context = new PriceCalculationContext(); - - if (_catalogSettings.PriceDisplayType == PriceDisplayType.Hide || _catalogSettings.PriceDisplayType == PriceDisplayType.PriceWithoutDiscountsAndAttributes) - return context; - - context.Attributes = new LazyMultimap(x => - { - "load {0}".FormatInvariant(string.Join(";", x)).Dump(); - - var result = _productAttributeService.GetProductVariantAttributesByProductIds(x, null); - return result; - }, productIds); - - if (_catalogSettings.PriceDisplayType == PriceDisplayType.PreSelectedPrice) - { - context.AttributeCombinations = new LazyMultimap(x => - { - var result = _productAttributeService.GetProductVariantAttributeCombinations(x); - return result; - }, productIds); - } + var context = new PriceCalculationContext(products, + x => _productAttributeService.GetProductVariantAttributesByProductIds(x, null), + x => _productAttributeService.GetProductVariantAttributeCombinations(x), + x => _productService.GetTierPrices(x, _services.WorkContext.CurrentCustomer, _services.StoreContext.CurrentStore.Id) + ); return context; } @@ -362,23 +359,14 @@ public virtual decimal GetFinalPrice(Product product, return GetFinalPrice(product, customer, additionalCharge, includeDiscounts, 1); } - /// - /// Gets the final price - /// - /// Product - /// The customer - /// Additional charge - /// A value indicating whether include discounts or not for final price computation - /// Shopping cart item quantity - /// A product bundle item - /// Final price public virtual decimal GetFinalPrice( Product product, Customer customer, decimal additionalCharge, bool includeDiscounts, int quantity, - ProductBundleItemData bundleItem = null) + ProductBundleItemData bundleItem = null, + PriceCalculationContext context = null) { //initial price decimal result = product.Price; @@ -391,7 +379,7 @@ public virtual decimal GetFinalPrice( //tier prices if (product.HasTierPrices && !bundleItem.IsValid()) { - decimal? tierPrice = GetMinimumTierPrice(product, customer, quantity); + decimal? tierPrice = GetMinimumTierPrice(product, customer, quantity, context); if (tierPrice.HasValue) result = Math.Min(result, tierPrice.Value); } @@ -407,22 +395,13 @@ public virtual decimal GetFinalPrice( { result = result + additionalCharge; } + if (result < decimal.Zero) result = decimal.Zero; + return result; } - /// - /// Gets the final price including bundle per-item pricing - /// - /// Product - /// Bundle items - /// The customer - /// Additional charge - /// A value indicating whether include discounts or not for final price computation - /// Shopping cart item quantity - /// A product bundle item - /// Final price public virtual decimal GetFinalPrice( Product product, IEnumerable bundleItems, @@ -430,7 +409,8 @@ public virtual decimal GetFinalPrice( decimal additionalCharge, bool includeDiscounts, int quantity, - ProductBundleItemData bundleItem = null) + ProductBundleItemData bundleItem = null, + PriceCalculationContext context = null) { if (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing) { @@ -439,14 +419,14 @@ public virtual decimal GetFinalPrice( foreach (var itemData in items.Where(x => x.IsValid())) { - decimal itemPrice = GetFinalPrice(itemData.Item.Product, customer, itemData.AdditionalCharge, includeDiscounts, 1, itemData); + decimal itemPrice = GetFinalPrice(itemData.Item.Product, customer, itemData.AdditionalCharge, includeDiscounts, 1, itemData, context); result = result + decimal.Multiply(itemPrice, itemData.Item.Quantity); } return (result < decimal.Zero ? decimal.Zero : result); } - return GetFinalPrice(product, customer, additionalCharge, includeDiscounts, quantity, bundleItem); + return GetFinalPrice(product, customer, additionalCharge, includeDiscounts, quantity, bundleItem, context); } /// @@ -465,7 +445,7 @@ public virtual decimal GetLowestPrice(Product product, PriceCalculationContext c throw Error.InvalidOperation("Choose the other override for products of type grouped product."); if (context == null) - context = CreatePriceCalculationContext(null); + context = CreatePriceCalculationContext(); bool isBundlePerItemPricing = (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing); @@ -473,7 +453,7 @@ public virtual decimal GetLowestPrice(Product product, PriceCalculationContext c // TODO(?): attribute price adjustments were not regarded here cause of performance - decimal lowestPrice = GetFinalPrice(product, null, _services.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); + decimal lowestPrice = GetFinalPrice(product, null, _services.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue, null, context); if (product.LowestAttributeCombinationPrice.HasValue && product.LowestAttributeCombinationPrice.Value < lowestPrice) { @@ -488,18 +468,20 @@ public virtual decimal GetLowestPrice(Product product, PriceCalculationContext c if (!displayFromMessage && product.ProductType != ProductType.BundledProduct) { - var attributes = context.Attributes.Ensure(product.Id); + var attributes = context.Attributes.Load(product.Id); displayFromMessage = attributes.Any(x => x.ProductVariantAttributeValues.Any(y => y.PriceAdjustment != decimal.Zero)); } if (!displayFromMessage && product.HasTierPrices && !isBundlePerItemPricing) { - var tierPrices = product.TierPrices - .OrderBy(tp => tp.Quantity) - .FilterByStore(_services.StoreContext.CurrentStore.Id) - .FilterForCustomer(_services.WorkContext.CurrentCustomer) - .ToList() - .RemoveDuplicatedQuantities(); + //var tierPrices = product.TierPrices + // .OrderBy(tp => tp.Quantity) + // .FilterByStore(_services.StoreContext.CurrentStore.Id) + // .FilterForCustomer(_services.WorkContext.CurrentCustomer) + // .ToList() + // .RemoveDuplicatedQuantities(); + + var tierPrices = context.TierPrices.Load(product.Id); displayFromMessage = (tierPrices.Count > 0 && !(tierPrices.Count == 1 && tierPrices.First().Quantity <= 1)); } @@ -507,14 +489,7 @@ public virtual decimal GetLowestPrice(Product product, PriceCalculationContext c return lowestPrice; } - /// - /// Get the lowest price of a grouped product. - /// - /// Grouped product. - /// Products associated to product. - /// The associated product with the lowest price. - /// The lowest price. - public virtual decimal? GetLowestPrice(Product product, IEnumerable associatedProducts, out Product lowestPriceProduct) + public virtual decimal? GetLowestPrice(Product product, PriceCalculationContext context, IEnumerable associatedProducts, out Product lowestPriceProduct) { if (product == null) throw new ArgumentNullException("product"); @@ -527,10 +502,14 @@ public virtual decimal GetLowestPrice(Product product, PriceCalculationContext c lowestPriceProduct = null; decimal? lowestPrice = null; + var customer = _services.WorkContext.CurrentCustomer; + + if (context == null) + context = CreatePriceCalculationContext(); foreach (var associatedProduct in associatedProducts) { - var tmpPrice = GetFinalPrice(associatedProduct, _services.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue); + var tmpPrice = GetFinalPrice(associatedProduct, customer, decimal.Zero, true, int.MaxValue, null, context); if (associatedProduct.LowestAttributeCombinationPrice.HasValue && associatedProduct.LowestAttributeCombinationPrice.Value < tmpPrice) { @@ -563,27 +542,28 @@ public virtual decimal GetPreselectedPrice(Product product, PriceCalculationCont var result = decimal.Zero; + if (context == null) + context = CreatePriceCalculationContext(); + if (product.ProductType == ProductType.BundledProduct) { var bundleItems = _productService.GetBundleItems(product.Id); - var ids = bundleItems.Select(x => x.Item.ProductId).ToList(); - ids.Add(product.Id); - var bundleContext = CreatePriceCalculationContext(ids); + var productIds = bundleItems.Select(x => x.Item.ProductId).ToList(); + productIds.Add(product.Id); + + context.Collect(productIds); foreach (var bundleItem in bundleItems.Where(x => x.Item.Product.CanBeBundleItem())) { // fetch bundleItems.AdditionalCharge for all bundle items - var unused = GetPreselectedPrice(bundleItem.Item.Product, bundleContext, bundleItem, bundleItems); + var unused = GetPreselectedPrice(bundleItem.Item.Product, context, bundleItem, bundleItems); } - result = GetPreselectedPrice(product, bundleContext, null, bundleItems); + result = GetPreselectedPrice(product, context, null, bundleItems); } else { - if (context == null) - context = CreatePriceCalculationContext(null); - result = GetPreselectedPrice(product, context, null, null); } diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs index efc889d9f4..fd762a1f2b 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ProductService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ProductService.cs @@ -5,11 +5,13 @@ using System.Linq.Expressions; using System.ServiceModel.Syndication; using System.Web.Mvc; +using SmartStore.Collections; using SmartStore.Core; using SmartStore.Core.Caching; using SmartStore.Core.Data; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Common; +using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Localization; using SmartStore.Core.Domain.Media; using SmartStore.Core.Domain.Orders; @@ -1639,6 +1641,32 @@ public virtual TierPrice GetTierPriceById(int tierPriceId) return tierPrice; } + public virtual Multimap GetTierPrices(int[] productIds, Customer customer = null, int storeId = 0) + { + Guard.ArgumentNotNull(() => productIds); + + var query = + from x in _tierPriceRepository.TableUntracked + where productIds.Contains(x.ProductId) + select x; + + if (storeId != 0) + query = query.Where(x => x.StoreId == 0 || x.StoreId == storeId); + + query = query.OrderBy(x => x.ProductId).ThenBy(x => x.Quantity); + + var list = query.ToList(); + + if (customer != null) + list = list.FilterForCustomer(customer).ToList(); + + var map = list + .RemoveDuplicatedQuantities() + .ToMultimap(x => x.ProductId, x => x); + + return map; + } + /// /// Inserts a tier price /// diff --git a/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs b/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs index aec30f45cd..232a326378 100644 --- a/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs +++ b/src/Plugins/SmartStore.WebApi/Controllers/OData/ProductsController.cs @@ -261,7 +261,7 @@ public IQueryable GetProductBundleItems(int key) Product lowestPriceProduct; var associatedProducts = Service.PrepareProductSearchQuery(searchContext); - result = _priceCalculationService.Value.GetLowestPrice(entity, associatedProducts, out lowestPriceProduct); + result = _priceCalculationService.Value.GetLowestPrice(entity, null, associatedProducts, out lowestPriceProduct); } else { diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index 8d70852acd..2c1ec945ce 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -1002,7 +1002,6 @@ public IEnumerable PrepareProductOverviewModels( string taxInfo = T(taxDisplayType == TaxDisplayType.IncludingTax ? "Tax.InclVAT" : "Tax.ExclVAT"); string shippingInfoLink = _urlHelper.RouteUrl("Topic", new { SystemName = "shippinginfo" }); var cachedManufacturerModels = new Dictionary(); - PriceCalculationContext priceCalculationContext = null; var res = new Dictionary(StringComparer.OrdinalIgnoreCase) { @@ -1015,7 +1014,7 @@ public IEnumerable PrepareProductOverviewModels( { "Common.AdditionalShippingSurcharge", T("Common.AdditionalShippingSurcharge") } }; - int[] productIds = products.Select(x => x.Id).ToArray(); + var cargoData = _priceCalculationService.CreatePriceCalculationContext(products); var models = new List(); @@ -1036,9 +1035,6 @@ public IEnumerable PrepareProductOverviewModels( { #region Prepare product price - if (priceCalculationContext == null) - priceCalculationContext = _priceCalculationService.CreatePriceCalculationContext(productIds); - var priceModel = new ProductOverviewModel.ProductPriceModel { ForceRedirectionAfterAddingToCart = forceRedirectionAfterAddingToCart, @@ -1057,7 +1053,7 @@ public IEnumerable PrepareProductOverviewModels( { StoreId = currentStore.Id, ParentGroupedProductId = product.Id, - PageSize = (_catalogSettings.PriceDisplayType == PriceDisplayType.LowestPrice ? int.MaxValue : 1), + PageSize = int.MaxValue, VisibleIndividuallyOnly = false }; @@ -1065,23 +1061,25 @@ public IEnumerable PrepareProductOverviewModels( if (associatedProducts.Count > 0) { - contextProduct = associatedProducts.First(); + contextProduct = associatedProducts.OrderBy(x => x.DisplayOrder).First(); if (displayPrices && _catalogSettings.PriceDisplayType != PriceDisplayType.Hide) { decimal? displayPrice = null; + bool displayFromMessage = false; if (_catalogSettings.PriceDisplayType == PriceDisplayType.PreSelectedPrice) { - displayPrice = _priceCalculationService.GetPreselectedPrice(contextProduct, null); + displayPrice = _priceCalculationService.GetPreselectedPrice(contextProduct, cargoData); } else if (_catalogSettings.PriceDisplayType == PriceDisplayType.PriceWithoutDiscountsAndAttributes) { - displayPrice = _priceCalculationService.GetFinalPrice(contextProduct, null, currentCustomer, decimal.Zero, false, 1, null); + displayPrice = _priceCalculationService.GetFinalPrice(contextProduct, null, currentCustomer, decimal.Zero, false, 1, null, cargoData); } else { - displayPrice = _priceCalculationService.GetLowestPrice(product, associatedProducts, out contextProduct); + displayFromMessage = true; + displayPrice = _priceCalculationService.GetLowestPrice(product, cargoData, associatedProducts, out contextProduct); } if (contextProduct != null && !contextProduct.CustomerEntersPrice) @@ -1100,8 +1098,13 @@ public IEnumerable PrepareProductOverviewModels( decimal finalPrice = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workingCurrency); priceModel.OldPrice = null; - priceModel.Price = String.Format(res["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice)); - priceModel.HasDiscount = finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero; + + if (displayFromMessage) + priceModel.Price = String.Format(res["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice)); + else + priceModel.Price = _priceFormatter.FormatPrice(finalPrice); + + priceModel.HasDiscount = (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero); } else { @@ -1144,15 +1147,15 @@ public IEnumerable PrepareProductOverviewModels( if (_catalogSettings.PriceDisplayType == PriceDisplayType.PreSelectedPrice) { - displayPrice = _priceCalculationService.GetPreselectedPrice(product, priceCalculationContext); + displayPrice = _priceCalculationService.GetPreselectedPrice(product, cargoData); } else if (_catalogSettings.PriceDisplayType == PriceDisplayType.PriceWithoutDiscountsAndAttributes) { - displayPrice = _priceCalculationService.GetFinalPrice(product, null, currentCustomer, decimal.Zero, false, 1, null); + displayPrice = _priceCalculationService.GetFinalPrice(product, null, currentCustomer, decimal.Zero, false, 1, null, cargoData); } else { - displayPrice = _priceCalculationService.GetLowestPrice(product, priceCalculationContext, out displayFromMessage); + displayPrice = _priceCalculationService.GetLowestPrice(product, cargoData, out displayFromMessage); } decimal taxRate = decimal.Zero; @@ -1194,6 +1197,35 @@ public IEnumerable PrepareProductOverviewModels( #endregion } + // color squares + if (prepareColorAttributes && _catalogSettings.ShowColorSquaresInLists) + { + #region Prepare color attributes + + var attributes = cargoData.Attributes.Load(contextProduct.Id); + var colorAttribute = attributes.FirstOrDefault(x => x.AttributeControlType == AttributeControlType.ColorSquares); + + if (colorAttribute != null) + { + var colorValues = + from a in colorAttribute.ProductVariantAttributeValues.Take(50) + where (a.ColorSquaresRgb.HasValue() && !a.ColorSquaresRgb.IsCaseInsensitiveEqual("transparent")) + select new ProductOverviewModel.ColorAttributeModel + { + Color = a.ColorSquaresRgb, + Alias = a.Alias, + FriendlyName = a.GetLocalized(l => l.Name) + }; + + if (colorValues.Any()) + { + model.ColorAttributes.AddRange(colorValues.Distinct()); + } + } + + #endregion + } + // picture if (preparePictureModel) { @@ -1297,46 +1329,6 @@ public IEnumerable PrepareProductOverviewModels( models.Add(model); } - // Color squares - // Perf: Loading all applicable attributes in one go is definitely faster - // than fetching them one by one withing the above loop. - if (prepareColorAttributes && _catalogSettings.ShowColorSquaresInLists) - { - #region Prepare color attributes - - var minPriceProductIds = models.Select(x => x.MinPriceProductId).ToArray(); - var allAttrs = _productAttributeService.GetProductVariantAttributesByProductIds(minPriceProductIds, AttributeControlType.ColorSquares); - - foreach (var model in models) - { - if (!allAttrs.ContainsKey(model.MinPriceProductId)) - continue; - - // get the FIRST color type attribute - ProductVariantAttribute colorAttr = allAttrs[model.MinPriceProductId].FirstOrDefault(x => x.AttributeControlType == AttributeControlType.ColorSquares); - - if (colorAttr != null) - { - var colorValues = - from a in colorAttr.ProductVariantAttributeValues.Take(50) - where (a.ColorSquaresRgb.HasValue() && !a.ColorSquaresRgb.IsCaseInsensitiveEqual("transparent")) - select new ProductOverviewModel.ColorAttributeModel - { - Color = a.ColorSquaresRgb, - Alias = a.Alias, - FriendlyName = a.GetLocalized(l => l.Name) - }; - - if (colorValues.Any()) - { - model.ColorAttributes.AddRange(colorValues.Distinct()); - } - } - } - - #endregion - } - return models; } From cea2e962979d3d7d27b0ee435af29d960f4f7f67 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 27 Jul 2015 10:47:11 +0200 Subject: [PATCH 0306/1256] Removed odd extension method --- .../Catalog/PriceCalculationService.cs | 23 ++++++++----------- .../Discounts/DiscountExtentions.cs | 16 ------------- .../Orders/OrderProcessingService.cs | 9 ++++---- .../Orders/OrderTotalCalculationService.cs | 23 +++++++++++-------- 4 files changed, 28 insertions(+), 43 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index aaa8825d56..7cff4b8abb 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -67,26 +67,23 @@ public PriceCalculationService( /// Discounts protected virtual IList GetAllowedDiscounts(Product product, Customer customer) { - var allowedDiscounts = new List(); + var result = new List(); if (_catalogSettings.IgnoreDiscounts) - return allowedDiscounts; + return result; if (product.HasDiscountsApplied) { //we use this property ("HasDiscountsApplied") for performance optimziation to avoid unnecessary database calls foreach (var discount in product.AppliedDiscounts) { - if (_discountService.IsDiscountValid(discount, customer) && - discount.DiscountType == DiscountType.AssignedToSkus && - !allowedDiscounts.ContainsDiscount(discount)) + if (discount.DiscountType == DiscountType.AssignedToSkus && !result.Any(x => x.Id == discount.Id) && _discountService.IsDiscountValid(discount, customer)) { - allowedDiscounts.Add(discount); + result.Add(discount); } } } - //performance optimization - //load all category discounts just to ensure that we have at least one + //performance optimization. load all category discounts just to ensure that we have at least one if (_discountService.GetAllDiscounts(DiscountType.AssignedToCategories).Any()) { var productCategories = _categoryService.GetProductCategoriesByProductId(product.Id); @@ -100,20 +97,20 @@ protected virtual IList GetAllowedDiscounts(Product product, Customer { //we use this property ("HasDiscountsApplied") for performance optimziation to avoid unnecessary database calls var categoryDiscounts = category.AppliedDiscounts; + foreach (var discount in categoryDiscounts) { - if (_discountService.IsDiscountValid(discount, customer) && - discount.DiscountType == DiscountType.AssignedToCategories && - !allowedDiscounts.ContainsDiscount(discount)) + if (discount.DiscountType == DiscountType.AssignedToCategories && !result.Any(x => x.Id == discount.Id) && _discountService.IsDiscountValid(discount, customer)) { - allowedDiscounts.Add(discount); + result.Add(discount); } } } } } } - return allowedDiscounts; + + return result; } /// diff --git a/src/Libraries/SmartStore.Services/Discounts/DiscountExtentions.cs b/src/Libraries/SmartStore.Services/Discounts/DiscountExtentions.cs index d8c29939db..ccc62d5921 100644 --- a/src/Libraries/SmartStore.Services/Discounts/DiscountExtentions.cs +++ b/src/Libraries/SmartStore.Services/Discounts/DiscountExtentions.cs @@ -29,7 +29,6 @@ public static decimal GetDiscountAmount(this Discount discount, decimal amount) return result; } - public static Discount GetPreferredDiscount(this IList discounts, decimal amount) { @@ -47,20 +46,5 @@ public static Discount GetPreferredDiscount(this IList discounts, deci return preferredDiscount; } - - public static bool ContainsDiscount(this IList discounts, Discount discount) - { - if (discounts == null) - throw new ArgumentNullException("discounts"); - - if (discount == null) - throw new ArgumentNullException("discount"); - - foreach (var dis1 in discounts) - if (discount.Id == dis1.Id) - return true; - - return false; - } } } diff --git a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs index 54d3a2f8d1..97e13a1ece 100644 --- a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs +++ b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs @@ -649,7 +649,7 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR orderSubTotalDiscountInclTax = orderSubTotalDiscountAmount1; //discount history - if (orderSubTotalAppliedDiscount1 != null && !appliedDiscounts.ContainsDiscount(orderSubTotalAppliedDiscount1)) + if (orderSubTotalAppliedDiscount1 != null && !appliedDiscounts.Any(x => x.Id == orderSubTotalAppliedDiscount1.Id)) appliedDiscounts.Add(orderSubTotalAppliedDiscount1); //sub total (excl tax) @@ -712,7 +712,7 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR if (!orderShippingTotalInclTax.HasValue || !orderShippingTotalExclTax.HasValue) throw new SmartException("Shipping total couldn't be calculated"); - if (shippingTotalDiscount != null && !appliedDiscounts.ContainsDiscount(shippingTotalDiscount)) + if (shippingTotalDiscount != null && !appliedDiscounts.Any(x => x.Id == shippingTotalDiscount.Id)) appliedDiscounts.Add(shippingTotalDiscount); } else @@ -783,7 +783,7 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR throw new SmartException("Order total couldn't be calculated"); //discount history - if (orderAppliedDiscount != null && !appliedDiscounts.ContainsDiscount(orderAppliedDiscount)) + if (orderAppliedDiscount != null && !appliedDiscounts.Any(x => x.Id == orderAppliedDiscount.Id)) appliedDiscounts.Add(orderAppliedDiscount); } else @@ -1089,7 +1089,8 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR decimal discountAmount = _priceCalculationService.GetDiscountAmount(sc, out scDiscount); decimal discountAmountInclTax = _taxService.GetProductPrice(sc.Item.Product, discountAmount, true, customer, out taxRate); decimal discountAmountExclTax = _taxService.GetProductPrice(sc.Item.Product, discountAmount, false, customer, out taxRate); - if (scDiscount != null && !appliedDiscounts.ContainsDiscount(scDiscount)) + + if (scDiscount != null && !appliedDiscounts.Any(x => x.Id == scDiscount.Id)) appliedDiscounts.Add(scDiscount); //attributes diff --git a/src/Libraries/SmartStore.Services/Orders/OrderTotalCalculationService.cs b/src/Libraries/SmartStore.Services/Orders/OrderTotalCalculationService.cs index 294db65762..4aef87d01f 100644 --- a/src/Libraries/SmartStore.Services/Orders/OrderTotalCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Orders/OrderTotalCalculationService.cs @@ -355,8 +355,7 @@ public virtual decimal GetOrderSubtotalDiscount(Customer customer, { foreach (var discount in allDiscounts) { - if (_discountService.IsDiscountValid(discount, customer) && discount.DiscountType == DiscountType.AssignedToOrderSubTotal && - !allowedDiscounts.ContainsDiscount(discount)) + if (discount.DiscountType == DiscountType.AssignedToOrderSubTotal && !allowedDiscounts.Any(x => x.Id == discount.Id) && _discountService.IsDiscountValid(discount, customer)) { allowedDiscounts.Add(discount); } @@ -668,12 +667,17 @@ public virtual decimal GetShippingDiscount(Customer customer, decimal shippingTo var allDiscounts = _discountService.GetAllDiscounts(DiscountType.AssignedToShipping); var allowedDiscounts = new List(); - if (allDiscounts != null) - foreach (var discount in allDiscounts) - if (_discountService.IsDiscountValid(discount, customer) && - discount.DiscountType == DiscountType.AssignedToShipping && - !allowedDiscounts.ContainsDiscount(discount)) - allowedDiscounts.Add(discount); + + if (allDiscounts != null) + { + foreach (var discount in allDiscounts) + { + if (discount.DiscountType == DiscountType.AssignedToShipping && !allowedDiscounts.Any(x => x.Id == discount.Id) && _discountService.IsDiscountValid(discount, customer)) + { + allowedDiscounts.Add(discount); + } + } + } appliedDiscount = allowedDiscounts.GetPreferredDiscount(shippingTotal); if (appliedDiscount != null) @@ -1068,8 +1072,7 @@ public virtual decimal GetOrderTotalDiscount(Customer customer, decimal orderTot { foreach (var discount in allDiscounts) { - if (_discountService.IsDiscountValid(discount, customer) && discount.DiscountType == DiscountType.AssignedToOrderTotal && - !allowedDiscounts.ContainsDiscount(discount)) + if (discount.DiscountType == DiscountType.AssignedToOrderTotal && !allowedDiscounts.Any(x => x.Id == discount.Id) &&_discountService.IsDiscountValid(discount, customer)) { allowedDiscounts.Add(discount); } From e283be263cd9014f2d32b6881c62bfe3cfe540e5 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 27 Jul 2015 12:02:29 +0200 Subject: [PATCH 0307/1256] Added optional customer number field --- changelog.md | 1 + .../Domain/Customers/CustomerSettings.cs | 6 ++++++ .../Customers/SystemCustomerAttributeNames.cs | 1 + .../201506181858349_AclRecordCustomerRole.cs | 12 ++++++++++++ .../Controllers/CustomerController.cs | 9 ++++++++- .../Models/Customers/CustomerModel.cs | 6 ++++++ .../Models/Settings/CustomerUserSettingsModel.cs | 3 +++ .../Views/Customer/_CreateOrUpdate.cshtml | 14 ++++++++++++++ .../Views/Setting/CustomerUser.cshtml | 9 +++++++++ .../Controllers/CustomerController.cs | 11 +++++++++++ .../Models/Customer/CustomerInfoModel.cs | 5 +++++ .../SmartStore.Web/Views/Customer/Info.cshtml | 7 ++++++- 12 files changed, 82 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index 438a5a59e4..499f044df1 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,7 @@ * Skrill payment plugin (distributed via Marketplace) * (Dev) DevTool plugin: added option to display all widget zones in public store * New options for manufacturer display on the homepage +* Added optional customer number field ### Improvements * (Perf) several minor optimizations for faster app startup and page rendering diff --git a/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs b/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs index f37d102711..3b2f13bb66 100644 --- a/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs +++ b/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs @@ -8,6 +8,7 @@ public class CustomerSettings : ISettings public CustomerSettings() { UsernamesEnabled = true; + CustomerNumberEnabled = true; DefaultPasswordFormat = PasswordFormat.Hashed; HashedPasswordFormat = "SHA1"; PasswordMinLength = 6; @@ -29,6 +30,11 @@ public CustomerSettings() /// public bool UsernamesEnabled { get; set; } + /// + /// Gets or sets a value indicating whether customers can enter a customer id + /// + public bool CustomerNumberEnabled { get; set; } + /// /// Gets or sets a value indicating whether users can check the availability of usernames (when registering or changing in 'My Account') /// diff --git a/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerAttributeNames.cs b/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerAttributeNames.cs index ea0bb24d01..e7c43c19da 100644 --- a/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerAttributeNames.cs +++ b/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerAttributeNames.cs @@ -20,6 +20,7 @@ public static partial class SystemCustomerAttributeNames public static string VatNumber { get { return "VatNumber"; } } public static string VatNumberStatusId { get { return "VatNumberStatusId"; } } public static string TimeZoneId { get { return "TimeZoneId"; } } + public static string CustomerNumber { get { return "CustomerNumber"; } } //Other attributes public static string DiscountCouponCode { get { return "DiscountCouponCode"; } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs index 153e8be49e..d6c9752fbd 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201506181858349_AclRecordCustomerRole.cs @@ -131,6 +131,18 @@ before you can assign them to all subcategories and products.
    "Zeige Herstellerbilder auf der Homepage", "Specifies whether manufacturers will be displayed as images or textual links on the homepage.", "Bestimmt ob Hersteller auf der Homepage als Bilder oder textuelle Links angezeigt werden."); + + builder.AddOrUpdate("Admin.Configuration.Settings.CustomerUser.CustomerNumberEnabled", + "Customers can enter a customer number", + "Kunden knnen Kundennummer hinterlegen", + "Specifies whether customers can enter a customer number.", + "Bestimmt ob Kunden eine Kundennummer hinterlegen knnen."); + + builder.AddOrUpdate("Account.Fields.CustomerNumber", + "Customer number", + "Kundennummer"); + + } } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs index 0a8e0c6858..11786ceaf6 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CustomerController.cs @@ -234,6 +234,7 @@ protected CustomerModel PrepareCustomerModelForList(Customer customer) Username = customer.Username, FullName = customer.GetFullName(), Company = customer.GetAttribute(SystemCustomerAttributeNames.Company), + CustomerNumber = customer.GetAttribute(SystemCustomerAttributeNames.CustomerNumber), Phone = customer.GetAttribute(SystemCustomerAttributeNames.Phone), ZipPostalCode = customer.GetAttribute(SystemCustomerAttributeNames.ZipPostalCode), CustomerRoleNames = GetCustomerRolesNames(customer.CustomerRoles.ToList()), @@ -281,7 +282,8 @@ private void PrepareCustomerModelForCreate(CustomerModel model) model.StateProvinceEnabled = _customerSettings.StateProvinceEnabled; model.PhoneEnabled = _customerSettings.PhoneEnabled; model.FaxEnabled = _customerSettings.FaxEnabled; - + model.CustomerNumberEnabled = _customerSettings.CustomerNumberEnabled; + if (_customerSettings.CountryEnabled) { model.AvailableCountries.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.SelectCountry"), Value = "0" }); @@ -607,6 +609,7 @@ public ActionResult Edit(int id) model.Gender = customer.GetAttribute(SystemCustomerAttributeNames.Gender); model.DateOfBirth = customer.GetAttribute(SystemCustomerAttributeNames.DateOfBirth); model.Company = customer.GetAttribute(SystemCustomerAttributeNames.Company); + model.CustomerNumber = customer.GetAttribute(SystemCustomerAttributeNames.CustomerNumber); model.StreetAddress = customer.GetAttribute(SystemCustomerAttributeNames.StreetAddress); model.StreetAddress2 = customer.GetAttribute(SystemCustomerAttributeNames.StreetAddress2); model.ZipPostalCode = customer.GetAttribute(SystemCustomerAttributeNames.ZipPostalCode); @@ -619,6 +622,7 @@ public ActionResult Edit(int id) model.GenderEnabled = _customerSettings.GenderEnabled; model.DateOfBirthEnabled = _customerSettings.DateOfBirthEnabled; model.CompanyEnabled = _customerSettings.CompanyEnabled; + model.CustomerNumberEnabled = _customerSettings.CustomerNumberEnabled; model.StreetAddressEnabled = _customerSettings.StreetAddressEnabled; model.StreetAddress2Enabled = _customerSettings.StreetAddress2Enabled; model.ZipPostalCodeEnabled = _customerSettings.ZipPostalCodeEnabled; @@ -765,6 +769,8 @@ public ActionResult Edit(CustomerModel model, bool continueEditing, FormCollecti _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.DateOfBirth, model.DateOfBirth); if (_customerSettings.CompanyEnabled) _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.Company, model.Company); + if (_customerSettings.CustomerNumberEnabled) + _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.Company, model.CustomerNumber); if (_customerSettings.StreetAddressEnabled) _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.StreetAddress, model.StreetAddress); if (_customerSettings.StreetAddress2Enabled) @@ -835,6 +841,7 @@ public ActionResult Edit(CustomerModel model, bool continueEditing, FormCollecti //form fields model.GenderEnabled = _customerSettings.GenderEnabled; model.DateOfBirthEnabled = _customerSettings.DateOfBirthEnabled; + model.CustomerNumberEnabled = _customerSettings.CustomerNumberEnabled; model.CompanyEnabled = _customerSettings.CompanyEnabled; model.StreetAddressEnabled = _customerSettings.StreetAddressEnabled; model.StreetAddress2Enabled = _customerSettings.StreetAddress2Enabled; diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Customers/CustomerModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Customers/CustomerModel.cs index 4cf4e2a992..72f0f78fb3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Customers/CustomerModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Customers/CustomerModel.cs @@ -62,6 +62,12 @@ public CustomerModel() [AllowHtml] public string Company { get; set; } + public bool CustomerNumberEnabled { get; set; } + [SmartResourceDisplayName("Account.Fields.CustomerNumber")] + [AllowHtml] + public string CustomerNumber { get; set; } + + public bool StreetAddressEnabled { get; set; } [SmartResourceDisplayName("Admin.Customers.Customers.Fields.StreetAddress")] [AllowHtml] diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Settings/CustomerUserSettingsModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Settings/CustomerUserSettingsModel.cs index 56f374c6a6..04c6344582 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Settings/CustomerUserSettingsModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Settings/CustomerUserSettingsModel.cs @@ -25,6 +25,9 @@ public partial class CustomerSettingsModel [SmartResourceDisplayName("Admin.Configuration.Settings.CustomerUser.UsernamesEnabled")] public bool UsernamesEnabled { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Settings.CustomerUser.CustomerNumberEnabled")] + public bool CustomerNumberEnabled { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Settings.CustomerUser.AllowUsersToChangeUsernames")] public bool AllowUsersToChangeUsernames { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Customer/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Customer/_CreateOrUpdate.cshtml index 5f224792df..6c72eae453 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Customer/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Customer/_CreateOrUpdate.cshtml @@ -200,6 +200,20 @@ } + + @if (Model.CustomerNumberEnabled) + { + + + @Html.SmartLabelFor(model => model.CustomerNumber) + + + @Html.EditorFor(model => model.CustomerNumber) + @Html.ValidationMessageFor(model => model.CustomerNumber) + + + } + @if (Model.StreetAddressEnabled) { diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/CustomerUser.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/CustomerUser.cshtml index 4fcee50d11..6acbacd0b7 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/CustomerUser.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/CustomerUser.cshtml @@ -77,6 +77,15 @@ @Html.ValidationMessageFor(model => model.CustomerSettings.UsernamesEnabled) + + + @Html.SmartLabelFor(model => model.CustomerSettings.CustomerNumberEnabled) + + + @Html.SettingEditorFor(model => model.CustomerSettings.CustomerNumberEnabled) + @Html.ValidationMessageFor(model => model.CustomerSettings.CustomerNumberEnabled) + + @Html.SmartLabelFor(model => model.CustomerSettings.AllowUsersToChangeUsernames) diff --git a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs index a7b162f8cd..e9716f4573 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs @@ -241,6 +241,7 @@ protected void PrepareCustomerInfoModel(CustomerInfoModel model, Customer custom model.StateProvinceId = customer.GetAttribute(SystemCustomerAttributeNames.StateProvinceId); model.Phone = customer.GetAttribute(SystemCustomerAttributeNames.Phone); model.Fax = customer.GetAttribute(SystemCustomerAttributeNames.Fax); + model.CustomerNumber = customer.GetAttribute(SystemCustomerAttributeNames.CustomerNumber); //newsletter var newsletter = _newsLetterSubscriptionService.GetNewsLetterSubscriptionByEmail(customer.Email, _storeContext.CurrentStore.Id); @@ -311,6 +312,7 @@ protected void PrepareCustomerInfoModel(CustomerInfoModel model, Customer custom model.AllowUsersToChangeUsernames = _customerSettings.AllowUsersToChangeUsernames; model.CheckUsernameAvailabilityEnabled = _customerSettings.CheckUsernameAvailabilityEnabled; model.SignatureEnabled = _forumSettings.ForumsEnabled && _forumSettings.SignaturesEnabled; + model.CustomerNumberEnabled = _customerSettings.CustomerNumberEnabled; //external authentication foreach (var ear in _openAuthenticationService.GetExternalIdentifiersFor(customer)) @@ -1002,9 +1004,18 @@ public ActionResult Info(CustomerInfoModel model) //form fields if (_customerSettings.GenderEnabled) + { _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.Gender, model.Gender); + } + + if (_customerSettings.CustomerNumberEnabled) + { + _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.CustomerNumber, model.CustomerNumber); + } + _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.FirstName, model.FirstName); _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.LastName, model.LastName); + if (_customerSettings.DateOfBirthEnabled) { DateTime? dateOfBirth = null; diff --git a/src/Presentation/SmartStore.Web/Models/Customer/CustomerInfoModel.cs b/src/Presentation/SmartStore.Web/Models/Customer/CustomerInfoModel.cs index ed98738e60..3b1f96f544 100644 --- a/src/Presentation/SmartStore.Web/Models/Customer/CustomerInfoModel.cs +++ b/src/Presentation/SmartStore.Web/Models/Customer/CustomerInfoModel.cs @@ -22,6 +22,11 @@ public CustomerInfoModel() [AllowHtml] public string Email { get; set; } + [SmartResourceDisplayName("Account.Fields.CustomerNumber")] + [AllowHtml] + public string CustomerNumber { get; set; } + public bool CustomerNumberEnabled { get; set; } + public bool CheckUsernameAvailabilityEnabled { get; set; } public bool AllowUsersToChangeUsernames { get; set; } public bool UsernamesEnabled { get; set; } diff --git a/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml b/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml index aeb7d5df5e..2e75e5f05e 100644 --- a/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml @@ -60,7 +60,6 @@
    @T("Account.YourPersonalDetails") - @*codehint: sm-edit begin*@ @if (Model.GenderEnabled) {
    @@ -134,6 +133,12 @@ }
    } + + @if(Model.CustomerNumberEnabled) + { + @Html.ControlGroupFor(model => model.CustomerNumber, required: false) + } +
    if (Model.AssociatedExternalAuthRecords.Count > 0) From 55d130406d16f38a6873ef1e59d3bc0856ebba3d Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 27 Jul 2015 12:18:26 +0200 Subject: [PATCH 0308/1256] Fixed paging issue in product list of a category (backend) --- .../Catalog/CategoryService.cs | 76 +++++++++++-------- .../Controllers/CategoryController.cs | 42 +++++----- 2 files changed, 69 insertions(+), 49 deletions(-) diff --git a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs index d563031d2b..d85423e343 100644 --- a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs @@ -400,24 +400,27 @@ public virtual IPagedList GetProductCategoriesByCategoryId(int if (categoryId == 0) return new PagedList(new List(), pageIndex, pageSize); - string key = string.Format(PRODUCTCATEGORIES_ALLBYCATEGORYID_KEY, showHidden, categoryId, pageIndex, pageSize, _workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id); + int storeId = _storeContext.CurrentStore.Id; + string key = string.Format(PRODUCTCATEGORIES_ALLBYCATEGORYID_KEY, showHidden, categoryId, pageIndex, pageSize, _workContext.CurrentCustomer.Id, storeId); + return _cacheManager.Get(key, () => { var query = from pc in _productCategoryRepository.Table join p in _productRepository.Table on pc.ProductId equals p.Id - where pc.CategoryId == categoryId && - !p.Deleted && - (showHidden || p.Published) - orderby pc.DisplayOrder + where pc.CategoryId == categoryId && !p.Deleted && (showHidden || p.Published) select pc; if (!showHidden) { - query = ApplyHiddenProductCategoriesFilter(query); - query = query.OrderBy(pc => pc.DisplayOrder); + query = ApplyHiddenProductCategoriesFilter(query, storeId); } + query = query + .OrderBy(pc => pc.DisplayOrder) + .ThenBy(pc => pc.Id); // required for paging! + var productCategories = new PagedList(query, pageIndex, pageSize); + return productCategories; }); } @@ -465,35 +468,46 @@ orderby pc.DisplayOrder }); } - protected virtual IQueryable ApplyHiddenProductCategoriesFilter(IQueryable query) + protected virtual IQueryable ApplyHiddenProductCategoriesFilter(IQueryable query, int storeId = 0) { + bool group = false; + //ACL (access control list) - var allowedCustomerRolesIds = _workContext.CurrentCustomer.CustomerRoles - .Where(cr => cr.Active).Select(cr => cr.Id).ToList(); + if (!QuerySettings.IgnoreAcl) + { + group = true; + var allowedCustomerRolesIds = _workContext.CurrentCustomer.CustomerRoles.Where(cr => cr.Active).Select(cr => cr.Id).ToList(); - query = from pc in query - join c in _categoryRepository.Table on pc.CategoryId equals c.Id - join acl in _aclRepository.Table - on new { c1 = c.Id, c2 = "Category" } equals new { c1 = acl.EntityId, c2 = acl.EntityName } into c_acl - from acl in c_acl.DefaultIfEmpty() - where !c.SubjectToAcl || allowedCustomerRolesIds.Contains(acl.CustomerRoleId) - select pc; + query = from pc in query + join c in _categoryRepository.Table on pc.CategoryId equals c.Id + join acl in _aclRepository.Table + on new { c1 = c.Id, c2 = "Category" } equals new { c1 = acl.EntityId, c2 = acl.EntityName } into c_acl + from acl in c_acl.DefaultIfEmpty() + where !c.SubjectToAcl || allowedCustomerRolesIds.Contains(acl.CustomerRoleId) + select pc; + } //Store mapping - var currentStoreId = _storeContext.CurrentStore.Id; - query = from pc in query - join c in _categoryRepository.Table on pc.CategoryId equals c.Id - join sm in _storeMappingRepository.Table - on new { c1 = c.Id, c2 = "Category" } equals new { c1 = sm.EntityId, c2 = sm.EntityName } into c_sm - from sm in c_sm.DefaultIfEmpty() - where !c.LimitedToStores || currentStoreId == sm.StoreId - select pc; - - //only distinct categories (group by ID) - query = from pc in query - group pc by pc.Id into pcGroup - orderby pcGroup.Key - select pcGroup.FirstOrDefault(); + if (!QuerySettings.IgnoreMultiStore && storeId > 0) + { + group = true; + query = from pc in query + join c in _categoryRepository.Table on pc.CategoryId equals c.Id + join sm in _storeMappingRepository.Table + on new { c1 = c.Id, c2 = "Category" } equals new { c1 = sm.EntityId, c2 = sm.EntityName } into c_sm + from sm in c_sm.DefaultIfEmpty() + where !c.LimitedToStores || storeId == sm.StoreId + select pc; + } + + if (group) + { + //only distinct categories (group by ID) + query = from pc in query + group pc by pc.Id into pcGroup + orderby pcGroup.Key + select pcGroup.FirstOrDefault(); + } return query; } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs index 94dddf36f5..6c24f4f22b 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/CategoryController.cs @@ -764,29 +764,35 @@ public ActionResult ProductList(GridCommand command, int categoryId) if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog)) return AccessDeniedView(); - var productCategories = _categoryService.GetProductCategoriesByCategoryId(categoryId, - command.Page - 1, command.PageSize, true); + var productCategories = _categoryService.GetProductCategoriesByCategoryId(categoryId, command.Page - 1, command.PageSize, true); + + var products = _productService.GetProductsByIds(productCategories.Select(x => x.ProductId).ToArray()); var model = new GridModel { - Data = productCategories - .Select(x => + Data = productCategories.Select(x => { - var product = _productService.GetProductById(x.ProductId); + var productModel = new CategoryModel.CategoryProductModel + { + Id = x.Id, + CategoryId = x.CategoryId, + ProductId = x.ProductId, + IsFeaturedProduct = x.IsFeaturedProduct, + DisplayOrder1 = x.DisplayOrder + }; - return new CategoryModel.CategoryProductModel() - { - Id = x.Id, - CategoryId = x.CategoryId, - ProductId = x.ProductId, - ProductName = product.Name, - Sku = product.Sku, - ProductTypeName = product.GetProductTypeLabel(_localizationService), - ProductTypeLabelHint = product.ProductTypeLabelHint, - Published = product.Published, - IsFeaturedProduct = x.IsFeaturedProduct, - DisplayOrder1 = x.DisplayOrder - }; + var product = products.FirstOrDefault(y => y.Id == x.ProductId); + + if (product != null) + { + productModel.ProductName = product.Name; + productModel.Sku = product.Sku; + productModel.ProductTypeName = product.GetProductTypeLabel(_localizationService); + productModel.ProductTypeLabelHint = product.ProductTypeLabelHint; + productModel.Published = product.Published; + } + + return productModel; }), Total = productCategories.TotalCount }; From a0a4d1a4fdcfda5598ec56913793b90228b9c9d9 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 27 Jul 2015 12:44:18 +0200 Subject: [PATCH 0309/1256] Implemented function to show widget zone with a filter instead of widget --- .../DependencyRegistrar.cs | 3 +- .../Filters/WidgetZoneFilter.cs | 123 ++++++++++ .../SmartStore.DevTools.csproj | 2 +- .../Views/DevTools/WidgetZone.cshtml | 2 +- .../Widgets/ShowZonesWidget.cs | 220 ------------------ 5 files changed, 127 insertions(+), 223 deletions(-) create mode 100644 src/Plugins/SmartStore.DevTools/Filters/WidgetZoneFilter.cs delete mode 100644 src/Plugins/SmartStore.DevTools/Widgets/ShowZonesWidget.cs diff --git a/src/Plugins/SmartStore.DevTools/DependencyRegistrar.cs b/src/Plugins/SmartStore.DevTools/DependencyRegistrar.cs index e562ef1d9f..91f0a57419 100644 --- a/src/Plugins/SmartStore.DevTools/DependencyRegistrar.cs +++ b/src/Plugins/SmartStore.DevTools/DependencyRegistrar.cs @@ -26,7 +26,8 @@ public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, b { // intercept ALL public store controller actions builder.RegisterType().AsActionFilterFor(); - + builder.RegisterType().AsActionFilterFor(); + //// intercept CatalogController's Product action //builder.RegisterType().AsResultFilterFor(x => x.Product(default(int), default(string))).InstancePerRequest(); //builder.RegisterType().AsActionFilterFor().InstancePerRequest(); diff --git a/src/Plugins/SmartStore.DevTools/Filters/WidgetZoneFilter.cs b/src/Plugins/SmartStore.DevTools/Filters/WidgetZoneFilter.cs new file mode 100644 index 0000000000..253fdd0b60 --- /dev/null +++ b/src/Plugins/SmartStore.DevTools/Filters/WidgetZoneFilter.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using System.Web.Mvc; +using SmartStore.Core.Logging; +using SmartStore.Core.Localization; +using SmartStore.DevTools.Services; +using SmartStore.Core; +using SmartStore.Services; +using SmartStore.Services.Customers; +using SmartStore.Web.Framework.UI; +using SmartStore.Utilities; +using System.IO; + +namespace SmartStore.DevTools.Filters +{ + public class WidgetZoneFilter : IActionFilter, IResultFilter + { + private readonly ICommonServices _services; + private readonly Lazy _widgetProvider; + private readonly ProfilerSettings _profilerSettings; + + public WidgetZoneFilter( + ICommonServices services, + Lazy widgetProvider, + ProfilerSettings profilerSettings) + { + this._services = services; + this._widgetProvider = widgetProvider; + this._profilerSettings = profilerSettings; + } + + public void OnActionExecuting(ActionExecutingContext filterContext) + { + if (!_profilerSettings.DisplayWidgetZones) + return; + } + + public void OnActionExecuted(ActionExecutedContext filterContext) + { + if (!_profilerSettings.DisplayWidgetZones) + return; + } + + public void OnResultExecuting(ResultExecutingContext filterContext) + { + if (!_profilerSettings.DisplayWidgetZones) + return; + + // should only run on a full view rendering result + var result = filterContext.Result as ViewResultBase; + if (result == null) + { + return; + } + + if (!this.ShouldRender(filterContext.HttpContext)) + { + return; + } + + if (!filterContext.IsChildAction) + { + _widgetProvider.Value.RegisterAction( + new Wildcard("*"), + "WidgetZone", + "DevTools", + new { area = "SmartStore.DevTools" }); + } + + var viewName = result.ViewName; + + if (viewName.IsEmpty()) + { + string action = (filterContext.RouteData.Values["action"] as string).EmptyNull(); + viewName = action; + + if (action == "WidgetsByZone") + { + var model = result.Model as WidgetZoneModel; + + filterContext.Result = new ViewResult + { + ViewName = "~/Plugins/SmartStore.DevTools/Views/DevTools/WidgetZone.cshtml", + }; + filterContext.RouteData.Values.Add("widgetZone", model.WidgetZone); + } + } + } + + public void OnResultExecuted(ResultExecutedContext filterContext) + { + if (!_profilerSettings.DisplayWidgetZones) + return; + + // should only run on a full view rendering result + if (!(filterContext.Result is ViewResultBase)) + { + return; + } + + if (!this.ShouldRender(filterContext.HttpContext)) + { + return; + } + } + + private bool ShouldRender(HttpContextBase ctx) + { + if (!_services.WorkContext.CurrentCustomer.IsAdmin()) + { + return ctx.Request.IsLocal; + } + + return true; + } + + } +} diff --git a/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj b/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj index 2db1f156da..78718fe893 100644 --- a/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj +++ b/src/Plugins/SmartStore.DevTools/SmartStore.DevTools.csproj @@ -144,6 +144,7 @@ + @@ -155,7 +156,6 @@ - diff --git a/src/Plugins/SmartStore.DevTools/Views/DevTools/WidgetZone.cshtml b/src/Plugins/SmartStore.DevTools/Views/DevTools/WidgetZone.cshtml index 2dcf0c42a0..222fe683e0 100644 --- a/src/Plugins/SmartStore.DevTools/Views/DevTools/WidgetZone.cshtml +++ b/src/Plugins/SmartStore.DevTools/Views/DevTools/WidgetZone.cshtml @@ -1,3 +1,3 @@ - + Widget Zone diff --git a/src/Plugins/SmartStore.DevTools/Widgets/ShowZonesWidget.cs b/src/Plugins/SmartStore.DevTools/Widgets/ShowZonesWidget.cs deleted file mode 100644 index f9834ae0d6..0000000000 --- a/src/Plugins/SmartStore.DevTools/Widgets/ShowZonesWidget.cs +++ /dev/null @@ -1,220 +0,0 @@ -using System.Collections.Generic; -using System.Web; -using System.Web.Routing; -using SmartStore.Core.Domain.Customers; -using SmartStore.Core.Plugins; -using SmartStore.Services; -using SmartStore.Services.Cms; -using SmartStore.Services.Common; - -namespace SmartStore.DevTools.Widgets -{ - [SystemName("Widgets.ShowZones")] - [FriendlyName("Show Zones")] - public class ShowZonesWidget : IWidget - { - private readonly ICommonServices _services; - private readonly HttpContextBase _httpContext; - - public ShowZonesWidget(ICommonServices services, - HttpContextBase httpContext, - IGenericAttributeService genericAttributeService) - { - _services = services; - _httpContext = httpContext; - } - - public IList GetWidgetZones() - { - return new List() - { - //Blogs - "blogpost_page_before_body", "mobile_blogpost_page_before_body", - "blogpost_page_before_comments", "mobile_blogpost_page_before_comments", - "blogpost_page_inside_comment", "mobile_blogpost_page_inside_comment", - "blogpost_page_after_comments", "mobile_blogpost_page_after_comments", - "bloglist_page_before_posts", "mobile_bloglist_page_before_posts", - "bloglist_page_inside_post", "mobile_bloglist_page_inside_post", - "bloglist_page_after_posts", "mobile_bloglist_page_after_posts", - - //Categories - "categorydetails_after_breadcrumb", - "categorydetails_top", "mobile_categorydetails_top", - "categorydetails_before_subcategories", "mobile_categorydetails_before_subcategories", - "categorydetails_before_featured_products", "mobile_categorydetails_before_featured_products", - "categorydetails_after_featured_products", - "categorydetails_before_product_list", "mobile_categorydetails_before_product_list", - "categorydetails_bottom", "mobile_categorydetails_bottom", - "categorydetails_before_filters", - - //Products - "productbox_add_info", - "productsbytag_before_product_list", - "productreviews_page_inside_review", - "productdetails_overview_top", - "productdetails_overview_bottom", - "productsbytag_top", "mobile_productsbytag_top", - "productsbytag_bottom", "mobile_productsbytag_bottom", - "productdetails_add_info", "mobile_productdetails_add_info", - "productdetails_top", "mobile_productdetails_top", - "productdetails_before_pictures", "mobile_productdetails_before_pictures", - "productdetails_after_pictures", "mobile_productdetails_after_pictures", - "productdetails_bottom", "mobile_productdetails_bottom", - - //Navigation - "productbreadcrumb_before", - "productbreadcrumb_after", - "header_menu_before", - "header_menu_after", - "megamenu_before_first_item", - "megamenu_after_last_item", - "account_dropdown_before", - "account_dropdown_after", - "header_links_before", "mobile_header_links_before", - "header_links_after", "mobile_header_links_after", - "infoblock_before", "mobile_infoblock_before", - "infoblock_after", "mobile_infoblock_after", - "account_navigation_before", "mobile_account_navigation_before", - "account_navigation_after", "mobile_account_navigation_after", - - //Checkout - "checkout_progress_before", - "checkout_progress_after", - "checkout_billing_address_top", "mobile_checkout_billing_address_top", - "checkout_billing_address_middle", "mobile_checkout_billing_address_middle", - "checkout_billing_address_bottom", "mobile_checkout_billing_address_bottom", - "checkout_completed_top", "mobile_checkout_completed_top", - "checkout_completed_bottom", "mobile_checkout_completed_bottom", - "checkout_confirm_top", "mobile_checkout_confirm_top", - "checkout_confirm_before_summary", "mobile_checkout_confirm_before_summary", - "checkout_confirm_bottom", "mobile_checkout_confirm_bottom", - "checkout_payment_method_top", "mobile_checkout_payment_method_top", - "checkout_payment_method_bottom", "mobile_checkout_payment_method_bottom", - "checkout_shipping_address_top", "mobile_checkout_shipping_address_top", - "checkout_shipping_address_middle", "mobile_checkout_shipping_address_middle", - "checkout_shipping_address_bottom", "mobile_checkout_shipping_address_bottom", - "checkout_shipping_method_top", "mobile_checkout_shipping_method_top", - "checkout_shipping_method_bottom", "mobile_checkout_shipping_method_bottom", - - //PDF - "invoice_footer_before", - "invoice_footer_after", - "invoice_header_before", - "invoice_header_right", - "invoice_header_after", - "invoice_top", - "invoice_orderinfo_top", - "invoice_orderinfotable_after", - "invoice_orderinfo_bottom", - "invoice_lines_before", - "invoice_checkoutattributes_before", - "invoice_ordertotals_before", - "invoice_ordernotes_before", - "invoice_bottom", - "pdfcatalog_cover_top", - "pdfcatalog_cover_logo_after", - "pdfcatalog_cover_storename_after", - "pdfcatalog_productdetail_top", - "pdfcatalog_productdetail_fulldescription_before", - "pdfcatalog_productdetail_picture_before", - "pdfcatalog_productdetail_specificationattributes_before", - "pdfcatalog_productdetail_bundleditems_before", - "pdfcatalog_productdetail_associatedproducts_before", - - //Manufacturer - "manufacturerdetails_top", "mobile_manufacturerdetails_top", - "manufacturerdetails_before_featured_products", "mobile_manufacturerdetails_before_featured_products", - "manufacturerdetails_after_featured_products", - "manufacturerdetails_before_filters", - "manufacturerdetails_before_product_list", "mobile_manufacturerdetails_before_product_list", - "manufacturerdetails_bottom", "mobile_manufacturerdetails_bottom", - - //Misc - "compareproducts_row", "mobile_compareproducts_row", - "productsearch_page_advanced", - "productsearch_page_basic", - "productsearch_page_advanced", - "searchbox", "mobile_searchbox", - "footer", "mobile_footer", - "contactus_top", "mobile_contactus_top", - "contactus_bottom", "mobile_contactus_bottom", - "productreviews_page_top", "mobile_productreviews_page_top", - "productreviews_page_inside_review", "mobile_productreviews_page_inside_review", - "productreviews_page_bottom", "mobile_productreviews_page_bottom", - "profile_page_info_userdetails", "mobile_profile_page_info_userdetails", - "profile_page_info_userstats", "mobile_profile_page_info_userstats", - "notifications", "mobile_notifications", - "shipmentdetails_top", - "shipmentdetails_orderinfo_top", - "shipmentdetails_orderinfotable_after", - "shipmentdetails_orderinfo_bottom", - "shipmentdetails_lines_before", - - //Global - "home_page_top", "mobile_home_page_top", - "home_page_bottom", "mobile_home_page_bottom", - "main_column_before", - "main_column_after", - "left_side_column_before", - "left_side_column_after_category_navigation", - "left_side_column_after_manufacturer_navigation", - "left_side_column_after_tags", - "left_side_column_after_info", - "left_side_column_after_poll", - "left_side_column_after", - "right_side_column_before", - "right_side_column_after_recentlyviewed", - "right_side_column_after_poll", - "right_side_column_after", - "body_start_html_tag_after", "mobile_body_start_html_tag_after", - "content_before", "mobile_content_before", - "content_after", "mobile_content_after", - "body_end_html_tag_before", "mobile_body_end_html_tag_after", - "head_html_tag", "mobile_head_html_tag", - "admin_navbar_before", - "admin_navbar_after", - "admin_breadcrumb", - "admin_content_before", - "admin_content_after", - "admin_menu_before", - - //News - "newslist_page_before_items", "mobile_newslist_page_before_items", - "newslist_page_inside_item", "mobile_newslist_page_inside_item", - "newslist_page_after_items", "mobile_newslist_page_after_items", - "newsitem_page_before_body", "mobile_newsitem_page_before_body", - "newsitem_page_before_comments", "mobile_newsitem_page_before_comments", - "newsitem_page_inside_comment", "mobile_newsitem_page_inside_comment", - "newsitem_page_after_comments", "mobile_newsitem_page_after_comments", - - //Orders - "orderdetails_page_top", "mobile_orderdetails_page_top", - "orderdetails_page_overview", "mobile_orderdetails_page_overview", - "orderdetails_page_beforeproducts", "mobile_orderdetails_page_beforeproducts", - "orderdetails_page_afterproducts", "mobile_orderdetails_page_afterproducts", - "orderdetails_page_aftertotal", "mobile_orderdetails_page_aftertotal", - "orderdetails_page_bottom", "mobile_orderdetails_page_bottom", - - //Shopping Cart - "mini_shopping_cart_bottom", - "order_summary_content_before", "mobile_order_summary_content_before", - "order_summary_content_totals_left", "mobile_order_summary_content_totals_left", - "order_summary_content_deals", "mobile_order_summary_content_deals", - "order_summary_content_totals_bottom", "mobile_order_summary_content_totals_bottom", - "order_summary_content_after", "mobile_order_summary_content_after" - }; - } - - public void GetDisplayWidgetRoute(string widgetZone, object model, int storeId, out string actionName, out string controllerName, out RouteValueDictionary routeValues) - { - controllerName = "DevTools"; - actionName = "WidgetZone"; - routeValues = new RouteValueDictionary() - { - { "Namespaces", "SmartStore.DevTools.Controllers" }, - { "area", "SmartStore.DevTools" }, - { "widgetZone", widgetZone } - }; - } - } -} \ No newline at end of file From 69853f2ddb015053973d131c189581b3d0e72ad7 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 27 Jul 2015 15:46:29 +0200 Subject: [PATCH 0310/1256] Reduce database round trips initiated by price calculation --- changelog.md | 1 + src/Libraries/SmartStore.Core/PagedList`T.cs | 7 ++- .../Catalog/CategoryService.cs | 29 ++++++++++++ .../Catalog/ICategoryService.cs | 10 +++++ .../Catalog/IPriceCalculationService.cs | 4 +- .../Catalog/PriceCalculationContext.cs | 19 +++++++- .../Catalog/PriceCalculationService.cs | 45 ++++++++----------- 7 files changed, 85 insertions(+), 30 deletions(-) diff --git a/changelog.md b/changelog.md index f1153fdf11..999f0e404b 100644 --- a/changelog.md +++ b/changelog.md @@ -28,6 +28,7 @@ * #709 News feed produced invalid RSS feed. Added content:encoded. Added maximum news age setting for feed export. * #735 Include SKUs of attribute combinations when filtering the backend product list * Filter for homepage and published\unpublished products in backend product list +* Reduce database round trips initiated by price calculation ### Bugfixes * #523 Redirecting to payment provider performed by core instead of plugin diff --git a/src/Libraries/SmartStore.Core/PagedList`T.cs b/src/Libraries/SmartStore.Core/PagedList`T.cs index 63db21a70d..7d5c66a94b 100644 --- a/src/Libraries/SmartStore.Core/PagedList`T.cs +++ b/src/Libraries/SmartStore.Core/PagedList`T.cs @@ -19,7 +19,11 @@ public class PagedList : List, IPagedList public PagedList(IQueryable source, int pageIndex, int pageSize) { Guard.ArgumentNotNull(source, "source"); - Init(source.Skip(pageIndex * pageSize).Take(pageSize), pageIndex, pageSize, source.Count()); + + if (pageIndex == 0 && pageSize == int.MaxValue) // avoid unnecessary SQL + Init(source, pageIndex, pageSize, source.Count()); + else + Init(source.Skip(pageIndex * pageSize).Take(pageSize), pageIndex, pageSize, source.Count()); } /// @@ -31,6 +35,7 @@ public PagedList(IQueryable source, int pageIndex, int pageSize) public PagedList(IList source, int pageIndex, int pageSize) { Guard.ArgumentNotNull(source, "source"); + Init(source.Skip(pageIndex * pageSize).Take(pageSize), pageIndex, pageSize, source.Count); } diff --git a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs index d85423e343..ea0bc201ae 100644 --- a/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/CategoryService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using SmartStore.Collections; using SmartStore.Core; using SmartStore.Core.Caching; using SmartStore.Core.Data; @@ -468,6 +469,34 @@ orderby pc.DisplayOrder }); } + public virtual Multimap GetProductCategoriesByProductIds(int[] productIds, bool? hasDiscountsApplied = null, bool showHidden = false) + { + Guard.ArgumentNotNull(() => productIds); + + var query = + from pc in _productCategoryRepository.TableUntracked.Expand(x => x.Category) + join c in _categoryRepository.Table on pc.CategoryId equals c.Id + where productIds.Contains(pc.ProductId) && !c.Deleted && (showHidden || c.Published) + orderby pc.DisplayOrder + select pc; + + if (hasDiscountsApplied.HasValue) + { + query = query.Where(x => x.Category.HasDiscountsApplied == hasDiscountsApplied); + } + + var list = query.ToList(); + + if (!showHidden) + { + list = list.Where(x => _aclService.Authorize(x.Category) && _storeMappingService.Authorize(x.Category)).ToList(); + } + + var map = list.ToMultimap(x => x.ProductId, x => x); + + return map; + } + protected virtual IQueryable ApplyHiddenProductCategoriesFilter(IQueryable query, int storeId = 0) { bool group = false; diff --git a/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs b/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs index 6b7650d69b..209507a66d 100644 --- a/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/ICategoryService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using SmartStore.Collections; using SmartStore.Core; using SmartStore.Core.Domain.Catalog; @@ -96,6 +97,15 @@ IPagedList GetProductCategoriesByCategoryId(int categoryId, /// Product category mapping collection IList GetProductCategoriesByProductId(int productId, bool showHidden = false); + /// + /// Gets product category mappings + /// + /// Product identifiers + /// A value indicating whether to filter categories with applied discounts + /// A value indicating whether to show hidden records + /// Map with product category mappings + Multimap GetProductCategoriesByProductIds(int[] productIds, bool? hasDiscountsApplied = null, bool showHidden = false); + /// /// Gets a product category mapping /// diff --git a/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs index 090a301e8d..e3c7b9d5a6 100644 --- a/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs @@ -181,13 +181,15 @@ decimal GetDiscountAmount(Product product, /// Product quantity /// Applied discount /// A product bundle item + /// Object with cargo data for better performance /// Discount amount decimal GetDiscountAmount(Product product, Customer customer, decimal additionalCharge, int quantity, out Discount appliedDiscount, - ProductBundleItemData bundleItem = null); + ProductBundleItemData bundleItem = null, + PriceCalculationContext context = null); /// diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationContext.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationContext.cs index 0f594e6fdc..ee316d42c6 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationContext.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationContext.cs @@ -17,15 +17,18 @@ public class PriceCalculationContext private Func> _funcAttributes; private Func> _funcAttributeCombinations; private Func> _funcTierPrices; + private Func> _funcProductCategories; private LazyMultimap _attributes; private LazyMultimap _attributeCombinations; private LazyMultimap _tierPrices; + private LazyMultimap _productCategories; public PriceCalculationContext(IEnumerable products, Func> attributes, Func> attributeCombinations, - Func> tierPrices) + Func> tierPrices, + Func> productCategories) { if (products == null) { @@ -41,6 +44,7 @@ public PriceCalculationContext(IEnumerable products, _funcAttributes = attributes; _funcAttributeCombinations = attributeCombinations; _funcTierPrices = tierPrices; + _funcProductCategories = productCategories; } public LazyMultimap Attributes @@ -79,11 +83,24 @@ public LazyMultimap TierPrices } } + public LazyMultimap ProductCategories + { + get + { + if (_productCategories == null) + { + _productCategories = new LazyMultimap(keys => _funcProductCategories(keys), _productIds); + } + return _productCategories; + } + } + public void Collect(IEnumerable productIds) { Attributes.Collect(productIds); AttributeCombinations.Collect(productIds); TierPrices.Collect(productIds); + ProductCategories.Collect(productIds); } } } diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index 7cff4b8abb..9fef3cf937 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -1,9 +1,9 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Web; -using SmartStore.Collections; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Discounts; @@ -65,7 +65,7 @@ public PriceCalculationService( /// Product /// Customer /// Discounts - protected virtual IList GetAllowedDiscounts(Product product, Customer customer) + protected virtual IList GetAllowedDiscounts(Product product, Customer customer, PriceCalculationContext context = null) { var result = new List(); if (_catalogSettings.IgnoreDiscounts) @@ -86,7 +86,13 @@ protected virtual IList GetAllowedDiscounts(Product product, Customer //performance optimization. load all category discounts just to ensure that we have at least one if (_discountService.GetAllDiscounts(DiscountType.AssignedToCategories).Any()) { - var productCategories = _categoryService.GetProductCategoriesByProductId(product.Id); + IEnumerable productCategories = null; + + if (context == null) + productCategories = _categoryService.GetProductCategoriesByProductId(product.Id); + else + productCategories = context.ProductCategories.Load(product.Id); + if (productCategories != null) { foreach (var productCategory in productCategories) @@ -272,7 +278,8 @@ public virtual PriceCalculationContext CreatePriceCalculationContext(IEnumerable var context = new PriceCalculationContext(products, x => _productAttributeService.GetProductVariantAttributesByProductIds(x, null), x => _productAttributeService.GetProductVariantAttributeCombinations(x), - x => _productService.GetTierPrices(x, _services.WorkContext.CurrentCustomer, _services.StoreContext.CurrentStore.Id) + x => _productService.GetTierPrices(x, _services.WorkContext.CurrentCustomer, _services.StoreContext.CurrentStore.Id), + x => _categoryService.GetProductCategoriesByProductIds(x, true) ); return context; @@ -385,7 +392,7 @@ public virtual decimal GetFinalPrice( if (includeDiscounts) { Discount appliedDiscount = null; - decimal discountAmount = GetDiscountAmount(product, customer, additionalCharge, quantity, out appliedDiscount, bundleItem); + decimal discountAmount = GetDiscountAmount(product, customer, additionalCharge, quantity, out appliedDiscount, bundleItem, context); result = result + additionalCharge - discountAmount; } else @@ -471,13 +478,6 @@ public virtual decimal GetLowestPrice(Product product, PriceCalculationContext c if (!displayFromMessage && product.HasTierPrices && !isBundlePerItemPricing) { - //var tierPrices = product.TierPrices - // .OrderBy(tp => tp.Quantity) - // .FilterByStore(_services.StoreContext.CurrentStore.Id) - // .FilterForCustomer(_services.WorkContext.CurrentCustomer) - // .ToList() - // .RemoveDuplicatedQuantities(); - var tierPrices = context.TierPrices.Load(product.Id); displayFromMessage = (tierPrices.Count > 0 && !(tierPrices.Count == 1 && tierPrices.First().Quantity <= 1)); @@ -649,23 +649,14 @@ public virtual decimal GetDiscountAmount(Product product, return GetDiscountAmount(product, customer, additionalCharge, 1, out appliedDiscount); } - /// - /// Gets discount amount - /// - /// Product - /// The customer - /// Additional charge - /// Product quantity - /// Applied discount - /// A product bundle item - /// Discount amount public virtual decimal GetDiscountAmount( Product product, Customer customer, decimal additionalCharge, int quantity, out Discount appliedDiscount, - ProductBundleItemData bundleItem = null) + ProductBundleItemData bundleItem = null, + PriceCalculationContext context = null) { appliedDiscount = null; decimal appliedDiscountAmount = decimal.Zero; @@ -675,14 +666,14 @@ public virtual decimal GetDiscountAmount( { if (bundleItem.Item.Discount.HasValue && bundleItem.Item.BundleProduct.BundlePerItemPricing) { - appliedDiscount = new Discount() + appliedDiscount = new Discount { UsePercentage = bundleItem.Item.DiscountPercentage, DiscountPercentage = bundleItem.Item.Discount.Value, DiscountAmount = bundleItem.Item.Discount.Value }; - finalPriceWithoutDiscount = GetFinalPrice(product, customer, additionalCharge, false, quantity, bundleItem); + finalPriceWithoutDiscount = GetFinalPrice(product, customer, additionalCharge, false, quantity, bundleItem, context); appliedDiscountAmount = appliedDiscount.GetDiscountAmount(finalPriceWithoutDiscount); } } @@ -694,13 +685,13 @@ public virtual decimal GetDiscountAmount( return appliedDiscountAmount; } - var allowedDiscounts = GetAllowedDiscounts(product, customer); + var allowedDiscounts = GetAllowedDiscounts(product, customer, context); if (allowedDiscounts.Count == 0) { return appliedDiscountAmount; } - finalPriceWithoutDiscount = GetFinalPrice(product, customer, additionalCharge, false, quantity, bundleItem); + finalPriceWithoutDiscount = GetFinalPrice(product, customer, additionalCharge, false, quantity, bundleItem, context); appliedDiscount = allowedDiscounts.GetPreferredDiscount(finalPriceWithoutDiscount); if (appliedDiscount != null) From f0daa77c8d6be0004542ac111482b6317247d381 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 27 Jul 2015 20:15:21 +0200 Subject: [PATCH 0311/1256] Web-API: requests always led to new guest customers though HMAC authentication. Core is now informed through new principal about the authentication. IWorkContext.set_CurrentCustomer useless in this scenario. --- .../Collections/LazyMultimap.cs | 2 +- .../SmartStore.Core/SmartNetPrincipal.cs | 29 +++++++++++++++ .../SmartStore.Core/SmartStore.Core.csproj | 1 + .../FormsAuthenticationService.cs | 28 ++++++++++----- .../Catalog/PriceCalculationService.cs | 15 ++------ .../WebApi/Security/HmacAuthentication.cs | 3 +- .../Security/WebApiAuthenticateAttribute.cs | 36 +++++++++---------- .../WebApi/WebApiCore.cs | 4 +-- 8 files changed, 75 insertions(+), 43 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/SmartNetPrincipal.cs diff --git a/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs b/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs index 803ff63ded..9aa3d30a8c 100644 --- a/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs +++ b/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs @@ -46,7 +46,7 @@ protected virtual void Load(IEnumerable keys) { ++_roundTripCount; - Debug.WriteLine("Round trip {0} of {1}: {2}", _roundTripCount, typeof(T).Name, string.Join(",", loadKeys.OrderBy(x => x))); + //Debug.WriteLine("Round trip {0} of {1}: {2}", _roundTripCount, typeof(T).Name, string.Join(",", loadKeys.OrderBy(x => x))); var items = _load(loadKeys); diff --git a/src/Libraries/SmartStore.Core/SmartNetPrincipal.cs b/src/Libraries/SmartStore.Core/SmartNetPrincipal.cs new file mode 100644 index 0000000000..0fae852141 --- /dev/null +++ b/src/Libraries/SmartStore.Core/SmartNetPrincipal.cs @@ -0,0 +1,29 @@ +using System.Security.Principal; +using System.Web.Security; +using SmartStore.Core.Domain.Customers; + +namespace SmartStore.Core +{ + public interface ISmartNetPrincipal : IPrincipal + { + int CustomerId { get; set; } + } + + + public class SmartNetPrincipal : ISmartNetPrincipal + { + public SmartNetPrincipal(Customer customer, string type) + { + this.Identity = new GenericIdentity(customer.Username, type); + this.CustomerId = customer.Id; + } + + public bool IsInRole(string role) + { + return Identity != null && Identity.IsAuthenticated && role.HasValue() && Roles.IsUserInRole(Identity.Name, role); + } + + public IIdentity Identity { get; private set; } + public int CustomerId { get; set; } + } +} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 8a063d5b66..f1c102b6d5 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -357,6 +357,7 @@ + diff --git a/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs b/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs index c43d075957..657f93cd69 100644 --- a/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs +++ b/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs @@ -1,6 +1,7 @@ using System; using System.Web; using System.Web.Security; +using SmartStore.Core; using SmartStore.Core.Domain.Customers; using SmartStore.Services.Customers; @@ -77,18 +78,29 @@ public virtual Customer GetAuthenticatedCustomer() if (_cachedCustomer != null) return _cachedCustomer; - if (_httpContext == null || - _httpContext.Request == null || - !_httpContext.Request.IsAuthenticated || - !(_httpContext.User.Identity is FormsIdentity)) + if (_httpContext == null || _httpContext.Request == null || !_httpContext.Request.IsAuthenticated) { return null; } - var formsIdentity = (FormsIdentity)_httpContext.User.Identity; - var customer = GetAuthenticatedCustomerFromTicket(formsIdentity.Ticket); - if (customer != null && customer.Active && !customer.Deleted && customer.IsRegistered()) - _cachedCustomer = customer; + Customer customer = null; + FormsIdentity formsIdentity = null; + SmartNetPrincipal smartNetPrincipal = null; + + if ((formsIdentity = _httpContext.User.Identity as FormsIdentity) != null) + { + customer = GetAuthenticatedCustomerFromTicket(formsIdentity.Ticket); + } + else if ((smartNetPrincipal = _httpContext.User as SmartNetPrincipal) != null) + { + customer = _customerService.GetCustomerById(smartNetPrincipal.CustomerId); + } + + if (customer != null && customer.Active && !customer.Deleted && customer.IsRegistered()) + { + _cachedCustomer = customer; + } + return _cachedCustomer; } diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs index 9fef3cf937..082bc2ad23 100644 --- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs +++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs @@ -210,15 +210,6 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC } } - //if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) - // defaultValue.IsPreSelected = true; - - //if (defaultValue == null) - // defaultValue = pvaValues.FirstOrDefault(x => x.IsPreSelected); - - //if (defaultValue != null) - // selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); - // value pre-selected by a bundle item filter discards the default pre-selection if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) { @@ -448,6 +439,8 @@ public virtual decimal GetLowestPrice(Product product, PriceCalculationContext c if (product.ProductType == ProductType.GroupedProduct) throw Error.InvalidOperation("Choose the other override for products of type grouped product."); + // note: attribute price adjustments were never regarded here cause of many reasons + if (context == null) context = CreatePriceCalculationContext(); @@ -455,9 +448,7 @@ public virtual decimal GetLowestPrice(Product product, PriceCalculationContext c displayFromMessage = isBundlePerItemPricing; - // TODO(?): attribute price adjustments were not regarded here cause of performance - - decimal lowestPrice = GetFinalPrice(product, null, _services.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue, null, context); + var lowestPrice = GetFinalPrice(product, null, _services.WorkContext.CurrentCustomer, decimal.Zero, true, int.MaxValue, null, context); if (product.LowestAttributeCombinationPrice.HasValue && product.LowestAttributeCombinationPrice.Value < lowestPrice) { diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/Security/HmacAuthentication.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/Security/HmacAuthentication.cs index 0cdab6e3c7..b661d994ec 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/Security/HmacAuthentication.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/Security/HmacAuthentication.cs @@ -150,6 +150,7 @@ public enum HmacResult : int UserUnknown, UserDisabled, UserInvalid, - UserHasNoPermission + UserHasNoPermission, + UserIsInactive } } diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs index 06f25a322e..00dc7563de 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/Security/WebApiAuthenticateAttribute.cs @@ -21,20 +21,11 @@ namespace SmartStore.Web.Framework.WebApi.Security [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] public class WebApiAuthenticateAttribute : System.Web.Http.AuthorizeAttribute { - private readonly IWorkContext _workContext; - private readonly IPermissionService _permissionService; - protected HmacAuthentication _hmac = new HmacAuthentication(); - public WebApiAuthenticateAttribute() - { - var engine = EngineContext.Current; - - _workContext = engine.Resolve(); - _permissionService = engine.Resolve(); - } - - /// The system name of the permission + /// + /// The system name of the permission + /// public string Permission { get; set; } protected string CreateContentMd5Hash(HttpRequestMessage request) @@ -54,14 +45,18 @@ protected virtual bool HasPermission(HttpActionContext actionContext, Customer c try { - if (Permission.HasValue() && _permissionService.GetPermissionRecordBySystemName(Permission) != null) + if (Permission.HasValue()) { - result = _permissionService.Authorize(Permission, customer); + var permissionService = EngineContext.Current.Resolve(); + + if (permissionService.GetPermissionRecordBySystemName(Permission) != null) + { + result = permissionService.Authorize(Permission, customer); + } } } - catch (Exception) - { - } + catch { } + return result; } protected virtual void LogUnauthorized(HttpActionContext actionContext, HmacResult result, Customer customer) @@ -177,6 +172,9 @@ protected virtual HmacResult IsAuthenticated(HttpActionContext actionContext, Da if (customer == null) return HmacResult.UserUnknown; + if (!customer.Active || customer.Deleted) + return HmacResult.UserIsInactive; + if (!HasPermission(actionContext, customer)) return HmacResult.UserHasNoPermission; @@ -206,13 +204,15 @@ public override void OnAuthorization(HttpActionContext actionContext) if (result == HmacResult.Success) { - _workContext.CurrentCustomer = customer; + // inform core about the authentication. note you cannot use IWorkContext.set_CurrentCustomer here. + HttpContext.Current.User = new SmartNetPrincipal(customer, HmacAuthentication.Scheme1); var response = HttpContext.Current.Response; response.AddHeader(WebApiGlobal.Header.Version, cacheControllingData.Version); response.AddHeader(WebApiGlobal.Header.MaxTop, WebApiGlobal.MaxTop.ToString()); response.AddHeader(WebApiGlobal.Header.Date, now.ToString("o")); + response.AddHeader(WebApiGlobal.Header.CustomerId, customer.Id.ToString()); response.Cache.SetCacheability(HttpCacheability.NoCache); } diff --git a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCore.cs b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCore.cs index 9f97de2d1b..7d9db0fd44 100644 --- a/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCore.cs +++ b/src/Presentation/SmartStore.Web.Framework/WebApi/WebApiCore.cs @@ -1,5 +1,4 @@ using System.Text; -using Microsoft.Data.OData; namespace SmartStore.Web.Framework.WebApi { @@ -13,8 +12,6 @@ public static class WebApiGlobal public static string MostRecentOdataPath { get { return "odata/v1"; } } public static string PluginSystemName { get { return "SmartStore.WebApi"; } } - public static ODataVersion ODataVersion { get { return ODataVersion.V3; } } - /// see http://tools.ietf.org/html/rfc6648 public static class Header { @@ -24,6 +21,7 @@ public static class Header public static string PublicKey { get { return Prefix + "PublicKey"; } } public static string MaxTop { get { return Prefix + "MaxTop"; } } public static string Version { get { return Prefix + "Version"; } } + public static string CustomerId { get { return Prefix + "CustomerId"; } } public static string HmacResultId { get { return Prefix + "HmacResultId"; } } public static string HmacResultDescription { get { return Prefix + "HmacResultDesc"; } } //public static string LastRequest { get { return Prefix + "LastRequest"; } } From 2302f8bb32b6946ca75c40022c6888e0274ceda2 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 28 Jul 2015 11:29:56 +0200 Subject: [PATCH 0312/1256] Some changes to last commit --- .../SmartStore.Core/SmartNetPrincipal.cs | 26 ++++++++++++++----- .../FormsAuthenticationService.cs | 13 ++++------ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/Libraries/SmartStore.Core/SmartNetPrincipal.cs b/src/Libraries/SmartStore.Core/SmartNetPrincipal.cs index 0fae852141..bcbcb35043 100644 --- a/src/Libraries/SmartStore.Core/SmartNetPrincipal.cs +++ b/src/Libraries/SmartStore.Core/SmartNetPrincipal.cs @@ -1,4 +1,6 @@ -using System.Security.Principal; +using System.Security; +using System.Security.Claims; +using System.Security.Principal; using System.Web.Security; using SmartStore.Core.Domain.Customers; @@ -6,7 +8,21 @@ namespace SmartStore.Core { public interface ISmartNetPrincipal : IPrincipal { - int CustomerId { get; set; } + } + + + public class SmartNetIdentity : ClaimsIdentity + { + [SecuritySafeCritical] + public SmartNetIdentity(int customerId, string name, string type) + : base(new GenericIdentity(name, type)) + { + CustomerId = customerId; + } + + public int CustomerId { get; private set; } + + public override bool IsAuthenticated { get { return CustomerId != 0; } } } @@ -14,16 +30,14 @@ public class SmartNetPrincipal : ISmartNetPrincipal { public SmartNetPrincipal(Customer customer, string type) { - this.Identity = new GenericIdentity(customer.Username, type); - this.CustomerId = customer.Id; + this.Identity = new SmartNetIdentity(customer.Id, customer.Username, type); } public bool IsInRole(string role) { - return Identity != null && Identity.IsAuthenticated && role.HasValue() && Roles.IsUserInRole(Identity.Name, role); + return (Identity != null && Identity.IsAuthenticated && role.HasValue() && Roles.IsUserInRole(Identity.Name, role)); } public IIdentity Identity { get; private set; } - public int CustomerId { get; set; } } } diff --git a/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs b/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs index 657f93cd69..7e8924468c 100644 --- a/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs +++ b/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs @@ -25,8 +25,7 @@ public partial class FormsAuthenticationService : IAuthenticationService /// HTTP context /// Customer service /// Customer settings - public FormsAuthenticationService(HttpContextBase httpContext, - ICustomerService customerService, CustomerSettings customerSettings) + public FormsAuthenticationService(HttpContextBase httpContext, ICustomerService customerService, CustomerSettings customerSettings) { this._httpContext = httpContext; this._customerService = customerService; @@ -78,22 +77,20 @@ public virtual Customer GetAuthenticatedCustomer() if (_cachedCustomer != null) return _cachedCustomer; - if (_httpContext == null || _httpContext.Request == null || !_httpContext.Request.IsAuthenticated) - { + if (_httpContext == null || _httpContext.Request == null || !_httpContext.Request.IsAuthenticated || _httpContext.User == null) return null; - } Customer customer = null; FormsIdentity formsIdentity = null; - SmartNetPrincipal smartNetPrincipal = null; + SmartNetIdentity smartNetIdentity = null; if ((formsIdentity = _httpContext.User.Identity as FormsIdentity) != null) { customer = GetAuthenticatedCustomerFromTicket(formsIdentity.Ticket); } - else if ((smartNetPrincipal = _httpContext.User as SmartNetPrincipal) != null) + else if ((smartNetIdentity = _httpContext.User.Identity as SmartNetIdentity) != null) { - customer = _customerService.GetCustomerById(smartNetPrincipal.CustomerId); + customer = _customerService.GetCustomerById(smartNetIdentity.CustomerId); } if (customer != null && customer.Active && !customer.Deleted && customer.IsRegistered()) From 8e0e471d0d7c9d97ab8678103b05a43aef81467b Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 28 Jul 2015 13:24:56 +0200 Subject: [PATCH 0313/1256] Increased version number to 2.2.2 --- SmartStoreNET.Tasks.Targets | 2 +- src/AssemblyVersionInfo.cs | 2 +- .../Localization/App/de/all.smres.xml | 170 +++++++++++++++--- .../App_Data/Localization/App/de/head.txt | 2 +- .../Localization/App/en/all.smres.xml | 154 +++++++++++++--- .../App_Data/Localization/App/en/head.txt | 2 +- 6 files changed, 280 insertions(+), 52 deletions(-) diff --git a/SmartStoreNET.Tasks.Targets b/SmartStoreNET.Tasks.Targets index 980f2060e3..4cc8cafa8a 100644 --- a/SmartStoreNET.Tasks.Targets +++ b/SmartStoreNET.Tasks.Targets @@ -44,7 +44,7 @@ x86 $(BUILD_NUMBER) - 2.2.1 + 2.2.2 $(StageFolder) .$(Version) diff --git a/src/AssemblyVersionInfo.cs b/src/AssemblyVersionInfo.cs index 8cf3480af0..0c8dfa2cfb 100644 --- a/src/AssemblyVersionInfo.cs +++ b/src/AssemblyVersionInfo.cs @@ -12,4 +12,4 @@ [assembly: AssemblyVersion("2.2.0.0")] [assembly: AssemblyFileVersion("2.2.0.0")] -[assembly: AssemblyInformationalVersion("2.2.1.0")] +[assembly: AssemblyInformationalVersion("2.2.2.0")] diff --git a/src/Presentation/SmartStore.Web/App_Data/Localization/App/de/all.smres.xml b/src/Presentation/SmartStore.Web/App_Data/Localization/App/de/all.smres.xml index b492367ecf..37af334470 100644 --- a/src/Presentation/SmartStore.Web/App_Data/Localization/App/de/all.smres.xml +++ b/src/Presentation/SmartStore.Web/App_Data/Localization/App/de/all.smres.xml @@ -240,6 +240,9 @@ Land + + Kundennummer + Geburtsdatum @@ -783,6 +786,9 @@ Telefonnummer wird benötigt + + * Eingabefelder mit Sternchen sind Pflichfelder und müssen ausgefüllt werden. + Bundesland/Region @@ -2932,6 +2938,15 @@ Auf Aktualisierung prüfen + + Unbekannter Fehler beim Paket-Download. Bitte versuchen Sie es später erneut. + + + AutoUpdate möglich + + + <p>Dieses Update kann automatisch installiert werden. Hierfür lädt SmartStore.NET ein Installationspaket auf Ihren Webserver herunter, führt die Installation durch und startet die Anwendung neu. Vor der Installation wird der Verzeichnisinhalt Ihres Shops gesichert, mit Ausnahme der Ordner <i>App_Data</i> und <i>Media</i> sowie der SQL Server Datenbank. </p><p>Klicken Sie die Schaltfläche <b>Jetzt aktualisieren</b>, um das Paket downzuloaden und zu installieren. Alternativ hierzu können Sie weiter unten das Paket auf Ihren lokalen PC downloaden und die Installation zu einem späteren Zeitpunkt manuell durchführen.</p> + Aktuelle Version @@ -2947,23 +2962,14 @@ Update verfügbar - - Ihre Version - Jetzt aktualisieren - - AutoUpdate möglich - - - Unbekannter Fehler beim Paket-Download. Bitte versuchen Sie es später erneut. - - - <p>Dieses Update kann automatisch installiert werden. Hierfür lädt SmartStore.NET ein Installationspaket auf Ihren Webserver herunter, führt die Installation durch und startet die Anwendung neu. Vor der Installation wird der Verzeichnisinhalt Ihres Shops gesichert, mit Ausnahme der Ordner <i>App_Data</i> und <i>Media</i> sowie der SQL Server Datenbank. </p><p>Klicken Sie die Schaltfläche <b>Jetzt aktualisieren</b>, um das Paket downzuloaden und zu installieren. Alternativ hierzu können Sie weiter unten das Paket auf Ihren lokalen PC downloaden und die Installation zu einem späteren Zeitpunkt manuell durchführen.</p> + + Ihre Version - Über + Über SmartStore.NET Aktionen @@ -3064,6 +3070,9 @@ Die eindeutige nummerische ID des Datensatzes + + Fehler beim Senden einer E-Mail + Excel-Datei @@ -3214,6 +3223,9 @@ Suchen + + Jetzt senden + Suchmaschinen (SEO) @@ -3286,6 +3298,9 @@ Zugriffsrechte + + Es sind keine Kundengruppen definiert + Zugriffsrecht @@ -3346,6 +3361,24 @@ Die Ereignistypen wurden erfolgreich bearbeitet. + + Diese Konfiguration für Kindelemente übernehmen + + + Diese Funktion übernimmt die Zugriffsrecht-Konfiguration dieser Warengruppe für alle Unterwarengruppen und Produkte.<br/> + Bitte beachten Sie, dass die Änderungen der Zugriffsrechte zunächst gespeichert werden müssen, <br /> + bevor diese für Unterkategorien und Produkte übernommen werden können. <br /> + <b>Vorsicht:</b> Bitte beachten Sie, <b>dass vorhandene Zugriffsrechte überschrieben bzw. gelöscht werden</b>. + + + Diese Konfiguration für Kindelemente übernehmen + + + Diese Funktion übernimmt die Shop-Konfiguration dieser Warengruppe für alle Unterwarengruppen und Produkte.<br/> + Bitte beachten Sie, dass die Änderungen an der Store-Konfiguration zunächst gespeichert werden müssen, <br /> + bevor diese für Unterkategorien und Produkte übernommen werden können. <br /> + <b>Vorsicht:</b> Bitte beachten Sie, <b>dass vorhandene Store-Konfiguration überschrieben bzw. gelöscht werden</b>. + Content Slider @@ -4115,7 +4148,7 @@ Zahlung - Das Plugin erlaubt keine Aktivierung dieser Zahlungsmethode. + Das Plugin erlaubt keine Aktivierung dieser Zahlungsart. Zahlungsarten @@ -4127,10 +4160,10 @@ Konfiguration - Wiederkehrender Zahlungstyp + Wiederkehrende Zahlungen - Unterstützt Capture + Buchung möglich Teilerstattung möglich @@ -4139,7 +4172,7 @@ Erstattung möglich - Kann storniert werden + Stornierung möglich Plugins @@ -4756,6 +4789,18 @@ Legt fest, ob die Hersteller-Produktnummer im Shop angezeigt werden soll. + + Zeige Herstellerbilder auf der Homepage + + + Bestimmt ob Hersteller auf der Homepage als Bilder oder textuelle Links angezeigt werden. + + + Zeige Hersteller auf der Homepage + + + Bestimmt ob Hersteller auf der Homepage angezeigt werden. + Produktbilder bei der Autovervollständigung anzeigen @@ -4804,6 +4849,12 @@ Zeigt das Gewicht des Produktes an. + + Unterwarengruppen anzeigen + + + Legt fest, ob und wo Unterwarengruppen auf einer Warengruppenseite angezeigt werden sollen. + SKU Suche unterdrücken @@ -4996,6 +5047,12 @@ Legt die maximale Länge des angezeigten Benutzernamens fest. + + Kunden können Kundennummer hinterlegen + + + Bestimmt ob Kunden eine Kundennummer hinterlegen können. + Kundeneinstellungen @@ -7039,6 +7096,12 @@ Ein Name für die Forengruppe ist erforderlich + + URL-Alias + + + Legt einen Suchmaschinen-freundlichen Seitennamen für das Forum fest. 'Tolles Forum' resultiert bspw. in '~/tolles-forum'. Standard ist der Name des Forums. + Das Forum wurde erfolgreich aktualisiert @@ -7084,6 +7147,12 @@ Ein Name für die Forengruppe ist erforderlich + + URL-Alias + + + Legt einen Suchmaschinen-freundlichen Seitennamen für die Forengruppe fest. 'Tolle Forengruppe' resultiert bspw. in '~/tolle-forengruppe'. Standard ist der Name der Forengruppe. + Die Forengruppe wurde erfolgreich aktualisert. @@ -7144,6 +7213,12 @@ Der Name der Vorlage (Schreibgeschützt) + + Nur manuell senden + + + Legt fest, ob E-Mails, die von dieser Nachrichtenvorlage abgeleitet sind, ausschließlich manuell gesendet werden sollen. + Betreff @@ -8386,8 +8461,11 @@ Hilfe + + Dokumentation + - Community-Forum + Community SmartStore.NET ist ein Fork der ASP.NET Open-Source E-Commerce-Lösung {0}. @@ -8759,10 +8837,10 @@ Setzt den Zahlungsstatus auf 'Bezahlt' ohne dabei den Zahlungsanbieter zu kontaktieren. - Auftrags-GUID + Bestellreferenznummer - Interne Referenz für den Auftrag. + Die interne Bestellreferenznummer. Im Gegensatz zur Auftragsnummer existiert diese bereits im Kassenbereich, d.h. vor der eigentlichen Erstelllung des Auftrags. Auftragsnummer @@ -8858,10 +8936,10 @@ Setzt den Zahlungsstatus auf 'Teilweise erstattet' samt Erstattungsbetrag, ohne dabei den Zahlungsanbieter zu kontaktieren. - Zahlungsmethode + Zahlungsart - Die Zahlungsmethode für diese Transaktion + Die Zahlungsart für diese Transaktion Die Zahlungsgebühr (netto) für diesen Auftrag @@ -9100,6 +9178,12 @@ Notiz + + Neue IPN + + + In den Auftragsnotizen ist eine neue Benachrichtigung vom Zahlungsanbieter eingetroffen. + Auftrag als PDF @@ -9502,6 +9586,9 @@ Plugins verwalten + + Bitte beachten Sie, dass der tatsächliche Grundpreis von verschiedenen Faktoren abhängig ist und erst im Shop zuverlässig berechnet werden kann. + Promotion Feeds @@ -10360,6 +10447,12 @@ Priorität eingeben + + Nur manuell senden + + + Legt fest, ob die E-Mail ausschließlich manuell gesendet werden soll. + Gesendet um @@ -10421,7 +10514,7 @@ Lade nur noch nicht gesendete E-Mails - Zeige E-Mails nur aus der Warteschlange. + Lade nur noch nicht gesendete E-Mails. Maximale Sendeversuche @@ -10429,6 +10522,12 @@ Gibt die Anzahl der Zustellversuche an. + + Lade nur manuell zu sendende E-Mails + + + Lade nur manuell zu sendende E-Mails. + Anfangsdatum @@ -10445,7 +10544,7 @@ Wiederholen - Die Nachricht wird erneut gesendet + Die Nachricht wurde erfolgreich neu eingereiht. Die E-Mail wurde erfolgreich bearbeitet @@ -10643,10 +10742,10 @@ '{0}' Plugin ist nicht kompatibel mit Ihrer SmartStore.NET-Version. Löschen Sie es oder installieren Sie die richtige Version. - Es gibt keine aktiven Zahlungsmethoden. + Es existieren keine aktiven Zahlungsarten. - Die Zahlungsmethoden sind OK. + Die Zahlungsarten sind OK. Die Hauptwährung für den Shop wurde nicht festgelegt. @@ -11150,7 +11249,7 @@ Weiter - Keine Zahlungsmethoden verfügbar. + Es sind keine Zahlungsarten verfügbar. Ihre Bestellung ist angekommen @@ -11168,7 +11267,7 @@ Zahlungsinformation - Zahlungsmethode + Zahlungsarten Bestelldetails @@ -11386,6 +11485,9 @@ Fehler + + Die gewählte Zahlungsart verursachte leider einen Fehler. Bitte korrigieren Sie Ihre Eingaben, versuchen Sie es erneut oder wählen Sie eine andere Zahlungsart. + Fehler beim Versenden der Email. Bitte versuchen Sie es später erneut. @@ -11815,6 +11917,15 @@ Jahre + + Über der Produktliste + + + Am Seitenende + + + Nicht anzeigen + Benutze CONTAINS und AND mit prefix_term @@ -12762,7 +12873,7 @@ Gesamtsumme - Zahlungsmethode + Zahlungsart Zahlungsgebühr @@ -13370,6 +13481,9 @@ {0} am Lager. + + Nicht im Sortiment + Nicht am Lager diff --git a/src/Presentation/SmartStore.Web/App_Data/Localization/App/de/head.txt b/src/Presentation/SmartStore.Web/App_Data/Localization/App/de/head.txt index 9e3f271712..afe64e4f3b 100644 --- a/src/Presentation/SmartStore.Web/App_Data/Localization/App/de/head.txt +++ b/src/Presentation/SmartStore.Web/App_Data/Localization/App/de/head.txt @@ -1 +1 @@ -201504232202590_AutoUpdateRes \ No newline at end of file +201506181858349_AclRecordCustomerRole \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/App_Data/Localization/App/en/all.smres.xml b/src/Presentation/SmartStore.Web/App_Data/Localization/App/en/all.smres.xml index 45d1081077..c6d776abb6 100644 --- a/src/Presentation/SmartStore.Web/App_Data/Localization/App/en/all.smres.xml +++ b/src/Presentation/SmartStore.Web/App_Data/Localization/App/en/all.smres.xml @@ -240,6 +240,9 @@ Country + + Customer number + Date of birth @@ -783,6 +786,9 @@ Phone number is required. + + * Input elements with asterisk are required and have to be filled out. + State / province @@ -3025,6 +3031,15 @@ Check for update + + Unknown error during package download. Please try again later. + + + AutoUpdate possible + + + <p>This update can be installed automatically. For this SmartStore.NET downloads an installation package to your webserver, executes it and restarts the application. Before the installation your shop directory is backed up, except the folders <i>App_Data</i> and <i>Media</i>, as well as the SQL Server database file. </p><p>Click the <b>Update now</b> button to download and install the package. As an alternative to this, you can download the package to your local PC further below and perform the installation at a later time manually.</p> + Current version @@ -3040,26 +3055,17 @@ Update available - - Your version - Update now - - AutoUpdate possible - - - Unknown error during package download. Please try again later. - - - <p>This update can be installed automatically. For this SmartStore.NET downloads an installation package to your webserver, executes it and restarts the application. Before the installation your shop directory is backed up, except the folders <i>App_Data</i> and <i>Media</i>, as well as the SQL Server database file. </p><p>Click the <b>Update now</b> button to download and install the package. As an alternative to this, you can download the package to your local PC further below and perform the installation at a later time manually.</p> + + Your version Actions - About + About SmartStore.NET Actions @@ -3160,6 +3166,9 @@ The unique numeric id of the entity + + Error sending an email + Excel file @@ -3310,6 +3319,9 @@ Search + + Send now + Search engines (SEO) @@ -3382,6 +3394,9 @@ Access control list + + No customer roles defined + Permission name @@ -3445,6 +3460,24 @@ The types have been updated successfully. + + Transfer this ACL configuration to children + + + This function assigns the ACL configuration of this category to all subcategories and products included in this category.<br /> + Please keep in mind you have to save changes in the ACL configuration <br/> + before you can assign them to all subcategories and products. <br/> + <b>Attention:</b> Please keep in mind that <b>existing ACL records will be deleted</b> + + + Transfer this store configuration to children + + + This function assigns the store configuration of this category to all subcategories and products included in this category.<br /> + Please keep in mind you have to save changes in the store configuration <br/> + before you can assign them to all subcategories and products. <br/> + <b>Attention:</b> Please keep in mind that <b>existing store mappings will be deleted</b> + Content Slider @@ -4271,19 +4304,19 @@ Display order - Recurring support + Recurring payments Supports capture - Partial refund + Supports partial refund - Refund + Supports refund - Void + Supports void Plugins @@ -4912,6 +4945,18 @@ Check to show manufacturer part numbers in public store. + + Show manufacturer pictures on homepage + + + Specifies whether manufacturers will be displayed as images or textual links on the homepage. + + + Show manufacturers on homepage + + + Specifies whether manufacturers will be displayed on the homepage. + Show product images in autocomplete box @@ -4960,6 +5005,12 @@ Check to display the weight. When enabled, customers will see the weight of the product. + + Show subcategories + + + Indicates whether and where to show subcategories on a category page. + Suppress SKU search @@ -5152,6 +5203,12 @@ Determines the maximum length of the displayed customer name. + + Customers can enter a customer number + + + Specifies whether customers can enter a customer number. + Customer settings @@ -7235,6 +7292,12 @@ Forum group name is required. + + URL-Alias + + + Set a search engine friendly page name e.g. 'the-best-forum' to make your page URL 'http://www.yourStore.com/the-best-forum'. Leave empty to generate it automatically based on the name of the forum. + The forum has been updated successfully. @@ -7283,6 +7346,12 @@ Forum Group Name is required. + + URL-Alias + + + Set a search engine friendly page name e.g. 'the-best-forumgroup' to make your page URL 'http://www.yourStore.com/the-best-forumgroup'. Leave empty to generate it automatically based on the name of the forum group. + The forum group has been updated successfully. @@ -7346,6 +7415,12 @@ The name of this template (read only). + + Only send manually + + + Indicates whether emails derived from this message template should only be send manually. + Subject @@ -8657,8 +8732,11 @@ Help + + Documentation + - Community forums + Community SmartStore.NET is a fork of the ASP.NET open source e-commerce solution {0}. @@ -9042,10 +9120,10 @@ Sets the payment status to 'paid' without contacting the payment provider. - Order GUID + Order reference number - Internal reference for order. + The internal order reference number. In contrast to the order number it already exists during checkout that is before order creation. Order Number @@ -9389,6 +9467,12 @@ Note + + New IPN + + + A new notification from the payment provider has arrived in the order notes. + Order as PDF @@ -9800,6 +9884,9 @@ Manage plugins + + Please keep in mind, the base price is depending on several factors and will therefore only be calculated reliable in the front end. + Promotion feeds @@ -10691,6 +10778,12 @@ Enter priority. + + Only send manually + + + Indicates whether the email should only be send manually. + Sent on @@ -10755,7 +10848,7 @@ Load not sent emails only - Only load emails into queue that have not yet been sent. + Load not sent emails only. Maximum send attempts @@ -10763,6 +10856,12 @@ The maximum number of attempts to send a message. + + Load emails manually send only + + + Load emails manually send only. + Start date @@ -11762,6 +11861,9 @@ Error + + Unfortunately the selected payment method caused an error. Please correct your entries, try it again or select another payment method. + Error while sending the email. Please try again later. @@ -12188,6 +12290,15 @@ Years + + Above product list + + + At bottom of page + + + Do not display + Using CONTAINS and AND with prefix_term @@ -13720,6 +13831,9 @@ {0} in stock + + Not in assortment + Out of stock diff --git a/src/Presentation/SmartStore.Web/App_Data/Localization/App/en/head.txt b/src/Presentation/SmartStore.Web/App_Data/Localization/App/en/head.txt index 9e3f271712..afe64e4f3b 100644 --- a/src/Presentation/SmartStore.Web/App_Data/Localization/App/en/head.txt +++ b/src/Presentation/SmartStore.Web/App_Data/Localization/App/en/head.txt @@ -1 +1 @@ -201504232202590_AutoUpdateRes \ No newline at end of file +201506181858349_AclRecordCustomerRole \ No newline at end of file From cbef8d05c7f16d4eb9d8859809ab6efd83b92962 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 28 Jul 2015 18:57:48 +0200 Subject: [PATCH 0314/1256] Display base price in CompactProductBox --- .../SmartStore.Web/Controllers/CatalogHelper.cs | 5 +++-- .../SmartStore.Web/Controllers/ProductController.cs | 4 ++-- .../Views/Shared/_ProductBoxCompact.cshtml | 12 +++++++++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs index bd9c4354af..fb877fd0b3 100644 --- a/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs +++ b/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs @@ -986,7 +986,8 @@ public IEnumerable PrepareProductOverviewModels( bool prepareSpecificationAttributes = false, bool forceRedirectionAfterAddingToCart = false, bool prepareColorAttributes = false, - bool prepareManufacturers = false) + bool prepareManufacturers = false, + bool isCompact = false) { if (products == null) throw new ArgumentNullException("products"); @@ -1315,7 +1316,7 @@ from a in colorAttr.ProductVariantAttributeValues.Take(50) if (_catalogSettings.ShowBasePriceInProductLists) { - model.BasePriceInfo = minPriceProduct.GetBasePriceInfo(_localizationService, _priceFormatter); + model.BasePriceInfo = minPriceProduct.GetBasePriceInfo(_localizationService, _priceFormatter, 0, isCompact); } var addShippingPrice = _currencyService.ConvertCurrency( diff --git a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs index ff7660fd01..4fcfdf40ec 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs @@ -445,7 +445,7 @@ public ActionResult RelatedProducts(int productId, int? productThumbPictureSize) if (products.Count == 0) return Content(""); - var model = _helper.PrepareProductOverviewModels(products, true, true, productThumbPictureSize).ToList(); + var model = _helper.PrepareProductOverviewModels(products, true, true, productThumbPictureSize, false, false, false, false, true).ToList(); return PartialView(model); } @@ -472,7 +472,7 @@ public ActionResult ProductsAlsoPurchased(int productId, int? productThumbPictur return Content(""); // prepare model - var model = _helper.PrepareProductOverviewModels(products, true, true, productThumbPictureSize).ToList(); + var model = _helper.PrepareProductOverviewModels(products, true, true, productThumbPictureSize, false, false, false, false, true).ToList(); return PartialView(model); } diff --git a/src/Presentation/SmartStore.Web/Views/Shared/_ProductBoxCompact.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/_ProductBoxCompact.cshtml index 682c3fe67a..ed3cffd7f8 100644 --- a/src/Presentation/SmartStore.Web/Views/Shared/_ProductBoxCompact.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Shared/_ProductBoxCompact.cshtml @@ -25,6 +25,16 @@
    -
    @Model.ProductPrice.Price
    +
    + @Model.ProductPrice.Price +
    +
    + @if (Model.DisplayBasePrice && !String.IsNullOrEmpty(Model.BasePriceInfo)) + { + + @Model.BasePriceInfo + + } +
    \ No newline at end of file From 8ab3417a87c0ac4371d13fdf348e55e9d3a61be9 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 28 Jul 2015 19:07:32 +0200 Subject: [PATCH 0315/1256] Minor CSS change --- src/Presentation/SmartStore.Web/Content/bootstrap/media.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Presentation/SmartStore.Web/Content/bootstrap/media.less b/src/Presentation/SmartStore.Web/Content/bootstrap/media.less index 1decab71de..8b89ef39df 100644 --- a/src/Presentation/SmartStore.Web/Content/bootstrap/media.less +++ b/src/Presentation/SmartStore.Web/Content/bootstrap/media.less @@ -38,7 +38,7 @@ // ------------------------- .media .pull-left { - margin-right: 10px; + margin-right: 25px; } .media .pull-right { margin-left: 10px; From 4399ea6f8a3c6f0683b7ac071dbaaba9c590ee15 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Wed, 29 Jul 2015 13:41:01 +0200 Subject: [PATCH 0316/1256] Minor change --- .../Administration/Controllers/ProductController.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index 3258627c81..f419909ac5 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -20,6 +20,7 @@ using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Discounts; using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Domain.Seo; using SmartStore.Core.Events; using SmartStore.Core.Infrastructure; using SmartStore.Core.Localization; @@ -97,6 +98,7 @@ public partial class ProductController : AdminControllerBase private readonly IGenericAttributeService _genericAttributeService; private readonly IPdfConverter _pdfConverter; private readonly ICommonServices _services; + private readonly SeoSettings _seoSettings; #endregion @@ -147,7 +149,8 @@ public ProductController( IEventPublisher eventPublisher, IGenericAttributeService genericAttributeService, IPdfConverter pdfConverter, - ICommonServices services) + ICommonServices services, + SeoSettings seoSettings) { this._productService = productService; this._productTemplateService = productTemplateService; @@ -193,6 +196,7 @@ public ProductController( this._genericAttributeService = genericAttributeService; _pdfConverter = pdfConverter; _services = services; + _seoSettings = seoSettings; } #endregion @@ -559,7 +563,7 @@ private void UpdateDataOfExistingProduct(Product product, ProductModel model, bo MediaHelper.UpdateDownloadTransientStateFor(p, x => x.SampleDownloadId); // SEO - m.SeName = p.ValidateSeName(m.SeName, p.Name, true); + m.SeName = p.ValidateSeName(m.SeName, p.Name, true, _urlRecordService, _seoSettings); _urlRecordService.SaveSlug(p, m.SeName, 0); foreach (var localized in model.Locales) @@ -569,7 +573,7 @@ private void UpdateDataOfExistingProduct(Product product, ProductModel model, bo _localizedEntityService.SaveLocalizedValue(product, x => x.FullDescription, localized.FullDescription, localized.LanguageId); // search engine name - var localizedSeName = p.ValidateSeName(localized.SeName, localized.Name, false, localized.LanguageId); + var localizedSeName = p.ValidateSeName(localized.SeName, localized.Name, false, _urlRecordService, _seoSettings, localized.LanguageId); _urlRecordService.SaveSlug(p, localizedSeName, localized.LanguageId); } From 34a1a9517c1c8206a149050342145f7e8637f08c Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 30 Jul 2015 22:44:10 +0200 Subject: [PATCH 0317/1256] New export profile entity --- .../Customers/SystemCustomerRoleNames.cs | 1 - .../Domain/Export/ExportProfile.cs | 73 ++++++++++ .../SmartStore.Core/SmartStore.Core.csproj | 2 + .../Mapping/Export/ExportProfileMap.cs | 27 ++++ ...01507301550466_ExportFramework.Designer.cs | 29 ++++ .../201507301550466_ExportFramework.cs | 105 +++++++++++++++ .../201507301550466_ExportFramework.resx | 126 ++++++++++++++++++ .../Setup/Builder/PermissionMigrator.cs | 55 ++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 9 ++ .../ExportImport/ExportService.cs | 79 +++++++++++ .../ExportImport/IExportService.cs | 33 +++++ .../Security/StandardPermissionProvider.cs | 3 + .../SmartStore.Services.csproj | 2 + .../DependencyRegistrar.cs | 2 + .../Controllers/ExportController.cs | 73 ++++++++++ .../Models/Export/ExportProfileModel.cs | 31 +++++ .../Administration/SmartStore.Admin.csproj | 3 + .../Administration/Views/Export/List.cshtml | 59 ++++++++ .../Administration/sitemap.config | 2 + 19 files changed, 713 insertions(+), 1 deletion(-) create mode 100644 src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs create mode 100644 src/Libraries/SmartStore.Data/Mapping/Export/ExportProfileMap.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.resx create mode 100644 src/Libraries/SmartStore.Data/Setup/Builder/PermissionMigrator.cs create mode 100644 src/Libraries/SmartStore.Services/ExportImport/ExportService.cs create mode 100644 src/Libraries/SmartStore.Services/ExportImport/IExportService.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml diff --git a/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerRoleNames.cs b/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerRoleNames.cs index 760d14d9be..214fd18191 100644 --- a/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerRoleNames.cs +++ b/src/Libraries/SmartStore.Core/Domain/Customers/SystemCustomerRoleNames.cs @@ -3,7 +3,6 @@ namespace SmartStore.Core.Domain.Customers { public static partial class SystemCustomerRoleNames { - /// codehint: sm-add public static string SuperAdministrators { get { return "SuperAdmins"; } } public static string Administrators { get { return "Administrators"; } } diff --git a/src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs b/src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs new file mode 100644 index 0000000000..bca569da98 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs @@ -0,0 +1,73 @@ +using System; +using SmartStore.Core.Domain.Tasks; + +namespace SmartStore.Core.Domain +{ + public class ExportProfile : BaseEntity + { + /// + /// The name of the profile + /// + public string Name { get; set; } + + /// + /// Whether the export profile is enabled + /// + public bool Enabled { get; set; } + + /// + /// The system name of the export provider + /// + public string ProviderSystemName { get; set; } + + /// + /// The entity type to be exported + /// + public string EntityType { get; set; } + + /// + /// Number of hours after the profile is automatically executed by scheduling + /// + public int SchedulingHours { get; set; } + + /// + /// The scheduling task identifier + /// + public int SchedulingTaskId { get; set; } + + /// + /// The profile GUID is the folder name in the file system + /// + public Guid ProfileGuid { get; set; } + + /// + /// XML with partioning information + /// + public string Partitioning { get; set; } + + /// + /// XML with filtering information + /// + public string Filtering { get; set; } + + /// + /// Last start time the profile has been executed + /// + public DateTime? LastExecutionStartUtc { get; set; } + + /// + /// /// Last end time the profile has been executed + /// + public DateTime? LastExecutionEndUtc { get; set; } + + /// + /// Message of the last execution + /// + public string LastExecutionMessage { get; set; } + + /// + /// The scheduling task + /// + public virtual ScheduleTask ScheduleTask { get; set; } + } +} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index f1c102b6d5..e4f7dc5af8 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -159,6 +159,7 @@ + @@ -595,6 +596,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Setup/Builder/PermissionMigrator.cs b/src/Libraries/SmartStore.Data/Setup/Builder/PermissionMigrator.cs new file mode 100644 index 0000000000..fe509e1cdf --- /dev/null +++ b/src/Libraries/SmartStore.Data/Setup/Builder/PermissionMigrator.cs @@ -0,0 +1,55 @@ +using System.Data.Entity; +using System.Linq; +using SmartStore.Core.Data; +using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Domain.Security; + +namespace SmartStore.Data.Setup +{ + internal class PermissionMigrator + { + private readonly SmartObjectContext _ctx; + private readonly DbSet _permissionRecords; + private readonly IQueryable _customerRoles; + + public PermissionMigrator(SmartObjectContext ctx) + { + Guard.ArgumentNotNull(() => ctx); + + _ctx = ctx; + _permissionRecords = _ctx.Set(); + _customerRoles = _ctx.Set().Expand(x => x.PermissionRecords); + } + + public void AddPermission(PermissionRecord permission, string[] rolesToMap) + { + Guard.ArgumentNotNull(() => permission); + Guard.ArgumentNotNull(() => rolesToMap); + + if (permission.SystemName.IsEmpty()) + return; + + var permissionRecord = _permissionRecords.FirstOrDefault(x => x.SystemName == permission.SystemName); + + if (permissionRecord == null) + { + _permissionRecords.Add(permission); + + _ctx.SaveChanges(); + } + + permissionRecord = _permissionRecords.FirstOrDefault(x => x.SystemName == permission.SystemName); + + foreach (var roleName in rolesToMap) + { + var role = _customerRoles.FirstOrDefault(x => x.SystemName == roleName); + if (role != null && !role.PermissionRecords.Any(x => x.SystemName == permission.SystemName)) + { + role.PermissionRecords.Add(permissionRecord); + } + } + + _ctx.SaveChanges(); + } + } +} diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index a6fce9f98b..9bde1ba879 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -121,6 +121,7 @@ + @@ -331,6 +332,11 @@ 201507250039446_Merge2.cs + + + 201507301550466_ExportFramework.cs + + @@ -627,6 +633,9 @@ 201507250039446_Merge2.cs + + 201507301550466_ExportFramework.cs + diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportService.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportService.cs new file mode 100644 index 0000000000..c19a63129a --- /dev/null +++ b/src/Libraries/SmartStore.Services/ExportImport/ExportService.cs @@ -0,0 +1,79 @@ +using System; +using System.Linq; +using SmartStore.Core.Data; +using SmartStore.Core.Domain; +using SmartStore.Core.Events; +using SmartStore.Services.Tasks; + +namespace SmartStore.Services.ExportImport +{ + public partial class ExportService : IExportService + { + private readonly IRepository _exportProfileRepository; + private readonly IEventPublisher _eventPublisher; + private readonly Lazy _scheduleTaskService; + + public ExportService( + IRepository exportProfileRepository, + IEventPublisher eventPublisher, + Lazy scheduleTaskService) + { + _exportProfileRepository = exportProfileRepository; + _eventPublisher = eventPublisher; + _scheduleTaskService = scheduleTaskService; + } + + #region Export profiles + + public virtual void InsertExportProfile(ExportProfile profile) + { + if (profile == null) + throw new ArgumentNullException("profile"); + + _exportProfileRepository.Insert(profile); + + _eventPublisher.EntityInserted(profile); + } + + public virtual void UpdateExportProfile(ExportProfile profile) + { + if (profile == null) + throw new ArgumentNullException("profile"); + + _exportProfileRepository.Update(profile); + + _eventPublisher.EntityUpdated(profile); + } + + public virtual void DeleteExportProfile(ExportProfile profile) + { + if (profile == null) + throw new ArgumentNullException("profile"); + + if (profile.ScheduleTask != null) + { + _scheduleTaskService.Value.DeleteTask(profile.ScheduleTask); + } + + _exportProfileRepository.Delete(profile); + + _eventPublisher.EntityDeleted(profile); + } + + public virtual IQueryable GetExportProfiles(bool? enabled = null) + { + var query = + from x in _exportProfileRepository.Table.Expand(x => x.ScheduleTask) + select x; + + if (enabled.HasValue) + { + query = query.Where(x => x.Enabled == enabled.Value); + } + + return query.OrderBy(x => x.Name); + } + + #endregion + } +} diff --git a/src/Libraries/SmartStore.Services/ExportImport/IExportService.cs b/src/Libraries/SmartStore.Services/ExportImport/IExportService.cs new file mode 100644 index 0000000000..0e8389011b --- /dev/null +++ b/src/Libraries/SmartStore.Services/ExportImport/IExportService.cs @@ -0,0 +1,33 @@ +using System.Linq; +using SmartStore.Core.Domain; + +namespace SmartStore.Services.ExportImport +{ + public interface IExportService + { + /// + /// Inserts an export profile + /// + /// Export profile + void InsertExportProfile(ExportProfile profile); + + /// + /// Updates an export profile + /// + /// Export profile + void UpdateExportProfile(ExportProfile profile); + + /// + /// Deletes an export profile + /// + /// Export profile + void DeleteExportProfile(ExportProfile profile); + + /// + /// Get queryable export profiles + /// + /// Whether to filter enabled or disabled profiles + /// + IQueryable GetExportProfiles(bool? enabled = null); + } +} diff --git a/src/Libraries/SmartStore.Services/Security/StandardPermissionProvider.cs b/src/Libraries/SmartStore.Services/Security/StandardPermissionProvider.cs index 01b83e6a38..7018c51146 100644 --- a/src/Libraries/SmartStore.Services/Security/StandardPermissionProvider.cs +++ b/src/Libraries/SmartStore.Services/Security/StandardPermissionProvider.cs @@ -49,6 +49,7 @@ public partial class StandardPermissionProvider : IPermissionProvider public static readonly PermissionRecord ManageMaintenance = new PermissionRecord { Name = "Admin area. Manage Maintenance", SystemName = "ManageMaintenance", Category = "Configuration" }; public static readonly PermissionRecord UploadPictures = new PermissionRecord { Name = "Admin area. Upload Pictures", SystemName = "UploadPictures", Category = "Configuration" }; public static readonly PermissionRecord ManageScheduleTasks = new PermissionRecord { Name = "Admin area. Manage Schedule Tasks", SystemName = "ManageScheduleTasks", Category = "Configuration" }; + public static readonly PermissionRecord ManageExports = new PermissionRecord { Name = "Admin area. Manage Exports", SystemName = "ManageExports", Category = "Configuration" }; //public store permissions @@ -103,6 +104,7 @@ public virtual IEnumerable GetPermissions() ManageMaintenance, UploadPictures, ManageScheduleTasks, + ManageExports, DisplayPrices, EnableShoppingCart, EnableWishlist, @@ -160,6 +162,7 @@ public virtual IEnumerable GetDefaultPermissions() ManageMaintenance, UploadPictures, ManageScheduleTasks, + ManageExports, DisplayPrices, EnableShoppingCart, EnableWishlist, diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index 49e1c86d78..33484e0895 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -162,6 +162,8 @@ + + diff --git a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs index 99d42a6b9c..29357d57db 100644 --- a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs +++ b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs @@ -223,6 +223,8 @@ public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, b .InstancePerRequest(); builder.RegisterType().As().InstancePerRequest(); + builder.RegisterType().As().InstancePerRequest(); + builder.RegisterType().As().InstancePerRequest(); builder.RegisterType().As().InstancePerRequest(); builder.RegisterType().As().InstancePerRequest(); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs new file mode 100644 index 0000000000..839265dfef --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs @@ -0,0 +1,73 @@ +using System.Linq; +using System.Web.Mvc; +using SmartStore.Admin.Models.Export; +using SmartStore.Core; +using SmartStore.Core.Domain; +using SmartStore.Services; +using SmartStore.Services.ExportImport; +using SmartStore.Services.Security; +using SmartStore.Web.Framework.Controllers; +using Telerik.Web.Mvc; + +namespace SmartStore.Admin.Controllers +{ + [AdminAuthorize] + public class ExportController : AdminControllerBase + { + private readonly ICommonServices _services; + private readonly IExportService _exportService; + + public ExportController( + ICommonServices services, + IExportService exportService) + { + _services = services; + _exportService = exportService; + } + + public ActionResult Index() + { + return RedirectToAction("List"); + } + + public ActionResult List() + { + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + return View(); + } + + [HttpPost, GridAction(EnableCustomBinding = true)] + public ActionResult List(GridCommand command) + { + var model = new GridModel(); + + if (_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + { + var query = _exportService.GetExportProfiles(); + var profiles = query.ToList(); + + model.Total = profiles.Count; + + model.Data = profiles.Select(x => + { + var profileModel = new ExportProfileModel + { + Name = x.Name, + ProviderSystemName = x.ProviderSystemName, + EntityType = x.EntityType, + Enabled = x.Enabled, + FileType = "", // TODO + SchedulingHours = x.SchedulingHours, + LastExecution = "" // TODO + }; + + return profileModel; + }); + } + + return new JsonResult { Data = model }; + } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs new file mode 100644 index 0000000000..c95bd05837 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs @@ -0,0 +1,31 @@ +using System.Web.Mvc; +using SmartStore.Web.Framework; +using SmartStore.Web.Framework.Mvc; + +namespace SmartStore.Admin.Models.Export +{ + public partial class ExportProfileModel : EntityModelBase + { + [SmartResourceDisplayName("Admin.Configuration.Export.Name")] + public string Name { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.ProviderSystemName")] + public string ProviderSystemName { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.EntityType")] + public string EntityType { get; set; } + + [SmartResourceDisplayName("Common.Enabled")] + public bool Enabled { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.FileType")] + public string FileType { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.SchedulingHours")] + public int SchedulingHours { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.LastExecution")] + [AllowHtml] + public string LastExecution { get; set; } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index 209e12c89f..0f7013c4e4 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -175,6 +175,7 @@ + @@ -247,6 +248,7 @@ + @@ -498,6 +500,7 @@ + diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml new file mode 100644 index 0000000000..17122852e5 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml @@ -0,0 +1,59 @@ +@using SmartStore.Admin.Models.Export +@using Telerik.Web.Mvc.UI +@{ + ViewBag.Title = T("Common.Export").Text; +} + +
    +
    + + @T("Common.Export") +
    + +
    + + + +
    + + + + +
    + @(Html.Telerik().Grid() + .Name("export-profile-grid") + .DataKeys(x => + { + x.Add(y => y.Id).RouteKey("Id"); + }) + .Columns(columns => + { + columns.Bound(x => x.Name) + .Width(400) + .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })) + .ClientTemplate("\"><#= Name #>"); + columns.Bound(x => x.ProviderSystemName); + columns.Bound(x => x.EntityType); + columns.Bound(x => x.Enabled) + .Width(100) + .Template(item => @Html.SymbolForBool(item.Enabled)) + .ClientTemplate(@Html.SymbolForBool("Enabled")) + .Centered(); + columns.Bound(x => x.FileType); + columns.Bound(x => x.SchedulingHours); + columns.Bound(x => x.LastExecution) + .ReadOnly(); + }) + .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "Export")) + .ClientEvents(events => events.OnRowDataBound("onRowDataBound_ExportProfiles")) + .EnableCustomBinding(true)) +
    +
    diff --git a/src/Presentation/SmartStore.Web/Administration/sitemap.config b/src/Presentation/SmartStore.Web/Administration/sitemap.config index 33a9fd264f..0ba3a9156e 100644 --- a/src/Presentation/SmartStore.Web/Administration/sitemap.config +++ b/src/Presentation/SmartStore.Web/Administration/sitemap.config @@ -127,6 +127,8 @@ + + From 0b29a2a3f87f43d8acc49d252995bc5d80e463b2 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Fri, 31 Jul 2015 00:02:29 +0200 Subject: [PATCH 0318/1256] Changing an object state is only possible if an object state exists --- src/Libraries/SmartStore.Data/ObjectContextBase.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Libraries/SmartStore.Data/ObjectContextBase.cs b/src/Libraries/SmartStore.Data/ObjectContextBase.cs index fd6ad01650..48dd480551 100644 --- a/src/Libraries/SmartStore.Data/ObjectContextBase.cs +++ b/src/Libraries/SmartStore.Data/ObjectContextBase.cs @@ -19,6 +19,7 @@ using Microsoft.SqlServer.Management.Smo; using SmartStore.Core.Infrastructure; using SmartStore.Core.Events; +using System.Data.Entity.Core.Objects; namespace SmartStore.Data { @@ -532,7 +533,12 @@ public int DetachAll() public void ChangeState(TEntity entity, System.Data.Entity.EntityState newState) { - ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.ChangeObjectState(entity, newState); + var objectStateManager = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager; + + ObjectStateEntry entry; + + if (objectStateManager.TryGetObjectStateEntry(entity, out entry)) + objectStateManager.ChangeObjectState(entity, newState); } public bool SetToUnchanged(TEntity entity) From 44cafbe8c955705239913cef97ae3cc96b23bf31 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 31 Jul 2015 13:41:21 +0200 Subject: [PATCH 0319/1256] Altered systemname of purchase order number payment plugin --- .../Administration/Controllers/OrderController.cs | 2 +- src/Presentation/SmartStore.Web/Controllers/OrderController.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs index c4157b9b0a..7f7a8b5db3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/OrderController.cs @@ -346,7 +346,7 @@ protected void PrepareOrderDetailsModel(OrderModel model, Order order) var pm = _paymentService.LoadPaymentMethodBySystemName(order.PaymentMethodSystemName); if (pm != null) { - if (pm.Metadata.SystemName.Equals("Payments.PurchaseOrder", StringComparison.InvariantCultureIgnoreCase)) + if (pm.Metadata.SystemName.Equals("SmartStore.PurchaseOrderNumber", StringComparison.InvariantCultureIgnoreCase)) { model.DisplayPurchaseOrderNumber = true; model.PurchaseOrderNumber = order.PurchaseOrderNumber; diff --git a/src/Presentation/SmartStore.Web/Controllers/OrderController.cs b/src/Presentation/SmartStore.Web/Controllers/OrderController.cs index 57c7c32649..f84d4e14bc 100644 --- a/src/Presentation/SmartStore.Web/Controllers/OrderController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/OrderController.cs @@ -171,7 +171,7 @@ protected OrderDetailsModel PrepareOrderDetailsModel(Order order) model.CanRePostProcessPayment = _paymentService.CanRePostProcessPayment(order); //purchase order number (we have to find a better to inject this information because it's related to a certain plugin) - if (paymentMethod != null && paymentMethod.Metadata.SystemName.Equals("Payments.PurchaseOrder", StringComparison.InvariantCultureIgnoreCase)) + if (paymentMethod != null && paymentMethod.Metadata.SystemName.Equals("SmartStore.PurchaseOrderNumber", StringComparison.InvariantCultureIgnoreCase)) { model.DisplayPurchaseOrderNumber = true; model.PurchaseOrderNumber = order.PurchaseOrderNumber; From 14827cd5b33cbb2cc61d12dbe8704cce4d802532 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Mon, 3 Aug 2015 10:06:00 +0200 Subject: [PATCH 0320/1256] Editing an export profile --- .../Domain/Export/ExportCore.cs | 54 +++++ .../Domain/Export/ExportProfile.cs | 27 ++- .../SmartStore.Core/SmartStore.Core.csproj | 1 + src/Libraries/SmartStore.Core/XmlHelper.cs | 41 ++++ .../Mapping/Export/ExportProfileMap.cs | 4 +- .../201507301550466_ExportFramework.cs | 105 --------- .../201507301550466_ExportFramework.resx | 126 ----------- ...1508011828241_ExportFramework.Designer.cs} | 2 +- .../201508011828241_ExportFramework.cs | 157 ++++++++++++++ .../201508011828241_ExportFramework.resx | 126 +++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../Export/ExportExtensions.cs | 16 ++ .../Export/ExportService.cs | 146 +++++++++++++ .../Export/IExportProvider.cs | 16 ++ .../Export/IExportService.cs | 58 +++++ .../ExportImport/ExportService.cs | 79 ------- .../ExportImport/IExportService.cs | 33 --- .../SmartStore.Services.csproj | 6 +- .../DependencyRegistrar.cs | 6 + .../Administration/Content/admin.less | 1 - .../Controllers/ExportController.cs | 205 ++++++++++++++++-- .../Models/Export/ExportProfileModel.cs | 45 +++- .../Administration/SmartStore.Admin.csproj | 2 + .../Administration/Views/Export/Create.cshtml | 27 +++ .../Administration/Views/Export/Edit.cshtml | 135 ++++++++++++ .../Administration/Views/Export/List.cshtml | 115 +++++++++- .../Administration/sitemap.config | 2 +- 27 files changed, 1154 insertions(+), 391 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Domain/Export/ExportCore.cs delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.cs delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.resx rename src/Libraries/SmartStore.Data/Migrations/{201507301550466_ExportFramework.Designer.cs => 201508011828241_ExportFramework.Designer.cs} (92%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.resx create mode 100644 src/Libraries/SmartStore.Services/Export/ExportExtensions.cs create mode 100644 src/Libraries/SmartStore.Services/Export/ExportService.cs create mode 100644 src/Libraries/SmartStore.Services/Export/IExportProvider.cs create mode 100644 src/Libraries/SmartStore.Services/Export/IExportService.cs delete mode 100644 src/Libraries/SmartStore.Services/ExportImport/ExportService.cs delete mode 100644 src/Libraries/SmartStore.Services/ExportImport/IExportService.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml create mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml diff --git a/src/Libraries/SmartStore.Core/Domain/Export/ExportCore.cs b/src/Libraries/SmartStore.Core/Domain/Export/ExportCore.cs new file mode 100644 index 0000000000..b5cca2b555 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/Export/ExportCore.cs @@ -0,0 +1,54 @@ +using System; + +namespace SmartStore.Core.Domain.Export +{ + public enum ExportFileType + { + Xml = 0, + Xls, + Csv, + Txt, + Pdf + } + + + public enum ExportEntityType + { + Product = 0, + Category, + Manufacturer, + Customer, + Order + } + + + [Serializable] + public class ExportPartition + { + public ExportPartition() + { + Limit = 100; + BatchSize = 1000; + } + + /// + /// The number of records to be skipped + /// + public int Offset { get; set; } + + /// + /// How many records to be loaded per database round-trip + /// + public int Limit { get; set; } + + /// + /// The maximum number of records of one processed batch + /// + public int BatchSize { get; set; } + + /// + /// Whether to start a separate run-through for each store + /// + public bool PerStore { get; set; } + } +} diff --git a/src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs b/src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs index bca569da98..ed71e475a0 100644 --- a/src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs +++ b/src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs @@ -1,4 +1,5 @@ using System; +using SmartStore.Core.Domain.Export; using SmartStore.Core.Domain.Tasks; namespace SmartStore.Core.Domain @@ -11,24 +12,34 @@ public class ExportProfile : BaseEntity public string Name { get; set; } /// - /// Whether the export profile is enabled + /// The system name of the export provider /// - public bool Enabled { get; set; } + public string ProviderSystemName { get; set; } /// - /// The system name of the export provider + /// Whether the export profile is enabled /// - public string ProviderSystemName { get; set; } + public bool Enabled { get; set; } /// - /// The entity type to be exported + /// The export file type identifier /// - public string EntityType { get; set; } + public int FileTypeId { get; set; } /// - /// Number of hours after the profile is automatically executed by scheduling + /// The export file type /// - public int SchedulingHours { get; set; } + public ExportFileType FileType + { + get + { + return (ExportFileType)FileTypeId; + } + set + { + FileTypeId = (int)value; + } + } /// /// The scheduling task identifier diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index e4f7dc5af8..21718e5f5a 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -159,6 +159,7 @@ + diff --git a/src/Libraries/SmartStore.Core/XmlHelper.cs b/src/Libraries/SmartStore.Core/XmlHelper.cs index d8fd64a6ce..7f546eba8a 100644 --- a/src/Libraries/SmartStore.Core/XmlHelper.cs +++ b/src/Libraries/SmartStore.Core/XmlHelper.cs @@ -115,6 +115,47 @@ public static DateTime DeserializeDateTime(string dateTime) } } + /// + /// Serializes an object instance to a XML formatted string + /// + /// Object type + /// Object instance + /// XML + public static string Serialize(T instance) + { + if (instance != null) + { + using (var writer = new StringWriter()) + { + var xmlSerializer = new XmlSerializer(typeof(T)); + + xmlSerializer.Serialize(writer, instance); + return writer.ToString(); + } + } + return null; + } + + /// + /// Deserializes a XML formatted string to an object instance + /// + /// Object type + /// XML + /// Object instance + public static T Deserialize(string xml) + { + if (xml.HasValue()) + { + using (var reader = new StringReader(xml)) + { + var serializer = new XmlSerializer(typeof(T)); + + return (T)serializer.Deserialize(reader); + } + } + return (T)Activator.CreateInstance(typeof(T)); + } + #endregion } } diff --git a/src/Libraries/SmartStore.Data/Mapping/Export/ExportProfileMap.cs b/src/Libraries/SmartStore.Data/Mapping/Export/ExportProfileMap.cs index 96538c9c74..a6e66ad885 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Export/ExportProfileMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/Export/ExportProfileMap.cs @@ -12,12 +12,12 @@ public ExportProfileMap() this.Property(x => x.Name).IsRequired().HasMaxLength(100); this.Property(x => x.ProviderSystemName).IsRequired().HasMaxLength(4000); - this.Property(x => x.EntityType).IsRequired().HasMaxLength(100); - this.Property(x => x.EntityType).IsRequired().HasMaxLength(100); this.Property(x => x.Partitioning).IsMaxLength(); this.Property(x => x.Filtering).IsMaxLength(); this.Property(x => x.LastExecutionMessage).HasMaxLength(4000); + this.Ignore(x => x.FileType); + this.HasRequired(x => x.ScheduleTask) .WithMany() .HasForeignKey(x => x.SchedulingTaskId) diff --git a/src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.cs b/src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.cs deleted file mode 100644 index f4c69b6734..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.cs +++ /dev/null @@ -1,105 +0,0 @@ -namespace SmartStore.Data.Migrations -{ - using System.Data.Entity.Migrations; - using SmartStore.Core.Domain.Customers; - using SmartStore.Core.Domain.Security; - using SmartStore.Data.Setup; - - public partial class ExportFramework : DbMigration, ILocaleResourcesProvider, IDataSeeder - { - public override void Up() - { - CreateTable( - "dbo.ExportProfile", - c => new - { - Id = c.Int(nullable: false, identity: true), - Name = c.String(nullable: false, maxLength: 100), - Enabled = c.Boolean(nullable: false), - ProviderSystemName = c.String(nullable: false, maxLength: 4000), - EntityType = c.String(nullable: false, maxLength: 100), - SchedulingHours = c.Int(nullable: false), - SchedulingTaskId = c.Int(nullable: false), - ProfileGuid = c.Guid(nullable: false), - Partitioning = c.String(), - Filtering = c.String(), - LastExecutionStartUtc = c.DateTime(), - LastExecutionEndUtc = c.DateTime(), - LastExecutionMessage = c.String(maxLength: 4000), - }) - .PrimaryKey(t => t.Id) - .ForeignKey("dbo.ScheduleTask", t => t.SchedulingTaskId) - .Index(t => t.SchedulingTaskId); - - } - - public override void Down() - { - DropForeignKey("dbo.ExportProfile", "SchedulingTaskId", "dbo.ScheduleTask"); - DropIndex("dbo.ExportProfile", new[] { "SchedulingTaskId" }); - DropTable("dbo.ExportProfile"); - } - - public bool RollbackOnFailure - { - get { return false; } - } - - public void Seed(SmartObjectContext context) - { - context.MigrateLocaleResources(MigrateLocaleResources); - - var permissionMigrator = new PermissionMigrator(context); - - permissionMigrator.AddPermission(new PermissionRecord - { - Name = "Admin area. Manage Exports", - SystemName = "ManageExports", - Category = "Configuration" - }, new string[] { SystemCustomerRoleNames.Administrators }); - } - - public void MigrateLocaleResources(LocaleResourcesBuilder builder) - { - builder.AddOrUpdate("Common.Enabled", - "Enabled", - "Aktiviert"); - - builder.AddOrUpdate("Admin.Configuration.Export.Name", - "Profile name", - "Profilname", - "Specifies the name of the export profile.", - "Legt den Namen des Exportprofils fest."); - - builder.AddOrUpdate("Admin.Configuration.Export.ProviderSystemName", - "Provider name", - "Provider-Name", - "Specifies the name of the export provider.", - "Legt den Namen des Export-Providers fest."); - - builder.AddOrUpdate("Admin.Configuration.Export.EntityType", - "Entity type", - "Entittstyp", - "Specifies the type of the entity to be exported.", - "Legt den Typ der zu exportierenden Entitt fest."); - - builder.AddOrUpdate("Admin.Configuration.Export.FileType", - "File type", - "Dateityp", - "The file type of the exported data.", - "Der Dateityp der exportierten Daten."); - - builder.AddOrUpdate("Admin.Configuration.Export.SchedulingHours", - "Hours (interval)", - "Stunden (Intervall)", - "Specifies the interval in hours to which the export should execute automatically.", - "Legt das Intervall in Stunden fest, zu dem der Export automatisch erfolgen soll."); - - builder.AddOrUpdate("Admin.Configuration.Export.LastExecution", - "Last execution", - "Letzte Ausfhrung", - "Information about the last execution of the export.", - "Informationen zur letzten Ausfhrung des Exports."); - } - } -} diff --git a/src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.resx b/src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.resx deleted file mode 100644 index a08ee1d639..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.Designer.cs index 4e2831a004..0e3246e714 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201507301550466_ExportFramework.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class ExportFramework : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201507301550466_ExportFramework"; } + get { return "201508011828241_ExportFramework"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.cs b/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.cs new file mode 100644 index 0000000000..86c6f7c509 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.cs @@ -0,0 +1,157 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + using SmartStore.Core.Domain.Customers; + using SmartStore.Core.Domain.Security; + using SmartStore.Data.Setup; + + public partial class ExportFramework : DbMigration, ILocaleResourcesProvider, IDataSeeder + { + public override void Up() + { + CreateTable( + "dbo.ExportProfile", + c => new + { + Id = c.Int(nullable: false, identity: true), + Name = c.String(nullable: false, maxLength: 100), + ProviderSystemName = c.String(nullable: false, maxLength: 4000), + Enabled = c.Boolean(nullable: false), + FileTypeId = c.Int(nullable: false), + SchedulingTaskId = c.Int(nullable: false), + ProfileGuid = c.Guid(nullable: false), + Partitioning = c.String(), + Filtering = c.String(), + LastExecutionStartUtc = c.DateTime(), + LastExecutionEndUtc = c.DateTime(), + LastExecutionMessage = c.String(maxLength: 4000), + }) + .PrimaryKey(t => t.Id) + .ForeignKey("dbo.ScheduleTask", t => t.SchedulingTaskId) + .Index(t => t.SchedulingTaskId); + + } + + public override void Down() + { + DropForeignKey("dbo.ExportProfile", "SchedulingTaskId", "dbo.ScheduleTask"); + DropIndex("dbo.ExportProfile", new[] { "SchedulingTaskId" }); + DropTable("dbo.ExportProfile"); + } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + + var permissionMigrator = new PermissionMigrator(context); + + permissionMigrator.AddPermission(new PermissionRecord + { + Name = "Admin area. Manage Exports", + SystemName = "ManageExports", + Category = "Configuration" + }, new string[] { SystemCustomerRoleNames.Administrators }); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Common.Enabled", "Enabled", "Aktiviert"); + builder.AddOrUpdate("Common.Provider", "Provider", "Provider"); + builder.AddOrUpdate("Common.Profile", "Profile", "Profil"); + builder.AddOrUpdate("Common.Partition", "Partition", "Aufteilung"); + builder.AddOrUpdate("Common.Image", "Image", "Bild"); + + + builder.AddOrUpdate("Admin.Configuration.Export.ProviderSystemName.Validate", + "There were no export provider found for system name \"{0}\". A provider is mandatory for an export profile.", + "Es wurde kein Export-Provider mit dem Systemnamen \"{0}\" gefunden. Ein Provider ist fr ein Exportprofil zwingend erforderlich."); + + builder.AddOrUpdate("Admin.Configuration.Export.NoProfiles", + "There were no export profiles found.", + "Es wurden keine Exportprofile gefunden."); + + + builder.AddOrUpdate("Admin.Configuration.Export.ProviderSystemName", + "Provider", + "Provider", + "Specifies the export provider. It is responsible for the individual formatting of the export data.", + "Legt den Export-Provider fest. Er ist fr die individuelle Formatierung der zu exportierenden Daten zustndig."); + + builder.AddOrUpdate("Admin.Configuration.Export.EntityType", + "Entity", + "Entitt", + "The entity type the provider processes.", + "Der Entittstyp, den der Provider verarbeitet."); + + + builder.AddOrUpdate("Admin.Configuration.Export.Name", + "Name of profile", + "Name des Profils", + "Specifies the name of the export profile.", + "Legt den Namen des Exportprofils fest."); + + builder.AddOrUpdate("Admin.Configuration.Export.FileType", + "File type", + "Dateityp", + "The file type of the exported data.", + "Der Dateityp der exportierten Daten."); + + builder.AddOrUpdate("Admin.Configuration.Export.SchedulingHours", + "Hours (interval)", + "Stunden (Intervall)", + "Specifies the interval in hours to which the export should execute automatically.", + "Legt das Intervall in Stunden fest, zu dem der Export automatisch erfolgen soll."); + + builder.AddOrUpdate("Admin.Configuration.Export.LastExecution", + "Last execution", + "Letzte Ausfhrung", + "Information about the last execution of the export.", + "Informationen zur letzten Ausfhrung des Exports."); + + + builder.AddOrUpdate("Admin.Configuration.Export.Segmentation.Offset", + "Offset", + "Abstand", + "Specifies the number of records to be skipped.", + "Legt die Anzahl der zu berspringenden Datenstze fest."); + + builder.AddOrUpdate("Admin.Configuration.Export.Segmentation.Limit", + "Limit", + "Begrenzung", + "Specifies how many records to be loaded per database round-trip.", + "Legt die Anzahl der Datenstze fest, die pro Datenbankaufruf geladen werden sollen."); + + builder.AddOrUpdate("Admin.Configuration.Export.Segmentation.BatchSize", + "Batch size", + "Stapelgre", + "Specifies the maximum number of records of one processed batch.", + "Legt die maximale Anzahl der Datenstze eines Vearbeitungsstapels fest."); + + builder.AddOrUpdate("Admin.Configuration.Export.Segmentation.PerStore", + "Per store", + "Per Shop", + "Specifies whether to start a separate run-through for each store.", + "Legt fest, ob fr jeden Shop ein separater Verarbeitungsdurchlauf erfolgen soll."); + + + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportFileType.Xml", "XML (Extensible Markup Language)", "XML (Extensible Markup Language)"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportFileType.Xls", "XLS (Microsoft Excel)", "XLS (Microsoft Excel)"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportFileType.Csv", "CSV (Delimiter Separated Values)", "CSV (Trennzeichen getrennt)"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportFileType.Txt", "TXT (Plain text)", "TXT (Einfacher Text)"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportFileType.Pdf", "PDF (Portable Document Format)", "PDF (Portables Dokumentenformat)"); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Product", "Product", "Produkt"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Category", "Category", "Warengruppe"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Manufacturer", "Manufacturer", "Hersteller"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Customer", "Customer", "Kunde"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Order", "Order", "Auftrag"); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.resx b/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.resx new file mode 100644 index 0000000000..ce78c71be0 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index 9bde1ba879..b39ffa09d7 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -332,9 +332,9 @@ 201507250039446_Merge2.cs - - - 201507301550466_ExportFramework.cs + + + 201508011828241_ExportFramework.cs @@ -633,8 +633,8 @@ 201507250039446_Merge2.cs - - 201507301550466_ExportFramework.cs + + 201508011828241_ExportFramework.cs diff --git a/src/Libraries/SmartStore.Services/Export/ExportExtensions.cs b/src/Libraries/SmartStore.Services/Export/ExportExtensions.cs new file mode 100644 index 0000000000..3ea12ec406 --- /dev/null +++ b/src/Libraries/SmartStore.Services/Export/ExportExtensions.cs @@ -0,0 +1,16 @@ +using System.Linq; +using SmartStore.Core.Plugins; + +namespace SmartStore.Services.Export +{ + public static class ExportExtensions + { + public static bool IsValid(this Provider provider) + { + return ( + provider != null && + provider.Value.SupportedFileTypes != null && provider.Value.SupportedFileTypes.Any() + ); + } + } +} diff --git a/src/Libraries/SmartStore.Services/Export/ExportService.cs b/src/Libraries/SmartStore.Services/Export/ExportService.cs new file mode 100644 index 0000000000..14be36fc7e --- /dev/null +++ b/src/Libraries/SmartStore.Services/Export/ExportService.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SmartStore.Core.Data; +using SmartStore.Core.Domain; +using SmartStore.Core.Domain.Tasks; +using SmartStore.Core.Events; +using SmartStore.Core.Plugins; +using SmartStore.Services.Tasks; + +namespace SmartStore.Services.Export +{ + public partial class ExportService : IExportService + { + private const int _defaultSchedulingHours = 6; + + private readonly IRepository _exportProfileRepository; + private readonly IEventPublisher _eventPublisher; + private readonly IScheduleTaskService _scheduleTaskService; + private readonly IProviderManager _providerManager; + + public ExportService( + IRepository exportProfileRepository, + IEventPublisher eventPublisher, + IScheduleTaskService scheduleTaskService, + IProviderManager providerManager) + { + _exportProfileRepository = exportProfileRepository; + _eventPublisher = eventPublisher; + _scheduleTaskService = scheduleTaskService; + _providerManager = providerManager; + } + + #region Export profiles + + public virtual ExportProfile InsertExportProfile(Provider provider) + { + if (provider == null) + throw new ArgumentNullException("provider"); + + var guid = Guid.NewGuid(); + var name = provider.Metadata.FriendlyName; + var systemName = provider.Metadata.SystemName; + var taskType = "SmartStore.Services.ExportImport.{0}Task.{1}, SmartStore.Services".FormatInvariant(systemName, guid.ToString().Replace("-", "")); + + if (name.IsEmpty()) + name = systemName; + + var task = new ScheduleTask + { + Name = string.Concat(name, " Export Task"), + Seconds = _defaultSchedulingHours * 3600, + Type = taskType, + Enabled = false, + StopOnError = false, + IsHidden = true + }; + + _scheduleTaskService.InsertTask(task); + + var profile = new ExportProfile + { + Name = name, + Enabled = true, + ProviderSystemName = systemName, + ProfileGuid = guid, + SchedulingTaskId = task.Id, + FileType = provider.Value.SupportedFileTypes.FirstOrDefault() + }; + + _exportProfileRepository.Insert(profile); + + task.Alias = profile.Id.ToString(); + _scheduleTaskService.UpdateTask(task); + + _eventPublisher.EntityInserted(profile); + + return profile; + } + + public virtual void UpdateExportProfile(ExportProfile profile) + { + if (profile == null) + throw new ArgumentNullException("profile"); + + _exportProfileRepository.Update(profile); + + _eventPublisher.EntityUpdated(profile); + } + + public virtual void DeleteExportProfile(ExportProfile profile) + { + if (profile == null) + throw new ArgumentNullException("profile"); + + int scheduleTaskId = profile.SchedulingTaskId; + + _exportProfileRepository.Delete(profile); + + var scheduleTask = _scheduleTaskService.GetTaskById(scheduleTaskId); + _scheduleTaskService.DeleteTask(scheduleTask); + + _eventPublisher.EntityDeleted(profile); + } + + public virtual IQueryable GetExportProfiles(bool? enabled = null) + { + var query = + from x in _exportProfileRepository.Table.Expand(x => x.ScheduleTask) + select x; + + if (enabled.HasValue) + { + query = query.Where(x => x.Enabled == enabled.Value); + } + + return query.OrderBy(x => x.Name); + } + + public virtual ExportProfile GetExportProfileById(int id) + { + if (id == 0) + return null; + + return _exportProfileRepository.GetById(id); + } + + + public virtual IEnumerable> LoadAllExportProviders(int storeId = 0) + { + var allProviders = _providerManager.GetAllProviders(storeId) + .Where(x => x.IsValid()); + + return allProviders; + } + + public virtual Provider LoadProvider(string systemName, int storeId = 0) + { + var provider = _providerManager.GetProvider(systemName, storeId); + + return (provider.IsValid() ? provider : null); + } + + #endregion + } +} diff --git a/src/Libraries/SmartStore.Services/Export/IExportProvider.cs b/src/Libraries/SmartStore.Services/Export/IExportProvider.cs new file mode 100644 index 0000000000..752f6096ed --- /dev/null +++ b/src/Libraries/SmartStore.Services/Export/IExportProvider.cs @@ -0,0 +1,16 @@ +using System.IO; +using SmartStore.Core.Domain; +using SmartStore.Core.Domain.Export; +using SmartStore.Core.Plugins; + +namespace SmartStore.Services.Export +{ + public partial interface IExportProvider : IProvider, IUserEditable + { + MemoryStream Execute(ExportProfile profile); + + ExportFileType[] SupportedFileTypes { get; } + + ExportEntityType EntityType { get; } + } +} diff --git a/src/Libraries/SmartStore.Services/Export/IExportService.cs b/src/Libraries/SmartStore.Services/Export/IExportService.cs new file mode 100644 index 0000000000..3e8e2e60df --- /dev/null +++ b/src/Libraries/SmartStore.Services/Export/IExportService.cs @@ -0,0 +1,58 @@ +using System.Collections.Generic; +using System.Linq; +using SmartStore.Core.Domain; +using SmartStore.Core.Plugins; + +namespace SmartStore.Services.Export +{ + public interface IExportService + { + /// + /// Inserts an export profile + /// + /// Export provider + /// New export profile + ExportProfile InsertExportProfile(Provider provider); + + /// + /// Updates an export profile + /// + /// Export profile + void UpdateExportProfile(ExportProfile profile); + + /// + /// Deletes an export profile + /// + /// Export profile + void DeleteExportProfile(ExportProfile profile); + + /// + /// Get queryable export profiles + /// + /// Whether to filter enabled or disabled profiles + /// Export profiles + IQueryable GetExportProfiles(bool? enabled = null); + + /// + /// Gets an export profile by identifier + /// + /// Export profile identifier + /// Export profile + ExportProfile GetExportProfileById(int id); + + /// + /// Load all export providers + /// + /// Store identifier + /// Export providers + IEnumerable> LoadAllExportProviders(int storeId = 0); + + /// + /// Load export provider by system name + /// + /// Provider system name + /// Store identifier + /// Export provider + Provider LoadProvider(string systemName, int storeId = 0); + } +} diff --git a/src/Libraries/SmartStore.Services/ExportImport/ExportService.cs b/src/Libraries/SmartStore.Services/ExportImport/ExportService.cs deleted file mode 100644 index c19a63129a..0000000000 --- a/src/Libraries/SmartStore.Services/ExportImport/ExportService.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Linq; -using SmartStore.Core.Data; -using SmartStore.Core.Domain; -using SmartStore.Core.Events; -using SmartStore.Services.Tasks; - -namespace SmartStore.Services.ExportImport -{ - public partial class ExportService : IExportService - { - private readonly IRepository _exportProfileRepository; - private readonly IEventPublisher _eventPublisher; - private readonly Lazy _scheduleTaskService; - - public ExportService( - IRepository exportProfileRepository, - IEventPublisher eventPublisher, - Lazy scheduleTaskService) - { - _exportProfileRepository = exportProfileRepository; - _eventPublisher = eventPublisher; - _scheduleTaskService = scheduleTaskService; - } - - #region Export profiles - - public virtual void InsertExportProfile(ExportProfile profile) - { - if (profile == null) - throw new ArgumentNullException("profile"); - - _exportProfileRepository.Insert(profile); - - _eventPublisher.EntityInserted(profile); - } - - public virtual void UpdateExportProfile(ExportProfile profile) - { - if (profile == null) - throw new ArgumentNullException("profile"); - - _exportProfileRepository.Update(profile); - - _eventPublisher.EntityUpdated(profile); - } - - public virtual void DeleteExportProfile(ExportProfile profile) - { - if (profile == null) - throw new ArgumentNullException("profile"); - - if (profile.ScheduleTask != null) - { - _scheduleTaskService.Value.DeleteTask(profile.ScheduleTask); - } - - _exportProfileRepository.Delete(profile); - - _eventPublisher.EntityDeleted(profile); - } - - public virtual IQueryable GetExportProfiles(bool? enabled = null) - { - var query = - from x in _exportProfileRepository.Table.Expand(x => x.ScheduleTask) - select x; - - if (enabled.HasValue) - { - query = query.Where(x => x.Enabled == enabled.Value); - } - - return query.OrderBy(x => x.Name); - } - - #endregion - } -} diff --git a/src/Libraries/SmartStore.Services/ExportImport/IExportService.cs b/src/Libraries/SmartStore.Services/ExportImport/IExportService.cs deleted file mode 100644 index 0e8389011b..0000000000 --- a/src/Libraries/SmartStore.Services/ExportImport/IExportService.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Linq; -using SmartStore.Core.Domain; - -namespace SmartStore.Services.ExportImport -{ - public interface IExportService - { - /// - /// Inserts an export profile - /// - /// Export profile - void InsertExportProfile(ExportProfile profile); - - /// - /// Updates an export profile - /// - /// Export profile - void UpdateExportProfile(ExportProfile profile); - - /// - /// Deletes an export profile - /// - /// Export profile - void DeleteExportProfile(ExportProfile profile); - - /// - /// Get queryable export profiles - /// - /// Whether to filter enabled or disabled profiles - /// - IQueryable GetExportProfiles(bool? enabled = null); - } -} diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index 33484e0895..db5a654dd3 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -162,8 +162,10 @@ - - + + + + diff --git a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs index 29357d57db..e361097cc9 100644 --- a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs +++ b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs @@ -41,6 +41,7 @@ using SmartStore.Services.Directory; using SmartStore.Services.Discounts; using SmartStore.Services.Events; +using SmartStore.Services.Export; using SmartStore.Services.ExportImport; using SmartStore.Services.Filter; using SmartStore.Services.Forums; @@ -794,6 +795,7 @@ protected override void Load(ContainerBuilder builder) RegisterAsSpecificProvider(type, systemName, registration); RegisterAsSpecificProvider(type, systemName, registration); RegisterAsSpecificProvider(type, systemName, registration); + RegisterAsSpecificProvider(type, systemName, registration); } } @@ -919,6 +921,10 @@ private string ProviderTypeToKnownGroupName(Type implType) { return "CMS"; } + else if (typeof(IExportProvider).IsAssignableFrom(implType)) + { + return "Exporting"; + } return null; } diff --git a/src/Presentation/SmartStore.Web/Administration/Content/admin.less b/src/Presentation/SmartStore.Web/Administration/Content/admin.less index 75d3bfcdb8..dcb332fcb7 100644 --- a/src/Presentation/SmartStore.Web/Administration/Content/admin.less +++ b/src/Presentation/SmartStore.Web/Administration/Content/admin.less @@ -738,7 +738,6 @@ td.adminTitle > .ctl-label { label { display: inline-block; padding-right: 20px; - margin-top: 1px; margin-bottom: 0; } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs index 839265dfef..cd8bf2190a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs @@ -1,12 +1,18 @@ -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using System.Web.Mvc; using SmartStore.Admin.Models.Export; using SmartStore.Core; using SmartStore.Core.Domain; +using SmartStore.Core.Domain.Export; +using SmartStore.Core.Plugins; using SmartStore.Services; -using SmartStore.Services.ExportImport; +using SmartStore.Services.Export; +using SmartStore.Services.Media; using SmartStore.Services.Security; using SmartStore.Web.Framework.Controllers; +using SmartStore.Web.Framework.Plugins; using Telerik.Web.Mvc; namespace SmartStore.Admin.Controllers @@ -16,13 +22,62 @@ public class ExportController : AdminControllerBase { private readonly ICommonServices _services; private readonly IExportService _exportService; + private readonly PluginMediator _pluginMediator; + private readonly IPictureService _pictureService; public ExportController( ICommonServices services, - IExportService exportService) + IExportService exportService, + PluginMediator pluginMediator, + IPictureService pictureService) { _services = services; _exportService = exportService; + _pluginMediator = pluginMediator; + _pictureService = pictureService; + } + + private void PrepareExportProfileModel(ExportProfileModel model, ExportProfile profile, Provider provider) + { + var partition = XmlHelper.Deserialize(profile.Partitioning); + + model.AvailableFileTypes = new List(); + + model.Id = profile.Id; + model.Name = profile.Name; + model.ProviderSystemName = profile.ProviderSystemName; + model.Enabled = profile.Enabled; + model.FileType = profile.FileType; + model.FileTypeName = profile.FileType.ToString().ToUpper(); + model.SchedulingHours = profile.ScheduleTask.Seconds / 3600; + + model.Offset = partition.Offset; + model.Limit = partition.Limit; + model.BatchSize = partition.BatchSize; + model.PerStore = partition.PerStore; + + if (provider != null) + { + model.ThumbnailUrl = _pluginMediator.GetIconUrl(provider.Metadata); + + if (model.ThumbnailUrl.IsEmpty()) + model.ThumbnailUrl = _pictureService.GetDefaultPictureUrl(48); + else + model.ThumbnailUrl = Url.Content(model.ThumbnailUrl); + + model.ProviderFriendlyName = _pluginMediator.GetLocalizedFriendlyName(provider.Metadata); + + model.EntityType = T("Enums.SmartStore.Core.Domain.ExportEntityType." + provider.Value.EntityType.ToString()); + + foreach (var fileType in provider.Value.SupportedFileTypes) + { + model.AvailableFileTypes.Add(new SelectListItem + { + Text = T("Enums.SmartStore.Core.Domain.ExportFileType." + fileType.ToString()), + Value = ((int)fileType).ToString() + }); + } + } } public ActionResult Index() @@ -45,6 +100,7 @@ public ActionResult List(GridCommand command) if (_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) { + var providers = _exportService.LoadAllExportProviders().ToList(); var query = _exportService.GetExportProfiles(); var profiles = query.ToList(); @@ -52,16 +108,8 @@ public ActionResult List(GridCommand command) model.Data = profiles.Select(x => { - var profileModel = new ExportProfileModel - { - Name = x.Name, - ProviderSystemName = x.ProviderSystemName, - EntityType = x.EntityType, - Enabled = x.Enabled, - FileType = "", // TODO - SchedulingHours = x.SchedulingHours, - LastExecution = "" // TODO - }; + var profileModel = new ExportProfileModel(); + PrepareExportProfileModel(profileModel, x, providers.FirstOrDefault(y => y.Metadata.SystemName == x.ProviderSystemName)); return profileModel; }); @@ -69,5 +117,136 @@ public ActionResult List(GridCommand command) return new JsonResult { Data = model }; } + + public ActionResult Create() + { + if (_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + { + var model = new ExportProfileModel(); + + model.AvailableExportProviders = _exportService.LoadAllExportProviders() + .Select(x => + { + var item = new SelectListItem + { + Text = x.Metadata.FriendlyName, + Value = x.Metadata.SystemName + }; + + return item; + }).ToList(); + + return PartialView(model); + } + + return Content(T("Admin.AccessDenied.Description")); + } + + [HttpPost] + public ActionResult Create(ExportProfileModel model) + { + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + if (model.ProviderSystemName.HasValue()) + { + var provider = _exportService.LoadProvider(model.ProviderSystemName); + if (provider != null) + { + var profile = _exportService.InsertExportProfile(provider); + + PrepareExportProfileModel(model, profile, provider); + + return RedirectToAction("Edit", new { id = profile.Id }); + } + } + + NotifyError(T("Admin.Configuration.Export.ProviderSystemName.Validate", model.ProviderSystemName.NaIfEmpty())); + + return RedirectToAction("List"); + } + + public ActionResult Edit(int id) + { + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + var profile = _exportService.GetExportProfileById(id); + if (profile == null) + return RedirectToAction("List"); + + var provider = _exportService.LoadProvider(profile.ProviderSystemName); + + var model = new ExportProfileModel(); + + PrepareExportProfileModel(model, profile, provider); + + return View(model); + } + + [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] + [FormValueRequired("save", "save-continue")] + public ActionResult Edit(ExportProfileModel model, bool continueEditing) + { + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + var profile = _exportService.GetExportProfileById(model.Id); + if (profile == null) + return RedirectToAction("List"); + + if (ModelState.IsValid) + { + var partition = new ExportPartition + { + Offset = model.Offset, + Limit = model.Limit, + BatchSize = model.BatchSize, + PerStore = model.PerStore + }; + + profile.Name = model.Name; + profile.Enabled = model.Enabled; + profile.ScheduleTask.Seconds = model.SchedulingHours * 3600; + profile.FileType = model.FileType; + profile.Partitioning = XmlHelper.Serialize(partition); + + _exportService.UpdateExportProfile(profile); + + NotifySuccess(T("Admin.Common.DataSuccessfullySaved")); + + return (continueEditing ? RedirectToAction("Edit", new { id = profile.Id }) : RedirectToAction("List")); + } + + PrepareExportProfileModel(model, profile, _exportService.LoadProvider(model.ProviderSystemName)); + + return View(model); + } + + [HttpPost, ActionName("Delete")] + public ActionResult DeleteConfirmed(int id) + { + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + var profile = _exportService.GetExportProfileById(id); + if (profile == null) + return RedirectToAction("List"); + + try + { + _exportService.DeleteExportProfile(profile); + + NotifySuccess(T("Admin.Common.TaskSuccessfullyProcessed")); + + return RedirectToAction("List"); + } + catch (Exception exc) + { + NotifyError(exc); + } + + return RedirectToAction("Edit", new { id = profile.Id }); + } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs index c95bd05837..547211434c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs @@ -1,4 +1,6 @@ -using System.Web.Mvc; +using System.Collections.Generic; +using System.Web.Mvc; +using SmartStore.Core.Domain.Export; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Mvc; @@ -6,20 +8,42 @@ namespace SmartStore.Admin.Models.Export { public partial class ExportProfileModel : EntityModelBase { - [SmartResourceDisplayName("Admin.Configuration.Export.Name")] - public string Name { get; set; } + [SmartResourceDisplayName("Common.Image")] + public string ThumbnailUrl { get; set; } + public string ThumbnailClasses + { + get + { + return "grid-icon"; + } + } [SmartResourceDisplayName("Admin.Configuration.Export.ProviderSystemName")] public string ProviderSystemName { get; set; } + public List AvailableExportProviders { get; set; } + + [SmartResourceDisplayName("Common.Provider")] + public string ProviderFriendlyName { get; set; } [SmartResourceDisplayName("Admin.Configuration.Export.EntityType")] public string EntityType { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Export.SupportedFileTypes")] + public string SupportedFileTypes { get; set; } + + + [SmartResourceDisplayName("Admin.Configuration.Export.Name")] + public string Name { get; set; } + [SmartResourceDisplayName("Common.Enabled")] public bool Enabled { get; set; } [SmartResourceDisplayName("Admin.Configuration.Export.FileType")] - public string FileType { get; set; } + public ExportFileType FileType { get; set; } + public List AvailableFileTypes { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.FileType")] + public string FileTypeName { get; set; } [SmartResourceDisplayName("Admin.Configuration.Export.SchedulingHours")] public int SchedulingHours { get; set; } @@ -27,5 +51,18 @@ public partial class ExportProfileModel : EntityModelBase [SmartResourceDisplayName("Admin.Configuration.Export.LastExecution")] [AllowHtml] public string LastExecution { get; set; } + + + [SmartResourceDisplayName("Admin.Configuration.Export.Segmentation.Offset")] + public int Offset { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Segmentation.Limit")] + public int Limit { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Segmentation.BatchSize")] + public int BatchSize { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Segmentation.PerStore")] + public bool PerStore { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index 0f7013c4e4..ef978b7e3a 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -501,6 +501,8 @@ + + diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml new file mode 100644 index 0000000000..b6f318d5b4 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml @@ -0,0 +1,27 @@ +@using SmartStore.Admin.Models.Export +@model ExportProfileModel +@{ + Layout = null; +} + +
    + @if(Model.AvailableExportProviders.Count > 0) + { +
    + + + + + +
    + @Html.SmartLabelFor(model => model.ProviderSystemName) + + @Html.DropDownListFor(model => model.ProviderSystemName, Model.AvailableExportProviders) +
    +
    + } + else + { + @T("Admin.Configuration.Export.NoProfiles") + } +
    \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml new file mode 100644 index 0000000000..1a594c0333 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml @@ -0,0 +1,135 @@ +@model ExportProfileModel +@using SmartStore.Core.Domain.Export; +@using SmartStore.Admin.Models.Export; +@{ + var title = string.Concat(T("Admin.Common.Edit"), " ", T("Common.Profile")); + ViewBag.Title = title; +} + +@using (Html.BeginForm()) +{ +
    +
    + + @title - @Model.Name @Html.ActionLink("(" + T("Admin.Common.BackToList") + ")", "List") +
    +
    + + + +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + @Html.SmartLabelFor(model => model.ProviderFriendlyName) + + @Model.ProviderFriendlyName.NaIfEmpty() (@(Model.ProviderSystemName.NaIfEmpty())) +
    + @Html.SmartLabelFor(model => model.Name) + + @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
    + @Html.SmartLabelFor(model => model.Enabled) + + @Html.EditorFor(model => model.Enabled) + @Html.ValidationMessageFor(model => model.Enabled) +
    + @Html.SmartLabelFor(model => model.EntityType) + + @Html.DisplayFor(model => model.EntityType) +
    + @Html.SmartLabelFor(model => model.FileType) + + @Html.DropDownListFor(model => model.FileType, Model.AvailableFileTypes) + @Html.ValidationMessageFor(model => model.FileType) +
    + @Html.SmartLabelFor(model => model.SchedulingHours) + + @Html.EditorFor(model => model.SchedulingHours) + @Html.ValidationMessageFor(model => model.SchedulingHours) +
    +
    +
    + @T("Common.Partition") +
    +
    +
    + @Html.SmartLabelFor(model => model.Offset) + + @Html.EditorFor(model => model.Offset) + @Html.ValidationMessageFor(model => model.Offset) +
    + @Html.SmartLabelFor(model => model.Limit) + + @Html.EditorFor(model => model.Limit) + @Html.ValidationMessageFor(model => model.Limit) +
    + @Html.SmartLabelFor(model => model.BatchSize) + + @Html.EditorFor(model => model.BatchSize) + @Html.ValidationMessageFor(model => model.BatchSize) +
    + @Html.SmartLabelFor(model => model.PerStore) + + @Html.EditorFor(model => model.PerStore) + @Html.ValidationMessageFor(model => model.PerStore) +
    +
    +} + +@Html.DeleteConfirmation("export-profile-delete") + + diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml index 17122852e5..e559017485 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml @@ -1,16 +1,17 @@ -@using SmartStore.Admin.Models.Export -@using Telerik.Web.Mvc.UI +@using SmartStore.Core.Domain.Export; +@using SmartStore.Admin.Models.Export; +@using Telerik.Web.Mvc.UI; @{ ViewBag.Title = T("Common.Export").Text; } @@ -34,26 +35,118 @@ }) .Columns(columns => { + columns.Bound(x => x.ThumbnailUrl) + .Width(70) + .Centered() + .Template( + @ + @item.Id + + ) + .ClientTemplate("<#= Id #>"); columns.Bound(x => x.Name) .Width(400) .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })) .ClientTemplate("\"><#= Name #>"); - columns.Bound(x => x.ProviderSystemName); - columns.Bound(x => x.EntityType); + columns.Bound(x => x.ProviderSystemName) + .Template(x => "{0} ({1})".FormatInvariant(x.ProviderFriendlyName, x.ProviderSystemName)) + .ClientTemplate("<#= ProviderFriendlyName #> (<#= ProviderSystemName #>)"); columns.Bound(x => x.Enabled) .Width(100) .Template(item => @Html.SymbolForBool(item.Enabled)) .ClientTemplate(@Html.SymbolForBool("Enabled")) .Centered(); - columns.Bound(x => x.FileType); - columns.Bound(x => x.SchedulingHours); + columns.Bound(x => x.EntityType); + columns.Bound(x => x.FileTypeName) + .Centered(); + columns.Bound(x => x.SchedulingHours) + .Centered(); columns.Bound(x => x.LastExecution) .ReadOnly(); }) - .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "Export")) - .ClientEvents(events => events.OnRowDataBound("onRowDataBound_ExportProfiles")) - .EnableCustomBinding(true)) + .DataBinding(dataBinding => dataBinding.Ajax().Select("List", "Export")) + .ClientEvents(events => events.OnRowDataBound("onRowDataBound_ExportProfiles")) + .EnableCustomBinding(true)) + + + + diff --git a/src/Presentation/SmartStore.Web/Administration/sitemap.config b/src/Presentation/SmartStore.Web/Administration/sitemap.config index 0ba3a9156e..6a43d810d8 100644 --- a/src/Presentation/SmartStore.Web/Administration/sitemap.config +++ b/src/Presentation/SmartStore.Web/Administration/sitemap.config @@ -127,7 +127,7 @@ - + From 47324752b9fd841535ab02093b83c25fd3ee8c6b Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Mon, 3 Aug 2015 21:34:23 +0200 Subject: [PATCH 0321/1256] Fixed compilation errors --- .../Orders/OrderProcessingService.cs | 6 +- .../Services/AmazonPayApi.cs | 18 ++-- .../Services/AmazonPayService.cs | 6 +- .../Views/Shipping/Restrictions.cshtml | 91 ------------------- .../Controllers/ProductController.cs | 2 + 5 files changed, 18 insertions(+), 105 deletions(-) delete mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml diff --git a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs index 64ac5318b2..4995d1bd38 100644 --- a/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs +++ b/src/Libraries/SmartStore.Services/Orders/OrderProcessingService.cs @@ -796,14 +796,14 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR #endregion #region Addresses & pre payment workflow - + // give payment processor the opportunity to fullfill billing address var preProcessPaymentResult = _paymentService.PreProcessPayment(processPaymentRequest); if (!preProcessPaymentResult.Success) { result.Errors.AddRange(preProcessPaymentResult.Errors); - result.Errors.Add(T("Common.Error.PreProcessPayment")); + result.Errors.Add(_localizationService.GetResource("Common.Error.PreProcessPayment")); return result; } @@ -1338,7 +1338,7 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR #region Notifications, notes and attributes //notes, messages - order.OrderNotes.Add(new OrderNote() + order.OrderNotes.Add(new OrderNote { Note = TNote("OrderPlaced"), DisplayToCustomer = false, diff --git a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs index 6e69b3596c..a6241f8409 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs @@ -23,6 +23,7 @@ using SmartStore.Core.Plugins; using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Discounts; +using SmartStore.Core.Domain.Stores; namespace SmartStore.AmazonPay.Api { @@ -221,7 +222,7 @@ public OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, st if (orderTotalAmount.HasValue) { - attributes.OrderTotal = new OrderTotal() + attributes.OrderTotal = new OrderTotal { Amount = orderTotalAmount.Value.ToString("0.00", CultureInfo.InvariantCulture), CurrencyCode = currencyCode ?? "EUR" @@ -230,7 +231,7 @@ public OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, st if (orderGuid.HasValue()) { - attributes.SellerOrderAttributes = new SellerOrderAttributes() + attributes.SellerOrderAttributes = new SellerOrderAttributes { SellerOrderId = orderGuid, StoreName = storeName @@ -264,10 +265,10 @@ public OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, st if (shoppingCartTotalBase.HasValue) { - var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); - + var currency = (Currency)null; // TODO: Merge _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); return SetOrderReferenceDetails(client, orderReferenceId, shoppingCartTotalBase, currency.CurrencyCode); } + return null; } @@ -435,14 +436,15 @@ public void Capture(AmazonPayClient client, CapturePaymentRequest capture, Captu result.NewPaymentStatus = capture.Order.PaymentStatus; var request = new CaptureRequest(); - var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + var store = (Store)null; // TODO: MERGE _storeService.GetStoreById(capture.Order.StoreId); + var currency = _currencyService.GetCurrencyById(store.PrimaryStoreCurrencyId); request.SellerId = client.Settings.SellerId; request.AmazonAuthorizationId = capture.Order.AuthorizationTransactionId; request.CaptureReferenceId = GetRandomId("Capture"); //request.SellerCaptureNote = client.Settings.SellerNoteCapture.Truncate(255); - request.CaptureAmount = new Price() + request.CaptureAmount = new Price { Amount = capture.Order.OrderTotal.ToString("0.00", CultureInfo.InvariantCulture), CurrencyCode = currency.CurrencyCode @@ -532,7 +534,7 @@ public string Refund(AmazonPayClient client, RefundPaymentRequest refund, Refund result.NewPaymentStatus = refund.Order.PaymentStatus; string amazonRefundId = null; - var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + var currency = (Currency)null; // TODO: MERGE _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); var request = new RefundRequest(); request.SellerId = client.Settings.SellerId; @@ -540,7 +542,7 @@ public string Refund(AmazonPayClient client, RefundPaymentRequest refund, Refund request.RefundReferenceId = GetRandomId("Refund"); //request.SellerRefundNote = client.Settings.SellerNoteRefund.Truncate(255); - request.RefundAmount = new Price() + request.RefundAmount = new Price { Amount = refund.AmountToRefund.ToString("0.00", CultureInfo.InvariantCulture), CurrencyCode = currency.CurrencyCode diff --git a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs index 04c34acd1c..722877beed 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs @@ -453,7 +453,7 @@ public AmazonPayViewModel ProcessPluginRequest(AmazonPayRequestType type, TempDa //model.IsOrderConfirmed = state.IsOrderConfirmed; } - var currency = _services.WorkContext.WorkingCurrency; + var currency = store.PrimaryStoreCurrency; var settings = _services.Settings.LoadSetting(store.Id); model.SellerId = settings.SellerId; @@ -903,7 +903,7 @@ public PreProcessPaymentResult PreProcessPayment(ProcessPaymentRequest request) var orderGuid = request.OrderGuid.ToString(); var store = _storeService.GetStoreById(request.StoreId); var customer = _customerService.GetCustomerById(request.CustomerId); - var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + var currency = store.PrimaryStoreCurrency; var settings = _services.Settings.LoadSetting(store.Id); var state = _httpContext.GetAmazonPayState(_services.Localization); var client = new AmazonPayClient(settings); @@ -972,7 +972,7 @@ public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest request) { var orderGuid = request.OrderGuid.ToString(); var store = _storeService.GetStoreById(request.StoreId); - var currency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + var currency = store.PrimaryStoreCurrency; var settings = _services.Settings.LoadSetting(store.Id); var state = _httpContext.GetAmazonPayState(_services.Localization); var client = new AmazonPayClient(settings); diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml deleted file mode 100644 index d7936aacde..0000000000 --- a/src/Presentation/SmartStore.Web/Administration/Views/Shipping/Restrictions.cshtml +++ /dev/null @@ -1,91 +0,0 @@ -@model ShippingMethodRestrictionModel -@{ - ViewBag.Title = T("Admin.Configuration.Shipping.Restrictions").Text; -} -@using (Html.BeginForm()) -{ -
    -
    - - @T("Admin.Configuration.Shipping.Restrictions") -
    -
    - -
    -
    - -
    - - @T("Admin.Configuration.Shipping.Restrictions.Description") -
    - - - - - -
    - @if (Model.AvailableCountries.Count == 0) - { - No countries defined - } - else if (Model.AvailableShippingMethods.Count == 0) - { - No shipping methods available - } - else - { - - -
    - - - - - @foreach (var sm in Model.AvailableShippingMethods) - { - - } - - - - @foreach (var c in Model.AvailableCountries) - { - - - @foreach (var sm in Model.AvailableShippingMethods) - { - var restricted = Model.Restricted.ContainsKey(c.Id) && Model.Restricted[c.Id][sm.Id]; - - } - - } - -
    - @T("Admin.Configuration.Shipping.Restrictions.Country") - - - -
    - @c.Name - - -
    -
    - } -
    -} diff --git a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs index 257885df19..2a8df6a0cb 100644 --- a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs @@ -122,6 +122,8 @@ public ProductController( this._localizationSettings = localizationSettings; this._captchaSettings = captchaSettings; this._helper = helper; + this._downloadService = downloadService; + this._localizationService = localizationService; } #endregion From c7836dcb5e6a7ff030357b31f2d953a8158a490c Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Mon, 3 Aug 2015 23:07:57 +0200 Subject: [PATCH 0322/1256] Fixed installation errors --- src/Libraries/SmartStore.Core/Domain/Media/Download.cs | 7 ++++++- src/Libraries/SmartStore.Core/Domain/Media/Picture.cs | 7 ++++++- .../SmartStore.Data/Setup/SeedData/InvariantSeedData.cs | 6 +++--- .../SmartStore.Web/Controllers/InstallController.cs | 2 +- .../Infrastructure/Installation/InstallDataSeeder.cs | 1 + 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Domain/Media/Download.cs b/src/Libraries/SmartStore.Core/Domain/Media/Download.cs index 88fb804395..0082cbfc67 100644 --- a/src/Libraries/SmartStore.Core/Domain/Media/Download.cs +++ b/src/Libraries/SmartStore.Core/Domain/Media/Download.cs @@ -10,7 +10,12 @@ namespace SmartStore.Core.Domain.Media [DataContract] public partial class Download : BaseEntity, ITransient { - /// + public Download() + { + this.UpdatedOnUtc = DateTime.UtcNow; + } + + /// /// Gets or sets a GUID /// [DataMember] diff --git a/src/Libraries/SmartStore.Core/Domain/Media/Picture.cs b/src/Libraries/SmartStore.Core/Domain/Media/Picture.cs index c47fc53836..f527b7d693 100644 --- a/src/Libraries/SmartStore.Core/Domain/Media/Picture.cs +++ b/src/Libraries/SmartStore.Core/Domain/Media/Picture.cs @@ -12,7 +12,12 @@ namespace SmartStore.Core.Domain.Media [DataContract] public partial class Picture : BaseEntity, ITransient { - private ICollection _productPictures; + public Picture() + { + this.UpdatedOnUtc = DateTime.UtcNow; + } + + private ICollection _productPictures; /// /// Gets or sets the picture binary /// diff --git a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs index 3bc2bee247..6aee45953b 100644 --- a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs +++ b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs @@ -56,7 +56,7 @@ public void Initialize(SmartObjectContext context) public IList Pictures() { - var entities = new List() + var entities = new List { CreatePicture(File.ReadAllBytes(_sampleImagesPath + "company_logo.png"), "image/png", GetSeName("company-logo")), CreatePicture(File.ReadAllBytes(_sampleImagesPath + "clouds.png"), "image/png", GetSeName("slider-bg")), @@ -7914,7 +7914,7 @@ public IList Products() #region Antonio Vivaldi: then spring - var productInstantDownloadVivaldi = new Product() + var productInstantDownloadVivaldi = new Product { ProductType = ProductType.SimpleProduct, VisibleIndividually = true, @@ -7938,7 +7938,7 @@ public IList Products() AllowBackInStockSubscriptions = false, IsDownload = true, HasSampleDownload = true, - SampleDownload = new Download() + SampleDownload = new Download { DownloadGuid = Guid.NewGuid(), ContentType = "audio/mp3", diff --git a/src/Presentation/SmartStore.Web/Controllers/InstallController.cs b/src/Presentation/SmartStore.Web/Controllers/InstallController.cs index 1ed1d7d418..e0bef97946 100644 --- a/src/Presentation/SmartStore.Web/Controllers/InstallController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/InstallController.cs @@ -545,7 +545,7 @@ protected virtual InstallationResult InstallCore(ILifetimeScope scope, InstallMo var pluginsCount = plugins.Count; var idx = 0; - using (var dbScope = new DbContextScope(autoDetectChanges: false)) { + using (var dbScope = new DbContextScope(autoDetectChanges: false, hooksEnabled: false)) { foreach (var plugin in plugins) { try diff --git a/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs b/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs index 55ad836c04..4e964cc565 100644 --- a/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs +++ b/src/Presentation/SmartStore.Web/Infrastructure/Installation/InstallDataSeeder.cs @@ -539,6 +539,7 @@ public virtual void Seed(SmartObjectContext context) _ctx.Configuration.AutoDetectChangesEnabled = false; _ctx.Configuration.ValidateOnSaveEnabled = false; + _ctx.HooksEnabled = false; _config.ProgressMessageCallback("Progress.CreatingRequiredData"); From 7f515674d323e56f1266548f6957563d7755605d Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 4 Aug 2015 00:52:26 +0200 Subject: [PATCH 0323/1256] Implemented logging for TaskScheduler --- .../Logging/LoggingExtensions.cs | 2 +- .../SmartStore.Core/Logging/TraceLogger.cs | 13 +++++++++--- .../Tasks/InitializeSchedulerFilter.cs | 11 ++++++---- .../Tasks/TaskScheduler.cs | 21 ++++++++++++++----- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs b/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs index 922ba78a78..cbcaec0d05 100644 --- a/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs +++ b/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs @@ -39,7 +39,7 @@ public static void Error(this ILogger logger, Exception exception, Customer cust private static void FilteredLog(ILogger logger, LogLevel level, string message, Exception exception = null, Customer customer = null) { - //don't log thread abort exception + // don't log thread abort exception if ((exception != null) && (exception is System.Threading.ThreadAbortException)) return; diff --git a/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs b/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs index 8bf32d705b..9cc515b7f2 100644 --- a/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs +++ b/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs @@ -5,6 +5,7 @@ using SmartStore.Core.Domain.Logging; using SmartStore.Core.Domain.Customers; using System.Diagnostics; +using SmartStore.Utilities; namespace SmartStore.Core.Logging { @@ -12,7 +13,7 @@ public class TraceLogger : DisposableObject, ILogger { private readonly TraceSource _traceSource; - public TraceLogger() : this("SmartStore.log") + public TraceLogger() : this(CommonHelper.MapPath("~/SmartStore.log")) { } @@ -85,12 +86,17 @@ public IList GetLogByIds(int[] logIds) public void InsertLog(LogContext context) { var type = LogLevelToEventType(context.LogLevel); - _traceSource.TraceEvent(type, (int)type, "{0}: {1}".FormatCurrent(type.ToString().ToUpper(), context.ShortMessage)); + var msg = context.ShortMessage; + if (context.FullMessage.HasValue()) + { + msg += "\r\n{0}".FormatCurrent(context.FullMessage); + } + _traceSource.TraceEvent(type, (int)type, "{0}: {1}".FormatCurrent(type.ToString().ToUpper(), msg)); } public void InsertLog(LogLevel logLevel, string shortMessage, string fullMessage = "", Customer customer = null) { - var context = new LogContext() + var context = new LogContext { LogLevel = logLevel, ShortMessage = shortMessage, @@ -120,6 +126,7 @@ private TraceEventType LogLevelToEventType(LogLevel level) public void Flush() { + _traceSource.Flush(); } protected override void OnDispose(bool disposing) diff --git a/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs b/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs index 1ab5570df6..9175b7a0bc 100644 --- a/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs +++ b/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs @@ -26,24 +26,27 @@ public void OnAuthorization(AuthorizationContext filterContext) { s_initializing = true; + var logger = EngineContext.Current.Resolve(); + try { var taskService = EngineContext.Current.Resolve(); var storeService = EngineContext.Current.Resolve(); var eventPublisher = EngineContext.Current.Resolve(); - var taskManager = EngineContext.Current.Resolve(); + var taskScheduler = EngineContext.Current.Resolve(); var tasks = taskService.GetAllTasks(true); taskService.CalculateNextRunTimes(tasks, true /* isAppStart */); - taskManager.SetBaseUrl(storeService, filterContext.HttpContext); - taskManager.Start(); + taskScheduler.SetBaseUrl(storeService, filterContext.HttpContext); + taskScheduler.Start(); + + logger.Information("Initialized TaskScheduler with base url '{0}'".FormatInvariant(taskScheduler.BaseUrl)); eventPublisher.Publish(new AppInitScheduledTasksEvent { ScheduledTasks = tasks }); } catch (Exception ex) { - var logger = EngineContext.Current.Resolve(); logger.Error("Error while initializing Task Scheduler", ex); } finally diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs b/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs index ff1b736ffb..79ae357366 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs @@ -9,6 +9,7 @@ using System.Web.Hosting; using SmartStore.Core.Async; using SmartStore.Core.Domain.Tasks; +using SmartStore.Core.Logging; namespace SmartStore.Services.Tasks { @@ -122,11 +123,21 @@ protected internal virtual void CallEndpoint(string url) req.GetResponseAsync().ContinueWith(t => { - if (t.IsFaulted) - { - // TODO: Now what?! Disable timer? - } - t.Result.Dispose(); + if (t.IsFaulted) + { + // TODO: Now what?! Disable timer? + using (var logger = new TraceLogger()) + { + foreach (var ex in t.Exception.InnerExceptions) + { + logger.Error("Error while calling TaskScheduler endpoint (URL: {0})".FormatInvariant(url), ex); + } + } + } + else + { + t.Result.Dispose(); + } }); } From c323360a559b9f993dbd27056e0f830f4cef86f1 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 4 Aug 2015 00:53:40 +0200 Subject: [PATCH 0324/1256] Minor fix for last commit --- src/Libraries/SmartStore.Core/Logging/TraceLogger.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs b/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs index 9cc515b7f2..c54d0e2adf 100644 --- a/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs +++ b/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs @@ -13,7 +13,7 @@ public class TraceLogger : DisposableObject, ILogger { private readonly TraceSource _traceSource; - public TraceLogger() : this(CommonHelper.MapPath("~/SmartStore.log")) + public TraceLogger() : this(CommonHelper.MapPath("~/App_Data/SmartStore.log")) { } From c01cce0526f11e417a62552df9f8e3e55256bdc2 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 4 Aug 2015 10:45:30 +0200 Subject: [PATCH 0325/1256] Some changes to new export framework --- .../Domain/DataExchange/ExportCore.cs | 14 + .../Domain/DataExchange/ExportFilter.cs | 121 +++++++ .../{Export => DataExchange}/ExportProfile.cs | 53 ++- .../Domain/Export/ExportCore.cs | 54 ---- .../SmartStore.Core/SmartStore.Core.csproj | 5 +- .../ExportProfileMap.cs | 7 +- .../201508011828241_ExportFramework.resx | 126 -------- ...1508040836122_ExportFramework.Designer.cs} | 2 +- ....cs => 201508040836122_ExportFramework.cs} | 150 ++++++++- .../201508040836122_ExportFramework.resx | 126 ++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 12 +- .../DataExchange/ExportExtensions.cs | 15 + .../{Export => DataExchange}/ExportService.cs | 13 +- .../IExportProvider.cs | 9 +- .../IExportService.cs | 2 +- .../Export/ExportExtensions.cs | 16 - .../SmartStore.Services.csproj | 8 +- .../DependencyRegistrar.cs | 2 +- .../Controllers/ExportController.cs | 203 ++++++++---- .../Models/DataExchange/ExportProfileModel.cs | 158 +++++++++ .../Models/Export/ExportProfileModel.cs | 68 ---- .../Administration/SmartStore.Admin.csproj | 2 +- .../Administration/Views/Export/Create.cshtml | 8 +- .../Administration/Views/Export/Edit.cshtml | 306 +++++++++++++++--- .../Administration/Views/Export/List.cshtml | 22 +- .../Administration/Views/Plugin/List.cshtml | 2 +- 26 files changed, 1042 insertions(+), 462 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Domain/DataExchange/ExportCore.cs create mode 100644 src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs rename src/Libraries/SmartStore.Core/Domain/{Export => DataExchange}/ExportProfile.cs (62%) delete mode 100644 src/Libraries/SmartStore.Core/Domain/Export/ExportCore.cs rename src/Libraries/SmartStore.Data/Mapping/{Export => DataExchange}/ExportProfileMap.cs (75%) delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.resx rename src/Libraries/SmartStore.Data/Migrations/{201508011828241_ExportFramework.Designer.cs => 201508040836122_ExportFramework.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201508011828241_ExportFramework.cs => 201508040836122_ExportFramework.cs} (53%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.resx create mode 100644 src/Libraries/SmartStore.Services/DataExchange/ExportExtensions.cs rename src/Libraries/SmartStore.Services/{Export => DataExchange}/ExportService.cs (90%) rename src/Libraries/SmartStore.Services/{Export => DataExchange}/IExportProvider.cs (55%) rename src/Libraries/SmartStore.Services/{Export => DataExchange}/IExportService.cs (97%) delete mode 100644 src/Libraries/SmartStore.Services/Export/ExportExtensions.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs delete mode 100644 src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportCore.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportCore.cs new file mode 100644 index 0000000000..2f513eab63 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportCore.cs @@ -0,0 +1,14 @@ +using System; + +namespace SmartStore.Core.Domain.DataExchange +{ + public enum ExportEntityType + { + Product = 0, + Category, + Manufacturer, + Customer, + Order, + NewsletterSubscriber + } +} diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs new file mode 100644 index 0000000000..a192083317 --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using SmartStore.Core.Domain.Catalog; +using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Domain.Payments; +using SmartStore.Core.Domain.Shipping; + +namespace SmartStore.Core.Domain.DataExchange +{ + [Serializable] + public class ExportFilter + { + /// + /// Store identifier; 0 to load all records + /// + public int StoreId { get; set; } + + /// + /// Entity created from + /// + public DateTime? CreatedFrom { get; set; } + + /// + /// Entity created to + /// + public DateTime? CreatedTo { get; set; } + + #region Product + + /// + /// Minimum price + /// + public decimal? PriceMinimum { get; set; } + + /// + /// Maximum price + /// + public decimal? PriceMaximum { get; set; } + + /// + /// Minimum product availability + /// + public int? AvailabilityMinimum { get; set; } + + /// + /// Maximum product availability + /// + public int? AvailabilityMaximum { get; set; } + + /// + /// A value indicating whether to load only published or non published products + /// + public bool? IsPublished { get; set; } + + /// + /// Category identifiers + /// + public int[] CategoryIds { get; set; } + + /// + /// A value indicating whether to load products without any catgory mapping + /// + public bool? WithoutCategories { get; set; } + + /// + /// Manufacturer identifiers + /// + public int[] ManufacturerIds { get; set; } + + /// + /// A value indicating whether to load products without any manufacturer mapping + /// + public bool? WithoutManufacturers { get; set; } + + /// + /// Identifiers of product tags + /// + public int? ProductTagIds { get; set; } + + /// + /// A value indicating whether loaded products are marked as featured + /// + public bool? IncludeFeaturedProducts { get; set; } + + /// + /// A value indicating whether to load only featured products + /// + public bool? OnlyFeaturedProducts { get; set; } + + /// + /// Filter by product type + /// + public ProductType? ProductType { get; set; } + + #endregion + + #region Order + + /// + /// Filter by order status + /// + public OrderStatus? OrderStatus { get; set; } + + /// + /// Filter by payment status + /// + public PaymentStatus? PaymentStatus { get; set; } + + /// + /// Filter by shipping status + /// + public ShippingStatus? ShippingStatus { get; set; } + + /// + /// Identifiers of customer roles + /// + public int[] CustomerRoleIds { get; set; } + + #endregion + } +} diff --git a/src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs similarity index 62% rename from src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs rename to src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs index ed71e475a0..fdd4eb5e34 100644 --- a/src/Libraries/SmartStore.Core/Domain/Export/ExportProfile.cs +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs @@ -1,16 +1,27 @@ using System; -using SmartStore.Core.Domain.Export; +using SmartStore.Core.Domain.DataExchange; using SmartStore.Core.Domain.Tasks; namespace SmartStore.Core.Domain { public class ExportProfile : BaseEntity { + public ExportProfile() + { + Limit = 100; + BatchSize = 1000; + } + /// /// The name of the profile /// public string Name { get; set; } + /// + /// The name of the folder (file system) + /// + public string FolderName { get; set; } + /// /// The system name of the export provider /// @@ -21,26 +32,6 @@ public class ExportProfile : BaseEntity /// public bool Enabled { get; set; } - /// - /// The export file type identifier - /// - public int FileTypeId { get; set; } - - /// - /// The export file type - /// - public ExportFileType FileType - { - get - { - return (ExportFileType)FileTypeId; - } - set - { - FileTypeId = (int)value; - } - } - /// /// The scheduling task identifier /// @@ -52,29 +43,29 @@ public ExportFileType FileType public Guid ProfileGuid { get; set; } /// - /// XML with partioning information + /// XML with filtering information /// - public string Partitioning { get; set; } + public string Filtering { get; set; } /// - /// XML with filtering information + /// The number of records to be skipped /// - public string Filtering { get; set; } + public int Offset { get; set; } /// - /// Last start time the profile has been executed + /// How many records to be loaded per database round-trip /// - public DateTime? LastExecutionStartUtc { get; set; } + public int Limit { get; set; } /// - /// /// Last end time the profile has been executed + /// The maximum number of records of one processed batch /// - public DateTime? LastExecutionEndUtc { get; set; } + public int BatchSize { get; set; } /// - /// Message of the last execution + /// Whether to start a separate run-through for each store /// - public string LastExecutionMessage { get; set; } + public bool PerStore { get; set; } /// /// The scheduling task diff --git a/src/Libraries/SmartStore.Core/Domain/Export/ExportCore.cs b/src/Libraries/SmartStore.Core/Domain/Export/ExportCore.cs deleted file mode 100644 index b5cca2b555..0000000000 --- a/src/Libraries/SmartStore.Core/Domain/Export/ExportCore.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; - -namespace SmartStore.Core.Domain.Export -{ - public enum ExportFileType - { - Xml = 0, - Xls, - Csv, - Txt, - Pdf - } - - - public enum ExportEntityType - { - Product = 0, - Category, - Manufacturer, - Customer, - Order - } - - - [Serializable] - public class ExportPartition - { - public ExportPartition() - { - Limit = 100; - BatchSize = 1000; - } - - /// - /// The number of records to be skipped - /// - public int Offset { get; set; } - - /// - /// How many records to be loaded per database round-trip - /// - public int Limit { get; set; } - - /// - /// The maximum number of records of one processed batch - /// - public int BatchSize { get; set; } - - /// - /// Whether to start a separate run-through for each store - /// - public bool PerStore { get; set; } - } -} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 21718e5f5a..8e4537dd4c 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -159,8 +159,9 @@ - - + + + diff --git a/src/Libraries/SmartStore.Data/Mapping/Export/ExportProfileMap.cs b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs similarity index 75% rename from src/Libraries/SmartStore.Data/Mapping/Export/ExportProfileMap.cs rename to src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs index a6e66ad885..22d4cc1c4f 100644 --- a/src/Libraries/SmartStore.Data/Mapping/Export/ExportProfileMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs @@ -1,7 +1,7 @@ using System.Data.Entity.ModelConfiguration; using SmartStore.Core.Domain; -namespace SmartStore.Data.Mapping.Export +namespace SmartStore.Data.Mapping.DataExchange { public partial class ExportProfileMap : EntityTypeConfiguration { @@ -11,12 +11,9 @@ public ExportProfileMap() this.HasKey(x => x.Id); this.Property(x => x.Name).IsRequired().HasMaxLength(100); + this.Property(x => x.FolderName).IsRequired().HasMaxLength(100); this.Property(x => x.ProviderSystemName).IsRequired().HasMaxLength(4000); - this.Property(x => x.Partitioning).IsMaxLength(); this.Property(x => x.Filtering).IsMaxLength(); - this.Property(x => x.LastExecutionMessage).HasMaxLength(4000); - - this.Ignore(x => x.FileType); this.HasRequired(x => x.ScheduleTask) .WithMany() diff --git a/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.resx b/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.resx deleted file mode 100644 index ce78c71be0..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.Designer.cs index 0e3246e714..24f974b961 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class ExportFramework : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201508011828241_ExportFramework"; } + get { return "201508040836122_ExportFramework"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.cs b/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.cs similarity index 53% rename from src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.cs rename to src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.cs index 86c6f7c509..84a392c3ff 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201508011828241_ExportFramework.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.cs @@ -1,6 +1,5 @@ namespace SmartStore.Data.Migrations { - using System; using System.Data.Entity.Migrations; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Security; @@ -16,16 +15,16 @@ public override void Up() { Id = c.Int(nullable: false, identity: true), Name = c.String(nullable: false, maxLength: 100), + FolderName = c.String(nullable: false, maxLength: 100), ProviderSystemName = c.String(nullable: false, maxLength: 4000), Enabled = c.Boolean(nullable: false), - FileTypeId = c.Int(nullable: false), SchedulingTaskId = c.Int(nullable: false), ProfileGuid = c.Guid(nullable: false), - Partitioning = c.String(), Filtering = c.String(), - LastExecutionStartUtc = c.DateTime(), - LastExecutionEndUtc = c.DateTime(), - LastExecutionMessage = c.String(maxLength: 4000), + Offset = c.Int(nullable: false), + Limit = c.Int(nullable: false), + BatchSize = c.Int(nullable: false), + PerStore = c.Boolean(nullable: false), }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.ScheduleTask", t => t.SchedulingTaskId) @@ -66,6 +65,10 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Common.Profile", "Profile", "Profil"); builder.AddOrUpdate("Common.Partition", "Partition", "Aufteilung"); builder.AddOrUpdate("Common.Image", "Image", "Bild"); + builder.AddOrUpdate("Common.Filter", "Filter", "Filter"); + builder.AddOrUpdate("Common.Projection", "Projection", "Projektion"); + builder.AddOrUpdate("Common.Publishing", "Publishing", "Verffentlichung"); + builder.AddOrUpdate("Common.Website", "Website", "Web-Seite"); builder.AddOrUpdate("Admin.Configuration.Export.ProviderSystemName.Validate", @@ -115,43 +118,156 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Informationen zur letzten Ausfhrung des Exports."); - builder.AddOrUpdate("Admin.Configuration.Export.Segmentation.Offset", + builder.AddOrUpdate("Admin.Configuration.Export.Offset", "Offset", "Abstand", "Specifies the number of records to be skipped.", "Legt die Anzahl der zu berspringenden Datenstze fest."); - builder.AddOrUpdate("Admin.Configuration.Export.Segmentation.Limit", + builder.AddOrUpdate("Admin.Configuration.Export.Limit", "Limit", "Begrenzung", "Specifies how many records to be loaded per database round-trip.", "Legt die Anzahl der Datenstze fest, die pro Datenbankaufruf geladen werden sollen."); - builder.AddOrUpdate("Admin.Configuration.Export.Segmentation.BatchSize", + builder.AddOrUpdate("Admin.Configuration.Export.BatchSize", "Batch size", "Stapelgre", "Specifies the maximum number of records of one processed batch.", "Legt die maximale Anzahl der Datenstze eines Vearbeitungsstapels fest."); - builder.AddOrUpdate("Admin.Configuration.Export.Segmentation.PerStore", + builder.AddOrUpdate("Admin.Configuration.Export.PerStore", "Per store", "Per Shop", "Specifies whether to start a separate run-through for each store.", "Legt fest, ob fr jeden Shop ein separater Verarbeitungsdurchlauf erfolgen soll."); - - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportFileType.Xml", "XML (Extensible Markup Language)", "XML (Extensible Markup Language)"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportFileType.Xls", "XLS (Microsoft Excel)", "XLS (Microsoft Excel)"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportFileType.Csv", "CSV (Delimiter Separated Values)", "CSV (Trennzeichen getrennt)"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportFileType.Txt", "TXT (Plain text)", "TXT (Einfacher Text)"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportFileType.Pdf", "PDF (Portable Document Format)", "PDF (Portables Dokumentenformat)"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Product", "Product", "Produkt"); builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Category", "Category", "Warengruppe"); builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Manufacturer", "Manufacturer", "Hersteller"); builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Customer", "Customer", "Kunde"); builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Order", "Order", "Auftrag"); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.StoreId", + "Store", + "Shop", + "Filter by store.", + "Nach Shop filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.CreatedFrom", + "Created from", + "Erstellt ab", + "Filter by created date.", + "Nach dem Erstellungsdatum filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.CreatedTo", + "Created to", + "Erstellt bis", + "Filter by created date.", + "Nach dem Erstellungsdatum filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.PriceMinimum", + "Price from", + "Preis von", + "Filter by price.", + "Nach dem Preis filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.PriceMaximum", + "Price to", + "Preis bis", + "Filter by price.", + "Nach dem Preis filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.AvailabilityMinimum", + "Availability from", + "Verfgbar von", + "Filter by availability quantity.", + "Nach der Verfgbarkeitsmenge filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.AvailabilityMaximum", + "Availability to", + "Verfgbar bis", + "Filter by availability quantity.", + "Nach der Verfgbarkeitsmenge filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.IsPublished", + "Published", + "Verffentlicht", + "Filter by publishing.", + "Nach Verffentlichung filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.CategoryIds", + "Categories", + "Warengruppen", + "Filter by categtories.", + "Nach Warengruppen filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.WithoutCategories", + "Without category mapping", + "Ohne Warengruppenzuordnung", + "Filter by missing category mapping.", + "Nach fehlender Warengruppenzuordnung filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.ManufacturerIds", + "Manufacturers", + "Hersteller", + "Filter by manufacturers.", + "Nach Hersteller filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.WithoutManufacturers", + "Without manufacturer mapping", + "Ohne Herstellerzuordnung", + "Filter by missing manufacturer mapping.", + "Nach fehlender Herstellerzuordnung filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.ProductTagIds", + "Product tags", + "Produkt-Tags", + "Filter by product tags.", + "Nach Produkt-Tags filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.IncludeFeaturedProducts", + "Include featured products", + "Empfohlene Produkte einbeziehen", + "Specifies whether to include featured products.", + "Legt fest, ob empfohlene Produkte einbezogen werden sollen."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.OnlyFeaturedProducts", + "Only featured products", + "Nur empfohlene Produkte", + "Filter by featured products.", + "Nach empfohlenen Produkten filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.ProductType", + "Product type", + "Produkttyp", + "Filter by product type.", + "Nach Produkttyp filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.OrderStatus", + "Order status", + "Auftragsstatus", + "Filter by order status.", + "Nach Auftragsstaus filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.PaymentStatus", + "Payment status", + "Zahlungsstatus", + "Filter by payment status.", + "Nach Zahlungsstatus filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.ShippingStatus", + "Shipping status", + "Versandstatus", + "Filter by shipping status.", + "Nach Versandstatus filtern."); + + builder.AddOrUpdate("Admin.Configuration.Export.Filter.CustomerRoleIds", + "Customer roles", + "Kundengruppen", + "Filter by customer roles.", + "Nach Kundengruppen filtern."); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.resx b/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.resx new file mode 100644 index 0000000000..c1ffae86af --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + H4sIAAAAAAAEAOy92XIcObIo+D5m8w8yPd0ZO1cqqbvM+rZVzTWSIiXa0cImKemc80IDI0FmNCMjsmLh0mP3y+ZhPml+YQDEktj3iMjMyocqJQMOB+BwONwdDsf/9//8v7/9z+dV9uoRllVa5L+/fvfml9evYJ4UizS///11U9/997+9/p//1//+v/12ulg9v/rRw/0Fw6GaefX762Vdr//+9m2VLOEKVG9WaVIWVXFXv0mK1VuwKN6+/+WX//H23bu3EKF4jXC9evXbZZPX6QqSP9CfJ0WewHXdgOxLsYBZ1X1HJVcE66uvYAWrNUjg76+vVqCsr+qihG8+gBq8fnWUpQB14wpmd69fgTwvalCjTv79ewWv6rLI76/W6APIrl/WEMHdgayCXef/vgG3Hccv7/E43m4q9qiSpqqLlSPCd3/pCPOWr+5F3tcD4RDpThGJ6xc8akK+31//owHk0/c8rV+/4hv8+0lWYmCGwieEzAgszd98SEuYoK8vb2hE//aKA/+3gUvev3n/5pc3v/zbq5Mmq5sS/p7Dpi5B9m+vLprbLE3+Hb5cFw8w/z1vsozuOuo8KmM+oE8XZbGGZf1yCe+6AZ0vXr96y9Z7y1ccqlF12mGe5/Vf3r9+9RU1Dm4zOHAGRRIyqo8whyWo4eIC1DUsc4wDkvELrXNt4f/3rSFWREvq9asv4PkzzO/r5e+vf0Vr6Cx9hov+Q9cBRFa0AFGdumygpIP6Rj/AKinTdctDoW0bmkqrdQZePhcJyCIM1Kqxb+UClqYp1GM6rz7AO4B4skdzXBQZBLkB0W9vNytKu85On9dFWaNG71JMFueFxtQ/rC/v9fXul1EW2FmRIRacp23052OKWr96qWq4MvThr7+M04nTHAMv3FaPiAZv7YsmQ72+BtWDmW+MlMHL5WOTDoja366zm2aICQkplYRFPyMItG93dxWsw0b9OV2lgSiOQZ0sr9J/wUD6I6bEq9mZK76Cx/SeiAM5f0DMHa9fXcKMAFXLdN0qe6ycvGHBz8pidVlkvDRmoG6uiqZMcI8LI+g1KO/xZHltCGzXnPcDXK16QyM5bArqtoxK1ygykRghEZo1iEyYFPmiClupuK6mp3/b7k2jLtbf8tOyLMpQVF/hc43s0O910mNC9iS8TldmqQsqtPbQAvSse5ovfFttkgRWlW+7NNnkSksMLj2vPqULtFpDJwj9eV+i0aKtJUFrn+N6u7pf0H/g3qCpuQ/aWvT/o4ENXJwiOZ4d1TVIlisyEuc9oBtH9UaK8LAfqNuiCBaqY+KeoEnA9i5jXhNlhJ0RAdSV90G9HH+lImUXCkQxmOHE59Yt7DQH5Yudahy0ab8fZ0/6guSmYTeM1bJSyz0jPgKJditd6Dct+Ea7VUMJ2q0GVKbd6jpNoXLoO1PLNATqq+VI6BpB6vqH4inPCrDwEtOLFLzpERzEskaOdDQKNti/V7DH9b3MQnUOCarRHAB9W70YjS1UT4q8RpNhkHBxxoLFSK4X4nEaOn1GY6r0zu04LZ1XX+FTKD+dV9clQP2l9FdfVN/XC7zSvsktljiua0ZER1FSDzJQ3dZFmRYlgQvRSvFOOr3DA7caydVicFcU0w/uuphkaJdwnb1EGZ9VO5OM6eRk9CaOk2T0Nq6a23/CpB7fBDsuFi+jb2UnJfTdOmROSKRTlCkMdENiNIoOGTQAovcnSdHkdbBFD/PFF5A3IMtenPdnpXm0MUqqKcyj3tixN496g8p2QDTJTSO6YYGlA2FgdOYdCxhk1bHd8tdtaDwH5cawTHWelV9/HSX8pQ0TMTmULBvXt/WpqHQ7xEgjvCjKwCNfZDKXBmNtrL6DqnoqysX0LbfnT1dVsIcA+xva8CG0q5K1gGqNFEl0AV6w7P4C62Xh447q6ldvGEQHqaVjUIpQ80bZPCdZs4CLEzLpsMR74/li/DPmoV28wZUv+ibfx1GC+zavkEaxRm205J9itN0oSQfwCiA+s+dgvfJLmqerZkWCFY9WrcrRabkwSVcASaGLEv3qoq7/9vrVFY6hRNxkxAyeR8LcYruEFaJ1UsejxRkCtwtKtV5KfsK0LBZNUh83+QKtJLSwkXJcprdNDduYLw/5egJqkBX3b0yoDxJX3daGaKGMNhA9GqIfIGuCsZ1XaEEiKwkmtUf8i9Im29BNapGZWPKGrr8x0hyqCXabS90gU05oKObSPaxVdVsdsUJXREvsSMj6yyhhWJDZmMTcTHt8XewSFYLkHa5mVENjuD2XyLi026yjnRsiFhwEhaMhJTHJ0wW8Xjar25zyPvgi+4Em/jYLnjkiHKplePBjvCswUR3CAQeTBi8qvXvIXakTbHO8e9Vni3Tb1LsW7AZ8w9XRDJIFNe/fHLxrlJDbMKwGYN91XaddFY1w9eKgVGjEY0si3FzwJSBQojY/lkWzRh2Jo190m8B5vkgf04XfSdE4W7nrWdfke7u14R+nvaPFKs1PitWKCrYZrbGea+EKbcnhJieanKdv+adiBS8i6Io9nngKwxdYAyQ0sO9e55SLo4XixqZkHNzedVpr7zDHGdlRlhVPg0cXPqbwKVjlPVqvy+IRLi6RNM7vr5pV2Ex/LerIGHt012jDyLhBB/cxHtIu5OO6OEqCLQdyLxN3juyNwVN89dCMv+hA3tyBBKsgJdpH66/IiNpIjdGa/YhYbPRGzquP6V19AspgE6zHE0NbuYR/NGkJv9VLRPF2OwnmlA7nRvnRSetIIUxHDdaN6zTButHRYsH1IXhM59UmIj9OdHfozH3Ps3aB9wiDx4hmpV1w3+4EnJ4erQ7N6fM6LYmi/gG88DjtUBwldfpIUMRg+0+gugJIa4KxZpXF5nifCfUGh0Mc3ZcQ0opjQHjABtk1fB5fEz2vLmHSlHTOAn/p0SE6eUky2HYqVMbRGC9gmRbBq2/ASfZ+gjhwrZxX+OQ50hXl8+oMTX9/lB2s3S0WKV55IOsxniyxS8PeUe1+YwE8nz4juyZ4LZxXp1UwOVFvTpCBdV/gWIRAIwbkyCg6zx/R0kTo+iiDQLWxLpKHaIcQ2FwjGI8eQYrqphmFNdBvLO2p94aV5hFH/rl4akeNdxqELXRSkIGQ3r0Qh8BZUfZ9PIbI+go8ugLJQ4HNaZyoLvicGVuDGON5S0tkgQxGb7BGQYz+Lg4lziS1GNv4kzgYCQHgokNGhZSPp6yitYA7eNy8HDd1vXEuBKwtDP0zrZZZWtVxkHaLP4OIeZFcZ/w3vjhPkHZO0KVJ+IkWjST6DvQtW4zbQGeYnFDhu9HbuFojPCBzHIg9TpJ/pD9l87hFQeM6zRcBmHp31mmOT+mi8FcnthjMcGSm6ATbpG0i4+M6he2aDBb4aA+FVT0cRp4Uq9s0787lIjIh6nMf3FAdrddZGq4x/4Tp/XK8pcjaMdHR/0wXI2L/NC5thp0mVJ4MiMKESbwTi3hRFzCDPpF72xtyIQ4wfYTlC67s6D2hMwE7Vj0GFex2nyhm94DvCwRVU8I2y7FSnYySk3ZoM24k9oAW/2BR25GWhEGQEy2DByqOe70LE4EljryI5fhgkGJqxMZ5tSxafwoo3T0d6qildksctkhp9EtfetNBXxcbX/km/EUNJcQkaUBdQ5BoaaAL3blhAYWoHaZcFbDDAnkGGG2ifixjxPxDpoyxYIoQK8cRdQ4vYhCrB9S7xTShUzyIagACnGfH6UNEbd9pQE3/ZWCqMUhhPcdxkRI82iF0MJrecxCqjvNgnn0eDsHVXW5BND1mAVQd5qA8+0ss0Lu0TZBHRwCr+y+vohmPvoJqfIZanuO9Bvfawd0wcKI8pYqV4pSG8ZSmP0CZIqVOZkdqu6+pp5kgi1qqWbKp6jlVPGqngTuM1nWI3uNin/7Q8CALKDIhXa7kQgbIlQ35s2FNZ3lQsbsshLLDHJhrl2kfjqS7Q7GMM4RCgRdECNns22c3HG66eLwA0ym1w69DXLO6LUOU70g5TfuZiRGp8b3CtlKk+0vqG1HRnVp9U65WufPJb+cy80li1HrJPGp20VXVSdGs8R3tRfDMiJgCHjSxmxkSH0lWWSiPbjBh4rnGgZjM+OvCYIqJhjddQWfLb+CEbUkL7Lo5SVwMY3gkzGMQnBfWHokOVcf56rxaQ5vyGpJxyADVQ5FCB10w6u3ugBtGPYrDVqxuy7AVj3ThBt9/idSyyYE/3V2J46JGfDrptR7D0ypxdqZ+GcW60HO4MBNlZO2NvlgBgJ2nzfGkCt+kCn8gi7n6U10XbUYQHrd3RE6H5xsbPBZgd1hEAF2C/F4bsxUtKUHMu3Hx4xe2+ObQtp2C72UKA4FUJD3gjxQ+fdEbVZ7SOPbho4fJYj6AlNg31l7YVkxLe785qeqBNj3mywRNXgAIyw7Q98DzmZCu/kFx14ivlkRjvZBh8QDQX8e5iw8Lixcz/hLp8uPevGMR++RWFCFyCOPJLSdv/MQJgzM858hBvEyVz0xlVkynG3ltpd6rQXGMplo0jis4bsyFqa8x0gRJ/IJRTtcofIdVrF03UR6DkJD9ssmgVRboOH6VqzUc/dTqOM3wm+tDeufA24/9pdQ46Prsw8SAYBJfO3lsNmgGCa9zU8SZPKpROon4lA33s2H2AsVuufNXOM7T6TMSVPSLohPYyJv4h/FOkJTWsfa8yW/vYaJwPTYdJFbwZeg3NKLDbqNuy7ARWN4rcD6iz4ryE3wmCaknb71TTPFjxlqXf5Q7Fb5asKudFeHolcN0WDXqtiJZWrEOgs6rMwjwRPQKwox+beVOteFQizsAG2D1JYDhh8IoEgFHMOF8bi2Y+hvFirsQrxGEywYa20E+jC4faHL/KWQEy62W923YSvpLN8wfinWorjCC/Ai5OWTT/yiyJJIQOUiPbY7vmjTihuKEQ4jSdoUoHYKKdjCo6BBns3txNl6nXOzmLp5xycoFRUEKFMPaaK/ShtsZLZ5oOsIrnHmia59E3XQihjwJmNevp9DlTdI7lgsbE26SRK1tOvUwonyC2fquyf4TViT5aRRkXwsfXCE6vOs9dIXerrit7tjRFktHixxWFVqrptQLQp0bbj0rRqSsob9qr64WdHbQr2of8dPrHMOvg32ibqun0ccmHVptf3tklzYEjUV6BdjwenucViyeA4/b0FlRrkB4vE+H7Qpk+hRTUbLrT/mqTcTkz0d3d2mWRjBTSU7gYFsmkl59XrXhIEcJ81yk980Bm9iSOHz0GVT1+fposUDWzgTXqWJaDbjrn4v7NPe8Mo3r95mllSj8rwq3JFUoDL3ov6HAqIh1oVSMWRdBXBWdLuRnmHtdN3lYSV9ZEHWHOTjXXvM2h67bHczNRqMR+83DCCqXEtD1/gIduWQgNwcqoTYDoSY2C+ZK69NnrNCA7Kipl1ilaVMfXcKk9Q1KRqCrIZ0GqwrCnNjVcp0gpAY0q4uiUtyQGYqlAxFLhV5LQLy6eF2s00TTR1Ku7iRbLO8lB+PaTeJgkveQFEk7x5YI/eKKXbt0CZGNkeMIK6iaYAZE2kU5hNBVBZh7l59Aubgo0ryuPqVVrTr0l8Apeq+Gk4xBA+w6kj4C0WqvEYAl4o+DUQtAHtA57xSVDlSdS5KHkpJfCSTQXg0ZZNgPBHW365GhUeRvOgQHm17d1llaVvUkUeFYfZ2kIZPRH6cVxGJrkL9M0I48JN1gkSHuwOlbH9M8cT3TO6EeRBnxlVuyNN9N1dD70Rv6r3SNdSWQGVJQRXq4d1nk0Pi4ZaQXkPtX/cZn9iB7W23JtGtIuhX2G+0As9kAuSJh0+bLnfdqepFqO8dBil1kAJQdZaHCUj715AqI1e9wHLZndVuGDdPWy+UTj1F1jo9gDypBFiuf/vVT8RliIp5XhUHQvo8gkK6XJYS2Df4lQoNI0MIyTbjGAp+C/gGCXbzxIkOihXSExr5o7Fj+JtpwB05qS9EwN5vKrXjj0pGYoSXWlbGKs31LbwSKYTF7hWR3lAKInZdCBZmFLD08dqAeATd1h31II5b2PjQ1nlw6v88Rrdv3bYMj8k6fk6xZoLXOXCPWnXzFOWfrVippHi8Bcprw7H7mbCFkKTk5hXjllWMHiewnrljdPUBfZjAdpJWReYOf351H+b69LeFjCgxSL84B9zaodV5mu6d6Iix+rRITFI42HPhGiErrcB3WvGbNd6QKvi9nEVwS557AOU7ciVhvrx5lNEYTxA+AUJ2lKSMlvJb1cVbcD/Frzksa167eUDi2I8a968wkceN48NhBHk+F7DFKWYqi9c0GcMNOsnKBlaRAwWzUdiWAhzCCw16gbuszyO8bcB8csxnr7oZrbqtiEeMAzusSXsvswWZrv7N1+E4kj7+6KuNFHR9p+0jdyIJvngd2Dtdit/GC5UgHnNQ+JfeieO2GvC9Xu2XadrWXzcpuEqwbKLaPTKF0u2YhgvbqTSec92qSZCr9FwF+0+M5bNnqtubxtfQz01Fda/KN0T6q/UcDr+AUR5lnGbg/X6HB4pTdxrsaMS6K1vv7jMQI3q42L107GZewIqJNLsxlkFKJqQUUxLseOujIToY6WKpKcB4krFnWRUhuS2htECEjPQzat25KITmSkXRe4dV1kTX3aS4IEeOlxKJJZMIniuoUSSjwKpWdCPESCheKu+Gx0khQKLfD28b0LnQZ/gRVN8B4gS8X7O3/KRMHaHMjmPMNeDHgV/hU+bt0ce03FIrt4LHeoztJ1pEp3ceY0vhuSTz3cY9RyujUxN5sADdsLSsXmFgKFMyybVf8+RXXPyhK6rZ23Ht8tSzKGMvRsdkzIrqmbjWaRTePk/bP6HPfKo/qwWkeZWR+JsuwJcrMFKFQuruyEK4XcKj9We5p8dICeL+KVlXws5yKLPtR1MQkS0jiIWdtAKOo3vCItkOHxb06yqsnj2AetWkz4JTbNRwhbmh4yphRg4kWjAY2zG6muhYw7y2KgyKo58ORY0hHUova65rf7hD/bXbYLXrOr8AiQrEMuyXSwrBLjyqSLje63DmNIrdcFYkTw+WEkCLRQqZ4y4kgCXGQDeq2YhmJ88iHNmFbp+mOf1c9mpG2LJ6+5Z+QInFBtMVAewkbXx9Jep3rAkvK7bnaOI81OtqFSq0VQKS1zAJgCqTy3l/z38hYtZy33Ihk8ly2UQVdJsCoo9wkwIgOcl3dlulU89dfR3GelRBGuyEfK/UpQtRJNIyHmwKDaI2S7LTPUtoyf+DWYZOi1HZ2raUMLFdpVRlyEPJQ6myKekhREunBw5RLDrfPNWyYNCXCKhDgIJ+85dOo+uI8snHzJODoLQekQo22iAU9x27Ney1iXVrSIG1Dh/iwujW8HukS4zQp8PpZbkd3l06QIKxvslNMJmz5G+Zlwn3TNHWUJLCqpmnwAl+ARkarlZiP/ZK59mLoSPmZeSHrltXZS9YOyZQ9BCupW20SOh9EqLotkgk6+IHmSHI4UmSUq910sZPvI8xx8dw5RzovOTRp1G07uElgbugiDSjrJJUJXd1NCihcnnWdCRJoBMdBoqnbIlTaGomGZwsjCEXUJSfUxaJY3kJyPxvt3kwI6f6PFD4FosAJsb0SIijwxJriHl8rd92OEPZjQ3B7kEIqaxWPVjjtCaYOdkDS3pGfuq61AOFbQKD0Pwh+dVuEQB/LolmPfMo80l2tKYMbv26emQkiVJTNAUvQKHbIPm4Rf643nTdrWC3Nb2ggTppTZXJpTgOES/OuE0EineA4yHWNkNl7abyXa3yqaJl2LYWLC+lDaTJ54iUuurl1lhTtU2vtPwchoW6LEGiiZ1dIW8GvOpMBb4ufgn21M9hZwb7K5vigEiEvzjTbROtIHGwX4AXfSomKrE2jPeZJkoJjTpqyhHnyMsnzS31jl2ATNvoBJukKZK9fXZToF5Fir9/97fWrK5xB4ffXf/NeC2wgVug8/QD1lGLlqrmtkUjMzvMku8ZorYj1V+dhMY3htPVTNHaNG0NzQ17RnmqETKPTjLSTOtOMsGts0pGhhhyWsntjjHBEu0iKVQSQnUE4Nk3VLY9NYHXLY1O7wz9+ak/CQ6Mzab/Wx22FiJXRmkCKd5Mv4OJoNepI6FeAf8ISIraLkF59CZOHoqmPasRHt00NpzSlhcar/1hN8Lppp3rEuuZ0dHeXZilak9Hsg/XoNCD3g7BRg182LiGSXyeIt1jdyZulECY6qn68icRdnkQNF2gzXiIDUD3AhWpKRh3hyePj+C/J4oZOn9dpSRwJX4q8Xk7c5n9CMD496fXVPnL0Ad6mwddWKFRHCdk3PxXZYgL+EBueiDGpho9B/jCJAcy1OYmIods8P5myueF9oemaPL8FEygX3W5KFMAhFd7Y675BBkHZpXG9LkFegQT/3KgGkzc9yZJRNX4JqyYbn+wnYI0d6dMSXGx0otFeNbeDjj7tkC+aMlmCCk7pwL8Aqe+lb/411bHnpWsO2+dI4Kyb9rRkcq/xB5jBeq9e3tJYwpcQH71Rd4utji0+georfOq8OF8LfM8mYV4lDD/qZE9ppEeeZBnd8ICbY09ZuRApIQVyjcnTxg22LchCBtkSRde8AwV739D3Clnpn9KqLhQPJsoAb7pD3E1n1VDCcbIG1PVNkI/pHTHkjIOQAd58r+DiZ1ovhcGYoYVBWVRxHRyphXO+afibpIQT+s8VCZ3ly7169rVNEaXqGS5W9GxTJO8ZVe7as0u4gHAFF7QQO1W+BUpDGZnCCCwMxlzD+fl11Hd10sG+VCQ7WyJ9KJ4q9unV2koaC5C8tOMAFEKPhwoKX5MLQo/Xlls0lVRgHgJW1G0Nx6CBHt5WqoW6icd5Z2tzEmO7w25qGDbZ/qOwVvTQrvpCJ1PGUBCsOs5KLq+VLtcWfAPRZNgOy1zdVk+v0BXK7KAxkDEvwkQ/WBxJoPTUtNd2NzUMim7/UViXemhXgcIpWlMo7VYDkut0QQInXMgcBIu6rd5vRkkF2XMfdtIpRqDcyKEK51XfWZItDUTwRvUIT4pmPZFT+xIRY51iB9EUXruhtWkS3FzBHNuxU4ysbWqaYX1BxhaVP3W0ds6rDXcQ9+Hc/taRHFDuW7KV20nYwG1HI5ek2vHcqOqII1KAKndlFXzQlkz1MOgGyuEtJBtjHBEp+HZIFD3/on38LRTNPxrQjT7I6MjT+qJMk9FDeIeGRo/YnWI0k4xk7Ajj3rfR6ohjk4xtbWzazRLmOm1464fiKc8KsIjwnNV51SOLpsZ/Rgskr2CP19EEwtL6J0zvlw6mi+EuXZMvMojULDB+IEMr4E9InrxY/K1UlI6qqkhwVPKiV1bkpx4RtSSV5mfSqsL9uw4HjdLjGslBpLVC2s6qoVsDlKxjXaGmaz1EuF75lbwFEaRXYhQHvVLdVhRt8Cv1Zsd02RX7q5jFJthjK21agySwO9iXLjfJwb/XYpMcrAdlnZbgO6xBDd9FumrfEjwGjmOQgTyBgWZZNfots6kcaCNJBm0gmyzaRRbWpoMTxIYWOP6JU+SAIJvRRDxu6sN4fJ7U6CJqhhiig/xTtxVFB7kuQfKAKD5RoDe5pBvXuiM8A33Dxz/ALH2E5Ytn9cl1H+vgOn7RK2LvXEP+1IGgNMTNRgaIHWQAlEGALFRQqicaZQyhdHC6m1ckoVOUSDrZIfo0/nLjYoi5DlTrVb5aPO0VxI75JfwDvxnp7yBg0BzWgWYdxEgoFm0RxDKX4hw+XUJQFflZUbbcNL0bpONfSNzeUQ4IwjqgvzxlN7XdDdjx88Zc1eDu7msxRYqao8Uqzc1Xe//6S5QHQRjZFiev3BZdsfO1qCmaKGxpGYTE7pSCBRqbBVHOTtAmFBZPwWM67Gy69R9hZ7sAZaffOJ4Qtud5HhXpKY4RYRnNAxknLGSeFEtoScIS8RAOixjNYxlH6dgFUbxhboV1wUqpGxqetjGUYBJLQw0b9Y6x0JBsL1ECmfvt7ZHVne8KrUiOeVUw5i5HOfTtkFyt0Vrr77gPssDnRArUICvu32jxHrbH0eW5nPDf1mwiEM+9AievOkszNLAIb7Yjvn76lnfDvqCOlvyTYHkn4Pda5VpWly15qwriY8hWtZx9sxo+8RitHp0tCXRYHOmiRRVmPWiH6i04dWgPctNV4I38eNS4YTZjSDA5mRTvus+91PnznQhSI0wuyrU8bbsKPJQC6F5d1A09cIwg/KKLvYPA+zOIJh33Ks6Lp19ywllzwLINsdSuwX24WYaQHJaW99L6a6RHykx7tXZXvtlMZSXZbuli1T7KwMTgzR+gTEG+Sdd+Uqxu0xwEasRm5AdeVrd19dBEYGXD3fs61R2CxmnkC8ibO5DgSSwv0Gwbo87iNOvomzbcbiIdiYXtZ7qIh+xT3GtToIKEcq7RyJZo8Q8WtdUhzlFVpfc5WkUp4aPzhe4M+l2cY+E+ShD79h3PnPqTC3wJ1vUmXEWu5AU703byeAmJzOQhzrEP8XV+a+pvdwRpe97rTFR1UjWKOXS7vWbzu2FxCJqAbVWVY826fsyTE4u21Y5Vi1o+g/V1sdKr2HewLA6nEdNVfYbN1I9x1sQ3Fl81POiDowv0Dk00R+s1fK7Rp9V6/PT4ODXPH01ahl9Wp9ZLXpdFFiMuZKbTK34JOYhXV5nqLUh5nvMZj9QfZFvHdYR6Z6vFUHnEJM+j1i0grXGjlLxGGmjrqxwLbkhieB4ibiaHXcRiFznKUmCwnSJI6plc3KOlfgnVlLo0r7HVJYL2wO3qthR0C4+j2aFFZIiOLLKivPqjASWsLu9vRx9U61ta/BOtBDq4P3rsaHvddIKGziuECW3kMImQRClAh+QwEdEQQ639nOYPONB3zhx2rtrW9uhZlnqnnbLmtSNdp7DsXOHe28+A47DX6CRbnPjPGLcs+qBozHSerutQL0PUiwHG0HM8UOmqH1j3hgXdrGs5hLByFWAxfaebJiQ2vFCo6aHOTrePFMKM6HNzHn+p2n8O8kLd1kSxClyr30vdKc5IjV5V2WmO4YMVpCuYIF6JMwjDsWpRae/URjpk/FzcF8Oh5mwOSH7s9So7LhYvU7y1WuQ1Wi/9edRXWD8V5cMUwQFIML2QJXzSlCXMk5dwzzrBefqcLEF+D8ljob6oNfuHshF5wB0e4Y22FhVeZwIW41eNNdw3SHFmzCPjwBVDYqD0Y2FBgzbSTbc8HnbDT2sX5cubHslhR1W3ZdhRfx1lb+snxvBwya+jZJOwzxb+N9/t5HOBEYST1cZgOSvKFZp06m7aWO19TlcpYrHrotVWg4Nt8AKrltvkANqia8/8GIlsO80XaGaja1hu5s0XQG7mBlo5HZaDaFa31ZI/VMNqscxjOHn4Zex9dEu4gsTtd5v5mNykfvWGQXPgRnVbhFCj2xiR+NTCz69p5X0cM3VM7j8GycN5TqI0r5pb6gjX21+twHhYElEneDQXeKwMO3NkolawnjTriQlWsFCNFWJ6o1WNSXzTBlDrcUTxW9PXTa7hCqnTQcFFMnQHQaJuax7t7EcKn1BXl9O37Gux2buP0DTcF+VLBF7mUR34+MDHk/FxJ9wjsDGH6cDFBy6ejIvJVKRJUNhysVoV+Rse04GN1W3FcR+hEX0si2Y9PVuilmdYhQbXwEhR2GO6Co6S7BImBX612t1ji0MHELo3A5LDiht7xc3psNXGwDkH+Z4vNodg4beHjWFrA48qw9bkEIKprQALsrC/lyGrsHgz1D8swH1egFdZozvHHanVWPkTPoP8vgH3o+1kd3dplvrZQUPdavPzsJTUbR0tFiWsgt90+AAzGOGOhyd7qt+Dbkcn30Z69rgZoKgdhC8UNw8BIswzC0GF+K9/CS4gGorBdGB9dVsGyW97p8tV8r9UNVwhOjwRJWHq5i8x6caOixrPxdAx94d0BfPK7yBUWCkDssNiOSyWfVosZ0XZrALDBgiO6o2A6rBWNFxL0eljkw4tt79nOvAnMxic0KZYp8kuhh4I/CsNOlBDCeqfBjQwnVT6iGgxPEjuu2BZPIfVqlmtMaJ7MA/FWqnXRSxMiD//CRPtK4HjBP7jxFfTe9dxDiwQbIOeV50xe/xy1NTLooyI8BJpDuuUSrngi3MkGUqzsSJRAC1Wblh4Oh+AEkxy7V8N6xqztVk6Nr2noZV93wCZek5BBm0BxAmCPn0ufILvUa17/DY3heUg/dVtUWTCTW5NeKbxfdeRZOhIgoUjs+JcZ4C5EeDpwx0lmOSERw0b9SU/uiGZUJGVa3sbXZS0ZIwhTjD8QaSo25rZaWHw1Lwfp1WvHAYOcZ6rNUjvfRwY3e5cvelxHFjXm3fGiooxmikjNYzzOOzaFhvzsq6D250sooD41GEZcqgOq9F7NY4kyY+T5BRNWdYda0LdNWTbLoSu/0gJZSKt92mCLNpJSBL8Hkh4osKoV/qvYL7Ad39Alr2E4jqqa5AssbHz7ix1zsi2qf0+qPZfjLWtZeVX+FR9hnipBx69DCJTjvEgOdVtySkWfBZDlqROHP46SiqTOPIkqtoxZiDzyRImD0UTlP68fdLmjYDqsGg0i2aWSMidfCPjapmu1xi+u24VC+95dQ2eT58hRQ1fVAhRf6Ux2jtX2/EiSCx9S+3p46WG5oUKOeyNRIZtnIG2dYSXKKwrBr0+IW8lohA+pOY3bdU8xUZ+8X0k0X7IZz+SBLSXXNPLLP5Qw1nYecmsS3yBDfP1BXjBLPAprXCIp7/QUiA8SC11WzzJQoUWmYktDTbjxypdZwoeuhErb9aZbR1hnVlXjLrO4i2ww8rSMPFLkkH2mWXP1YARXcAyLRbhUWo1yAi+KgzRVY2mHS/JGH6JWM7XSPeZzvO0TkG2zZKM7qKVFLtha6hFFwNolFcstGtwhnL/n1os8yabszz3EsskEXH6L/IWESGLV6QHwUGA3wgID+JZ3Vac68h+l2oleEhS6vnyeQztz9X0VLk9lMKon0mp9BFW1s0GfCNv1FCCINWABqp6GVkNfUpD75RULKKDIFG3ddHnCH0XJgIGPO/ncdLauxrLoqrQssjCuYxHdeCzbeUzB60mJAD+EPhu2CvvP8NHmAXfMVoWZT1cV5s6lu4Mgcdr3GDMrYdEESMHRClvERiWI6KC/vmvOIRATA7LEpZTtDXhUx2mG37wj6Z9qijsYgd50+sTqPQZIH1I53d1QXVlQXtVId4VhSvYPWrjkSsyv0vvm7K1WDs8B5GvbmueeNI9TLVIxVb4vEgCnt9QGA4c682xu5ool6RR8OEcXK9q/zmwjWbtkxtYkS6zmDz8SdYs4Hl+laImweBv848AuwBVhW+OoYI6SqBBj3B0WlyntfY1vDitTBLE/wXWoLvBp1P34zX2AVKh4hO0N81cRb53cAlzJJKPqp/poj1kCcLWYvmvIh+fDm1TP0uw7vR/oe829ZGp/cTMW9jIjwu8wUWQL2ValEQqB50n44FdA11WVJ+5UO/JzYrakdvLNsN1EMyuyJjGrvV2RZ5XZxm4r4YW/S9z6FuKtqsjmqDJzV4QDelZYafgC1zdwrKXq1lx+/oV0dZ/f/2LMF0MLL4tQ7wAyCCGQ6V3+krtqwcdrOR2TTsh9MejqiqSlBCmn6fndVHiePG7FCd0TpZw0WC2qR64oZ3mi1etqaqusrFq25nD1jADjbgP0TpdI+oiFvr99f8pDNCqmeFMeNMM03OuFZGMHanx8TiSHxWa9TSvRTUtzZN0DTLrDnEYLFU9PFlDW3zJB7jGMjqvrYlv04muHuZlVFPepaFlTi810e63txSX6ZnvHw1s4IJbwDd4LSiZT11FxnxSaBcm1DQnYcIPxVOeFThjEtvCL2/evOPn5bdveRsT8woH2OBI2hNQJWAhynW0khcR2Nc8lAnY1zx9Np3o7xbOzbQ39JVSG5ZlKhgY1pNN2SYkTMr0WZCUW8Sl0pFMy6PS+bLpAn/XeG5OpRYbzWJuYo8mzHTClm5Vws6aFbNV3Kwf0WyiVzKnNn2hqs3G3t1h+UVK3su86f5V8rQcXMbILKQLByvakLCtAvn8LKsfwgR8qp8nmw50VbaGMbtQHFum4d+xHYMxubdvxTa2nzHZIczAmOw8WTHm5snqWRizPyEzykoeUMaMmwM7ezYU8NpLRmJDRbHjVZ2YgIVUdN0FqfYhrVo1+GiNJgX7oLvRpLBSMpKukoypengXptK2IWEwS8YNIk230l0I01cZjyxDC/ZiPwJN+h9dSgesdVqQRVbLhTJR9yvb/slcQiKceRK9xJoV6SaQcVYksulHX39uPe4G8U36CMsXEtVm0LAYYI0O56G8sahlvEb3c7TtU9eb6bQwKZ2tuIqqNzdnDerAsCUZWECooOEwH/1M2YzDNro1loJyFNNxqXK+bLpAZxvaCi61NGR5+JF5dIdtWdUYZmDQHbRmccLMO0CMotJo0cqAZYxJw7lwpRT/HNatriMT8JWOzrtg5XZMzQyD4QmDWFJW1EhBX54zNinhP11bWyMXjSOaTkAa59OmK3S9reJsyx1dVmcift7h3V03jpkYeAd3eZIZNM3vv8B6WSxuLiHCluIo7hPsG9A6H81VZUzM1nLhX4v2ZHYUKYzojbyqkVKHpu0RMQq86dErOy2DltKFBnQii7QFe0rMv6C1I5hgKWvnyMqUbKvMtoj7F91NzMjBydhwuDJsz4A8VnvWi6eWK/owAfMoaLpLbMOKHtM0s6slLguxuGVxyDopGZ+dpP2ZkKmktLZpn6k434F4f+N68zaLigNEUOmh+HDv2+FQXMQsYSw7pvUZ+3Ga4UjwvgFjN1n46FTg0NuTQlxdHtTorhNtLvCb+stX0NFjuKvkThahGdkmpiD7/AqUaRQTSCzTfFnth1QakVnkVZuPrb3JhcwL0vNNujMVD2lryfhVVsGFafUNSjh3k7Ft2zjXaigTsK/VHNr0g86KOAsPH2fF/UVR1Wa+FSBlvNoDufCniHineFLZ/Qn4UDknO8N73UvQNwPj6LiEB1Zx4PC8tBsTCuglfKhi8O3gQ9UIJmJF1fzYNN/XmdsjfwkfU/j0CWbruybLsc7LFJic84bqGj+9UNPDWW9qXe2370a3dVztNrDpHPmW8+zg028rzsb++E3B8xquzIqAAClj6h7IhYlFxDulCCi7PwFXKudkJxQB3Pt+7xgYR8clPLCKAz0UASl6CR+qGHw7+FA1golYUTU/Ns33deZTBIosM0tBBkq6rReZ061xFuFOST5p16fYi2VzsBMSD/f8KK+ecBRAIWSpY5mCglPxWQviym00YplmKGHg7eA1Sccn4jbJXFipeAh+Vl77UdTEVZUU5eKG4hgdeyjqqHiQBnflRFVTCq6Us/t28KZhKBPxqWHubHm2rTUf58JylVY4PVg3kt7ljweqPhvTV5PyL1fDiX/1rWlOhjDACCeIdkSSg0c/P5yJGKfPOKUqyI6aeol5sU0/x02QJqeaRW15ejV1RbdsazYd2KlDR6chTSAlnebYpj+zH0eeFWWzIm5XI4OLoDJuHqBcWFeC2olPowTkqDsxAWepibs7bERycFvyEQurZKQuK7gjJ3HIZ2IleS+m4iU5gXeHmW7I/9v3+rSTTQEq2ciZg2ikEvah+rZ1e6aq/1MxnmQ+bJre1NoGIdZyjYWQaYc8hvhqMauYb0v5TtL1aQUeMx/WfLcF6hfFL2YtiRpwfBWMQq7iPilfbwkLKsYwqQ4nzo9N86TCbKzYPjJtGUksA5axYvdejD0bShHbBxBH0t90vZiAkXTUtWmerTkzRxntARYsIhftps9D3vfJuG4nLYY+z9R3/J5E/5z8kFdMxSXaWrpMZXQFn3xu8gY1qce2j0uthjIB01rNoU0/Zk9VJh1JK/mc+KldxlNxb9uahHWlMntL+ZYZxFxMy8ybTSdIhXk3dxKmo+dRDk65vbvG/fF4d4cFFT2faocX52KXmM2U7kSAHIHhdjGhibL3k7LdDiYv+Zje1ScAB0SgLi9BBRc/03q54SAVuxjqydiyr+LClaZmVGJRxv3x7rZb9moC3rOcBitOlGKYnTEZJWJgIRO/SGvpmNJXa9Q3KGFP1SqYX4ZaDWVCntbOoU0/+jrbxcPf6SXmxshM1cm4mW11dxRR+8HMxdTS+bTpDFNxXrX1a1FDGxtpA6dUWTGIs8pK4d0d1lT0fCplVZyL7beRLuETWj4XBUJQ9evH6HvXVZKxoQTehSG1ze2Ul95mJBNwq8387YQHXzYQO0XAWNNa7EntH5eG/BZMUNIjnLCS3JrTE4kFU+XMdL32yGHdne1F3vEJ1qt8HrZ/c+n73drMPauY+IKB1jGdqy9O3oAsl5+Cq7eHBaVDmJATpXNk0/6AYN7wgj5jr13ECgcdMdiAxxyS9C5Ia1b1ZCrdWUVjW55ab0HkyiWsmzLHr15Bm5sRcnC5OkBBumnO0iZ2TGfWjWESbVk3TzuhJ286bSn3VBWiX9qLKQCdNJOCNHsCynYvO27yRQa1ZzOaOnIthQV301TUTanPD6kxjLZZWPRsEjXEOBU2vdjUmlFF5kZi3DaUNUZnwt3cP4zDmINfd3IXEUZhCqtQVRidU3cx1sI0iDnYdAcjL9jceCYOlUIbMyd6p0vcScbUjmACrtTO0Q6x5NUaJuldd/v/qK7L9LapoS2L6mtrWFZe0YOFDT3YQZa2G9F0LG43x7vA8vKRfFvjP28UHKnc3d1xSRUMDRonZcOjOzIfs9WynH+pBAx3Co3FnzesPItSDFu6kWgZ3E+268k725aj7Zb1WpMv/flXXPjYZ9+xbPjGf/21eOZehf22fA3uNfnhRFjNuvFYIQxmtQqGiuNlPOtw/gBlCvJ6mJaTYnWb5gTwBq2Y9BGWL9fpSpPX1g2PhnAaFB40te6Q7O4lPfDRvLCeHZ1OLrjOqU3P6HpzL37d+CwNOgsUW8HxO2zfOQxrO5bGDlp6FqP6R4NKEGd8z9OgVUHj2YqlwXRIsj6Ygc+5Gcg6uh0cL5tTm57R9baN9313AA+xH4Gh90nAb49U3yNR3g/F7KmzRTAPg2vdccIYd43l5/C+uc63wyLYGmcbP7gfIGuGEQrc6siaWmQOq4TgibBU9P1RLxvTqt3a1WM14PlWkhV/OKwqHsXci8vJNLDV/328aFulyc+sru+FTn5zBVbrDH4onvKsAOrMBnLwyNzFIZe5Dft+js5b8r5MyF1ySludBjA1Z+Ow6xSWaNQJZF4cUXKYHFzGYQOkC48p0Ds+f0L4bO49Wj+UCVhUP1U2HaDrbQGDmhwRAuQIbLmL7gVl7ydlwt11IVDh+O1PS4+Yqp5mP1ZferDYmZXt7RKzWo5lui3eNIs2PWEqbhE7uzPydCzsw7wxdUt1V2bhvX0Qn4OlfpZmNc7ubr6m5oDDiie56kEsqumKz7W2LZS95hHOsRbMLGAvk+e9LlcXJVaM0hUoX06fkyXI7+ElqOFJU6Imkhd1FLGppjRmGFdyCg42tiI1zLq+jyOdrfs0AWdaz4KdtFai2Q4GJX+4cSZTJT5Lsuhn5kVpZ6ZmQinBHbiPqT8b2x2D5OE8R31JHq6a2yop0zbW1nib2FRRxoKKOi5MaWx2p64Y245mAt62nU8XZ9bWcbXJCDPUm5ind9GnYDmWGRl6B627oySTvNuu5GI5uIx5B0gXdlWgdzw4mJ9V9eOYgEP187QzpwZHd3dphr7AG1NyIAFSypM9kBNPCpgnf8RP2YUpOElFWJu2585+Rl6vdFM+1VWUD5T6bs6apmZ66HtuTdFM/J3QEdF4H9GK+YJYH9zDm7OyWBn5TlNH7hKlwd0coOqGpmc7i95M4pw0Et+mF3S9bWG+68KV9TY1RmU8qpnZ2U7sy/RMJ5Ldpg+bWjOaEHX6iCbnc3F/Q/3Gk6mxI5R15MbEAOJmTqhbkSlxXOe30KwwjmcS28I4d1a6IVt1K9jXKCplwCMx7G66HXUjmJg3d1J1PFnC5KFo+HB74bM6S64lAmnWXGldpxy6tq3LmFoY49Zxt+vwJuB41/m2WgV85RnTlydNiUhxfwFeSFr/8zzFeE0PqWhqyZOZsxXc8pnrGrN/SSSKXmvVmQm40moGrPpB1dsaLuzfzBHYxpZHVAhseNPrsSrL5iXcaloa8wtl19HNwP6m+bbpEl93ttXwuUhAlv4LLvo+3nwG+X2DvQEqBlRXkXG8AO3C65qmJNw99HzruNo8jgn42DxvNp3o68zIsRamncmkczTlfE24rbj1NJP1tiNW2ym5UYrq1KgGLPsouxUo62+3/4RJjYvgM5rvhHQM5HlREyx//17Bk6zEbFD9/rouG1FkYtRXsJZcX61ev2qLlXeABWZkkZ0+r4uyRuS7SzMow8YAGNFdJUu4aDJ4DaoHGTa63IjsHw1s4OJ0BdIMWR0gWeItTj5iCaARfX9BU4Zxc8/Vvo+GnpmngvQ/SYpGPkq63IisUwi+wHpZSEfIAJjRGSK1pS0YI/RdG7VqxRatBpmZddJKOU19mRHJCajhfVGm0mXXFb6YR5MmdVNKcXRFtgTRYWIgrMmD36JKS6hathIwM2oquaIUJ5PX0m7g2olgYSzmo4X/AvLmDhBy6RYHDWZEbcLphKzfH6XMN+ghBiRdLIeUcEP4i6kjmAVUq4CUmYnev86lFncshBkh2pvxrb5HpKVIe8YAWBObKAHyxcCBGFEeZ8X9RVFJcfVlRiS9Fi5DsjGDTEiwQQCvamyHXsKKqGhShBI4I/Kv8KlSif6+zLwmiyw7yqsnxVIcSq0QqVBYMwHWa3Uc0IYvmnoCy1VaVUh/bGP6pL3iYCyUQbQt5yA7auolVoLbfNbqBnTwxsZIXI+Kg4dCOzTXxTpNlHhIqQ0ioMJg14uPZdGslb0gpUZExKkpw9F5iC133u84fKD1MMklqwTQLGY/pndoIywXRuwSQHvsOoR29FMJjKHQDs3XopaObig0ohHfR5fTS/qOusWep9KsNg9DWyJRUYx9wto4WuoBUvkwmfdhjX1jX/mS949/jc1OPZMn7NcoaqqnIkxj0DwMIB2P9gUIr8bsm7ElHnlJQEkpksLfDpEm4a6mAW3eZL+GHVqzbcIGtzNSad49h853Z/eGxobMLjLMVJYdow5dyK3J7mqoUV0idxUVhsFw/dOmE18AERLKvnTlZsIskZFKaHorV+EYALMKL78yJNXoVde+HEzGa7haZ0DOkDI4WwfGiw4xD2MtYzQ4ORCzYgFziDhWuyJ5GLPp29+mkdq+m4tOBjTfSw2aodDcm/5GhrQ3mysuJnaBoEIs8BOm90vpDs4A2KL7kCIVolJwNg9jp2qb1ovkDoaR7+jIWznbsVHORgYZws7kLEJFA9qjIscEenRtnKpx7a7WIL2XEq8vs5hfQgqtYGFBrOz9z7BGdqVpiuWQ5oHzcUxSCohhZ65olVuzKqDOqFzLwgdU5oQiPMSxDRvcdu4h6rxY3mXJ+b6xs5ihFhpvPgthnsKyqCpUMdOg5GEsRi9d/TarHv2qVVpLW2RWWMCz1rm9KTfTW+ljkbtXqHNSxWnjDXsYSFWQHT2y0PyB7uaMXV1pOMAfRiYefwonxVaI+6N8CjF3EMofybPUsaCc9Ijz5oycyYqU00CrB6iuJKOc6nBWQ0FNAxIKUsezMal3wx6jamnHwloNjKlioJs1tVikElpxR8cjcRtzmG3LdHQlV9agSTAmC9LtSKirmzIP4rKHqTfDoapIUQWkenjyCjLaCWe+GqIpsEoopUIXgUr9fmumkizpinY8XLaVSFTisqmIWGNQqd+9dVwkwKjHwIPKaEIrFBpyCKjGZZf+POPmaL3OUri4Luh+ikTRwqtHpasmIxYVKKKhlRarhG7qKYhCuQ1/2tBtgHYZX18pJs0GnOMuuaFheZSLhmTSChYjlNWLQDgpWpkiJh1nLAHPPsGrFu+ap3plYlj+Iq8FR5iRyUjERiXFos0gQzdGmpI+IqxxWEIVDZ0spb4S89hSjG/YrC8IoPajMmsMnuSaRmmgnf06xUEKpx6MDFxGIi6MTUMeKcZJ1E6mZTauTslQ6jpGBlBW1bCYPRmNjUhIqsUeia7mNSoFdxuoea2GEXKaJcuGL95cwqouEdPDBRU9KVLRopZ6sObKMpoKkZgaclq0INs2NiMOJysdxXkzRJtKKCkF1AxNBi+lFxdoqiOXFOfIFOoTvGlow4OoR8BByuhBRRRrSMEjmogIXNCvmhQsoHkc7NQGk4VFJ/NOa7nOxw/R39CiOirxRIhQGgeCACz1RmzC2HXOCBGXhCpKIocQ5DjNMiTjhmh4DVU4UIvhsDUi0IdDOBGRupj3zX1MDZUEWPOo+Co6Om0i9C3IJSCWySHVBHjQSxZBv7loLSGavoJ6gNp6MvIp7gBoaKhvQkJI6q5CMCH7CxJa4olA6tEIsDIiUVc2NIQRUU1AjJNiRU5CNjdH5PQQ4PTj4MGDV54UqYQ+SlL7my6X8DGFT59gtr5rshxLR6ZAY8WYahoNDgOCYKpaNqORbqpmPMjd3+rRrk0RSD06AVZGL+qekYZQIqqR1yZusOf3zXUnOT0EOP04ePBgLpIildBHSWqftVlkmZZRWADNEqDhpM6C9uqXbhUxKEZmjM2ltZv28pl86DSIvucUpGr4wxU6AxFoVDK3iIySniT4UdREfyBp7emLfHJyqMD141HUChe7GtwKuimmwId63OXAG+56ooSA+hqacWorSrlNvN2oo6Mev2bb6sYaz9ozElEBaWGaGYnmaOpNTiTdbVGt6WdXUT1kq/ry6EDtfVhtsKBNkyObi8MlWi11JVDqcYnAMrrRV3s1RJIgm4IiJF7VTBIOzDAMFlpJlD6I1kQVDt0UZLmhbykraELDGEZAgSqoAcxkoJFIaMDcuo7JHN2lby1ntDBW89iOJQ5PtLjkxBAoGiQ06LvzOrFBwdmsdWosMUQHhU7FIXICe9CmzVRq9uhK4dSDkYHLaNPnBtDQRYpqZC9u26ZOnnIQpu7rpKg1DaaSnbJECjebHFDqcDB5BfWwtPV04WB8tgaL2DB5G5rYsNEo2aW9sCSjJAW0eXxsBugRCMhmfTYys+8SJP4WJb14EMP62UAqV6HZXcZjmoYEmrASEcim85oQEmdCTBMu0qdLublAPV6CCi5+pvWSSn8iksZURT04Q00Z2ahULxqqmRCr2CmWc1GWxeZmk4lGTUN5BfNApfV09HOQTPo2JKRUzlEsSn6nJ9SanGwtx/EylcckLNvQ6HIPJyMyiH4KxCCnNpBKiddlRjJJPArTmCSQZE/SqqNaePWQdNVklFIkf9IQTdvCyHqsrG3jCjVXchus57JxxOs7V55xm+RATElCDkI9LhZQFXtpvgLJ4RlzYdLZw242OcnURGABzWNg4HUkMatocpSy2DkVlb1N5z4O1uhR4AFNNjAHH2RP87hGdiowqeIM0lwKqRMQsgpyqcAmtNNKHSnSkYX2pvNmFlLCWpwVWTCS4+nTxOzE5wm8ofOFy+SRGlwnQpS15LJJyG+olU9q5GpjksmdHp+KunWpBnYYpG51BtJvqjUqNKzxTyhhHcal8VYEUmwa3wUbc2a+I8QBasIEZPBxY+emJZE8i6cFyQwVjYPV19dctVJmKDUT2NDmyNevNGlZb1TJVCXL2wONZn26Y5MKBX2KWp2A8OiATKG2Y4ro60Sfa9d18Wix+XK3nsITLjNtR6znVMFUAckD+lSgJCOxcsoYMCMJaOjgzAE0LrWMavsfiyqaBMm22RasURgpYItJQ2l9mmjzJFh3YbrMDroumfdvm9pBVDHv5GPOyaRKlK4j7EtqXtPBoAiiCo1ppolhuiBNlMa8TDfWFHmsEP9l4bEWvOg8L9f3rWvVV+u63oPXKqpjUFurmPIwI9K/faBdUegwF3o8zmTSonOYoz4ZsvtE6XugnjQjlwQonZbbgqPstxXwdnrnTKL65gqs1hncPJ+ppg4HaR4SWyGYQhy6kTPQDs9mMPcuZPRRQKoHJK8gow/9sIeGQgqEE1wR2bSs2eJFIJuhaLZxZ7JMulVTfv72p1n7UVYxrgpVTc1q0xwxOLUwNTGdyOhDwDFJNxPRuBd8DadoLtUdBq/GYkVq8eViF8prGp/sFA4/WYQ4IF2B8uX0OVmC/B5eAmSqDY8iSVzPxkoaP6+prjyxVWHKmGzGK91yNs9CxSUl+cOahiy05SCZSjGoxiIcm1yKV6i0x8DGOuqRmqpKc6wo39TSZRUxNTTyEbGqfc0WZariPljNdhWVqNNsXcMLXEZ9WwGpHpi8gjRrG/VGmC5tmxzhBPr28DLYjSZwSATSDIWHlZKFeqxMRxYB18hBQsKjYeZLwq4iTV1JeRnSfsVpkI8swNin0W7OymKlI50OXKeLKWvJFT/uQTetmqdGPS3prgsHwlHA1mPb1IlMNArxyCSj3rq7Ed69kwl4NbhOKCtryUU9/dqfVtir8crkm/D0X1Ty6ZhNCmc3MB2LeVFqsoBa6eN8N5L3ACUBtrZ11UO2RSGNWlO9QKgLx7VtT0Z2yUOKEcK+2dcFb87ztE5BprmBoqugHrm2njwWXHgbURsOrkM/7mUo6duPN+K7jWZiKuvaD1yFwobEtpemLFuUUN04qb5JWumXLM0ZWuXQ6iGrKylzs/IPcGoIqsE+clI7045kuROZdiDjzjPGjvPb2xYBDioGaQ7Loey3t/ixyBXoPvz2FoEkcF03IPtSLGBW9QX9M+abmt2XV1drkGBx/t+vXr96XmV59fvrZV2v//72bUVQV29WaVIWVXFXv0mK1VuwKN6+/+WX//H23bu3qxbH24Sx637jeju0hNYWmm2uFKdbX8CztKzqD6AGt6BCFD9ZrASwqxUo62+3/4RJTaKrnzlZ8ttA5b7B/kFC+rhSnDlchvWjvhb+3bn4cIvETfYGd+2N7lB2Q9EzNEgsEMh4oeLcVKyOEFyhxQPKful03T9fIHIUWbPKN3/z/Keujf/P1m+/2GP4AKkHkmlETIEDvrRaZ+ClzeHMYWSLnHF2O70EZVdij/G8+gDvQJPVHPE3n0Vcv73lOIDntbcCs3ESgOdgK/7m3qENYXAGlQeHG+pvK4ufFRm+cS7gob/bY7vAbyOgelcvVQ1XIlZZuT320xzcZpAj2PDRHk/3yDCaTfzMMD8DYqnT+PH0f2zShTDwTYHD7JDTMvJkNTM5m8/2uL7d3VWQW9P9N3ssn9NVyiHpPtnjOAZ1srxCqhKLh/rsQHHETHglcuQevm6NqGJftg6RVLoXvS0Elb76tsqpoywFFYui++Sw7mFS5AsOy/DRHk/rMaORtF9mkGR1sf6Wn5Zlwe39TIHDPCHN8rLJv9cJN1vUdwdZASrEt4h5BXxsiRtGZG9I8fXfHfvXJAmsKnkPqTLHPoozQn12UcU+pYsFzHlNrP/qtDPd4xMfJBkT4sbgdie20B1v586W4x0Kt0YaK95AD7OQJCi9TCUrPOMIaqpxHhFX5CSksO2LTRvRkhIKHVgP1EuO38gXJ/UK8sPsvzlYYGj2OcuLfJlye/ySrqC4LW2+bs3C2wQHh6w1VfizxfJSVx1nRfXtiTYBW2KP8Xs1hF9/LzMWJ1/m3k8BZSC+4zQH+AFEGcq+zB5rl1tAZHWmwE0C5KLxO3x1UOmeUfuVIN+ozy7b/lf8MhK755NPLjiuS4BaFjZ7psCB69YLUMPFN1E5ZEu2RtJQ+1W0jT1sO59K5FyUaVGi9nllrP/qsDzKYsUtDfLFDYPEuzR8dbC6Cs7mKtxqi73ov9ljuYTr7IXvyPDRGY/YJabAQSyecNLwxMkfk3ArmnxwUPAacjLBKXb9R4d+FAuOZ9svDnQooUJIsSUuPgO0qbSHqazXYPjshkvSNeqzw3ZD7IOEZM3mpQVf5tTDBX6mG2TZi9BJqmRrhDw91ED/P4XJx/2vrT6OnG83FXHqPY6PREnEFNjj+0RewaQRtV8cdq+i5N0T5IuTglyKSt3mq4uJWVVPRck784evrh6/q4qfr81nNwOgPYpDUm2BuDEFWSUMVgayNeu2Cxzpn7sPWbgMKo+Va6g/kopGN6o8LVMBuVglSdYs4IKOgD/nXeBKII922pfl1U1Q5e7Y++yXLUWUjUjAXCxM0kOCC9ttXbwFP90aMBevTZ6umhU5oT9atS+fsP4bsdwBO3jWY5eUOxzIkBqXsKrLNKnVhNLBOZgRTZYpozGEwu0Rc8ZblEGSz4DdRxg6oxxHPm46wONhSxz4tR+IwKB0gQc+EvurRDqUunhuLkp4BTNkPfFHhFzR9vJ5ZMaOwcnTeV9IwzwS6rPrMlBgFApdjnnacDz+hKf/6mQ/JOLWsvnqjqk7hBQOE2XlUx6xXC2RGaLcg8RS1ygf+kKAGOyjy9ukxvwpXcDrZbO6zQVLkSuyx/kjrdJbPnxx+OiwTprbLK2WvIijPs8ZBBnfk7RzDvSL/lpxBFHuL8AnFtt4JArR3Re5WHklGhl5aZVcC5DuCwoY5wV5ni/Sx3Qh8d1JAfZEdAbaBUrtbrFKkaWyWgnHZ2yJO3/BFZJHohYqKXai79O3/BOy3S+EbZMvc3HltXXUwlUO4WChwhr8O3x5aq/6M7YpU+KGUckPQqEb3uu05rc96rNLKGNWPA2+FpIAX4hslEE4tLBel8UjXFyCGknYq4Y7w5MUO0iDojagl0O49/66qEEmp48UwmsM6kaUQM4HY9fFUcJpX2yJY/g17lCf8UYIxKYLHXr60HAdxB9cfE15cweSuilhiXa0+itSLHlpoYKxb+Uj4iYWZ/vFxbbePETJGtab7w796erIlAa+zOVw+I8mLeG3eokT5/WpXdhTYhmEcwsbdUOOnyl3WL8Nklto4SdY0ThaLDhs/Fo2QrvM7iaDJju7m+/uEUz8zNLfHdT/PGuXJ5UekzECJOVOvt52OX27U+CXQ7hT4/R5nZYkVvMDeKnklOFh3FshSQwIBtnaUkM5aDeg4pOuMqqNWOwgTZmawgUjodSp1/gc8+i+hFDUTcVSt0PToeI1vmEqnJ5yxS7rcrgxzi9MqsBFfnWVTl6SDH6G+T0fCSyH8G3hApZpIcyjCsajFaJgEDSCJJZBuFAeH4ZJr5twRS44zxAf9IdsPFK2zMXiWqR4JYOsr32yxFfIeetLBeUUGQmeT5+RpSVGRm4KXPCdVgJtySeH8DTwfILMvvsCn41yUWpskZNOhmyz8/wRrVhUuT8NFZQyOZBTfH/yIPcoc0XODj1S/+gRpBm4TTMBvRrKryX5IOQQTqe8GuxiqYM1UDy1Y+9S/vCTKyt3spLSuxfi7zgryr5/xxDZpoKlpAZ0OOwAyUOBXQg4fYNw2MEXOtrb6lyMguFtn7ZR3SZxhXTH9/J5l0O4ttAe4eta4CEc6QYXXVUhBFJS7LTq8L5z3LwcN3UtpFcQSp0x/0yrZZZWtQY9D+JAmVbWZBCx+wWyw0TPmBzC4fgBWUOkaprwFx2YEqegcB6VM45v2UKCZvPV2Rt6IkQLMgUOexB+OA1kkt6xJX4YyVXVD2gTxs9ZifG7Wki/Fk/zhVV7PJwDh3XuxdMcx6HIGE0G4BzbxGCBMvbRAjpHO1m0pwN0ssToBxA4M0z3NoIaJ9qvYSV9Q0oyDiOw01j60/XqaL3OUt5WkALY4/8J0/slt9D7bw7Ukdh57pbdz3TBI+k+OdBLMp5PzuMZ9gi9eNGAebSlEyxKoDkP4qOGCcAMCjFVw8fdDA7QjHV4gVHwn3Fl7oFDOI+XeEGcLXPR/CvYbWcSR4VY6oH5CwRVU8L27SkpdgbCowVZiK1Q6IEX/9DipgFcQ8vI4aXo7RMKnUPWYIlj7uROIgWIZxuYBvomBgjvUWxedNeOhAbbmjCeYeMOu3HfR/S5B/Koq44TyYP/Hxav0vdYevbAlTl52FWxjVzRtgRN9rVl4ocvc/EXdnqMaNkwJfYYO31FwEd/dz4drU6KZo2vKyyEO7piuYPuoMDqh62fBXL0T5R/Fb+yEI4RB+0ZW/uWsxBxQBdujdTrXOZpYFbI3vPuIfbUVbdV7OF4ORHL5quL8hk3cepxUSNjXYlVUuzi5gzPLNfPtSq6T1Z+CJPT42oDY1WnYmKpA+aUBCEJKDefXXp5D8VUlpuvnmGB1XXRXvOR4zfBuvf/m+w4RCh0dDdf4pfpeJx0wewhriM7vnYnAHAb3Sz7fatDTT1yb/9HCp++CFqiULg1ClcnPQNvi7RIfG6LqGqOo2x1zcmSm3FFLicmrjn8lGIHFvLEZkyBS4TLIR+ZWO53nSrOOmFw+V+umnrVRLwaG1OJ899oZvbpda6I8OS1EoQBnj4tlnFYq29a5f7ww0YN5LLJoCpRiwW4UxiA3OPGFDjYzmmGHzMYMq9wprNQ6qKTdyGYctSSYhcnXJswBGuzbF4a3hmnhvNp7UJ5JUIG4dUCm/pI1QoH5dNSPwFS204D5jdLRBjopmcAcHDsPtclEPMrU5+3RyRTZ6qBspjC5COEtdW31feI6hblJ/hM8qXwnnGmyHlb35LnluZVOyP5w1lsPm5xI4btVz1VPkk/b+R5dQYB1ln7nUW4UcEX7z+30ldFozAsjdCfafVYtp9x6f5LLoIwZQcG9mLgeJwbyLJz8Gq4GhD74JCmgupwTgVzOKDT4zoco+3eMdrh+Ghfjo/miqvpVkv33koU5azNrOKvlqnqb79CJhHFzmK4Hb0Yw0t/d8BGMvZwmLpvLhcksvVdk/0nrMi9df6mBFfojPdroUY7lMVfMgbuPq/w7293/00IImPXzP/hE0zGopiK1/tmBUuX+u5gKKyPFgv8HiDXpc1nF6OjT87EWxub739Owe4og4+z4r5PZ+fOl9raI/Fk25wo8JgCh/MRNISLohLT61LfZ58lZqfrJF2Ol0zgpqlFNer+2bav2EU3hfZ4f4KqGw2Lkv4++zx+hU+V/2rT1h53tYmKClsy3/rFRJEliqe/zz7vF0WW/SiwGnUJE/x0jMe6NaIYab2ido/y6knUAtiSrTNRAiP/OywBytrUWpr4xChb4nRVKdILSjHeqIr3ClNf56woV0CSipkvdcd8BTI+owVT4uDIip6COHbiq6O7uzRLJR5VpsABH05TxLvoum/Tu4/OqzZ+p3/UjaMYV+gQNaMIIvKLFsLPyivsKq5oTmsId+VzcZ/m0mt6Yqkb5j69lRK5ALA1e1U3O4Gn8v0cu29Vyprj7FRnaVnVIutTn91mXkS1+TrtHoXE8RrkL4JG2350wSONpfOLz6sRv6Nvj2meCDJaKHToo5Bq7MQ1tVjLdu/4fa3/6ozpvRTTexdM/5WusbkPMvFuLlfkoBUsixzKcmEzBQ7rp0/iy62fzecppPxcej1ZA8E3etuV5KPWq2pu62E6Od6sughfycnnpsgVpzyvB1/mcA7yVHyGdY0MyaoQl59Y6oB5WUKowy0pd5ijBhlXaSLFzJd53Br8AeSPanclMx3PRj9WDT2Unkkesc+MhkklFpeHcDIh2FYZFTvgJz53nt/niNRtmmn+5Iotcolrn+ZZ3jEes51rtdH6auBio1H5rDV9/bEc8fEMgwiqxe1tCR9TIK5btmTXtqiZmLs/awzj6x6L5zmuvOo43PwZ5PcNTjzPYaG/TxtGc1wsOKO2/eIaedi6ZaUPeg1FDji7YIau7onoiZRDOMiCzTNX6kaUQA5zBO45orRfnNwZW5037M8ZBTxWROnOuSd60RUmw3ssHjJcXXVblf++xydNRtIQSLeCodDh+DJP/2jgFZRY5VyRg+stA/fnK9QfnEBDHLqk2CHosubcz+TD/GvwT62TtXdDr+qSRFxURVOG2h0yjD7r3ArNLuhtfe/F5cSWuGOUXCPmilwOgs/KYnWRNff865NsidNBfNEkwrqiPm/NKuijqMI4v8fiGfMmr7oLHB7DMiHvY3MKb/vJYfdqMm6Lab/MsxdsuyZ/sOR07Wyfxv/ntMjmuqI/RH0GXv4a8HgGw6oqj7Mv4BZlAbBT20z9I74/ippfe1zRHuvmmPDh3OfJd7upiYRzXhug2ElNWeziUDSTVjFKimCy4X9sYFUj7RyvLIk+wBbPeVi57ZrVjh7100ewca4VYEwBVwvk1bfVz6d+L9r3tWhFILtXGDuq1C03MfsuXzZ1MHsfZ07mWxqB3paMHX4+1z4Py1Va4ZCE9s5T4J7PYfPZ/40otnUNxr12MKRvY+204evWcNDpc40vLWVHTb1EjaYJCUyIwU06zB6c5YZuHC6Le90/Rlh9T5XzBabJXcrrSbJyd+ydiDc1IgGzb+sbntjr4gFyTgP6uyO2oySBVaXCyZQ6aOQ4rglpnSp5ISvfmtV+VpTNKjyQZkDjsY41dcdZtNfFOk14FMPHuRa/eL3b9V73+YU8W8jFVtxo27nETYQvCVtEWBsEj+/iUFQeZ3WQFnkUw8fZVgcmgex1SabA+caA9LKAo3OxlZ68X7H7ao8Jv1DDoek+uTjAqlqWmYX+7o5NNZOycnfsJOu2FG9bcpBZbjILhAsrXzk1qYj6WBbNWiqnhpJdvpbxddh7eMnSf55DSOGlKVWfmIKDwLLkmUO+zZHUNiICIqhtBI+vOFRU3lZ/1/ZfLNsm7t6z8xoyF2ELpp1O97WiqDfOMiGNyTICMAWO+MQ0UtRnl6NIyXtAHm8AxbW8uivvnQ9ByPkolLocP7fHWArUkmLHecHXDhsBL1fk3l85WrHUwYXYvl0lRywUOuNtrzgr/ZMqIHeOO2nKEubJi3iLQA7h0kJb7xLw8QRsiXuf2QNL1ZoRoRwse1DLJA712ZWvm9sap2w+z5MMdUzG3jyEZwv4grO+hQHCvQWSdnp4blA3FjlkYIvasckhXVvsRIJmbDyEZwuasfAQni2guuLak0N4yick51OsY4LsDEIpySzAY7QtJaYFeIy2pWS2AHcK3sBVhKul/VdH/pBznQ+n9atNgm5T5No7Mes9/d3lmsxdky/gQvbMKF/mgvUJlIuLIs3r6icsIZpbPrBPAeKwzy1h8lA09VFdl+ltU0OlnaeHDGix+o9VZmiqBXHfvVUhn7Jyh1CkyHk6B817rdDI184BltguQEIXGb5IHJwgFpGpGHpIl+CVciGGem2+umESVdDNV0dMkjH7jfALqB7gQk9NFYxbn08eH9+LPW6/umE6fV6nJQl6+VLk9VJEKgD44v9PCCRU5sv9OPhDWsKk/gBvU/52jwrIxQU1VOvyzn4qMok7SgUV0pKMg9RQXi0dg/xBNLWkAN74xcUqBfDDf36iRo3LvLD2WQdVmIdyL+znt4B3j/KF7vsC0UmkmavlEA4rrUE6Y5n+iyzT6xLkFUjwT2Fj08CFtyYyqR4yvMVLWDV8XnETrIt0XOMMCxp6yiFCWpCNSA3lFAkxaHmaAWnAXC6vlMkSVFDphZUCuNhVqfzuBVPg7vHrcgRK/X19mTtWbHDhhMdN3e7RWi+ddSWXA584ed934ViGNqMu4QqkuXCzQgFi38YnUH2FT52x/rXAEa+JJN+bBmxrjoN6g/t7hWynT2lVhz+ELkHpk1PYDs04h0eDB5JfM9R3RweF9HDCcavYtbxPH9M7Yj9FZC4JSh/mskMzDnP1bfNY6O8OErSCi59pvZQymVDohleSKob6/Cdg3Di8GsCfk13h79Qxilsk74apody5X3YGx5c5WAcSb627l/a86ntAriMCQWeSAriPHRmma5mtJCt30XySdJ1iVUPQKbkiD5ySG0t8mYNeDHOs9YuqL/XdFZukg0yBg4cQVpVwS3746MJNG7IT5U/kJgnAHkvVQWJECD/yTJmlqTtiGBJuUBE6tCmaXp+8iPhc9z8aQKjMotp8dVA88rS+KNNEfjIslnpglp77iqUulFT117ev6n769lF64OxxrNzbQO32Kh20AsS3DSkZFCAOKoPxmDT0eFRzLOp9HPqheMqzAiwk+cu4IpeNqq+qVHskAC6RsgnMK9jjEIL1xWKHviP5+ROm90v+FULqu0MIZJMvMoh3GS74kfruLF9P8I1XmYRtC7Zre/5KEmQFb88Yje/2LK875vYcvpV+FbIfffVLeHRdDE/kyiLp6eI91hRpD20cv5GI0cdtZIVlHE6NG+vdDoGTSt03VyzHqAS/9iJBNhS5+Z1k1jz9fXpbbudWED5FahOxhqyaHovnq1vyqtstya9LkDyggckOLfkyB6w4DFGmpzAFjieLUH4Eypc5nROmj7CUvxYsFP4JVk+4s4LGFLCKpnRZDG1KzsH77x4OEPnadPYfuzsaZtNh6qbML+EfJANmoPJCofJSW7T1R2KjSJfcYjNQXEUqnt/rEoKqyM+Ksp0t3tfOFbrgJdMOie3OuziEQm+86kgOLaD7vMmTz4ulLpwK7u6+ikmj6e8OXp/FKs2lIX5siQulqeUrvzqoANnN0J7ZNv2C/HmChG+MjZ/F5rX5m1Bst+S+AGWnuog3XekSV/+cDCNb4qLsbGgsO5KWlc9mtEc8rxnDN92PCrEwLOGCHFTIx81CzLHbHuRdzzdXa5gMkYmbuQ9LJ6xD7ZNb2A3fOGIx5vKTj+TbWhqQbYB1vI1zlmZo8QlBsXyZkwh9+pZ3ZFC9L8AUO3vFd+f5Dd1kBSoUGsw+yoUTupEUDWkf7Ph/8qRJ+8GJY/BgNO7boRRau8YNnfwlD0tH2NkRHv9tXFp57pmed15+gDJFSuywEk6K1W2ag/Bdw4zffx6dkI60gzw03GaBPzhE5Nb8w6XtF4cTRpA3dyDBt/NKZNZKbwOrYBzDwSRxYE5hODC/5y+P99/ssfxMFzyS7pPD/SnJQdgn92AdUEFCBNlxsVDogRf/0OKmARy08KpK73Nk/aaEI875Bxhl5e5neDhFqXB9iStzN7xxkCSPlS9zCTyTPQW0+bo/rhEkQZMHufeCK3K05r419bc7gqJL7CgadSLItu9+o2x58fa5XXQ4dJWURpas3CG8AT7X6JP46Bj13e3ixB9NWsruS/TfPZbzSZHXZZHJvLwqmP03COKuuQiLbfJVdpSlQBCb5NOkBqVnTubtEtzkZugo0ru9cxpNhCvQjSrH+T4oRLAMbNe4GdUtyqs/GlDC6vL+ljtg4QsdzaCjxT+bqhaP14VCB6OGGB8qxGKpy152UcIrmMFEcquCKZpir1FhJMtBtjEyBS43PvIHfLwn1V+Ewj0M/rpOkaWP+TFMGA5oPCSfpu72q6uxM6Tjp2BVh/B92RzH0C5+nbnOEdoXDIKODfBPn1MCeb25XcXKCICScxeQDw5MX2WnObjN+I2C/u6ADSZNCYU+UZ8dHHbio0KfnF8UKu6LwaXF7Qhs0Zw74ad6lR0Xixe+i/R3Fz0orxFj9363r7B+KsoHXh2SwzgJEbTgXshq6ZPki1JYDuPcyulzsgT5PSTpyfSNqUC3RrR1nQq9W9aPzevRelXVbRVyupcf/F58EG+le1xJx4v9c4EKhRymTJGr5nBWlCtQ10K0jFjqohyHPRykXKDNbZZWS373oD7PKVi3KeBOOeoCJwM8zRdoRrl54Yq2RoQRNuk+RVDSOjBfXU1ZfRxp1jbP49h8dcUkSkf6+3jWy1xG6hKuIHE3Id0y0FClUfkYq/r647APaZQ7sGg/TbmhSpLsOSfY2xGGOwbJw3lOjiLpLMNhrKdA6sGE1pjGYcdo1y4i+mHiXmDYuXvAdODONVwhxSf0oEyG0YNV7dBsqw2Bnzu/AHwY0ebrHh+7nqCJui/KlzjcxGPzsUCNKA5ctHVc1AfSRmEiDllAXO+BhXaHhT7CHJZpEin+g8fmk/LYiGLbjch/hy/tS+AMps1XJ0wCkoNNIeXjoyS7hEkRmqt7QOPBuZq6286ycf0e45y2nlfnC96t23/bGjb8XkZhwwGNBxtq6v652PAqazh3fftljsB01bOV+ucq55Kl/aOXgbK0R+MjS9V1x2FixZv0Xm/Rx3pnScZ8atabyzcCQdWUsA2OC3SK0Kh8vCH6+ttqfbSPeSHV7gkLbVZgsUVOh6lpIZym4k97bMt08/8hRU1WwQ5lHps/Q2pQHHhyz3nyrCibVbxTDgGdB1da4BjpZINqU3wHQyyd63yCEIhHNXx0OFgs1mnC4xk+7vF5yUVJXgfoEiyHuiVpXF5eST2C7T7FOyuLlYq7+TIXzlThZEuc1vY/YVILS7r96HaFULw86HptEEiuDAJHb0OnsB+/tM8I8wiFYi/cw8tPSvQUxB5LDGLWoILPRWD4EoXIy4WnqT2S4blpUnolVSye7dhe+l65ex7TXWZOjDkag2KgMCaVYxhpRxvBJAg3VKQ3JTTXJGY771+tQXofqP33WLzO91VVt9YEjaRR4OsaLJL2y5wxy6Gx37M5WIgOHSkEikXm5V4xYNhW1j5OEvIcaedd5hlAUryLyybe6UlLjUT6FjtfNv8FDPzeLA7MA1nG5/hhShx0xLoGyRKvgXdnqXimKin2wf1ej/t9CO6/6HH/RY17JlH3FT5Vn2FdwzKe806O00Pw2SIaSf5JWxcdejo4x7UvWfLjHaRNpwbsSGzNyRImD0UTK0mQgM5HnTXj2NbNf5uTZJE3w7Dt1IVyynGroVz6fQ2eT5+hQAamwIGq4LkPYRZcmmyR0/a11SnD4ile2yJYIiSOkuOMIWImTRYltC748GQAU8qxQxKmsNU723t0SVPitx0uwAtuNda7ujKsfm/rWmIaZ93xzfPYZOX22GO9TrpzLnSebHG5LQKbTSbXX5IMylJwMwWO+C5gmRYLYYdgi1xOh2uQkdqcU4QpcDFz0PTJ36hlSuZwLcWK1TzP0zoFmXSB82V7vM5JgpX0XySvHx5I6L7C4/PZUSxwjLPWT6MFxvuFjyuxkSw48mtKfJkHVgVCd1yS60tMwdZw/SXE5w99LsvQvY3G5bWz6RGMw+sXfVqBd7whsPnuge29Atv7vdbRT8qiqpA1kkXhKB6bjy1sRLG/XDXbThoYCeUXATVh5BNq6jN8hJmwqVHfXVyXRVn3QZ6cu5IucQi9bLJMipApcFAR192BLke0zee5Irvwc4xChtDho4vxfAfLEpYCLqZgzhOX+Mnizkr82jbO3cjF5g6fXSLsSA7QT6DijUO6YGtEFPqAkx4G5ptrkfikmlPV3NaTnz/RdfzNmUuoBUid3vgklNPV3lY+2Tl9ldxpCZxmjMJnguX1xpnaNs5VnGD6u4vLKMmaBTzPr1JUG3CGuFjqdNABqgoH46KCWn7cIQK46AttZV5h6L86uBrTms/p0H2aMlLtC6xBF73MKWdsiRtG5Vs+QqEbXgnNqM/zx79dwhyJp6PqZ7q4hzWvCLJlDseCpMZ/FTk3dPq7K7afJVh3qpUMKVPsihu/dy6ZKaHQFe9xgYU/v6D5MqdjXLRJ849YbL46rmX8qK+4nMnX6bero6oqkpS8RCvsWWgrJTGjN0frdZZiTqcUFs1Gpa/Hb089tEoJQXvkQtz9lQ3cXBVNKX0Gxmq3G1DLtj1MzKEvgd28BiVe3p7d7Inl2M3f3krnO4QlBv+bE0NsaqnYQeFGsyJzj32reWHoZBgndGimZgQS4Ib+RNvqsljcXMKqLlOsJJ3gUZokhE1twZZl6rSANsLC3FYgm3ANRGAWiy4Hio+WelMzTe96u6GubegeCxGhxVdBWpjeP2imrYg1cPoHhBEmXtK5sInu8Mw20cdplqHPg/vWYrb5Kqopd5lrFmcgTTlkMaedQx3GmM4dQ4r8IsXz+eq8+tpk2e+v70BWQcfRBzPPBSxXaYWTAbVJ+m7ohIhaHjLVFPJecPA0uAV76ZsLnD0BeQQ+M3Q4cE+hcM0mb6xZRVVDJW0cWUOOfht3mn1hgUv4BMrFRZHmddUFxN58r+DiZ1ovO2ewLqLEWFmMIRGqWPCFsaHAGWBxReATc4e3cZMykSGewOlVdRcNR6gTQ8XhkAbyEY8tpsThcW8jA5nHH67mdIZ79+81uNfrNjJwMZEXKdzA2GgxIuJQ1cXLJWHduSj+EoQp+g7V+1qxQxykOSx5kMGZ230Z/q76D3hCwT38UixgVm3qXSVLuAJkRNUaJMSCX8CztKxwaDi4BRVsQV6/Qn1/TJHU64/cOofLH9lJ1qbI6gG+gDy9g1V9XTzA/PfX73959/71q6MsBRWOG8juXr96XmV59feErFuQ50VNhv7762Vdr//+9m1FWqzerNKkLKrirn6TFKu3YFG8Rbj+8vbdu7dwsXrLV+/QWmH55X/0WKpqkdEzTh2cdvPcvyn9PU853vjt36HAaf0MX8K7Vyo58ttbvuJvEt7CXfj9dYopS1YjeZyBRJcCfK87x1CQ9Oz1Kyxu8KXQQeS81aJvT0vbBvJHUCZLgBSRL+C5vQPx++tff3HGyRyqWaOuSzEEQ8DMvh86Bm5Kj+tI7jh6nDTuDjRZ3SO5TU1I6AMWLQOePq+LEoveu5Q3EfaXA9/94s6CZ0WGpnEU1L1so6MNNE389RePNobMWbYcJKLAsnrRYDfKNageuDnkBebfz/MFfP799f9NKv/91fl/3PD1/+0VWRl/f/XLq//lQzPMsW3SibYfTZ7+0cCUcM1dipec6xSnGeI8HHnGkf+/rcDz/+G6+r/d3VWwDln35Kg+BMExqJPlVfovGILkAjEmXqAjCJ+OIyDmhz+L7PnVY/ES/cYFqw1/XsEE2RRVCGuQLIVCtyxEAeGB/8WM4G+RhJpF61/hc33Z5Ddd9UEOvfOQQ4h/1t/y07IsyhDZ2nWJhCi3WHDQcp1iZgoYESdZbdjiM6hqcnvTty8DAvIL2SWhvUEo4vflnSdlmiRBlrW0Px4jo9lGpU44L+zz6lO6QPIrhB/Rn/fYhYCEf0LsL6mQsOlNj2m4VxE0Wuut5R8NbOCizSE3ZCPbkz2GGpu7FsZUDlLBOqsfm060YealY5DXGCOvgz71nBt92lohMgu7LvpW0Vhu0xyUL14qpFGZeO+xaX5Bwkq+cTshtl6JH4qnPCvAYk8WXz8cveWhZjT3dfa9gn2j5JqVv1SXoAkycXp8x4TF4/B8F5cr41AvfHg955J15IXs9LnuHvyJge28+gqfQubzvLouAeoPtUPb6sDDrbgbCkmQJszes/NQ1vRdMu9QPrrBngilTVS3/x6MHx2JbrlipK4msc3SuS6id/W6GKOjl3Cdvbj11gHtGD0+OYmN8ThJYqMc8l5H1hnbC0YRZDt7j1ltKtpp2nhD3EQn+61vjMTYHatNkEvM7aZfs7XDDBAm63b8oxGqp3uyT3QJlnWK/6+/uquV7TmX2Vphcdvw2qei0i9yn/5eFGWQWx0p5KVMpQzv2HDRMjLi1i94VQVZD9gOac8hkXAjHIhqjbDuusR97TWCPVl4zJhGPed7JreLmaDg80X0w4OhmfZKhqmF9x5bcd8Ee61khLF0YyDtYduOWKDP/Nbm7GXJ01WzIrvb0YpsIf22C5N0BTIc0oJ+VSQ25d3fEMvhCAQ0667dR4OfqKUWe3+vJxalcNId2/gOfkkEOIi7iKrjJl+gFYLW45BvuT0G3hPBsxmfu6pG1w1S1JhU1v6cwibsDsPF5YWOv4nx7LUn/HTRp1RzZaahYhAntfT07gRXPagrfeheCBf292vHktjDteT2GI86f/M6pLbQWJwNeZzDTSP+fX2+iM2pV00CBv0pXcDrZbO6zSnTyQfRDzSft1nQBFw0t1laLcPCuGJFJUb1cOidx1FF8n4JYtxC2E54AUrUBZIVeEguG4ax43QkftPHdOHongkXO3a+o1Hkjl6V9cJ5tFil+fAYbwSEPeN0jyuGTTXOd/Mt/4QszYvAzaXHEUs8sQme4m5aQp6nCNNCZXqK29mjLCueBncAfEzhU9CGeLRel8UjXFwCnKTxqlmFzNLXoo6Kr0dGHjTgBhvYv1gou6OL6+IoCdInhERe/qiuHproSwTkzR1I6qaEJdph6q9Ig9os6FitfEQsExvnefUxvatPQBmkZfU4wvfn7hG2b/USlhdM2iK/nvWPug1bvV48+pyiHTXYEKvTBG/9R4sF12RQ98+rIaAoQiRM2NR8z7N2EfbogkaGiN6ukm93Aj4v47JDcvq8TktiEX8ALyqMLuE+5DEWgjCcuz+B6gogTQTGmFUWk8cNFa5+SBQgGhg+Jzq6LyFc8QE6HgdOAyL8nGSk8KPhraQwedIhYR46CpF3NL6L4ZmjCBiZZ45CfIf4TCLCjarz6gxNan/AEaSULdrb4SDrsZ0s8YVjH8eSbejZ5jXPEAqcVkEk5N4ADbAXQI7f28kf0RJDyPrTpiBNry6Sh0huQmwTEXxHjyBFddOMwhngBpL20Wv3SvNo4/1cPLVjxRtN96ZSkA6f3r0QO/qsKPv+HUNkFoWgPQbJA0nLiq+9Bx5sYBMN4ztvaci+TB4wKWT76o4iY0xMi689cIyBjwwcLjpUVIBTNFUUsTkGPm5ejpu6LoIuxXS4fqbVMkurOhxht5YziPgSCWbG5+GD7wTp2wRVmoT5mWkE0beOb9li3AY6M+OEih2K3sbVGuEBmfdArM5GqDaGBxWv0xWMEMRH4z7NFxEx966m07yGZRXMi530YrDCkRmok3CTtonshesUtms3SOajzRNWNfV8+QrfxsBbyajMivrfnzZWXbbgkFG0z0GPRm3WTImO/me6GBH7p3FpM+xKsWXOgDiuwIl1YhDndLV/YZZCEfMy2LacukpHnj7C8gXPqrvrha0d4nihUyr5XI+la4f04xhUsNtegx0FA64vEFRNCUm6KH0YpHd3x40hHJrBP9imPDySbTxP+xKFxC0WehTQhQvBEgdwxXDTMAgxGWLiu1oWrecHbMLbI0a0DbFK+xE/YYwq8Llb3dMo3C/+vYJxgrbUIWDRFYe+KX8JYulWo9+WD9MdOk0kAqbujKs6KZo1joxeBM2aiMUm25hLSCA5Pia7YBijbvDgrdvBr24teORP7Oyv4PEJZ8KRR66IrbglcpTLcVEjDSx6jJQxP5bHQunZLk6g1CEciQk3jHNmc5GSABOPYPS+YoiCj6PVQpPrMcFZ1XXR3kjgMXv5cDsc39hTBBtVxy6KEOnwlyC/N/js/ULCY8UUxvVJbWHk1k74LPYt4lxGQXIv9kcKn75IdDYLCWwfxd6Krj1RhrrRxEwgZJXf6q8eEeOwUOUSYlD/xSfk8JAIaI5EQN1B4Z4tqXlv6I2nk4241zg7wTprf4+SSvYj83DdDzVDZ44n7WWTQXWyBK/d4WoNR3dQdY/NDbkRgmLI+nC+GMg2T3JeF2yCiAAf/AbphTKi3GuqKMR09ozYyHsKKwylQOydkh9E4dPnugR0VtEx9Er6AG5PRJrRIebxEslJkRXlJ/hMUhDERr59j5G4qlJ75qudWZdSeMks2t/UDOrAeXWGTO5mc3UnQsTxyBxIXzw7cGEMLqQp6t4Htvafhhv3kA1HObiKfm5B0f1wchP35OZw2mLs3e6dthwOI3b7MMI+jKJ/E7xNsL8nm1I/Kg8VeagZppSsmUeU463586rPPBEUSLSrbLpn/Bn1oUKrBMQ+WV2N6aE9kFolNQ7Ae1aUKxCYsarHdQU2j6zG6mf0BE6Rrl4f3d2lWRqsHpM7ukG609g7/nnVniH0qdxDIkA0mZu1XQ5jIfxWnN0+4xPnFnOHwD39XNyneaSoWoyvvwVugdLleKYj541HFlEeQYhd0x8/+HdHxGDfH+ttuWe+/diVyRv00c4UMZNGQybdgz1f0lqtQR7pORPp8aONlt1XDFojCD3O2vuY5omH/4GrHtKTEyrhQWBaR7Ke3sVE9j4Ksv9K1xdFhRPl+EWySbSrZZFDeQI4vzSbfaKsOKztv//ZGzXtKtgT6Wl0BL/zcAQT31zVba1Bei1BFOO23vVT8RliYp1XhfEqzntXvrtelhDa4/+LK360RGCZJhzuoIyVP0CQ9rxV6au9/Z72r9szD5f8Wdb+NhwCxeKR8/scUa/NpBbkGZ/oVZ4IL9nYczetVO0Jc4+n5c64r97elvAxBbLFFeo6mFGgW/PpcVbcY312T1j0M8jvG5yo0JlHNzWDmFR6tCxIaTtHjM1jmw4Hu62PNUpy8w7XiSY/hd2S3uQPj4XyGtzHCVLdznv0h3CL+AfzU5i4vXjZEzk7yl7c0+ikyciFI/2JsfuxIDlXvIIjGKtnGbg/X6Gu4ytwRtq4Rydf1vt1o3ZcnaYNEL+qcU7rS1gVTbk3Kvjs+k1PTyOT++QH6pFLbw/4qT44h3ixusia+1SVi9byULloEjXbBxwdfYVP1R69gDg7h0bUwMkrWHFQ4Qw0cTBFkcDbqdz+meyU7dBfDwZGj9b6Hk2RZUd59bQ3IXh4QB5B66RWdH+en0js3wX6UdRhT5eMfQcLEW1PuGb2bT4e97RRa53Mi3OiH2WLjpbniWyrHxtY1UiLxWtkGw4Yt1MDGf/Ykz7j2hNZYLYFf/3VXWGO9PRTlGBghKTje4xDwfZWGm5wOHAfrkv4Z6RYXfXUhShOsFylFT53vYQJlrT7y/wh+9Aoi2nIOxCG2HquT58xVUF21NRLTNeEKAN7Ne+z36yKFwnbz9Y5deUmItpOckbG/g3z1nXxAOOYkQTdUZLAqoqHlMR/oAkOStJkvejOirJZ7dFZ/nWxThP35dVVC8ssMvfitnrF1E5fuNiFizFTXJ0k64Nwx54sEDIgdxbtqu34AsHziFsOzB/Xxu7qfYceqaq+tpI4yBmF0+UGIcAXb3AvAl8w6LAoptwTG8mjFmis76YE2ifh87EsmrWnBOrqjhsS6vVKTeQTiq/drhO0lmMIFLz2ZErVQayM4uHcTfFEluWeyKidEA/7xm5zONVb4u0H05KxRLzASfBFza+iT9m7G/YDm6QgNMlBYGe4FAXBOQ7CLnGTmvj+UsP3xHNYMXB1Oa4jomrvHUbOnz5kEWvKEubJS7RL4j3CS7A5vjVkZv+b96pkj7vCqP0D1LGFGTLaa7QWsvM8yVBXLcnxVz9J3DeGbw1O0dg1bmx4M2CiETKNTjPSTjZMM8KusUlHhhpyWKzujTFiDAn+FO8NIDuDcGyaqlsem8Dqlsemdoc/ztUywiejM+LwIvGorRDRMVoTSFNvkLazGPlJkkv4BMrFRYE2uOonLCFircC8kkuYPBRNfVTXZXrb1DC21Sg0UP3HKlJepE4JUET4ucaexUmjN2j96yhjJBFx2IzBT8eUEMmREzT/rJ7iNe0ICx0hFDYRuEvRFFNhfIF5xKsHuFCRLrinJ4+PcbI1YWSnz+u0JJbTlyKvlyPg/U8I4oyd5ssPKRJu9QdI+DAkXnNA02V4/FRki0hzJSKPyAgU8mOQP0QzpTi80ZYYjff8JDbKPkdWZLTntyDShtRJaKIUxMznigNz0IL4V/uIOn7vECTsu+yjoI/GbqoGLmHViOl0PaXRGl+Yjk8cEXHEXiO7c9CJ4nf9osF1KxjbnXoB0ljB5lwGrCg07VBiWwUnuGxal+Eovq6xExNv74EGbS5cwhVIcypI3SMq/BPAL9x2xu3XArvlEyYjUcSjkt4q/F4h3f5TiqZrbxIvzv5GJ6nq3npXLSwga4IcJh/TO6Ls7yHr9ENzn7xNzaD5+17Bxc+0XnqyEFc9uCtMBobo7pYpmXVPGLRXZ6hZRnu5x71dBZ6QA8Oe1OGHRSO7+c6rvqvkHhbgtRdPoYFMs3VEg+ESDXaN33SPpqkNGOPdGbmCOdarY/WwRReve19gVVG3ZgMfFNnMCNHNZntyyC0eZo+SygzjiRrHMqO6djHvm6X/aEA3Ef6y+nue1uThvbGPG4eGRj9dnGI0k4xk7NPQ3l5q9+uxSca2NjbtRjuyi39U96F4yrMCLIKTEZ1XPaooitFnxOJ5BXucSp3QavdFUv8nTO+XXmqhTQvHTb7I4AdQgzgOwu6pd3wRMw6Pum37X3GCj33a9mfZoL9SaVLCLmD2kXTF8HTjliuPtHdzv7w8s0cdt0QNCl4lGI5BBvC7AiHqWzV6VE1MIyzuYQDt//B4Uo6vP8KDcvggZ7U/7xDPKMmvS5A8pPl9xDNAEvM2rlJCDvJgrJPGDzBLH2Fp80bktrwJ1i+APfJiDEPyut/R1oxwPiX6jUf3HjjoHnVT5pfwD5ytbl+mPfy6VKSJm13/ieF3uoSgKvKzomx5JY6S3nEcJPavhb3vg9Q2BMHpnhGXLDn0xZO7u69FrCh33cvefHJe9xcRaEER41bYtkSbOGyQBQn1OQHlXm2S4dLyApSd4hDkeWr9Qn7HrHTdsOevN5Mcfrw6u/yf+dhjvMsSaHXCErE/du6PZk/H2D13Tsx1M3+1RjTsw+KGedwTmTfzspDT9tuajca1tlW02MLWL74ecZZmiNyBWYHb5Nod+ULza4+cNV5H0D1ZAPIhxuK9rck0Pwuj7AmL7MwsdELlGtzvMeUd37R2Jd4PUKZI1xl4GFmRt2kO9kniPTQuNLUKw6xT/RPGPi/2gLy5Awm+BFQis0pxvS+0FW+12epJB9KvsbD/TBfjIf80btwDqCChvP8xoFMz+AfblM8DClWV3udoBaaEKU2vxL/zcC31hyU4l6DHVRKmdojt35t7OP7NvR9s7ZB+nFfhr1bsneGP9oPkIYZBTmyab0397Y6gJIMcI0WeYmfdk+00lL/6fwe63HwBxPG2YcAbWm8cuPGdvxcswM4RMQRnm0efqEdyggPm/2jSMiyIkFL+8rossnD3p1Lxn4BP3hunxXUl79sSPspSEP2RgohWY1A0cKiYbu/j7cdEK4boLQWltFIVxpTj83Gs1dFEkRXl1R8NKGF1eX8bu5+t5bD4J5om+oA3+qFHG2Y1QUPnFcJ0BTOYBEa/R9hmorC0ecsR+04aCt9pP6f5Az4Nkyll2xNsdJ3CsnU97JVgne0YKV5aaPy4of8hdVs7hukdFIUQ8SzY/ggAz8GesHMEv7PkyLoU7P9gnFdVdppj+KBt4womTQkd+2flRaTfDYnmJftc3BeDE24Uq8wRz6d6lR0Xi5dYqa+Q1YkYt3fnfYX1U1E+jOD5XoHyhSydPsW3j/yWYQmM1CEoT5/RKPN7SPJJhfZPjsyhmw6PLLfY/yyS0OOFMl2Geha3e9zrmDnqO3HxucAIHIhiH811VpQrNGVUhEkk9N7voEiWZ4wX5vf/5ZkPBU7Odpov0GSGboFuOljnFtwTAdSOMWyfb3GMotQ5Wx72JuISriAxuBGqPZlMMqbYiozrvNrgZJKQqd7vcsY6HrMcg+ThPCfHeHRu0z1hmxiB+fM6KGYPf5/i3iQdsXMNV2iD35sTolH2DvzKLuqakBY+GPHIYYYniKb3RflymOP9neNO7B2meH+nmNA1TfbtMD+GwYCG0D5GG3tKEeL4/CfTVf//9q6tOW5bSf+VU3nch3iTs/vmbJUsW46r7ESR5Lh2X1j0DCRxTQ2nSI4v59cfErzh0g00SICXsV8Sa9BAX/ChiUujMS7SINwE9WKX3rBddjZJcVe+LJ3jNIt4tP1mP2yWeQwqfJ//ANSc+xzpybwnOaZRH+G9Y94Ko3ut7gmxMwHZ6Fd+/Tw2DD3b4aqBI2Doi1cWF9XCtU2tdB7dbfUEv4zxBPwpl0qzL7Xz9d36TY3A0Cc4oWbULYZeJk/sUJzP9tsPGM0Lo6ssPz2d4zauoJLXbOqL767yHps2d7vLjslusTxCDvtCPEdzl1/zTIA5/XzhKs+exsNQrj3tQk02Xgyx7rR4zNPH/2c7S+qtEZEj9W0hPzsd9UWheNJM9E3RTmdffGveWfTUWP/ix5T25nAFfCpe/fQ2O5dYA0GjmsuIZZLawMYPDYlvqa4RkvWvZwLLsFNl6+z+1xGNOgclOxw+Ph3j5OFc5sSQ9Ufu3cPf3HGN1dHMiw97YLNvbBijwxKeT2y/t3PPMWP8xW7HX01r9wb11K0mDsRXmq2zyDH3B0jgnis9RWPCHfR67FyDA7A8O+zraJ44Tb9NaeeiLOPdYz2H+OUq0U6i3Iw9tPWrx7b+6dgW2ZH8wb4Ub1k9cM9wJwdWzuueDvggI2nyWwuXasJFvMGoXerLl69FN/Xf7pcOpjsBrx9JaDfDt9k85pS4fGS7T9np7JJKBDmGXWW6FP5gSE3fBo35aPNNcRd/ffWVCZqOaaZqpItWnPZxnTElTPBD9PFD85xygWjKjdhm0Zvwnu51ssv4kS3D7wh0eFBmd8rrbNHX8bfaIOf1oJ2qnfvo0Vvw8MLQ6g/QVK3PBA6X33Ypk/OdjuqBuplrlicZ/nQr8RisjFPe2qQ3D2/LOC8JT5fNFu7mIYTqzSEpkzgd+S6eXHv1d5L4Ze3kXzwjEOd9JuMNDBcldJ9mj+iyWk1kp8N+Uj4yJArTj0D/NUYgfkkfj+P3I9k/ld2DMfOzXtJQQv7qTcjRNw0cvo4pHx/NQvJMxup1d4X0lymfor6VX+dfddJXjHlWFNXcPP3Rg3560OFDdy5RGJUmb9lnlk6bAN4+ZnlJfQaaFuJVkft8V/rNsT05831uFjJuhJRZqrIQkExslJEqpLI8Z7mv9hZJGEMR7CqvH5SsE0dNWT41mcN+jwvbbVRPp1y3rMlWdB6eJ8gx+SauZwr75N9LX67wRjaPAT8T+zdBa6TwJtLH8rBLT3v25nCbVM3G/Ypu3NnSdVwUdTBdVVBO3kbuGvOi511S6rnlRrXkLcrlHSvjNvjQz+vMdYPTctrDbfqzncdQmhtWzbLyi+JDsn9gk84ymxb+Lzv40bFp7kMeH9tZAyIbva36ZUupD8Zr+SKrXezEcZknWT4xkzJXp35Pz93iZK9ffVR49NeUD3DXRqR/CUD6jhdAb/9ySMzcFhhC1Wlbx6L8jmucoWqI/K+dhhM2QFw7s2W11b4UxXeTYKgZoid5WEu1uKk+LY/Z/rJWddzglBsiD9GG4aheBTi6WVZrYOI9kkEVx8Ha1wyTq7nZ7uj2YUb0bdcEtVdbVqN6VeI1bmNnak+K4rtJMNQM0ZPXLH9Kijq4pEkKI2awGdOtanvkQSvwHdXHIGNHr6g34eUaWq/TOOi11UOO46m97jqYJ/f2Ckb0+nu3/cpfT3rcGp8jmcgrZuNG8bxTGlSATv5RMjSVA/boDfucsC+/s/R4f0oPIz/AHra+KFEvXrqjUXh0h3TVJ4nyIS5aiwcIGH6RZg/dpeFz7ctWP1IqAtI+XWWz66wYEUA51AwxSOv7IN9LX3rbOPQNjroT3pRMzS1DvM7T1AziwbM0/Turj/4WTcI4g+euFL04FF/GnKaLdYN/Rs+3B5bN3O/PNzT95M011CnOhneCRj1b1swD/pcVPFraQ1N/ZI4tYVi/KIpsl/CebTm8+nrM8noRcJ9UK43b3SPbn+qt+eKTgvxXh/0/6tXIbz9JRK1Ityy9/1kueHdKy+SYJrtKjt9++kVTdWhQkkFqUSmRm/wPrUke1VIfrMbpZXYoyjyuTKWP1+SwS45xCqmjEBOHd23wvlm15CU71mdVhxLUlsKwlbCCZS0jzL7novgdm0mePxMwYYbKXyd2YvvmYn1/0Tu60rQQevZl9uWQZkNCKN6pw49yf/7nzz//otrj+Z+HJjT/H3WMf33H6TIudvFeHzkV4veYGKDkkkwIRRDA9frPADZYLwrj7gL/0lCLxEwOKNAkIsmDSAWqTwqNNgxjgZCFmyo4ukjs1KQcS2NLcGOoKtM69rtwaK4wWMynCTUXg1+37do8tBu1/0cx15WLfdv/NgvWZIFlQZSiIOgCLRQGWYo+FI7Cg8mrgBMYHqF1JtSL3wucIAutB07DqnwROPVRPB79Ep/X46u/Pj5LbGr4ces+BQ4/w7p/YW/Sxx5dHCuT15GarfgJK6Lb7JTvDGu9tq681ut/nMW5aDF/kCyBsdWrPAO4zDGOCE9zHNziMLuL8zqi14u7OGOYOXX5EjAzxMIuBrP287opXwZN2bSys/FkLtOzNTqyHmEWN7b8RHx5fM04FR8DL2Ns06zo6v7RZgCs9zvUoJ51+i5BYFAcqfxsfJiolYsfW3oTIap6PvnM8m939UVrtG9FIqlTpQKnNaCDN/SFC1TVMNhw+q4Jsi2NiX4Wh1yjWtfEXBEawtMZTctVjVxm5avB1WZ2LBcE1fx7lm67VgtvWtYp9e9jvnOWz7hxKbKVmpMLtr6BKWmzhU3MFo4SKnAlpnZoWKeDigSWB4Gac//78UDObMUKq8LeZr5wKwDb/F86d/e28NdOuUN8w6rWkjrZSnOpl3BSI7cgh3AqRbPAD74RjovVU4SJB5VNMAMSCTfiEcaUK/ArwaTtWAfodaSfvwsUuqBgMfjhuRTmwl1ZrVMquT5XqrIIFH1dGBPllbEll2weU5I6DlhaDEpdIgWPILKsH5U0pbyl/retAwDM/bHyrjeAdvoYXh0Y3IfojJCQhFsuGq5LBtG/xWmbWnc1ZPfQ/zjLR0ZNvwOJEtjPdArPgCpjsiGEpTkhyULIskyQHRzE2eLKpY8XgBWehGpuVL1I0vq6IJyAaxSmbEG8Ln5vu2gg8ZKNvzwa2jykEazESj9eSvJUSZS+7Gw+Xp1GLh+vxXDVPFpzW+Y8TUXBJ0RR91IRCq6eQOzR4cdZwAVJLssDEgSBGWywMDAD1aLwFd+fWgRrXS6ebeCrk1aSYfhx8zjqVdkEdrpUPdvATietJMPw4+ax06uyCezUOYa2gZtaUvmwlv+webxwNTaDlSYfVaQL7dpTAVHSyKhJ0P0c5jyf2ose0NIqQuFWky+HFzWRsJjs1brDqNaW+1MrnAddpjTRJvlkwjAIVE0yBxrJabMxfJLyZK8ArLZTfQwIpo7/DkHqDJClAWpJ0T33fqeTB13VNpdtgMwIvlk3vMYCbnVg25AHXCPo5vJ4k4G3rKd79bV+NzBOL07lY93ijhcqn+RVezyTBkrOTxPh5j2gUT0XQC6GxassPz3xTVnfwMPPF3ueUkvCr5vHxaDLdkDAH1adGwXNa64aDNqfzwMHwIu1qwZCxP/7Os9ORxQFAonWee3Ps3yIOENdhEDQwQwTEDwkRoNca3AhgNzuPRYSLws4HXpfzutxOPkKJh+Y2FO6LiSEZp+9OPbrrPMXLtZiIOLvVgQIkjPNXaTH7Xkj7S9bj41r1KAwkg2+cO9vYtE8L2jmnObSUbP4DLdLz/S+iB/Y70klTf4tgvNKrTQNlyg5KI9McDaJuCS1KHwXz8QFYg0YK+4+4juAGN2nLIUvLuGyHz4eEbdmRPVS6hIEDIWbDTuDIlsCzPpzmCwDmxnzlbgBZ+ksJa+T+/IyzvfR9al+i69g+w9J+YjoML4bLdeSOimkxoYfw3kScj9NBEWvCwkTYFcsDhFprgMrNLZLA/kaSHJQnhkmPU4I8IQ253lPV3FdWHsvDoWVzobWBLXZ5kijcSb16LLTpj+ykq1/nl1LqUvQ/LptDA2KrH+efcO+VGi/zqoGis45bWJ/EhBcEgcs3/zeJaTVJnYyIZx5/QhapuPrgctsbmgsVqRuWTaxH38fdc1fsk5ILVlfwHclZgNQr8f6P2OdqHzHCJZ7bK8FRo624SAXBMszSu5YTyAib0v0FZY9pO1SU86XyObHMf1PitEXnK2Up/xQP6bDAsQaB5oPCyIrUxup5AzmwKI+m5j99hd45vcqP9Jjoe5lybltxgW5jPNmyvLidNinzHg80R6rCJTAiZdY6gQTVSJlSqIWhjzRwmwRBkCabhSeg4jrgdAmvlJrgNmc36pR6Fr8c6Vha/1n8GsA1own8qNwtfTBfMv/9sh2yX17+/CiLPPk46lkG8CYUX5ILoxy6+gzq7cFKMKi/3ms/4woeomux44HGhBCuUaDrgQpO8IwO1HjITTVg5qUJS0mwAZW6lzp2oYGznfpmyeDbXGHbdJgacx3U4e7+MGew2wts4hBZkgWsfRMZguCSg4zhAXTjwHgsmTcMfcp0JnfA8SoHb4kyiryxYH2d5wn8aHsfetl9vQxOXDCCH8yXrwPIxJJ92CkAqdtQbtsELSM5GGueKEGCoo2k6IUKUSx14y/zazNVw/U+b+7UzG69FKdAM+/TlVJ1UvvDwmOUYlIxIJccJbuETfQqqEnir02/G3XJ1Igebbeb8sur4OcfUtSIwS6fO5tyNWicdZtRw+wXM1eo6rE33F66kFq1jAMLuZFLleXImZLGBLDo/AUBsqNtg54VhtYGtaLTycpU4ZtTww3N/uLbuOnY8peZl8OaRbjV4R7Amn/pf9x5WiA1VseCbLxF8PCXcLySr8dk/KwW+OtOBE1/zrHRJCvWC+9JIvw61kkWx/0oTATpVsBrNa/pFwGRDMuG93ws5KF4hCO2gYSrx9ImuRu0czbA5auEoWp1J0rgplXgFmnQD9QYma6Onz0a7mrJC3rfLfBrzfM5aYUzcxCasTnc23Cqivduy17jaLM8nrilTzF+bdXX3eP8eGB3cQluzzlFYvdN8P0viWQp/bdj3Qnx0WQ4+maXwJNyCG9woCk0YPmwdAOWAc0+B8/MLEAJiTLL/cafLz79OZQybL7dHv6WOzypIkV38StK0R4+a14jGbzd7AwzVw2CFaHu/Wv8NYHuhnn8VMwt/Rs/mKXAg/u+t3mDIS5XnT54vzw61nscQ76bGaP8+L+PkmrX1g005snPUO5oeHXrSc+GFShMFs6oQp/oifoxAmHgsZbfwrpzGY8uk6bmOtU+n2uAP2uAmr8wKKrPHuaDyUyc2XeJBdtHh+KQhSOYmesBSB32Q94rAQeQ1csOG0tk8+Vyd9mD5Hw77qj8MmGQifPGpWymWawPVdMmlBzF5PNwgBNVIo0i5FFXAXUNrEBtByq5vRbrnBa3GVdPrLdp+ykRtBqP+PY0iglkOmls6ANVsssWsgYWYs9w4AR0ZCES7Xqgnkwd6e80vjhOv7GczG/OSR1u55SMuPTLZWxktBSLdx2nmVNHxJPoSdWg48us7tZI1/9HCyTKqiUUbSwKePHAcQvKF0yyKt1F8Pn22wXp8m/2L6TMXobHx5O2qpG6P2eQOzu4cdZEKiJLQujlwZBHWyqMGjTdaIw7SRcEF++FwDh4r/Vuf95zPk3M9dvT/Vu2OeEffmdpcf7U3qokxDXXTI0znc9e0xVv5f1tOsui7D6Vti1bYDo68ucQzJ1OYCTZoCIcANmEuY6jWbZJqP0iBPvJXEoFdjiCloqtM8XQ5TfUAHIGCsEk1R5uVCVNHu4zJ74OpHo1IQqc/sxkbUUkiL+fkbeCjW1E7uZYVT/+zpTX3lQepETqF3Y/DhPoJM7kjx5Kdg868BPJ9tiOPqDfSkc3ZFQZW53JLIWm5R+PyN3hJraid3MMKr/bbzE0hOoXTjjlZURSPLkjmDzrAM/nWzLzbuzNP07K5PDQxtcSV33KfVmX++p/KVZuVZ4Ri7KbHknnkvgq/7h4lB8MexMCSRqr3Y/z3PLbgrGfK34EHOtCFuDiOvYPRi1dbXofhV9w2LbnsvT7sXsgFr/rZaRcNreDRZ3DM17b+UVzw1VD6qqBsu7bf5sz66SvChfxmX8MS70c7661i0rgRxTP/2jKUVzed3uHtlT/NtP+49Z1fPxx1RrQPNCMrdXX49ZXqcov0/qKzEaO6Uc4qeQWBjWLexPKbuLi08AP7kYYidTWLj9dWIntn/1FCfpRVnGu8dmrQFYFaSDzQuSWgQZEm5pvIciiN1QSlfVrKBVLTtouPK7XXYCjSkXg5CRKCzc2hP7d6x8zCD7KeUQP4XExtCaNEGXwVoFFMtay1VSimhEWajMcZZGRvYRkxQYwIYicMT0pRYOl3HJHniIjMZhKII4DKU2EyW78pRDfrUvAU3UFdJ6wMBFITD0R9QSRe9i/owfuX/qV4+TnCGOFaQy9ZpEaBNBekVC5y0Vg0wlCpq1DajRKEz27qjIBm8rvosPp/uY95XBE8lUJjlESrIsFiHs3GUK20BV11r6eFUpwGGrEhHZGviZGVk59LdINQZ9CdR+X2hToB5QsH/rSkDxu0LbVK59uxr9MqsE4HROobHxLKthU0H3c7VmgMa8Ug5ylEksDIeTO43XUASxGUotHIZIPo3DUARxGEptHOpQNnZb5nxzp2ieIwO4gWQgZ5DSIsVw6KBxHoogbnWp3TsKO4S6UxQKQV8olBP4IBzwtsmupklMgLqbptjkchoKmw4sf0qKolq+dvuXuj4aCaibRmVdblbT2kOcXpzKx3qJ3Tzeh0phJocXo6YaFun4JWVksAtlEF9eXESkAc9p77JjssP4tIUGRi0FhRPGxNh+S0Fp/3WenY4Yk7bQwKmlsHBqr2toTNrfofbbIuI09n19sbSPmUfnsTKZaSIrU1qkeJ3cV9PGfG+RAiaDpIApiVIYOJu50boR+QgIZWh3khamnPKPrIQ8qVCGMmmKLUxu2JdK4essOZQF3mEgFcQYJCTMv5Bl11CEzblIC6yOEOkxudjEidRvN6xaDhzqBSADXbBSDptRIrGqpzxZD6moksBqqlS0tRz24i+2qsPoTes75Pll6krP/JCybi8jOWg7Y41R0pHlcpGI2qf89VKsA3mhobd4OY2P8ck2jL+xkkEuY71x8tKFtOxbKU8Que6nEASiSeKMFORRHqpZWnKHXmtrWKQTUudroghlEF+h2LqOz8Ady/Z3eN2eEfZEh9SmwCqqK4JXUF0pRfQeZLAGfTGqCBWld1V9xjvyI7g0VMrBXpFJbBseWAJEff8DowS3QzBih53GO/Z0TGNwpMJktp3HgZJ4VGCQQCcxHR2QOXcfBpyxRmH6vlDZvmYHVg1kk3PUScClgUZl2xMdUiPqu6JDGbgvOhRbmLzPcSZCGcREKLZpMqT20zUZykBNhmLb+GBxUUH5A0seHqFJs1IOjgiZhMbwZVLN6wvYMegkBrYCFWW3weKTABrD3oOTJ1KTagEDUSYw7RMppNYxISTFAUaFUAqPC4GAzqrJMWVi11BYWDZEVgf7dIyTB6hLhyLYoXalVtxyW5u+ISoFjFqFiLDr/ZaVJcstyMUIsR1xiNZmZD37jm5tnQY0u07myhyb7mKEJDFoU1w0Vwaw54BQwrsPCLGjOAQ5aALQTobkxA3wsZBMg54JyWRWtesRtMfjSFQCWGWZxobCPCuKqvEU56qTgMjTqKymhnw36rMpvrr6V4ksQroScP3RFdqWHvFXQ7CDVAouO0QCGyvkNMRwEEI7Ael24w2K6CSmbf3o4nhME7a/y1r6hNkPJ7vKOOg0CpoMLbldAvmYHQ8MQOjsJ/c3rKhcMA9jJgQmtKeVePyDRmE69GyJCB2hHlhazl3N5JQT0agmJW9J9REqtONg+rGwlDffdYeMsrFJ3N+MBjpXKYA8C5gwAKlBJoCaEBPS31vUt0XEUiwypCcgTB9xVlIpNlGkstJvNen21UiwiAeZyqWHbd1K6EuNoRCwj4S+R3JYuVABCoSXqdWbBcKbSUCweyWAOYhdagGMz+dNmMPun8kqE8wBxrVHV7xx3RwGalwZNQie64EFuEs1jXH8vBlaWP4ks0Ry2LrRKDKtoX+BUPqmew0h8phpMIMEQ4fEgwoSsZJXtVaCGDnoOuqDr3X7IJS4UkqkN1cDCRaX64GB4k11pci7+t2E1q4+fJMMumuny78a9fuwbkO/azT+e1xd7/CK6HLMXU3Tcii6bQNCdc0p1QzfD+VKSPP9QK57gDVBs+iFYc1zF+cPDBwRlGqe+nxl5ukWsk7YUSuFRA7ke7SykIZxQY1ayb9LXcgswC2hwmgSsEJInADXoaRGTPebRn9sI/kiE/qplekMygAXqxotDBemxuJqvNr9d3RwTajqOm0IR4rcERPV9+hGVdXscy2NNNhkayYTSLfXDFMukM7/tAu6F8crG++7je555e6eyAKFAF7Hs1oQKtCGwPIgZrIPEpA82ECZ2STyrn3Ubduzdq/fPH2nVzbsiYG3BptdMeNdQEMrynkG0Bh2pzGIAfGpGr2y4esEKIuotxaTiTcuo75dwDwgYQBTQLdIGxMYL4e6q94eTZmUVkn8q6scs/F62B3i8SoqpsMVlQm999KMqvfHa/0JpMF54sSGHleuoDddjlwvB2tCBtDKQhgCd4I4sZd+XIMZXiRpWjnSvmWDERTScCYgYWiC0l16vaFpXGuNNuQQUNJGSA1guSDczQDdiR/e9gFsYa6Aq6XmC+D6YLkA5JqGPABNK5R7/e6m6VIhGM2hE4UwgZrOgddEUzW4q9plMjCqqhOFUFXNt8BrDj9OX1xlaWpUUyYIoaKYjKFZM0HJFsap1uSDiJoWYeVEkolCajXkXBZ9PSRLxQgV1UAlMULINI2hVTQohySfaFS0JJQwtgRFTYGtGpNleDclPhGiVbR/4DSFTQqu0oRgnBppMu2IPg+zCZvR5zENYXo9O5qWMpEp6YtxOkqrGAJNlEQ4t02Yl0NCG3fT9WltjHYCqEIYRcu/w6sKv/pRl0eO2/VVyIIpLMW+DxrD8e0jVY7EZDyIviKNRWQp5c8gMpjKR6+tV/Tbs22Txm5taCYLukxv8pEoNmsasQKdR9FnHrc8Lw9hVwWk87+lImWj4rXgZFNjFTX5JoUihFsKpx6UHCsa4ivwQA64giGCYXIgB5SKS2rFmFrLk2lauxPtAj4P796vqzBHn+4Lt4FK4ldxLVXZUM/TBsogv+FMWifyfxIdXtUuQVx0Xa3PHuOC7T8k5aPAQVfcVsWbOlJdNQUer4qmtxtvCGncDu3jZoAreFIErImOeFJuQU+meS/2O9k+ci2/fmEp8/SpCS0OUSAJ4BDFtIpDPTBjoruKQBJE41TISB9iYmRI+sgboWRx9GMW67iwV/KLjmVM0+WXxMeEQuFXaTUD520XReMpvFdMnxkN7eJayoSeBAdrat9XY6rPsQuhLiLJuuRTCbe05pOSllocHkgZxtUByVjbkWzKsTphg5vQ2Sit//4OHTah5oyNxKd3oBGOk1tXBPoDQeLaAH/zRxn5cLbcdvRbMuB6MJBpZODEIQbH4qYwLBhRWv/rxrnNYMyCTAjstlT0byBSmmexNWLq4REIMmRZRlJEg+Aa0YwBP3a70AxCaFXOWG1oG8k87RutZuauEDa2NrOpVjoC9Aw0xigXnDqYm9Dz7IgtiKVBjGGIU8GprUoh2gBqrMMkhkzn1FuW5CYMu+6+LmASssSLFnXJ8x7ExPaPOKV2sCG6NXPKbwGPsqnUBG4g6NlibgrTc8RbNfEImM6PTYq1wpvIOJ0k17Uqb9SaNm9cpRl5PtsIZUs2qbmdWYxCaVfKCWxqHM7zO34iRHSUs3vDsAkUotv46ZiyIQUbrrhCaZi6jE7yFlbl/m0SKS4WUhmhtG8kjY+c1d5c4dXx51SmqG/4dulE/r9W4VXVtjXbvVL7RxutEuyjPXZn1otZnAxy1qbovytXSVrWEYTGvXiX6vPszdskMjetEXu48Z/xjH7JU5x/e/V19xgfHthNXE3P+1eWgM1FayWTC5affWrdL/ykk7wHJr5E1Wx2gQ9NTTQC/4OsvUy9LbWRl56MxzfWOiFOcSwvXfGGqM9W+TOTwSnbqvh3zcuaqH/PyTplQyhDTtm0d6qak2X0CaoR6nePQEWGE3GdyP9RuPaQVVMTfaNq5LUGsrcwUIfwE+i7U7f9NQfPwJefh4qu8uzJZA8TeQiDwC9htU7F+LDVZFPcZQ6GEIi3bgbhPa1Ie1sL8oc4ucmlgW9/tY7N+KAX1g7WhmeTmEAB0oXAwzxqw09eRcCDXED4FLWuwTzYG2KNnWzPgpnb0rf/iA98jQm6k5/Kit4ckjKJU0NArakCruS4YFr4QbDbJv7O8sjXdGN0AcM6K7td0LqB1DW2BEci015pG5kCSHwCzZ7/B6bGFZyY/Ad66q1pwvp62xhzmB1zcIesOmI/DrhdN2nPBkX1d/EyOxRlHif1YyjVNKzXr0t4dZdFWH3DTpN/XnZzj8iaBS050WebxDWo/Qkmj90kFTgZXa5JVB3Xd9XmEx6pooJNetcK2L2Y1mJ4xALPejUbHIb3uqYZdkg8ZjZXT2cWnpzYbAG1hZfIqL0vPV6mG2hii+HxBLzdxtswPco2zbBDdjezuXo6s/Dk7HELqK0+Mkf+ImqP0wEfAF9tz/CVRR7taz4Ptof4PJhdTEpHsKRAblbKKf/dsiYRP8KjJmbWSci4Vmee49EnOpONbD+4VgiDHVp7VP35s6aR2vBVL7O8L3v+rHnysv2h+rNasFbrvXfZnqUF//X5s5tTVfuJNX+9ZEXyMDTxvGrzwPjjvEOjHc2bw33WrfoUiTqSrrh7dIOV8T4u44u8TOqnCariXTXr5I+58v2Z+vnCj2z/5vDnqTyeykpl9vQxldaUz5+Z+T9/psn8vLlvUPhQoRIzqVRgfx5enJJ038t9FaeFso7GmrisrP+aVb83fVkNzZI9fOtb+iM7EBtqzfeSHdlhXw25O/Z0rB81L/483Maf2RjZ3hfsLXuId9+u6yTpfLsJa8TeEbLZn79M4oc8firaNob61Z8VhvdPX//n37Bg1GSfaQgA + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index b39ffa09d7..bbd83bec0a 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -121,7 +121,7 @@ - + @@ -332,9 +332,9 @@ 201507250039446_Merge2.cs - - - 201508011828241_ExportFramework.cs + + + 201508040836122_ExportFramework.cs @@ -633,8 +633,8 @@ 201507250039446_Merge2.cs - - 201508011828241_ExportFramework.cs + + 201508040836122_ExportFramework.cs diff --git a/src/Libraries/SmartStore.Services/DataExchange/ExportExtensions.cs b/src/Libraries/SmartStore.Services/DataExchange/ExportExtensions.cs new file mode 100644 index 0000000000..3c0c8472f9 --- /dev/null +++ b/src/Libraries/SmartStore.Services/DataExchange/ExportExtensions.cs @@ -0,0 +1,15 @@ +using SmartStore.Core.Plugins; + +namespace SmartStore.Services.DataExchange +{ + public static class ExportExtensions + { + public static bool IsValid(this Provider provider) + { + return ( + provider != null && + provider.Value.FileType.HasValue() + ); + } + } +} diff --git a/src/Libraries/SmartStore.Services/Export/ExportService.cs b/src/Libraries/SmartStore.Services/DataExchange/ExportService.cs similarity index 90% rename from src/Libraries/SmartStore.Services/Export/ExportService.cs rename to src/Libraries/SmartStore.Services/DataExchange/ExportService.cs index 14be36fc7e..2b8a2f2ba1 100644 --- a/src/Libraries/SmartStore.Services/Export/ExportService.cs +++ b/src/Libraries/SmartStore.Services/DataExchange/ExportService.cs @@ -7,8 +7,9 @@ using SmartStore.Core.Events; using SmartStore.Core.Plugins; using SmartStore.Services.Tasks; +using SmartStore.Utilities; -namespace SmartStore.Services.Export +namespace SmartStore.Services.DataExchange { public partial class ExportService : IExportService { @@ -38,14 +39,15 @@ public virtual ExportProfile InsertExportProfile(Provider provi if (provider == null) throw new ArgumentNullException("provider"); - var guid = Guid.NewGuid(); var name = provider.Metadata.FriendlyName; var systemName = provider.Metadata.SystemName; - var taskType = "SmartStore.Services.ExportImport.{0}Task.{1}, SmartStore.Services".FormatInvariant(systemName, guid.ToString().Replace("-", "")); if (name.IsEmpty()) name = systemName; + var folderName = SeoHelper.GetSeName(name, true, false).ToValidPath(); + var taskType = "SmartStore.Services.DataExchange.{0}Task.{1}, SmartStore.Services".FormatInvariant(systemName, CommonHelper.GenerateRandomDigitCode(10)); + var task = new ScheduleTask { Name = string.Concat(name, " Export Task"), @@ -61,11 +63,10 @@ public virtual ExportProfile InsertExportProfile(Provider provi var profile = new ExportProfile { Name = name, + FolderName = folderName, Enabled = true, ProviderSystemName = systemName, - ProfileGuid = guid, - SchedulingTaskId = task.Id, - FileType = provider.Value.SupportedFileTypes.FirstOrDefault() + SchedulingTaskId = task.Id }; _exportProfileRepository.Insert(profile); diff --git a/src/Libraries/SmartStore.Services/Export/IExportProvider.cs b/src/Libraries/SmartStore.Services/DataExchange/IExportProvider.cs similarity index 55% rename from src/Libraries/SmartStore.Services/Export/IExportProvider.cs rename to src/Libraries/SmartStore.Services/DataExchange/IExportProvider.cs index 752f6096ed..318c0e2586 100644 --- a/src/Libraries/SmartStore.Services/Export/IExportProvider.cs +++ b/src/Libraries/SmartStore.Services/DataExchange/IExportProvider.cs @@ -1,16 +1,17 @@ using System.IO; using SmartStore.Core.Domain; -using SmartStore.Core.Domain.Export; +using SmartStore.Core.Domain.DataExchange; using SmartStore.Core.Plugins; -namespace SmartStore.Services.Export +namespace SmartStore.Services.DataExchange { public partial interface IExportProvider : IProvider, IUserEditable { + // TODO: a more complex result type is required. e.g. IEnumerable.... MemoryStream Execute(ExportProfile profile); - ExportFileType[] SupportedFileTypes { get; } - ExportEntityType EntityType { get; } + + string FileType { get; } } } diff --git a/src/Libraries/SmartStore.Services/Export/IExportService.cs b/src/Libraries/SmartStore.Services/DataExchange/IExportService.cs similarity index 97% rename from src/Libraries/SmartStore.Services/Export/IExportService.cs rename to src/Libraries/SmartStore.Services/DataExchange/IExportService.cs index 3e8e2e60df..bc6ca8b092 100644 --- a/src/Libraries/SmartStore.Services/Export/IExportService.cs +++ b/src/Libraries/SmartStore.Services/DataExchange/IExportService.cs @@ -3,7 +3,7 @@ using SmartStore.Core.Domain; using SmartStore.Core.Plugins; -namespace SmartStore.Services.Export +namespace SmartStore.Services.DataExchange { public interface IExportService { diff --git a/src/Libraries/SmartStore.Services/Export/ExportExtensions.cs b/src/Libraries/SmartStore.Services/Export/ExportExtensions.cs deleted file mode 100644 index 3ea12ec406..0000000000 --- a/src/Libraries/SmartStore.Services/Export/ExportExtensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Linq; -using SmartStore.Core.Plugins; - -namespace SmartStore.Services.Export -{ - public static class ExportExtensions - { - public static bool IsValid(this Provider provider) - { - return ( - provider != null && - provider.Value.SupportedFileTypes != null && provider.Value.SupportedFileTypes.Any() - ); - } - } -} diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index db5a654dd3..cf282b9d21 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -160,12 +160,12 @@ + - - - - + + + diff --git a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs index e361097cc9..b003f82cef 100644 --- a/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs +++ b/src/Presentation/SmartStore.Web.Framework/DependencyRegistrar.cs @@ -41,7 +41,7 @@ using SmartStore.Services.Directory; using SmartStore.Services.Discounts; using SmartStore.Services.Events; -using SmartStore.Services.Export; +using SmartStore.Services.DataExchange; using SmartStore.Services.ExportImport; using SmartStore.Services.Filter; using SmartStore.Services.Forums; diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs index cd8bf2190a..510772fdb3 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs @@ -1,16 +1,18 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Web.Mvc; -using SmartStore.Admin.Models.Export; +using SmartStore.Admin.Models.DataExchange; using SmartStore.Core; using SmartStore.Core.Domain; -using SmartStore.Core.Domain.Export; +using SmartStore.Core.Domain.Catalog; +using SmartStore.Core.Domain.DataExchange; using SmartStore.Core.Plugins; using SmartStore.Services; -using SmartStore.Services.Export; +using SmartStore.Services.Catalog; +using SmartStore.Services.DataExchange; using SmartStore.Services.Media; using SmartStore.Services.Security; +using SmartStore.Web.Framework; using SmartStore.Web.Framework.Controllers; using SmartStore.Web.Framework.Plugins; using Telerik.Web.Mvc; @@ -24,60 +26,108 @@ public class ExportController : AdminControllerBase private readonly IExportService _exportService; private readonly PluginMediator _pluginMediator; private readonly IPictureService _pictureService; + private readonly ICategoryService _categoryService; public ExportController( ICommonServices services, IExportService exportService, PluginMediator pluginMediator, - IPictureService pictureService) + IPictureService pictureService, + ICategoryService categoryService) { _services = services; _exportService = exportService; _pluginMediator = pluginMediator; _pictureService = pictureService; + _categoryService = categoryService; } private void PrepareExportProfileModel(ExportProfileModel model, ExportProfile profile, Provider provider) { - var partition = XmlHelper.Deserialize(profile.Partitioning); - - model.AvailableFileTypes = new List(); + model.Providing = new ExportProfileModel.Provider + { + SystemName = profile.ProviderSystemName + }; model.Id = profile.Id; model.Name = profile.Name; - model.ProviderSystemName = profile.ProviderSystemName; model.Enabled = profile.Enabled; - model.FileType = profile.FileType; - model.FileTypeName = profile.FileType.ToString().ToUpper(); model.SchedulingHours = profile.ScheduleTask.Seconds / 3600; - model.Offset = partition.Offset; - model.Limit = partition.Limit; - model.BatchSize = partition.BatchSize; - model.PerStore = partition.PerStore; - if (provider != null) { - model.ThumbnailUrl = _pluginMediator.GetIconUrl(provider.Metadata); + model.Providing.ThumbnailUrl = _pluginMediator.GetIconUrl(provider.Metadata); - if (model.ThumbnailUrl.IsEmpty()) - model.ThumbnailUrl = _pictureService.GetDefaultPictureUrl(48); + if (model.Providing.ThumbnailUrl.IsEmpty()) + model.Providing.ThumbnailUrl = _pictureService.GetDefaultPictureUrl(48); else - model.ThumbnailUrl = Url.Content(model.ThumbnailUrl); + model.Providing.ThumbnailUrl = Url.Content(model.Providing.ThumbnailUrl); + + model.Providing.Url = provider.Metadata.PluginDescriptor.Url; + model.Providing.ConfigurationUrl = Url.Action("ConfigurePlugin", new { systemName = provider.Metadata.SystemName }); + model.Providing.FriendlyName = _pluginMediator.GetLocalizedFriendlyName(provider.Metadata); + model.Providing.Author = provider.Metadata.PluginDescriptor.Author; + model.Providing.Version = provider.Metadata.PluginDescriptor.Version.ToString(); + model.Providing.Description = _pluginMediator.GetLocalizedDescription(provider.Metadata); + + model.Providing.EntityType = provider.Value.EntityType; + model.Providing.EntityTypeName = T("Enums.SmartStore.Core.Domain.ExportEntityType." + provider.Value.EntityType.ToString()); + model.Providing.FileType = provider.Value.FileType.ToUpper(); + } + } - model.ProviderFriendlyName = _pluginMediator.GetLocalizedFriendlyName(provider.Metadata); + private void PrepareExportProfileModelForEdit(ExportProfileModel model, ExportProfile profile, Provider provider) + { + var filter = XmlHelper.Deserialize(profile.Filtering); - model.EntityType = T("Enums.SmartStore.Core.Domain.ExportEntityType." + provider.Value.EntityType.ToString()); + var allStores = _services.StoreService.GetAllStores(); + var allCategories = _categoryService.GetAllCategories(showHidden: true); + var mappedCategories = allCategories.ToDictionary(x => x.Id); - foreach (var fileType in provider.Value.SupportedFileTypes) - { - model.AvailableFileTypes.Add(new SelectListItem - { - Text = T("Enums.SmartStore.Core.Domain.ExportFileType." + fileType.ToString()), - Value = ((int)fileType).ToString() - }); - } - } + var yes = T("Admin.Common.Yes").Text; + var no = T("Admin.Common.No").Text; + + model.StoreCount = allStores.Count; + model.AllString = T("Admin.Common.All"); + model.UnspecifiedString = T("Common.Unspecified"); + model.Offset = profile.Offset; + model.Limit = profile.Limit; + model.BatchSize = profile.BatchSize; + model.PerStore = profile.PerStore; + + model.Filtering = new ExportProfileModel.Filter + { + StoreId = filter.StoreId, + CreatedFrom = filter.CreatedFrom, + CreatedTo = filter.CreatedTo, + PriceMinimum = filter.PriceMinimum, + PriceMaximum = filter.PriceMaximum, + AvailabilityMinimum = filter.AvailabilityMinimum, + AvailabilityMaximum = filter.AvailabilityMaximum, + IsPublished = filter.IsPublished, + CategoryIds = filter.CategoryIds, + WithoutCategories = filter.WithoutCategories, + ManufacturerIds = filter.ManufacturerIds, + WithoutManufacturers = filter.WithoutManufacturers, + ProductTagIds = filter.ProductTagIds, + IncludeFeaturedProducts = filter.IncludeFeaturedProducts, + OnlyFeaturedProducts = filter.OnlyFeaturedProducts, + ProductType = filter.ProductType, + OrderStatus = filter.OrderStatus, + PaymentStatus = filter.PaymentStatus, + ShippingStatus = filter.ShippingStatus, + CustomerRoleIds = filter.CustomerRoleIds + }; + + model.Filtering.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList(); + + model.Filtering.AvailableStores = allStores + .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }) + .ToList(); + + model.Filtering.AvailableCategories = allCategories + .Select(x => new SelectListItem { Text = x.GetCategoryNameWithPrefix(_categoryService, mappedCategories), Value = x.Id.ToString() }) + .ToList(); } public ActionResult Index() @@ -123,8 +173,9 @@ public ActionResult Create() if (_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) { var model = new ExportProfileModel(); + model.Providing = new ExportProfileModel.Provider(); - model.AvailableExportProviders = _exportService.LoadAllExportProviders() + model.Providing.AvailableExportProviders = _exportService.LoadAllExportProviders() .Select(x => { var item = new SelectListItem @@ -148,20 +199,18 @@ public ActionResult Create(ExportProfileModel model) if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) return AccessDeniedView(); - if (model.ProviderSystemName.HasValue()) + if (model.Providing.SystemName.HasValue()) { - var provider = _exportService.LoadProvider(model.ProviderSystemName); + var provider = _exportService.LoadProvider(model.Providing.SystemName); if (provider != null) { var profile = _exportService.InsertExportProfile(provider); - PrepareExportProfileModel(model, profile, provider); - return RedirectToAction("Edit", new { id = profile.Id }); } } - NotifyError(T("Admin.Configuration.Export.ProviderSystemName.Validate", model.ProviderSystemName.NaIfEmpty())); + NotifyError(T("Admin.Configuration.Export.ProviderSystemName.Validate", model.Providing.SystemName.NaIfEmpty())); return RedirectToAction("List"); } @@ -180,6 +229,7 @@ public ActionResult Edit(int id) var model = new ExportProfileModel(); PrepareExportProfileModel(model, profile, provider); + PrepareExportProfileModelForEdit(model, profile, provider); return View(model); } @@ -195,32 +245,60 @@ public ActionResult Edit(ExportProfileModel model, bool continueEditing) if (profile == null) return RedirectToAction("List"); - if (ModelState.IsValid) - { - var partition = new ExportPartition - { - Offset = model.Offset, - Limit = model.Limit, - BatchSize = model.BatchSize, - PerStore = model.PerStore - }; - - profile.Name = model.Name; - profile.Enabled = model.Enabled; - profile.ScheduleTask.Seconds = model.SchedulingHours * 3600; - profile.FileType = model.FileType; - profile.Partitioning = XmlHelper.Serialize(partition); - - _exportService.UpdateExportProfile(profile); - - NotifySuccess(T("Admin.Common.DataSuccessfullySaved")); + var provider = _exportService.LoadProvider(profile.ProviderSystemName); - return (continueEditing ? RedirectToAction("Edit", new { id = profile.Id }) : RedirectToAction("List")); + if (!ModelState.IsValid) + { + PrepareExportProfileModel(model, profile, provider); + PrepareExportProfileModelForEdit(model, profile, provider); + return View(model); } - PrepareExportProfileModel(model, profile, _exportService.LoadProvider(model.ProviderSystemName)); - - return View(model); + var filter = new ExportFilter + { + StoreId = model.Filtering.StoreId ?? 0, + CreatedFrom = model.Filtering.CreatedFrom, + CreatedTo = model.Filtering.CreatedTo, + PriceMinimum = model.Filtering.PriceMinimum, + PriceMaximum = model.Filtering.PriceMaximum, + AvailabilityMinimum = model.Filtering.AvailabilityMinimum, + AvailabilityMaximum = model.Filtering.AvailabilityMaximum, + IsPublished = model.Filtering.IsPublished, + CategoryIds = model.Filtering.CategoryIds, + WithoutCategories = model.Filtering.WithoutCategories, + ManufacturerIds = model.Filtering.ManufacturerIds, + WithoutManufacturers = model.Filtering.WithoutManufacturers, + ProductTagIds = model.Filtering.ProductTagIds, + IncludeFeaturedProducts = model.Filtering.IncludeFeaturedProducts, + OnlyFeaturedProducts = model.Filtering.OnlyFeaturedProducts, + ProductType = model.Filtering.ProductType, + OrderStatus = model.Filtering.OrderStatus, + PaymentStatus = model.Filtering.PaymentStatus, + ShippingStatus = model.Filtering.ShippingStatus, + CustomerRoleIds = model.Filtering.CustomerRoleIds + }; + + profile.Name = model.Name; + profile.Enabled = model.Enabled; + profile.ScheduleTask.Seconds = model.SchedulingHours * 3600; + profile.Offset = model.Offset; + profile.Limit = model.Limit; + profile.BatchSize = model.BatchSize; + profile.PerStore = model.PerStore; + + if (profile.Name.IsEmpty()) + profile.Name = provider.Metadata.FriendlyName; + + if (profile.Name.IsEmpty()) + profile.Name = provider.Metadata.SystemName; + + profile.Filtering = XmlHelper.Serialize(filter); + + _exportService.UpdateExportProfile(profile); + + NotifySuccess(T("Admin.Common.DataSuccessfullySaved")); + + return (continueEditing ? RedirectToAction("Edit", new { id = profile.Id }) : RedirectToAction("List")); } [HttpPost, ActionName("Delete")] @@ -248,5 +326,10 @@ public ActionResult DeleteConfirmed(int id) return RedirectToAction("Edit", new { id = profile.Id }); } + + public ActionResult Execute(int id) + { + return null; + } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs new file mode 100644 index 0000000000..ca98c7ab9b --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Web.Mvc; +using SmartStore.Core.Domain.Catalog; +using SmartStore.Core.Domain.DataExchange; +using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Domain.Payments; +using SmartStore.Core.Domain.Shipping; +using SmartStore.Web.Framework; +using SmartStore.Web.Framework.Mvc; + +namespace SmartStore.Admin.Models.DataExchange +{ + public partial class ExportProfileModel : EntityModelBase + { + [SmartResourceDisplayName("Admin.Configuration.Export.Name")] + public string Name { get; set; } + + [SmartResourceDisplayName("Common.Enabled")] + public bool Enabled { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.SchedulingHours")] + public int SchedulingHours { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.LastExecution")] + [AllowHtml] + public string LastExecution { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Offset")] + public int Offset { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Limit")] + public int Limit { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.BatchSize")] + public int BatchSize { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.PerStore")] + public bool PerStore { get; set; } + + public Provider Providing { get; set; } + public Filter Filtering { get; set; } + + public int StoreCount { get; set; } + public string AllString { get; set; } + public string UnspecifiedString { get; set; } + + + public class Provider + { + [SmartResourceDisplayName("Common.Image")] + public string ThumbnailUrl { get; set; } + + [SmartResourceDisplayName("Common.Website")] + public string Url { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Plugins.Fields.Configure")] + public string ConfigurationUrl { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.ProviderSystemName")] + public string SystemName { get; set; } + public List AvailableExportProviders { get; set; } + + [SmartResourceDisplayName("Common.Provider")] + public string FriendlyName { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Plugins.Fields.Author")] + public string Author { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Plugins.Fields.Version")] + public string Version { get; set; } + + [SmartResourceDisplayName("Common.Description")] + [AllowHtml] + public string Description { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.EntityType")] + public ExportEntityType EntityType { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.EntityType")] + public string EntityTypeName { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.FileType")] + public string FileType { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.SupportedFileTypes")] + public string SupportedFileTypes { get; set; } + } + + + public class Filter + { + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.StoreId")] + public int? StoreId { get; set; } + public List AvailableStores { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.IsPublished")] + public bool? IsPublished { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ProductType")] + public ProductType? ProductType { get; set; } + public List AvailableProductTypes { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CreatedFrom")] + public DateTime? CreatedFrom { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CreatedTo")] + public DateTime? CreatedTo { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.PriceMinimum")] + public decimal? PriceMinimum { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.PriceMaximum")] + public decimal? PriceMaximum { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.AvailabilityMinimum")] + public int? AvailabilityMinimum { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.AvailabilityMaximum")] + public int? AvailabilityMaximum { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CategoryIds")] + public int[] CategoryIds { get; set; } + public List AvailableCategories { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.WithoutCategories")] + public bool? WithoutCategories { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ManufacturerIds")] + public int[] ManufacturerIds { get; set; } + public List AvailableManufacturers { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.WithoutManufacturers")] + public bool? WithoutManufacturers { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ProductTagIds")] + public int? ProductTagIds { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.IncludeFeaturedProducts")] + public bool? IncludeFeaturedProducts { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.OnlyFeaturedProducts")] + public bool? OnlyFeaturedProducts { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.OrderStatus")] + public OrderStatus? OrderStatus { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.PaymentStatus")] + public PaymentStatus? PaymentStatus { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ShippingStatus")] + public ShippingStatus? ShippingStatus { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CustomerRoleIds")] + public int[] CustomerRoleIds { get; set; } + } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs deleted file mode 100644 index 547211434c..0000000000 --- a/src/Presentation/SmartStore.Web/Administration/Models/Export/ExportProfileModel.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Collections.Generic; -using System.Web.Mvc; -using SmartStore.Core.Domain.Export; -using SmartStore.Web.Framework; -using SmartStore.Web.Framework.Mvc; - -namespace SmartStore.Admin.Models.Export -{ - public partial class ExportProfileModel : EntityModelBase - { - [SmartResourceDisplayName("Common.Image")] - public string ThumbnailUrl { get; set; } - public string ThumbnailClasses - { - get - { - return "grid-icon"; - } - } - - [SmartResourceDisplayName("Admin.Configuration.Export.ProviderSystemName")] - public string ProviderSystemName { get; set; } - public List AvailableExportProviders { get; set; } - - [SmartResourceDisplayName("Common.Provider")] - public string ProviderFriendlyName { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.EntityType")] - public string EntityType { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.SupportedFileTypes")] - public string SupportedFileTypes { get; set; } - - - [SmartResourceDisplayName("Admin.Configuration.Export.Name")] - public string Name { get; set; } - - [SmartResourceDisplayName("Common.Enabled")] - public bool Enabled { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.FileType")] - public ExportFileType FileType { get; set; } - public List AvailableFileTypes { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.FileType")] - public string FileTypeName { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.SchedulingHours")] - public int SchedulingHours { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.LastExecution")] - [AllowHtml] - public string LastExecution { get; set; } - - - [SmartResourceDisplayName("Admin.Configuration.Export.Segmentation.Offset")] - public int Offset { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Segmentation.Limit")] - public int Limit { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Segmentation.BatchSize")] - public int BatchSize { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Segmentation.PerStore")] - public bool PerStore { get; set; } - } -} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index ef978b7e3a..0188006d32 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -248,7 +248,7 @@ - + diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml index b6f318d5b4..e8b3dc3b2d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml @@ -1,20 +1,20 @@ -@using SmartStore.Admin.Models.Export +@using SmartStore.Admin.Models.DataExchange @model ExportProfileModel @{ Layout = null; }
    - @if(Model.AvailableExportProviders.Count > 0) + @if(Model.Providing.AvailableExportProviders.Count > 0) {
    - @Html.SmartLabelFor(model => model.ProviderSystemName) + @Html.SmartLabelFor(model => model.Providing.SystemName) - @Html.DropDownListFor(model => model.ProviderSystemName, Model.AvailableExportProviders) + @Html.DropDownListFor(model => model.Providing.SystemName, Model.Providing.AvailableExportProviders)
    diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml index 1a594c0333..15e1640b40 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml @@ -1,16 +1,22 @@ @model ExportProfileModel -@using SmartStore.Core.Domain.Export; -@using SmartStore.Admin.Models.Export; +@using SmartStore.Core.Domain.DataExchange; +@using SmartStore.Admin.Models.DataExchange; @{ - var title = string.Concat(T("Admin.Common.Edit"), " ", T("Common.Profile")); + var title = string.Concat(T("Admin.Common.Edit"), " ", T("Common.Profile")); ViewBag.Title = title; } @using (Html.BeginForm()) { + @Html.HiddenFor(model => model.Id) +
    - + @if (Model.Providing.ThumbnailUrl.HasValue()) + { + + } +   @title - @Model.Name @Html.ActionLink("(" + T("Admin.Common.BackToList") + ")", "List")
    @@ -22,109 +28,323 @@
    -
    - + @Html.ValidationSummary(false) + + @Html.SmartStore().TabStrip().Name("export-profile-edit").Items(x => + { + x.Add().Text(T("Common.General").Text).Content(TabGeneral()).Selected(true); + x.Add().Text(T("Common.Filter").Text).Content(TabFilter()); + x.Add().Text(T("Common.Projection").Text).Content(TabProjection()); + x.Add().Text(T("Common.Partition").Text).Content(TabPartition()); + x.Add().Text(T("Admin.Configuration").Text).Content(TabConfiguration()); + x.Add().Text(T("Common.Publishing").Text).Content(TabDeployment()); + + EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "export-profile-edit", this.Html, this.Model)); + }) +} + +@helper TabGeneral() +{ +
    + + + + + + + + + + + + + @if (Model.Providing.Url.HasValue()) + { + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + @Html.SmartLabelFor(model => model.Providing.FriendlyName) + + @Model.Providing.FriendlyName.NaIfEmpty() + (@(Model.Providing.SystemName.NaIfEmpty())) +
    + @Html.SmartLabelFor(model => model.Providing.Author) + + @Html.DisplayFor(model => model.Providing.Author) +
    + @Html.SmartLabelFor(model => model.Providing.Version) + + @Html.DisplayFor(model => model.Providing.Version) +
    - @Html.SmartLabelFor(model => model.ProviderFriendlyName) + @Html.SmartLabelFor(model => model.Providing.Url) - @Model.ProviderFriendlyName.NaIfEmpty() (@(Model.ProviderSystemName.NaIfEmpty())) + @Model.Providing.Url
    + @Html.SmartLabelFor(model => model.Providing.EntityTypeName) + + @Html.DisplayFor(model => model.Providing.EntityTypeName) +
    + @Html.SmartLabelFor(model => model.Providing.FileType) + + @Html.DisplayFor(model => model.Providing.FileType) +
    + @Html.SmartLabelFor(model => model.Providing.Description) + + @if (Model.Providing.Description.HasValue()) + { + @Html.Raw(Model.Providing.Description) + } + else + { + @("".NaIfEmpty()) + } +
     
    + @Html.SmartLabelFor(model => model.Name) + + @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
    + @Html.SmartLabelFor(model => model.Enabled) + + @Html.EditorFor(model => model.Enabled) + @Html.ValidationMessageFor(model => model.Enabled) +
    + @Html.SmartLabelFor(model => model.SchedulingHours) + + @Html.EditorFor(model => model.SchedulingHours) + @Html.ValidationMessageFor(model => model.SchedulingHours) +
    +} + +@helper TabFilter() +{ + + @if (Model.StoreCount > 1) + { + } + + @if (Model.Providing.EntityType == ExportEntityType.Product) + { + + + + + + + + + + + + - - + + + + + + //TODO manus + //TODO product tags + } + else if (Model.Providing.EntityType == ExportEntityType.Order) + { + } +
    - @Html.SmartLabelFor(model => model.Name) + @Html.SmartLabelFor(model => model.Filtering.StoreId) - @Html.EditorFor(model => model.Name) - @Html.ValidationMessageFor(model => model.Name) + @Html.DropDownListFor(model => model.Filtering.StoreId, Model.Filtering.AvailableStores, Model.AllString) + @Html.ValidationMessageFor(model => model.Filtering.StoreId)
    - @Html.SmartLabelFor(model => model.Enabled) + @Html.SmartLabelFor(model => model.Filtering.IsPublished) - @Html.EditorFor(model => model.Enabled) - @Html.ValidationMessageFor(model => model.Enabled) + @Html.EditorFor(model => model.Filtering.IsPublished) + @Html.ValidationMessageFor(model => model.Filtering.IsPublished)
    - @Html.SmartLabelFor(model => model.EntityType) + @Html.SmartLabelFor(model => model.Filtering.ProductType) - @Html.DisplayFor(model => model.EntityType) + @Html.DropDownListFor(model => model.Filtering.ProductType, Model.Filtering.AvailableProductTypes, Model.AllString)
    - @Html.SmartLabelFor(model => model.FileType) + @Html.SmartLabelFor(model => model.Filtering.CreatedFrom) - @Html.DropDownListFor(model => model.FileType, Model.AvailableFileTypes) - @Html.ValidationMessageFor(model => model.FileType) + @Html.EditorFor(model => model.Filtering.CreatedFrom) + @Html.ValidationMessageFor(model => model.Filtering.CreatedFrom)
    - @Html.SmartLabelFor(model => model.SchedulingHours) + @Html.SmartLabelFor(model => model.Filtering.CreatedTo) - @Html.EditorFor(model => model.SchedulingHours) - @Html.ValidationMessageFor(model => model.SchedulingHours) + @Html.EditorFor(model => model.Filtering.CreatedTo) + @Html.ValidationMessageFor(model => model.Filtering.CreatedTo) +
    + @Html.SmartLabelFor(model => model.Filtering.PriceMinimum) + + @Html.EditorFor(model => model.Filtering.PriceMinimum) + @Html.ValidationMessageFor(model => model.Filtering.PriceMinimum) +
    + @Html.SmartLabelFor(model => model.Filtering.PriceMaximum) + + @Html.EditorFor(model => model.Filtering.PriceMaximum) + @Html.ValidationMessageFor(model => model.Filtering.PriceMaximum) +
    + @Html.SmartLabelFor(model => model.Filtering.AvailabilityMinimum) + + @Html.EditorFor(model => model.Filtering.AvailabilityMinimum) + @Html.ValidationMessageFor(model => model.Filtering.AvailabilityMinimum)
    -
    -
    - @T("Common.Partition") -
    -
    +
    + @Html.SmartLabelFor(model => model.Filtering.AvailabilityMaximum) + + @Html.EditorFor(model => model.Filtering.AvailabilityMaximum) + @Html.ValidationMessageFor(model => model.Filtering.AvailabilityMaximum) +
    + @Html.SmartLabelFor(model => model.Filtering.CategoryIds) + + @Html.ListBoxFor(model => model.Filtering.CategoryIds, + new MultiSelectList(Model.Filtering.AvailableCategories, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.Filtering.CategoryIds)
    - @Html.SmartLabelFor(model => model.Offset) + @Html.SmartLabelFor(model => model.Filtering.WithoutCategories) - @Html.EditorFor(model => model.Offset) - @Html.ValidationMessageFor(model => model.Offset) + @Html.EditorFor(model => model.Filtering.WithoutCategories) + @Html.ValidationMessageFor(model => model.Filtering.WithoutCategories)
    - @Html.SmartLabelFor(model => model.Limit) + @Html.SmartLabelFor(model => model.Filtering.WithoutManufacturers) - @Html.EditorFor(model => model.Limit) - @Html.ValidationMessageFor(model => model.Limit) + @Html.EditorFor(model => model.Filtering.WithoutManufacturers) + @Html.ValidationMessageFor(model => model.Filtering.WithoutManufacturers)
    - @Html.SmartLabelFor(model => model.BatchSize) + @Html.SmartLabelFor(model => model.Filtering.IncludeFeaturedProducts) - @Html.EditorFor(model => model.BatchSize) - @Html.ValidationMessageFor(model => model.BatchSize) + @Html.EditorFor(model => model.Filtering.IncludeFeaturedProducts) + @Html.ValidationMessageFor(model => model.Filtering.IncludeFeaturedProducts)
    - @Html.SmartLabelFor(model => model.PerStore) + @Html.SmartLabelFor(model => model.Filtering.OnlyFeaturedProducts) - @Html.EditorFor(model => model.PerStore) - @Html.ValidationMessageFor(model => model.PerStore) + @Html.EditorFor(model => model.Filtering.OnlyFeaturedProducts) + @Html.ValidationMessageFor(model => model.Filtering.OnlyFeaturedProducts)
    +} - -
    +@helper TabProjection() +{ +} + +@helper TabPartition() +{ + + + + + + + + + + + + + + + + + +
    + @Html.SmartLabelFor(model => model.Offset) + + @Html.EditorFor(model => model.Offset) + @Html.ValidationMessageFor(model => model.Offset) +
    + @Html.SmartLabelFor(model => model.Limit) + + @Html.EditorFor(model => model.Limit) + @Html.ValidationMessageFor(model => model.Limit) +
    + @Html.SmartLabelFor(model => model.BatchSize) + + @Html.EditorFor(model => model.BatchSize) + @Html.ValidationMessageFor(model => model.BatchSize) +
    + @Html.SmartLabelFor(model => model.PerStore) + + @Html.EditorFor(model => model.PerStore) + @Html.ValidationMessageFor(model => model.PerStore) +
    +} + +@helper TabConfiguration() +{ +} + +@helper TabDeployment() +{ } @Html.DeleteConfirmation("export-profile-delete") diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml index e559017485..a38c3a9ed5 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml @@ -1,5 +1,5 @@ -@using SmartStore.Core.Domain.Export; -@using SmartStore.Admin.Models.Export; +@using SmartStore.Core.Domain.DataExchange; +@using SmartStore.Admin.Models.DataExchange; @using Telerik.Web.Mvc.UI; @{ ViewBag.Title = T("Common.Export").Text; @@ -35,29 +35,29 @@ }) .Columns(columns => { - columns.Bound(x => x.ThumbnailUrl) + columns.Bound(x => x.Providing.ThumbnailUrl) .Width(70) .Centered() .Template( @ - @item.Id + @item.Id ) - .ClientTemplate("<#= Id #>"); + .ClientTemplate("<#= Id #>"); columns.Bound(x => x.Name) .Width(400) .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })) .ClientTemplate("\"><#= Name #>"); - columns.Bound(x => x.ProviderSystemName) - .Template(x => "{0} ({1})".FormatInvariant(x.ProviderFriendlyName, x.ProviderSystemName)) - .ClientTemplate("<#= ProviderFriendlyName #> (<#= ProviderSystemName #>)"); + columns.Bound(x => x.Providing.SystemName) + .Template(x => "{0} ({1})".FormatInvariant(x.Providing.FriendlyName, x.Providing.SystemName)) + .ClientTemplate("<#= Providing.FriendlyName #> (<#= Providing.SystemName #>)"); columns.Bound(x => x.Enabled) .Width(100) .Template(item => @Html.SymbolForBool(item.Enabled)) .ClientTemplate(@Html.SymbolForBool("Enabled")) .Centered(); - columns.Bound(x => x.EntityType); - columns.Bound(x => x.FileTypeName) + columns.Bound(x => x.Providing.EntityTypeName); + columns.Bound(x => x.Providing.FileType) .Centered(); columns.Bound(x => x.SchedulingHours) .Centered(); @@ -115,7 +115,7 @@ smallIcon: dialog.find('.modal-body'), callbackSuccess: function (resp) { dialog.find('.modal-body').html(resp); - $('#ProviderSystemName').selectWrapper(); + $('select[name="Providing.SystemName"]').selectWrapper(); }, callbackComplete: function () { showPrimaryButton(true); diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml index ea9c2f4f27..6458d88ec1 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Plugin/List.cshtml @@ -67,7 +67,7 @@ { - Website + @T("Common.Website") } @if (plugin.Author.HasValue()) From d9903ef1c91f0ee06b00dd2ffb584df3d229a97a Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 4 Aug 2015 11:33:41 +0200 Subject: [PATCH 0326/1256] Fixed merging issues with payment plugins --- .../Services/AmazonPayApi.cs | 54 +++++++++---------- .../Services/AmazonPayService.cs | 11 ++-- .../Services/IAmazonPayApi.cs | 6 +-- 3 files changed, 30 insertions(+), 41 deletions(-) diff --git a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs index a6241f8409..59e41a1e2b 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayApi.cs @@ -1,29 +1,28 @@ using System; +using System.Collections.Generic; +using System.Globalization; using System.IO; -using System.Web; using System.Linq; using System.Text; -using System.Globalization; -using System.Collections.Generic; +using System.Web; using OffAmazonPaymentsService; using OffAmazonPaymentsService.Model; -using SmartStore.Utilities; -using SmartStore.AmazonPay.Services; using SmartStore.AmazonPay.Extensions; +using SmartStore.AmazonPay.Services; using SmartStore.AmazonPay.Settings; using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Domain.Directory; +using SmartStore.Core.Domain.Discounts; using SmartStore.Core.Domain.Orders; -using SmartStore.Services.Payments; -using SmartStore.Services.Directory; -using SmartStore.Services.Orders; -using SmartStore.Services.Localization; -using SmartStore.Services.Common; -using SmartStore.Services.Helpers; using SmartStore.Core.Infrastructure; using SmartStore.Core.Plugins; -using SmartStore.Core.Domain.Directory; -using SmartStore.Core.Domain.Discounts; -using SmartStore.Core.Domain.Stores; +using SmartStore.Services; +using SmartStore.Services.Common; +using SmartStore.Services.Directory; +using SmartStore.Services.Helpers; +using SmartStore.Services.Orders; +using SmartStore.Services.Payments; +using SmartStore.Utilities; namespace SmartStore.AmazonPay.Api { @@ -32,33 +31,30 @@ public class AmazonPayApi : IAmazonPayApi private readonly ICountryService _countryService; private readonly IStateProvinceService _stateProvinceService; private readonly IOrderService _orderService; - private readonly ILocalizationService _localizationService; private readonly IAddressService _addressService; private readonly IDateTimeHelper _dateTimeHelper; - private readonly ICurrencyService _currencyService; private readonly CurrencySettings _currencySettings; private readonly IOrderTotalCalculationService _orderTotalCalculationService; + private readonly ICommonServices _services; public AmazonPayApi( ICountryService countryService, IStateProvinceService stateProvinceService, IOrderService orderService, - ILocalizationService localizationService, IAddressService addressService, IDateTimeHelper dateTimeHelper, - ICurrencyService currencyService, CurrencySettings currencySettings, - IOrderTotalCalculationService orderTotalCalculationService) + IOrderTotalCalculationService orderTotalCalculationService, + ICommonServices services) { _countryService = countryService; _stateProvinceService = stateProvinceService; _orderService = orderService; - _localizationService = localizationService; _addressService = addressService; _dateTimeHelper = dateTimeHelper; - _currencyService = currencyService; _currencySettings = currencySettings; _orderTotalCalculationService = orderTotalCalculationService; + _services = services; } private string GetRandomId(string prefix) @@ -252,7 +248,7 @@ public OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, st return null; } - public OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, string orderReferenceId, Customer customer, List cart) + public OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, string orderReferenceId, string currencyCode, List cart) { decimal orderTotalDiscountAmountBase = decimal.Zero; Discount orderTotalAppliedDiscount = null; @@ -265,8 +261,7 @@ public OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, st if (shoppingCartTotalBase.HasValue) { - var currency = (Currency)null; // TODO: Merge _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); - return SetOrderReferenceDetails(client, orderReferenceId, shoppingCartTotalBase, currency.CurrencyCode); + return SetOrderReferenceDetails(client, orderReferenceId, shoppingCartTotalBase, currencyCode); } return null; @@ -436,8 +431,7 @@ public void Capture(AmazonPayClient client, CapturePaymentRequest capture, Captu result.NewPaymentStatus = capture.Order.PaymentStatus; var request = new CaptureRequest(); - var store = (Store)null; // TODO: MERGE _storeService.GetStoreById(capture.Order.StoreId); - var currency = _currencyService.GetCurrencyById(store.PrimaryStoreCurrencyId); + var store = _services.StoreService.GetStoreById(capture.Order.StoreId); request.SellerId = client.Settings.SellerId; request.AmazonAuthorizationId = capture.Order.AuthorizationTransactionId; @@ -447,7 +441,7 @@ public void Capture(AmazonPayClient client, CapturePaymentRequest capture, Captu request.CaptureAmount = new Price { Amount = capture.Order.OrderTotal.ToString("0.00", CultureInfo.InvariantCulture), - CurrencyCode = currency.CurrencyCode + CurrencyCode = store.PrimaryStoreCurrency.CurrencyCode }; var response = client.Service.Capture(request); @@ -534,7 +528,7 @@ public string Refund(AmazonPayClient client, RefundPaymentRequest refund, Refund result.NewPaymentStatus = refund.Order.PaymentStatus; string amazonRefundId = null; - var currency = (Currency)null; // TODO: MERGE _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); + var store = _services.StoreService.GetStoreById(refund.Order.StoreId); var request = new RefundRequest(); request.SellerId = client.Settings.SellerId; @@ -545,7 +539,7 @@ public string Refund(AmazonPayClient client, RefundPaymentRequest refund, Refund request.RefundAmount = new Price { Amount = refund.AmountToRefund.ToString("0.00", CultureInfo.InvariantCulture), - CurrencyCode = currency.CurrencyCode + CurrencyCode = store.PrimaryStoreCurrency.CurrencyCode }; var response = client.Service.Refund(request); @@ -631,7 +625,7 @@ public string ToInfoString(AmazonPayApiData data) try { - string[] strings = _localizationService.GetResource("Plugins.Payments.AmazonPay.MessageStrings").SplitSafe(";"); + string[] strings = _services.Localization.GetResource("Plugins.Payments.AmazonPay.MessageStrings").SplitSafe(";"); string state = data.State.Grow(data.ReasonCode, " "); if (data.ReasonDescription.HasValue()) diff --git a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs index 722877beed..6ce88f3eb8 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/AmazonPayService.cs @@ -19,7 +19,6 @@ using SmartStore.Core.Domain.Common; using SmartStore.Core.Domain.Customers; using SmartStore.Core.Domain.Directory; -using SmartStore.Core.Domain.Discounts; using SmartStore.Core.Domain.Logging; using SmartStore.Core.Domain.Orders; using SmartStore.Core.Domain.Payments; @@ -35,7 +34,6 @@ using SmartStore.Services.Messages; using SmartStore.Services.Orders; using SmartStore.Services.Payments; -using SmartStore.Services.Stores; using SmartStore.Services.Tasks; namespace SmartStore.AmazonPay.Services @@ -51,7 +49,6 @@ public class AmazonPayService : IAmazonPayService private readonly ICurrencyService _currencyService; private readonly CurrencySettings _currencySettings; private readonly ICustomerService _customerService; - private readonly IStoreService _storeService; private readonly IPriceFormatter _priceFormatter; private readonly OrderSettings _orderSettings; private readonly RewardPointsSettings _rewardPointsSettings; @@ -71,7 +68,6 @@ public AmazonPayService( ICurrencyService currencyService, CurrencySettings currencySettings, ICustomerService customerService, - IStoreService storeService, IPriceFormatter priceFormatter, OrderSettings orderSettings, RewardPointsSettings rewardPointsSettings, @@ -90,7 +86,6 @@ public AmazonPayService( _currencyService = currencyService; _currencySettings = currencySettings; _customerService = customerService; - _storeService = storeService; _priceFormatter = priceFormatter; _orderSettings = orderSettings; _rewardPointsSettings = rewardPointsSettings; @@ -534,7 +529,7 @@ public AmazonPayViewModel ProcessPluginRequest(AmazonPayRequestType type, TempDa _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.SelectedPaymentMethod, AmazonPayCore.SystemName, store.Id); var client = new AmazonPayClient(settings); - var unused = _api.SetOrderReferenceDetails(client, model.OrderReferenceId, customer, cart); + var unused = _api.SetOrderReferenceDetails(client, model.OrderReferenceId, store.PrimaryStoreCurrency.CurrencyCode, cart); // this is ugly... var paymentRequest = _httpContext.Session["OrderPaymentInfo"] as ProcessPaymentRequest; @@ -901,7 +896,7 @@ public PreProcessPaymentResult PreProcessPayment(ProcessPaymentRequest request) try { var orderGuid = request.OrderGuid.ToString(); - var store = _storeService.GetStoreById(request.StoreId); + var store = _services.StoreService.GetStoreById(request.StoreId); var customer = _customerService.GetCustomerById(request.CustomerId); var currency = store.PrimaryStoreCurrency; var settings = _services.Settings.LoadSetting(store.Id); @@ -971,7 +966,7 @@ public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest request) try { var orderGuid = request.OrderGuid.ToString(); - var store = _storeService.GetStoreById(request.StoreId); + var store = _services.StoreService.GetStoreById(request.StoreId); var currency = store.PrimaryStoreCurrency; var settings = _services.Settings.LoadSetting(store.Id); var state = _httpContext.GetAmazonPayState(_services.Localization); diff --git a/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayApi.cs b/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayApi.cs index df245dd32f..70d72d9aa1 100644 --- a/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayApi.cs +++ b/src/Plugins/SmartStore.AmazonPay/Services/IAmazonPayApi.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; using System.Web; using OffAmazonPaymentsService.Model; -using SmartStore.Core.Domain.Customers; -using SmartStore.Core.Domain.Orders; using SmartStore.AmazonPay.Services; using SmartStore.AmazonPay.Settings; +using SmartStore.Core.Domain.Customers; +using SmartStore.Core.Domain.Orders; using SmartStore.Services.Payments; namespace SmartStore.AmazonPay.Api @@ -21,7 +21,7 @@ public partial interface IAmazonPayApi OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, string orderReferenceId, decimal? orderTotalAmount, string currencyCode, string orderGuid = null, string storeName = null); - OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, string orderReferenceId, Customer customer, List cart); + OrderReferenceDetails SetOrderReferenceDetails(AmazonPayClient client, string orderReferenceId, string currencyCode, List cart); void ConfirmOrderReference(AmazonPayClient client, string orderReferenceId); From 3cea57b1a3ddf944fc0b5356caffb41a2bd976ee Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 4 Aug 2015 12:21:41 +0200 Subject: [PATCH 0327/1256] Nullable bool input properties can surprisingly be rendered through EditorFor (DropDownListFor not necessary). --- .../Controllers/ProductController.cs | 14 -------------- .../Models/Catalog/ProductListModel.cs | 8 -------- .../Administration/Views/Product/List.cshtml | 17 ++++++++--------- 3 files changed, 8 insertions(+), 31 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs index f419909ac5..0aa775ff8f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs @@ -870,8 +870,6 @@ public ActionResult List(ProductListModel model) return AccessDeniedView(); var allStores = _storeService.GetAllStores(); - var yes = T("Admin.Common.Yes").Text; - var no = T("Admin.Common.No").Text; model.DisplayProductPictures = _adminAreaSettings.DisplayProductPictures; model.DisplayPdfExport = _pdfSettings.Enabled; @@ -897,18 +895,6 @@ public ActionResult List(ProductListModel model) model.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList(); - model.AvailableWithoutCategories.Add(new SelectListItem { Text = yes, Value = "true" }); - model.AvailableWithoutCategories.Add(new SelectListItem { Text = no, Value = "false" }); - - model.AvailableWithoutManufacturers.Add(new SelectListItem { Text = yes, Value = "true" }); - model.AvailableWithoutManufacturers.Add(new SelectListItem { Text = no, Value = "false" }); - - model.AvailableIsPublished.Add(new SelectListItem { Text = yes, Value = "true" }); - model.AvailableIsPublished.Add(new SelectListItem { Text = no, Value = "false" }); - - model.AvailableHomePageProducts.Add(new SelectListItem { Text = yes, Value = "true" }); - model.AvailableHomePageProducts.Add(new SelectListItem { Text = no, Value = "false" }); - return View(model); } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductListModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductListModel.cs index a13db2730d..912c5fe33c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductListModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductListModel.cs @@ -14,10 +14,6 @@ public ProductListModel() AvailableManufacturers = new List(); AvailableStores = new List(); AvailableProductTypes = new List(); - AvailableIsPublished = new List(); - AvailableHomePageProducts = new List(); - AvailableWithoutCategories = new List(); - AvailableWithoutManufacturers = new List(); } public GridModel Products { get; set; } @@ -62,10 +58,6 @@ public ProductListModel() public IList AvailableCategories { get; set; } public IList AvailableManufacturers { get; set; } public IList AvailableStores { get; set; } - public IList AvailableWithoutCategories { get; set; } - public IList AvailableWithoutManufacturers { get; set; } public IList AvailableProductTypes { get; set; } - public IList AvailableIsPublished { get; set; } - public IList AvailableHomePageProducts { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml index 6352375f48..8dd9c04a99 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Product/List.cshtml @@ -9,7 +9,6 @@ @{ var trueTemplate = "#if (Published) {# #} #"; var allString = T("Admin.Common.All").Text; - var unspecifiedString = T("Common.Unspecified").Text; ViewBag.Title = T("Admin.Catalog.Products.Manage").Text; } @@ -109,7 +108,7 @@ @Html.SmartLabelFor(model => model.SearchProductTypeId) - @Html.DropDownList("SearchProductTypeId", Model.AvailableProductTypes, allString) + @Html.DropDownListFor(model => model.SearchProductTypeId, Model.AvailableProductTypes, allString) @if (Model.StoreCount > 1) @@ -119,7 +118,7 @@ @Html.SmartLabelFor(model => model.SearchStoreId) - @Html.DropDownList("SearchStoreId", Model.AvailableStores, allString) + @Html.DropDownListFor(model => model.SearchStoreId, Model.AvailableStores, allString) } @@ -128,7 +127,7 @@ @Html.SmartLabelFor(model => model.SearchWithoutCategories) - @Html.DropDownList("SearchWithoutCategories", Model.AvailableWithoutCategories, unspecifiedString) + @Html.EditorFor(model => model.SearchWithoutCategories) @@ -136,7 +135,7 @@ @Html.SmartLabelFor(model => model.SearchCategoryId) - @Html.DropDownList("SearchCategoryId", Model.AvailableCategories, allString) + @Html.DropDownListFor(model => model.SearchCategoryId, Model.AvailableCategories, allString) @@ -144,7 +143,7 @@ @Html.SmartLabelFor(model => model.SearchWithoutManufacturers) - @Html.DropDownList("SearchWithoutManufacturers", Model.AvailableWithoutManufacturers, unspecifiedString) + @Html.EditorFor(model => model.SearchWithoutManufacturers) @@ -152,7 +151,7 @@ @Html.SmartLabelFor(model => model.SearchManufacturerId) - @Html.DropDownList("SearchManufacturerId", Model.AvailableManufacturers, allString) + @Html.DropDownListFor(model => model.SearchManufacturerId, Model.AvailableManufacturers, allString) @@ -160,7 +159,7 @@ @Html.SmartLabelFor(model => model.SearchIsPublished) - @Html.DropDownList("SearchIsPublished", Model.AvailableIsPublished, unspecifiedString) + @Html.EditorFor(model => model.SearchIsPublished) @@ -168,7 +167,7 @@ @Html.SmartLabelFor(model => model.SearchHomePageProducts) - @Html.DropDownList("SearchHomePageProducts", Model.AvailableHomePageProducts, unspecifiedString) + @Html.EditorFor(model => model.SearchHomePageProducts) From 72f2e7b68e7773b516d8252e3bae284a3f2a35c4 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 4 Aug 2015 13:16:41 +0200 Subject: [PATCH 0328/1256] Google Analytics: added support for mobile devices --- changelog.md | 1 + .../SmartStore.GoogleAnalytics/Description.txt | 2 +- .../GoogleAnalyticPlugin.cs | 13 ++++++++++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/changelog.md b/changelog.md index 50347c769c..dafb9d59ad 100644 --- a/changelog.md +++ b/changelog.md @@ -29,6 +29,7 @@ * #735 Include SKUs of attribute combinations when filtering the backend product list * Filter for homepage and published\unpublished products in backend product list * Reduce database round trips initiated by price calculation +* Google Analytics: added support for mobile devices ### Bugfixes * #523 Redirecting to payment provider performed by core instead of plugin diff --git a/src/Plugins/SmartStore.GoogleAnalytics/Description.txt b/src/Plugins/SmartStore.GoogleAnalytics/Description.txt index 4a7c23c2ff..c19a7f4113 100644 --- a/src/Plugins/SmartStore.GoogleAnalytics/Description.txt +++ b/src/Plugins/SmartStore.GoogleAnalytics/Description.txt @@ -1,7 +1,7 @@ FriendlyName: Google Analytics SystemName: SmartStore.GoogleAnalytics Group: Analytics -Version: 2.2.0 +Version: 2.2.2.1 MinAppVersion: 2.2.0 DisplayOrder: 1 FileName: SmartStore.GoogleAnalytics.dll diff --git a/src/Plugins/SmartStore.GoogleAnalytics/GoogleAnalyticPlugin.cs b/src/Plugins/SmartStore.GoogleAnalytics/GoogleAnalyticPlugin.cs index 0c798730ff..61d434af55 100644 --- a/src/Plugins/SmartStore.GoogleAnalytics/GoogleAnalyticPlugin.cs +++ b/src/Plugins/SmartStore.GoogleAnalytics/GoogleAnalyticPlugin.cs @@ -31,9 +31,16 @@ public GoogleAnalyticPlugin(ISettingService settingService, /// Widget zones public IList GetWidgetZones() { - return !string.IsNullOrWhiteSpace(_googleAnalyticsSettings.WidgetZone) - ? new List() { _googleAnalyticsSettings.WidgetZone } - : new List() { "head_html_tag" }; + var zones = new List() { "head_html_tag", "mobile_head_html_tag" }; + if(!string.IsNullOrWhiteSpace(_googleAnalyticsSettings.WidgetZone)) + { + zones = new List() { + _googleAnalyticsSettings.WidgetZone, + _googleAnalyticsSettings.WidgetZone == "head_html_tag" ? "mobile_head_html_tag" : "mobile_body_end_html_tag_after" + }; + } + + return zones; } /// From f081152dab4f0b6e2487d74033937c24d081d0d0 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Tue, 4 Aug 2015 17:43:17 +0200 Subject: [PATCH 0329/1256] More about export profile data filtering --- .../Domain/DataExchange/ExportFilter.cs | 17 +- .../201508040836122_ExportFramework.cs | 14 +- .../Controllers/ExportController.cs | 180 +++++++++++----- .../Models/DataExchange/ExportFilterModel.cs | 88 ++++++++ .../Models/DataExchange/ExportProfileModel.cs | 73 +------ .../Administration/SmartStore.Admin.csproj | 1 + .../Administration/Views/Export/Edit.cshtml | 199 +++++++++++++----- 7 files changed, 372 insertions(+), 200 deletions(-) create mode 100644 src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs index a192083317..db02950efb 100644 --- a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs @@ -75,17 +75,12 @@ public class ExportFilter /// /// Identifiers of product tags /// - public int? ProductTagIds { get; set; } + public int[] ProductTagIds { get; set; } /// - /// A value indicating whether loaded products are marked as featured + /// A value indicating whether to load products that are marked as featured (relates only to categories and manufacturers) /// - public bool? IncludeFeaturedProducts { get; set; } - - /// - /// A value indicating whether to load only featured products - /// - public bool? OnlyFeaturedProducts { get; set; } + public bool? FeaturedProducts { get; set; } /// /// Filter by product type @@ -99,17 +94,17 @@ public class ExportFilter /// /// Filter by order status /// - public OrderStatus? OrderStatus { get; set; } + public OrderStatus[] OrderStatus { get; set; } /// /// Filter by payment status /// - public PaymentStatus? PaymentStatus { get; set; } + public PaymentStatus[] PaymentStatus { get; set; } /// /// Filter by shipping status /// - public ShippingStatus? ShippingStatus { get; set; } + public ShippingStatus[] ShippingStatus { get; set; } /// /// Identifiers of customer roles diff --git a/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.cs b/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.cs index 84a392c3ff..b62177e5a4 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.cs @@ -157,7 +157,7 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Admin.Configuration.Export.Filter.CreatedFrom", "Created from", - "Erstellt ab", + "Erstellt von", "Filter by created date.", "Nach dem Erstellungsdatum filtern."); @@ -227,17 +227,11 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Filter by product tags.", "Nach Produkt-Tags filtern."); - builder.AddOrUpdate("Admin.Configuration.Export.Filter.IncludeFeaturedProducts", - "Include featured products", - "Empfohlene Produkte einbeziehen", - "Specifies whether to include featured products.", - "Legt fest, ob empfohlene Produkte einbezogen werden sollen."); - - builder.AddOrUpdate("Admin.Configuration.Export.Filter.OnlyFeaturedProducts", + builder.AddOrUpdate("Admin.Configuration.Export.Filter.FeaturedProducts", "Only featured products", "Nur empfohlene Produkte", - "Filter by featured products.", - "Nach empfohlenen Produkten filtern."); + "Filter by featured products. Is only applied when the filtering by categories and manufacturers.", + "Nach empfohlenen Produkten filtern. Wird nur bei der Filterung nach Warengruppen und Hersteller angewendet."); builder.AddOrUpdate("Admin.Configuration.Export.Filter.ProductType", "Product type", diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs index 510772fdb3..ce04e4a736 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs @@ -6,9 +6,13 @@ using SmartStore.Core.Domain; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.DataExchange; +using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Domain.Payments; +using SmartStore.Core.Domain.Shipping; using SmartStore.Core.Plugins; using SmartStore.Services; using SmartStore.Services.Catalog; +using SmartStore.Services.Customers; using SmartStore.Services.DataExchange; using SmartStore.Services.Media; using SmartStore.Services.Security; @@ -27,19 +31,28 @@ public class ExportController : AdminControllerBase private readonly PluginMediator _pluginMediator; private readonly IPictureService _pictureService; private readonly ICategoryService _categoryService; + private readonly IManufacturerService _manufacturerService; + private readonly IProductTagService _productTagService; + private readonly ICustomerService _customerService; public ExportController( ICommonServices services, IExportService exportService, PluginMediator pluginMediator, IPictureService pictureService, - ICategoryService categoryService) + ICategoryService categoryService, + IManufacturerService manufacturerService, + IProductTagService productTagService, + ICustomerService customerService) { _services = services; _exportService = exportService; _pluginMediator = pluginMediator; _pictureService = pictureService; _categoryService = categoryService; + _manufacturerService = manufacturerService; + _productTagService = productTagService; + _customerService = customerService; } private void PrepareExportProfileModel(ExportProfileModel model, ExportProfile profile, Provider provider) @@ -81,53 +94,88 @@ private void PrepareExportProfileModelForEdit(ExportProfileModel model, ExportPr var filter = XmlHelper.Deserialize(profile.Filtering); var allStores = _services.StoreService.GetAllStores(); - var allCategories = _categoryService.GetAllCategories(showHidden: true); - var mappedCategories = allCategories.ToDictionary(x => x.Id); - var yes = T("Admin.Common.Yes").Text; - var no = T("Admin.Common.No").Text; - - model.StoreCount = allStores.Count; model.AllString = T("Admin.Common.All"); - model.UnspecifiedString = T("Common.Unspecified"); + //model.UnspecifiedString = T("Common.Unspecified"); + model.StoreCount = allStores.Count; model.Offset = profile.Offset; model.Limit = profile.Limit; model.BatchSize = profile.BatchSize; model.PerStore = profile.PerStore; - model.Filtering = new ExportProfileModel.Filter + Action initModelBase = x => { - StoreId = filter.StoreId, - CreatedFrom = filter.CreatedFrom, - CreatedTo = filter.CreatedTo, - PriceMinimum = filter.PriceMinimum, - PriceMaximum = filter.PriceMaximum, - AvailabilityMinimum = filter.AvailabilityMinimum, - AvailabilityMaximum = filter.AvailabilityMaximum, - IsPublished = filter.IsPublished, - CategoryIds = filter.CategoryIds, - WithoutCategories = filter.WithoutCategories, - ManufacturerIds = filter.ManufacturerIds, - WithoutManufacturers = filter.WithoutManufacturers, - ProductTagIds = filter.ProductTagIds, - IncludeFeaturedProducts = filter.IncludeFeaturedProducts, - OnlyFeaturedProducts = filter.OnlyFeaturedProducts, - ProductType = filter.ProductType, - OrderStatus = filter.OrderStatus, - PaymentStatus = filter.PaymentStatus, - ShippingStatus = filter.ShippingStatus, - CustomerRoleIds = filter.CustomerRoleIds + x.StoreId = filter.StoreId; + x.CreatedFrom = filter.CreatedFrom; + x.CreatedTo = filter.CreatedTo; + + x.AvailableStores = allStores + .Select(y => new SelectListItem { Text = y.Name, Value = y.Id.ToString() }) + .ToList(); }; - model.Filtering.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList(); + if (model.Providing.EntityType == ExportEntityType.Product) + { + var allCategories = _categoryService.GetAllCategories(showHidden: true); + var mappedCategories = allCategories.ToDictionary(x => x.Id); + var allManufacturers = _manufacturerService.GetAllManufacturers(true); + var allProductTags = _productTagService.GetAllProductTags(); - model.Filtering.AvailableStores = allStores - .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }) - .ToList(); + model.ProductFiltering = new ExportProductFilterModel + { + PriceMinimum = filter.PriceMinimum, + PriceMaximum = filter.PriceMaximum, + AvailabilityMinimum = filter.AvailabilityMinimum, + AvailabilityMaximum = filter.AvailabilityMaximum, + IsPublished = filter.IsPublished, + CategoryIds = filter.CategoryIds, + WithoutCategories = filter.WithoutCategories, + ManufacturerIds = filter.ManufacturerIds, + WithoutManufacturers = filter.WithoutManufacturers, + ProductTagIds = filter.ProductTagIds, + FeaturedProducts = filter.FeaturedProducts, + ProductType = filter.ProductType + }; + + model.ProductFiltering.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList(); + + model.ProductFiltering.AvailableCategories = allCategories + .Select(x => new SelectListItem { Text = x.GetCategoryNameWithPrefix(_categoryService, mappedCategories), Value = x.Id.ToString() }) + .ToList(); + + model.ProductFiltering.AvailableManufacturers = allManufacturers + .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }) + .ToList(); + + model.ProductFiltering.AvailableProductTags = allProductTags + .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }) + .ToList(); + + initModelBase(model.ProductFiltering); + } + else if (model.Providing.EntityType == ExportEntityType.Order) + { + var allCustomerRoles = _customerService.GetAllCustomerRoles(true); - model.Filtering.AvailableCategories = allCategories - .Select(x => new SelectListItem { Text = x.GetCategoryNameWithPrefix(_categoryService, mappedCategories), Value = x.Id.ToString() }) - .ToList(); + model.OrderFiltering = new ExportOrderFilterModel + { + OrderStatus = filter.OrderStatus, + PaymentStatus = filter.PaymentStatus, + ShippingStatus = filter.ShippingStatus, + CustomerRoleIds = filter.CustomerRoleIds + }; + + model.OrderFiltering.AvailableOrderStates = OrderStatus.Pending.ToSelectList(false).ToList(); + model.OrderFiltering.AvailablePaymentStates = PaymentStatus.Pending.ToSelectList(false).ToList(); + model.OrderFiltering.AvailableShippingStates = ShippingStatus.NotYetShipped.ToSelectList(false).ToList(); + + model.OrderFiltering.AvailableCustomerRoles = allCustomerRoles + .OrderBy(x => x.Name) + .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }) + .ToList(); + + initModelBase(model.OrderFiltering); + } } public ActionResult Index() @@ -254,30 +302,48 @@ public ActionResult Edit(ExportProfileModel model, bool continueEditing) return View(model); } - var filter = new ExportFilter + ExportFilter filter = null; + + Action getFromModelBase = x => { - StoreId = model.Filtering.StoreId ?? 0, - CreatedFrom = model.Filtering.CreatedFrom, - CreatedTo = model.Filtering.CreatedTo, - PriceMinimum = model.Filtering.PriceMinimum, - PriceMaximum = model.Filtering.PriceMaximum, - AvailabilityMinimum = model.Filtering.AvailabilityMinimum, - AvailabilityMaximum = model.Filtering.AvailabilityMaximum, - IsPublished = model.Filtering.IsPublished, - CategoryIds = model.Filtering.CategoryIds, - WithoutCategories = model.Filtering.WithoutCategories, - ManufacturerIds = model.Filtering.ManufacturerIds, - WithoutManufacturers = model.Filtering.WithoutManufacturers, - ProductTagIds = model.Filtering.ProductTagIds, - IncludeFeaturedProducts = model.Filtering.IncludeFeaturedProducts, - OnlyFeaturedProducts = model.Filtering.OnlyFeaturedProducts, - ProductType = model.Filtering.ProductType, - OrderStatus = model.Filtering.OrderStatus, - PaymentStatus = model.Filtering.PaymentStatus, - ShippingStatus = model.Filtering.ShippingStatus, - CustomerRoleIds = model.Filtering.CustomerRoleIds + filter.StoreId = x.StoreId ?? 0; + filter.CreatedFrom = x.CreatedFrom; + filter.CreatedTo = x.CreatedTo; }; + if (model.ProductFiltering != null && provider.Value.EntityType == ExportEntityType.Product) + { + filter = new ExportFilter + { + PriceMinimum = model.ProductFiltering.PriceMinimum, + PriceMaximum = model.ProductFiltering.PriceMaximum, + AvailabilityMinimum = model.ProductFiltering.AvailabilityMinimum, + AvailabilityMaximum = model.ProductFiltering.AvailabilityMaximum, + IsPublished = model.ProductFiltering.IsPublished, + CategoryIds = model.ProductFiltering.CategoryIds, + WithoutCategories = model.ProductFiltering.WithoutCategories, + ManufacturerIds = model.ProductFiltering.ManufacturerIds, + WithoutManufacturers = model.ProductFiltering.WithoutManufacturers, + ProductTagIds = model.ProductFiltering.ProductTagIds, + FeaturedProducts = model.ProductFiltering.FeaturedProducts, + ProductType = model.ProductFiltering.ProductType + }; + + getFromModelBase(model.ProductFiltering); + } + else if (model.OrderFiltering != null && provider.Value.EntityType == ExportEntityType.Order) + { + filter = new ExportFilter + { + OrderStatus = model.OrderFiltering.OrderStatus, + PaymentStatus = model.OrderFiltering.PaymentStatus, + ShippingStatus = model.OrderFiltering.ShippingStatus, + CustomerRoleIds = model.OrderFiltering.CustomerRoleIds + }; + + getFromModelBase(model.OrderFiltering); + } + profile.Name = model.Name; profile.Enabled = model.Enabled; profile.ScheduleTask.Seconds = model.SchedulingHours * 3600; diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs new file mode 100644 index 0000000000..ca812df0b6 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Web.Mvc; +using SmartStore.Core.Domain.Catalog; +using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Domain.Payments; +using SmartStore.Core.Domain.Shipping; +using SmartStore.Web.Framework; + +namespace SmartStore.Admin.Models.DataExchange +{ + public class ExportFilterModelBase + { + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.StoreId")] + public int? StoreId { get; set; } + public List AvailableStores { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CreatedFrom")] + public DateTime? CreatedFrom { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CreatedTo")] + public DateTime? CreatedTo { get; set; } + } + + + public class ExportProductFilterModel : ExportFilterModelBase + { + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.IsPublished")] + public bool? IsPublished { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ProductType")] + public ProductType? ProductType { get; set; } + public List AvailableProductTypes { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.PriceMinimum")] + public decimal? PriceMinimum { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.PriceMaximum")] + public decimal? PriceMaximum { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.AvailabilityMinimum")] + public int? AvailabilityMinimum { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.AvailabilityMaximum")] + public int? AvailabilityMaximum { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CategoryIds")] + public int[] CategoryIds { get; set; } + public List AvailableCategories { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.WithoutCategories")] + public bool? WithoutCategories { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ManufacturerIds")] + public int[] ManufacturerIds { get; set; } + public List AvailableManufacturers { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.WithoutManufacturers")] + public bool? WithoutManufacturers { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ProductTagIds")] + public int[] ProductTagIds { get; set; } + public List AvailableProductTags { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.FeaturedProducts")] + public bool? FeaturedProducts { get; set; } + } + + + public class ExportOrderFilterModel : ExportFilterModelBase + { + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.OrderStatus")] + public OrderStatus[] OrderStatus { get; set; } + public List AvailableOrderStates { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.PaymentStatus")] + public PaymentStatus[] PaymentStatus { get; set; } + public List AvailablePaymentStates { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ShippingStatus")] + public ShippingStatus[] ShippingStatus { get; set; } + public List AvailableShippingStates { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CustomerRoleIds")] + public int[] CustomerRoleIds { get; set; } + public List AvailableCustomerRoles { get; set; } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs index ca98c7ab9b..4dd20aa2e1 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs @@ -39,11 +39,12 @@ public partial class ExportProfileModel : EntityModelBase public bool PerStore { get; set; } public Provider Providing { get; set; } - public Filter Filtering { get; set; } + + public ExportProductFilterModel ProductFiltering { get; set; } + public ExportOrderFilterModel OrderFiltering { get; set; } public int StoreCount { get; set; } public string AllString { get; set; } - public string UnspecifiedString { get; set; } public class Provider @@ -86,73 +87,5 @@ public class Provider [SmartResourceDisplayName("Admin.Configuration.Export.SupportedFileTypes")] public string SupportedFileTypes { get; set; } } - - - public class Filter - { - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.StoreId")] - public int? StoreId { get; set; } - public List AvailableStores { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.IsPublished")] - public bool? IsPublished { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ProductType")] - public ProductType? ProductType { get; set; } - public List AvailableProductTypes { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CreatedFrom")] - public DateTime? CreatedFrom { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CreatedTo")] - public DateTime? CreatedTo { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.PriceMinimum")] - public decimal? PriceMinimum { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.PriceMaximum")] - public decimal? PriceMaximum { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.AvailabilityMinimum")] - public int? AvailabilityMinimum { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.AvailabilityMaximum")] - public int? AvailabilityMaximum { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CategoryIds")] - public int[] CategoryIds { get; set; } - public List AvailableCategories { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.WithoutCategories")] - public bool? WithoutCategories { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ManufacturerIds")] - public int[] ManufacturerIds { get; set; } - public List AvailableManufacturers { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.WithoutManufacturers")] - public bool? WithoutManufacturers { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ProductTagIds")] - public int? ProductTagIds { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.IncludeFeaturedProducts")] - public bool? IncludeFeaturedProducts { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.OnlyFeaturedProducts")] - public bool? OnlyFeaturedProducts { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.OrderStatus")] - public OrderStatus? OrderStatus { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.PaymentStatus")] - public PaymentStatus? PaymentStatus { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ShippingStatus")] - public ShippingStatus? ShippingStatus { get; set; } - - [SmartResourceDisplayName("Admin.Configuration.Export.Filter.CustomerRoleIds")] - public int[] CustomerRoleIds { get; set; } - } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index 0188006d32..0d06106427 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -247,6 +247,7 @@ + diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml index 15e1640b40..ad73a907f4 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml @@ -151,144 +151,228 @@ @helper TabFilter() { - @if (Model.StoreCount > 1) + @if (Model.ProductFiltering != null) { + if (Model.StoreCount > 1) + { + + + + + } - } - - @if (Model.Providing.EntityType == ExportEntityType.Product) - { - + - //TODO manus - + - //TODO product tags } - else if (Model.Providing.EntityType == ExportEntityType.Order) + else if (Model.OrderFiltering != null) { + if (Model.StoreCount > 1) + { + + + + + } + + + + + + + + + + + + + + + + + + + + + + + + }
    + @Html.SmartLabelFor(model => model.ProductFiltering.StoreId) + + @Html.DropDownListFor(model => model.ProductFiltering.StoreId, Model.ProductFiltering.AvailableStores, Model.AllString) + @Html.ValidationMessageFor(model => model.ProductFiltering.StoreId) +
    - @Html.SmartLabelFor(model => model.Filtering.StoreId) + @Html.SmartLabelFor(model => model.ProductFiltering.CreatedFrom) - @Html.DropDownListFor(model => model.Filtering.StoreId, Model.Filtering.AvailableStores, Model.AllString) - @Html.ValidationMessageFor(model => model.Filtering.StoreId) + @Html.EditorFor(model => model.ProductFiltering.CreatedFrom) + @Html.ValidationMessageFor(model => model.ProductFiltering.CreatedFrom)
    - @Html.SmartLabelFor(model => model.Filtering.IsPublished) + @Html.SmartLabelFor(model => model.ProductFiltering.CreatedTo) - @Html.EditorFor(model => model.Filtering.IsPublished) - @Html.ValidationMessageFor(model => model.Filtering.IsPublished) + @Html.EditorFor(model => model.ProductFiltering.CreatedTo) + @Html.ValidationMessageFor(model => model.ProductFiltering.CreatedTo)
    - @Html.SmartLabelFor(model => model.Filtering.ProductType) + @Html.SmartLabelFor(model => model.ProductFiltering.ProductType) - @Html.DropDownListFor(model => model.Filtering.ProductType, Model.Filtering.AvailableProductTypes, Model.AllString) + @Html.DropDownListFor(model => model.ProductFiltering.ProductType, Model.ProductFiltering.AvailableProductTypes, Model.AllString)
    - @Html.SmartLabelFor(model => model.Filtering.CreatedFrom) + @Html.SmartLabelFor(model => model.ProductFiltering.IsPublished) - @Html.EditorFor(model => model.Filtering.CreatedFrom) - @Html.ValidationMessageFor(model => model.Filtering.CreatedFrom) + @Html.EditorFor(model => model.ProductFiltering.IsPublished) + @Html.ValidationMessageFor(model => model.ProductFiltering.IsPublished)
    - @Html.SmartLabelFor(model => model.Filtering.CreatedTo) + @Html.SmartLabelFor(model => model.ProductFiltering.PriceMinimum) - @Html.EditorFor(model => model.Filtering.CreatedTo) - @Html.ValidationMessageFor(model => model.Filtering.CreatedTo) + @Html.EditorFor(model => model.ProductFiltering.PriceMinimum) + @Html.ValidationMessageFor(model => model.ProductFiltering.PriceMinimum)
    - @Html.SmartLabelFor(model => model.Filtering.PriceMinimum) + @Html.SmartLabelFor(model => model.ProductFiltering.PriceMaximum) - @Html.EditorFor(model => model.Filtering.PriceMinimum) - @Html.ValidationMessageFor(model => model.Filtering.PriceMinimum) + @Html.EditorFor(model => model.ProductFiltering.PriceMaximum) + @Html.ValidationMessageFor(model => model.ProductFiltering.PriceMaximum)
    - @Html.SmartLabelFor(model => model.Filtering.PriceMaximum) + @Html.SmartLabelFor(model => model.ProductFiltering.AvailabilityMinimum) - @Html.EditorFor(model => model.Filtering.PriceMaximum) - @Html.ValidationMessageFor(model => model.Filtering.PriceMaximum) + @Html.EditorFor(model => model.ProductFiltering.AvailabilityMinimum) + @Html.ValidationMessageFor(model => model.ProductFiltering.AvailabilityMinimum)
    - @Html.SmartLabelFor(model => model.Filtering.AvailabilityMinimum) + @Html.SmartLabelFor(model => model.ProductFiltering.AvailabilityMaximum) - @Html.EditorFor(model => model.Filtering.AvailabilityMinimum) - @Html.ValidationMessageFor(model => model.Filtering.AvailabilityMinimum) + @Html.EditorFor(model => model.ProductFiltering.AvailabilityMaximum) + @Html.ValidationMessageFor(model => model.ProductFiltering.AvailabilityMaximum)
    - @Html.SmartLabelFor(model => model.Filtering.AvailabilityMaximum) + @Html.SmartLabelFor(model => model.ProductFiltering.WithoutCategories) - @Html.EditorFor(model => model.Filtering.AvailabilityMaximum) - @Html.ValidationMessageFor(model => model.Filtering.AvailabilityMaximum) + @Html.EditorFor(model => model.ProductFiltering.WithoutCategories) + @Html.ValidationMessageFor(model => model.ProductFiltering.WithoutCategories)
    - @Html.SmartLabelFor(model => model.Filtering.CategoryIds) + @Html.SmartLabelFor(model => model.ProductFiltering.CategoryIds) - @Html.ListBoxFor(model => model.Filtering.CategoryIds, - new MultiSelectList(Model.Filtering.AvailableCategories, "Value", "Text"), + @Html.ListBoxFor(model => model.ProductFiltering.CategoryIds, + new MultiSelectList(Model.ProductFiltering.AvailableCategories, "Value", "Text"), new { multiple = "multiple", @class = "control-xlarge" }) - @Html.ValidationMessageFor(model => model.Filtering.CategoryIds) + @Html.ValidationMessageFor(model => model.ProductFiltering.CategoryIds)
    - @Html.SmartLabelFor(model => model.Filtering.WithoutCategories) + @Html.SmartLabelFor(model => model.ProductFiltering.WithoutManufacturers) - @Html.EditorFor(model => model.Filtering.WithoutCategories) - @Html.ValidationMessageFor(model => model.Filtering.WithoutCategories) + @Html.EditorFor(model => model.ProductFiltering.WithoutManufacturers) + @Html.ValidationMessageFor(model => model.ProductFiltering.WithoutManufacturers)
    - @Html.SmartLabelFor(model => model.Filtering.WithoutManufacturers) + @Html.SmartLabelFor(model => model.ProductFiltering.ManufacturerIds) - @Html.EditorFor(model => model.Filtering.WithoutManufacturers) - @Html.ValidationMessageFor(model => model.Filtering.WithoutManufacturers) + @Html.ListBoxFor(model => model.ProductFiltering.ManufacturerIds, + new MultiSelectList(Model.ProductFiltering.AvailableManufacturers, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.ProductFiltering.ManufacturerIds)
    - @Html.SmartLabelFor(model => model.Filtering.IncludeFeaturedProducts) + @Html.SmartLabelFor(model => model.ProductFiltering.ProductTagIds) - @Html.EditorFor(model => model.Filtering.IncludeFeaturedProducts) - @Html.ValidationMessageFor(model => model.Filtering.IncludeFeaturedProducts) + @Html.ListBoxFor(model => model.ProductFiltering.ProductTagIds, + new MultiSelectList(Model.ProductFiltering.AvailableProductTags, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.ProductFiltering.ProductTagIds)
    - @Html.SmartLabelFor(model => model.Filtering.OnlyFeaturedProducts) + @Html.SmartLabelFor(model => model.ProductFiltering.FeaturedProducts) - @Html.EditorFor(model => model.Filtering.OnlyFeaturedProducts) - @Html.ValidationMessageFor(model => model.Filtering.OnlyFeaturedProducts) + @Html.EditorFor(model => model.ProductFiltering.FeaturedProducts) + @Html.ValidationMessageFor(model => model.ProductFiltering.FeaturedProducts)
    + @Html.SmartLabelFor(model => model.OrderFiltering.StoreId) + + @Html.DropDownListFor(model => model.OrderFiltering.StoreId, Model.OrderFiltering.AvailableStores, Model.AllString) + @Html.ValidationMessageFor(model => model.OrderFiltering.StoreId) +
    + @Html.SmartLabelFor(model => model.OrderFiltering.CreatedFrom) + + @Html.EditorFor(model => model.OrderFiltering.CreatedFrom) + @Html.ValidationMessageFor(model => model.OrderFiltering.CreatedFrom) +
    + @Html.SmartLabelFor(model => model.OrderFiltering.CreatedTo) + + @Html.EditorFor(model => model.OrderFiltering.CreatedTo) + @Html.ValidationMessageFor(model => model.OrderFiltering.CreatedTo) +
    + @Html.SmartLabelFor(model => model.OrderFiltering.OrderStatus) + + @Html.ListBoxFor(model => model.OrderFiltering.OrderStatus, + new MultiSelectList(Model.OrderFiltering.AvailableOrderStates, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.OrderFiltering.OrderStatus) +
    + @Html.SmartLabelFor(model => model.OrderFiltering.PaymentStatus) + + @Html.ListBoxFor(model => model.OrderFiltering.PaymentStatus, + new MultiSelectList(Model.OrderFiltering.AvailablePaymentStates, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.OrderFiltering.PaymentStatus) +
    + @Html.SmartLabelFor(model => model.OrderFiltering.ShippingStatus) + + @Html.ListBoxFor(model => model.OrderFiltering.ShippingStatus, + new MultiSelectList(Model.OrderFiltering.AvailableShippingStates, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.OrderFiltering.ShippingStatus) +
    + @Html.SmartLabelFor(model => model.OrderFiltering.CustomerRoleIds) + + @Html.ListBoxFor(model => model.OrderFiltering.CustomerRoleIds, + new MultiSelectList(Model.OrderFiltering.AvailableCustomerRoles, "Value", "Text"), + new { multiple = "multiple", @class = "control-xlarge" }) + @Html.ValidationMessageFor(model => model.OrderFiltering.CustomerRoleIds) +
    } @@ -351,5 +435,16 @@ From 2f78cf063cbda3ecea28c32975720aaeeb35c765 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 4 Aug 2015 19:02:03 +0200 Subject: [PATCH 0330/1256] Payment plugin Purchase Order Number was included in Offline Payment Plugin --- changelog.md | 1 + .../Migrations/201410091620122_NewRes.cs | 8 +-- .../Controllers/OfflinePaymentController.cs | 43 +++++++++++- .../SmartStore.OfflinePayment/Description.txt | 2 +- .../Localization/resources.de-de.xml | 16 +++++ .../Localization/resources.en-us.xml | 22 +++++- .../Models/ConfigurationModel.cs | 4 ++ .../Models/PaymentInfoModel.cs | 6 ++ .../SmartStore.OfflinePayment/Plugin.cs | 6 ++ .../Providers/PurchaseOrderNumberProvider.cs | 69 +++++++++++++++++++ .../Settings/OfflinePaymentSettings.cs | 5 ++ .../SmartStore.OfflinePayment.csproj | 7 ++ ...rchaseOrderNumberPaymentInfo.Mobile.cshtml | 10 +++ .../PurchaseOrderNumberPaymentInfo.cshtml | 20 ++++++ 14 files changed, 210 insertions(+), 9 deletions(-) create mode 100644 src/Plugins/SmartStore.OfflinePayment/Providers/PurchaseOrderNumberProvider.cs create mode 100644 src/Plugins/SmartStore.OfflinePayment/Views/OfflinePayment/PurchaseOrderNumberPaymentInfo.Mobile.cshtml create mode 100644 src/Plugins/SmartStore.OfflinePayment/Views/OfflinePayment/PurchaseOrderNumberPaymentInfo.cshtml diff --git a/changelog.md b/changelog.md index dafb9d59ad..f262cce186 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,7 @@ * #733 Option to set a display order for homepage products * #607 HTML capable full description for payment methods displayed in checkout * #732 Product list: Option to display the pre-selected price instead of the lowest price +* New payment provider for Offline Payment Plugin: Purchase Order Number ### Improvements * (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%. diff --git a/src/Libraries/SmartStore.Data/Migrations/201410091620122_NewRes.cs b/src/Libraries/SmartStore.Data/Migrations/201410091620122_NewRes.cs index 8d3ab6ca6e..4c637b9c9d 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201410091620122_NewRes.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201410091620122_NewRes.cs @@ -91,15 +91,15 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Gltig bis"); builder.Update("Plugins.Payment.CashOnDelivery.PaymentInfoDescription") - .Value("en", "Once your order is placed, you will be contacted by our stuff to confirm the order.") + .Value("en", "Once your order is placed, you will be contacted by our staff to confirm the order.") .Value("de", "Sobald Ihre Bestellung abgeschloen ist, werden Sie persnlich von einem unserer Mitarbeiter kontaktiert, um die Bestellung zu besttigen."); builder.Update("Plugins.Payment.Invoice.PaymentInfoDescription") - .Value("en", "Once your order is placed, you will be contacted by our stuff to confirm the order.") + .Value("en", "Once your order is placed, you will be contacted by our staff to confirm the order.") .Value("de", "Sobald Ihre Bestellung abgeschloen ist, werden Sie persnlich von einem unserer Mitarbeiter kontaktiert, um die Bestellung zu besttigen."); builder.Update("Plugins.Payment.DirectDebit.PaymentInfoDescription") - .Value("en", "Once your order is placed, you will be contacted by our stuff to confirm the order.") + .Value("en", "Once your order is placed, you will be contacted by our staff to confirm the order.") .Value("de", "Sobald Ihre Bestellung abgeschloen ist, werden Sie persnlich von einem unserer Mitarbeiter kontaktiert, um die Bestellung zu besttigen."); builder.Update("Plugins.Payment.PayInStore.PaymentInfoDescription") @@ -107,7 +107,7 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) .Value("de", "Reservieren Sie Produkte und zahlen Sie an der Kasse in unserem Ladenlokal."); builder.Update("Plugins.Payment.Prepayment.PaymentInfoDescription") - .Value("en", "Once your order is placed, you will be contacted by our stuff to confirm the order.") + .Value("en", "Once your order is placed, you will be contacted by our staff to confirm the order.") .Value("de", "Sobald Ihre Bestellung abgeschloen ist, werden Sie persnlich von einem unserer Mitarbeiter kontaktiert, um die Bestellung zu besttigen."); } diff --git a/src/Plugins/SmartStore.OfflinePayment/Controllers/OfflinePaymentController.cs b/src/Plugins/SmartStore.OfflinePayment/Controllers/OfflinePaymentController.cs index d1c5369d54..def82d68f8 100644 --- a/src/Plugins/SmartStore.OfflinePayment/Controllers/OfflinePaymentController.cs +++ b/src/Plugins/SmartStore.OfflinePayment/Controllers/OfflinePaymentController.cs @@ -191,6 +191,10 @@ public override ProcessPaymentRequest GetPaymentInfo(FormCollection form) paymentInfo.DirectDebitCountry = form["DirectDebitCountry"]; paymentInfo.DirectDebitIban = form["DirectDebitIban"]; } + else if (type == "PurchaseOrderNumber") + { + paymentInfo.PurchaseOrderNumber = form["PurchaseOrderNumber"]; + } } return paymentInfo; @@ -229,6 +233,10 @@ public override string GetPaymentSummary(FormCollection form) return number.Mask(8); } } + else if (type == "PurchaseOrderNumber") + { + return form["PurchaseOrderNumber"]; + } } return null; @@ -495,5 +503,38 @@ public ActionResult ManualPaymentInfo() #endregion - } + #region PurchaseOrderNumber + + [AdminAuthorize] + [ChildActionOnly] + public ActionResult PurchaseOrderNumberConfigure() + { + var model = ConfigureGet(); + + return View("GenericConfigure", model); + } + + [HttpPost, AdminAuthorize, ChildActionOnly, ValidateInput(false)] + public ActionResult PurchaseOrderNumberConfigure(PurchaseOrderNumberConfigurationModel model, FormCollection form) + { + if (!ModelState.IsValid) + return InvoiceConfigure(); + + ConfigurePost(model, form); + + return PurchaseOrderNumberConfigure(); + } + + public ActionResult PurchaseOrderNumberPaymentInfo() + { + var model = PaymentInfoGet(); + + var form = this.GetPaymentData(); + model.PurchaseOrderNumber = form["PurchaseOrderNumber"]; + + return PartialView("PurchaseOrderNumberPaymentInfo", model); + } + + #endregion + } } \ No newline at end of file diff --git a/src/Plugins/SmartStore.OfflinePayment/Description.txt b/src/Plugins/SmartStore.OfflinePayment/Description.txt index 869d27cb75..33f0f72b71 100644 --- a/src/Plugins/SmartStore.OfflinePayment/Description.txt +++ b/src/Plugins/SmartStore.OfflinePayment/Description.txt @@ -2,7 +2,7 @@ Description: Contains common offline payment methods like Direct Debit, Invoice, Prepayment etc. Group: Payment SystemName: SmartStore.OfflinePayment -Version: 2.2.0 +Version: 2.2.2.1 MinAppVersion: 2.2.0 DisplayOrder: 0 FileName: SmartStore.OfflinePayment.dll diff --git a/src/Plugins/SmartStore.OfflinePayment/Localization/resources.de-de.xml b/src/Plugins/SmartStore.OfflinePayment/Localization/resources.de-de.xml index 2effbe1ecb..2568394d3b 100644 --- a/src/Plugins/SmartStore.OfflinePayment/Localization/resources.de-de.xml +++ b/src/Plugins/SmartStore.OfflinePayment/Localization/resources.de-de.xml @@ -211,5 +211,21 @@ + + + Bestellnummer + + + + + + + + + + Bestellnummer + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.OfflinePayment/Localization/resources.en-us.xml b/src/Plugins/SmartStore.OfflinePayment/Localization/resources.en-us.xml index 7f21d92f8a..5063cd088b 100644 --- a/src/Plugins/SmartStore.OfflinePayment/Localization/resources.en-us.xml +++ b/src/Plugins/SmartStore.OfflinePayment/Localization/resources.en-us.xml @@ -33,7 +33,7 @@ @@ -96,7 +96,7 @@ @@ -137,7 +137,7 @@ @@ -207,5 +207,21 @@ + + + Purchase order + + + + + + + + + + PO Number + + + \ No newline at end of file diff --git a/src/Plugins/SmartStore.OfflinePayment/Models/ConfigurationModel.cs b/src/Plugins/SmartStore.OfflinePayment/Models/ConfigurationModel.cs index 5a2b5690b5..369cb30b9a 100644 --- a/src/Plugins/SmartStore.OfflinePayment/Models/ConfigurationModel.cs +++ b/src/Plugins/SmartStore.OfflinePayment/Models/ConfigurationModel.cs @@ -45,4 +45,8 @@ public class PayInStoreConfigurationModel : ConfigurationModelBase public class PrepaymentConfigurationModel : ConfigurationModelBase { } + + public class PurchaseOrderNumberConfigurationModel : ConfigurationModelBase + { + } } \ No newline at end of file diff --git a/src/Plugins/SmartStore.OfflinePayment/Models/PaymentInfoModel.cs b/src/Plugins/SmartStore.OfflinePayment/Models/PaymentInfoModel.cs index a48704604d..d120d787c7 100644 --- a/src/Plugins/SmartStore.OfflinePayment/Models/PaymentInfoModel.cs +++ b/src/Plugins/SmartStore.OfflinePayment/Models/PaymentInfoModel.cs @@ -97,4 +97,10 @@ public class PrepaymentPaymentInfoModel : PaymentInfoModelBase { } + public class PurchaseOrderNumberPaymentInfoModel : PaymentInfoModelBase + { + [SmartResourceDisplayName("Plugins.Payment.PurchaseOrder.PurchaseOrderNumber")] + [AllowHtml] + public string PurchaseOrderNumber { get; set; } + } } \ No newline at end of file diff --git a/src/Plugins/SmartStore.OfflinePayment/Plugin.cs b/src/Plugins/SmartStore.OfflinePayment/Plugin.cs index 1fd3c082ee..f496f22698 100644 --- a/src/Plugins/SmartStore.OfflinePayment/Plugin.cs +++ b/src/Plugins/SmartStore.OfflinePayment/Plugin.cs @@ -41,12 +41,18 @@ public override void Install() }); settings.SaveSetting(new ManualPaymentSettings { + DescriptionText = "@Plugins.Payments.Manual.PaymentInfoDescription", TransactMode = TransactMode.Pending }); settings.SaveSetting(new DirectDebitPaymentSettings { DescriptionText = "@Plugins.Payments.DirectDebit.PaymentInfoDescription" }); + settings.SaveSetting(new PurchaseOrderNumberPaymentSettings + { + DescriptionText = "@Plugins.Payments.PurchaseOrderNumber.PaymentInfoDescription", + TransactMode = TransactMode.Pending + }); // add resources loc.ImportPluginResourcesFromXml(this.PluginDescriptor); diff --git a/src/Plugins/SmartStore.OfflinePayment/Providers/PurchaseOrderNumberProvider.cs b/src/Plugins/SmartStore.OfflinePayment/Providers/PurchaseOrderNumberProvider.cs new file mode 100644 index 0000000000..10bc19c582 --- /dev/null +++ b/src/Plugins/SmartStore.OfflinePayment/Providers/PurchaseOrderNumberProvider.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Web.Routing; +using SmartStore.Core.Domain.Orders; +using SmartStore.Core.Domain.Payments; +using SmartStore.Core.Plugins; +using SmartStore.OfflinePayment.Settings; +using SmartStore.Services.Configuration; +using SmartStore.Services.Localization; +using SmartStore.Services.Payments; + +namespace SmartStore.OfflinePayment +{ + [SystemName("SmartStore.PurchaseOrderNumber")] + [FriendlyName("Purchase Order Number")] + [DisplayOrder(10)] + public class PurchaseOrderNumberProvider : OfflinePaymentProviderBase, IConfigurable + { + private readonly ISettingService _settingService; + private readonly ILocalizationService _localizationService; + + public PurchaseOrderNumberProvider(ISettingService settingService, ILocalizationService localizationService) + { + _settingService = settingService; + _localizationService = localizationService; + } + + public override ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentRequest) + { + var result = new ProcessPaymentResult(); + var settings = CommonServices.Settings.LoadSetting(processPaymentRequest.StoreId); + + result.AllowStoringCreditCardNumber = true; + switch (settings.TransactMode) + { + case TransactMode.Pending: + result.NewPaymentStatus = PaymentStatus.Pending; + break; + case TransactMode.Authorize: + result.NewPaymentStatus = PaymentStatus.Authorized; + break; + case TransactMode.AuthorizeAndCapture: + result.NewPaymentStatus = PaymentStatus.Paid; + break; + default: + { + result.AddError(T("Common.Payment.TranactionTypeNotSupported")); + return result; + } + } + + return result; + } + + public override bool RequiresInteraction + { + get + { + return true; + } + } + + protected override string GetActionPrefix() + { + return "PurchaseOrderNumber"; + } + + } +} diff --git a/src/Plugins/SmartStore.OfflinePayment/Settings/OfflinePaymentSettings.cs b/src/Plugins/SmartStore.OfflinePayment/Settings/OfflinePaymentSettings.cs index 7344b3ca56..c4f4fc9758 100644 --- a/src/Plugins/SmartStore.OfflinePayment/Settings/OfflinePaymentSettings.cs +++ b/src/Plugins/SmartStore.OfflinePayment/Settings/OfflinePaymentSettings.cs @@ -29,6 +29,11 @@ public class ManualPaymentSettings : PaymentSettingsBase, ISettings public TransactMode TransactMode { get; set; } } + public class PurchaseOrderNumberPaymentSettings : PaymentSettingsBase, ISettings + { + public TransactMode TransactMode { get; set; } + } + public class PayInStorePaymentSettings : PaymentSettingsBase, ISettings { } diff --git a/src/Plugins/SmartStore.OfflinePayment/SmartStore.OfflinePayment.csproj b/src/Plugins/SmartStore.OfflinePayment/SmartStore.OfflinePayment.csproj index 015c3b66c5..01c44a1163 100644 --- a/src/Plugins/SmartStore.OfflinePayment/SmartStore.OfflinePayment.csproj +++ b/src/Plugins/SmartStore.OfflinePayment/SmartStore.OfflinePayment.csproj @@ -145,6 +145,7 @@ + @@ -214,6 +215,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + diff --git a/src/Plugins/SmartStore.OfflinePayment/Views/OfflinePayment/PurchaseOrderNumberPaymentInfo.Mobile.cshtml b/src/Plugins/SmartStore.OfflinePayment/Views/OfflinePayment/PurchaseOrderNumberPaymentInfo.Mobile.cshtml new file mode 100644 index 0000000000..87191ec5e0 --- /dev/null +++ b/src/Plugins/SmartStore.OfflinePayment/Views/OfflinePayment/PurchaseOrderNumberPaymentInfo.Mobile.cshtml @@ -0,0 +1,10 @@ +@{ + Layout = ""; +} +@using SmartStore.Web.Framework; +@using SmartStore.OfflinePayment.Models; +@model PurchaseOrderNumberPaymentInfoModel + +@Html.SmartLabelFor(model => model.PurchaseOrderNumber, false) +@Html.TextBoxFor(model => model.PurchaseOrderNumber, new { autocomplete = "off" }) +@Html.ValidationMessageFor(model => model.PurchaseOrderNumber) diff --git a/src/Plugins/SmartStore.OfflinePayment/Views/OfflinePayment/PurchaseOrderNumberPaymentInfo.cshtml b/src/Plugins/SmartStore.OfflinePayment/Views/OfflinePayment/PurchaseOrderNumberPaymentInfo.cshtml new file mode 100644 index 0000000000..0d21481f2d --- /dev/null +++ b/src/Plugins/SmartStore.OfflinePayment/Views/OfflinePayment/PurchaseOrderNumberPaymentInfo.cshtml @@ -0,0 +1,20 @@ +@using SmartStore.Web.Framework; +@using SmartStore.OfflinePayment.Models; + +@model PurchaseOrderNumberPaymentInfoModel + +@{ + Layout = ""; +} + +@Html.Hidden("OfflinePaymentMethodType", "PurchaseOrderNumber") + +
    +
    + @Html.LabelFor(model => model.PurchaseOrderNumber, new { @class="control-label required" }) +
    + @Html.TextBoxFor(model => model.PurchaseOrderNumber, new { style = "width: 165px;", autocomplete = "off" }) + @Html.ValidationMessageFor(model => model.PurchaseOrderNumber) +
    +
    +
    \ No newline at end of file From 2a5b3db711fb67cee52ed18d6f699ed00f671e1e Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Tue, 4 Aug 2015 23:30:05 +0200 Subject: [PATCH 0331/1256] Proper error handling for TaskScheduler and several other fixes & enhancements --- changelog.md | 16 +++++--- .../SmartStore.Core/Logging/TraceLogger.cs | 2 +- .../Messages/QueuedMessagesSendTask.cs | 5 ++- .../ChangeTaskSchedulerBaseUrlConsumer.cs | 17 +++++++-- .../Tasks/ITaskScheduler.cs | 5 +-- .../Tasks/InitializeSchedulerFilter.cs | 16 +++++++- .../Tasks/TaskScheduler.cs | 37 ++++++++++++++++--- .../Administration/Scripts/admin.common.js | 3 ++ .../Views/ScheduleTask/List.cshtml | 5 --- .../Controllers/TaskSchedulerController.cs | 4 +- src/Presentation/SmartStore.Web/Web.config | 8 +++- 11 files changed, 90 insertions(+), 28 deletions(-) diff --git a/changelog.md b/changelog.md index f262cce186..4643e9ae8f 100644 --- a/changelog.md +++ b/changelog.md @@ -4,13 +4,15 @@ ### New Features * #141 Payment and shipping methods by customer roles -* #67 Restrict payment methods to certain countries -* #94 Restrict payment methods to certain shipping methods -* #526 Min\max amount option for which the payment method should be offered during checkout +* #67 Restrict payment methods to countries +* #94 Restrict payment methods to shipping methods +* #584 Email attachment support for message templates +* Attach order invoice PDF automatically to order notification emails +* #526 Min/Max amount option for which the payment method should be offered during checkout * #718 ShopConnector: Import option for "Published" and "Disable buy\wishlist button" * #702 Facebook and Twitter external authentication suitable for multi-stores -* New scheduled task: clear e-mail queue -* New scheduled task: clear uploadeded transient media files +* New scheduled task: Clear e-mail queue +* New scheduled task: Clear uploadeded transient media files * #704 Make primary store currency suitable for multi-stores * #727 Web-API: Option to deactivate TimestampOlderThanLastRequest validation * #731 Web-API: Allow deletion and inserting of product category and manufacturer assignments @@ -23,7 +25,9 @@ * (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%. * (Perf) Significantly reduced number of database reads during product list rendering. Increases request speed by up to 10%. * (Perf) Implemented 2nd level cache for infrequently changed entities. Increases request speed by up to 10%. -* #721 Message Queue: implemented "Delete all" +* TaskScheduler: Rewritten from scratch to be suitable for Web Farms +* TaskScheduler: Editing tasks does not require app restart anymore +* TaskScheduler: Enhanced UI * #721 Message Queue: implemented "Delete all" * #725 Prevent LowestProductPrice being 0 * #709 News feed produced invalid RSS feed. Added content:encoded. Added maximum news age setting for feed export. diff --git a/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs b/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs index c54d0e2adf..610b2c57f1 100644 --- a/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs +++ b/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs @@ -89,7 +89,7 @@ public void InsertLog(LogContext context) var msg = context.ShortMessage; if (context.FullMessage.HasValue()) { - msg += "\r\n{0}".FormatCurrent(context.FullMessage); + msg += "{0}{1}".FormatCurrent(Environment.NewLine, context.FullMessage); } _traceSource.TraceEvent(type, (int)type, "{0}: {1}".FormatCurrent(type.ToString().ToUpper(), msg)); } diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs index b3058c31a8..a37e7e82c4 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs @@ -16,7 +16,7 @@ public QueuedMessagesSendTask(IQueuedEmailService queuedEmailService) public void Execute(TaskExecutionContext ctx) { - const int pageSize = 100; + const int pageSize = 1000; const int maxTries = 3; for (int i = 0; i < 9999999; ++i) @@ -26,7 +26,8 @@ public void Execute(TaskExecutionContext ctx) MaxSendTries = maxTries, PageIndex = i, PageSize = pageSize, - Expand = "Attachments" + Expand = "Attachments", + UnsentOnly = true }; var queuedEmails = _queuedEmailService.SearchEmails(q); diff --git a/src/Libraries/SmartStore.Services/Tasks/ChangeTaskSchedulerBaseUrlConsumer.cs b/src/Libraries/SmartStore.Services/Tasks/ChangeTaskSchedulerBaseUrlConsumer.cs index ea67030e61..a79a13c4ec 100644 --- a/src/Libraries/SmartStore.Services/Tasks/ChangeTaskSchedulerBaseUrlConsumer.cs +++ b/src/Libraries/SmartStore.Services/Tasks/ChangeTaskSchedulerBaseUrlConsumer.cs @@ -7,6 +7,7 @@ using SmartStore.Core.Domain.Stores; using SmartStore.Core.Events; using SmartStore.Services.Stores; +using SmartStore.Utilities; namespace SmartStore.Services.Tasks { @@ -18,27 +19,37 @@ public class ChangeTaskSchedulerBaseUrlConsumer : private readonly ITaskScheduler _taskScheduler; private readonly IStoreService _storeService; private readonly HttpContextBase _httpContext; + private readonly bool _shouldChange; public ChangeTaskSchedulerBaseUrlConsumer(ITaskScheduler taskScheduler, IStoreService storeService, HttpContextBase httpContext) { this._taskScheduler = taskScheduler; this._storeService = storeService; this._httpContext = httpContext; + this._shouldChange = CommonHelper.GetAppSetting("sm:TaskSchedulerBaseUrl").IsWebUrl() == false; } public void HandleEvent(EntityInserted eventMessage) { - _taskScheduler.SetBaseUrl(_storeService, _httpContext); + HandleEventCore(); } public void HandleEvent(EntityUpdated eventMessage) { - _taskScheduler.SetBaseUrl(_storeService, _httpContext); + HandleEventCore(); } public void HandleEvent(EntityDeleted eventMessage) { - _taskScheduler.SetBaseUrl(_storeService, _httpContext); + HandleEventCore(); } + + private void HandleEventCore() + { + if (_shouldChange) + { + _taskScheduler.SetBaseUrl(_storeService, _httpContext); + } + } } } diff --git a/src/Libraries/SmartStore.Services/Tasks/ITaskScheduler.cs b/src/Libraries/SmartStore.Services/Tasks/ITaskScheduler.cs index 99a5d554c5..15d4b31df9 100644 --- a/src/Libraries/SmartStore.Services/Tasks/ITaskScheduler.cs +++ b/src/Libraries/SmartStore.Services/Tasks/ITaskScheduler.cs @@ -74,7 +74,6 @@ public static class ITaskSchedulerExtensions internal static void SetBaseUrl(this ITaskScheduler scheduler, IStoreService storeService, HttpContextBase httpContext) { - var path = VirtualPathUtility.ToAbsolute("~/TaskScheduler"); string url = ""; if (!httpContext.Request.IsLocal) @@ -82,13 +81,13 @@ internal static void SetBaseUrl(this ITaskScheduler scheduler, IStoreService sto var defaultStore = storeService.GetAllStores().FirstOrDefault(x => storeService.IsStoreDataValid(x)); if (defaultStore != null) { - url = defaultStore.Url; + url = defaultStore.Url.EnsureEndsWith("/") + "TaskScheduler"; } } if (url.IsEmpty()) { - url = WebHelper.GetAbsoluteUrl(path, httpContext.Request); + url = WebHelper.GetAbsoluteUrl(VirtualPathUtility.ToAbsolute("~/TaskScheduler"), httpContext.Request); } scheduler.BaseUrl = url; diff --git a/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs b/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs index 9175b7a0bc..849916d622 100644 --- a/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs +++ b/src/Libraries/SmartStore.Services/Tasks/InitializeSchedulerFilter.cs @@ -10,6 +10,7 @@ using System.Web.Mvc; using SmartStore.Core.Data; using SmartStore.Core.Logging; +using SmartStore.Utilities; namespace SmartStore.Services.Tasks { @@ -38,7 +39,20 @@ public void OnAuthorization(AuthorizationContext filterContext) var tasks = taskService.GetAllTasks(true); taskService.CalculateNextRunTimes(tasks, true /* isAppStart */); - taskScheduler.SetBaseUrl(storeService, filterContext.HttpContext); + var baseUrl = CommonHelper.GetAppSetting("sm:TaskSchedulerBaseUrl"); + if (baseUrl.IsWebUrl()) + { + taskScheduler.BaseUrl = baseUrl; + } + else + { + // autoresolve base url + taskScheduler.SetBaseUrl(storeService, filterContext.HttpContext); + } + + var sweepInterval = CommonHelper.GetAppSetting("sm:TaskSchedulerSweepInterval", 60); + taskScheduler.SweepInterval = TimeSpan.FromSeconds(sweepInterval); + taskScheduler.Start(); logger.Information("Initialized TaskScheduler with base url '{0}'".FormatInvariant(taskScheduler.BaseUrl)); diff --git a/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs b/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs index 79ae357366..acf2e7c692 100644 --- a/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs +++ b/src/Libraries/SmartStore.Services/Tasks/TaskScheduler.cs @@ -19,6 +19,7 @@ public class DefaultTaskScheduler : DisposableObject, ITaskScheduler, IRegistere private string _baseUrl; private System.Timers.Timer _timer; private bool _shuttingDown; + private int _errCount; private readonly ConcurrentDictionary _authTokens = new ConcurrentDictionary(); public DefaultTaskScheduler() @@ -115,7 +116,7 @@ protected internal virtual void CallEndpoint(string url) req.UserAgent = "SmartStore.NET"; req.Method = "POST"; req.ContentType = "text/plain"; - req.ContentLength = 0; + req.ContentLength = 0; string authToken = Guid.NewGuid().ToString(); _authTokens.TryAdd(authToken, true); @@ -125,22 +126,48 @@ protected internal virtual void CallEndpoint(string url) { if (t.IsFaulted) { - // TODO: Now what?! Disable timer? - using (var logger = new TraceLogger()) + HandleException(t.Exception, url); + _errCount++; + if (_errCount >= 10) { - foreach (var ex in t.Exception.InnerExceptions) + // 10 failed attempts in succession. Stop the timer! + this.Stop(); + using (var logger = new TraceLogger()) { - logger.Error("Error while calling TaskScheduler endpoint (URL: {0})".FormatInvariant(url), ex); + logger.Information("Stopping TaskScheduler sweep timer. Too many failed requests in succession."); } } } else { + _errCount = 0; t.Result.Dispose(); } }); } + private void HandleException(AggregateException exception, string url) + { + using (var logger = new TraceLogger()) + { + string msg = "Error while calling TaskScheduler endpoint '{0}'.".FormatInvariant(url); + var wex = exception.InnerExceptions.OfType().FirstOrDefault(); + + if (wex == null) + { + logger.Error(msg, exception); + } + else + { + using (var response = wex.Response as HttpWebResponse) + { + msg += " HTTP {0}, {1}".FormatCurrent((int)response.StatusCode, response.StatusDescription); + logger.Error(msg); + } + } + } + } + private void CheckUrl(string url) { if (!url.IsWebUrl()) diff --git a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js index 1387de0d25..e1ae7ea26e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js +++ b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.common.js @@ -108,6 +108,9 @@ var Admin = { } } }); + }, + error: function (xhr, ajaxOptions, thrownError) { + window.clearInterval(interval); } }); } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml index b6ec8f00be..20e6437c3c 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml @@ -83,11 +83,6 @@ } }); - function refreshGrid() { - var grid = $("#schedule-tasks-grid").data("tGrid"); - grid.ajaxRequest(); - } - Admin.TaskWatcher.startWatching({ context: $('#schedule-tasks-grid'), elementsSelector: '.task-progress', diff --git a/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs b/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs index eef3ac94e0..c67a3949f3 100644 --- a/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs +++ b/src/Presentation/SmartStore.Web/Controllers/TaskSchedulerController.cs @@ -44,6 +44,8 @@ public ActionResult Sweep() var prevTaskStart = DateTime.UtcNow; var count = 0; + return new HttpStatusCodeResult(System.Net.HttpStatusCode.Unauthorized, "YOOO, this is not authorized dude. WTF?!"); + foreach (var task in pendingTasks) { var elapsedSincePrevTask = DateTime.UtcNow - prevTaskStart; @@ -80,7 +82,7 @@ public ActionResult Execute(int id /* taskId */) _taskExecutor.Execute(task); - return Content("Task '{0}' executed".FormatCurrent(task.Name)); + return Content("Task '{0}' executed".FormatCurrent(task.Name)); } } diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config index cf1a8fedd3..ca8993dab2 100644 --- a/src/Presentation/SmartStore.Web/Web.config +++ b/src/Presentation/SmartStore.Web/Web.config @@ -81,12 +81,18 @@ + + + + - + From 893bfb962088aa95b2c5a9acf186681369a9d914 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 5 Aug 2015 00:03:14 +0200 Subject: [PATCH 0332/1256] Minor fixes for last commit --- .../Administration/Views/ScheduleTask/List.cshtml | 3 ++- src/Presentation/SmartStore.Web/Web.config | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml index 20e6437c3c..0bd33e4cc9 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml @@ -26,7 +26,8 @@ .Columns(columns => { columns.Bound(x => x.Name).ClientTemplate("<#= Name #>"); - columns.Bound(x => x.Seconds); + columns.Bound(x => x.Seconds) + .ClientTemplate("<#= _.formatTime(Seconds) #>"); columns.Bound(x => x.Enabled) .ClientTemplate(@Html.SymbolForBool("Enabled")) .Centered() diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config index ca8993dab2..cabadacd9d 100644 --- a/src/Presentation/SmartStore.Web/Web.config +++ b/src/Presentation/SmartStore.Web/Web.config @@ -92,7 +92,7 @@ - + From c0cdd409956bbab4261c219c6675d16b42c068ae Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 5 Aug 2015 00:16:04 +0200 Subject: [PATCH 0333/1256] Removed KeepAlive Task. Not necessary anymore: the TaskScheduler sweeper does the job now. --- ...01508042207146_RemoveKeepAlive.Designer.cs | 29 ++++ .../201508042207146_RemoveKeepAlive.cs | 35 +++++ .../201508042207146_RemoveKeepAlive.resx | 126 ++++++++++++++++++ .../Setup/SeedData/InvariantSeedData.cs | 8 -- .../SmartStore.Data/SmartStore.Data.csproj | 7 + .../Common/KeepAliveTask.cs | 20 --- .../SmartStore.Services.csproj | 1 - .../Installation/DeDESeedData.cs | 4 - 8 files changed, 197 insertions(+), 33 deletions(-) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.Designer.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.cs create mode 100644 src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.resx delete mode 100644 src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs diff --git a/src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.Designer.cs new file mode 100644 index 0000000000..fbd14a355a --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.Designer.cs @@ -0,0 +1,29 @@ +// +namespace SmartStore.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")] + public sealed partial class RemoveKeepAlive : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(RemoveKeepAlive)); + + string IMigrationMetadata.Id + { + get { return "201508042207146_RemoveKeepAlive"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.cs b/src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.cs new file mode 100644 index 0000000000..5955672869 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.cs @@ -0,0 +1,35 @@ +namespace SmartStore.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + using SmartStore.Data.Setup; + + public partial class RemoveKeepAlive : DbMigration, ILocaleResourcesProvider, IDataSeeder + { + public override void Up() + { + Sql("DELETE FROM [dbo].[ScheduleTask] WHERE [Type] = 'SmartStore.Services.Common.KeepAliveTask, SmartStore.Services'"); + } + + public override void Down() + { + } + + public bool RollbackOnFailure + { + get { return false; } + } + + public void Seed(SmartObjectContext context) + { + context.MigrateLocaleResources(MigrateLocaleResources); + } + + public void MigrateLocaleResources(LocaleResourcesBuilder builder) + { + builder.AddOrUpdate("Admin.System.ScheduleTasks", + "Scheduled Tasks", + "Geplante Aufgaben"); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.resx b/src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.resx new file mode 100644 index 0000000000..483dbdf042 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201508042207146_RemoveKeepAlive.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs index 6aee45953b..a38b7a8533 100644 --- a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs +++ b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs @@ -4777,14 +4777,6 @@ public IList ScheduleTasks() StopOnError = false, }, new ScheduleTask - { - Name = "Keep alive", - Seconds = 300, - Type = "SmartStore.Services.Common.KeepAliveTask, SmartStore.Services", - Enabled = true, - StopOnError = false, - }, - new ScheduleTask { Name = "Delete guests", Seconds = 600, diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index a6fce9f98b..0c98484c4a 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -331,6 +331,10 @@ 201507250039446_Merge2.cs + + + 201508042207146_RemoveKeepAlive.cs + @@ -627,6 +631,9 @@ 201507250039446_Merge2.cs + + 201508042207146_RemoveKeepAlive.cs +
    diff --git a/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs b/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs deleted file mode 100644 index a7ae21aa9a..0000000000 --- a/src/Libraries/SmartStore.Services/Common/KeepAliveTask.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Net; -using System.Threading.Tasks; -using SmartStore.Core; -using SmartStore.Services.Tasks; - -namespace SmartStore.Services.Common -{ - /// - /// Represents a task for keeping the site alive - /// - public partial class KeepAliveTask : ITask - { - - public void Execute(TaskExecutionContext ctx) - { - // do absolutely nothing - } - } -} diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj index 49e1c86d78..de9c015e87 100644 --- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj +++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj @@ -244,7 +244,6 @@ - diff --git a/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs b/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs index bf7c9b7940..fbc4191d29 100644 --- a/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs +++ b/src/Presentation/SmartStore.Web/Infrastructure/Installation/DeDESeedData.cs @@ -2525,10 +2525,6 @@ protected override void Alter(IList entities) { x.Name = "Temporäre Uploads bereinigen"; }) - .Alter("SmartStore.Services.Common.KeepAliveTask, SmartStore.Services", x => - { - x.Name = "Keep alive"; - }) .Alter("SmartStore.Services.Customers.DeleteGuestsTask, SmartStore.Services", x => { x.Name = "Gastbenutzer löschen"; From 7996b6a407025dc33b4a64f83e975aab295af339 Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Wed, 5 Aug 2015 00:20:42 +0200 Subject: [PATCH 0334/1256] Updated changelog --- changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.md b/changelog.md index 4643e9ae8f..06341a80cf 100644 --- a/changelog.md +++ b/changelog.md @@ -35,6 +35,8 @@ * Filter for homepage and published\unpublished products in backend product list * Reduce database round trips initiated by price calculation * Google Analytics: added support for mobile devices +* (Dev) TaskScheduler: Tasks can propagate progress info (percentage & message) +* (Dev) TaskScheduler: Cancellation request is sent to tasks on app shutdown ### Bugfixes * #523 Redirecting to payment provider performed by core instead of plugin From 829d9eeb4fdde4e231bd194ee91874de8b75ed8e Mon Sep 17 00:00:00 2001 From: Murat Cakir Date: Thu, 6 Aug 2015 01:24:05 +0200 Subject: [PATCH 0335/1256] Minor UI fix for TaskScheduler --- .../Administration/Controllers/ScheduleTaskController.cs | 1 + .../Administration/Models/Tasks/ScheduleTaskModel.cs | 1 + .../Administration/Views/ScheduleTask/List.cshtml | 2 +- src/Presentation/SmartStore.Web/Web.config | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs index 0de794588b..28c0c267f9 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ScheduleTaskController.cs @@ -101,6 +101,7 @@ protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) Id = task.Id, Name = task.Name, Seconds = task.Seconds, + PrettySeconds = TimeSpan.FromSeconds(task.Seconds).Prettify(), Enabled = task.Enabled, StopOnError = task.StopOnError, LastStartUtc = task.LastStartUtc.HasValue ? task.LastStartUtc.Value.RelativeFormat(true, "f") : "", diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs index b303fbb6ee..c4b5883759 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/Tasks/ScheduleTaskModel.cs @@ -15,6 +15,7 @@ public partial class ScheduleTaskModel : EntityModelBase [SmartResourceDisplayName("Admin.System.ScheduleTasks.Seconds")] public int Seconds { get; set; } + public string PrettySeconds { get; set; } [SmartResourceDisplayName("Admin.System.ScheduleTasks.Enabled")] public bool Enabled { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml index 0bd33e4cc9..ddbd401aad 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/ScheduleTask/List.cshtml @@ -27,7 +27,7 @@ { columns.Bound(x => x.Name).ClientTemplate("<#= Name #>"); columns.Bound(x => x.Seconds) - .ClientTemplate("<#= _.formatTime(Seconds) #>"); + .ClientTemplate("<#= PrettySeconds #>"); columns.Bound(x => x.Enabled) .ClientTemplate(@Html.SymbolForBool("Enabled")) .Centered() diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config index cabadacd9d..ca8993dab2 100644 --- a/src/Presentation/SmartStore.Web/Web.config +++ b/src/Presentation/SmartStore.Web/Web.config @@ -92,7 +92,7 @@ - + From a120191a6410a17407d44eef557c2471d4c47cdd Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Thu, 6 Aug 2015 11:40:54 +0200 Subject: [PATCH 0336/1256] Disable field for customer number in frontend according to customer setting --- .../SmartStore.Web/Views/Customer/Info.cshtml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml b/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml index 2e75e5f05e..e32a12bef9 100644 --- a/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml +++ b/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml @@ -134,10 +134,12 @@
    } - @if(Model.CustomerNumberEnabled) - { - @Html.ControlGroupFor(model => model.CustomerNumber, required: false) - } +
    + @Html.LabelFor(model => model.CustomerNumber, new { @class = "control-label", @for = "CustomerNumber" }) +
    + @Html.TextBoxFor(model => model.CustomerNumber, !Model.CustomerNumberEnabled ? new { @readonly = "true" } : null) +
    +
    From 9abd1a948fba58983429cc26f6a18fea8daed453 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Thu, 6 Aug 2015 11:40:54 +0200 Subject: [PATCH 0337/1256] Disable field for customer number in frontend according to customer setting --- .../Views/Customer/_CreateOrUpdate.cshtml | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Customer/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Customer/_CreateOrUpdate.cshtml index 6c72eae453..508b65a07d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Customer/_CreateOrUpdate.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Customer/_CreateOrUpdate.cshtml @@ -201,18 +201,15 @@ } - @if (Model.CustomerNumberEnabled) - { - - - @Html.SmartLabelFor(model => model.CustomerNumber) - - - @Html.EditorFor(model => model.CustomerNumber) - @Html.ValidationMessageFor(model => model.CustomerNumber) - - - } + + + @Html.SmartLabelFor(model => model.CustomerNumber) + + + @Html.EditorFor(model => model.CustomerNumber) + @Html.ValidationMessageFor(model => model.CustomerNumber) + + @if (Model.StreetAddressEnabled) { From aa4a544b9c34c383df7ca54e0dfc6459c4d56f15 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Thu, 6 Aug 2015 15:07:26 +0200 Subject: [PATCH 0338/1256] Export framework manages provider specific configuration data --- .../Domain/DataExchange/ExportProfile.cs | 13 +- .../Domain/DataExchange/ExportProjection.cs | 18 + .../SmartStore.Core/SmartStore.Core.csproj | 1 + src/Libraries/SmartStore.Core/XmlHelper.cs | 45 ++- .../Mapping/DataExchange/ExportProfileMap.cs | 2 + .../201508040836122_ExportFramework.resx | 126 ------- ...1508051818404_ExportFramework.Designer.cs} | 2 +- ....cs => 201508051818404_ExportFramework.cs} | 21 +- .../201508051818404_ExportFramework.resx | 126 +++++++ .../SmartStore.Data/SmartStore.Data.csproj | 10 +- .../DataExchange/IExportProvider.cs | 17 +- .../Messages/QueuedMessagesSendTask.cs | 3 +- .../Controllers/ExportController.cs | 264 +++++++++---- .../Models/DataExchange/ExportFilterModel.cs | 2 +- .../Models/DataExchange/ExportPreviewModel.cs | 10 + .../Models/DataExchange/ExportProfileModel.cs | 25 +- .../DataExchange/ExportProjectionModel.cs | 17 + .../Administration/SmartStore.Admin.csproj | 3 + .../Administration/Views/Export/Create.cshtml | 6 +- .../Administration/Views/Export/Edit.cshtml | 357 ++++++++++-------- .../Administration/Views/Export/List.cshtml | 18 +- .../Views/Export/Preview.cshtml | 20 + 22 files changed, 698 insertions(+), 408 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProjection.cs delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.resx rename src/Libraries/SmartStore.Data/Migrations/{201508040836122_ExportFramework.Designer.cs => 201508051818404_ExportFramework.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201508040836122_ExportFramework.cs => 201508051818404_ExportFramework.cs} (92%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.resx create mode 100644 src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportPreviewModel.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProjectionModel.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Export/Preview.cshtml diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs index fdd4eb5e34..907701cc2b 100644 --- a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs @@ -38,14 +38,19 @@ public ExportProfile() public int SchedulingTaskId { get; set; } /// - /// The profile GUID is the folder name in the file system + /// XML with filtering information /// - public Guid ProfileGuid { get; set; } + public string Filtering { get; set; } /// - /// XML with filtering information + /// XML with projection information /// - public string Filtering { get; set; } + public string Projection { get; set; } + + /// + /// Provider specific configuration data + /// + public string ProviderConfigData { get; set; } /// /// The number of records to be skipped diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProjection.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProjection.cs new file mode 100644 index 0000000000..3020a71b1c --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProjection.cs @@ -0,0 +1,18 @@ +using System; + +namespace SmartStore.Core.Domain.DataExchange +{ + [Serializable] + public class ExportProjection + { + /// + /// The language to be applied to the export + /// + public int LanguageId { get; set; } + + /// + /// The currency to be applied to the export + /// + public int CurrencyId { get; set; } + } +} diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 8e4537dd4c..4dbef97117 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -157,6 +157,7 @@ + diff --git a/src/Libraries/SmartStore.Core/XmlHelper.cs b/src/Libraries/SmartStore.Core/XmlHelper.cs index 7f546eba8a..b73c914f03 100644 --- a/src/Libraries/SmartStore.Core/XmlHelper.cs +++ b/src/Libraries/SmartStore.Core/XmlHelper.cs @@ -120,7 +120,7 @@ public static DateTime DeserializeDateTime(string dateTime) /// /// Object type /// Object instance - /// XML + /// XML string public static string Serialize(T instance) { if (instance != null) @@ -136,11 +136,32 @@ public static string Serialize(T instance) return null; } + /// + /// Serializes an object instance to a XML formatted string + /// + /// Object instance + /// Object type + /// XML string + public static string Serialize(object instance, Type type) + { + if (instance != null) + { + using (var writer = new StringWriter()) + { + var xmlSerializer = new XmlSerializer(type); + + xmlSerializer.Serialize(writer, instance); + return writer.ToString(); + } + } + return null; + } + /// /// Deserializes a XML formatted string to an object instance /// /// Object type - /// XML + /// XML string /// Object instance public static T Deserialize(string xml) { @@ -156,6 +177,26 @@ public static T Deserialize(string xml) return (T)Activator.CreateInstance(typeof(T)); } + /// + /// Deserializes a XML formatted string to an object instance + /// + /// XML string + /// Object type + /// Object instance + public static object Deserialize(string xml, Type type) + { + if (xml.HasValue()) + { + using (var reader = new StringReader(xml)) + { + var serializer = new XmlSerializer(type); + + return serializer.Deserialize(reader); + } + } + return Activator.CreateInstance(type); + } + #endregion } } diff --git a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs index 22d4cc1c4f..c64b24cefe 100644 --- a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs @@ -14,6 +14,8 @@ public ExportProfileMap() this.Property(x => x.FolderName).IsRequired().HasMaxLength(100); this.Property(x => x.ProviderSystemName).IsRequired().HasMaxLength(4000); this.Property(x => x.Filtering).IsMaxLength(); + this.Property(x => x.Projection).IsMaxLength(); + this.Property(x => x.ProviderConfigData).IsMaxLength(); this.HasRequired(x => x.ScheduleTask) .WithMany() diff --git a/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.resx b/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.resx deleted file mode 100644 index c1ffae86af..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.Designer.cs index 24f974b961..ebbd4a40ae 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class ExportFramework : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201508040836122_ExportFramework"; } + get { return "201508051818404_ExportFramework"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.cs b/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.cs rename to src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.cs index b62177e5a4..af3d696b92 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201508040836122_ExportFramework.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.cs @@ -19,8 +19,9 @@ public override void Up() ProviderSystemName = c.String(nullable: false, maxLength: 4000), Enabled = c.Boolean(nullable: false), SchedulingTaskId = c.Int(nullable: false), - ProfileGuid = c.Guid(nullable: false), Filtering = c.String(), + Projection = c.String(), + ProviderConfigData = c.String(), Offset = c.Int(nullable: false), Limit = c.Int(nullable: false), BatchSize = c.Int(nullable: false), @@ -79,6 +80,11 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "There were no export profiles found.", "Es wurden keine Exportprofile gefunden."); + builder.AddOrUpdate("Admin.Configuration.Export.NoProviderConfigurationRequired", + "The export provider {0} requires no further configuration.", + "Der Export-Provider {0} bentigt keine weitergehende Konfiguration."); + + builder.AddOrUpdate("Admin.Configuration.Export.ProviderSystemName", "Provider", @@ -262,6 +268,19 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Kundengruppen", "Filter by customer roles.", "Nach Kundengruppen filtern."); + + + builder.AddOrUpdate("Admin.Configuration.Export.Projection.LanguageId", + "Language", + "Sprache", + "Specifies the language to be applied to the export.", + "Legt die auf den Export anzuwendende Sprache fest."); + + builder.AddOrUpdate("Admin.Configuration.Export.Projection.CurrencyId", + "Currency", + "Whrung", + "Specifies the currency to be applied to the export.", + "Legt die auf den Export anzuwendende Whrung fest."); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.resx b/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.resx new file mode 100644 index 0000000000..3219191ea2 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index bbd83bec0a..a203443917 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -332,9 +332,9 @@ 201507250039446_Merge2.cs - - - 201508040836122_ExportFramework.cs + + + 201508051818404_ExportFramework.cs @@ -633,8 +633,8 @@ 201507250039446_Merge2.cs - - 201508040836122_ExportFramework.cs + + 201508051818404_ExportFramework.cs diff --git a/src/Libraries/SmartStore.Services/DataExchange/IExportProvider.cs b/src/Libraries/SmartStore.Services/DataExchange/IExportProvider.cs index 318c0e2586..1f3877ae3a 100644 --- a/src/Libraries/SmartStore.Services/DataExchange/IExportProvider.cs +++ b/src/Libraries/SmartStore.Services/DataExchange/IExportProvider.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using SmartStore.Core.Domain; using SmartStore.Core.Domain.DataExchange; using SmartStore.Core.Plugins; @@ -7,11 +8,19 @@ namespace SmartStore.Services.DataExchange { public partial interface IExportProvider : IProvider, IUserEditable { - // TODO: a more complex result type is required. e.g. IEnumerable.... - MemoryStream Execute(ExportProfile profile); - ExportEntityType EntityType { get; } string FileType { get; } + + /// + /// Get configuration information + /// + /// The partial view name for the configuration + /// Type of the view model + /// Whether configuration is required + bool RequiresConfiguration(out string partialViewName, out Type modelType); + + // TODO: a more complex result type is required. e.g. IEnumerable.... + MemoryStream Execute(ExportProfile profile); } } diff --git a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs index b3058c31a8..7d4c8ab9e8 100644 --- a/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs +++ b/src/Libraries/SmartStore.Services/Messages/QueuedMessagesSendTask.cs @@ -26,7 +26,8 @@ public void Execute(TaskExecutionContext ctx) MaxSendTries = maxTries, PageIndex = i, PageSize = pageSize, - Expand = "Attachments" + Expand = "Attachments", + UnsentOnly = true }; var queuedEmails = _queuedEmailService.SearchEmails(q); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs index ce04e4a736..6f7ac50ab8 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs @@ -1,6 +1,11 @@ using System; +using System.Globalization; +using System.IO; using System.Linq; +using System.Text; using System.Web.Mvc; +using System.Web.Routing; +using System.Xml.Serialization; using SmartStore.Admin.Models.DataExchange; using SmartStore.Core; using SmartStore.Core.Domain; @@ -14,6 +19,8 @@ using SmartStore.Services.Catalog; using SmartStore.Services.Customers; using SmartStore.Services.DataExchange; +using SmartStore.Services.Directory; +using SmartStore.Services.Localization; using SmartStore.Services.Media; using SmartStore.Services.Security; using SmartStore.Web.Framework; @@ -34,6 +41,8 @@ public class ExportController : AdminControllerBase private readonly IManufacturerService _manufacturerService; private readonly IProductTagService _productTagService; private readonly ICustomerService _customerService; + private readonly ILanguageService _languageService; + private readonly ICurrencyService _currencyService; public ExportController( ICommonServices services, @@ -43,7 +52,9 @@ public ExportController( ICategoryService categoryService, IManufacturerService manufacturerService, IProductTagService productTagService, - ICustomerService customerService) + ICustomerService customerService, + ILanguageService languageService, + ICurrencyService currencyService) { _services = services; _exportService = exportService; @@ -53,56 +64,98 @@ public ExportController( _manufacturerService = manufacturerService; _productTagService = productTagService; _customerService = customerService; + _languageService = languageService; + _currencyService = currencyService; } - private void PrepareExportProfileModel(ExportProfileModel model, ExportProfile profile, Provider provider) + #region Utilities + + private string GetThumbnailUrl(Provider provider) { - model.Providing = new ExportProfileModel.Provider - { - SystemName = profile.ProviderSystemName - }; + var url = _pluginMediator.GetIconUrl(provider.Metadata); + + if (url.IsEmpty()) + url = _pictureService.GetDefaultPictureUrl(48); + else + url = Url.Content(url); + return url; + } + + private void PrepareExportProfileModel(ExportProfileModel model, ExportProfile profile, Provider provider) + { model.Id = profile.Id; model.Name = profile.Name; model.Enabled = profile.Enabled; model.SchedulingHours = profile.ScheduleTask.Seconds / 3600; + model.Provider = new ExportProfileModel.ProviderModel + { + SystemName = profile.ProviderSystemName + }; + if (provider != null) { - model.Providing.ThumbnailUrl = _pluginMediator.GetIconUrl(provider.Metadata); - - if (model.Providing.ThumbnailUrl.IsEmpty()) - model.Providing.ThumbnailUrl = _pictureService.GetDefaultPictureUrl(48); - else - model.Providing.ThumbnailUrl = Url.Content(model.Providing.ThumbnailUrl); - - model.Providing.Url = provider.Metadata.PluginDescriptor.Url; - model.Providing.ConfigurationUrl = Url.Action("ConfigurePlugin", new { systemName = provider.Metadata.SystemName }); - model.Providing.FriendlyName = _pluginMediator.GetLocalizedFriendlyName(provider.Metadata); - model.Providing.Author = provider.Metadata.PluginDescriptor.Author; - model.Providing.Version = provider.Metadata.PluginDescriptor.Version.ToString(); - model.Providing.Description = _pluginMediator.GetLocalizedDescription(provider.Metadata); - - model.Providing.EntityType = provider.Value.EntityType; - model.Providing.EntityTypeName = T("Enums.SmartStore.Core.Domain.ExportEntityType." + provider.Value.EntityType.ToString()); - model.Providing.FileType = provider.Value.FileType.ToUpper(); + model.Provider.ThumbnailUrl = GetThumbnailUrl(provider); + + model.Provider.Url = provider.Metadata.PluginDescriptor.Url; + model.Provider.ConfigurationUrl = Url.Action("ConfigurePlugin", new { systemName = provider.Metadata.SystemName }); + model.Provider.FriendlyName = _pluginMediator.GetLocalizedFriendlyName(provider.Metadata); + model.Provider.Author = provider.Metadata.PluginDescriptor.Author; + model.Provider.Version = provider.Metadata.PluginDescriptor.Version.ToString(); + model.Provider.Description = _pluginMediator.GetLocalizedDescription(provider.Metadata); + + model.Provider.EntityType = provider.Value.EntityType; + model.Provider.EntityTypeName = T("Enums.SmartStore.Core.Domain.ExportEntityType." + provider.Value.EntityType.ToString()); + model.Provider.FileType = provider.Value.FileType.ToUpper(); } } private void PrepareExportProfileModelForEdit(ExportProfileModel model, ExportProfile profile, Provider provider) { var filter = XmlHelper.Deserialize(profile.Filtering); + var projection = XmlHelper.Deserialize(profile.Projection); var allStores = _services.StoreService.GetAllStores(); + var allLanguages = _languageService.GetAllLanguages(true); + var allCurrencies = _currencyService.GetAllCurrencies(true); model.AllString = T("Admin.Common.All"); - //model.UnspecifiedString = T("Common.Unspecified"); + model.UnspecifiedString = T("Common.Unspecified"); model.StoreCount = allStores.Count; model.Offset = profile.Offset; model.Limit = profile.Limit; model.BatchSize = profile.BatchSize; model.PerStore = profile.PerStore; + if (provider != null) + { + string partialName; + Type dataType; + if (provider.Value.RequiresConfiguration(out partialName, out dataType)) + { + model.Provider.ConfigPartialViewName = partialName; + model.Provider.ConfigDataType = dataType; + model.Provider.ConfigData = XmlHelper.Deserialize(profile.ProviderConfigData, dataType); + } + } + + // projection + model.Projection = new ExportProjectionModel + { + LanguageId = projection.LanguageId, + CurrencyId = projection.CurrencyId + }; + + model.Projection.AvailableLanguages = allLanguages + .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }) + .ToList(); + + model.Projection.AvailableCurrencies = allCurrencies + .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }) + .ToList(); + + // filtering Action initModelBase = x => { x.StoreId = filter.StoreId; @@ -114,14 +167,14 @@ private void PrepareExportProfileModelForEdit(ExportProfileModel model, ExportPr .ToList(); }; - if (model.Providing.EntityType == ExportEntityType.Product) + if (model.Provider.EntityType == ExportEntityType.Product) { var allCategories = _categoryService.GetAllCategories(showHidden: true); var mappedCategories = allCategories.ToDictionary(x => x.Id); var allManufacturers = _manufacturerService.GetAllManufacturers(true); var allProductTags = _productTagService.GetAllProductTags(); - model.ProductFiltering = new ExportProductFilterModel + model.ProductFilter = new ExportProductFilterModel { PriceMinimum = filter.PriceMinimum, PriceMaximum = filter.PriceMaximum, @@ -137,27 +190,27 @@ private void PrepareExportProfileModelForEdit(ExportProfileModel model, ExportPr ProductType = filter.ProductType }; - model.ProductFiltering.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList(); + model.ProductFilter.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList(); - model.ProductFiltering.AvailableCategories = allCategories + model.ProductFilter.AvailableCategories = allCategories .Select(x => new SelectListItem { Text = x.GetCategoryNameWithPrefix(_categoryService, mappedCategories), Value = x.Id.ToString() }) .ToList(); - model.ProductFiltering.AvailableManufacturers = allManufacturers + model.ProductFilter.AvailableManufacturers = allManufacturers .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }) .ToList(); - model.ProductFiltering.AvailableProductTags = allProductTags + model.ProductFilter.AvailableProductTags = allProductTags .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }) .ToList(); - initModelBase(model.ProductFiltering); + initModelBase(model.ProductFilter); } - else if (model.Providing.EntityType == ExportEntityType.Order) + else if (model.Provider.EntityType == ExportEntityType.Order) { var allCustomerRoles = _customerService.GetAllCustomerRoles(true); - model.OrderFiltering = new ExportOrderFilterModel + model.OrderFilter = new ExportOrderFilterModel { OrderStatus = filter.OrderStatus, PaymentStatus = filter.PaymentStatus, @@ -165,20 +218,22 @@ private void PrepareExportProfileModelForEdit(ExportProfileModel model, ExportPr CustomerRoleIds = filter.CustomerRoleIds }; - model.OrderFiltering.AvailableOrderStates = OrderStatus.Pending.ToSelectList(false).ToList(); - model.OrderFiltering.AvailablePaymentStates = PaymentStatus.Pending.ToSelectList(false).ToList(); - model.OrderFiltering.AvailableShippingStates = ShippingStatus.NotYetShipped.ToSelectList(false).ToList(); + model.OrderFilter.AvailableOrderStates = OrderStatus.Pending.ToSelectList(false).ToList(); + model.OrderFilter.AvailablePaymentStates = PaymentStatus.Pending.ToSelectList(false).ToList(); + model.OrderFilter.AvailableShippingStates = ShippingStatus.NotYetShipped.ToSelectList(false).ToList(); - model.OrderFiltering.AvailableCustomerRoles = allCustomerRoles + model.OrderFilter.AvailableCustomerRoles = allCustomerRoles .OrderBy(x => x.Name) .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }) .ToList(); - initModelBase(model.OrderFiltering); + initModelBase(model.OrderFilter); } } - public ActionResult Index() + #endregion + + public ActionResult Index() { return RedirectToAction("List"); } @@ -221,9 +276,9 @@ public ActionResult Create() if (_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) { var model = new ExportProfileModel(); - model.Providing = new ExportProfileModel.Provider(); + model.Provider = new ExportProfileModel.ProviderModel(); - model.Providing.AvailableExportProviders = _exportService.LoadAllExportProviders() + model.Provider.AvailableExportProviders = _exportService.LoadAllExportProviders() .Select(x => { var item = new SelectListItem @@ -247,9 +302,9 @@ public ActionResult Create(ExportProfileModel model) if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) return AccessDeniedView(); - if (model.Providing.SystemName.HasValue()) + if (model.Provider.SystemName.HasValue()) { - var provider = _exportService.LoadProvider(model.Providing.SystemName); + var provider = _exportService.LoadProvider(model.Provider.SystemName); if (provider != null) { var profile = _exportService.InsertExportProfile(provider); @@ -258,7 +313,7 @@ public ActionResult Create(ExportProfileModel model) } } - NotifyError(T("Admin.Configuration.Export.ProviderSystemName.Validate", model.Providing.SystemName.NaIfEmpty())); + NotifyError(T("Admin.Configuration.Export.ProviderSystemName.Validate", model.Provider.SystemName.NaIfEmpty())); return RedirectToAction("List"); } @@ -282,9 +337,9 @@ public ActionResult Edit(int id) return View(model); } - [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] - [FormValueRequired("save", "save-continue")] - public ActionResult Edit(ExportProfileModel model, bool continueEditing) + [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] + [FormValueRequired("save", "save-continue")] + public ActionResult Edit(ExportProfileModel model, bool continueEditing) { if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) return AccessDeniedView(); @@ -302,8 +357,31 @@ public ActionResult Edit(ExportProfileModel model, bool continueEditing) return View(model); } - ExportFilter filter = null; + profile.Name = model.Name; + profile.Enabled = model.Enabled; + profile.ScheduleTask.Seconds = model.SchedulingHours * 3600; + profile.Offset = model.Offset; + profile.Limit = model.Limit; + profile.BatchSize = model.BatchSize; + profile.PerStore = model.PerStore; + + if (profile.Name.IsEmpty()) + profile.Name = provider.Metadata.FriendlyName; + + if (profile.Name.IsEmpty()) + profile.Name = provider.Metadata.SystemName; + + // projection + var projection = new ExportProjection + { + LanguageId = model.Projection.LanguageId, + CurrencyId = model.Projection.CurrencyId + }; + + profile.Projection = XmlHelper.Serialize(projection); + // filtering + ExportFilter filter = null; Action getFromModelBase = x => { filter.StoreId = x.StoreId ?? 0; @@ -311,54 +389,57 @@ public ActionResult Edit(ExportProfileModel model, bool continueEditing) filter.CreatedTo = x.CreatedTo; }; - if (model.ProductFiltering != null && provider.Value.EntityType == ExportEntityType.Product) + if (model.ProductFilter != null && provider.Value.EntityType == ExportEntityType.Product) { filter = new ExportFilter { - PriceMinimum = model.ProductFiltering.PriceMinimum, - PriceMaximum = model.ProductFiltering.PriceMaximum, - AvailabilityMinimum = model.ProductFiltering.AvailabilityMinimum, - AvailabilityMaximum = model.ProductFiltering.AvailabilityMaximum, - IsPublished = model.ProductFiltering.IsPublished, - CategoryIds = model.ProductFiltering.CategoryIds, - WithoutCategories = model.ProductFiltering.WithoutCategories, - ManufacturerIds = model.ProductFiltering.ManufacturerIds, - WithoutManufacturers = model.ProductFiltering.WithoutManufacturers, - ProductTagIds = model.ProductFiltering.ProductTagIds, - FeaturedProducts = model.ProductFiltering.FeaturedProducts, - ProductType = model.ProductFiltering.ProductType + PriceMinimum = model.ProductFilter.PriceMinimum, + PriceMaximum = model.ProductFilter.PriceMaximum, + AvailabilityMinimum = model.ProductFilter.AvailabilityMinimum, + AvailabilityMaximum = model.ProductFilter.AvailabilityMaximum, + IsPublished = model.ProductFilter.IsPublished, + CategoryIds = model.ProductFilter.CategoryIds, + WithoutCategories = model.ProductFilter.WithoutCategories, + ManufacturerIds = model.ProductFilter.ManufacturerIds, + WithoutManufacturers = model.ProductFilter.WithoutManufacturers, + ProductTagIds = model.ProductFilter.ProductTagIds, + FeaturedProducts = model.ProductFilter.FeaturedProducts, + ProductType = model.ProductFilter.ProductType }; - getFromModelBase(model.ProductFiltering); + getFromModelBase(model.ProductFilter); } - else if (model.OrderFiltering != null && provider.Value.EntityType == ExportEntityType.Order) + else if (model.OrderFilter != null && provider.Value.EntityType == ExportEntityType.Order) { filter = new ExportFilter { - OrderStatus = model.OrderFiltering.OrderStatus, - PaymentStatus = model.OrderFiltering.PaymentStatus, - ShippingStatus = model.OrderFiltering.ShippingStatus, - CustomerRoleIds = model.OrderFiltering.CustomerRoleIds + OrderStatus = model.OrderFilter.OrderStatus, + PaymentStatus = model.OrderFilter.PaymentStatus, + ShippingStatus = model.OrderFilter.ShippingStatus, + CustomerRoleIds = model.OrderFilter.CustomerRoleIds }; - getFromModelBase(model.OrderFiltering); + getFromModelBase(model.OrderFilter); } - profile.Name = model.Name; - profile.Enabled = model.Enabled; - profile.ScheduleTask.Seconds = model.SchedulingHours * 3600; - profile.Offset = model.Offset; - profile.Limit = model.Limit; - profile.BatchSize = model.BatchSize; - profile.PerStore = model.PerStore; - - if (profile.Name.IsEmpty()) - profile.Name = provider.Metadata.FriendlyName; + profile.Filtering = XmlHelper.Serialize(filter); - if (profile.Name.IsEmpty()) - profile.Name = provider.Metadata.SystemName; + // provider configuration + profile.ProviderConfigData = null; + try + { + string partialName; + Type dataType; - profile.Filtering = XmlHelper.Serialize(filter); + if (provider.Value.RequiresConfiguration(out partialName, out dataType) && model.CustomProperties.ContainsKey("ProviderConfigData")) + { + profile.ProviderConfigData = XmlHelper.Serialize(model.CustomProperties["ProviderConfigData"], dataType); + } + } + catch (Exception exc) + { + NotifyError(exc); + } _exportService.UpdateExportProfile(profile); @@ -393,6 +474,27 @@ public ActionResult DeleteConfirmed(int id) return RedirectToAction("Edit", new { id = profile.Id }); } + public ActionResult Preview(int id) + { + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + var profile = _exportService.GetExportProfileById(id); + if (profile == null) + return RedirectToAction("List"); + + var provider = _exportService.LoadProvider(profile.ProviderSystemName); + + var model = new ExportPreviewModel + { + Id = profile.Id, + Name = profile.Name, + ThumbnailUrl = GetThumbnailUrl(provider) + }; + + return View(model); + } + public ActionResult Execute(int id) { return null; diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs index ca812df0b6..3294830cb9 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs @@ -9,7 +9,7 @@ namespace SmartStore.Admin.Models.DataExchange { - public class ExportFilterModelBase + public abstract class ExportFilterModelBase { [SmartResourceDisplayName("Admin.Configuration.Export.Filter.StoreId")] public int? StoreId { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportPreviewModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportPreviewModel.cs new file mode 100644 index 0000000000..d9aa966dcb --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportPreviewModel.cs @@ -0,0 +1,10 @@ +using SmartStore.Web.Framework.Mvc; + +namespace SmartStore.Admin.Models.DataExchange +{ + public class ExportPreviewModel : EntityModelBase + { + public string Name { get; set; } + public string ThumbnailUrl { get; set; } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs index 4dd20aa2e1..4638c6fd0e 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; +using System.Dynamic; using System.Web.Mvc; -using SmartStore.Core.Domain.Catalog; +using System.Web.Routing; using SmartStore.Core.Domain.DataExchange; -using SmartStore.Core.Domain.Orders; -using SmartStore.Core.Domain.Payments; -using SmartStore.Core.Domain.Shipping; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Mvc; @@ -13,6 +11,10 @@ namespace SmartStore.Admin.Models.DataExchange { public partial class ExportProfileModel : EntityModelBase { + public int StoreCount { get; set; } + public string AllString { get; set; } + public string UnspecifiedString { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Export.Name")] public string Name { get; set; } @@ -38,17 +40,20 @@ public partial class ExportProfileModel : EntityModelBase [SmartResourceDisplayName("Admin.Configuration.Export.PerStore")] public bool PerStore { get; set; } - public Provider Providing { get; set; } + public ProviderModel Provider { get; set; } - public ExportProductFilterModel ProductFiltering { get; set; } - public ExportOrderFilterModel OrderFiltering { get; set; } + public ExportProductFilterModel ProductFilter { get; set; } + public ExportOrderFilterModel OrderFilter { get; set; } - public int StoreCount { get; set; } - public string AllString { get; set; } + public ExportProjectionModel Projection { get; set; } - public class Provider + public class ProviderModel { + public string ConfigPartialViewName { get; set; } + public Type ConfigDataType { get; set; } + public object ConfigData { get; set; } + [SmartResourceDisplayName("Common.Image")] public string ThumbnailUrl { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProjectionModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProjectionModel.cs new file mode 100644 index 0000000000..0cd5ddd22f --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProjectionModel.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Web.Mvc; +using SmartStore.Web.Framework; + +namespace SmartStore.Admin.Models.DataExchange +{ + public class ExportProjectionModel + { + [SmartResourceDisplayName("Admin.Configuration.Export.Projection.LanguageId")] + public int LanguageId { get; set; } + public List AvailableLanguages { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Projection.CurrencyId")] + public int CurrencyId { get; set; } + public List AvailableCurrencies { get; set; } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index 0d06106427..1fb41c6bf1 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -248,6 +248,8 @@ + + @@ -504,6 +506,7 @@ + diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml index e8b3dc3b2d..3eb5eac1ea 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/Create.cshtml @@ -5,16 +5,16 @@ }
    - @if(Model.Providing.AvailableExportProviders.Count > 0) + @if(Model.Provider.AvailableExportProviders.Count > 0) {
    - @Html.SmartLabelFor(model => model.Providing.SystemName) + @Html.SmartLabelFor(model => model.Provider.SystemName) - @Html.DropDownListFor(model => model.Providing.SystemName, Model.Providing.AvailableExportProviders) + @Html.DropDownListFor(model => model.Provider.SystemName, Model.Provider.AvailableExportProviders)
    diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml index ad73a907f4..f825f3b48a 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml @@ -8,39 +8,39 @@ @using (Html.BeginForm()) { - @Html.HiddenFor(model => model.Id) +
    + @Html.HiddenFor(model => model.Id) -
    -
    - @if (Model.Providing.ThumbnailUrl.HasValue()) - { - - } -   - @title - @Model.Name @Html.ActionLink("(" + T("Admin.Common.BackToList") + ")", "List") +
    +
    + +   + @title - @Model.Name @Html.ActionLink("(" + T("Admin.Common.BackToList") + ")", "List") +
    +
    +  @T("Admin.Common.Preview") + + + +
    -
    - - - -
    -
    - - @Html.ValidationSummary(false) - @Html.SmartStore().TabStrip().Name("export-profile-edit").Items(x => - { - x.Add().Text(T("Common.General").Text).Content(TabGeneral()).Selected(true); - x.Add().Text(T("Common.Filter").Text).Content(TabFilter()); - x.Add().Text(T("Common.Projection").Text).Content(TabProjection()); - x.Add().Text(T("Common.Partition").Text).Content(TabPartition()); - x.Add().Text(T("Admin.Configuration").Text).Content(TabConfiguration()); - x.Add().Text(T("Common.Publishing").Text).Content(TabDeployment()); + @Html.ValidationSummary(false) - EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "export-profile-edit", this.Html, this.Model)); - }) + @Html.SmartStore().TabStrip().Name("export-profile-edit").Items(x => + { + x.Add().Text(T("Common.General").Text).Content(TabGeneral()).Selected(true); + x.Add().Text(T("Common.Partition").Text).Content(TabPartition()); + x.Add().Text(T("Common.Filter").Text).Content(TabFilter()); + x.Add().Text(T("Common.Projection").Text).Content(TabProjection()); + x.Add().Text(T("Admin.Configuration").Text).Content(TabConfiguration()); + x.Add().Text(T("Common.Publishing").Text).Content(TabDeployment()); + + EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "export-profile-edit", this.Html, this.Model)); + }) +
    } @helper TabGeneral() @@ -48,64 +48,64 @@ - @if (Model.Providing.Url.HasValue()) + @if (Model.Provider.Url.HasValue()) { } + +
    - @Html.SmartLabelFor(model => model.Providing.FriendlyName) + @Html.SmartLabelFor(x => x.Provider.FriendlyName) - @Model.Providing.FriendlyName.NaIfEmpty() - (@(Model.Providing.SystemName.NaIfEmpty())) + @Model.Provider.FriendlyName.NaIfEmpty() + (@(Model.Provider.SystemName.NaIfEmpty()))
    - @Html.SmartLabelFor(model => model.Providing.Author) + @Html.SmartLabelFor(x => x.Provider.Author) - @Html.DisplayFor(model => model.Providing.Author) + @Html.DisplayFor(x => x.Provider.Author)
    - @Html.SmartLabelFor(model => model.Providing.Version) + @Html.SmartLabelFor(x => x.Provider.Version) - @Html.DisplayFor(model => model.Providing.Version) + @Html.DisplayFor(x => x.Provider.Version)
    - @Html.SmartLabelFor(model => model.Providing.Url) + @Html.SmartLabelFor(x => x.Provider.Url) - @Model.Providing.Url + @Model.Provider.Url
    - @Html.SmartLabelFor(model => model.Providing.EntityTypeName) + @Html.SmartLabelFor(x => x.Provider.EntityTypeName) - @Html.DisplayFor(model => model.Providing.EntityTypeName) + @Html.DisplayFor(x => x.Provider.EntityTypeName)
    - @Html.SmartLabelFor(model => model.Providing.FileType) + @Html.SmartLabelFor(x => x.Provider.FileType) - @Html.DisplayFor(model => model.Providing.FileType) + @Html.DisplayFor(x => x.Provider.FileType)
    - @Html.SmartLabelFor(model => model.Providing.Description) + @Html.SmartLabelFor(x => x.Provider.Description) - @if (Model.Providing.Description.HasValue()) + @if (Model.Provider.Description.HasValue()) { - @Html.Raw(Model.Providing.Description) + @Html.Raw(Model.Provider.Description) } else { @@ -120,29 +120,71 @@
    - @Html.SmartLabelFor(model => model.Name) + @Html.SmartLabelFor(x => x.Name) - @Html.EditorFor(model => model.Name) - @Html.ValidationMessageFor(model => model.Name) + @Html.EditorFor(x => x.Name) + @Html.ValidationMessageFor(x => x.Name)
    - @Html.SmartLabelFor(model => model.Enabled) + @Html.SmartLabelFor(x => x.Enabled) - @Html.EditorFor(model => model.Enabled) - @Html.ValidationMessageFor(model => model.Enabled) + @Html.EditorFor(x => x.Enabled) + @Html.ValidationMessageFor(x => x.Enabled)
    - @Html.SmartLabelFor(model => model.SchedulingHours) + @Html.SmartLabelFor(x => x.SchedulingHours) - @Html.EditorFor(model => model.SchedulingHours) - @Html.ValidationMessageFor(model => model.SchedulingHours) + @Html.EditorFor(x => x.SchedulingHours) + @Html.ValidationMessageFor(x => x.SchedulingHours) +
    +} + +@helper TabPartition() +{ + + + + + + + + + + + + + + + +
    + @Html.SmartLabelFor(x => x.Offset) + + @Html.EditorFor(x => x.Offset) + @Html.ValidationMessageFor(x => x.Offset) +
    + @Html.SmartLabelFor(x => x.Limit) + + @Html.EditorFor(x => x.Limit) + @Html.ValidationMessageFor(x => x.Limit) +
    + @Html.SmartLabelFor(x => x.BatchSize) + + @Html.EditorFor(x => x.BatchSize) + @Html.ValidationMessageFor(x => x.BatchSize) +
    + @Html.SmartLabelFor(x => x.PerStore) + + @Html.EditorFor(x => x.PerStore) + @Html.ValidationMessageFor(x => x.PerStore)
    @@ -151,226 +193,226 @@ @helper TabFilter() { - @if (Model.ProductFiltering != null) + @if (Model.ProductFilter != null) { if (Model.StoreCount > 1) { } } - else if (Model.OrderFiltering != null) + else if (Model.OrderFilter != null) { if (Model.StoreCount > 1) { } } @@ -378,46 +420,24 @@ } @helper TabProjection() -{ -} - -@helper TabPartition() {
    - @Html.SmartLabelFor(model => model.ProductFiltering.StoreId) + @Html.SmartLabelFor(x => x.ProductFilter.StoreId) - @Html.DropDownListFor(model => model.ProductFiltering.StoreId, Model.ProductFiltering.AvailableStores, Model.AllString) - @Html.ValidationMessageFor(model => model.ProductFiltering.StoreId) + @Html.DropDownListFor(x => x.ProductFilter.StoreId, Model.ProductFilter.AvailableStores, Model.AllString) + @Html.ValidationMessageFor(x => x.ProductFilter.StoreId)
    - @Html.SmartLabelFor(model => model.ProductFiltering.CreatedFrom) + @Html.SmartLabelFor(x => x.ProductFilter.CreatedFrom) - @Html.EditorFor(model => model.ProductFiltering.CreatedFrom) - @Html.ValidationMessageFor(model => model.ProductFiltering.CreatedFrom) + @Html.EditorFor(x => x.ProductFilter.CreatedFrom) + @Html.ValidationMessageFor(x => x.ProductFilter.CreatedFrom)
    - @Html.SmartLabelFor(model => model.ProductFiltering.CreatedTo) + @Html.SmartLabelFor(x => x.ProductFilter.CreatedTo) - @Html.EditorFor(model => model.ProductFiltering.CreatedTo) - @Html.ValidationMessageFor(model => model.ProductFiltering.CreatedTo) + @Html.EditorFor(x => x.ProductFilter.CreatedTo) + @Html.ValidationMessageFor(x => x.ProductFilter.CreatedTo)
    - @Html.SmartLabelFor(model => model.ProductFiltering.ProductType) + @Html.SmartLabelFor(x => x.ProductFilter.ProductType) - @Html.DropDownListFor(model => model.ProductFiltering.ProductType, Model.ProductFiltering.AvailableProductTypes, Model.AllString) + @Html.DropDownListFor(x => x.ProductFilter.ProductType, Model.ProductFilter.AvailableProductTypes, Model.AllString)
    - @Html.SmartLabelFor(model => model.ProductFiltering.IsPublished) + @Html.SmartLabelFor(x => x.ProductFilter.IsPublished) - @Html.EditorFor(model => model.ProductFiltering.IsPublished) - @Html.ValidationMessageFor(model => model.ProductFiltering.IsPublished) + @Html.EditorFor(x => x.ProductFilter.IsPublished) + @Html.ValidationMessageFor(x => x.ProductFilter.IsPublished)
    - @Html.SmartLabelFor(model => model.ProductFiltering.PriceMinimum) + @Html.SmartLabelFor(x => x.ProductFilter.PriceMinimum) - @Html.EditorFor(model => model.ProductFiltering.PriceMinimum) - @Html.ValidationMessageFor(model => model.ProductFiltering.PriceMinimum) + @Html.EditorFor(x => x.ProductFilter.PriceMinimum) + @Html.ValidationMessageFor(x => x.ProductFilter.PriceMinimum)
    - @Html.SmartLabelFor(model => model.ProductFiltering.PriceMaximum) + @Html.SmartLabelFor(x => x.ProductFilter.PriceMaximum) - @Html.EditorFor(model => model.ProductFiltering.PriceMaximum) - @Html.ValidationMessageFor(model => model.ProductFiltering.PriceMaximum) + @Html.EditorFor(x => x.ProductFilter.PriceMaximum) + @Html.ValidationMessageFor(x => x.ProductFilter.PriceMaximum)
    - @Html.SmartLabelFor(model => model.ProductFiltering.AvailabilityMinimum) + @Html.SmartLabelFor(x => x.ProductFilter.AvailabilityMinimum) - @Html.EditorFor(model => model.ProductFiltering.AvailabilityMinimum) - @Html.ValidationMessageFor(model => model.ProductFiltering.AvailabilityMinimum) + @Html.EditorFor(x => x.ProductFilter.AvailabilityMinimum) + @Html.ValidationMessageFor(x => x.ProductFilter.AvailabilityMinimum)
    - @Html.SmartLabelFor(model => model.ProductFiltering.AvailabilityMaximum) + @Html.SmartLabelFor(x => x.ProductFilter.AvailabilityMaximum) - @Html.EditorFor(model => model.ProductFiltering.AvailabilityMaximum) - @Html.ValidationMessageFor(model => model.ProductFiltering.AvailabilityMaximum) + @Html.EditorFor(x => x.ProductFilter.AvailabilityMaximum) + @Html.ValidationMessageFor(x => x.ProductFilter.AvailabilityMaximum)
    - @Html.SmartLabelFor(model => model.ProductFiltering.WithoutCategories) + @Html.SmartLabelFor(x => x.ProductFilter.WithoutCategories) - @Html.EditorFor(model => model.ProductFiltering.WithoutCategories) - @Html.ValidationMessageFor(model => model.ProductFiltering.WithoutCategories) + @Html.EditorFor(x => x.ProductFilter.WithoutCategories) + @Html.ValidationMessageFor(x => x.ProductFilter.WithoutCategories)
    - @Html.SmartLabelFor(model => model.ProductFiltering.CategoryIds) + @Html.SmartLabelFor(x => x.ProductFilter.CategoryIds) - @Html.ListBoxFor(model => model.ProductFiltering.CategoryIds, - new MultiSelectList(Model.ProductFiltering.AvailableCategories, "Value", "Text"), + @Html.ListBoxFor(x => x.ProductFilter.CategoryIds, + new MultiSelectList(Model.ProductFilter.AvailableCategories, "Value", "Text"), new { multiple = "multiple", @class = "control-xlarge" }) - @Html.ValidationMessageFor(model => model.ProductFiltering.CategoryIds) + @Html.ValidationMessageFor(x => x.ProductFilter.CategoryIds)
    - @Html.SmartLabelFor(model => model.ProductFiltering.WithoutManufacturers) + @Html.SmartLabelFor(x => x.ProductFilter.WithoutManufacturers) - @Html.EditorFor(model => model.ProductFiltering.WithoutManufacturers) - @Html.ValidationMessageFor(model => model.ProductFiltering.WithoutManufacturers) + @Html.EditorFor(x => x.ProductFilter.WithoutManufacturers) + @Html.ValidationMessageFor(x => x.ProductFilter.WithoutManufacturers)
    - @Html.SmartLabelFor(model => model.ProductFiltering.ManufacturerIds) + @Html.SmartLabelFor(x => x.ProductFilter.ManufacturerIds) - @Html.ListBoxFor(model => model.ProductFiltering.ManufacturerIds, - new MultiSelectList(Model.ProductFiltering.AvailableManufacturers, "Value", "Text"), + @Html.ListBoxFor(x => x.ProductFilter.ManufacturerIds, + new MultiSelectList(Model.ProductFilter.AvailableManufacturers, "Value", "Text"), new { multiple = "multiple", @class = "control-xlarge" }) - @Html.ValidationMessageFor(model => model.ProductFiltering.ManufacturerIds) + @Html.ValidationMessageFor(x => x.ProductFilter.ManufacturerIds)
    - @Html.SmartLabelFor(model => model.ProductFiltering.ProductTagIds) + @Html.SmartLabelFor(x => x.ProductFilter.ProductTagIds) - @Html.ListBoxFor(model => model.ProductFiltering.ProductTagIds, - new MultiSelectList(Model.ProductFiltering.AvailableProductTags, "Value", "Text"), + @Html.ListBoxFor(x => x.ProductFilter.ProductTagIds, + new MultiSelectList(Model.ProductFilter.AvailableProductTags, "Value", "Text"), new { multiple = "multiple", @class = "control-xlarge" }) - @Html.ValidationMessageFor(model => model.ProductFiltering.ProductTagIds) + @Html.ValidationMessageFor(x => x.ProductFilter.ProductTagIds)
    - @Html.SmartLabelFor(model => model.ProductFiltering.FeaturedProducts) + @Html.SmartLabelFor(x => x.ProductFilter.FeaturedProducts) - @Html.EditorFor(model => model.ProductFiltering.FeaturedProducts) - @Html.ValidationMessageFor(model => model.ProductFiltering.FeaturedProducts) + @Html.EditorFor(x => x.ProductFilter.FeaturedProducts) + @Html.ValidationMessageFor(x => x.ProductFilter.FeaturedProducts)
    - @Html.SmartLabelFor(model => model.OrderFiltering.StoreId) + @Html.SmartLabelFor(x => x.OrderFilter.StoreId) - @Html.DropDownListFor(model => model.OrderFiltering.StoreId, Model.OrderFiltering.AvailableStores, Model.AllString) - @Html.ValidationMessageFor(model => model.OrderFiltering.StoreId) + @Html.DropDownListFor(x => x.OrderFilter.StoreId, Model.OrderFilter.AvailableStores, Model.AllString) + @Html.ValidationMessageFor(x => x.OrderFilter.StoreId)
    - @Html.SmartLabelFor(model => model.OrderFiltering.CreatedFrom) + @Html.SmartLabelFor(x => x.OrderFilter.CreatedFrom) - @Html.EditorFor(model => model.OrderFiltering.CreatedFrom) - @Html.ValidationMessageFor(model => model.OrderFiltering.CreatedFrom) + @Html.EditorFor(x => x.OrderFilter.CreatedFrom) + @Html.ValidationMessageFor(x => x.OrderFilter.CreatedFrom)
    - @Html.SmartLabelFor(model => model.OrderFiltering.CreatedTo) + @Html.SmartLabelFor(x => x.OrderFilter.CreatedTo) - @Html.EditorFor(model => model.OrderFiltering.CreatedTo) - @Html.ValidationMessageFor(model => model.OrderFiltering.CreatedTo) + @Html.EditorFor(x => x.OrderFilter.CreatedTo) + @Html.ValidationMessageFor(x => x.OrderFilter.CreatedTo)
    - @Html.SmartLabelFor(model => model.OrderFiltering.OrderStatus) + @Html.SmartLabelFor(x => x.OrderFilter.OrderStatus) - @Html.ListBoxFor(model => model.OrderFiltering.OrderStatus, - new MultiSelectList(Model.OrderFiltering.AvailableOrderStates, "Value", "Text"), + @Html.ListBoxFor(x => x.OrderFilter.OrderStatus, + new MultiSelectList(Model.OrderFilter.AvailableOrderStates, "Value", "Text"), new { multiple = "multiple", @class = "control-xlarge" }) - @Html.ValidationMessageFor(model => model.OrderFiltering.OrderStatus) + @Html.ValidationMessageFor(x => x.OrderFilter.OrderStatus)
    - @Html.SmartLabelFor(model => model.OrderFiltering.PaymentStatus) + @Html.SmartLabelFor(x => x.OrderFilter.PaymentStatus) - @Html.ListBoxFor(model => model.OrderFiltering.PaymentStatus, - new MultiSelectList(Model.OrderFiltering.AvailablePaymentStates, "Value", "Text"), + @Html.ListBoxFor(x => x.OrderFilter.PaymentStatus, + new MultiSelectList(Model.OrderFilter.AvailablePaymentStates, "Value", "Text"), new { multiple = "multiple", @class = "control-xlarge" }) - @Html.ValidationMessageFor(model => model.OrderFiltering.PaymentStatus) + @Html.ValidationMessageFor(x => x.OrderFilter.PaymentStatus)
    - @Html.SmartLabelFor(model => model.OrderFiltering.ShippingStatus) + @Html.SmartLabelFor(x => x.OrderFilter.ShippingStatus) - @Html.ListBoxFor(model => model.OrderFiltering.ShippingStatus, - new MultiSelectList(Model.OrderFiltering.AvailableShippingStates, "Value", "Text"), + @Html.ListBoxFor(x => x.OrderFilter.ShippingStatus, + new MultiSelectList(Model.OrderFilter.AvailableShippingStates, "Value", "Text"), new { multiple = "multiple", @class = "control-xlarge" }) - @Html.ValidationMessageFor(model => model.OrderFiltering.ShippingStatus) + @Html.ValidationMessageFor(x => x.OrderFilter.ShippingStatus)
    - @Html.SmartLabelFor(model => model.OrderFiltering.CustomerRoleIds) + @Html.SmartLabelFor(x => x.OrderFilter.CustomerRoleIds) - @Html.ListBoxFor(model => model.OrderFiltering.CustomerRoleIds, - new MultiSelectList(Model.OrderFiltering.AvailableCustomerRoles, "Value", "Text"), + @Html.ListBoxFor(x => x.OrderFilter.CustomerRoleIds, + new MultiSelectList(Model.OrderFilter.AvailableCustomerRoles, "Value", "Text"), new { multiple = "multiple", @class = "control-xlarge" }) - @Html.ValidationMessageFor(model => model.OrderFiltering.CustomerRoleIds) + @Html.ValidationMessageFor(x => x.OrderFilter.CustomerRoleIds)
    - - - - - - - -
    - @Html.SmartLabelFor(model => model.Offset) - - @Html.EditorFor(model => model.Offset) - @Html.ValidationMessageFor(model => model.Offset) -
    - @Html.SmartLabelFor(model => model.Limit) - - @Html.EditorFor(model => model.Limit) - @Html.ValidationMessageFor(model => model.Limit) -
    - @Html.SmartLabelFor(model => model.BatchSize) + @Html.SmartLabelFor(x => x.Projection.LanguageId) - @Html.EditorFor(model => model.BatchSize) - @Html.ValidationMessageFor(model => model.BatchSize) + @Html.DropDownListFor(x => x.Projection.LanguageId, Model.Projection.AvailableLanguages, Model.UnspecifiedString) + @Html.ValidationMessageFor(x => x.Projection.LanguageId)
    - @Html.SmartLabelFor(model => model.PerStore) + @Html.SmartLabelFor(x => x.Projection.CurrencyId) - @Html.EditorFor(model => model.PerStore) - @Html.ValidationMessageFor(model => model.PerStore) + @Html.DropDownListFor(x => x.Projection.CurrencyId, Model.Projection.AvailableCurrencies, Model.UnspecifiedString) + @Html.ValidationMessageFor(x => x.Projection.CurrencyId)
    @@ -425,6 +445,23 @@ @helper TabConfiguration() { +
    +
    + @if (Model.Provider.ConfigPartialViewName.HasValue()) + { + var viewData = new ViewDataDictionary(); + viewData.TemplateInfo.HtmlFieldPrefix = "CustomProperties[ProviderConfigData]"; + @Html.Hidden("CustomProperties[ProviderConfigData].__Type__", Model.Provider.ConfigDataType.AssemblyQualifiedName) + @Html.Partial(Model.Provider.ConfigPartialViewName, Model.Provider.ConfigData, viewData) + } + else + { +
    + @Html.Raw(T("Admin.Configuration.Export.NoProviderConfigurationRequired", Model.Provider.FriendlyName.NaIfEmpty())) +
    + } +
    +
    } @helper TabDeployment() @@ -437,14 +474,14 @@ jQuery(document).ready(function () { // show/hide product category filter - $('select[name="ProductFiltering.WithoutCategories"]').change(function () { + $('select[name="ProductFilter.WithoutCategories"]').change(function () { $('#FilterCategoryIdsContainer').toggle(_.isEmpty($(this).val())); }).trigger('change'); // show/hide product manufacturer filter - $('select[name="ProductFiltering.WithoutManufacturers"]').change(function () { + $('select[name="ProductFilter.WithoutManufacturers"]').change(function () { $('#FilterManufacturerIdsContainer').toggle(_.isEmpty($(this).val())); }).trigger('change'); }); - + \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml index a38c3a9ed5..10fafd92f6 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml @@ -35,29 +35,29 @@ }) .Columns(columns => { - columns.Bound(x => x.Providing.ThumbnailUrl) + columns.Bound(x => x.Provider.ThumbnailUrl) .Width(70) .Centered() .Template( @ - @item.Id + @item.Id ) - .ClientTemplate("<#= Id #>"); + .ClientTemplate("<#= Id #>"); columns.Bound(x => x.Name) .Width(400) .Template(x => Html.ActionLink(x.Name, "Edit", new { id = x.Id })) .ClientTemplate("\"><#= Name #>"); - columns.Bound(x => x.Providing.SystemName) - .Template(x => "{0} ({1})".FormatInvariant(x.Providing.FriendlyName, x.Providing.SystemName)) - .ClientTemplate("<#= Providing.FriendlyName #> (<#= Providing.SystemName #>)"); + columns.Bound(x => x.Provider.SystemName) + .Template(x => "{0} ({1})".FormatInvariant(x.Provider.FriendlyName, x.Provider.SystemName)) + .ClientTemplate("<#= Provider.FriendlyName #> (<#= Provider.SystemName #>)"); columns.Bound(x => x.Enabled) .Width(100) .Template(item => @Html.SymbolForBool(item.Enabled)) .ClientTemplate(@Html.SymbolForBool("Enabled")) .Centered(); - columns.Bound(x => x.Providing.EntityTypeName); - columns.Bound(x => x.Providing.FileType) + columns.Bound(x => x.Provider.EntityTypeName); + columns.Bound(x => x.Provider.FileType) .Centered(); columns.Bound(x => x.SchedulingHours) .Centered(); @@ -115,7 +115,7 @@ smallIcon: dialog.find('.modal-body'), callbackSuccess: function (resp) { dialog.find('.modal-body').html(resp); - $('select[name="Providing.SystemName"]').selectWrapper(); + $('select[name="Provider.SystemName"]').selectWrapper(); }, callbackComplete: function () { showPrimaryButton(true); diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/Preview.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/Preview.cshtml new file mode 100644 index 0000000000..710655ebfc --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/Preview.cshtml @@ -0,0 +1,20 @@ +@using SmartStore.Admin.Models.DataExchange +@model ExportPreviewModel +@{ + var title = string.Concat(T("Admin.Common.Preview"), " ", T("Common.Export")); + ViewBag.Title = title; +} + +
    +
    + +   + @title - @Model.Name @Html.ActionLink("(" + T("Common.Back") + ")", "Edit", new { id = Model.Id }) +
    +
    +
    +
    + +
    + TODO +
    \ No newline at end of file From b547e25d3032ae4e24c0865c187fa50cbf072375 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Fri, 7 Aug 2015 13:10:49 +0200 Subject: [PATCH 0339/1256] Added export deployment entity --- .../Domain/DataExchange/ExportCore.cs | 8 ++ .../Domain/DataExchange/ExportDeployment.cs | 80 +++++++++++ .../Domain/DataExchange/ExportFilter.cs | 7 +- .../Domain/DataExchange/ExportProfile.cs | 22 +++ .../Domain/DataExchange/ExportProjection.cs | 4 +- .../SmartStore.Core/SmartStore.Core.csproj | 1 + .../DataExchange/ExportDeploymentMap.cs | 29 ++++ .../Mapping/DataExchange/ExportProfileMap.cs | 1 + .../201508051818404_ExportFramework.resx | 126 ------------------ ...1508070937542_ExportFramework.Designer.cs} | 2 +- ....cs => 201508070937542_ExportFramework.cs} | 125 ++++++++++++++++- .../201508070937542_ExportFramework.resx | 126 ++++++++++++++++++ .../SmartStore.Data/SmartStore.Data.csproj | 11 +- .../DataExchange/ExportService.cs | 21 ++- .../DataExchange/IExportService.cs | 8 ++ .../Controllers/ExportController.cs | 96 ++++++++++--- .../DataExchange/ExportDeploymentModel.cs | 49 +++++++ .../Models/DataExchange/ExportFilterModel.cs | 2 +- .../Models/DataExchange/ExportProfileModel.cs | 13 +- .../DataExchange/ExportProjectionModel.cs | 4 +- .../Administration/SmartStore.Admin.csproj | 3 + .../DataExchange/ExportDeplomentValidator.cs | 16 +++ .../DataExchange/ExportProfileValidator.cs | 16 +++ .../Administration/Views/Export/Edit.cshtml | 61 ++++++++- .../Administration/Views/Export/List.cshtml | 6 +- 25 files changed, 666 insertions(+), 171 deletions(-) create mode 100644 src/Libraries/SmartStore.Core/Domain/DataExchange/ExportDeployment.cs create mode 100644 src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportDeploymentMap.cs delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.resx rename src/Libraries/SmartStore.Data/Migrations/{201508051818404_ExportFramework.Designer.cs => 201508070937542_ExportFramework.Designer.cs} (92%) rename src/Libraries/SmartStore.Data/Migrations/{201508051818404_ExportFramework.cs => 201508070937542_ExportFramework.cs} (62%) create mode 100644 src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.resx create mode 100644 src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportDeploymentModel.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportDeplomentValidator.cs create mode 100644 src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportProfileValidator.cs diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportCore.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportCore.cs index 2f513eab63..7ddc34bf58 100644 --- a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportCore.cs +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportCore.cs @@ -11,4 +11,12 @@ public enum ExportEntityType Order, NewsletterSubscriber } + + public enum ExportDeploymentType + { + FileSystem = 0, + Email, + Http, + Ftp + } } diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportDeployment.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportDeployment.cs new file mode 100644 index 0000000000..0f350e499f --- /dev/null +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportDeployment.cs @@ -0,0 +1,80 @@ +using SmartStore.Core.Domain.DataExchange; + +namespace SmartStore.Core.Domain +{ + public class ExportDeployment : BaseEntity + { + /// + /// The profile identifier + /// + public int ProfileId { get; set; } + + /// + /// Name of the deployment + /// + public string Name { get; set; } + + /// + /// Whether the deployment is enabled + /// + public bool Enabled { get; set; } + + /// + /// Whether to deploy in a folder that can be reached from the internet + /// + public bool IsPublic { get; set; } + + /// + /// The deployment type identifier + /// + public int DeploymentTypeId { get; set; } + + /// + /// The deployment type + /// + public ExportDeploymentType DeploymentType + { + get + { + return (ExportDeploymentType)DeploymentTypeId; + } + set + { + DeploymentTypeId = (int)value; + } + } + + public string Username { get; set; } + + public string Password { get; set; } + + /// + /// Deployment URL + /// + public string Url { get; set; } + + /// + /// The file system path + /// + public string FileSystemPath { get; set; } + + /// + /// Multiple email addresses can be separated by semicolon + /// + public string EmailAddresses { get; set; } + + /// + /// Subject of the email + /// + public string EmailSubject { get; set; } + + /// + /// Identifier of the email account + /// + public int EmailAccountId { get; set; } + + // TODO: more FTP options + + public virtual ExportProfile Profile { get; set; } + } +} diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs index db02950efb..4d7ecd7316 100644 --- a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportFilter.cs @@ -10,6 +10,11 @@ namespace SmartStore.Core.Domain.DataExchange [Serializable] public class ExportFilter { + public ExportFilter() + { + IsPublished = true; + } + /// /// Store identifier; 0 to load all records /// @@ -50,7 +55,7 @@ public class ExportFilter /// /// A value indicating whether to load only published or non published products /// - public bool? IsPublished { get; set; } + public bool IsPublished { get; set; } /// /// Category identifiers diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs index 907701cc2b..0de9030c7e 100644 --- a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using SmartStore.Core.Domain.DataExchange; using SmartStore.Core.Domain.Tasks; @@ -6,6 +7,8 @@ namespace SmartStore.Core.Domain { public class ExportProfile : BaseEntity { + private ICollection _deployments; + public ExportProfile() { Limit = 100; @@ -72,9 +75,28 @@ public ExportProfile() /// public bool PerStore { get; set; } + /// + /// Whether to combine and compress the export files in a ZIP archive + /// + public bool CreateZipArchive { get; set; } + + /// + /// Email addresses (semicolon separated) where to send a notification message of the completion of the export + /// + public string CompletedEmailAddresses { get; set; } + /// /// The scheduling task /// public virtual ScheduleTask ScheduleTask { get; set; } + + /// + /// Gets or sets export deployments + /// + public virtual ICollection Deployments + { + get { return _deployments ?? (_deployments = new HashSet()); } + set { _deployments = value; } + } } } diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProjection.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProjection.cs index 3020a71b1c..8696afbdce 100644 --- a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProjection.cs +++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProjection.cs @@ -8,11 +8,11 @@ public class ExportProjection /// /// The language to be applied to the export /// - public int LanguageId { get; set; } + public int? LanguageId { get; set; } /// /// The currency to be applied to the export /// - public int CurrencyId { get; set; } + public int? CurrencyId { get; set; } } } diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj index 4dbef97117..e04d7f01e5 100644 --- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj +++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj @@ -157,6 +157,7 @@ + diff --git a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportDeploymentMap.cs b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportDeploymentMap.cs new file mode 100644 index 0000000000..0a57740d6e --- /dev/null +++ b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportDeploymentMap.cs @@ -0,0 +1,29 @@ +using System.Data.Entity.ModelConfiguration; +using SmartStore.Core.Domain; + +namespace SmartStore.Data.Mapping.DataExchange +{ + public class ExportDeploymentMap : EntityTypeConfiguration + { + public ExportDeploymentMap() + { + this.ToTable("ExportDeployment"); + this.HasKey(x => x.Id); + + this.Property(x => x.Name).IsRequired().HasMaxLength(100); + this.Property(x => x.Username).HasMaxLength(400); + this.Property(x => x.Password).HasMaxLength(400); + this.Property(x => x.Url).HasMaxLength(4000); + this.Property(x => x.FileSystemPath).HasMaxLength(400); + this.Property(x => x.EmailAddresses).HasMaxLength(4000); + this.Property(x => x.EmailSubject).HasMaxLength(400); + + this.Ignore(x => x.DeploymentType); + + this.HasRequired(x => x.Profile) + .WithMany(x => x.Deployments) + .HasForeignKey(x => x.ProfileId) + .WillCascadeOnDelete(true); + } + } +} diff --git a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs index c64b24cefe..7d62b17bd6 100644 --- a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs +++ b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs @@ -16,6 +16,7 @@ public ExportProfileMap() this.Property(x => x.Filtering).IsMaxLength(); this.Property(x => x.Projection).IsMaxLength(); this.Property(x => x.ProviderConfigData).IsMaxLength(); + this.Property(x => x.CompletedEmailAddresses).HasMaxLength(400); this.HasRequired(x => x.ScheduleTask) .WithMany() diff --git a/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.resx b/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.resx deleted file mode 100644 index 3219191ea2..0000000000 --- a/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 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 - - - dbo - - \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.Designer.cs similarity index 92% rename from src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.Designer.cs rename to src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.Designer.cs index ebbd4a40ae..eb6be6802a 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.Designer.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.Designer.cs @@ -13,7 +13,7 @@ public sealed partial class ExportFramework : IMigrationMetadata string IMigrationMetadata.Id { - get { return "201508051818404_ExportFramework"; } + get { return "201508070937542_ExportFramework"; } } string IMigrationMetadata.Source diff --git a/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.cs b/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.cs similarity index 62% rename from src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.cs rename to src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.cs index af3d696b92..c85249ef25 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201508051818404_ExportFramework.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.cs @@ -9,6 +9,28 @@ public partial class ExportFramework : DbMigration, ILocaleResourcesProvider, ID { public override void Up() { + CreateTable( + "dbo.ExportDeployment", + c => new + { + Id = c.Int(nullable: false, identity: true), + ProfileId = c.Int(nullable: false), + Name = c.String(nullable: false, maxLength: 100), + Enabled = c.Boolean(nullable: false), + IsPublic = c.Boolean(nullable: false), + DeploymentTypeId = c.Int(nullable: false), + Username = c.String(maxLength: 400), + Password = c.String(maxLength: 400), + Url = c.String(maxLength: 4000), + FileSystemPath = c.String(maxLength: 400), + EmailAddresses = c.String(maxLength: 4000), + EmailSubject = c.String(maxLength: 400), + EmailAccountId = c.Int(nullable: false), + }) + .PrimaryKey(t => t.Id) + .ForeignKey("dbo.ExportProfile", t => t.ProfileId, cascadeDelete: true) + .Index(t => t.ProfileId); + CreateTable( "dbo.ExportProfile", c => new @@ -26,6 +48,8 @@ public override void Up() Limit = c.Int(nullable: false), BatchSize = c.Int(nullable: false), PerStore = c.Boolean(nullable: false), + CreateZipArchive = c.Boolean(nullable: false), + CompletedEmailAddresses = c.String(maxLength: 400), }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.ScheduleTask", t => t.SchedulingTaskId) @@ -35,9 +59,12 @@ public override void Up() public override void Down() { + DropForeignKey("dbo.ExportDeployment", "ProfileId", "dbo.ExportProfile"); DropForeignKey("dbo.ExportProfile", "SchedulingTaskId", "dbo.ScheduleTask"); DropIndex("dbo.ExportProfile", new[] { "SchedulingTaskId" }); + DropIndex("dbo.ExportDeployment", new[] { "ProfileId" }); DropTable("dbo.ExportProfile"); + DropTable("dbo.ExportDeployment"); } public bool RollbackOnFailure @@ -68,7 +95,7 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Common.Image", "Image", "Bild"); builder.AddOrUpdate("Common.Filter", "Filter", "Filter"); builder.AddOrUpdate("Common.Projection", "Projection", "Projektion"); - builder.AddOrUpdate("Common.Publishing", "Publishing", "Verffentlichung"); + builder.AddOrUpdate("Common.Deployment", "Deployment", "Bereitstellung"); builder.AddOrUpdate("Common.Website", "Website", "Web-Seite"); @@ -105,6 +132,10 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Specifies the name of the export profile.", "Legt den Namen des Exportprofils fest."); + builder.AddOrUpdate("Admin.Configuration.Export.Name.Validate", + "Please enter the name of the profile.", + "Bitte den Namen des Profils eingeben."); + builder.AddOrUpdate("Admin.Configuration.Export.FileType", "File type", "Dateityp", @@ -148,12 +179,23 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Specifies whether to start a separate run-through for each store.", "Legt fest, ob fr jeden Shop ein separater Verarbeitungsdurchlauf erfolgen soll."); + builder.AddOrUpdate("Admin.Configuration.Export.CreateZipArchive", + "Create ZIP archive", + "ZIP-Archiv erstellen", + "Specifies whether to combine and compress the export files in a ZIP archive.", + "Legt fest, ob die Exportdateien in einem ZIP-Archiv zusammengefasst und komprimiert werden sollen."); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Product", "Product", "Produkt"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Category", "Category", "Warengruppe"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Manufacturer", "Manufacturer", "Hersteller"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Customer", "Customer", "Kunde"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.ExportEntityType.Order", "Order", "Auftrag"); + builder.AddOrUpdate("Admin.Configuration.Export.CompletedEmailAddresses", + "Notification (email addresses)", + "Benachrichtigung (E-Mail-Addressen)", + "Specifies the email addresses (semicolon separated) where to send a notification message of the completion of the export.", + "Legt die E-Mail Addressen (Semikolon getrennt) fest, an die eine Benachrichtigung ber die Fertigstellung des Exports verschickt werden soll."); + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Product", "Product", "Produkt"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Category", "Category", "Warengruppe"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Manufacturer", "Manufacturer", "Hersteller"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Customer", "Customer", "Kunde"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Order", "Order", "Auftrag"); builder.AddOrUpdate("Admin.Configuration.Export.Filter.StoreId", "Store", @@ -281,6 +323,77 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Whrung", "Specifies the currency to be applied to the export.", "Legt die auf den Export anzuwendende Whrung fest."); + + + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.FileSystem", "File system", "Dateisystem"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Email", "Email", "E-Mail"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Http", "HTTP", "HTTP"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Ftp", "FTP", "FTP"); + + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.Name", + "Name", + "Name", + "Specifies the name of the deployment.", + "Legt den Namen der Bereitstellung fest."); + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.Name.Validate", + "Please enter the name of the deployment.", + "Bitte den Namen der Bereitstellung eingeben."); + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.IsPublic", + "Make public", + "ffentlich machen", + "Specifies whether to publish the exported data (e.g. whether they are accessible on the internet).", + "Legt fest, ob die exportierten Daten ffentlich gemacht werden sollen (z.B. ob sie ber das Internet erreichbar sind)."); + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.DeploymentType", + "Type of deployment", + "Typ der Bereitstellung", + "Specifies the deployment type.", + "Legt den Bereitstellungstyp fest."); + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.Username", + "User name", + "Benutzername", + "Specifies the user name.", + "Legt den Benutzernamen fest."); + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.Password", + "Password", + "Passwort", + "Specifies the password.", + "Legt das Passwort fest."); + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.Url", + "URL", + "URL", + "Specifies the URL on which the data should be deployed.", + "Legt die URL fest, unter der die Daten bereitgestellt werden sollen."); + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.FileSystemPath", + "Relative path", + "Relativer Pfad", + "Specifies the relative path for the deployed data.", + "Legt den relativen Pfad fr die bereitgestellten Daten fest."); + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.EmailAddresses", + "Email addresses", + "E-Mail-Addressen", + "Specifies the email addresses (semicolon separated) where to send the data.", + "Legt die E-Mail Addressen (Semikolon getrennt) fest, an die die Daten verschickt werden soll."); + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.EmailSubject", + "Email subject", + "E-Mail Betreff", + "Specifies the subject of the data should be sent.", + "Legt den Betreff der verschickten Daten fest."); + + builder.AddOrUpdate("Admin.Configuration.Export.Deployment.EmailAccountId", + "Email account", + "E-Mail Konto", + "Specifies the email account through which the data should be sent.", + "Legt das E-Mail Konto fest, ber welches die Daten verschickt werden sollen."); } } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.resx b/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.resx new file mode 100644 index 0000000000..80b65fc188 --- /dev/null +++ b/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj index a203443917..48259842a2 100644 --- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj +++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj @@ -120,6 +120,7 @@ + @@ -332,9 +333,9 @@ 201507250039446_Merge2.cs - - - 201508051818404_ExportFramework.cs + + + 201508070937542_ExportFramework.cs @@ -633,8 +634,8 @@ 201507250039446_Merge2.cs - - 201508051818404_ExportFramework.cs + + 201508070937542_ExportFramework.cs diff --git a/src/Libraries/SmartStore.Services/DataExchange/ExportService.cs b/src/Libraries/SmartStore.Services/DataExchange/ExportService.cs index 2b8a2f2ba1..d678942acc 100644 --- a/src/Libraries/SmartStore.Services/DataExchange/ExportService.cs +++ b/src/Libraries/SmartStore.Services/DataExchange/ExportService.cs @@ -16,17 +16,20 @@ public partial class ExportService : IExportService private const int _defaultSchedulingHours = 6; private readonly IRepository _exportProfileRepository; + private readonly IRepository _exportDeploymentRepository; private readonly IEventPublisher _eventPublisher; private readonly IScheduleTaskService _scheduleTaskService; private readonly IProviderManager _providerManager; public ExportService( IRepository exportProfileRepository, + IRepository exportDeploymentRepository, IEventPublisher eventPublisher, IScheduleTaskService scheduleTaskService, IProviderManager providerManager) { _exportProfileRepository = exportProfileRepository; + _exportDeploymentRepository = exportDeploymentRepository; _eventPublisher = eventPublisher; _scheduleTaskService = scheduleTaskService; _providerManager = providerManager; @@ -123,7 +126,12 @@ public virtual ExportProfile GetExportProfileById(int id) if (id == 0) return null; - return _exportProfileRepository.GetById(id); + var profile = _exportProfileRepository.Table + .Expand(x => x.ScheduleTask) + .Expand(x => x.Deployments) + .FirstOrDefault(x => x.Id == id); + + return profile; } @@ -142,6 +150,17 @@ public virtual Provider LoadProvider(string systemName, int sto return (provider.IsValid() ? provider : null); } + + public virtual void DeleteExportDeployment(ExportDeployment deployment) + { + if (deployment == null) + throw new ArgumentNullException("deployment"); + + _exportDeploymentRepository.Delete(deployment); + + _eventPublisher.EntityDeleted(deployment); + } + #endregion } } diff --git a/src/Libraries/SmartStore.Services/DataExchange/IExportService.cs b/src/Libraries/SmartStore.Services/DataExchange/IExportService.cs index bc6ca8b092..bb511ebc8d 100644 --- a/src/Libraries/SmartStore.Services/DataExchange/IExportService.cs +++ b/src/Libraries/SmartStore.Services/DataExchange/IExportService.cs @@ -40,6 +40,7 @@ public interface IExportService /// Export profile ExportProfile GetExportProfileById(int id); + /// /// Load all export providers /// @@ -54,5 +55,12 @@ public interface IExportService /// Store identifier /// Export provider Provider LoadProvider(string systemName, int storeId = 0); + + + /// + /// Deletes an export deployment + /// + /// Export deployment + void DeleteExportDeployment(ExportDeployment deployment); } } diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs index 6f7ac50ab8..4a036ed0e5 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs @@ -1,11 +1,6 @@ using System; -using System.Globalization; -using System.IO; using System.Linq; -using System.Text; using System.Web.Mvc; -using System.Web.Routing; -using System.Xml.Serialization; using SmartStore.Admin.Models.DataExchange; using SmartStore.Core; using SmartStore.Core.Domain; @@ -82,7 +77,28 @@ private string GetThumbnailUrl(Provider provider) return url; } - private void PrepareExportProfileModel(ExportProfileModel model, ExportProfile profile, Provider provider) + private ExportDeploymentModel PrepareDeploymentModel(ExportDeployment deployment) + { + var model = new ExportDeploymentModel + { + Id = deployment.Id, + Name = deployment.Name, + Enabled = deployment.Enabled, + IsPublic = deployment.IsPublic, + DeploymentType = deployment.DeploymentType, + DeploymentTypeName = T("Enums.SmartStore.Core.Domain.DataExchange.ExportDeploymentType." + deployment.DeploymentType.ToString()), + Username = deployment.Username, + Password = deployment.Password, + Url = deployment.Url, + FileSystemPath = deployment.FileSystemPath, + EmailAddresses = deployment.EmailAddresses, + EmailSubject = deployment.EmailSubject, + EmailAccountId = deployment.EmailAccountId + }; + return model; + } + + private void PrepareProfileModel(ExportProfileModel model, ExportProfile profile, Provider provider) { model.Id = profile.Id; model.Name = profile.Name; @@ -106,12 +122,12 @@ private void PrepareExportProfileModel(ExportProfileModel model, ExportProfile p model.Provider.Description = _pluginMediator.GetLocalizedDescription(provider.Metadata); model.Provider.EntityType = provider.Value.EntityType; - model.Provider.EntityTypeName = T("Enums.SmartStore.Core.Domain.ExportEntityType." + provider.Value.EntityType.ToString()); + model.Provider.EntityTypeName = T("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType." + provider.Value.EntityType.ToString()); model.Provider.FileType = provider.Value.FileType.ToUpper(); } } - private void PrepareExportProfileModelForEdit(ExportProfileModel model, ExportProfile profile, Provider provider) + private void PrepareProfileModelForEdit(ExportProfileModel model, ExportProfile profile, Provider provider) { var filter = XmlHelper.Deserialize(profile.Filtering); var projection = XmlHelper.Deserialize(profile.Projection); @@ -127,16 +143,25 @@ private void PrepareExportProfileModelForEdit(ExportProfileModel model, ExportPr model.Limit = profile.Limit; model.BatchSize = profile.BatchSize; model.PerStore = profile.PerStore; + model.CreateZipArchive = profile.CreateZipArchive; + model.CompletedEmailAddresses = profile.CompletedEmailAddresses; if (provider != null) { - string partialName; - Type dataType; - if (provider.Value.RequiresConfiguration(out partialName, out dataType)) + try { - model.Provider.ConfigPartialViewName = partialName; - model.Provider.ConfigDataType = dataType; - model.Provider.ConfigData = XmlHelper.Deserialize(profile.ProviderConfigData, dataType); + string partialName; + Type dataType; + if (provider.Value.RequiresConfiguration(out partialName, out dataType)) + { + model.Provider.ConfigPartialViewName = partialName; + model.Provider.ConfigDataType = dataType; + model.Provider.ConfigData = XmlHelper.Deserialize(profile.ProviderConfigData, dataType); + } + } + catch (Exception exc) + { + NotifyError(exc); } } @@ -229,6 +254,9 @@ private void PrepareExportProfileModelForEdit(ExportProfileModel model, ExportPr initModelBase(model.OrderFilter); } + + // deplyoment + model.Deployments = profile.Deployments.Select(x => PrepareDeploymentModel(x)).ToList(); } #endregion @@ -262,7 +290,7 @@ public ActionResult List(GridCommand command) model.Data = profiles.Select(x => { var profileModel = new ExportProfileModel(); - PrepareExportProfileModel(profileModel, x, providers.FirstOrDefault(y => y.Metadata.SystemName == x.ProviderSystemName)); + PrepareProfileModel(profileModel, x, providers.FirstOrDefault(y => y.Metadata.SystemName == x.ProviderSystemName)); return profileModel; }); @@ -331,8 +359,8 @@ public ActionResult Edit(int id) var model = new ExportProfileModel(); - PrepareExportProfileModel(model, profile, provider); - PrepareExportProfileModelForEdit(model, profile, provider); + PrepareProfileModel(model, profile, provider); + PrepareProfileModelForEdit(model, profile, provider); return View(model); } @@ -352,8 +380,8 @@ public ActionResult Edit(ExportProfileModel model, bool continueEditing) if (!ModelState.IsValid) { - PrepareExportProfileModel(model, profile, provider); - PrepareExportProfileModelForEdit(model, profile, provider); + PrepareProfileModel(model, profile, provider); + PrepareProfileModelForEdit(model, profile, provider); return View(model); } @@ -364,6 +392,8 @@ public ActionResult Edit(ExportProfileModel model, bool continueEditing) profile.Limit = model.Limit; profile.BatchSize = model.BatchSize; profile.PerStore = model.PerStore; + profile.CreateZipArchive = model.CreateZipArchive; + profile.CompletedEmailAddresses = model.CompletedEmailAddresses; if (profile.Name.IsEmpty()) profile.Name = provider.Metadata.FriendlyName; @@ -499,5 +529,33 @@ public ActionResult Execute(int id) { return null; } + + #region Export deployment + + [HttpPost, GridAction(EnableCustomBinding = true)] + public ActionResult DeploymentList(GridCommand command, int id) + { + var model = new GridModel(); + + if (_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + { + var profile = _exportService.GetExportProfileById(id); + if (profile != null) + { + model.Total = profile.Deployments.Count; + + model.Data = profile.Deployments.Select(x => PrepareDeploymentModel(x)).ToList(); + } + } + + return new JsonResult { Data = model }; + } + + public ActionResult DeploymentEdit(int id) + { + return null; + } + + #endregion } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportDeploymentModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportDeploymentModel.cs new file mode 100644 index 0000000000..df0c40302e --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportDeploymentModel.cs @@ -0,0 +1,49 @@ +using System.ComponentModel.DataAnnotations; +using FluentValidation.Attributes; +using SmartStore.Admin.Validators.DataExchange; +using SmartStore.Core.Domain.DataExchange; +using SmartStore.Web.Framework; +using SmartStore.Web.Framework.Mvc; + +namespace SmartStore.Admin.Models.DataExchange +{ + [Validator(typeof(ExportDeploymentValidator))] + public class ExportDeploymentModel : EntityModelBase + { + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.Name")] + public string Name { get; set; } + + [SmartResourceDisplayName("Common.Enabled")] + public bool Enabled { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.DeploymentType")] + public ExportDeploymentType DeploymentType { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.DeploymentType")] + public string DeploymentTypeName { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.IsPublic")] + public bool IsPublic { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.Username")] + public string Username { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.Password")] + [DataType(DataType.Password)] + public string Password { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.Url")] + public string Url { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.FileSystemPath")] + public string FileSystemPath { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.EmailAddresses")] + public string EmailAddresses { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.EmailSubject")] + public string EmailSubject { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.EmailAccountId")] + public int EmailAccountId { get; set; } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs index 3294830cb9..589dc68f9f 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportFilterModel.cs @@ -26,7 +26,7 @@ public abstract class ExportFilterModelBase public class ExportProductFilterModel : ExportFilterModelBase { [SmartResourceDisplayName("Admin.Configuration.Export.Filter.IsPublished")] - public bool? IsPublished { get; set; } + public bool IsPublished { get; set; } [SmartResourceDisplayName("Admin.Configuration.Export.Filter.ProductType")] public ProductType? ProductType { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs index 4638c6fd0e..77f5ff7b6d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs @@ -1,14 +1,15 @@ using System; using System.Collections.Generic; -using System.Dynamic; using System.Web.Mvc; -using System.Web.Routing; +using FluentValidation.Attributes; +using SmartStore.Admin.Validators.DataExchange; using SmartStore.Core.Domain.DataExchange; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Mvc; namespace SmartStore.Admin.Models.DataExchange { + [Validator(typeof(ExportProfileValidator))] public partial class ExportProfileModel : EntityModelBase { public int StoreCount { get; set; } @@ -40,6 +41,12 @@ public partial class ExportProfileModel : EntityModelBase [SmartResourceDisplayName("Admin.Configuration.Export.PerStore")] public bool PerStore { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Export.CreateZipArchive")] + public bool CreateZipArchive { get; set; } + + [SmartResourceDisplayName("Admin.Configuration.Export.CompletedEmailAddresses")] + public string CompletedEmailAddresses { get; set; } + public ProviderModel Provider { get; set; } public ExportProductFilterModel ProductFilter { get; set; } @@ -47,6 +54,8 @@ public partial class ExportProfileModel : EntityModelBase public ExportProjectionModel Projection { get; set; } + public List Deployments { get; set; } + public class ProviderModel { diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProjectionModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProjectionModel.cs index 0cd5ddd22f..d95ea87ec8 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProjectionModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProjectionModel.cs @@ -7,11 +7,11 @@ namespace SmartStore.Admin.Models.DataExchange public class ExportProjectionModel { [SmartResourceDisplayName("Admin.Configuration.Export.Projection.LanguageId")] - public int LanguageId { get; set; } + public int? LanguageId { get; set; } public List AvailableLanguages { get; set; } [SmartResourceDisplayName("Admin.Configuration.Export.Projection.CurrencyId")] - public int CurrencyId { get; set; } + public int? CurrencyId { get; set; } public List AvailableCurrencies { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index 1fb41c6bf1..b7bcbd5add 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -247,6 +247,7 @@ + @@ -366,6 +367,8 @@ + + diff --git a/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportDeplomentValidator.cs b/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportDeplomentValidator.cs new file mode 100644 index 0000000000..4f1539698d --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportDeplomentValidator.cs @@ -0,0 +1,16 @@ +using FluentValidation; +using SmartStore.Admin.Models.DataExchange; +using SmartStore.Services.Localization; + +namespace SmartStore.Admin.Validators.DataExchange +{ + public partial class ExportDeploymentValidator : AbstractValidator + { + public ExportDeploymentValidator(ILocalizationService localization) + { + RuleFor(x => x.Name) + .NotEmpty() + .WithMessage(localization.GetResource("Admin.Configuration.Export.Deployment.Name.Validate")); + } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportProfileValidator.cs b/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportProfileValidator.cs new file mode 100644 index 0000000000..d0a1e14ca1 --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportProfileValidator.cs @@ -0,0 +1,16 @@ +using FluentValidation; +using SmartStore.Admin.Models.DataExchange; +using SmartStore.Services.Localization; + +namespace SmartStore.Admin.Validators.DataExchange +{ + public partial class ExportProfileValidator : AbstractValidator + { + public ExportProfileValidator(ILocalizationService localization) + { + RuleFor(x => x.Name) + .NotEmpty() + .WithMessage(localization.GetResource("Admin.Configuration.Export.Name.Validate")); + } + } +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml index f825f3b48a..7bf4b772b2 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml @@ -36,7 +36,7 @@ x.Add().Text(T("Common.Filter").Text).Content(TabFilter()); x.Add().Text(T("Common.Projection").Text).Content(TabProjection()); x.Add().Text(T("Admin.Configuration").Text).Content(TabConfiguration()); - x.Add().Text(T("Common.Publishing").Text).Content(TabDeployment()); + x.Add().Text(T("Common.Deployment").Text).Content(TabDeployment()); EngineContext.Current.Resolve().Publish(new TabStripCreated(x, "export-profile-edit", this.Html, this.Model)); }) @@ -466,6 +466,65 @@ @helper TabDeployment() { + +
    + @(Html.Telerik().Grid(Model.Deployments) + .Name("export-deployment-grid") + .DataKeys(keys => keys.Add(x => x.Id) + .RouteKey("Id")) + .Columns(columns => + { + columns.Bound(x => x.Name) + .Width(400) + .Template(x => Html.ActionLink(x.Name, "DeploymentEdit", new { id = x.Id })) + .ClientTemplate("\"><#= Name #>"); + columns.Bound(x => x.DeploymentTypeName); + columns.Bound(x => x.Enabled) + .Width(100) + .Template(item => @Html.SymbolForBool(item.Enabled)) + .ClientTemplate(@Html.SymbolForBool("Enabled")) + .Centered(); + }) + .ToolBar(commands => + { + commands.Custom() + .Name("export-deployment-insert-button") + .HtmlAttributes(new { @class = "btn btn-primary" }) + .Text(" " + @T("Common.AddNew")); + }) + .DataBinding(dataBinding => dataBinding.Ajax().Select("DeploymentList", "Export", new { id = Model.Id })) + .ClientEvents(events => events.OnRowDataBound("onRowDataBound_ExportDeployments")) + .EnableCustomBinding(true)) +
    + +

    + + + + + + + + + + +
    + @Html.SmartLabelFor(x => x.CreateZipArchive) + + @Html.EditorFor(x => x.CreateZipArchive) + @Html.ValidationMessageFor(x => x.CreateZipArchive) +
    + @Html.SmartLabelFor(x => x.CompletedEmailAddresses) + + @Html.EditorFor(x => x.CompletedEmailAddresses, new { @class = "control-xlarge" }) + @Html.ValidationMessageFor(x => x.CompletedEmailAddresses) +
    } @Html.DeleteConfirmation("export-profile-delete") diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml index 10fafd92f6..9c04d96eba 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml @@ -29,10 +29,8 @@ @(Html.Telerik().Grid() .Name("export-profile-grid") - .DataKeys(x => - { - x.Add(y => y.Id).RouteKey("Id"); - }) + .DataKeys(keys => keys.Add(x => x.Id) + .RouteKey("Id")) .Columns(columns => { columns.Bound(x => x.Provider.ThumbnailUrl) From 9c609eb5417912b5675f0cdf95ae0f50d37980f9 Mon Sep 17 00:00:00 2001 From: Marcus Gesing Date: Sat, 8 Aug 2015 13:43:44 +0200 Subject: [PATCH 0340/1256] CRUD export deployment --- .../Domain/Messages/EmailAccount.cs | 7 +- .../201508070937542_ExportFramework.cs | 25 +- .../DataExchange/ExportService.cs | 11 + .../DataExchange/IExportService.cs | 8 +- .../Controllers/ExportController.cs | 216 +++++++++++++++--- .../DataExchange/ExportDeploymentModel.cs | 30 ++- .../Models/DataExchange/ExportProfileModel.cs | 1 - .../Administration/SmartStore.Admin.csproj | 3 + .../DataExchange/ExportDeplomentValidator.cs | 28 ++- .../DataExchange/ExportProfileValidator.cs | 2 +- .../Views/Export/CreateDeployment.cshtml | 21 ++ .../Administration/Views/Export/Edit.cshtml | 18 +- .../Views/Export/EditDeployment.cshtml | 26 +++ .../Administration/Views/Export/List.cshtml | 2 +- .../Export/_CreateOrUpdateDeployment.cshtml | 127 ++++++++++ 15 files changed, 466 insertions(+), 59 deletions(-) create mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Export/CreateDeployment.cshtml create mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Export/EditDeployment.cshtml create mode 100644 src/Presentation/SmartStore.Web/Administration/Views/Export/_CreateOrUpdateDeployment.cshtml diff --git a/src/Libraries/SmartStore.Core/Domain/Messages/EmailAccount.cs b/src/Libraries/SmartStore.Core/Domain/Messages/EmailAccount.cs index decde80336..859a7bd74f 100644 --- a/src/Libraries/SmartStore.Core/Domain/Messages/EmailAccount.cs +++ b/src/Libraries/SmartStore.Core/Domain/Messages/EmailAccount.cs @@ -54,9 +54,10 @@ public string FriendlyName { get { - if (!String.IsNullOrWhiteSpace(this.DisplayName)) - return this.Email + " (" + this.DisplayName + ")"; - return this.Email; + if (DisplayName.IsEmpty()) + return Email; + + return "{0} ({1})".FormatInvariant(DisplayName, Email); } } diff --git a/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.cs b/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.cs index c85249ef25..a3ca9c5035 100644 --- a/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.cs +++ b/src/Libraries/SmartStore.Data/Migrations/201508070937542_ExportFramework.cs @@ -98,6 +98,11 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Common.Deployment", "Deployment", "Bereitstellung"); builder.AddOrUpdate("Common.Website", "Website", "Web-Seite"); + builder.AddOrUpdate("Admin.Validation.UsernamePassword", "Please enter username and password", "Bitte geben Sie Benutzername und Passwort ein"); + builder.AddOrUpdate("Admin.Validation.Url", "Please enter a valid URL", "Bitte geben Sie eine gltige URL ein"); + builder.AddOrUpdate("Admin.Validation.Name", "Please enter a name", "Bitte geben Sie einen Namen ein"); + builder.AddOrUpdate("Admin.Validation.EmailAddress", "Please enter a valid email address", "Bitte geben Sie eine gltige E-Mail Adresse ein"); + builder.AddOrUpdate("Admin.Configuration.Export.ProviderSystemName.Validate", "There were no export provider found for system name \"{0}\". A provider is mandatory for an export profile.", @@ -132,10 +137,6 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Specifies the name of the export profile.", "Legt den Namen des Exportprofils fest."); - builder.AddOrUpdate("Admin.Configuration.Export.Name.Validate", - "Please enter the name of the profile.", - "Bitte den Namen des Profils eingeben."); - builder.AddOrUpdate("Admin.Configuration.Export.FileType", "File type", "Dateityp", @@ -325,10 +326,10 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Legt die auf den Export anzuwendende Whrung fest."); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.FileSystem", "File system", "Dateisystem"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Email", "Email", "E-Mail"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Http", "HTTP", "HTTP"); - builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType.Ftp", "FTP", "FTP"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportDeploymentType.FileSystem", "File system", "Dateisystem"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportDeploymentType.Email", "Email", "E-Mail"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportDeploymentType.Http", "HTTP", "HTTP"); + builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportDeploymentType.Ftp", "FTP", "FTP"); builder.AddOrUpdate("Admin.Configuration.Export.Deployment.Name", @@ -337,10 +338,6 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) "Specifies the name of the deployment.", "Legt den Namen der Bereitstellung fest."); - builder.AddOrUpdate("Admin.Configuration.Export.Deployment.Name.Validate", - "Please enter the name of the deployment.", - "Bitte den Namen der Bereitstellung eingeben."); - builder.AddOrUpdate("Admin.Configuration.Export.Deployment.IsPublic", "Make public", "ffentlich machen", @@ -349,9 +346,9 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder) builder.AddOrUpdate("Admin.Configuration.Export.Deployment.DeploymentType", "Type of deployment", - "Typ der Bereitstellung", + "Art der Bereitstellung", "Specifies the deployment type.", - "Legt den Bereitstellungstyp fest."); + "Legt die Art Bereitstellung fest."); builder.AddOrUpdate("Admin.Configuration.Export.Deployment.Username", "User name", diff --git a/src/Libraries/SmartStore.Services/DataExchange/ExportService.cs b/src/Libraries/SmartStore.Services/DataExchange/ExportService.cs index d678942acc..b2e2a77d5d 100644 --- a/src/Libraries/SmartStore.Services/DataExchange/ExportService.cs +++ b/src/Libraries/SmartStore.Services/DataExchange/ExportService.cs @@ -150,6 +150,17 @@ public virtual Provider LoadProvider(string systemName, int sto return (provider.IsValid() ? provider : null); } + public virtual ExportDeployment GetExportDeploymentById(int id) + { + if (id == 0) + return null; + + var deployment = _exportDeploymentRepository.Table + .Expand(x => x.Profile) + .FirstOrDefault(x => x.Id == id); + + return deployment; + } public virtual void DeleteExportDeployment(ExportDeployment deployment) { diff --git a/src/Libraries/SmartStore.Services/DataExchange/IExportService.cs b/src/Libraries/SmartStore.Services/DataExchange/IExportService.cs index bb511ebc8d..a02512e322 100644 --- a/src/Libraries/SmartStore.Services/DataExchange/IExportService.cs +++ b/src/Libraries/SmartStore.Services/DataExchange/IExportService.cs @@ -56,9 +56,15 @@ public interface IExportService /// Export provider Provider LoadProvider(string systemName, int storeId = 0); + /// + /// Get export deployment by identifier + /// + /// Export deployment identifier + /// Export deployment + ExportDeployment GetExportDeploymentById(int id); /// - /// Deletes an export deployment + /// Deleted a export deployment /// /// Export deployment void DeleteExportDeployment(ExportDeployment deployment); diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs index 4a036ed0e5..754b4c2b95 100644 --- a/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs +++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ExportController.cs @@ -17,10 +17,12 @@ using SmartStore.Services.Directory; using SmartStore.Services.Localization; using SmartStore.Services.Media; +using SmartStore.Services.Messages; using SmartStore.Services.Security; using SmartStore.Web.Framework; using SmartStore.Web.Framework.Controllers; using SmartStore.Web.Framework.Plugins; +using SmartStore.Web.Framework.UI; using Telerik.Web.Mvc; namespace SmartStore.Admin.Controllers @@ -38,6 +40,7 @@ public class ExportController : AdminControllerBase private readonly ICustomerService _customerService; private readonly ILanguageService _languageService; private readonly ICurrencyService _currencyService; + private readonly IEmailAccountService _emailAccountService; public ExportController( ICommonServices services, @@ -49,7 +52,8 @@ public ExportController( IProductTagService productTagService, ICustomerService customerService, ILanguageService languageService, - ICurrencyService currencyService) + ICurrencyService currencyService, + IEmailAccountService emailAccountService) { _services = services; _exportService = exportService; @@ -61,6 +65,7 @@ public ExportController( _customerService = customerService; _languageService = languageService; _currencyService = currencyService; + _emailAccountService = emailAccountService; } #region Utilities @@ -77,27 +82,6 @@ private string GetThumbnailUrl(Provider provider) return url; } - private ExportDeploymentModel PrepareDeploymentModel(ExportDeployment deployment) - { - var model = new ExportDeploymentModel - { - Id = deployment.Id, - Name = deployment.Name, - Enabled = deployment.Enabled, - IsPublic = deployment.IsPublic, - DeploymentType = deployment.DeploymentType, - DeploymentTypeName = T("Enums.SmartStore.Core.Domain.DataExchange.ExportDeploymentType." + deployment.DeploymentType.ToString()), - Username = deployment.Username, - Password = deployment.Password, - Url = deployment.Url, - FileSystemPath = deployment.FileSystemPath, - EmailAddresses = deployment.EmailAddresses, - EmailSubject = deployment.EmailSubject, - EmailAccountId = deployment.EmailAccountId - }; - return model; - } - private void PrepareProfileModel(ExportProfileModel model, ExportProfile profile, Provider provider) { model.Id = profile.Id; @@ -122,7 +106,7 @@ private void PrepareProfileModel(ExportProfileModel model, ExportProfile profile model.Provider.Description = _pluginMediator.GetLocalizedDescription(provider.Metadata); model.Provider.EntityType = provider.Value.EntityType; - model.Provider.EntityTypeName = T("Enums.SmartStore.Core.Domain.DataExchange.ExportEntityType." + provider.Value.EntityType.ToString()); + model.Provider.EntityTypeName = provider.Value.EntityType.GetLocalizedEnum(_services.Localization, _services.WorkContext); model.Provider.FileType = provider.Value.FileType.ToUpper(); } } @@ -254,9 +238,69 @@ private void PrepareProfileModelForEdit(ExportProfileModel model, ExportProfile initModelBase(model.OrderFilter); } + } + + private ExportDeploymentModel PrepareDeploymentModel(ExportDeployment deployment) + { + var allEmailAccounts = _emailAccountService.GetAllEmailAccounts(); - // deplyoment - model.Deployments = profile.Deployments.Select(x => PrepareDeploymentModel(x)).ToList(); + var model = new ExportDeploymentModel + { + Id = deployment.Id, + ProfileId = deployment.ProfileId, + Name = deployment.Name, + Enabled = deployment.Enabled, + IsPublic = deployment.IsPublic, + DeploymentType = deployment.DeploymentType, + DeploymentTypeName = deployment.DeploymentType.GetLocalizedEnum(_services.Localization, _services.WorkContext), + Username = deployment.Username, + Password = deployment.Password, + Url = deployment.Url, + FileSystemPath = deployment.FileSystemPath, + EmailAddresses = deployment.EmailAddresses, + EmailSubject = deployment.EmailSubject, + EmailAccountId = deployment.EmailAccountId + }; + + model.AvailableDeploymentTypes = ExportDeploymentType.FileSystem.ToSelectList(false).ToList(); + + model.AvailableEmailAccounts = allEmailAccounts + .Select(x => new SelectListItem { Text = x.FriendlyName, Value = x.Id.ToString() }) + .ToList(); + + return model; + } + + private void ModelToEntity(ExportDeploymentModel model, ExportDeployment deployment) + { + deployment.ProfileId = model.ProfileId; + deployment.Name = model.Name; + deployment.Enabled = model.Enabled; + deployment.DeploymentType = model.DeploymentType; + deployment.IsPublic = model.IsPublic; + deployment.Username = model.Username; + deployment.Password = model.Password; + deployment.Url = model.Url; + deployment.FileSystemPath = model.FileSystemPath; + deployment.EmailAddresses = model.EmailAddresses; + deployment.EmailSubject = model.EmailSubject; + deployment.EmailAccountId = model.EmailAccountId; + } + + private ActionResult SmartRedirect(bool continueEditing, int profileId, int deploymentId) + { + if (!continueEditing) + { + TempData["SelectedTab.export-profile-edit"] = new SelectedTabInfo + { + TabId = "export-profile-edit-6", + Path = Url.Action("Edit", new { id = profileId }) + }; + } + + return (continueEditing ? + RedirectToAction("EditDeployment", new { id = deploymentId }) : + RedirectToAction("Edit", new { id = profileId })); } #endregion @@ -544,16 +588,132 @@ public ActionResult DeploymentList(GridCommand command, int id) { model.Total = profile.Deployments.Count; - model.Data = profile.Deployments.Select(x => PrepareDeploymentModel(x)).ToList(); + model.Data = profile.Deployments.Select(x => + { + var deploymentModel = new ExportDeploymentModel + { + Id = x.Id, + ProfileId = profile.Id, + Name = x.Name, + Enabled = x.Enabled, + DeploymentType = x.DeploymentType, + DeploymentTypeName = x.DeploymentType.GetLocalizedEnum(_services.Localization, _services.WorkContext) + }; + return deploymentModel; + }).ToList(); } } return new JsonResult { Data = model }; } - public ActionResult DeploymentEdit(int id) + public ActionResult CreateDeployment(int id) { - return null; + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + var profile = _exportService.GetExportProfileById(id); + if (profile == null) + return RedirectToAction("List"); + + var fileSystemName = ExportDeploymentType.FileSystem.GetLocalizedEnum(_services.Localization, _services.WorkContext); + + var model = PrepareDeploymentModel(new ExportDeployment + { + ProfileId = id, + Enabled = true, + DeploymentType = ExportDeploymentType.FileSystem, + Name = profile.Name + }); + + return View(model); + } + + [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] + [FormValueRequired("save", "save-continue")] + public ActionResult CreateDeployment(ExportDeploymentModel model, bool continueEditing, ExportDeploymentType deploymentType) + { + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + var profile = _exportService.GetExportProfileById(model.ProfileId); + if (profile == null) + return RedirectToAction("List"); + + if (ModelState.IsValid) + { + var deployment = new ExportDeployment(); + + ModelToEntity(model, deployment); + + profile.Deployments.Add(deployment); + + _exportService.UpdateExportProfile(profile); + + return SmartRedirect(continueEditing, profile.Id, deployment.Id); + } + + return CreateDeployment(profile.Id); + } + + public ActionResult EditDeployment(int id) + { + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + var deployment = _exportService.GetExportDeploymentById(id); + if (deployment == null) + return RedirectToAction("List"); + + var model = PrepareDeploymentModel(deployment); + + return View(model); + } + + [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")] + [FormValueRequired("save", "save-continue")] + public ActionResult EditDeployment(ExportDeploymentModel model, bool continueEditing) + { + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + var deployment = _exportService.GetExportDeploymentById(model.Id); + if (deployment == null) + return RedirectToAction("List"); + + if (ModelState.IsValid) + { + ModelToEntity(model, deployment); + + _exportService.UpdateExportProfile(deployment.Profile); + + NotifySuccess(T("Admin.Common.DataSuccessfullySaved")); + + return SmartRedirect(continueEditing, deployment.ProfileId, deployment.Id); + } + + model = PrepareDeploymentModel(deployment); + + return View(model); + } + + [HttpPost] + public ActionResult DeleteDeployment(int id) + { + if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageExports)) + return AccessDeniedView(); + + var deployment = _exportService.GetExportDeploymentById(id); + if (deployment == null) + return RedirectToAction("List"); + + int profileId = deployment.ProfileId; + + _exportService.DeleteExportDeployment(deployment); + + NotifySuccess(T("Admin.Common.TaskSuccessfullyProcessed")); + + return SmartRedirect(false, profileId, 0); } #endregion diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportDeploymentModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportDeploymentModel.cs index df0c40302e..d73036f76d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportDeploymentModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportDeploymentModel.cs @@ -1,4 +1,6 @@ -using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Web.Mvc; using FluentValidation.Attributes; using SmartStore.Admin.Validators.DataExchange; using SmartStore.Core.Domain.DataExchange; @@ -10,6 +12,8 @@ namespace SmartStore.Admin.Models.DataExchange [Validator(typeof(ExportDeploymentValidator))] public class ExportDeploymentModel : EntityModelBase { + public int ProfileId { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.Name")] public string Name { get; set; } @@ -18,9 +22,32 @@ public class ExportDeploymentModel : EntityModelBase [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.DeploymentType")] public ExportDeploymentType DeploymentType { get; set; } + public List AvailableDeploymentTypes { get; set; } + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.DeploymentType")] public string DeploymentTypeName { get; set; } + public string DeploymentTypeIconClass + { + get + { + switch (DeploymentType) + { + case ExportDeploymentType.FileSystem: + return "fa-folder-open-o"; + case ExportDeploymentType.Email: + return "fa-envelope-o"; + case ExportDeploymentType.Http: + return "fa-globe"; + case ExportDeploymentType.Ftp: + return "fa-clone"; + default: + return "fa-question"; + } + } + } + + [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.IsPublic")] public bool IsPublic { get; set; } @@ -45,5 +72,6 @@ public class ExportDeploymentModel : EntityModelBase [SmartResourceDisplayName("Admin.Configuration.Export.Deployment.EmailAccountId")] public int EmailAccountId { get; set; } + public List AvailableEmailAccounts { get; set; } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs index 77f5ff7b6d..71a6a8e85d 100644 --- a/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs +++ b/src/Presentation/SmartStore.Web/Administration/Models/DataExchange/ExportProfileModel.cs @@ -56,7 +56,6 @@ public partial class ExportProfileModel : EntityModelBase public List Deployments { get; set; } - public class ProviderModel { public string ConfigPartialViewName { get; set; } diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj index b7bcbd5add..5df7d83edd 100644 --- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj +++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj @@ -510,6 +510,9 @@ + + + diff --git a/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportDeplomentValidator.cs b/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportDeplomentValidator.cs index 4f1539698d..4caa43d099 100644 --- a/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportDeplomentValidator.cs +++ b/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportDeplomentValidator.cs @@ -1,5 +1,6 @@ using FluentValidation; using SmartStore.Admin.Models.DataExchange; +using SmartStore.Core.Domain.DataExchange; using SmartStore.Services.Localization; namespace SmartStore.Admin.Validators.DataExchange @@ -10,7 +11,32 @@ public ExportDeploymentValidator(ILocalizationService localization) { RuleFor(x => x.Name) .NotEmpty() - .WithMessage(localization.GetResource("Admin.Configuration.Export.Deployment.Name.Validate")); + .WithMessage(localization.GetResource("Admin.Validation.Name")); + + RuleFor(x => x.EmailAddresses) + .NotEmpty() + .When(x => x.DeploymentType == ExportDeploymentType.Email) + .WithMessage(localization.GetResource("Admin.Validation.EmailAddress")); + + RuleFor(x => x.Url) + .NotEmpty() + .When(x => x.DeploymentType == ExportDeploymentType.Http) + .WithMessage(localization.GetResource("Admin.Validation.Url")); + + RuleFor(x => x.Url) + .Matches(RegularExpressions.IsWebUrl) + .When(x => x.DeploymentType == ExportDeploymentType.Http) + .WithMessage(localization.GetResource("Admin.Validation.Url")); + + RuleFor(x => x.Username) + .NotEmpty() + .When(x => x.DeploymentType == ExportDeploymentType.Ftp) + .WithMessage(localization.GetResource("Admin.Validation.UsernamePassword")); + + RuleFor(x => x.Password) + .NotEmpty() + .When(x => x.DeploymentType == ExportDeploymentType.Ftp) + .WithMessage(localization.GetResource("Admin.Validation.UsernamePassword")); } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportProfileValidator.cs b/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportProfileValidator.cs index d0a1e14ca1..4fa8d0a556 100644 --- a/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportProfileValidator.cs +++ b/src/Presentation/SmartStore.Web/Administration/Validators/DataExchange/ExportProfileValidator.cs @@ -10,7 +10,7 @@ public ExportProfileValidator(ILocalizationService localization) { RuleFor(x => x.Name) .NotEmpty() - .WithMessage(localization.GetResource("Admin.Configuration.Export.Name.Validate")); + .WithMessage(localization.GetResource("Admin.Validation.Name")); } } } \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/CreateDeployment.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/CreateDeployment.cshtml new file mode 100644 index 0000000000..79f904409e --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/CreateDeployment.cshtml @@ -0,0 +1,21 @@ +@model ExportDeploymentModel +@using SmartStore.Core.Domain.DataExchange; +@using SmartStore.Admin.Models.DataExchange; +@{ + var title = string.Concat(T("Common.AddNew"), " ", T("Common.Deployment")); + ViewBag.Title = title; +} + +@using (Html.BeginForm()) +{ +
    +
    + @title @Html.ActionLink("(" + T("Common.Back") + ")", "Edit", new { id = Model.ProfileId }) +
    +
    + + +
    +
    + @Html.Partial("_CreateOrUpdateDeployment", Model) +} \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml index 7bf4b772b2..e284d1f9db 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/Edit.cshtml @@ -474,17 +474,19 @@ }
    - @(Html.Telerik().Grid(Model.Deployments) + @(Html.Telerik().Grid() .Name("export-deployment-grid") .DataKeys(keys => keys.Add(x => x.Id) .RouteKey("Id")) .Columns(columns => { columns.Bound(x => x.Name) - .Width(400) - .Template(x => Html.ActionLink(x.Name, "DeploymentEdit", new { id = x.Id })) - .ClientTemplate("\"><#= Name #>"); - columns.Bound(x => x.DeploymentTypeName); + .Template(x => Html.ActionLink(x.Name, "EditDeployment", "Export", new { id = x.Id }, null)) + .ClientTemplate("\"><#= Name #>"); + columns.Bound(x => x.DeploymentTypeName) + .Template(x => " {1}".FormatInvariant(x.DeploymentTypeIconClass, x.DeploymentTypeName)) + .ClientTemplate(" <#= DeploymentTypeName #>") + .Width(320); columns.Bound(x => x.Enabled) .Width(100) .Template(item => @Html.SymbolForBool(item.Enabled)) @@ -494,8 +496,8 @@ .ToolBar(commands => { commands.Custom() - .Name("export-deployment-insert-button") - .HtmlAttributes(new { @class = "btn btn-primary" }) + .Name("export-deployment-add-button") + .HtmlAttributes(new { @class = "btn btn-primary", href = @Url.Action("CreateDeployment", new { id = Model.Id }) }) .Text(" " + @T("Common.AddNew")); }) .DataBinding(dataBinding => dataBinding.Ajax().Select("DeploymentList", "Export", new { id = Model.Id })) @@ -520,7 +522,7 @@ @Html.SmartLabelFor(x => x.CompletedEmailAddresses) - @Html.EditorFor(x => x.CompletedEmailAddresses, new { @class = "control-xlarge" }) + @Html.EditorFor(x => x.CompletedEmailAddresses) @Html.ValidationMessageFor(x => x.CompletedEmailAddresses) diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/EditDeployment.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/EditDeployment.cshtml new file mode 100644 index 0000000000..356ded774d --- /dev/null +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/EditDeployment.cshtml @@ -0,0 +1,26 @@ +@model ExportDeploymentModel +@using SmartStore.Core.Domain.DataExchange; +@using SmartStore.Admin.Models.DataExchange; +@{ + var title = string.Concat(T("Admin.Common.Edit"), " ", T("Common.Deployment")); + ViewBag.Title = title; +} + +@using (Html.BeginForm()) +{ +
    +
    + @title - @Model.Name @Html.ActionLink("(" + T("Common.Back") + ")", "Edit", new { id = Model.ProfileId }) +
    +
    + + + +
    +
    + @Html.Partial("_CreateOrUpdateDeployment", Model) +} + +@Html.DeleteConfirmation("DeleteDeployment", "export-deployment-delete") \ No newline at end of file diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml index 9c04d96eba..6856f83fbc 100644 --- a/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml +++ b/src/Presentation/SmartStore.Web/Administration/Views/Export/List.cshtml @@ -70,7 +70,7 @@
    -