diff --git a/README.md b/README.md
index d3402dc825..a7a83aee3a 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ A comprehensive set of tools for CRM & CMS, sales, marketing, payment & shipping
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 ;-)
-* **Website:** [http://www.smartstore.com/net](http://www.smartstore.com/net)
+* **Website:** [http://www.smartstore.com/en/net](http://www.smartstore.com/en/net)
* **Forum:** [http://community.smartstore.com](http://community.smartstore.com)
* **Marketplace:** [http://community.smartstore.com/marketplace](http://community.smartstore.com/marketplace)
* **Documentation:** [SmartStore.NET Documentation in English](http://docs.smartstore.com/display/SMNET/SmartStore.NET+Documentation+Home)
diff --git a/SmartStoreNET.Tasks.Targets b/SmartStoreNET.Tasks.Targets
index 4fb755fcf5..f184eaa7eb 100644
--- a/SmartStoreNET.Tasks.Targets
+++ b/SmartStoreNET.Tasks.Targets
@@ -44,7 +44,7 @@
x86
$(BUILD_NUMBER)
- 2.5.0
+ 2.6.0
$(StageFolder)
.$(Version)
diff --git a/build.bat b/build.bat
index 2cee9dc2b5..b58175809a 100644
--- a/build.bat
+++ b/build.bat
@@ -5,7 +5,11 @@ FOR %%b in (
"%VS120COMNTOOLS%..\..\VC\vcvarsall.bat"
"%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
- "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
+ "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
+
+ "%VS110COMNTOOLS%..\..\VC\vcvarsall.bat"
+ "%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"
+ "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"
) do (
if exist %%b (
call %%b x86
diff --git a/changelog.md b/changelog.md
index 3c618df80f..0dac88a9fd 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,28 +1,69 @@
-# Release Notes
+# Release Notes
-## SmartStore.NET 2.5.1
+## SmartStore.NET 2.6
+
+### Highlights
+* Major improvements in Importer & Exporter: better field mapping, higher performance, bug fixes etc.
+* 'PayPal PLUS' payment plugin
+* 'paydirekt' payment plugin
+* 'Viveum' payment plugin
+* 'BeezUP' export provider
+* (Dev) Publishing SmartStore.Web from within Visual Studio now deploys the project correctly. No need to execute ClickToBuild.cmd anymore. Just publish directly to any target, including Azure.
### New Features
+* #961 Fix "Open Redirection Vulnerability"
* #571 Option to display another checkbox on confirm page to let the customer accept that his email address can be handed over to a third party
* #870 Implement address import for customers (both billing & shipping address)
* #886 Add setting to hide manufacturer images on product detail page and to hide default image for manufacturers
* Import localized SEO names for product and categories
+* #477 Implement option to specify the number of exported and imported pictures
+* #859 Make checkout attributes suitable for multi-stores
+* Product details: Select attribute and gift card values by query string parameters
+* #950 make contact form comply with current German law
### Improvements
+* Major improvements in Importer: better field mapping, higher performance, bug fixes etc.
* (Dev) Publishing SmartStore.Web from within Visual Studio now deploys the project correctly. No need to execute ClickToBuild.cmd anymore. Just publish directly to any target, including Azure.
* Localization & SEO: language switcher now takes language specific SEO slugs into account when building links
+* Smarter import of plugin resource files with graceful fallbacks (de-DE > de > de-* > en-US > en > en-* > *)
+* (Perf) Faster language resource file import
* Exports the product detail link including the attribute query string when exporting attribute combinations
* #918 Compare products: Display base price information
+* Export email attachments needs to be stored in database because the temp file may not exist anymore when sending the email
+* #913 Use HTML5 Input types (tel, email)
+* Added paging to frontend order list
+* Added paging to backend checkout attribute list
+* #977 Show PAngV base/delivery amount also
+* Updated LiveEngage LiveChat plugin
### Bugfixes
+* TaskScheduler could fail polling when primary store url is an external IP address
* Fixed ajax cache issue when saving payment or shipping restrictions. Internet Explorer showed the old data state (before storage).
* "The provider failed at the Execute method: Member 'CurrentValues' cannot be called for the entity of type 'Product'" when exporting product attribute combinations
* Bundles without selected attributes could throw an exception on product detail page
-* GMC feed did not export the product type (category path)
+* GMC feed did not export the product type and Billiger did not export shop_cat (category path)
* The error message of a payment provider when capturing a payment was not displayed
-* Adding new shipping method throws an exception
+* Adding new shipping method threw an exception
* Attribute Values: Assigning IsPreselected to more than one value causes an error
* BizImporter: fixed redirection bug when default file extension in .biz wasn't .html
+* Fixed: Export deployment emails were always send manually
+* Manually notifying gift card recipient threw an exception
+* Loading shipping by weight grid failed under SQL CE
+* #949 Import: ProcessSlugs does not process explicitly specified "SeName", if product name did not change in an update scenario
+* Customer import: Creates customer role duplicates for inserted customers
+* GMC feed does not generate the sale price if the sale price is set for a future date
+* Mobile devices: Fixed "Uncaught Error: Syntax error, unrecognized expression: :nth-child"
+* Download nor sample download were removable when editing product
+* Copied product must not share sample download of source product. Could produce "The DELETE statement conflicted with the REFERENCE constraint 'FK_dbo.Product_dbo.Download_SampleDownloadId'".
+* #921 Specification attribute options with single quotation marks are causing a Javascript error
+* #971 Product is added to cart automatically if it has a non-required file upload attribute
+* #973 Bundle item upload is nowhere linked
+* Base price in product list ignored PriceDisplayType (catalog settings) and possibly displayed the wrong base price info
+* Private messages: Fixes "No route in the route table matches the supplied values"
+* Payone: Hash string incorrect for frontend API payments where the order has more than 9 products
+* Export mail notification: Download link not working if SSL is enabled
+* Discount rule has spent amount including sub total option can cause wrong discount calculation if the cart contains a product several times
+* #986 File uploads possible through /content/filemanager/index.html
## SmartStore.NET 2.5
diff --git a/lib/SmartStore.Licensing/SmartStore.Licensing.dll b/lib/SmartStore.Licensing/SmartStore.Licensing.dll
index 51e391ce23..8acdf39c24 100644
Binary files a/lib/SmartStore.Licensing/SmartStore.Licensing.dll and b/lib/SmartStore.Licensing/SmartStore.Licensing.dll differ
diff --git a/src/AssemblyVersionInfo.cs b/src/AssemblyVersionInfo.cs
index 67335b18c1..f74f0edf78 100644
--- a/src/AssemblyVersionInfo.cs
+++ b/src/AssemblyVersionInfo.cs
@@ -9,7 +9,7 @@
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("2.5.0.0")]
+[assembly: AssemblyVersion("2.6.0.0")]
-[assembly: AssemblyFileVersion("2.5.0.0")]
-[assembly: AssemblyInformationalVersion("2.5.0.0")]
+[assembly: AssemblyFileVersion("2.6.0.0")]
+[assembly: AssemblyInformationalVersion("2.6.0.0")]
diff --git a/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs b/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs
index 66b12e67f8..789c363da0 100644
--- a/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs
+++ b/src/Libraries/SmartStore.Core/Collections/LazyMultimap.cs
@@ -99,7 +99,7 @@ public virtual void Collect(IEnumerable keys)
}
///
- /// Collect single key for combinde loading
+ /// Collect single key for combined loading
///
/// Data key
public virtual void Collect(int key)
diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs
index 50fd39fe5a..999f66bad3 100644
--- a/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs
@@ -191,6 +191,7 @@ public string Sku
/// Gets or sets the manufacturer part number
///
[DataMember]
+ [Index]
public string ManufacturerPartNumber
{
[DebuggerStepThrough]
@@ -208,6 +209,7 @@ public string ManufacturerPartNumber
/// Gets or sets the Global Trade Item Number (GTIN). These identifiers include UPC (in North America), EAN (in Europe), JAN (in Japan), and ISBN (for books).
///
[DataMember]
+ [Index]
public string Gtin
{
[DebuggerStepThrough]
diff --git a/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs b/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs
index d0dbf678e5..e6d7f56f56 100644
--- a/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs
@@ -24,6 +24,7 @@ public CustomerSettings()
NewsletterEnabled = true;
OnlineCustomerMinutes = 20;
StoreLastVisitedPage = true;
+ DisplayPrivacyAgreementOnContactUs = false;
}
///
@@ -151,6 +152,11 @@ public CustomerSettings()
///
public bool StoreLastVisitedPage { get; set; }
+ ///
+ /// Gets or sets a value indicating whether to display a checkbox to the customer where he can agree to privacy terms
+ ///
+ public bool DisplayPrivacyAgreementOnContactUs { get; set; }
+
#region Form fields
///
diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportDeployment.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportDeployment.cs
index 3b8190d6a4..b9e323c670 100644
--- a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportDeployment.cs
+++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportDeployment.cs
@@ -21,14 +21,9 @@ public class ExportDeployment : BaseEntity, ICloneable
public bool Enabled { get; set; }
///
- /// Whether to deploy in a folder that can be reached from the internet
+ /// XML with information about the last deployment result
///
- public bool IsPublic { get; set; }
-
- ///
- /// Whether to create a zip archive with the content of the export
- ///
- public bool CreateZip { get; set; }
+ public string ResultInfo { get; set; }
///
/// The deployment type identifier
@@ -84,6 +79,11 @@ public ExportHttpTransmissionType HttpTransmissionType
///
public string FileSystemPath { get; set; }
+ ///
+ /// Path of a subfolder
+ ///
+ public string SubFolder { get; set; }
+
///
/// Multiple email addresses can be separated by commas
///
@@ -117,14 +117,13 @@ public ExportDeployment Clone()
{
Name = this.Name,
Enabled = this.Enabled,
- IsPublic = this.IsPublic,
- CreateZip = this.CreateZip,
DeploymentTypeId = this.DeploymentTypeId,
Username = this.Username,
Password = this.Password,
Url = this.Url,
HttpTransmissionTypeId = this.HttpTransmissionTypeId,
FileSystemPath = this.FileSystemPath,
+ SubFolder = this.SubFolder,
EmailAddresses = this.EmailAddresses,
EmailSubject = this.EmailSubject,
EmailAccountId = this.EmailAccountId,
diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportEnums.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportEnums.cs
index 49e6991353..6ea68ec73c 100644
--- a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportEnums.cs
+++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportEnums.cs
@@ -23,7 +23,8 @@ public enum ExportDeploymentType
FileSystem = 0,
Email,
Http,
- Ftp
+ Ftp,
+ PublicFolder
}
///
@@ -125,7 +126,12 @@ public enum ExportFeatures
///
/// Whether to not automatically send a completion email
///
- CanOmitCompletionMail = 1 << 12
+ CanOmitCompletionMail = 1 << 12,
+
+ ///
+ /// Whether to provide additional data of attribute combinations
+ ///
+ UsesAttributeCombination = 1 << 13
}
///
diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs
index b49d8d76d1..3161d1ea94 100644
--- a/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs
+++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ExportProfile.cs
@@ -23,7 +23,7 @@ public ExportProfile()
public string Name { get; set; }
///
- /// The name of the folder (file system)
+ /// The root path of the export folder
///
public string FolderName { get; set; }
diff --git a/src/Libraries/SmartStore.Core/Domain/DataExchange/ImportProfile.cs b/src/Libraries/SmartStore.Core/Domain/DataExchange/ImportProfile.cs
index b642e3d50d..1139496b4a 100644
--- a/src/Libraries/SmartStore.Core/Domain/DataExchange/ImportProfile.cs
+++ b/src/Libraries/SmartStore.Core/Domain/DataExchange/ImportProfile.cs
@@ -85,6 +85,11 @@ public ImportEntityType EntityType
///
public string FileTypeConfiguration { get; set; }
+ ///
+ /// XML with extra data
+ ///
+ public string ExtraData { get; set; }
+
///
/// Mapping of import columns
///
diff --git a/src/Libraries/SmartStore.Core/Domain/Media/MediaSettings.cs b/src/Libraries/SmartStore.Core/Domain/Media/MediaSettings.cs
index cee3019aa8..b3072c0912 100644
--- a/src/Libraries/SmartStore.Core/Domain/Media/MediaSettings.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Media/MediaSettings.cs
@@ -18,7 +18,7 @@ public MediaSettings()
CartThumbPictureSize = 80;
CartThumbBundleItemPictureSize = 32;
MiniCartThumbPictureSize = 32;
- AutoCompleteSearchThumbPictureSize = 20;
+ VariantValueThumbPictureSize = 20;
MaximumImageSize = 1280;
DefaultPictureZoomEnabled = true;
PictureZoomType = "window";
@@ -38,7 +38,7 @@ public MediaSettings()
public int CartThumbPictureSize { get; set; }
public int CartThumbBundleItemPictureSize { get; set; }
public int MiniCartThumbPictureSize { get; set; }
- public int AutoCompleteSearchThumbPictureSize { get; set; }
+ public int VariantValueThumbPictureSize { get; set; }
public bool DefaultPictureZoomEnabled { get; set; }
public string PictureZoomType { get; set; }
diff --git a/src/Libraries/SmartStore.Core/Domain/Orders/CheckoutAttribute.cs b/src/Libraries/SmartStore.Core/Domain/Orders/CheckoutAttribute.cs
index a317879baa..63cbf58ea8 100644
--- a/src/Libraries/SmartStore.Core/Domain/Orders/CheckoutAttribute.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Orders/CheckoutAttribute.cs
@@ -1,14 +1,15 @@
using System.Collections.Generic;
using SmartStore.Core.Domain.Catalog;
using SmartStore.Core.Domain.Localization;
+using SmartStore.Core.Domain.Stores;
namespace SmartStore.Core.Domain.Orders
{
- ///
- /// Represents a checkout attribute
- ///
- public partial class CheckoutAttribute : BaseEntity, ILocalizedEntity
- {
+ ///
+ /// Represents a checkout attribute
+ ///
+ public partial class CheckoutAttribute : BaseEntity, ILocalizedEntity, IStoreMappingSupported
+ {
private ICollection _checkoutAttributeValues;
public CheckoutAttribute()
@@ -60,11 +61,16 @@ public CheckoutAttribute()
/// Gets or sets whether the checkout attribute is active
///
public bool IsActive { get; set; }
-
- ///
- /// Gets the attribute control type
- ///
- public AttributeControlType AttributeControlType
+
+ ///
+ /// Gets or sets a value indicating whether the entity is limited/restricted to certain stores
+ ///
+ public bool LimitedToStores { get; set; }
+
+ ///
+ /// Gets the attribute control type
+ ///
+ public AttributeControlType AttributeControlType
{
get
{
@@ -75,6 +81,7 @@ public AttributeControlType AttributeControlType
this.AttributeControlTypeId = (int)value;
}
}
+
///
/// Gets the checkout attribute values
///
diff --git a/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs b/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs
index d59871a751..9db5f14733 100644
--- a/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Orders/Order.cs
@@ -451,7 +451,7 @@ protected virtual SortedDictionary ParseTaxRates(string taxRat
public int? RewardPointsRemaining { get; set; }
///
- /// Gets or sets a value indicating whether a new payment notification (IPN) arrived
+ /// Gets or sets a value indicating whether a new payment notification arrived (IPN, webhook, callback etc.)
///
[DataMember]
public bool HasNewPaymentNotification { get; set; }
diff --git a/src/Libraries/SmartStore.Core/Domain/Orders/OrderSettings.cs b/src/Libraries/SmartStore.Core/Domain/Orders/OrderSettings.cs
index 996271de79..05e9a49fd4 100644
--- a/src/Libraries/SmartStore.Core/Domain/Orders/OrderSettings.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Orders/OrderSettings.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using SmartStore.Core.Configuration;
+using SmartStore.Core.Configuration;
using SmartStore.Core.Domain.Localization;
namespace SmartStore.Core.Domain.Orders
@@ -16,6 +15,7 @@ public OrderSettings()
ReturnRequestReasons = "Received Wrong Product,Wrong Product Ordered,There Was A Problem With The Product";
NumberOfDaysReturnRequestAvailable = 365;
MinimumOrderPlacementInterval = 30;
+ OrderListPageSize = 10;
}
///
@@ -87,5 +87,10 @@ public OrderSettings()
/// Gets or sets a value indicating whether to display all orders of all stores to a customer
///
public bool DisplayOrdersOfAllStores { get; set; }
+
+ ///
+ /// Page size of the order list
+ ///
+ public int OrderListPageSize { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Libraries/SmartStore.Core/Email/SmtpContext.cs b/src/Libraries/SmartStore.Core/Email/SmtpContext.cs
index 796e642109..054487610f 100644
--- a/src/Libraries/SmartStore.Core/Email/SmtpContext.cs
+++ b/src/Libraries/SmartStore.Core/Email/SmtpContext.cs
@@ -73,6 +73,8 @@ public SmtpClient ToSmtpClient()
smtpClient.UseDefaultCredentials = this.UseDefaultCredentials;
smtpClient.EnableSsl = this.EnableSsl;
+ smtpClient.Timeout = 10000;
+
if (this.UseDefaultCredentials)
{
smtpClient.Credentials = CredentialCache.DefaultNetworkCredentials;
diff --git a/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs
index c83270e71f..033c5d4230 100644
--- a/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs
+++ b/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs
@@ -24,7 +24,7 @@ public static void Dump(this Exception exception)
public static string ToAllMessages(this Exception exception)
{
var sb = new StringBuilder();
-
+
while (exception != null)
{
if (!sb.ToString().EmptyNull().Contains(exception.Message))
diff --git a/src/Libraries/SmartStore.Core/Extensions/StringExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/StringExtensions.cs
index 5a172fc17f..9131705215 100644
--- a/src/Libraries/SmartStore.Core/Extensions/StringExtensions.cs
+++ b/src/Libraries/SmartStore.Core/Extensions/StringExtensions.cs
@@ -490,16 +490,19 @@ public static string[] SplitSafe(this string value, string separator)
/// true: success, false: failure
[DebuggerStepThrough]
[SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")]
- public static bool SplitToPair(this string value, out string strLeft, out string strRight, string delimiter) {
+ public static bool SplitToPair(this string value, out string strLeft, out string strRight, string delimiter)
+ {
int idx = -1;
- if (value.IsEmpty() || delimiter.IsEmpty() || (idx = value.IndexOf(delimiter)) == -1)
+ if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(delimiter) || (idx = value.IndexOf(delimiter)) == -1)
{
strLeft = value;
strRight = "";
return false;
}
+
strLeft = value.Substring(0, idx);
strRight = value.Substring(idx + delimiter.Length);
+
return true;
}
diff --git a/src/Libraries/SmartStore.Core/IWebHelper.cs b/src/Libraries/SmartStore.Core/IWebHelper.cs
index 03b4f128c8..2d089bd64d 100644
--- a/src/Libraries/SmartStore.Core/IWebHelper.cs
+++ b/src/Libraries/SmartStore.Core/IWebHelper.cs
@@ -13,11 +13,21 @@ public partial interface IWebHelper
/// URL referrer
string GetUrlReferrer();
- ///
- /// Get context IP address
- ///
- /// URL referrer
- string GetCurrentIpAddress();
+ ///
+ /// Gets a unique client identifier
+ ///
+ /// A unique identifier
+ ///
+ /// The client identifier is a hashed combination of client ip address and user agent.
+ /// This method returns null if IP or user agent (or both) cannot be determined.
+ ///
+ string GetClientIdent();
+
+ ///
+ /// Get context IP address
+ ///
+ /// URL referrer
+ string GetCurrentIpAddress();
///
/// Gets this page name
diff --git a/src/Libraries/SmartStore.Core/IWorkContext.cs b/src/Libraries/SmartStore.Core/IWorkContext.cs
index d3a54cf702..e137ac98bd 100644
--- a/src/Libraries/SmartStore.Core/IWorkContext.cs
+++ b/src/Libraries/SmartStore.Core/IWorkContext.cs
@@ -59,10 +59,5 @@ public interface IWorkContext
/// Gets or sets a value indicating whether we're in admin area
///
bool IsAdmin { get; set; }
-
- /////
- ///// Gets a value indicating whether we're in the public shop
- /////
- //bool IsPublic { get; }
- }
+ }
}
diff --git a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs
index 7b1bbc9292..f39bbeedeb 100644
--- a/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs
+++ b/src/Libraries/SmartStore.Core/Infrastructure/DependencyManagement/ContainerManager.cs
@@ -95,7 +95,7 @@ public object ResolveUnregistered(Type type, ILifetimeScope scope = null)
}
}
- throw new SmartException("No contructor was found that had all the dependencies satisfied.");
+ throw new SmartException("No constructor for {0} was found that had all the dependencies satisfied.".FormatInvariant(type.Name.NaIfEmpty()));
}
private bool TryResolveAll(Type[] types, out object[] instances, ILifetimeScope scope = null)
diff --git a/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs b/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs
index e0baba6444..fb8a10be35 100644
--- a/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs
+++ b/src/Libraries/SmartStore.Core/Logging/LoggingExtensions.cs
@@ -47,7 +47,6 @@ public static void ErrorsAll(this ILogger logger, Exception exception, Customer
while (exception != null)
{
FilteredLog(logger, LogLevel.Error, exception.Message, exception.StackTrace, exception, customer);
-
exception = exception.InnerException;
}
}
@@ -62,7 +61,7 @@ private static void FilteredLog(ILogger logger, LogLevel level, string message,
{
if (exception != null && fullMessage.IsEmpty())
{
- fullMessage = exception.StackTrace;
+ fullMessage = "{0}\n{1}\n{2}".FormatCurrent(exception.Message, new String('-', 20), exception.StackTrace);
}
logger.InsertLog(level, message, fullMessage, customer);
diff --git a/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs b/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs
index 3b8f7a4657..593a39ddb0 100644
--- a/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs
+++ b/src/Libraries/SmartStore.Core/Logging/TraceLogger.cs
@@ -30,6 +30,8 @@ public TraceLogger(string fileName)
console.Filter = new EventTypeFilter(SourceLevels.All);
console.Name = "console";
+ _traceSource.Listeners.Add(console);
+
var textListener = new TextWriterTraceListener(fileName);
textListener.Filter = new EventTypeFilter(SourceLevels.All);
textListener.TraceOutputOptions = TraceOptions.DateTime;
@@ -41,17 +43,19 @@ public TraceLogger(string fileName)
_streamWriter = new StreamWriter(fileName, append, Encoding.UTF8);
textListener.Writer = _streamWriter;
+
+ _traceSource.Listeners.Add(textListener);
+ }
+ catch (IOException)
+ {
+ // file is locked by another process
}
- catch (IOException) { }
- _traceSource.Listeners.Add(console);
- _traceSource.Listeners.Add(textListener);
-
- // Allow the trace source to send messages to
- // listeners for all event types. Currently only
+ // Allow the trace source to send messages to
+ // listeners for all event types. Currently only
// error messages or higher go to the listeners.
- // Messages must get past the source switch to
- // get to the listeners, regardless of the settings
+ // Messages must get past the source switch to
+ // get to the listeners, regardless of the settings
// for the listeners.
_traceSource.Switch.Level = SourceLevels.All;
}
diff --git a/src/Libraries/SmartStore.Core/SmartStoreVersion.cs b/src/Libraries/SmartStore.Core/SmartStoreVersion.cs
index df3c302220..38750e3069 100644
--- a/src/Libraries/SmartStore.Core/SmartStoreVersion.cs
+++ b/src/Libraries/SmartStore.Core/SmartStoreVersion.cs
@@ -23,9 +23,10 @@ public static class SmartStoreVersion
new Version("2.5")
};
- private const string HELP_BASEURL = "http://docs.smartstore.com/display/SMNET25/";
+ //private const string HELP_BASEURL = "http://docs.smartstore.com/display/SMNET25/";
+ private const string HELP_BASEURL = "http://docs.smartstore.com/display/";
- static SmartStoreVersion()
+ static SmartStoreVersion()
{
s_breakingChangesHistory.Reverse();
@@ -67,9 +68,18 @@ public static Version Version
}
}
- public static string GenerateHelpUrl(string path)
+ public static string GenerateHelpUrl(string languageCode, string path)
{
- return HELP_BASEURL + path.Trim().TrimStart('/', '\\');
+ return String.Concat(
+ HELP_BASEURL,
+ GetUserGuideSpaceKey(languageCode),
+ "/",
+ path.EmptyNull().Trim().TrimStart('/', '\\'));
+ }
+
+ public static string GetUserGuideSpaceKey(string languageCode)
+ {
+ return "SMNET25";
}
///
diff --git a/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs b/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs
index 09f40c69d9..d3fcef7874 100644
--- a/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs
+++ b/src/Libraries/SmartStore.Core/Utilities/FileDownloadManager.cs
@@ -31,14 +31,24 @@ public FileDownloadManager(HttpRequestBase httpRequest)
/// 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)
+ /// Specifiers whether the file is located on the local server
+ public FileDownloadResponse DownloadFile(string url, bool sendAuthCookie = false, int? timeout = null, bool isLocal = false)
{
Guard.ArgumentNotEmpty(() => url);
url = WebHelper.GetAbsoluteUrl(url, _httpRequest);
- var req = (HttpWebRequest)WebRequest.Create(url);
- req.UserAgent = "SmartStore.NET";
+ HttpWebRequest req;
+
+ if (isLocal)
+ {
+ req = WebHelper.CreateHttpRequestForSafeLocalCall(new Uri(url));
+ }
+ else
+ {
+ req = WebRequest.CreateHttp(url);
+ req.UserAgent = "SmartStore.NET";
+ }
if (timeout.HasValue)
{
diff --git a/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs b/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs
index 95672ae9a5..3fbb4f83f8 100644
--- a/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs
+++ b/src/Libraries/SmartStore.Core/Utilities/FileSystemHelper.cs
@@ -31,6 +31,28 @@ public static string TempDir(string subDirectory = null)
return path;
}
+ ///
+ /// Ensures that path is a valid root path
+ ///
+ /// Relative path
+ /// Valid root path
+ public static string ValidateRootPath(string path)
+ {
+ if (path.HasValue())
+ {
+ path = path.Replace('\\', '/');
+
+ if (!path.StartsWith("~/"))
+ {
+ if (path.StartsWith("~"))
+ path = path.Substring(1);
+
+ path = (path.StartsWith("/") ? "~" : "~/") + path;
+ }
+ }
+ return path;
+ }
+
///
/// Safe way to cleanup the temp directory. Should be called via scheduled task.
///
@@ -114,8 +136,10 @@ public static bool Copy(string sourcePath, string destinationPath, bool overwrit
/// Source directory
/// Target directory
/// Whether to override existing files
- public static void CopyDirectory(DirectoryInfo source, DirectoryInfo target, bool overwrite = true)
+ public static bool CopyDirectory(DirectoryInfo source, DirectoryInfo target, bool overwrite = true)
{
+ var result = true;
+
foreach (FileInfo fi in source.GetFiles())
{
try
@@ -124,6 +148,7 @@ public static void CopyDirectory(DirectoryInfo source, DirectoryInfo target, boo
}
catch (Exception exc)
{
+ result = false;
exc.Dump();
}
}
@@ -137,9 +162,12 @@ public static void CopyDirectory(DirectoryInfo source, DirectoryInfo target, boo
}
catch (Exception exc)
{
+ result = false;
exc.Dump();
}
}
+
+ return result;
}
///
diff --git a/src/Libraries/SmartStore.Core/WebHelper.cs b/src/Libraries/SmartStore.Core/WebHelper.cs
index b5e9d594bc..edef7863b7 100644
--- a/src/Libraries/SmartStore.Core/WebHelper.cs
+++ b/src/Libraries/SmartStore.Core/WebHelper.cs
@@ -2,6 +2,7 @@
using System.Configuration;
using System.Diagnostics.CodeAnalysis;
using System.IO;
+using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
@@ -11,22 +12,29 @@
using SmartStore.Core.Domain.Stores;
using SmartStore.Core.Infrastructure;
using SmartStore.Utilities;
+using System.Net;
+using System.Text;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using System.Net.Sockets;
namespace SmartStore.Core
{
-
public partial class WebHelper : IWebHelper
{
+ private static object s_lock = new object();
private static bool? s_optimizedCompilationsEnabled;
private static AspNetHostingPermissionLevel? s_trustLevel;
private static readonly Regex s_staticExts = new Regex(@"(.*?)\.(css|js|png|jpg|jpeg|gif|bmp|html|htm|xml|pdf|doc|xls|rar|zip|ico|eot|svg|ttf|woff|otf|axd|ashx|less)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex s_htmlPathPattern = new Regex(@"(?<=(?:href|src)=(?:""|'))(?!https?://)(?[^(?:""|')]+)", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Multiline);
private static readonly Regex s_cssPathPattern = new Regex(@"url\('(?.+)'\)", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Multiline);
+ private static ConcurrentDictionary s_safeLocalHostNames = new ConcurrentDictionary();
private readonly HttpContextBase _httpContext;
private bool? _isCurrentConnectionSecured;
private string _storeHost;
private string _storeHostSsl;
+ private string _ipAddress;
private bool? _appPathPossiblyAppended;
private bool? _appPathPossiblyAppendedSsl;
@@ -49,17 +57,71 @@ public virtual string GetUrlReferrer()
return referrerUrl;
}
+ public virtual string GetClientIdent()
+ {
+ var ipAddress = this.GetCurrentIpAddress();
+ var userAgent = _httpContext.Request != null ? _httpContext.Request.UserAgent : string.Empty;
+
+ if (ipAddress.HasValue() && userAgent.HasValue())
+ {
+ return (ipAddress + userAgent).GetHashCode().ToString();
+ }
+
+ return null;
+ }
+
public virtual string GetCurrentIpAddress()
{
+ if (_ipAddress != null)
+ {
+ return _ipAddress;
+ }
+
+ if (_httpContext == null && _httpContext.Request == null)
+ {
+ return string.Empty;
+ }
+
+ var vars = _httpContext.Request.ServerVariables;
+
+ var keysToCheck = new string[]
+ {
+ "HTTP_CLIENT_IP",
+ "HTTP_X_FORWARDED_FOR",
+ "HTTP_X_FORWARDED",
+ "HTTP_X_CLUSTER_CLIENT_IP",
+ "HTTP_FORWARDED_FOR",
+ "HTTP_FORWARDED",
+ "REMOTE_ADDR",
+ "HTTP_CF_CONNECTING_IP"
+ };
+
string result = null;
- if (_httpContext != null && _httpContext.Request != null)
- result = _httpContext.Request.UserHostAddress;
+ foreach (var key in keysToCheck)
+ {
+ var ipString = vars[key];
+ if (ipString.HasValue())
+ {
+ var arrStrings = ipString.Split(',');
+ // Take the last entry
+ ipString = arrStrings[arrStrings.Length - 1].Trim();
+
+ IPAddress address;
+ if (IPAddress.TryParse(ipString, out address))
+ {
+ result = ipString;
+ break;
+ }
+ }
+ }
if (result == "::1")
+ {
result = "127.0.0.1";
+ }
- return result.EmptyNull();
+ return (_ipAddress = result.EmptyNull());
}
public virtual string GetThisPageUrl(bool includeQueryString)
@@ -191,12 +253,12 @@ private string GetStoreHost(bool useSsl, out bool appPathPossiblyAppended)
if (_currentStore != null)
{
- var securityMode = _currentStore.GetSecurityMode(useSsl);
+ var securityMode = _currentStore.GetSecurityMode();
if (httpHost.IsEmpty())
{
- //HTTP_HOST variable is not available.
- //It's possible only when HttpContext is not available (for example, running in a schedule task)
+ // HTTP_HOST variable is not available.
+ // It's possible only when HttpContext is not available (for example, running in a schedule task)
result = _currentStore.Url.EnsureEndsWith("/");
appPathPossiblyAppended = true;
@@ -598,5 +660,177 @@ public static string GetAbsoluteUrl(string url, HttpRequestBase request)
url = string.Format("{0}://{1}{2}", request.Url.Scheme, request.Url.Authority, url);
return url;
}
- }
+
+ public static string GetPublicIPAddress()
+ {
+ string result = string.Empty;
+
+ try
+ {
+ using (var client = new WebClient())
+ {
+ client.Headers["User-Agent"] = "Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0) (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
+ try
+ {
+ byte[] arr = client.DownloadData("http://checkip.amazonaws.com/");
+ string response = Encoding.UTF8.GetString(arr);
+ result = response.Trim();
+ }
+ catch { }
+ }
+ }
+ catch { }
+
+ var checkers = new string[]
+ {
+ "https://ipinfo.io/ip",
+ "https://api.ipify.org",
+ "https://icanhazip.com",
+ "https://wtfismyip.com/text",
+ "http://bot.whatismyipaddress.com/"
+ };
+
+ if (string.IsNullOrEmpty(result))
+ {
+ using (var client = new WebClient())
+ {
+ foreach (var checker in checkers)
+ {
+ try
+ {
+ result = client.DownloadString(checker).Replace("\n", "");
+ if (!string.IsNullOrEmpty(result))
+ {
+ break;
+ }
+ }
+ catch { }
+ }
+ }
+ }
+
+ if (string.IsNullOrEmpty(result))
+ {
+ try
+ {
+ var url = "http://checkip.dyndns.org";
+ var req = WebRequest.Create(url);
+ using (var resp = req.GetResponse())
+ {
+ using (var sr = new StreamReader(resp.GetResponseStream()))
+ {
+ var response = sr.ReadToEnd().Trim();
+ var a = response.Split(':');
+ var a2 = a[1].Substring(1);
+ var a3 = a2.Split('<');
+ result = a3[0];
+ }
+ }
+ }
+ catch { }
+ }
+
+ return result;
+ }
+
+ public static HttpWebRequest CreateHttpRequestForSafeLocalCall(Uri requestUri)
+ {
+ Guard.ArgumentNotNull(() => requestUri);
+
+ var safeHostName = GetSafeLocalHostName(requestUri);
+
+ var uri = requestUri;
+
+ if (!requestUri.Host.Equals(safeHostName, StringComparison.OrdinalIgnoreCase))
+ {
+ var url = String.Format("{0}://{1}{2}",
+ requestUri.Scheme,
+ requestUri.IsDefaultPort ? safeHostName : safeHostName + ":" + requestUri.Port,
+ requestUri.PathAndQuery);
+ uri = new Uri(url);
+ }
+
+ var request = WebRequest.CreateHttp(uri);
+ request.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;
+ request.ServicePoint.Expect100Continue = false;
+ request.UserAgent = "SmartStore.NET {0}".FormatInvariant(SmartStoreVersion.CurrentFullVersion);
+
+ return request;
+ }
+
+ private static string GetSafeLocalHostName(Uri requestUri)
+ {
+ return s_safeLocalHostNames.GetOrAdd(requestUri.Port, (port) =>
+ {
+ // first try original host
+ if (TestHost(requestUri, requestUri.Host, 5000))
+ {
+ return requestUri.Host;
+ }
+
+ // try loopback
+ var hostName = Dns.GetHostName();
+ var hosts = new List { "localhost", hostName, "127.0.0.1" };
+ foreach (var host in hosts)
+ {
+ if (TestHost(requestUri, host, 500))
+ {
+ return host;
+ }
+ }
+
+ // try local IP addresses
+ hosts.Clear();
+ var ipAddresses = Dns.GetHostAddresses(hostName).Where(x => x.AddressFamily == AddressFamily.InterNetwork).Select(x => x.ToString());
+ hosts.AddRange(ipAddresses);
+
+ foreach (var host in hosts)
+ {
+ if (TestHost(requestUri, host, 500))
+ {
+ return host;
+ }
+ }
+
+ // None of the hosts are callable. WTF?
+ return requestUri.Host;
+ });
+ }
+
+ private static bool TestHost(Uri originalUri, string host, int timeout)
+ {
+ var url = String.Format("{0}://{1}/taskscheduler/noop",
+ originalUri.Scheme,
+ originalUri.IsDefaultPort ? host : host + ":" + originalUri.Port);
+ var uri = new Uri(url);
+
+ var request = WebRequest.CreateHttp(uri);
+ request.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;
+ request.ServicePoint.Expect100Continue = false;
+ request.UserAgent = "SmartStore.NET";
+ request.Timeout = timeout;
+
+ HttpWebResponse response = null;
+
+ try
+ {
+ response = (HttpWebResponse)request.GetResponse();
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ return true;
+ }
+ }
+ catch
+ {
+ // try the next host
+ }
+ finally
+ {
+ if (response != null)
+ response.Dispose();
+ }
+
+ return false;
+ }
+ }
}
diff --git a/src/Libraries/SmartStore.Data/EfRepository.cs b/src/Libraries/SmartStore.Data/EfRepository.cs
index 860551f723..5afd5e5d41 100644
--- a/src/Libraries/SmartStore.Data/EfRepository.cs
+++ b/src/Libraries/SmartStore.Data/EfRepository.cs
@@ -161,7 +161,7 @@ public virtual void UpdateRange(IEnumerable entities)
private void SetEntityStateToModifiedIfApplicable(T entity)
{
var entry = InternalContext.Entry(entity);
- if (entry.State == System.Data.Entity.EntityState.Detached || (this.AutoCommitEnabledInternal && !InternalContext.Configuration.AutoDetectChangesEnabled))
+ if (entry.State < System.Data.Entity.EntityState.Added || (this.AutoCommitEnabledInternal && !InternalContext.Configuration.AutoDetectChangesEnabled))
{
entry.State = System.Data.Entity.EntityState.Modified;
}
diff --git a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportDeploymentMap.cs b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportDeploymentMap.cs
index 0a57740d6e..2c49aa7d7a 100644
--- a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportDeploymentMap.cs
+++ b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportDeploymentMap.cs
@@ -11,10 +11,12 @@ public ExportDeploymentMap()
this.HasKey(x => x.Id);
this.Property(x => x.Name).IsRequired().HasMaxLength(100);
+ this.Property(x => x.ResultInfo).IsMaxLength();
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.SubFolder).HasMaxLength(400);
this.Property(x => x.EmailAddresses).HasMaxLength(4000);
this.Property(x => x.EmailSubject).HasMaxLength(400);
diff --git a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs
index 6e5e6758fe..adacc3c4c6 100644
--- a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs
+++ b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ExportProfileMap.cs
@@ -11,7 +11,7 @@ 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.FolderName).IsRequired().HasMaxLength(400);
this.Property(x => x.SystemName).HasMaxLength(400);
this.Property(x => x.ProviderSystemName).IsRequired().HasMaxLength(4000);
this.Property(x => x.Filtering).IsMaxLength();
diff --git a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ImportProfileMap.cs b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ImportProfileMap.cs
index eb06973c22..02515fd268 100644
--- a/src/Libraries/SmartStore.Data/Mapping/DataExchange/ImportProfileMap.cs
+++ b/src/Libraries/SmartStore.Data/Mapping/DataExchange/ImportProfileMap.cs
@@ -14,6 +14,7 @@ public ImportProfileMap()
this.Property(x => x.FolderName).IsRequired().HasMaxLength(100);
this.Property(x => x.KeyFieldNames).HasMaxLength(1000);
this.Property(x => x.FileTypeConfiguration).IsMaxLength();
+ this.Property(x => x.ExtraData).IsMaxLength();
this.Property(x => x.ColumnMapping).IsMaxLength();
this.Property(x => x.ResultInfo).IsMaxLength();
diff --git a/src/Libraries/SmartStore.Data/Migrations/201508091512101_ExportFramework.cs b/src/Libraries/SmartStore.Data/Migrations/201508091512101_ExportFramework.cs
index fdad717e6c..5203e70451 100644
--- a/src/Libraries/SmartStore.Data/Migrations/201508091512101_ExportFramework.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/201508091512101_ExportFramework.cs
@@ -465,9 +465,9 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.EmailAddresses",
"Email addresses to",
- "E-Mail-Addressen an",
+ "E-Mail Adressen an",
"Specifies the email addresses where to send the data.",
- "Legt die E-Mail Addressen fest, an die die Daten verschickt werden soll.");
+ "Legt die E-Mail Adressen fest, an die die Daten verschickt werden soll.");
builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.EmailSubject",
"Email subject",
diff --git a/src/Libraries/SmartStore.Data/Migrations/201509021536425_ExportFramework1.cs b/src/Libraries/SmartStore.Data/Migrations/201509021536425_ExportFramework1.cs
index 8313baa6a1..09f2dc6314 100644
--- a/src/Libraries/SmartStore.Data/Migrations/201509021536425_ExportFramework1.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/201509021536425_ExportFramework1.cs
@@ -81,9 +81,9 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
builder.AddOrUpdate("Admin.DataExchange.Export.CompletedEmailAddresses",
"Email addresses to",
- "E-Mail-Addressen an",
+ "E-Mail Adressen an",
"Specifies the email addresses where to send the notification message.",
- "Legt die E-Mail Addressen fest, an die die Benachrichtigung geschickt werden soll.");
+ "Legt die E-Mail Adressen fest, an die die Benachrichtigung geschickt werden soll.");
builder.AddOrUpdate("Admin.DataExchange.Export.CompletedEmail.Subject",
"Export of profile \"{0}\" has been finished",
diff --git a/src/Libraries/SmartStore.Data/Migrations/201603121451066_ThirdPartyEmailHandOver.cs b/src/Libraries/SmartStore.Data/Migrations/201603121451066_ThirdPartyEmailHandOver.cs
index 63e182a699..9b5970f35a 100644
--- a/src/Libraries/SmartStore.Data/Migrations/201603121451066_ThirdPartyEmailHandOver.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/201603121451066_ThirdPartyEmailHandOver.cs
@@ -200,6 +200,36 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
builder.AddOrUpdate("Admin.DataExchange.Export.SystemProfilesTitle",
"System profiles",
"Systemprofile");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.CompletedEmailAddresses",
+ "Email addresses to",
+ "E-Mail Adressen an",
+ "Specifies the email addresses where to send the notification message.",
+ "Legt die E-Mail Adressen fest, an die die Benachrichtigung geschickt werden soll.");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.EmailAddresses",
+ "Email addresses to",
+ "E-Mail Adressen an",
+ "Specifies the email addresses where to send the data.",
+ "Legt die E-Mail Adressen fest, an die die Daten verschickt werden soll.");
+
+ builder.AddOrUpdate("Admin.Common.FileNotFound", "File not found", "Datei nicht gefunden");
+
+ builder.AddOrUpdate("Admin.Common.EnterEmailAdress",
+ "Please enter an email address.",
+ "Bitte geben Sie eine E-Mail-Adresse ein.");
+
+ builder.AddOrUpdate("Admin.Configuration.EmailAccounts.TestingEmail",
+ "Testing email functionality.",
+ "Test der E-Mail-Funktion.");
+
+ builder.AddOrUpdate("Admin.Common.EmailSuccessfullySent",
+ "The email has been successfully sent.",
+ "Die E-Mail wurde erfolgreich versendet.");
+
+ builder.AddOrUpdate("Admin.Common.SkipAndTakeGreaterThanOrEqualZero",
+ "Values for skip and limit must be greater than or equal to 0.",
+ "Werte fr berspringen und Begrenzen mssen grer oder gleich 0 sein.");
}
}
}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605020640016_GtinMpnIndex.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201605020640016_GtinMpnIndex.Designer.cs
new file mode 100644
index 0000000000..90e9ba6504
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605020640016_GtinMpnIndex.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 GtinMpnIndex : IMigrationMetadata
+ {
+ private readonly ResourceManager Resources = new ResourceManager(typeof(GtinMpnIndex));
+
+ string IMigrationMetadata.Id
+ {
+ get { return "201605020640016_GtinMpnIndex"; }
+ }
+
+ string IMigrationMetadata.Source
+ {
+ get { return null; }
+ }
+
+ string IMigrationMetadata.Target
+ {
+ get { return Resources.GetString("Target"); }
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605020640016_GtinMpnIndex.cs b/src/Libraries/SmartStore.Data/Migrations/201605020640016_GtinMpnIndex.cs
new file mode 100644
index 0000000000..98f1936ecc
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605020640016_GtinMpnIndex.cs
@@ -0,0 +1,19 @@
+namespace SmartStore.Data.Migrations
+{
+ using System.Data.Entity.Migrations;
+
+ public partial class GtinMpnIndex : DbMigration
+ {
+ public override void Up()
+ {
+ CreateIndex("dbo.Product", "ManufacturerPartNumber");
+ CreateIndex("dbo.Product", "Gtin");
+ }
+
+ public override void Down()
+ {
+ DropIndex("dbo.Product", new[] { "Gtin" });
+ DropIndex("dbo.Product", new[] { "ManufacturerPartNumber" });
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605020640016_GtinMpnIndex.resx b/src/Libraries/SmartStore.Data/Migrations/201605020640016_GtinMpnIndex.resx
new file mode 100644
index 0000000000..15bcc90554
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605020640016_GtinMpnIndex.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
+
+
+ H4sIAAAAAAAEAOy923LcuLIo+D4R8w8OP50zsY/ddq+OWLuje05IsmQrti9akmzvvV4UFAuSuMwiq3nRpSfmy+ZhPun8wgHAGwgk7iBZpa4Xu0QkEkAikUgkMhP/6//7/3/7n4/r9MU9Ksokz35/+ebVTy9foCzOV0l2+/vLurr5H39/+T//7//z//jteLV+fPGtg/uZwOGaWfn7y7uq2vz6+nUZ36F1VL5aJ3GRl/lN9SrO16+jVf767U8//fvrN29eI4ziJcb14sVv53VWJWtE/8B/HuVZjDZVHaWf8hVKy/Y7LrmgWF98jtao3EQx+v3lxToqqosqL9Crd1EVvXxxkCYR7sYFSm9evoiyLK+iCnfy168luqiKPLu92OAPUXr5tEEY7iZKS9R2/tcB3HQcP70l43g9VOxQxXVZ5WtLhG9+bgnzmq/uRN6XPeEw6Y4xiasnMmpKvt9fXuabJH75gm/p16O0IFAj0h5R+mKwJHtF65XNf//2ggP6t54p3r765dVPr376txdHdVrVBfo9Q3VVROm/vTirr9Mk/g/0dJn/QNnvWZ2mbE9xX3HZ6AP+dFbkG1RUT+fopu3/6erli9fjeq/5in01pk4zuNOs+vntyxefcePRdYp6RmAIQUf1HmWoiCq0OouqChUZwYEoKYXWubYunsoKrcnvrk3Mf3gdvXzxKXr8iLLb6u73l/jnyxcnySNadV/afnzNErzscKWqqJGuqdMsTusVOs0uEtxktOkaPMzzFEUZMEwNvvIsKsuHvFjhggrFePi+KDuEk9PiMqnS6Sl+mK+eJm/kE6oizNGEbOUsjb1DZVwkm0bgzNDePHP1MVnjZbG6zOmCLn05+RxlK1QclN+T1S2qfLE1WP6ZZ9PToWnqexFt8AZbYSEm9N2k/sVd/jCaN7+RH2LmRkUA+VIkeUGlslq+GwiPy+g28Fz89nrYfdV7cvR4hDeb27x4ctmZo8dXDIb95ixvS7Mt/+2nn4wm2ZK93iXlJo2evhCWt2FUY/65QFVFx2LNO1gk3CS3dUGhX7V49hzkzEFvp+Ggb1Fah9gpLJultNJT14lnP+ZxlCZ/olXXpgP3tjga5hUQ7tlY3lYzHXZTC6hYUXZbR7eWLALgIVOHMH3eF3m9mV9A9+0v1fRc6/tzdJ/cUgaSzOTLF+copQDlXbJp7CniyroawE+KfH2ep9CC7qGuLvK6iMn4ci3oZVRQ9dpNpvTd8hQlLZ69BJG3pdkI30y0XNqZaamu3ImnaB/X/qNGFyg/wjhUrQc4uJ2k0e3pGg/2JEmRhty/mI1Wc8StUt/zWOBDN11L5Z3/OdFVBVfKTCq6m8k4RyWVcaVcgHKQchkqA+xl40iMSqE7oeuunXGogyhoHM69hNXLOl/tqqP1MkeXrvWFjjCnJVldZ2l9m2SCENFVvczrGBI+4bQqf6EA6lZaEeIkFM5QsU5KsjjPUUyN+tYC4QLFNbHXveJx7QWBvK1Al0m2h3+Ti6y3v/wyRduDNXTylqWL94jyNirIsoK3dZ6Hr7gqwxJWQwprWAPutYhZVC4Gw7Z6+YpFtF+9zqt3ohV0UiB0gVl1Q9vzU54vo8fjR7TeeN96YUStIk7wcFOgrnoQV8m99+XTadlItYb5/XAFlY+mQomXDBMLJv7EYSjH3LSLHK9/e4FEqpX0370QkrcV6iyxpCrS+kRMfmEezOhA7sy/ZB/w+jijKr0ftoM0zR/e16is8LnkW155I/SwiQj3RHjdvcOM+bWKO0zkz8tkra17nK0ca/ramtyObUTSgMe0UYGo0o1KIQ1OKfZx7YOsfMDiTNqppvyqEaPjbjFFokjnyr1leIPMS5I3KPbyXCGjMJV2U5Z/rtfXqPhyQyRY6TeAKYy6zfLxW2LQ2oeWoE2fMLmoQUeh9HFQV+xiHHdWAgbKBhmst5xgEXtJCxZRMJnx4jAqUdsBQt1O0e186LSrsyGT9Ro12AKmmn2IbXWc4mWCCGJ+2O8S8rY6Gr2vk77V5rfttWeJ29XdQIa4gjzGs5xO3oqBV3rYhk7yYh1Vvht2h+0iSqvJu36wWifZUb5eMx7D00UylMFsTAc3N0ma4OXiS+0wFqd3KEUB4ig6w9VBHOc14MI9he0qDB99jMrqdHOwWuEjmiqcwdRhRCPxCkQk5ZcMPE9aO5uU1cf8NslcD6i4PuUiLKqlKJwVgpakkruJTvRfMWCDGiCWCrs/AGKrtx4maYqnuZ97VTd5WKCvYxB5hzk4217zmp6q2y3M1aDRiP3mYQQtWwoIqdh+N1Y9aqlBGIaQE1t/M6Xq8fEjUWii9KCu7ohKE1Mg1SlHVQOcBqMKwpyY1bKdIKwG1OuzvKzgsfXF4EDEUqHXAIhTF5tYT3kfabm8k+NiuJccjG036Zkf7iEtAjs3LhH6xRXbdukc4TMGZpE/qIkW7NoIBOwiDCF0VQJm3+WHqFid5UlWlR8SjITcuIP9FuAkvZfDAWNQANuOpLvqNNprBGBA/HEwcgHIA9qKwIu7nNY/wofYU6yUwX3noUDyS4EE2sshvcw6PUEd4pDW6zx71SLYn+nlbZ0kRVkFMt3q1ddZGtId+sO0gllsE2XTh28fkQNaIcbWaK/QKoS/3SdZLB5dNS0yAbCTDatdmm/maujt5A39M9kQXSlKNb78gW6V7/IMNZcfk7d1Ej3O1JLfeVt+kmnWELgVdhttDzNsgFyRsGnz5dZ7NbtIlZ3jIMUujgCkHR1D+RndO3JZ783vkgLFRD171eLYb8/ytjQb5kRhUdQ3pGwNH0EcTcpgzoMP+UdEiHhazhE0dXlXIGTa4M8BGsSCFhVJzDXm6EdTX/8LL7XL/FvkbeLdhtCpuRx2zvEpGM8Bxt1x7SdU3eUSE9IY5mqo3Ii3ZGwQ00MDpyttFevzLbsRSIY12iuA3REEEDsPQnkdC8f0cIkaaRFwU7ffhxRiSb0PTZXpZMZMUuHk0ulthml9dEdWwiRSiREsc8gjXpu0EGFu63us7HoomCNM++Utb0tmZAjrAjiVtnp9XaD7JNKIiTA3wtugBzmdcx33c2HxK3d9L/+t/oY0gBtXi2u/5hVrviWV76I38cYwDQbXea0cbDaY9fwXX1C/jq+b1SRGq/5KJrTHgOzySepa4LSsD9P8tnf4sl7SpHb5isGxHa64bWcu0eP0Xmxk8MSiHM7pt8MIshRD66sBcGAnqFxgJRDIm42arnjwEEGw3wvkbYWK5wuVitey2UB5lF0Mmy2ze6cm6na2Ft8R65bpqIznVXikl9Ht9Emkl4n/M8yTbWrq0De2bXmyw4wscMquiW4EmX0KtqI47Ya88VO5ZQYJH+2xQiGkQiG4XY8h/DL6FPmqjqtzfBpHDy7nuKiKcI9ejfBsh+LXdmlbNkh1Kw3hZlFSz6OKudVzI8oHlG5u6vS/UHmJOSUNguxz7oJLHi7XTD8cK8dy61UPyUTJQQBifBwIZR3cyWJpaZHhw/mxwmIsq3PFrWfJiKQ1xABQs2p+saAd/X2lz/68oJWGpDn/KLQCt0kzNdMEviGk7LekTDD0abZK7pNVHaXpk68esswF2MVdjjXhGfXEE9y/OdubNSyw41q03qQBIvrC5mPp8IS7h9wfaMJErtJjfheXRHeoYKf9Rnu6qNfBjvqBMHboqBLFDdq7j+GQ9h5OB/G25Zq++FFPv+iirL6JYqKCFHgfrbReumGafV8lqgUeppHT8n1yUx1FhfdlT4cnhLZCYqSSAn2p7jDFm+0kwFNgFOeg/GjimoMItZroxiQQEetGB6sV1wfvMZ2W7/KHLM0j/3vyFo/vzH3N0maBdwi9x/ipc4v/ciPgdMxA1KI5ftwkzRtK76InHqcZChooTlGEYPsPUXkRYa0JhZrVMTbLABXcG5JB5OC2QIhVHF07M0I2i9XktDwnmauLAA7RPaKjpzhFTad8ZRyL8QwVSe69+nqcdO+niD3Xyil1KT/OSJUA+TBCJrjF8jQhKy9KO4yNM2Bvv0Zxsia2qbMC/2ofSf77yxcXJNU63j8duh8s38lpeVx6k5N5PtCXcbCKQ+4ls3u8NDG6xufQ++RW5fGPf9RRa+vwEtnNcY1iPLiPElw3SRmsnu5hYE+dN6wkCzjyj/lDM+o2JYm382BeJTdP1CBwkhddHw8RPn35IT6M4h/0fVDyDrh3Gh9yGiQYTxta4hNIf+j11ijooR/PUrKu12EmqcEYPYbDSAmAVi2yBM2grOK1QDp4WD8d1lU1GBc81haB/p6Ud2lSVmGQtos/RZh5sVwf2W+cLz+xdk7RJbG3fWmEJPgO9CVdTdtAezA5otewE7VxscF4otRyIOY4e78Gcnnt4KHA4mr9HBwxdeas46xCRRmEv1qxNcKMJmaKVrDN2iY+fFwmqFmT3gIf76GorA4qLDqv6wod5evrJGuv9QIyIe4zlnk01RtxoU0Tf435O0pu76ZbiuNzTHD035PVhNg/TEubfqfxlSc9Ij9hEu7GIlxwRZg0iVvkJi4OMLlHxROpbGk96dRArIKJF606TbpE7e4T5Njd4/uEorIuEOmSQp0M8ipl3+bBmnWH9BWxPVryY4zajLR1tkoRvdHSWKDCmNeb9s5QQfI1hTJ8jJASaoTGySaaskYsT33ZbIn9Fgk6yXSlVy30ZT7YygfHGDmU4AyjALV1EWSlgcrD52oMKPjzjMplDkpjIEf/pGZW5QnKBLCrlg+k3lUyUJkTkhTelvjdyaQxeGl8rDqzmMJNjAeRDUCAc+w4e4mo7DsLqOg/BCYbAwjrOI6zhOJRDqGFUfSeg5B1nAdz7HN/CR7OrVDpc+fbX3oCvWnTl/bHFmX/4SqK8agryManqeU43ibcQSFQR3CiPGWKpeKUhXGUpt+iIsFKHXSOVHZfUU8xQQa1ZLNkUtVxqnjUVgO3GK3tEJ3HxerpSh4cA4pMyJZLuXAEZJ3IjLsbVnSWBxW7O4aQdpgDs+0ya8MButsXQ5whFAq8IEJ4+TR3qqJTMoxWqe1/7f2a5W1pvHwnetO8m5kQnhpfS3JWivFwA/ikdh0TMQY3anVN2Z7KrW9+lwgtbL2ryqO83uQZm9jN2TIlYJos40k3M9Q/kq4yXx4dMBHi2fqB6I7xl7nmKCYevNkKqrP8ACdsS0pg280JMDFMYZHQj0EwXhhbJFpULefL4yz7NuEawDggQPlQQGi/dDX9Y/LOEUYdiv1WLG9LsxVPFHBD4l8Ctawz4M8XK3GYV5hPZw3rSZNohteZ2mUUKqBnHzAT6JU6EtEXygGwtbRZ3lSRSKqL5E/k1/Yo9Ke8zPGOheKKx+3skdPi+TJ2HpssfRY9kJ5H2a3SZysMDwSOjQvvv7DFkUPbdgse7n5/m+/TbyKsaH1L0MOnSZ5vCH356HBk0V9AAucbYytsI6bhZHX9TVUHxCSp48rE5HQ8gF+Gkq4H1rr7J7RKoldt/b3irhBfDYkOkywqBpf19i+ThaTzM1zTJC7KLWySWHyUnyQpytSng58DBT9+Rg++cvu0vCyirExCREhNk+LS5eZWFCEwhPbmlpM3buJkhNM/58hevJimHpnqWDGfbuS0lTqvBsk1mmzRWK7gsD4Xur4qUiNZX6kxdsEgt2sMvv0qVq4bSq4A648n+3mdIqMHyQMlq9ygyW+t2peYAmXp74NSw6Ab3n/ABwjm+WZLi82Appfw02caZRqNngjz9A/9zNZwNxt6K1Dollt7heU8HT9iQYV1v2jGM/Lg/zDdDZL0dKy8b3Lbe0ZeuB7vm7CI9ruNvC3NRmAYV2B9RZ/mxQf0+C1K6/lbbxXTjznZc6aOqXDVgm3PWYPPtv9Ra8C1XznytgKdtkYe9r7IgiVuiEMGAMl9pRZOOam9qJk5w2SSYhZk3XQ974aSFbq8q9fXGfPqtyuyNnHo9tzgPMerF/lVSMcUDY8YRgZxta7YTUIRJSSvpo8YUtS1vTfhwpqmDYWSGFa0oVMBrUFMW0YDMO96ELOQbqpD6h0c6r0aIm9rIJp3/p6O6MEQUf3e+xG1EqsdjXuJw66hkS6NLFxGlmrXrYEc9lnJAbw1OUz7dSpvK5CGH8p37LQ8wVpPPeQ1XVAfk7/z13OoQdjwACyPG+5/SNaeCDjBPu8S6Kzrb8gdno089pcNLLa9fJhcPrDk/kvIiDG3Gobojyup4/RHf0jWobzCBPLDJ9mASf+DyJJAQmQvPbY5JGRWJ32GE/ZRDdsV1bCPQ9jBOIS9a/4zsg+rHOPGm7voFgeVC4oCCBTitAFnp/E/d8B49zqESvgEOYHAhG8kaJAU4401LED+vCYSqx12iGCsSVxe9QeC0HmkJIcEw+xTpgNT8YnDaNXoTEmgwmJJFyUqL8mpHqqz4FSh3ctNW4Hn/eZDGA/d7ZFg4RLkzbDU7VLpGUkNP7kIkkndrgTPQB+H6oIMdMExgfALLvb2Au+vIJpU3AtLpgWWHC+LfJatz0ntMrr1P5ZhJPul5by0QtlxdXt1sMyukn0UzP7qw5uK7Kn+PKtAvudleVtzPPM7y3u7C70lHPSdG9tXY9TYLB+J0bgpW74Jo/GH285HLA7KMrnN8Crq7krmeBxukZdQTkv67KH/3UsYc+Rw0vzPdRpAa9XIvHCPSFJb55e6+nJDkVK91/6WxvthDFVecs2bGaZVZYY14/oTOFlMl//dYbCuJlbTPOmqtjUp1E2rugxbm3jdWEscD8IjrJRFtNf95G1pzjETBXYaeVeEDOvc7hhSaG9us7nZ7SO+p7HwR7D92pO3FUhxatEEu9Agb7fhT8xD7JNpYadlm5HA24uE2ZeyqshTgm0rEyPZazQuD7sYbuLOCgvPcy7jAe2upnVsR6i+1DAYKo+YhkxZPdBDa1xJJa+WBsr6pk/5qJGEsPAF3Ez2u4jBLjJPnvKFrpImc8P11ZTajCih1SWKds/t8rYkdPP3V9uhRaTxgiU5ey7+qKMClee315MPqrHhrv6FV8IaTZhArnmtfYaG/OKYJzsSUtEQQq39mGQ/mAx1iySysdW2tkfPMtQ7zZQ1px1peHjQMQF4h2C/zyjWbUuj93XSt9r8to0jKPsHHr8W3sl9AFSTbSRdW1NlQScnddS8GDj5WAyynodp6PgRj6kMr69C29Szya9uLPr6N0k9NO8ex178ydsKpB3AyVltw7rcE/KGueC19O9wz6LBDFTzou8YFHrWl4UQlBYJWMjrWcvXh+U9VJkobU/xzQvyH1C6uanTDJWl/wleQBlMrLwgHixtV+gTNO1UtfvmS5MF3PTOdwV+j8p2gOHcGkYdVKn3AoGvuKqCQq+pIVPhddW8GBDv1eVRvnbM0U9qv2JQbAePtZ3Rxa6HMms0jaHH6a+lCKWdErVJub3DCDI6M7FXA+DA1lC5wMQgkDfLOuYp7vl1n5tYY4uJsts6uvW/sw20Bu0Dc4sQy9Gy2RMquuZuNVjihGUecG8ScDQSwjuJxMFmU+T3aNXiOwLcbG3DKPMqPNLAqTOCJpjY57RxG5l0j+1kqXSPpVviADXeYEeF4O46hrA9KzH7M+w14KQF8Lf+SlXBSQsgBq0ii9KDuroje1oTsHaOYsy3LqenLgPQKxXivcqgEEItBX1VhuM1k2x+UnsomeVmdDeJMhwnbJPt1duMLX8hvEy5b56mDuIYH1PnaRD/eZ+sUDHls2RayxgoOFWC5GqoOUhSowrCFmBWy+vEdZIX9fosL11MBLRu+apHsReh8rYu800ShzJLh3C3nf8wc3p2sFoV1AI6sX/ILmRlU8qXfkmBwkQsFSQHAGKrPVIUlG01XWQBoU4O5YpuMkD+8qztjJdAozj2Ek3eFqXS1kg0MlshPJUu6ut/oVglHf82TYDS52YhlH7d/5bgE5inASMqK9ITb5+vFk+oKe7wNXLXzhD1PDaERjxKd4RxMSxrORinPUHXwRYI7B39qepaA+C/BXhK/73gl7dFCfS+yOvNxHnsTPMmb42HPyjVKV97yuQwmwORoEHOIc9xi/hr5YQe1rBcml+xQJw0Z8pgac4C+EvzthNeIp3i2Mt1hZB59tL4Wa7xwPePapEB3yNZiQv+/kgqT5zERTu31pKiSaHT/LcXEvK2KIG0Sc4CXTiQtryjIYI6BHu/6J2kKSZWawj1NlbgJbhRoDMg7wVmizpYR8JgO4ueyG1yUGSfUHWXr6a8SZJwzFFdFCiLn45wzRkabRo7j6pBAVZ7j//deS1cRo/thhrC8PYt0udODChWLurrCovE9DSL00uCNpSrvaqx48d5GrskjeG5iYk701wjHDU6z0hbqTPPCNvGZh0ZbshiKds3NhKOeBdJiIoQpScITU1TectTE1je8tTUbvGr7j8DSrjJmbRb69O2QsXKZE1gxbvOVmhlmxDWupmHqFid5UlWld9RgTDb+fv0Ht2h+EdeDzHecx6lhcZnSaHaqR6hfNgPbm6SNAnwWmR/PthMTgPqVE0ONRj9UYGw/DrCvDXWnZxZCmMiGKafSNLlWdRwgTYTvkJa/kAr2ZRMOsKj+/u3szR0/LhJCmpI+JRnQ5rvmdr8LxRNT092fTXJXd+h6yTA+9Y9qoOY7psf8nQ1A3+IDc/EmEzDh1H2Y5YDMNfmLCKGbfP0aM7maLjKkCdjjiZPr6MZlIt2N6UKYB/COvW6r/GBoEj+pJKGpqiIYvJzUA1mb3qWJSNr/ByVTDLgCSX8hhjS5yW42OhMo72or3sdfd4hn9VFfBeVaE4D/lmUuIYOdhaQ5pg+/by0zZHzORY4m7q5LZndahzogevtvZ5kT8LniFy9MY/1Gl1bfIhIFqLWivM5r/oXzXyJRkJbNtXlXYL7F+HPNFrpQ5Stvtw7nKyk96jjKyDwPpWu0SsecLhThcoFNwwQyNbhT+mU2LQA+SOOSyRdc/ZC7AxPX8voFn1ISvL6AthBCPCqvSEeOiuHEu6qFaC2T3m+T27oKVE7CAjw6muJVt+T6k4YjB5aGJRBFdvB0VokEFTB3zROVOg/VyR0li936hmWGpI82n2xpGdDEdwzpty2Z+dohdAarVgJedyo90BHWSgtU2iBhcHoa1g/XYv7Lo9E7kpFso9LxAcvx8UuvdoYSWMBkpd2HIBE6PFQfmk5QUHo8IRNg6YEBebeG0beVn/H6mk+bqSarw3aS+nT7rbmO+xQQ7PJdh+FtaKGttUXWpkyhYJg1PGx5HJa6bC24OrlBmHbL3N5Wx29fFfoaAcNgax9EmCiW8uJBEpHTXNtd6ihUXS7j8K6VEPbChRO0ZpDaTcaEKzTeQkcfyGzFyzytjqjHCMVoByAZtIphBfexH4Qp2XXWfoObBTA1NUhPMrrzUwW83NMjA3JXz2LSbBvbZ7sORcoI+fYOUbWNDXPsD7hwxZNwTVxO+R5uY47qG1yaWPuRAYo+y3ZyOwkbOCmo4ElqXI8V7I64ogkoNJdWQbvtSUzPfQKb9knSDU5jGMieYeeBNHzzxZ9NYfXfLOkojnSp/YP7hua3B14jtHMMpKp3Zc720ajI05NsnFrU9NuER/aeX1nu7d1AuS4PS07ZMHU+I94gWTDu0WWRyAirZvH2sw5RBOoV2erFGE1K5reS6IR8Ec0CV8o/pYqSgdlmcfE5XnVKSvwrUdALUmm+em0Kn/7rsVFI3hdA1xEGiukiodKBtxn4kMlQqGia2chHirpLy499UqCYq9XytsKog028+Qtkew3YxrnmQ/OHlt5ptVIArOLfXC5ARf/TosNuFj3SmkN4NuvQQXfBYrjbwgeAsdhlEbZ8NaX+13QxKbbuQxoE0kGpSMb5O0CubWp4ASxoQQOf+MU2CHIZDQBr5s6Nx4HWdh51PQ+RHv5J28riA5yWUTxD0zxmbzIaQRw2NMd5Rnk6pv+DqXJPSqeHKvPrvsYO9fxi17ie2fr8id3BGUhrgYZIHZwBCB1AhxDeeWRYlGGEEp7o7t+RVI6BfGkc3lIL4y9XLsYQq4D2XqFV4vjeQWzY3aO/qiR0xsRrYFghGa/DhTrIES2smCLINRxKczl0zmKyjw7yYuGm+Y3g7T8i6jZO8gFgV8H1JFZZlPLP883nbdHFd3ctJEXU1+srNZJpo8b/ttPQV4bGcm2MEnrtih+z/VEzdBEcpaGIIBzJwjmedjMqXJ2hDchP38KHtN+Z1Ot/wA721lUtPqN5Q1hc5/nUJGd4hAelsEskGHcQpbJ34SXJCowDxG3iMkslmGUjl0QxQNzS04XYyl1xcKzZwwpGHDSkMMGjTEWGoL2EimQvt/OFlnV/a7QCnDNK4PRdznIpa+Qv819ExRQ7XdBeVsax2rTB4ptLbboscKf1pvpM5wQB+g/6qQI8GY5saER+JbhQ+E9LS+jx+NHxFDDFRVGdITZ4DYvnoJtxEd5VhV5GkLXCPfewWlJPb2QNcHkUp+XGjSWDTYTw7BXgAwb5KtpHcGYbFzRy74MtxJQCFN8e0ksb0ug2MSvWU0k2qkOfbD6F+Yb1twRXJtuLuBmaOi0xJjwskdxALdSDwloLrnml1m8jmgt7BzvAuK6IHzdJl/yjkOXINxLLXlbPMmec+YJfqwSSyPIQ1diZdb2aFYHsEYaVgy6zsItsP3KUjDxU5yiZmv2XA0E0Rkqktw7YQR1faH4PH0NLyo87VJ/lbkOA6IfTYhkh6dZUiVRus2SjO2ikRS7GteQi64RoFZejaFtTV7S/X9usSxmK7OU505imTI9/vQxv3WQyLjWLXEIYrDspbG8LYZM23TrEi4Z9XYIJo7M4FJmYK4E+GH1KsAEuaSCDXp9wDYE3RxA5crehrmBFsgYQpwQ+L1IkbfVpHHGPXrIC1VG6TfTGGo05qGJntc9zgiwpY5lzMd+W+F+C1S2hcnzEd2j1P9xzryowoXvWLZ+gsFnS76z6bOzeq8zR31C575yi74W0/tZYCZHRYGKOdqa0UFCw2kF8RLLYl+HjzyryBkiKlXPG/3NiYvclBiZ8qJUWsIpK/RpbvbhCgeR3zwe/kpAtZf/8rZYOnmnIgp1AKIz6G/W2iTxlppqlCtR4F9wXcqhhFWqAPVas2cFTcvSb7yuC3aMZ79aFas1hHsr4aFQK3VI1uCtQNbX/0Kx0pP+l8nclubXWIkHUxTAy6g1bx8+NS9sBUTYp5j0xTmRDGXZGJSjY7FyNYYfBKkCTJCkKlhbkxKb50TfexZa2vcBSNdzBtLPxtS9besg/fu65fBzL/zlbbXHTm9/vTAXYqFd9VSPo/TscQU8jCIUiqZVAcIvsie+Q6s6RZdR+cOB7Um18hWLZM/08rY0Bs1fpjFoHmB2Udl3TJvVbYx5dvy4IRypDvR8EyaGsLkFkLby9y0yDoOq7+ZLdlwU/krOZ6zxndcu1p+PEQ2+LCrHusfZyrXVOo4xn7i2y5JtOgY7LT8kK7ywfScI/3lLVsUZwnJcyCNqVldvDg406PP8oZXW/bCTLCIeC0d5RlwDiLXwE0VH2xqvObgDDgK1eVAUrVwVuTjFCn/u9BbHBfGAwOhe9Uj2O5q8rYb0vlpcg2UZb/Du6EC0K99xnGJ9Ng2oRrJ9k1zWtzx6NQZlr+shCODCHgTzUi2/Fj6rMH/V198vwOe8AC/S+nb+VkN5ZH6Mstsab812M2D+qBRhjCT2iTklDlh59orHtF9UUy8qPKL3RV5v5mdu3PL8jY5e1pvP9uxwi2C8+i7v0Bp9i4qEoHKxjpD65asRmv26k7dFCRWAc2eJOvRbDW/DnNem5H6K20V3I1/K5r89t0/Oh7b+QkoHp6l0vDINZTkjx3ONR1iYFfwhL5U53gJZXD7mt/lZEpMVsD3JCz5U6/QwXzEq0HTOcI3zWJch+DOqHvLix+Sze1YkWDA90SV81Nq1/BNMUZzHj/EdPhUg8rSUM2pFFh1pI3BmHTLCK2UtJsWODljMtaOtYZ8mSJwZ/cg4cMmQRlDqsYxB/TIH9d2y3kvfJQWKSWTWqw7JfkeVt6W9X5vGgNhMjOYh3V8myW5q/nrd3123k485QeBPVhMz7ElerPGk0xambe9jsk4wi13mjbbqfclDFlh5t2j6jeW8zG3HSGXbcbbCMxtcw7I73nyKaKY4z1NOi2UvmuVtPQM79YRH7cMo/nGa4RbiH55hA0dRFaX57SsJxj2LBp1g8MY+RJLZYNHXC7j8S1gPdPzXwQo6urZCyKykssbOxOSkGlDjcZyFSFX6Kcrqm4jaFIpLtMYKhdvNUStLIHR7QSJva5n96VuCHnBX1SF4k7TsqrOaH6DbjKEBeJlHtefjPR/PxsetcA/AxhymPRfvuXg2LqaKEnmKoFWCnJl4jGjPw/K2+lPFm0Cnk7fL3DSZ7/hFXpZYB0/9uYxHteezbeUz8320SU73CVV3uYt3aVu/fDVCtGcMxYSyhGrSQun31Um2N5Id5x1iTGT+PXDiwX/UqEarY8xP6UFVRfGdY97ZNrSjfAUi3POkvC2GYN7x+rgneBLIVdeIqYgRiJsRAdRWNKqVwkBeJScJEM2g2dPxfskH/Zh4e3hp3xPlcPuUrBFpc4aW5SH9iSRoA1zoVw34YFCUQwm2RAWorTWUQWXR91Et3RCYr4YjYWt42UVH/QwiqffyWSHpiiQvvF+TI+w0f8w0aVXrTRIkjDmff3CX+SxDO0eb9CnI+IzamWVMR0eTN3EYx5O3oc9PFEgPIU6k07uQhvR0ucDC7bJIvJ8PwGiccjI2m18c57X/UyW4EytyeRelaT8LAZKb9DsznOAksI7Ap6431ypMB8SSXDeiqzEwOJARjErHGQN6qTbjbrnrNiyevXKjWaaq48Uvkzh8toZX3anKsHF9AMT8IzzLCz5Hhq2vYolnMgyBrM/2ZalJlT5Ry010zUWZWot5kXjv0E2EVzXeVelawLXskFpc6683UXLr4ubWy6sOx15WydvSSIupAnO1OuZEDQfSOZd0t/byTjd3E2sWkYc7Qr8MOVT71ei8GieyiOJTZaPaNUkD0fQJ/5/XGTNUvpCQx7vAMSxep0XpGfGNw1XEUPutV+2ftbWNZeVn9FB+RGSpezro9yITxriXnPK2YIp5J/pf6CgXRp6EtX1NGOLyCUUlZtrmUWyvSNgRpv16UawXtaYx0atdCz8adk5IN3VM7HSOby1zv8PLNyvddhhhpfTI9otlv1ie02I5XW/yosKt3iRO+blG9feLY9sWx0meYs5ZqG3MEaTNMBHLYTCFSaD0I9n4deQy+oH8MDTZBL5k/udMvEhOEpSuyF8zJGvquOIoz26S27oYewtOlyIprddZn6pg4tbOUYml3Gl2o/LcCNNU+24ERk5ejgiXI2n8qAVwoTsS/Fdj8OFKVw4lXOoqQP2e53jKYvccFcSls8vJ9IpBtd/qVGI2RKKKhj/UeVjfTJOPyChHxkS7Jk3m9lgtpEtTmk/yCik/TLoQTy0fc2hqdX2aes+gjZFtVdhidSeSLHazJ5n7qjwSYfkObdL8yTFqgkexl2jyttpdyVekLbOoA2m9p2Uz2WHMrf8cVGjnPF8964Y4Gxi4vARKm6n3cAnTkDbDa5AUr1W1uSyirFwn9NWqEFMB4RzHE1HRBYM5HFIbC1KgUHOTu0uDC+RA00PbM3hKNeDgwlzMklWS3KNPTEZID38sF68uVbqjG1lgEr+pXvXAw5lIBiOciKSAfm6uj34Wv1H9vdIgb+uvafEjv1pSTS5wTKOogyS7zu8TTNhFA7dPy3ar6havpyNNIHOonwlK5CHMO3Oc7/CfZFucw/zYcU9j9GTDhJ+DDfLLzU2JPD3OqSOWH4rDqIrvLpI/PS3rZ3iRN892bI+bGnnMkb7SbKM/BgsLw2e1gyK+C+FqQ2rV9ic/qS42KEdwIJWXPsaHTWkVt2DG9ZGOJTWuy6EkqmQA43q9ZlVJTV6H0/IkjW7LflZ9Y6pkLQXTQvHqwFI6fSJ7GbNcx9P6Ca2vUdEJnTS/fvmCPlX0+8ufBBYYwRL1CKuviOS6R32lN+pKzbG0hQVcL5sJUU2S4rDsPUGj6xF5SwtO0EVCROcZDcQym6ZPuCPJBneXpNInAxxVfmMyBQdlmccJJWG3v9EnABpBjbdmujyvupcPuf4fZ6sXzbJV1hoW+WAZgSrgfYGOCBMTL+nfX/5fwvBNG+wFItNgNwSukTfjMeFGvmTvENnDXhxQnYvELpVxtBLFJqboavylXTQkkAprUCVmjySrxANiksV43lKboXBIDM+ZpJN9c3wJ3h9QRo6INnNo0g/2nUyxP32zHDF1tPvtNcOsBjyM9atV1zdDBgarSLmXhbZmXbip3eNb5TjmYlrlvO0Ex2Jdvt2FgKeZSynXqqtBnMvXsGFcTWsA845fqla2ZEOsPE31K3oEBZIiJ/u0xfBHCHdqqYJdn2F1gnOwGwsS9/wgKx9QcUX5RMUUDJyMzxoQW25jEQP8BjHwdvAa0PGZuA2YC5OWCfxivHaBz9PEVavJuHmFdS+sg8UVWh0RkwzNTyPjEn1ViCPHtWy40qA9aBughTolyYZi+NSHqK0SH1CvOvTSTkPQIF1YQCuygC2YU2L5VascwQxrVzlHJu23VRZbxK2tU8uMHBzEhi2IDQPyWM1Z76dXr0TDjhMLSfowA/NIaLpLbDMWPbppHq+WsCw0xg0wklJKhmcnsD8zMhVIa5P2RxUXY7D+sazhMkbGASIoxFrD017mvAVgBhjLjGldxn6YpOTat2tA280xfHAqcOjNSSGuLgdqtK9wD2+06frLV1DRo4V1IYvQjMKgsH0KlG4UM0gs3XwZ7YfMY4SLyKvDNL8l9xh6A48ACfFlB2TDkCLinTL2SLs/AwtK52QnjD6k90f5ml6Z94yj4hIeWMaBLZwtEwroAT6UMfh28KFsBDOxomx+TJrv6ixngmwe1jlL6GucV+3/ckskCA4aJEeQVkZJuA3INgkjX54r1UOYw0qpnCcjY2VTZWsYs322y5Rp+Fdyp2BM7mVdsY3tZ8zxEBZgzPE8GTHm8CD2Mmfd9sFXrazkAcETTQtjdZTh8ZpLxnCGE1kn5jiBSOi6C1LtXVI2udkPNnhSSKrFdjSq+xdVJYipOngbplK2AZ2RzRjXizTtSrchTFdlOrL0LZiL/QA06X6coz/qpECNi6+201AtG8oE3a9M+wfQFYDTT6KTWDMi3QwyzohEJv3o6i+tx11hvknuUfFE4/41GtYIWKHDOShvY9QQr7H9nGz7VPVmPi0MpLMRVzH1luaswzpbpei0QuuDqiqS67pCTdTU1VCiYzgTHAo+lFZ3YFCjrsj3HmbM23r4sBnhfGvBhgWMLDt9re1ZIO1QDM/SsnpGC8GL87n2dvCArRvLEnwNz6I5Ly998BYHZM/I87GwC/OGVC3kXVmE93bQ0NO235sb+iOvhgmECgpuc7H/SJuxOKZvjaCUjmI+LpXOl0kXujpbw6WGMpGHn5hHd3grl41hAQbdQSFK3n+5iajRtdBazCFgiDFZOBuuBPEvYT1XdWQGvlLReRes6C1Tj4Yx4gmNWJJWVEhBV57TNgnwn6qtrZGL2hHNJyC182nSFbbeVnG24Y4O1ZmJn3d4d1eNYyEG3sFdvm3/YoPi5CZp0pD0ZjRTBlbXVrAyXNGBqTU92EH2NhvRfIxuNse7wPLwSL7QF+SuJBwpYz8HXGBkoQKNVaChQ3egEB6jZbn8UvEY7gwLx4M3THoHY9jSjUTJ4G6yXU3exbYcZbeM1xq89Jdfcf5jX3zHMuEb9/XX4Fl6FXbb8mV0q8gOI8IG9thgMctVMFwcMPlLg/NbVCRRVvXTcpSvr5OMAlr5s5jiURBOgcKBpsYdWtpBxraj88kF2zk16dk2udWoxmd4oDNAsRUcv8PnO4thbcfS2MGTnsGo/lFHNEPs1yzxWhUsnq1YGqMOAetjNPAlNwOoo9vB8dCcmvSMrbdtvO+6AziI/QAM/ZwE/PZI9Wckyruh6C11pgiWYXClOU4Y466x/BLWN9v5tlgEW2Ns4wdHU3tfybjVkjWVyCxWCcUTYKmo+yNfNrpVu7Wrx2jAy60kI/6wWFU8iqUXl9XRwFT/d7GibZUmv7C6/ix08quLiLzl8C5/yNI8Wml5awwemLs45JDZsOvn5LwF92VG7oIpbXQbMKq5GIddJqjAoyY5Utnc6jImgMEhDushbXhMgt4yEzzls6X3aPVQZmBR9VSZdICttwUMqjNECJATsOUumhekvZ+VCXfXhHCO7hP0YGoHG0Mr9t4G0GEH5lrYJVZUjmC+bRueo51jyQ8o3dzUaUZyvo6ZyoiDpNW1TMvUdOZfeetyhoaXzJaxtXZgc/O5dp4tGL+puBj7f0YPJY0x1SZzFSAhpu6AbJhYRLxTyVyl3Z+BK6VzYtL24slcSe+7/J8946i4hAeWcaBDMlcQPcCHMgbfDj6UjWAmVpTNj0nzXZ3l0/CbPewGgwdPRL/QA27HjxUqsig9qKs7Qt7GxZJ7VE5KG6PaEKlUFW3IZ9aBncpebzWkGda71Rzb2EYWEwAneVGvaQ5qLYOLoBA391A2rAugtuLTINZgeSdm4Cw5cXeHjS7zTRIb8tEYVspIFMyakzjkC7ES3Iu5eAkm8O4w0xX9932R1xs1JzGAUjay5iAWKcA+TN+2bs+U9X8uxgPmw6TpodY2CLGGawyETDPkKcRXg1nGfFvKd0DX5xV4o/kw5rstUL8YftFrScyAw6tgDHIZ94F8vSUsKBnDrDqcOD8mzdMKi7Hil2Jl/iQdBAyxIoWzYUMQsflLdIH0N1UvZmAkFXVNmh/XXJijtOeBMVhALtpNmwfc99m4bidPDF3O+q9ldIs+JLg3xVOfCF/KeMpaqlcP2Aoub0PADSqeMdg+LjUaygxMazSHJv1Y/NkDcCSN5LPip2YZz8W9TWsA64Iye0v5djSIpZh2NG8mnaAVlt3c6X2Xmkc5OOn2bnuBzuPdHRaU9HyuHV6ci11iNp37nAA5AcPtosuctPezst0Ousq9T26qo6hYXZ3hLt9FJVp9T6q7gYNk7KKpB7FlV8WGK3XNyMQixP3hAisMezUD7xlOgxEnghgWZ8yREtGzkI5fwFoqpnTVGtUNAuwpWwXLy1CjoczI08o5NOlHV2e7ePgru8TsGHlUdTZuHre6O4qo+WCWYmpwPk06M6q4rNr6Oa+QyRlpgJOqrATEWmVl8O4Oa0p6PpeyKs7F9p+RztEDXj5nOUZQdutHa3tXVYLYEIC3YUhlcztlpTcZyQzcajJ/O2HBhwZipghoaxqLPfD8Y9OQ24IRm7VJKn6XbKj7uZpIYzAwFXgLYZX2e4x1d7YXuOMzrFd4HrZ/c+n63ZyZO1bR8cUIWsV0trY4uAEoy7WEq7eHBcEhzMiJ4ByZtN8jWNa9gHRjY+yxwkEHdDbgMZv7rIQzuyl7MpfuLKOxKU9ttsBz5RxVdZGdoz9qZBIZAYPD6gADaac5g03smM6sGsMs2rJqnnZCTx46bSj3ZBWCB+2FFIBWmklOmz2Kiop5s1p5N6OoA2spY3A7TUXelPz+UP6kdLjNwqBns6gh2qkw6cVQa0EVmRuJdtuQ1picCXdz/9AOYwl+3cldRBiFzq1CVmFyTt1FXwvdIJZg0x30vDjL0/RbXuFRtAHW5MNBVj6onuuV1wHTEXHgVmmIFE1B3Dp0fusY1mAoM/CswdwZsW1fazkl/Q7FP/Kaz1ksfJYr7YYIQCUerGul0pu2DmkPwhi3jttthzcD69vOt5GSwVde0JoS1wUmxe1Z9EStjKdZQvDq7nUUtWDbyriCnXlF1Zj5xUaQk5lRZ2YxlxjMgFE/mHpbw4XdFZ7ANqY8IkNgwptOd+eGzQPcqlsaywtl29EtwP66+TbpEl93sdVApvUez/3H/PaK+U14RroAFHUgnmdAbPhc1QpkU+Q6v3WcbTCeGZjZYO5MesFV3Qr21drZIOCJGHY3DWuqEczMmztpTjPiQh33WXKdK7dtxasGCzHazjIYzSdyUV+XcZE0D4abZVkDq0hTxrDQ1qlj4KYWSr2m7MwMjKYn/k6wHR7vfVShT6gkTvlXJ0W+1vKdog6cEJ4Ft0sDL29ofrYz6M0cJlQ98U16wdbbFua7zG1Zb6gxKeMxzSzOdmJf5mc6kewmfRhqLXemuLlJUvwFXel8agRI8DTRAVmdJQTMs+e+knZhjpOAjLBGZ9OFnQYP4pTLBE0GpTiVQuDwuTS1v56UoLdMpr78UUE9jllOp6p5stHjSL3lXD6qvCDPZyXrqHg6fozvouwWneOldlQXuIn4Se77oasJOoGQSlaeH9pWQNZt+z6NKDTu0wxsaDwLJn1RoNkOBqV/2HHmqEp4lhyjX5gXwc7MzYQgwS24b1R/MbY7jOIfpxnuS/zDzsCiqwixoKSODVNqm90py7PpaGbgbdP53AnLjWwwOj9PTb2ZeXoXnT8Nx7IgQ++gK+g/alSj1fE6StKDqoriO3rvfpIojlfyKhATg9A2LKxozvZp86U5WD+UGZhXP31GhsxkwRMXM4SrZiCxOh+xrIKGYR3ZdNwEwKSjPm+dnNWNZF4eBefLpAtsvW3gVGaxsSxmJ/ZYwswnbNlWAXZWrJit4mb1iBYTvcCcmvSFqbYYe5+uN3lR4b7d0O0jvkOrOkWXUflDytfyKhBDj6BtGFnRDJTMgu35NFYGfYdmYEA98U060dZLsltSczHmO360Zj55Ffj5UEfmUzSzDPPpOzQD8+mJv3PMhxtK88ZVuWMTNU+IFeSMN8Da8x7QDqSHqhh8+a1bN5TZeFY+a4ZH/Jv5TkvHuE71hOtUuAYqulWzjorqy/W/UFyRIvSIGSGmprQoy/KKYvn1a4mO0oLwR/n7y6qoRWYmqC9Qxb6qVb580Xxn+Kp9xEzgUa569HgUVeg2LxIEYunLn7S48C8S3gihaYu0KD7mcZQmf6JVO4Nwp3gofdc+RtltHd3C2Noys86hi6qgMZwlZT5p9zg4LfIzVKyTsky695YhxDyMFun42XMR4fhuXNfDPE3BXuHvRpWbsFUZii562HBIquFokbS+FCBNevcTXUfImVayapoygxXTJpX5hKq7HJzyMYQeIZYiCK+KeyxawZ6NAIyJTcVVVqlo3oJoUR6m+S15RBDC1ZXpuakx2IKs1FnONSi6R2ogHMO7VDr6qESnsdw8S+KqLkAcbZEpQVSYRhDG5CHZpJICrSWzD4DpUaM0uUfF02WyBnvKlpsOfEiQoxg7m3bIFm0fZnySpJVEiGnqmDaqZKoxjAFvNfCfoqy+iejUq/rOgmlR63BaIWs7cLFBcXKTxFQX6umn6DFcQS8nwWpf6A0SKDYV8I6NmTdjSrzLCNS9hlJTRN+iIomyIbT+KF9fJ1kkI46+lrbhf9QR/fI1S0A5w5a7jsKi66ZNmOC2Rsp3hiZLsOh8mxBDJ4XbOzpQAvf3d7rTQ4IKfIyDVY2+UIvmM3ooZbK7K9MiOX7EMjaL0oO6uiNntmYRyZVpFby2sf4tZAgz80C1CRrpCY59i1qPKJJhMOsFfZte2gtaqkVEMyBAONp0EoY6B/NGBrwJwk89arADL3DA2OFHVAyxqxCa0U+2EJh3rUzQkDcepGialzY0aMTc7jC9wBzwBgcfmU45JLU2RCKj2Dj9tna0TPJUeJij3Lbavo0zlMH94zPJ6Y4bfM4b8NghpiiyRSvdcWTJl7S0hVJNyLhJkkrEsg0T3Ho7wRC6DZoK2Ih6c1TUuKdG1+R60NqjwF6Z9EaI4JRK/rHTm1aDYWOlYJ1lHJemo1oXMQPSawhB0q1G5p4DXImj2x/tTKZyrYIJZtGg+Voo0PSF+o0HZQgrWUqRwMPo9bo7fJSneuU1bDgcARhYpXLYKNH6rGutUNSJWmJl6f3STTrxKaISV9qXtlxvxYKdD0GjlsyB1OJ4fYnWm1SyCiA4U8PVkwoxD2N8DFXg5EAMpDoBWynsfWMI/cCLvCxxxVSBkofRD7zZTuRW3BGAwWEY8FCBT8Wgp5E5eg1S/ZmLce8Cz1gjHzstT643UXILLqKuTL9qmo1FuWDGIEan04+owqdF3VKHIQ36HJV49X5Hye0dSMYRgCm6dwnmhlLSUx5Gi3TktAJh5JyEdML4KYtVsngoNjj3j2+H4bM+f5dvhFQxXO7WnkPHXAurrw+vhstHpo7iHnGowN9is7lzFPV6V4d+yNKLTeGi3LSJzsuBbWK4gOX9FMbEMiUke/2rpyIMrRkfWElKP/7WWkc9GPvEpONvkK+4G2KRfJoa8kGqK0JkBK7AFUTU4AcIyY3Vn5h5mipZbwygGAoLB1KmuXpXUWOEYmouGjJXN5f/8NBZEHXPGUjZ8HvnAQ0RWFQAGUBKOpBgfC9/hWUgloUxVkQZtwCRKga15KPTV4ZoJ7gYKOhn0AK0rIYR+5OVdU+46t0oAEqCgIqhQfAgvTgPChW5QJwTU6jLHKKgDQ8iHwEHCdGDcZVRkIJHNBMROG8WOSnGgPpxjKfWmyxjdABx1FznQKE+rJfpqEgeAEo+GBEYIgzjn6UgDIALoIqUyD4EOUzSlHlYTEUVDtRgOOMaAejDIZyJSK0z15AlQEElAVY/Kr6Kik6D65kBuQTECi0wBL06hzWlFigCyQciwEKkYVzoFDQRUU2sFZIGj/I19dAePPlgeghw6nHw4N4MAyIF6CMltYvWPPLAu+o98QDlGYZUKL5gBVCV5h0FVeo0jBXSqiXoAlCpM8HqqQTlflCOh0v6EIhKXFIHEWsQQd3a5lVcJMAo5CcHCq4vxi1RJYp5VNOyS+cKcnWw2aQJWl3mbD9Foijh5aNSVYOIxXgXK2ilxAptXdIpCEK5gT9N6NZD24yvqxSSZj3OaZdc3zDsGq0gGVjBYIRQvQCEA9ECtIPHGUrAX43dvKXifQynFcMjcIVoN5LpY2QQicau7KFoI3UhZ1//lZPMqLp28CZYFARWuc7rKW/UuHy9j8IBws9K2wm9biKtYkGAcU0jiluSmGthWjEqtm5FRhcCTkm6WYnW61ZD+IeUZiKsdlhCFQXFDLVBKeaptRu+YT2TCaDmo9IzmCO55uEu1oNIdaAA4eSDgcAhEnFxRArygBhnOY6OWh4HNkkZSl5HywDSqgoWMyejthGApErsgeiqX6MguN1A9WvVj5CzbghwvJgBITUVtUNW11cQVxoLpyezps1pCa4KALyShe0B15YOaBQXkPbYwCtPdTCk6gbUoQPQ7ZcZUwRfJ+qoTtvFo8Tmyt1qCs+4zJQdMZ5TCVN5mBE6j2Ia+yq3IrBg+nM/A+1tQ2BxyWVU0/9QVFGE4praXYxRaClgiklBaXVAsn4SjLswn41H1SX9/m1S24sq+p18yjmZVYlSdWQcd+40HSMUXlRhMS00MaMuALPDxfFPNUUOK8R9WTisBSc6L8v1XetK9dW4rvPglYrqFNRWKqY8zIT0p5G0V5JCi7lQ47EmkxKdxRx1IcX2E6XugXzStFzioXQabguWst9UwJvpnQuJ6quLaL1J0ZBCRE4dDlI/pHEFbwpx6CDdb0iS4k2fPh3K+P08gD4SSPmA4AoQfdiELQoKSRDOEFMxtKzY4kUgk6EotnFrssy6VZ+j+wQ9GOg8HKB2BYzhvZ3qYKwzkugDSjc3dZoRT9lRgZZm8pqGw5UiCEtVeTOKtSlrxoHcXTYmpcOrCCQfnQAL0YvJD6UglIhqYodX0mDnRDqkqYLpIcCpx8GDe3MRiBSgj5TUPi732iBDCaTCyxCsEMDffvYgQlUaMqX/vVlF+ZCN6kMU1SRaU1DZrMmJffb77GxK6gJQ8nGJwBDd2JxxCiIByOagCM0zpycJB6YZxhhaSpQuA56OKhy6Ochyxaa/k9CEhdGMgAGVUCPSk4FFAtBglM4vJHO02QSVnNHAGM1jM5YwPNHggokhUNRLaLBJGVVig4EzWevMWEKIDgadjENgAjvQhmYUNAirA+Hkg4HAIdp0SScVdAFRTRxK17SpkqcchK77KilqTIO5ZCeUofNqSKsud5aHK8iHpayncpbn04AaeM7DbSg85yejZJtP1ZCMDbTl+Bp+mZCATQMA9WBmdl2C9KAjpRcPolk/A6R0FerPqTymeUigsB6JQCadV1iNrAkxj62oy8N7dYZ7fBeVaPU9qe6YvLoiaXRV5IPT1ITIxuQQVlBNh1jGTqFO9VB65KshxbGchnAF/UDBeir6WUgmdRsAKaVzFIqSX9kJNSbnuJbleEeVpyTsuKHJ5R7Jcq0R/QyIRk4NkFKJ16bc1kk8BtOUJADScivVUSW8fEiqahClJFnFFURTtjCxHgu1rV2h+kp2g3VcNpZ4XefKMXkWtURLSchByMc1BpQlwAJjV1V4plyYbFr6qyHZvZwIY0D9GEbwKpLoVTQYJeTuK6Oy89G5S0amtSjwgLozMAfvdZ7mcU1sVBi9QaCR5iCkSkBAFWCpMH4pQSl1QKQTC+2h83oWksIa3BUZMJLl7dPM7MQ/QKEJL1eBq0SItBYsm4SHM5TySY58rvBwoQ+qdSkHthikanV60m+uNSo0rLBPSGEtxqWwVnhSbCY/lzxNv+UVTbdMr0vZJ1MB5xYFuMLVRF7L341FgVuSp1WS8tVlRwDfrbkCnsoBdgjTugr5bogCJLLscR7VfmLaHrTIgTeGAugt44d3rk6zhLyqrThCqSqoFA5FPViZEZ4NUuozKvTTnubBZ5GuxCeN9MSU1jUfuAyFCYlNT/2GLQJU106qS8rZ4XGmK+GhJpHmKnD5oBW1wCS0o+epFMRU4YV0TOGtqqDkU+lHIJzZwFRakROl5tKFdDQxpIWOBtqxzzlm4W0xvesRDK3xhgArSV0suAdedK4WMPKJKTd+Qe3qpMjXKtKpwBXamrwWHHbBvfum9GeWo56XdJe5BeEYYOOxDXUCE41BPDHJ+jf2rhRGFBFIIWB5WFBcM8/+qYS1gGtig0n/up82hkcCqdp4oArwXpaaONtKEM7g0nxBXtLD5+JkHRVPx4/xXZTdonM8TcNbfcAhX1tJcSbX1YUfesh1qX31eEFqDq8VhiUl/cOYhmNow0GOKoWg2hjh1OSSvLWo1C20deQj1VUFk7dLX45UkFTb0NR57iXtK4x2uir2g1WY8IISdR6DHvh249VJAm8nCmj5AOWVIBrKXp1UUFDRwMTBtEzLV+NHJpW0G8MaDWxURUM3Y2qNkQK04h7WnIjbRk99mjIdW8mWNVgSTMmCbDtg6Lt8yhyIO3r68mr8lrRIVQW0fJjyShAd+cc6FfRTIIZu+cfvaAcIfrOhnAJaPkB5JTi2zZhyCsSzUW540fTqrHuKVEY3AFY3OLGKnGajB1i1ZAMwQ1JQORsKqv32usFCbqaiJENFX/bbazIT66j98NtrDBKjTVVH6ad8hdKyK+hepx1qtl9eXGyimFyy/I+Lly8e12lW/v7yrqo2v75+XVLU5at1Ehd5md9Ur+J8/Tpa5a/f/vTTv79+8+b1usHxOh4dkX/jetu3hJVnfNznSslTait0khRl9S6qouuoxPNxtFoLYBdYAa++XP8LxRW9onvktrzfelJ3DbY5GJrIIHEOCTQxCHfg5Hd7TiFNUV3/FenTKzDwaaDhCR4WmXw6QsTMuKQernkRR2lUnLUPpnaSd4VHnqf1Ohv+5nlPXvviqazQmvweY2G/m2M7zeK0XiGsUSa4drTheiaUWmAuz6KyfMBHeVxQIfIgI4ccAjDH31UeIx2+mmO6TKqUI2b7yRzHYb56GqNovphj+ISq6D/Q00NjImExjUvsML5DzIvePNJRoR1egGbMZ3NcH5M1Zq3VZd4d0VmMQqE53nOUrVBxUH5PVlQ+s2j5MnOsTY1/5hk3dPa7LbbvRbRpfREgpKNiW9wXd/kDMFNCoS3ew5zcEPMLmi+zWMtFkhdYmnJruf9quZYvo1tgOdOvIqbfXnPind9BXgtbCLeh8xuS2XYVPSrfcLLYtXpMgsHMZO9S1Z5mBxP3Lttd611SbtLoqXXEYDGNS7ZmtvEH4kTkN9EtEodJltbc1gmmrj9jFO0nC0WJEIEfSP9xa1jjY447n/yJVm33fcUBj89FKBjgmIZzmj7wOIavFopFmzKJx8V+t8BGCIKwEtbm1Bhh5MocsEoQ2uMC1s2oYHu4vs9o5cXrklRdJiwurbqtMrHr8VGdNm/dQGzdF5rj/Zolf9ToAuXkgD7GyhWZ4zxJo9vTNe4PMauLQweKLVT7KuX0efJh+SPHWX2dJuUdrxUzn5+xgtNImYuqoK7SJbW3BdjHOIyuW5kWzTRrPuwe1PVeXE7jEnuMwK7BFdmYfYhv1Fla3yacxWFcYoPxMq9jYV0xn7dmFZyhYp2UZTIklvNZATw2B+7Xo9jW3S6smXN4epDFNXzdGg7SpZI05x6VB5cB56irbyvXnBQIdeGInMoxKrEwKEWPx49oveGMc8xnK1zt9t044HMIR2XmWKnzN4et+2YjZZuV1bgGjgUtWzL1Cl5Kcudp6imtMQYXCQ1W2wV9JJSMb682ICbpi5bRwomF/Ev2AYvBM5o0etRBrsxivaZp/vCehqFf5t/yil+6YvEc5wa5FQ2zOWZw9LWKeVMaW2Jj41mB+Njv853mFpQ3XaSor9SBI2QNZY+s8jQSiLTIY+i+zSl5Ptfra1R8ufnWJD8aoRoXPeMzuxAJ7cuIbKS0IzuqUUzHlM0ygFhzKAk/cRoa4yMu/v3l5r/JdPt25v67h37f3S3PROuuWR4L+91Cad308T2jLg2fbRTgg82myO9FO8Pw3WKcBcJ72epLJmxz4xILM+1mJcE4LpmdS3nmPEzz2/bRBge+VNaeiCeb5i6Jq9l4qtgCC18gPASSz5rvFft98VlSvhdjIqzV9SeS1E2jgpgePs/r9dWMXmQc9rsFtqgSzBbdN3Ms7WM7/4Xw8aGKuKsSodAa7+dcjrYv2y7uZp4f8mV0JapJeb5pX8L5Q6GFJ1dUtqPhvLiY74vPI/MAkMPUKWtPu5eIwmVcstzu1L2VxI+T/b51R5QwpnAPNXlu/fh9nUg05KbEQm8syetF/IF5+GphuGlCrkY2m+bTEl7bXZ2TvFhHokoglNpjvojSCsbalFiY/FbrJOsk0djaNyqxuhSFLyZGBRY97JIS8IQcFcx9KfEOpUiIG+g/2l9u9PGW0P1GX7jUJeXHCJ8N4BMtV7TkOZR05WN+m2SgEVcstcPcZTKSIhcAtmavGlJ2+OxVklwkBluVtOY0OxUN5RJZn/lsN/MiquHrvHsUFsebKON9BbqPNniwOCkEb1bms9U1TIXwt/skiwGnZq7Qoo9C1MWRZcRFy3Zv+H2t+2qN6S2I6a0Npn8mG2JoiVLRpZErstAK7vIMNZcDnFLAFlisn+gRwsZ8nkPKL6XX0zXg6+reriQXtV5WcxpZKco2W7lGb4XL9jE44MJ4KLLFCbvL8GUWdrWH/COqKlScloBHsVhqgfmuQEiFGyi3uhJERRKDmPkyC7ld00jmy/xbxKmd45JdczN+ZtfxHaN/QtVd7um2OcblEq2lQbCtMkoaa+wYZxyeO09vM5LY644kbeDvDMdF28OZrG7nyZgsKhe+VNefyqAaTokOsA1fXxfovknewW2Yo5JdE+cLMXd3I+rH1x0Wx9tmuOo03BzWA3M7EldQVbE1YZaAFjkUWeBsXS7aukei1Q6GsJAFeaVvRApk4/N9yxGl+fJ8PDD3iUtCRhHu3FH+rMsuGeC+3v16fubbeDISyV18V2Rz31TgkdHocRpxD7q4SGDMW/mWlMl1ik6zVXKfrOooTTm5DwLMGg5wR3OsSda9WGpha6vTVIpYKFzyXq9jIrTG+pp4GwcULx3O0NWRK58wxH6D0fAW1Z26KDzq4ANqVzyEvZLV+Jhd1GtYw2KKndQrCXoYwr731OUMpg8I4TQGeSNSIAcb4UHMXV2NS5ZXTi5+1FwHyQeL9RFl9U0UkwwVBd7RKugCRAZj3sr7ig89b77Y+AsMT8OPXQWG7xb9aetASgNfZuN7+kedFOhLdYeKXgfjvFAhCOsWBnUDxj8qt1i/NZZbeOHHRNE4WK04bPxa1kLbzG6X1Juf3eG7hdGlrcPPLPvdwlsrS5vlyeQdH/ltAeU26++xC2+S4Ich7Klx/LhJCmoMexc9lTBleBj7VqgzCMUArS05lIV2E5UXEVa2EMwyQLGFNB3VFC71hVKrXhMHv4PbAiFRNxVL7bwJ+4qiTypQbLMu+yfw+IXJFNjIr7bS0VOcoo8ou63ueAkGQbi2cIaKJBfmUQbj0ApVMCgaQRJDEFb+cXfJ5jiL8PlPEIqjIhuc8mQMfJmVj0hCVnKUdrWbKxvBZ0QCtZyH5Wl5XAq0pZ9sjIl9sk6ezbgiK52MGJ6ze7xiceXm0pHHLgWyMWPm8Y9/1BE13fB2zFGR9YUHrX9wHyVpdJ2kAno5lFtL8CBgCIt5SDIFdrHU4jSQPzRjb10nhcsHoNzqlJTcPFF7x0ledP07RPhsKpyU5IAWFxZR/IOmGCaZ74UQO77Q8rwtf5JHOHibv94jb5OaQvDUJut6Dc87DGHbQvSoa4GHsKQbWrVVE35rAoqtVh3Zdw7rp8O6qgS3AqHUGvP3pLxLk7JSoOdBLCjTyJoUYXY/w+cw0TIGQ1hcFuDTEK2axHy00ajExv4ooLLG8SVdAWiGr9bW0CNyQwvZQZsCiz1og+IkSoHejUvcMPbXcZfJGrisU0K6tdhe2Gnb4+EsOKw1Lx5nFSpKiNEgAKtdjwieERYEsY8S0OoEbNieCtDqJHaZoGYdcpKRK7Laz1E5PHV/lK+vk4yeb4FxaIGtxoJlYvO618Fmkyb8WQEEMMf/HSW3d/wjCO03C+oA5zz7k933ZMUjaT9Z0AsYzwfr8fR7hFq8KMAc2lIJFinQkp59Qd2oAkWdbVMOEMVYk3tUPJFJFOxnXJk51k6P/Jolwk02X2aj+Zeo3c4AQ4VY6oD5E4rKukCkbxLsIwiHFg7WopuRUOiAl/xQ4mYBLPDX2SpF9PJStPYJhbZ4z1BBQs5hI5EExLENQgN1Ez2E8yjyxtSE5a9yJCzY1rjx9Bu3lx9Ph8XBkUdedRpPHvKvp79722Pw7oErs7KwY06JMYkEJw2uyL6nMsRQuT12SPzwZc/H7bG9gSyP8nqTZ2LMEFRu5fYOYnXD1s0Cvfqnyr+MX8cQlh4HzR0b1hYgjwO2cGukXqAnuDze39q9x7eIv5yIZfhqo3yGDRg6zCt8WJdiBYptzJxJJJg26Scbc10z1zLvPqh87yanxtU4xspuxcRSC8wJdUISUA6fbXp5iy6SP3nLav/V0S2wvMwv8Lk0rmD8Olj7/n+BrkOEQktz83mUCeF4o4LFXVwnNnztjgPgNppZwhuTdsNwcxPVafUtQQ+fBC1RKNwahauVnp7RIg0Sl2gRWc1plK22ucMki/i3Z7gimxuTNRKfDxm+WogdlJP31zJBlxsV2Hi4fEbcnX/7ycrrpoiyMhGc1kYFcyy8ZcOpwqyTES734Kq5V03ALL8hlbidC6/udJLWFNFE4YYw7zEIPSx9SizTsFbXtMz84YaNGch5nSJZVkADcCs3ANjiNiqwODs3+YMk6RbEUhudvHXBhFEDxTZGuLLCJwWqzbIvlolOuHI4l9bOpCEREIRTC9ETYZAuIY2sFQ7KpaVuAsCznQLMbZbAV7lBAAvD7mNVRERAcXbd4fP2iGTmTtVTFjOYXISwsvq22h5x3bz4gB6BF0u5IuttvXkoFtzXu6JnrCq04qq5qSTXlEE0zwGdu/KpwrH9+md79QtjFArtPSxg3woXJQbWVbbnltFfeEyYXyBJK1T0TnbcHiqWWpgekxW6vKvX15mQ15YrMsfZJnoYY+s/LmQMfNZGvG0R6j0PNiwZWMZz2EOIfC3KaXaAoQOwyJa/kyG9tukGIuTXZwsc8FF1R4q0L7WxwJ0VqLkpEmMBR0XbxueBLvPH2Fzu9LUYtl9vkV2oul2lnpYnWOTWQ7w+z1dC8fNXtdk8F0EYlkXozrRqLNvPuGz/gSjWUdmegZ0YOBznerLsErzqfwwJ7fXEUkHmWSSD2XsXqXHtfYB2zwdo7/uyPzaPy90UNBpAe5PE1HGZsd4EUNVg1O5Kmym+7Vff4JE0UkW4OdTAWgrUxsQgxAjxZbbOiJ0PhcQfcVT8jJVG1WR5PmugwOzyyoEVumlWFNwHM/5fIArqOXDiFDwYjPt26HCza9zQyl+alD/Azo7xuG/jYOWlZ3rZefkWFUmUgfkrgsyXAr/7PFohnWgH8czU659Dd55cvyHyFT23jCG7mmvgoCyT2wyteusKH28HlFsduXcm08VpCb2fPXxd5mw26Er/ueZ8EbgiCzk1QVZIemL7UldfbigKqnFAWelEkK3Z/VjW8dvnWEwOO5q6+tK6yVwm9u1yEZRLjTbuixcb/eet4W+JojSJShdOj9tFg1pbSWpEgMrNsZO0P/iTkCOZ/W7DwF1af56Dh+8O29VRnlVFnkJpWmQwz//AG3bNBVhss6+yEBkdltuqtktwUz+zSaR3484fTIRL0E0qx/k+SEQwBLZr3EyDMC7+qKMClee310CEBltoecw/WP2rLivxPQuh0OLQTg/XMsRi6TxulPOpjHQ5QBvjqMDm7j37IX3DUCicMtxhqfiu/tEcH1nYvyZjL/fkVaeRcV177+uEN6qMSiz8Bcr+1ZuvBWdn4Mvs+ymg9MQH5Xbgy2zkZ1ahJmsgLzuZAqvAFCC/g0tyh+NH3H4paCnMZxvZuE8UIZZbShomd7iPqOnROMgaRd3tPxiDgcgOwceqsHP3UPNw8X02NyQLsTJe+qV/zGmHxYGR5VWn4eOPUXZbkweVeA2J+W5hhBGdXa0dXWn0IxAQabXZ1Cm3tzZflnGx3Pb8sY1jbvNCNPiwb19kgbN9ibateyRe0cEQFkfE4blbeSNSoOWdeMO7tz5vx/iFdgSiVhZZlB7U1R1utPWHOkcxpaXPLqHC7LBz2KGbZjfptAyZ9mGZTGUtRJq3n+wOC4QqpytCk5uEN1dA5fbYW6OHrhEAzLytL2RiL/MfiFuG7HdLbAcx1tlLGc5RqZVmfJ+sUCHLPQWVb81qP8mLen2Wl55X3T0ah3WsqDvNor3MN0nMo+g/LrX4xTc+rB/xPTtYrfCmzO2FzOd9LIrt0qBsEWBtUDyui0NSeZrVQVvkUfQfF1sdhASQtXxUYHFEabI7c6eT7qOFUt5Jz7EW3n+1uA9I8EmYuwloPtkcbsuKNCwebofv9thkMwmV22OnWdBAvE3JXmbZyazIX1i5yqlZRdT7Iq83oJzqS3bBmUAhWNq9h5cs3eclhBRZmqD6NCrYCyxDntmHEE+ktlEREEBto3hcxaGk8jQycfsk2PPm7qmspwutmtYN32fBNNNpv1Yk9aZZJrQxKB5qVGCJT3TAYD4vdy0a5uTV5h9vbQhCUj6h1Obiq0lrLUENFFvOy0UVVbWAlyuy7y+MViy1MCE2ucRhxEKhNd4mR7nUPikDsue4o7ooUBY/AY8nghA2LTT1zrFQ5jGzJfZ9vowe2/0IMi/IoWw8/cAITOazLV/X11VeRelpFqe4YxB78xCOLRw/6lroIexbuCT1++cfVGOBIT1bVI4NhrRtsRUJirHxEI4tKMbCQzi2gOuKaw+GcJRPWM4nRMeM0hOEQJIZgIdoGySmAXiItkEyG4BbWFKbKpxmOny15A+Y61w4Dc6GzhXZ9o4sY6h/zXdzbOfops5WaAXFXvNlNlgfomJ1lidZVX5HBcJzyzvgSEAs9rk7FP/I6yG4QXrOU0N6tCgGLUtA7HdvmTsXVG7hzHNzk6QJkMxxVOCgkW8kGvnG2n2JnAuw0MUHXywOjjCLQCqGGtKi/7gW4Bjdf7XDJKqgw1dLTMCY3Ub4KSp/oJWamjIYuz4f3d+/FXvcfLXDdPy4SQrq9PIpz/gEGCCAK/7/QhFAZb7cjYPfJQWKq3foOuH95WRANiaovtpBTHeQD3kKmKNkUD4tQRwkh3Jq6TDKfohHLRDAGb+4WEEAN/ynR3LUpMwJa/uamRRzX+6E/fQ64s2jfKH9vkB1ktZfE94hxhAWK63GOmOR/EmXKY3OiGIooaMKzr81kUnVkP4tnqNSyMagg7WRjhuSBkdBTxjCpwVoRHIoK0+IXstTDEgBZuNkXsR3UYmkVlgQwOZclcB+4qMCe4tfc/KC7X1dmT1WcuDCS3pTV80erbTSGVeyufAJkwl5F65l2GPUOVpHSSZkm5WAmLfxISKRdO1h/XNe9ckkx+0owCzkXhyjTXV5l+AeR/gz9RP+EGWrL/fCIUANujVXUN0h/2uJz2sfkrLyf08GQOnyqIwZmmkurMI+m0vlKnghYrk9OS/5hZjrfXJDz2wBmQtA6cJcZmimYa6ubR4L+91Capdo9T2p7kAmEwrt8AKvjjKf/wKMG4ZXPfhztkDjVgVkuAV4DE4OZc/90L0fX2axMwMWYnvL8GnZ9YAmnoyATCYAgP3Y8WF4A53PoHIbbStONiQNgKjHckUOOIEoKb7MQhdHGTlpiOo2890WG9DBUYGFVRKVpfB4Qf/RhpsGslOFE0rzJgA8Y6naS4wALk+Oge+KuhO6PpEGJe5KQ9H8+uRZwOwS4fI3kMyrNGEDeBstljpgBu+axVIbSsr669pXeT9d+whecjtcZXdnoGZ7BQctAXFtAySDBMRCZdBezfpeyU6RP7pLtQRkIeCKbDaqrqpU7QEAbLxzY5QNiazENGlCsUXfsfz8DmSRZ79buF3S147JLsM5XDLfreXrEYmyhSRsU7Bd2zNWRDxP6D0a1+0Zrjvl9uy/ldI+jwMBcmuxSh0d8+7yCfTeZ4ufsabIWoXD2I1EjC5mIyMs03BqWP/yZgicVGq/2WI5xCWZkHJrXGRnd4JO8+z3+c9yO7eCyM1Vk07JZ9V0WFwe9pJW3W5JfllE8Q88MOiilC+zwEpcHyE9ZVRgeZuJ4GtXvszqbpI+CwOiFQr/AqvH31jBYvJYRXOaLPo2gbv37ruDAQRem9b2453JjHyOqrrIyEMOyDfRzwiVk9qirD8RGwUKrAvNQGEVqXB2r3MUlXl2khfNbPG2dq7QBi+ddkTP7ryJQyh0xiv3HlEC2s8bnEJSLLXh1Ojmpjn4csw6fLew+qzWSQa6FY5LbCjNLF84XFECspvuRItt+jn98wgL3xAb/xib0+avQ7HdkvssKlrVRYyuZUts7XMQxnGJjbIz0Bi6kobKFzu0b/nbht2oMAujgjx8ISTihiGW2G338g4IB/MSeAI6B4lngGMakUf+5ey3kZ0Xwja/DEctAtF1ilpRAeOWQ9n0+zJ6PH5EAhlGBVaXlkd47dzmxZOQg3Bc5CD6tvSdPDltbR/J3RbBEuC1NBhnCBEz6wtpQuuCZgABzCnH9i+P+a3exaxNcV2QoM02xCHUrRmE1e3mzBDTNOuOb148P4vlewd/a64Ly20B2Gw2uf4Up+gjym6FiHC2wBLfGSqSXHCX4Yos76BobT4NCVtgZTYL/OCMvYajuMkKEmV3miVVEqXgAufLnvE6pxOACz7mt35LnEHksLqVtadZ2EyT4DlBLF7KOgRHsttbm3eZOQnmYAxKs6x4MSmMYSKjLY1Gbp9f4sTxuGjO08RxRgwKXH/6j1vDQt5yzU2ezSjHcFMf0T1KBedb5ruV1byoQN+qcYk5RvJyHohwVGCxcW/gZ1k2Ls+yhLXi45EIj/L2H22ONDeoKFAh4BoV7KZFXMolBbnhzGLuAoD5bLNf0heGP0Qlr7KzBVsjomhyczYfSIBE6yw613zrahwT7XVMm2JclVi61FIP9apPsLezdk21OytotEkr//04fozLgd11CLb7Mv6kyNcy7ubLbDhThnNcYrW2g7wRFeBlt/IcRcD9W2R5I9aaHQ6fmlRYQmgVX+yEu48klqJnIJ6xxOhzhXoeAzs0LgdAed2JbBRwKn+nFP6hDGeQIW/rLiov4ju0qlN0GZU/PL29GEwunl7K6tNwjf/h/gBzufCSN/1kI2Dy7PhxQxhVTI3MlVkIfyFtrm3KXFvDhWL73nzJjouCF/yjAotZw5vYeS2KY/a7hVUgot6iRSXgG5fYYTzOViC+7rtl/2r6QjDcQ6bMso/ijDCfbbbgD8lqxb9sPHy18u67Jax+hooYuHjnCu3xgtYVodDC/pA/fEOFuGrZ71sj6Q/iNMRj6j0aJ7uwtO40Ar5pm8cxfLXFJG4Y7Hf7M/Z5nkozyHdlNgvxdJUKN4fNt61hw69FEDbs0TiwoaLuX4sNL9Kay0XafFniulr2oIL6IYWlkuOhDBVJHMhtmMfmkixPi2LbOfs/0FPzbuUI0/DVCpOAxKY+kPLROt2jrclqIT6+vENr9C0qEqLU+zHxCJUDB2vqT8O+tFHulNR8mvMQ+RdiuPb9US87A/npYmCA622rZUG407S8y7woU/AAz363wEacCsU7W+azOa4P4pPgH6zfA89v87MkJo8QANf5bNGS4QofqnV6mK+E/ZH9bn1b2yWh+Iyqh7z4AV7cCjBWzu94wT3R1dI9cSmG28Ew1q0cP8Z3WL9D9HEBdWMy0K0RbW2nfP3Nu7G5xHVIq26rkFO92+r2XquY39EhuSNZ7B9zXCi8QDQqsj3vn+TFOqqqhH8AQiy1EISez35LF2h9nSblHb97MJ+XFKy74KjzLidPeRxnKzyj3LxwRVsjwiibtJ8CKGktmKuuJq2+7UfZwEaa3dDsD6P4x2mG+xX/COeiJUHqwFHGmKZhrmD5JALmPwjse79rbhKfoqy+ieg5obhEa7wP+drxIIwOrGqGZltVum8JeWOKjwEbvs6hNix1Amhj8cNwE4/N5UCgRbHnoq3jolaWh2EiDpmTy6cGw56Fto6FzhGZqlU7db4RySwup3hkNYJp+KfXiN5INKU3TtjeSrBZvaG9c/x0VORleYHSNAhH8dhcNjYtiufLVUttS002gebdV89NiUXlsiWp60809WyjssdypUB2UYDS51iEwq1hj3/UqEYr+tDYQVVF8Z1/LgwQpQO7GOKZhm2YxnlEXJGdMSG6RcQMLbKIUGjD4ry2ZKspnSSiP1v3zWJ/FB6fsX12xl97/JSskehCPXzdxoUXbLn5LbL5NuMkLxI+E+bw1S4wTAwHs8UgMt3w1SacjA8is6st9qL7ZnGJhjbpE9+R/qM1HrFLowILG+MRZ1k8sql9GHOGSfph/rA8cvPPdYR+WfL66wKv6UuaK43z7+g/2+ECusZ8trhKobt2DL5EzpdZ9XBFrKxRmj4JnWRKtkbIs0P1k/IsJgcxr64+0cWc+Kyt9YO27cFalESjAjsfJtGFyWr3ygs+wIV+sbiyLlGRCQMavtoofmUp5swZvtrGjF2U/HwNn63G9w7dRHVaYam2wtyYRGkpDBYC2Zp1exStN1Fy63kL2mFxugGQVd1Ws+1z3mV9nXWWuiltIuMCXZKOkbncj+owbCtrY32z2T+bqHSeAYDiXVw24UKCplH+pvKYc1cqZRgHa9UbyLACFLvgfqvG/dYH989q3D/LcS8k6j6jh/IjqipUhHNignE6CD5TRBPJP7B1MfeUCm5epd8uAceMh+3d8Oj7hKKyLlCTl95302dQOW35yvrbuuFPkZD0nJj1BQ/3xMout3MX0O38v0twk6W3QOaxuTOkAsWeJ585T56uN3lB3jW6SXxjZ0eoHLhRU39bWfEkT/GUinjY73Z3j1B+cva7rQ8/hG9cYmsaC5BO6UfCBck3XywuiaIf/BUR/WIbLfMl40867HdzbFjinCQoXZG/uPMYV2TPDUd5dpPc1gVwUy4BsQnIJMi6MBUuDnNUZHNlVtZpdZrdCLdvw3cLXmmSquE+kLRqgsoplG6NcL14yuIwgUgDIpc4JFXtiW47goUhXeR1ESMhGwbzeamQJhql/FiJ6EYFtiMV01iz323jYk6FdySGz7a4LqpCEvTZldhiPMzzFMLXfLfRBrMYPNuOCrZGLBw/EkXnHdqkeYDHlnhsLvehWhTTSIlW1wPiwG6szXX+ilwo1ea0pPHFHCsOX22NNv/kNSXms8XJpJ9dSB0US3f7Btc378iHqtpcFlFWrhOasxSimQzGrxV9G7YKZHMgFt0i+TLbKw34/sf98ofWBG+AxiVLX70Qfkzu0Sch28OowGr9CK4G3bct27OC2AlGqJx3q72dgJIXL90KC1pxZY8KbQ1rYi/dwgDwn/cJHp000gAot9loW/HVsgK333KFC9g4vM+titnHEyto48xnqzkiclUwLLDf7We8MUeIPvBQ+VJ2hS83NyXitprum+VNPHD/buWvEFXx3UXyJ8fDzGeLGcDLiSaJG9O9/7r09nmUrzf0FQKVFiEFclCeD4r4TrhBFUstMKcoyvgcn/3H+bfsg7LM44Qa/sSAN1S0qmOTLPiKTcyM6amIb9PUFOLZOHgWHNAXViLbKpq7aowggLZgtNcLyCGWJWTue+Xd4cuouEXQYdyowywuy87+9hrkB3OWubhL6J9N/N8Vlq1VkZB314/IYm/86BWmSoPagoFyVKcBFPK/AVOgb8uTb7gGAnCNQZc9Oaeh3txM0zHsFSOrVekBRWgxD2AD073zqKetiNVz+nuEASYe6JzfRLd4FpvowyQlymv/DKfBbPNVZFNuM9djnJ405ZCFnHYOtR9jWncMq9urhMzni9Pyc52mv7+8idKSVzd1o/dmnndJSTXGq4PNJk2Ih2qb3Eezqajr8WzUQXeJgwzYSdWA51z1qANwk7KbnvtGS6y55Yk4pLMuPYcVQwy1ZOxwBmfZMCJzh32reaHvpB8ntGjmZoSu2fb/y+hWfTyBwCVpnwYYk4OIiNj39OFEUOPOBZltjGkxTcL4SCqrIdMjLI+gMPpt1CGfy1HzHD1ExeosT7Kq/JDgfuD952uJVt+T6q71lFTl9NJWFrN4CVUM+ELbkOcMjHEF4BN9h7dR/dSRIZzA6Q7hNmcXoU6IwwuH1JOPeGwhJQ6PexsZSD9+PQt1tlbiwxUlGSp4kN6Y237p/y67D23uInINnJZDPXLfs44oQcpNFFNTzQqdJEVZEU67jkrUgLx80V2SdNdurWXtj/Qobd597gA+RVlyg8rqMv+Bst9fvv3pzduXL+jTrSReL715+eJxnWblrzGdxijL8ooO/feXd1W1+fX165K2WL5aJ3GRl/lN9SrO16+jVf4a4/r59Zs3r9Fq/Zqv3qI1wvLTv3dYynI1yqrDXBp3Lr35JonHPPXbfyCBGTomOUc3L2T89NtrvuJvAE+Stn9/mRCS0uVMHyCjeR6bm1MChWgvX74gbEeuAHvWe61Ez15pNs1k91ER30XFf1tHj/+dxVcV4itJQm+zOK1X6DS7SDDaaNMhvSYXTZZdOy07lxpcUKGYvgjtjm7wzwkwzsukSsNQrIn4DYDoE6qiNpykDIZwlP8uEM5wtBMCiN254xxlWFAdlN+TFdnaPDA1GP6ZZ2HG2KD7XkSb9rkhSd/McV3c5Q+jOXAf5WFOlCDPddnnEGPEnCUOOhxybranOHurqZb60SNsqdtZ2Q9J/ZcvPkWPH1F2W939/vJvP/1kjXQcQGY6pcazgLWhSggQeL4z8NZhBtrnDDUrwUw76OKkg88jfdYp+RP1qvQzmdEhdoRphFdMfz3Fm83j7y//H1rp1xen/3kl0OOK+Jbkdbb6txd0Lf364s2L/9e6O+yDvsE79DeXDtHnvIaXZnneD9Ozn0nPPAVZ39OpOvk2WCedV7z5cm356JmsUq3cfeMyFy2NjuqUPCejkevW6L9myR81ukB580qfCrmtXniSRrena9z1ziNXif6Xn2zxn1epj4YYUM1nntRzRzKxitOs6SZY7RyVgAVrZ9edx3bU1+zl508O209Hz0kUrw55QAXstCRpjc/S+jbJPA5+p+VlXsdytvc4FvH+hc+EU40sYp4WtjHD/fKLNer+POqH2Hiu5ReVz2qeveflpECos/L7bDSX0ePxI1pvvOxRGEm7YTVReeB+ZSJEumxePhbdZjFQ/vHA47akfIRcnqbPhOEX34JDS9Y+hVIAY2sQ9ZDYV79kH3IS2HbrxecHaZo/vK9RWeH9+1teeSFz01ohm1BUkKtARLMVNHhIIpoqIfNqR+/jbBUIk/MZwUoGHGTlA391vrOSgAzIXgo0tbZEAnyu19eo+HJD1kbpw9QTH+l6T6/2Cud5MBD7drEdEw01vRjpdDNyjTE7ypmdlw42myK/99sIxilL5fLNzPxDs305IbNm02fGn0063KahmlrREoryJiGL3XYe+oQhShOZNcu1CXfDIpX5PITCe5IX66iyuSCS47qI0ip0Pw9W6yQ7ytdr5t7cz7+lDHImO7i5SdIEc7kf6fxPZO8QDV8eoZDLbwcJ3Z74uldsJjr0Kbvsx0Ifo7Iy22fe2CMPukOQnn7Mb5MslEqN8VEOw7LXAKVRH4HYLTvNQUAgUyBMRgh5Ytp1R8Rg3h/jbRkMLd3ZXZm6khodAUyZNBgycA92wkQue6MsjGNfGyrtoGV3Fb3WCEaPqCNvFjsYjbjqPj05YpzEvAjarqc3IZG9DYLsn8nmLC+rKIXueN0sWnd5hppjchB8J9FjQGwe+5/5oQbK07Cz0nMSzwVqZyzbrdXbYFkGufp4yJt3TU7LCRweLu8KhMzx/2yLHy8RVCQxh9vJ2tqkE7zMv0Ve2vOCjg9LGGvH+Uv+KmvfyV83sId/KB45vc0w9Y7uSKjZJBzCKibPhEGm0xQX3Juurwt0n0QQg/oev3fBG+wwzW+JTvhMWHTx62ez6CMzY4ZJ6Ja53tTaKb38G7trixbXEWt0c5HCn/MqNMohY4bnTrOdF9GqMDzVZr11EXm+nQ3otTvHMfEMSruzs2K2HQ1pwfd2psBdoMEaNJaBYPXD+C0pEwyNBXxyn6zad1rdeWMSpfjijj40EXalnWDo0DiDX3B1jNO+9+w31eE8oTocoU4Xeyk90jw6v16saKOHIAoIeZIwu72o14G0jyD4OmSXWMtMucF69i8Uyt7ecxBvS8zMxY86+BKJsvomikmYVIF3mAo2KZvf6zp04X2VAOfJCRs8Ld8nN9VRVHidNjsc/jv7OfqjTgr0pbpDxdkol6FrBgWKb1AStLfl9sKqJpNTJTFRGg5WK65Jr+6flu/yhyzNIz9jQIvDb2q+ZmmzfDt0XiP71F3ZfLkR8Dn5SrZIjh83SfOO47voSYbRyGTYIqTOBhShP3d/iMqLiCTnDzGrY0wOl6BcfZ9bUDww4oJ2cFsgxGp9LuMaIbpEj6F8pM5RXBeF5w1Qj+ToKU5RIzb85B2L7wwVSe65THuMdPOnaL0W1im9OetfcPGRZaEikLCQpfnMorTD1ljk+1M4ipN1lJJUX/hXSXN2vfk7Ps+SEFa8TTp0PYiD3Wl5XHqRkMn24sckWNUhRsvsHi8xjKy5kPI8VlV5/OMfddSaBjwkeXOaovgO7qME101SBqeHORzso9PulWTBxvsxf2jG2nq1+U0D1v6Tmyd6Aj/Ji65/hwgfqHzQHkbxD5pWiWTm8/QPJYc7gu+0oSE+XPTHUi+Vgm5feGaSdb0OMTENvugxFD46cLRqUSUovCqK2ZwAH9ZPh3VV5bLgbNMlQ6C/J+VdmpSVP8J2LacI8yUWzCNriZP9FevbFFUSe1lxRgiCbx1f0tW0DbTHjCNyGzdVGxcbjCdKnQdidHHCtNFfolwm6xDXHyzu9lIlEObOSHWcVagovXmxlV4jrGhiBmol3Kxt4vPCZYKatesl8/HmicrqoKqK5Lqu0FG+vk4yeuKZlFlx/7snBMr2CQGfUXxHye3ddMt3fEwJjv57spoQ+4dpadPvSqFlTo84rMAJddcQxstk4kCdbYlVBEee3KPiicyqvellXNvH8NLppV+zhL8BNejHuLZPPw6jErXbq7ehoMf1CUVlXSDSO6WqbJ/7q2/iYM16joTeJvpmyI9xUw4WycM6W6WoySoLmMV8rwIa9GeoOK3QOoSZZoSQkCEkvou7vLH8YKk9gSNmt7s/E88LrT+CS2axjkb+dvGvJZnWGA/O80a+f65KwBZcceiacpcgO5zYpL3jKo/yepNnbDiB00lewBLKl7abJHrxTHdBP0Yd8JCt28Kubh4YtM/mrUVKfJZsERtxS2D/mMO8whpYcO8q8kRJ6IXSsV0YF6u9I9PIUTHMnc1ZQl1THJIjdRV9FHzi53aR/Il8RjBy6yov8wt8fIwrHrPbMyoNji/jW4RQmXeoDn8eZbcam70DhwT0Rgxrk9pCn6+dsFmEMtBss+3jJqrT6luCHj65RYSb+783ouuZKEPtaA6TLBrS42KqXdMPbjsXnkCCRyOW7Fc/ykna9UynZf3s4nL4GT34rODT8rKIsjLh/YwMtsJ+HVwxSLzeslCvLO8u6YPJbGNJntmSAoM/TJSirqJX3N50Otk2RHl26kR72l8/nySR3cgcTPd9Td+Z40l7Xqco8MOHFxs0uYGqTdABR3nb7jqdO18IZOeorLDeTnVPNke8FKuZ4atDeib1KHeaKgZx9ETYofHJC428o7DkoOSJvVXyvSh8/FgVEXmzdUq9kr2AeyYiTWsQ+8VeCzzK07z4gB7Bt0N8kbebV/OwTOD7vYk3xnbtNxdS5DbqmfDQwtpUe8Hn2gmuuldXAjkyx1PeLssvu+YIWTY0bk0QsZykmM17ly8vi9KHZIUu7+r1dcbkWHRB1MaPL2/dembWJ3eR3DNIwy/PREIP43OVj01dL+HYk9YzEKBDQ9ULP1ynJRaqzX2CzQKyZa9ndju78H4vuRczSQ3W1/R7qqE8wWKuHoJ15xe9thzIBqnvuTAEF7IUte/DuPZfhhufIRtO4qoS3FOBofveVyOsr8bev0Lbu93zr9i7H/y1DoA01O8miSkh+xPGM9miFtaUYNo2MsEh/4gSm98BlQjC5tzvGXPQuGd1V+f+3ulT6mQqgj6TBQAPMRTvbc0LkoswyjNhkZ2ZhVaoXEa3z5jylgcoW+J9i4okysD472dC1AnyHMJJBufJneh5RJsypt89St4Eu3OQvFE6AucY+WcbLHtQlslthldgdzifINvOPgacs1/6P/258AlnuFX+z3WYN/eCpQmjZ5ovdfXlhqKkg5ziCRqWH57JHjqFa5TCrBnGd2mL/KKgpd4GgUx31cqrds+EF30FXPd/T5erTxH16Bwk4BU7y17BDXxbzr0OdcQmeS/wJyYPp3dS2CZZs8+exZw+sqrIU4LJ705Gukxn4JO3wSNOntsSniQAO6DZwuvCzVdMN67Cz2OiJUN0loIgrWSFIeX4chxr9pR0mhcXf9RRgcrz2+vQ/WyOrqt/4WliU5OHT4NHD+EzNOTo6zbJNhOEpfVbjth32pD/TvsxyX4EekLK/pBnHq7SPRfwPORqN5z3ddI3VGfJHzVKKMqbBOlePbG9gC77hw6+Fl6O3gAav5dpW3whg8KJHoqavFyhPO7BSHAnZMePuG9lKG+gfTD5MsHkffbeZyKSlvasUIZNmjnsyENcTRyqR7VDWKN9xhIy+bQxS2NBUj6jWL7n9KYxjSMLg4rkjguDKYg74Hamd/wrvfy8HS8CAzfqf02/bGNxTfTIIovSg7q6IyKy8WY6RzEm2DMR4d2m7L6de4rw4zUTFuut9ZPZOmUOeAHRtmaFwNi/EN66zH+gMCuEojuIY1SW4ZDiP+/xqbnwyhxjvOhO8qJen5GnZp7HCrvMN0lsv7zaan7Bj0svbqOnFc3O0GcHqxXeO8Nnpd21IAS6Pih3PJMFQgdkz6JttR1fIGQe/U3MbSJVtVrk4IHyuZHEXo97fvN9GfxjVFakF55W+BaLZModsdHkTp4nod2UQM9J+Lwv8nrjKIHausGjOvyfzgh8+Prc7jpeazmEQCFrD1Kq9mJlEj+83RRPdFk+Exm1E+LhubFbQCueMec2xHseTEvHAofouFk2CD71bf5yF2KLnR/azLjt2dghXxdX3++GsU386twbAYHPJSGteYHbqvmeOA4rBK428W5AVE0O38BJnTvuPKqLAmXxE/RuliPiBuE5FjKGl69/d16Vl9Fjuyv5n7C/RZJ4Q3dhhg/tFV4L6WkWp7irk/nyjRo7fpynsUvSWJ/IfKYRjhqdZ6StbJhnhG1js44MN2SxWO0bG4kxLPgTsjdE6QlCU9NU3vLUBJa3PDW1W/xhkrJTPpmcEX1SHJu3QkXHZE1gTb3G2s5q4ncSztFDVKzOcrzBld9RgTBr+bmOHN2h+EdeD+7VoU+NQgPBgmI7JUDio2TrZHJzk6SJdyK8XuvfBBkj9aEhxxjynkWBsBw5wvM/1lOcph1jIbXDTATpUjDFVBifZ6rD8gdayUjn3dOj+/u3wZAdP26Sgp6cPuXZkOchIN7/QlGYsbN8+S7Bwq16h66HB9bd4kh6NAcx3Q8+5Okq0FyJyAMyAoP8MMp+BDtKcXiDLTEW7+lRaJTtszuh0Z5eR4E2pFZCU6Wg9f8LsyZqrOwVyZ/Ny87Ebz6Kx0ntJkEfjN1kDZyjkonR95RGG5JHJTxxRMQBe43Pnb1OFL7rZzWpW6LQ5tSzKAnlydudFJvjTBiatijJWQUvwk3dmAwnsXVNnS11ey802OPCOVpHScZksnTIh/QhIpFS7eH2c171+f+83LvjGG2qy7sE9zTCn6m/6IcoW325t1FyrR8k/FriQ8OHBPPBs3mKYfEXCWlV+9bban6eXu6r0Jh13ic39BTxDFmnG5r95A01vebva4lW35PqzpGFuOreXRm9VhfcjjMnsz4TBu30JGaWnR4wkuHxuYnsSO1/CzWx/fC07LpKs+xFnrkfOmT4zLcJeBI5x4PdkKDjYCpgjzFcMMoFyojCHqqHDbpw3fuEypLJNO6d4aqbEar0edqcZxB+/cJ+JtKvH09QB5kF1bWzZWPlQwSYk+SWNMh86nvMvqHJry3nGM0sI5n6mrU7LzX79dQkG7c2Ne0muwsMfwfYJb7xDuA+LTtUQRSjj5jFsyFdkNdb5kTqf582Nzd909PxuXSpaD8iEZ5heNRu28c6ynPJKLPgBk2pqGMHU+lFXfTy7upl25VH1mz6vKw8i7szN0T18oqlGA6jNMqG9D5O6ls5ubtOyENY2FsG1v5x5Wltu7Ixnpi/L3SXbOjd7PNYeQtK8ssiin8k2W3Ay0XqTDetUkJvCFGoK8zuoYxA6ObYhboF8IysGP2QnAJHmpoB7qdEu/Hk1gML3aOqi4xklEfPJkFKgDisQBO3uP4Twu50jqIyz07youGVMEp6y3GInn8NzvsuSE19G6wCmLgEc57v7EQ3N+TgEwbdwWqdZBIXMz6hmXVam5GgCBFuti1uLBYbZE59iI6i4lltkv7S8iwqWsXBy/LU2IXcrlnZuj5Xq+wk+1+v/u/2rq03blxJ/5XBPC4WJ5tZHGCxyFnAdpyJgWTisZ0Mdl8EpZtuC1FLvZI6iQ+w/30p6sZL8SpSt+RlJm4Wi1XFT7wWq2Yf/2e+9gj3CgN/naiog+D7C7obZvZc3TAnvKDZyDgHXZ1bZnoFNqZLzO1EtrI1ffsR++B5Uz7E36+/I0pTFzaYyRXuzkNePI90XJkuf5W1pWwzSrp/mltKXCQo5zBpiizChtFyGTJ+pvbx+wVaHHXszkX9gqx1KN/WVQuvnf3XI3Lw7pu9yMs3VuuNwOHqeZciNju4Uw/UbG5RkeRypwKzib8+wSfcRt3GmaYeCDRTgwf9wmMfWzGypEri1PHGhq29+CcNxOL4p3f5YSNfGqURsAg16EGBwbojEJu+cV0iJOtfNwLL5lFjm4xDuYh96bCI1a6MXSJIXmc1scVYatzF2xltsCbv0FeUjo1AlxeVqbeIEcc6RZHXNwAnk/D8vzmE5w84Ppq9kz4gX3kYMVJRUaDCF79ZziqNkjkW9b1Ttht3EttkmHwbl0KsE25T78mliMQNpl/zb2QMolXy+j5k9rULlDnCeqMzOpD4FIue24J4nXdD9kaAOf4q802RH91hyNYemcjDXQy67rgAvIHSgHhM41PeoXjkzUa7h798bkLSeGLWv2Fcuvt5H4puI6OAc7RoP0GrPZwIBbtAut89of05RQ9x+WUjva3dif7dYSd6gb8H9c7j7y6JwfLs+vuphhjg8cZvya3Zk7MLganJbFHj4/+Y9v/D0+7doPU/8FRwd86itvqoVOQYW6cP2XVRjBvEW5Fc85nLNHLYLNbpW8iRt6ssPQPyr+tstDSYhX9ZXjpa5kzyUnrYXxKBaNh4+ypvyrfJfo9GRazCfx7qUeMWFTtqPeHgYddxkpzUjNb2Lv/2CRX08Fbk3752v0iG/iYeWz1y+DrPTTeVUbdRcNy2puERxJ+h22rc5amLywZTe9TC6wav3NIQq6aPxU9ATQio+/R88M7Ux12vS+Rv8/BZdf8mu615XfrAGlahyb7mGxSYsXeeTCC3cWcb1sdZxmB7eEJH9CkukprVRpBGdLLpTqMclZYDnAlPECH8tZY113BgIZw3ApIgExZw/TZ+EixT6+twgEvt3AZdN47F8Fs656q37cO7/JDfJrs6tPYyfLnfVsf0Mt9T89e4+9XmBrJ7HP4Hqr7lxRfffXNbJMe4eCafTpcezeUBEMRl5GMkwvL6O9YyOyASi3usfDAzCzHNne9b7j/KSOhwraPK7sfytndvDpnfrx0u3uU1AwujmPubvMmLI+4yKhy6J/bOOWSBz/P8OU3Kpzl8+L1efAETtM8g96/zOrD9dbbHnTl2CrRbg72PydPUjQxASz+FCLaevox3X24yzH/3ZYvOQR6ek8/7aHl2L6QpLv3fx9n5MSZL7eIBHfGYvZkjpyDDwaekTkQiZkkbzTjwo7fute3PPt5uH7fD3s8u3m4X36GUWLXp6Y30cD9dv/SyWvhtDJfQw3CRl+U9StOfPeinB80HRzo19lbMTuskz16njPll/KpHEZXdMqiYcZ/9eUZntCfJSS6qKt49behhNqWb/QaDqTzOsxurFR9QfeRF96xb9C/NfOpyFfAmcfEmaWqN8XGjo9JjXT4nWVw8Ox32a79IlyeS7/EWEHb0tGLs8iVu5Pu7LZK8GBnTq37m4d3nuGZqcChv7xecexf1IQ8h6B06pc920lqwDSHxlZDNeizHy93ON0uTNzwuI3R9L+rnVtTnUf89HhYeimRklBHMxMu71WYJs3NMksrWHjfdo2xfH/nFadp3mkcPSVrSjcwTYGo8dpr9u/01ZrvN1K8NWN6mLhne5b3NC5m/udnNW4l7wVJZw0VnWWojW7gwbrxu7svU/DMB1X6NHuNzWuHBjSAQ1wrw3V3Fx1OcHLZydwR9Fo6uk/Ck58bMaKab/lbb+erf/JKoeSbyox0su2zM8MKtmQSbN6RiRPexcUsWv4zz4WGvWC9N9XH4WjuJfIajrJfA6YadsQdev3nk9e+WvIwHkj/Qt/Idqj/cDXo8wMp5DYwiWYwaPUb9VqaCcM3WImp9Ndh3mCPXT+MHAb/7QcAdxbfZfvPnZPoexeW5QG2qq418H7r51iUAXdjwdnc1LkK7m4a6a2wx9Bp/Llm5oWH2J4wmhdHN8YQ3/7jNx2Qzb8SCYOhNntZZgIOwxqavWfrwkvXBZ/yDpC/JaYwID/EXNKZ+4wn+IRu3kscofpOgdF//5f8VVNfpV3n2mBzORQxdvTu+P0rPx6xzI/fB8Q6V57S6yR6Faxu3hGhNfCIsXR2hyH7ZxtcP8Q7o/jnb/QCe+CbWHiwRXT43XAaL/+svN+VHsvH5z18ecN+73Frk52KHwFfa1uI1vNTi0R+uw/Mn1WuEseZ8KcprqipQdfTERF4yfq/C6Pqbu65A1fFrRNLE6LCxgBGJnW5GRfRpeNxXha8RvWF4meeyCxCjcRz3UeAHDNff6+Xpa3RK8y3l7WjX205vXx6V3k/zLZA9rBtvSvI6cTeGR3Ou9D/DAtQt30cHuPHraaPLUZcH4CZ3ow58DeII2AcSqKrTQxFn5TEhYRHHWxXiOMrZC39VzTGB7cMBcw8Ro0sjF/MS9kZRfF1F93FZUwM2+YreU8/GHW/dre7tLeean0chcx+F1P9qNfcNZnMveuvRuMi/JtgqIf30b8p2hGohOuYK1sMhz3y7eBA3GC++Vsf4z3oo9XUg02GjOeqhfc+XdCrz4fGxRKPcwMht/BgGl3G1e7pP/jlqJr/FHyGJZbUID4U67CmJFG63BHDzrsWr3gvMbuzNbIri7GyxfjZ/pYWKdrnWRNqkw4K6TLg8v0icgcF6dLtAHf2sDTZsuZMTWXiJZ9DrZCcOVz3IkWqdsBoP0c2Dtqv623LLy8oyMu70pkGn/gZatJzseAYjk+8Nqlh2c18zTPCsBkRdUi+Hvu1YmPZq25RTrzJtuX0uY3uSFt9OgqFmiJ58nZRk8usCS7h0ZcfD+ANt23LqS6YxO0tSVcd9lbT8lnAaqobszVv3Z+m2ndk2tda+pMW3PqFta4boyZZ7+7+H2OlyUt43KnLcmNtaaVpTSgXo5HeSoakccs4cuxa2nThHr4EXMHsuf817m6fpp7yOCDlrbgGTDOMjPzKs6EVWfnMJqEbXDdEJtZtvl696q/Zv9XtIKjG2qaMXUcPQJIefUaAE3Ak3FeLzbhp6aTc1Q4DjMs0PPwo4fPVlbbPbvHR47DzUDLg6ukNfE/TtLUpPj+c0c9yIrqJjGYWdFzdd9VGi/BWXrcVDHBzSgm69N+eKiOpv7mj6ydtwUzvYDzc7Tt4CDTL/G5UP2IqpB1Z/5JacZFi/KMt8l5Ce7a5RSIDyxtnrDpXELy3qshJx4L/O9r/Uy9chbVEn0T1KH/82/Pj+nFbJKU12WIR//PryV/6T+ZA1GU1/uSD3XvVpRrmL96I5sBp7qQyA5Kw8IAEr278ITeLPGBXN8/qrPCurIsbmFr/5JNslpzjl7cERGg4PtaY9S77kNTqhrL6SV+lt0i6da0psv2+G6wGdPV69oEBlgLXknyTmJJFtRUCjxRZRxpZuA2KMTqvAl3DLRe+5y+ge+FSobuZrM70sFk4CPeUdpko+ljAIIAWTTABM8ztdSftml7gLAOtDXBwQv0kcgCEFgqrjf0CQWgNkboBqTkqnAmeepuuYnGtJWZCRH1Y/BRM11jHr9geqkSi0bU8FREkjoyBB93OYOdK0Fz2gpVXEaBbE5LPhhfNOwVsYvJXZVah10kn0KzWWA9OjfNEk6IJ9jeRi9RRBMMeZYAL0GfhaSRo2ca5aCCZ1CzKg1yX9/EOg0AYFs8FP7qU3Fe6quELEYzvboQj2UlwUxmh5WWyxJavHFKOOBZZmg1LnoucRRP/2t7+9FHpu4NQ5XtKc+t/WDgDQq3ThXa8A7fhveHFgsP9EJ4QEI9xswOhdn/qnILqldVcDPFOaaJLhHbshUQKPM53CE6BK6cYuaVLtfjcTsjQLZIsBYrO4sunjGWAlf94wNaouk7R+qwk/7XDClGb6shr31osGo7ZY48+PBhIYKKsiWImFTl6t0KAofdlmJq9OI5vJazZcdW6B67jg6KRlZBh+XP1FR6+KSVvzX3a0T2ISkuY6av8vv/Noy5lLh+63aW4+GIFZQbiiMDcgkIXCIInTx6TFlnYxcAKfzAmdCfXijwInyELLgdPgUzvPiql72elxXNItnLs3u8xCp/9x7WMK/CRZ1v0zjyb9e9SLEzZ5namkFd/gTrWry/Tj8OMkg4vwDhySJTC2epUnAJf63bukTfXb6NlhprsmtRkuNgwzqy6fA2aK+AizwaydXlc1lkFLNqFsMyOZzfJsiQNZjzDNMDb/Qnx+fE24FHeBlzLuxKTo6v5xh/73nBSofhwrP9Je0thFCQyKw5RvZgyjtbIZx+Y+RIhwzydfUfH8UIdEl/YtTcR0KlNgtQe0GA194UKqahhsWM1rlGxzY+LynO1TVMczuKiqIvl8rlATvDQaSnSTHEUJdDBdOuUJlFQztZACccipUWbjoBiV62oiw1B7OdBtsbqaw1HXD2Z96zI3nDPduSCYeQWYdrb8iRJ1owvBR38OIglOuayjLU5oCFkbOtjiNbI511oMrlYzrc0IqukHK7t7n5mHqjqT/GNM7p6KCa/+6GYZdmzB2q8AGW2M4LAMpwIGFXIlxnZo2EFHKhJYHgRq1v3vZwSybpausCjsrWaGWwDYpp/p7Ie3ZSzM709olzwmO1LUH3WsB2yw/JBcMsqNAFCi3hqgCIv+4VT/GZnoRT/L0+PBDAihnv4qdDWQsiMM8xTQHUJj3wmrlDVpH2aw0MHVXNvQwPkhx+bRYJt9wFZpMDfmqewL+liBS1lFDDKDvthU6UZWC5RKFiuEGSOpAeAycy6S9CnQmT8CxEw7fE6UwUlrpgXap7hI4qzqx9ar/Pg5yQjh7A4iCtkgaCnJt+RWolLURIoleZyo8LeavfnigTr9vDsWo3Nv1Q3g+ec5JkHzP2aJHKMMEY0FtmCTw6PcQIuGHi320vC33jHRBJKbHf3WPOR1kNMfSQqEQJdPfQy5WDROeuzoAZaLOWvklfgUp+cepGoNw+BiWuQSdU3EbAlDYtgJT2Gg3GhrgWeewdywnn05OeFzjJkWhqtb/UX38fGUotf5tyzNYz4/K3UG0xEw5y/9jwtHA6ze/EhgjT8bFh4SVGD96njP8izMlFuxS6YXgokgs1gvPSML9esm0rgM+pg0Rku3AFgtf0s5D4gm3Dba4WfujWKX83gdAfE6aRkZhh9XHxCvV8WkrdkD4vUhW61y7S0qUqdugp0wTdkkIa0gtWymufkjwq43V94SQTfVomo08OoK84Hv+nuFiixOL87VU82xcWLikjcuesRTacDIpSZc/QioVM8GkLNh8U1enI8khrFv4MkPEvo2GU7Ur6vHxaDLekDwkJ+S3dQoII2KMGh/3gYOGmXWA4SI/Pf3Ij+fpCigSITOa3+eZCIiDYoiBIKOzDABwWPU0CDXEoYQQG77HguJlxkGHfO+nHbEIeQLWHzIxB7TdSEhNPnqxbJfJ12/ELFmA9GHYh8kz49q7ULaZJi0v6w9vU+jhklDrMFn7v1VbJqnBc2Uy1xz1My+wu1ibH4s4wN6m2BpiucIDg660FiqtOSgPCzBZqKpMmqZtDt7OFUQa8C3Yj9G/AAQMx9T5sIXkXDeiY/ctS4ZUb2UogQBL1knw86gyJoAs3y3jnlgM6Fbhx1w5nbr+D15rK7iYh/dnovdU1yi/V9J9STRwb0bNf6HnRQMs+HHcCPJVHGXe12MMAF2xewQYdY6sEKuXRporIEkB+WZYNFjhQBPaLNe93QVl4W1j/SnsNDV0JKgNtkayRlnTI/Ou2z6I6/Q8tfZtZSiBM2v68bQoMjy19l36BtG+22OGZTd4LSK80lAcEYcsHz1Z5eQVqs4yYRw5nUS1CzHlwOXyYYhV6ww3TKf3+H9U3Kqk1EteibrhGQD+vU/rhtAvR7Ln8Y6UcmJESy3a68FRo5w4MAWhAmoaNOxnkBkfCzRV5j3krYW4+T3jl4zRf28pv+VM/qMq5XqXGR1RkQUwNc40HqYEplb2jAlG1gD0/qsYvXbP+CZflSxwub6xhYr4HHWn3NtmxNBruKiolL9hUxLqYEJLxG3JOELt5M+UtDNpM0FpIsUILSKWWoJMJtyrnJC1+zTlYCt5d/BLwFYE97IO+Fq7ov5qye0+5Kf+ZBnws/yEUygZIYysXSat82gWmrRQgY109gzDCAlGhoNd3zVGbd9u3OBNT7cxs/k6PEmS2q+nk4gVafTbMPc/o0vXPexoqCPUZtUTywGH91FhlojX/0c7OAAVEopWtgbEjeA+AWlzYUJX3c2fNYw+Ip74l1+iKh/1x0pP2ng6JgTB75sEkBSrcqkCXVuobJZGNzRSpk0x4m4CKitYuc5H6qm3G/awmn2raZ//ISLAclDZxuQWQ1UyDPf+/PnclckTarJicN/0G2Lz6nZ0tXDQtRpFSDB+n2NK/QelbUDZ/SmyI/ToYRtnDsNY4tWjw9OIZMW6c5YCkAe8p/wWAg8hq6Yb1X7+Jik+BcUTRSaoW+QZTT8uvb72UEVo93NzH4fF7uUC2xYa6EdGQjRzBE2e9G53U06SfhC0UyB4NTrY7MaqevOd5lW5UUdnDw5xsXz9ffdU5wd0B3+Iq7OBW5i96yAV0vAQqv70XyUISKwN2LNL4EwAekVBg+NHiYNKTpgGdAgf/zExAyYYCw/Gxgu492XmwzLsvsSdJMbZPaRCM+IJKVZ/WJXptkqdswy3C3f52N5oJvQA2QM5uZ2BPnzjM5of32Mk/SiquLdE7lsf5Moltr2qaGCQA6UnEtgBlKsPuMUrJfRsU8y4+qbEjtqhN+pg6cxRExweKZgkgGOEl6GsUDIkpsqOLqMmqPlWwK2qGFMqsq4jv0hBjRbGMw2plE1Z4PfzfGUFxWW7REPsNH97gntzyl6iMsv8oePNBGz92MKzHeRjAwMR64kzDtGqc5h8MLqZNJgK2GSHWoZZ8zhMj9UGBm4tCvbgwqr0+qgghtK88YHFtRhfL8Gy/XDig8IRBeGWTxZ970XsFF6GW4CH+dcmd/mafoprzDe2yuXuqMGpuTqvj/8wr9XNRgf8oivpz0Xa+vC6ca6MotbXL595gBEKDR4hTfqfKvTYAKYqS1v1eYc+Kp/uMjKb4qjVIqE79Xu50lGsVEY83WWJTHXgrA1iDhrDtmr/EhmSsMBjKoy9dhFN82nke1/39CIJTW1VXMTwwhOhOuaCThgNmJLJHkal6zyBE+Mn062+S5z0vxgORxRVaYejuimmUsb+vcNDUdSU1s1NzGM6n+LyZW4XhQyTA0/TnMVaI8kT8MRbJ5l4KeTbUZnW3LReIe+JujbW5SeHs9pVkdeMd3rSepPvueTyQFcfgNEGxrCzHrEqu05ccgU6FwdWippn8+GKL/eC5AxFggmpvIykOU0rM06lpmDeTuj1oqGqhU4YTnCaX0OV/YYmtbN6hrXqZ7rjwrXQEXnXpjv0ZukKKvXcRV/jkvxHqeudY+q/hEOyU3b/Ex1Zvt7fUl1jP/x6/5zjvs6/pwOVYQBh2Mcf7+KK3QgYSNE9nQp2AhNoGkK/6s+SASa6UugJvpCDft3+S5Ok3+ifdfjQEMADdQkQKZrPM4OZ/JETGyzLwKb6ktN1EP3VUHOYsv8XOzA1kAyqZICpUaKW1Qck7LEGO8OuQUJRBKodZFK0zL7dkdolS2GWmQpdHrmaQrpRn4G9SElBly7CwuQd1coa6ErN7RVvwyRmqunUFmsJzJsVtGeuiFtC/1TPqGBvgTi3xfqFKj91sCBsC8Bxe8KdQNgG+f0PaqecujT4QnA4ZCj0bVZ4eEZD2Nf8XQKfTdcOdgiS6JpcDhhEtoaiqBmhlLdV9QtpMRPqCsBv5+uUMN+yMgr8B+KoAaGUh3M5BOuerY1nmpvk111LqD+7ktAE3WFZj2gaIUjUPRH1BJF72OCa+P+qSNNJwU6wgMcSKXqNYZQJwJKk6+oeH5IjpD2bDHYKENhZm06hrDM4DSNwuY0mW3jfTjAN0lawROZtoqRaEItM0kVH5dAoYJlR2WMy7bi+zg7P8YE0grjsFQqOWhKY1k0QuhbZynMNL8/oV3ymOzIFoiK9imzgYxeZQ24jrFd4Oof2rdH4uSoJAfnSmUNJ+mM5bKRyLRPH2Jov0YXKnqLlJu18ykukjgbYo1e5cfPSRZL+sWkkkIuZT2NvH+eY/LLxyyBph22GJKBpXCzjrlJNFNv83/774ivKBfITBJrXPJ6toF7Tc3SkltgpK2hWxj0L9/ERUFfBC4I+lLdeU2CitsiAdfyVBl4VjMUaxoZnFaENoYiqIm6VMv9+juezrM4vThXT/WJWjM0Sc8T1OSQFOoaGulIgC3JBoYqg9olxWVktIkhtLJTPbpQ0ZDZCR8hljWi5N9SmPD/vcjPJ1kjbaGipZZC01Ibv1lopP0d4t8WGW4p2Iy50j0FS6baVLCUGingvL2CFDAZJAVMaSiFomV1a2bdKBleqDJpdxrtW6istXAjTZm0kaZY0wiYnVJoDqSCGgYJDc6UJFvgoUh2jmS02WUT30lbkXcaS6E1KZMVCzAmUw6bkSHRqscnoQBU5ElgNXkq3TGQmBhBPA8SacCDIZHMtnHZCkpGaCSG2apJGsYc6H0JJYwDCbGlOAZymAmgP96mgx6LR9x0KXjMTROYN9XEEFc111BommyItLdYkGZSjUw0AaK8wssQlkaxGmEJtRsSNkQksAVhCVQrR45U14dDPEKx94YysN+GYt34yLwrFcdGphgcFxkKLSxT6UaAKoOhmBou8T8W8kaoMqgRqli3jkIZwpst1eAukoDrKoFKt0XEPBDZv34Gr0q5cnCryJJo75hy8Bag/R2+U8oN7hmGAGritNQXwReKXamJ6P2pB6xBXyxVxPTYRBr1SGhYSgnenMmILU6JH9DxlMJDCUymOzUeKA1vwxQSiCSq2zHjlrtjSnnDAoXqtNO02TtUk+3l15g8Aby2YGl0Ri7yssTMU3mrIgloZIFKZ+Rm7SO98+bKQQOzJNoTWjAwCnBUC9LBZ7Ygqbkg6ua1jeqP1JggSOIRGlMMHpkxFNov9niKkwM0bg1F8BfalepGpmYFpBqUeApwPOKJDM4936GqQoVmeJYRys5EIVqtCeISj6N/oeTwBPUpVw6rz5CYNfg6weAuYbVFEkWzFJWmZS4mjdAsVw61yZHoZv3nbKeY9OlScM6nCbSH3XxsC+CAmyeBD7V5KqOW5VblyuVtmlqVd+nTeOypyU18BqOa1Pzul3Gckrt6Sej0vlh3qMRLdOKzbeBq1mor92gTKFSecy0R0jfcHU0r/CREEtUZd3RxOqUJ2j/kLX1iIYV8OSJQmMnQkusl6FyUDO65Da+7o4HOGJS9i6WZd6u5lysTKd/8XleIYSHaRCCROauyVAZTb/8iFJxv+1LZJNsTGHgoyptiSmV+iqZNyV+KybAGkCogB1DbSKQTw6BtoUHqGYTaeT0aXN+pOgo39qEC/2qDygXG+eFjEeQ+9mxNhX99w8XEX/4Fq76paei3Bnq7wNTBjAK9qRgsonwmYW8OYY6nx7Eyum/NLlrGrKJcVdnLBqKp7rWCkhM0toNclS8UvJvyIS4OqHIwZVtRbgCpwioFl2lCPI0pv0eWIMQnSL9EaVSGXpq4qdY8J4kajrByNMlIIYUa7FOYvp7kkYu9iuzyPOrW56hd1CfK8cS8slxJ+MEHUVT9jEPBhdu4AMxkz1GCGFA+iphXVowkgLIS9ZZiMvqxTNTzBcwDEgYwBfQAqDGB8l2PvertHlSlNE/iX11uP03qyZ5/uavImU6uKEvovZcmVL3fWPZHDYrBU06sXzWAKwal4pKzFIZBUEPIB0E5sZd+XIIZLpO0jo7cc1YYgSMNZwIjDI1QugsaMrCWay3QhvwEuBe/DAPZM157M3RPNZVLY5EoxPKYf25Kakqfkjosk5mXjFH/ohFYLcOUiiUw+3yyWf/CLzDZeuDry6Y6V+Rd/e4wVq8+HAFEVAOSfzHq948AFf0u0Pjvcf6svvmsZY+B7dVUHeUrZnmTanKl+HfWRCnZG2qwJmgWsTCseeRzv0k1T32+MPN0lzBW2OErhUQONPYIZSENY4MavpL/IXUmswBP78H1o7pCSJwAMQYYJqqgAc6TbcRGB5BOtSydQhkgWkGjhSIKgSuu3NWWvvyP6HAFUmsYVdeqKAZZoJWVx01Q85LETIBZ6+IeeDBwaxL9ak5aJdiyzrUDvJjFyiAbNEW/lB1WB1JLiLQh1jKSoB60ITyuZHjV9HgQSIOhYSITMOFGFLsekM7/zgcKZEIqKwOUOPc8F2yFbkIKAXkdz2pBqJAyAsuDmEn/kYDkwT6UeUwiCUyjN46mYjAzqYPN0NwMI8g43JUpguVIIv2AN2kObBQ3MXq7mBnEgCsbeEjBWxJAyDda1Y3bQljJbWJTLfQLED1HlS5Ocupwx6yCfyxz0kqVBjGGwklJTq1VSqINoMYyTKIIWGV6WGDMYoJzBINgX7RFbcJ1BTGxfhI3qR3sE12bOdkIaE42ZVjIDQQFayOmUAVhW6uJHWA6PTZNrBXeRMrlpHFdrfJKrc3WjYs0I4nqEkmbNTapms8kRjHhy0TGUTGHo924L4QMB8rJR8Ow9wDRfXw8pWiIiChXnKNULF24uIzNskUSc3FClfuQjBHruC6qLKHUewS5O+ELoSZJdXkUyTHqK+Yukcj/bBVe1S5uptJlSiSSi+zuMsVH9yQ1hx/9eQaaPt1RV9BDfIS7nO4j8fyeRKKpgf/o5E9w5jKRKnir0t/SrGIINJkEtCXcrALT2puuD0+rtBNAFcIoQhxdUpX61Y+6JAauXl+OLJjCTETfQWM4Uq+jyhEdVFeiL02jEZkJ3TuIDIbkFWuLFf32bMtS2a0NzWhB5+lN8iXSbFVfLEXnUfSJv1sSX9fg2QBIJxfc9c0AE1Wa1IKDRrsqqhqbOIoQw1I49aAg19HgXif344MrKHZvo/34oJDaDBdliGxPpmntbmiXhnp0vy7CHH3YbrkNeBK/igshx4d6njY9g/yKraxI5H8rG17VLtB7dIv3Z09xifZ/JdUT1YKouK6KN3WYunwoe1JVGqbe3RDMdzvwl5sBruBJEbCm9Is3yhHgyTQf6X43tg9by++4MJd5+hQDmgGRIgkwINLpEYZ6YOYDexWBZAbKpZCSPsTCSJG8gTAxycbgxyza70JfyS865jFNlydC/k1wFH6V5jNp3HdhIjy97qDTYEQDX7mWLKEnwcGawvyqTNnhuhHqQm5ot3w84Zr2fEzyEc2AB1KGGeqApCrtl6zKlTLigNugs6W0/vs7dFwAPveL5smSily7I/DyREmW9ab9+jWZbDwYSPVlyIlDfByzm0KxYZTS+t83Tm0GOFdQBGQyAkYO07oKvMiSLzXA0eVTUvMSPUYMMyO5zDdsjqHoJkuqJE4Va0lVBd/rSDiTUjv1aLIjjTdGt1YWm9LbRVo3kLpKTvAi3Cy9lUOUqyGpUyQkeBItpyJXTOVwAqpmSldnlZLxkfHwbBLV1AXShZi1plFbp25wNXn1/KglpAPTXyDD1MHukaH8E8NFnDKRhIvjHZ12LHpT5EeVPVTkIQwCZ1hrFzbKhGmjTfGQWxiCIl67Gfr0cJFi/yYS+d+4CSnumprS7HUuI3sKRDmGx3aQUt/X7k5YQjq8doyXJaFziVeak2hdyTEunq+/757i7IDusGmHFGrAtkRbSWUUNqdbaxA4Xxu7Q6HTzDXbEjCL3EgjkD+MtWep16W2JG+ccjLU1gkx9Gny5hFGpknw/JlJsW/XVfG/fZ/XRGCCtOhNAg+kCmqF74KzC78yIdx98wDCJL/bKLNEbIY1pVFYWrliUNY3oo8qm5vMNDKDBEMH04YpSOhKXtVaCGKYPGYRmzpXtJGCWjGfAAl9m2lFkaiX4QDmayMs1GnYXJzBbcyhoA5pDjDRWvMdKvOnuZpjyAEX9axlxgBovSsC8BDz3VFsFDns3NJY0ImmovrA6CrPyqqIk3pWwbvTfnHShWJ+yCMxQRWwv/PFW78mcojbzC4bJIm7mvWDLhmXB7PTiTsMLEmRq5WyyhEyq0moFGSmQGGylolWG8kxPOqApG333WMyWYq0cYYdnqmpzdXTqYU3fgY3g9pUnjnT3mdS0wG7knEcw+MJyMzXbFwUKffGGXaIFK82V0+nFt44Ev0Mare7SCFloPGsJqmveKDtv60JZlKpmuKOXJ9+0WM3MQVWRmdrGqou13c95nOCm9a0blwnRq559402sj7uDEfo//TLv+qvXjRMasPjXkZFX/bqRZMUtf0B/1nlRXxA7/M9Skvy66sXd2dc+4iav16jMjkMLF5hnhkieaIHph3NTfZYB3wn6TQ5iTqSrrjP217F+7iKL4oqqeNa4uId/pZIul/iZVKfB31G+5vsw7k6nSusMjp+TplD51cv1O2/eiHI/KoJtFf6UAGLmWAV0Ifs8pyk+17uN3FacttNGYsrbP3fEf696Uv8aVbo8Nxz+iPPDBm15sObVJTt8Sf3gI6nFDMrP2T38VfkItvHEr1Dh3j3fFun8SJOMzIm+o5gzf7qdRIfivhYtjyG+vhPjOH98ft//T8Nhl+ShbMIAA==
+
+
+ dbo
+
+
\ No newline at end of file
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605061916117_SwapColumnMappingValues.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201605061916117_SwapColumnMappingValues.Designer.cs
new file mode 100644
index 0000000000..1fa094db33
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605061916117_SwapColumnMappingValues.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 SwapColumnMappingValues : IMigrationMetadata
+ {
+ private readonly ResourceManager Resources = new ResourceManager(typeof(SwapColumnMappingValues));
+
+ string IMigrationMetadata.Id
+ {
+ get { return "201605061916117_SwapColumnMappingValues"; }
+ }
+
+ string IMigrationMetadata.Source
+ {
+ get { return null; }
+ }
+
+ string IMigrationMetadata.Target
+ {
+ get { return Resources.GetString("Target"); }
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605061916117_SwapColumnMappingValues.cs b/src/Libraries/SmartStore.Data/Migrations/201605061916117_SwapColumnMappingValues.cs
new file mode 100644
index 0000000000..f16431d45b
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605061916117_SwapColumnMappingValues.cs
@@ -0,0 +1,105 @@
+namespace SmartStore.Data.Migrations
+{
+ using System.Collections.Generic;
+ using System.Data.Entity.Migrations;
+ using System.Linq;
+ using Core.Domain;
+ using Newtonsoft.Json;
+ using Newtonsoft.Json.Linq;
+ using Setup;
+
+ public partial class SwapColumnMappingValues : DbMigration, ILocaleResourcesProvider, IDataSeeder
+ {
+ public override void Up()
+ {
+ }
+
+ public override void Down()
+ {
+ }
+
+ public bool RollbackOnFailure
+ {
+ get { return false; }
+ }
+
+ public void Seed(SmartObjectContext context)
+ {
+ context.MigrateLocaleResources(MigrateLocaleResources);
+
+ var importProfiles = context.Set().Where(x => x.ColumnMapping != null).ToList();
+
+ foreach (var profile in importProfiles)
+ {
+ var dic = new Dictionary>();
+ var storeMapping = true;
+
+ try
+ {
+ var json = JObject.Parse(profile.ColumnMapping);
+
+ foreach (var kvp in json)
+ {
+ dynamic value = kvp.Value;
+
+ var mappedName = (string)value.MappedName;
+ var property = (string)value.Property;
+ var defaultValue = (string)value.Default;
+
+ if (mappedName.HasValue())
+ {
+ // break migration because data is already migrated
+ storeMapping = false;
+ break;
+ }
+ else if (property.HasValue())
+ {
+ if (!kvp.Key.IsCaseInsensitiveEqual(property) || defaultValue.HasValue())
+ {
+ // swap value
+ dic.Add(property, new Dictionary
+ {
+ { "MappedName", kvp.Key },
+ { "Default", defaultValue }
+ });
+ }
+ else
+ {
+ // ignore because persisting not required anymore
+ }
+ }
+ else
+ {
+ // explicitly ignored property
+ dic.Add(property, new Dictionary
+ {
+ { "MappedName", property },
+ { "Default", "[IGNOREPROPERTY]" }
+ });
+ }
+ }
+ }
+ catch
+ {
+ storeMapping = true;
+ dic.Clear();
+ }
+
+ if (storeMapping)
+ {
+ if (dic.Any())
+ profile.ColumnMapping = JsonConvert.SerializeObject(dic);
+ else
+ profile.ColumnMapping = null;
+ }
+ }
+
+ context.SaveChanges();
+ }
+
+ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
+ {
+ builder.Delete("Admin.DataExchange.ColumnMapping.Validate.MultipleMappedIgnored");
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605061916117_SwapColumnMappingValues.resx b/src/Libraries/SmartStore.Data/Migrations/201605061916117_SwapColumnMappingValues.resx
new file mode 100644
index 0000000000..15bcc90554
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605061916117_SwapColumnMappingValues.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/201605111140288_ImportExtraData.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201605111140288_ImportExtraData.Designer.cs
new file mode 100644
index 0000000000..6cac518be6
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605111140288_ImportExtraData.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 ImportExtraData : IMigrationMetadata
+ {
+ private readonly ResourceManager Resources = new ResourceManager(typeof(ImportExtraData));
+
+ string IMigrationMetadata.Id
+ {
+ get { return "201605111140288_ImportExtraData"; }
+ }
+
+ string IMigrationMetadata.Source
+ {
+ get { return null; }
+ }
+
+ string IMigrationMetadata.Target
+ {
+ get { return Resources.GetString("Target"); }
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605111140288_ImportExtraData.cs b/src/Libraries/SmartStore.Data/Migrations/201605111140288_ImportExtraData.cs
new file mode 100644
index 0000000000..191ace97ba
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605111140288_ImportExtraData.cs
@@ -0,0 +1,72 @@
+namespace SmartStore.Data.Migrations
+{
+ using System.Data.Entity.Migrations;
+ using Setup;
+
+ public partial class ImportExtraData : DbMigration, ILocaleResourcesProvider, IDataSeeder
+ {
+ public override void Up()
+ {
+ AddColumn("dbo.ImportProfile", "ExtraData", c => c.String());
+ }
+
+ public override void Down()
+ {
+ DropColumn("dbo.ImportProfile", "ExtraData");
+ }
+
+ public bool RollbackOnFailure
+ {
+ get { return false; }
+ }
+
+ public void Seed(SmartObjectContext context)
+ {
+ context.MigrateLocaleResources(MigrateLocaleResources);
+
+ context.MigrateSettings(x =>
+ {
+ x.Add("MediaSettings.VariantValueThumbPictureSize", "20");
+ x.Delete("MediaSettings.AutoCompleteSearchThumbPictureSize");
+ });
+ }
+
+ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
+ {
+ builder.AddOrUpdate("Admin.DataExchange.Import.NumberOfPictures",
+ "Number of pictures",
+ "Anzahl der Bilder",
+ "Specifies the number of images per object to be imported.",
+ "Legt die Anzahl der zu importierenden Bilder pro Objekt fest.");
+
+ builder.Update("Admin.Configuration.Settings.Catalog.DefaultPageSizeOptions")
+ .Value("en", "Number of displayed products per page");
+
+ builder.AddOrUpdate("Admin.Validation.ValueGreaterZero",
+ "The value must be greater than 0.",
+ "Der Wert muss grer 0 sein.");
+
+ builder.AddOrUpdate("Admin.Configuration.Settings.Order.OrderListPageSize",
+ "Number of displayed orders per page",
+ "Anzahl der Auftrge pro Seite",
+ "Specifies the number of displayed orders per page.",
+ "Legt die Anzahl der dargestellten Auftrge pro Seite fest.");
+
+ builder.AddOrUpdate("Admin.System.ScheduleTasks.RunningError",
+ "Error while running scheduled task \"{0}\"",
+ "Fehler beim Ausfhren der Aufgabe \"{0}\"");
+
+ builder.AddOrUpdate("Admin.System.ScheduleTasks.Cancellation",
+ "The scheduled task \"{0}\" has been canceled",
+ "Die geplante Aufgabe \"{0}\" wurde abgebrochen");
+
+ builder.AddOrUpdate("Admin.Common.HttpStatus",
+ "HTTP status {0} ({1}).",
+ "HTTP-Status {0} ({1}).");
+
+ builder.AddOrUpdate("Admin.System.Warnings.SitemapReachable.MethodNotAllowed",
+ "The reachability of the sitemap could not be validated.",
+ "Die Erreichbarkeit der Sitemap konnte nicht berprft werden.");
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605111140288_ImportExtraData.resx b/src/Libraries/SmartStore.Data/Migrations/201605111140288_ImportExtraData.resx
new file mode 100644
index 0000000000..738509bbb4
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605111140288_ImportExtraData.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/201605191216116_CheckoutAttributeMultiStore.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201605191216116_CheckoutAttributeMultiStore.Designer.cs
new file mode 100644
index 0000000000..d4625babee
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605191216116_CheckoutAttributeMultiStore.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 CheckoutAttributeMultiStore : IMigrationMetadata
+ {
+ private readonly ResourceManager Resources = new ResourceManager(typeof(CheckoutAttributeMultiStore));
+
+ string IMigrationMetadata.Id
+ {
+ get { return "201605191216116_CheckoutAttributeMultiStore"; }
+ }
+
+ string IMigrationMetadata.Source
+ {
+ get { return null; }
+ }
+
+ string IMigrationMetadata.Target
+ {
+ get { return Resources.GetString("Target"); }
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605191216116_CheckoutAttributeMultiStore.cs b/src/Libraries/SmartStore.Data/Migrations/201605191216116_CheckoutAttributeMultiStore.cs
new file mode 100644
index 0000000000..1b6ba5a31f
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605191216116_CheckoutAttributeMultiStore.cs
@@ -0,0 +1,17 @@
+namespace SmartStore.Data.Migrations
+{
+ using System.Data.Entity.Migrations;
+
+ public partial class CheckoutAttributeMultiStore : DbMigration
+ {
+ public override void Up()
+ {
+ AddColumn("dbo.CheckoutAttribute", "LimitedToStores", c => c.Boolean(nullable: false));
+ }
+
+ public override void Down()
+ {
+ DropColumn("dbo.CheckoutAttribute", "LimitedToStores");
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605191216116_CheckoutAttributeMultiStore.resx b/src/Libraries/SmartStore.Data/Migrations/201605191216116_CheckoutAttributeMultiStore.resx
new file mode 100644
index 0000000000..d743254b0e
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605191216116_CheckoutAttributeMultiStore.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/201605201911421_ExportRevision.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201605201911421_ExportRevision.Designer.cs
new file mode 100644
index 0000000000..e3a2d0014f
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605201911421_ExportRevision.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 ExportRevision : IMigrationMetadata
+ {
+ private readonly ResourceManager Resources = new ResourceManager(typeof(ExportRevision));
+
+ string IMigrationMetadata.Id
+ {
+ get { return "201605201911421_ExportRevision"; }
+ }
+
+ string IMigrationMetadata.Source
+ {
+ get { return null; }
+ }
+
+ string IMigrationMetadata.Target
+ {
+ get { return Resources.GetString("Target"); }
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605201911421_ExportRevision.cs b/src/Libraries/SmartStore.Data/Migrations/201605201911421_ExportRevision.cs
new file mode 100644
index 0000000000..d168932260
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605201911421_ExportRevision.cs
@@ -0,0 +1,204 @@
+namespace SmartStore.Data.Migrations
+{
+ using System.Data.Entity.Migrations;
+ using System.Linq;
+ using Core.Domain;
+ using Core.Domain.DataExchange;
+ using Setup;
+ using Utilities;
+
+ public partial class ExportRevision : DbMigration, ILocaleResourcesProvider, IDataSeeder
+ {
+ public override void Up()
+ {
+ AddColumn("dbo.ExportDeployment", "ResultInfo", c => c.String());
+ AddColumn("dbo.ExportDeployment", "SubFolder", c => c.String(maxLength: 400));
+ AlterColumn("dbo.ExportProfile", "FolderName", c => c.String(nullable: false, maxLength: 400));
+ DropColumn("dbo.ExportDeployment", "CreateZip");
+ }
+
+ public override void Down()
+ {
+ AddColumn("dbo.ExportDeployment", "CreateZip", c => c.Boolean(nullable: false));
+ AlterColumn("dbo.ExportProfile", "FolderName", c => c.String(nullable: false, maxLength: 100));
+ DropColumn("dbo.ExportDeployment", "SubFolder");
+ DropColumn("dbo.ExportDeployment", "ResultInfo");
+ }
+
+ public bool RollbackOnFailure
+ {
+ get { return false; }
+ }
+
+ public void Seed(SmartObjectContext context)
+ {
+ context.MigrateLocaleResources(MigrateLocaleResources);
+
+ // migrate folder name to folder path
+ var rootPath = "~/App_Data/ExportProfiles/";
+ var exportProfiles = context.Set().ToList();
+
+ foreach (var profile in exportProfiles)
+ {
+ if (!profile.FolderName.EmptyNull().StartsWith(rootPath))
+ {
+ profile.FolderName = rootPath + profile.FolderName;
+ }
+ }
+
+ context.SaveChanges();
+
+ // migrate public file system deployment to new public deployment
+ if (context.ColumnExists("ExportDeployment", "IsPublic"))
+ {
+ var fileSystemDeploymentTypeId = (int)ExportDeploymentType.FileSystem;
+ var publicFolderDeploymentTypeId = (int)ExportDeploymentType.PublicFolder;
+
+ context.ExecuteSqlCommand("Update [ExportDeployment] Set DeploymentTypeId = {0} Where DeploymentTypeId = {1} And IsPublic = 1",
+ true, null, publicFolderDeploymentTypeId, fileSystemDeploymentTypeId);
+
+ context.ColumnDelete("ExportDeployment", "IsPublic");
+ }
+
+ var oldFileManagerPath = CommonHelper.MapPath("~/Content/filemanager");
+ FileSystemHelper.ClearDirectory(oldFileManagerPath, true);
+ }
+
+ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
+ {
+ builder.AddOrUpdate("Admin.DataExchange.Export.FolderName",
+ "Folder path",
+ "Ordnerpfad",
+ "Specifies the relative path of the folder where to export the data.",
+ "Legt den relativen Pfad des Ordners fest, in den die Daten exportiert werden.");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.FileNamePattern.Validate",
+ "Please enter a valid pattern for file names. Example for file names: %Store.Id%-%Profile.Id%-%File.Index%-%Profile.SeoName%",
+ "Bitte ein gltiges Muster fr Dateinamen eingeben. Beispiel: %Store.Id%-%Profile.Id%-%File.Index%-%Profile.SeoName%");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.FolderName.Validate",
+ "Please enter a valid, relative folder path for the export data.",
+ "Bitte einen gltigen, relativen Ordnerpfad fr die zu exportierenden Daten eingeben.");
+
+ builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportDeploymentType.Http", "HTTP POST", "HTTP POST");
+ builder.AddOrUpdate("Enums.SmartStore.Core.Domain.DataExchange.ExportDeploymentType.PublicFolder", "Public folder", "ffentlicher Ordner");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.SubFolder",
+ "Name of subfolder",
+ "Name des Unterordners",
+ "Specifies the name of a subfolder where to publish the data.",
+ "Legt den Namen eines Unterordners fest, in den die Daten verffentlicht werden sollen.");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.ZipUsageNote",
+ "If there are a large number of export files, it is recommended to use the option Create ZIP archive. This saves time and avoids problems, such as a full email mailbox.",
+ "Bei einer groen Anzahl an Exportdateien wird empfohlen die Option ZIP-Archiv erstellen zu benutzen. Das spart Zeit und vermeidet Probleme, wie z.B. ein volles E-Mail Postfach.");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Cleanup",
+ "Clean up after successful deployment",
+ "Nach erfolgreicher Verffentlichung aufrumen",
+ "Specifies whether to delete unneeded files after all deployments succeeded.",
+ "Legt fest, ob nicht mehr bentigte Dateien gelscht werden sollen, nachdem alle Verffentlichungen erfolgreich waren.");
+
+ builder.AddOrUpdate("Admin.Common.FtpStatus",
+ "FTP status {0} ({1}).",
+ "FTP-Status {0} ({1}).");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.CopyFileFailed",
+ "At least one file could not be copied.",
+ "Mindestens eine Datei konnte nicht kopiert werden.");
+
+ builder.AddOrUpdate("Admin.Common.LastRun", "Last run", "Letzte Ausfhrung");
+ builder.AddOrUpdate("Admin.Common.SuccessfulOn", "Successful on", "Erfolgreich am");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.Name",
+ "Name of profile",
+ "Name des Profils",
+ "Specifies the name of the publishing profile.",
+ "Legt den Namen des Verffentlichungsprofils fest.");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.ProfilesTitle",
+ "Publishing profiles",
+ "Verffentlichungsprofile");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.NoProfiles",
+ "There are no publishing profiles.",
+ "Es liegen keine Verffentlichungsprofile vor.");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.Note",
+ "Click New profile to add one or multiple publishing profiles to specify how to further proceed with the export files.",
+ "Legen Sie ber Neues Profil ein oder mehrere Verffentlichungsprofile an, um festzulegen wie mit den Exportdateien weiter zu verfahren ist.");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.PublishingTarget",
+ "Publishing target",
+ "Verffentlichungsziel");
+
+ builder.AddOrUpdate("Admin.DataExchange.Export.Deployment.DeploymentType",
+ "Publishing type",
+ "Art der Verffentlichung",
+ "Specifies the type of publishing.",
+ "Legt die Art Verffentlichung fest.");
+
+ builder.AddOrUpdate("Common.Publishing",
+ "Publishing",
+ "Verffentlichung");
+
+ builder.AddOrUpdate("Common.NoFilesAvailable",
+ "There are no files available.",
+ "Es sind keine Dateien vorhanden.");
+
+ builder.AddOrUpdate("Common.CopyToClipboard", "Copy to clipboard", "In die Zwischenablage kopieren");
+ builder.AddOrUpdate("Common.CopyToClipboard.Succeeded", "Copied!", "Kopiert!");
+ builder.AddOrUpdate("Common.CopyToClipboard.Failded", "Failed to copy.", "Kopieren ist fehlgeschlagen.");
+
+ builder.AddOrUpdate("Products.NoBundledItems",
+ "No bundle items available",
+ "Keine Bundle-Bestandteile vorhanden");
+
+ builder.AddOrUpdate("Common.NoFileUploaded",
+ "There was no file uploaded.",
+ "Es wurde keine Datei hochgeladen.");
+
+ builder.AddOrUpdate("Products.BasePriceInfo",
+ "Content: {0} {1} ({2} / {3} {1})",
+ "Inhalt: {0} {1} ({2} / {3} {1})");
+
+ builder.AddOrUpdate("Products.BasePriceInfo.LanguageInsensitive",
+ "{0} {1} ({2} / {3} {1})",
+ "{0} {1} ({2} / {3} {1})");
+
+ builder.AddOrUpdate("PrivateMessages.Disabled",
+ "Private messages are disabled.",
+ "Private Nachrichten sind deaktiviert.");
+
+ builder.AddOrUpdate("Common.MethodNotSupportedForGuests",
+ "This function is not available for guests.",
+ "Diese Funktion steht fr Gste nicht zur Verfgung.");
+
+ builder.AddOrUpdate("ContactUs.PrivacyAgreement",
+ "Privacy consent",
+ "Einwilligungserklrung Datenschutz");
+
+ builder.AddOrUpdate("ContactUs.PrivacyAgreement.MustBeAccepted",
+ "Please agree to the storage of your data.",
+ "Bitte stimmen Sie der Speicherung Ihrer Daten zu.");
+
+ builder.AddOrUpdate("ContactUs.PrivacyAgreement.DetailText",
+ "Yes I've read the privacy terms and agree that my data given by me can be stored electronically. My data will thereby only be used to process my inquiry.",
+ "Ja, ich habe die Datenschutzerklrung zur Kenntnis genommen und bin damit einverstanden, dass die von mir angegebenen Daten elektronisch erhoben und gespeichert werden. Meine Daten werden dabei nur zur Bearbeitung meiner Anfrage genutzt.");
+
+ builder.AddOrUpdate("Admin.Configuration.Settings.CustomerUser.DisplayPrivacyAgreementOnContactUs",
+ "Get privacy consent for contact requests",
+ "Einwilligungserklrung im Kontaktformular fordern",
+ "Specifies whether a checkbox will be displayed on the contact page which requests the user to agree on storage of his data.",
+ "Bestimmt ob im Kontaktformular eine Checkbox angezeigt wird, die den Benutzer auffordert der Speicherung seiner Daten zuzustimmen.");
+
+
+ builder.Delete(
+ "Admin.DataExchange.Export.FolderAndFileName.Validate",
+ "Admin.DataExchange.Export.Deployment.IsPublic",
+ "Admin.DataExchange.Export.Deployment.CreateZip",
+ "Admin.Common.TemporaryFiles",
+ "Admin.Common.NoTempFilesFound");
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201605201911421_ExportRevision.resx b/src/Libraries/SmartStore.Data/Migrations/201605201911421_ExportRevision.resx
new file mode 100644
index 0000000000..a653f94065
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201605201911421_ExportRevision.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/201607111548571_FixExportDeploymentIsPublic.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201607111548571_FixExportDeploymentIsPublic.Designer.cs
new file mode 100644
index 0000000000..16b788408f
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201607111548571_FixExportDeploymentIsPublic.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 FixExportDeploymentIsPublic : IMigrationMetadata
+ {
+ private readonly ResourceManager Resources = new ResourceManager(typeof(FixExportDeploymentIsPublic));
+
+ string IMigrationMetadata.Id
+ {
+ get { return "201607111548571_FixExportDeploymentIsPublic"; }
+ }
+
+ string IMigrationMetadata.Source
+ {
+ get { return null; }
+ }
+
+ string IMigrationMetadata.Target
+ {
+ get { return Resources.GetString("Target"); }
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201607111548571_FixExportDeploymentIsPublic.cs b/src/Libraries/SmartStore.Data/Migrations/201607111548571_FixExportDeploymentIsPublic.cs
new file mode 100644
index 0000000000..f48207c9fc
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201607111548571_FixExportDeploymentIsPublic.cs
@@ -0,0 +1,21 @@
+namespace SmartStore.Data.Migrations
+{
+ using System.Data.Entity.Migrations;
+ using System.Web.Hosting;
+ using Core.Data;
+
+ public partial class FixExportDeploymentIsPublic : DbMigration
+ {
+ public override void Up()
+ {
+ if (HostingEnvironment.IsHosted && DataSettings.Current.IsSqlServer)
+ {
+ Sql("IF EXISTS(SELECT TOP 1 1 FROM sys.objects o INNER JOIN sys.columns c ON o.object_id = c.object_id WHERE o.name = 'ExportDeployment' AND c.name = 'IsPublic') ALTER TABLE [dbo].[ExportDeployment] DROP COLUMN [IsPublic];");
+ }
+ }
+
+ public override void Down()
+ {
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201607111548571_FixExportDeploymentIsPublic.resx b/src/Libraries/SmartStore.Data/Migrations/201607111548571_FixExportDeploymentIsPublic.resx
new file mode 100644
index 0000000000..55e598ca59
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201607111548571_FixExportDeploymentIsPublic.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 69c108466d..ff7fd39e2b 100644
--- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
+++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
@@ -384,6 +384,30 @@
201603121451066_ThirdPartyEmailHandOver.cs
+
+
+ 201605020640016_GtinMpnIndex.cs
+
+
+
+ 201605061916117_SwapColumnMappingValues.cs
+
+
+
+ 201605111140288_ImportExtraData.cs
+
+
+
+ 201605191216116_CheckoutAttributeMultiStore.cs
+
+
+
+ 201605201911421_ExportRevision.cs
+
+
+
+ 201607111548571_FixExportDeploymentIsPublic.cs
+
@@ -717,6 +741,24 @@
201603121451066_ThirdPartyEmailHandOver.cs
+
+ 201605020640016_GtinMpnIndex.cs
+
+
+ 201605061916117_SwapColumnMappingValues.cs
+
+
+ 201605111140288_ImportExtraData.cs
+
+
+ 201605191216116_CheckoutAttributeMultiStore.cs
+
+
+ 201605201911421_ExportRevision.cs
+
+
+ 201607111548571_FixExportDeploymentIsPublic.cs
+
diff --git a/src/Libraries/SmartStore.Services/Authentication/External/AuthorizeState.cs b/src/Libraries/SmartStore.Services/Authentication/External/AuthorizeState.cs
index dcc6c9762c..35e853bbfc 100644
--- a/src/Libraries/SmartStore.Services/Authentication/External/AuthorizeState.cs
+++ b/src/Libraries/SmartStore.Services/Authentication/External/AuthorizeState.cs
@@ -17,7 +17,7 @@ public AuthorizeState(string returnUrl, OpenAuthenticationStatus openAuthenticat
_returnUrl = returnUrl;
AuthenticationStatus = openAuthenticationStatus;
- //in way SEO friendly language URLs will be persisted
+ // in a way SEO friendly language URLs will be persisted
if (AuthenticationStatus == OpenAuthenticationStatus.Authenticated)
Result = new RedirectResult(!string.IsNullOrEmpty(_returnUrl) ? _returnUrl : "~/");
}
diff --git a/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs b/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs
index b948930425..05cddc7f7b 100644
--- a/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs
+++ b/src/Libraries/SmartStore.Services/Authentication/FormsAuthenticationService.cs
@@ -12,7 +12,7 @@ namespace SmartStore.Services.Authentication
///
public partial class FormsAuthenticationService : IAuthenticationService
{
- private readonly HttpContextBase _httpContext;
+ private readonly HttpContextBase _httpContext;
private readonly ICustomerService _customerService;
private readonly CustomerSettings _customerSettings;
private readonly TimeSpan _expirationTimeSpan;
@@ -33,7 +33,6 @@ public FormsAuthenticationService(HttpContextBase httpContext, ICustomerService
this._expirationTimeSpan = FormsAuthentication.Timeout;
}
-
public virtual void SignIn(Customer customer, bool createPersistentCookie)
{
var now = DateTime.UtcNow.ToLocalTime();
@@ -95,6 +94,21 @@ public virtual Customer GetAuthenticatedCustomer()
if (customer != null && customer.Active && !customer.Deleted && customer.IsRegistered())
{
+ if (customer.LastLoginDateUtc == null)
+ {
+ try
+ {
+ // This is most probably the very first "login" after registering. Delete the
+ // ASP.NET anonymous id cookie so that a new guest account can be created
+ // upon signing out.
+ System.Web.Security.AnonymousIdentificationModule.ClearAnonymousIdentifier();
+ }
+ finally
+ {
+ customer.LastLoginDateUtc = DateTime.UtcNow;
+ _customerService.UpdateCustomer(customer);
+ }
+ }
_cachedCustomer = customer;
}
@@ -117,5 +131,5 @@ public virtual Customer GetAuthenticatedCustomerFromTicket(FormsAuthenticationTi
return customer;
}
- }
+ }
}
\ No newline at end of file
diff --git a/src/Libraries/SmartStore.Services/Catalog/CopyProductService.cs b/src/Libraries/SmartStore.Services/Catalog/CopyProductService.cs
index 2dcb1cb673..f786bf9c78 100644
--- a/src/Libraries/SmartStore.Services/Catalog/CopyProductService.cs
+++ b/src/Libraries/SmartStore.Services/Catalog/CopyProductService.cs
@@ -84,8 +84,8 @@ public virtual Product CopyProduct(Product product, string newName, bool isPubli
var utcNow = DateTime.UtcNow;
// product download & sample download
- int downloadId = product.DownloadId;
- int? sampleDownloadId = product.SampleDownloadId;
+ int downloadId = 0;
+ int? sampleDownloadId = null;
if (product.IsDownload)
{
diff --git a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs
index 64a412d339..f8565562e5 100644
--- a/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs
+++ b/src/Libraries/SmartStore.Services/Catalog/IProductAttributeParser.cs
@@ -33,21 +33,20 @@ public partial interface IProductAttributeParser
IEnumerable ParseProductVariantAttributeValues(string attributesXml);
///
- /// Get list of localized product variant attribute values
+ /// Get list of product variant attribute values
///
- /// XML formatted attributes
+ /// Map of combined attributes
/// Product variant attributes
- /// Language identifier
- /// List of localized product variant attribute values
- IList ParseProductVariantAttributeValues(string attributesXml, IEnumerable attributes, int languageId = 0);
+ /// List of product variant attribute values
+ IList ParseProductVariantAttributeValues(Multimap attributeCombination, IEnumerable attributes);
- ///
- /// Gets selected product variant attribute value
- ///
+ ///
+ /// Gets selected product variant attribute value
+ ///
/// XML formatted attributes
- /// Product variant attribute identifier
- /// Product variant attribute value
- IList ParseValues(string attributesXml, int productVariantAttributeId);
+ /// Product variant attribute identifier
+ /// Product variant attribute value
+ IList ParseValues(string attributesXml, int productVariantAttributeId);
///
/// Adds an attribute
diff --git a/src/Libraries/SmartStore.Services/Catalog/Importer/CategoryImporter.cs b/src/Libraries/SmartStore.Services/Catalog/Importer/CategoryImporter.cs
index 84a933a3cf..3f7315905b 100644
--- a/src/Libraries/SmartStore.Services/Catalog/Importer/CategoryImporter.cs
+++ b/src/Libraries/SmartStore.Services/Catalog/Importer/CategoryImporter.cs
@@ -2,12 +2,14 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Linq.Expressions;
using SmartStore.Core.Async;
using SmartStore.Core.Data;
using SmartStore.Core.Domain.Catalog;
using SmartStore.Core.Domain.DataExchange;
using SmartStore.Core.Domain.Media;
using SmartStore.Core.Domain.Seo;
+using SmartStore.Core.Domain.Stores;
using SmartStore.Core.Events;
using SmartStore.Services.DataExchange.Import;
using SmartStore.Services.Localization;
@@ -21,179 +23,166 @@ namespace SmartStore.Services.Catalog.Importer
public class CategoryImporter : EntityImporterBase
{
private readonly IRepository _categoryRepository;
- private readonly IRepository _urlRecordRepository;
private readonly IRepository _pictureRepository;
private readonly ICommonServices _services;
- private readonly IUrlRecordService _urlRecordService;
private readonly ICategoryTemplateService _categoryTemplateService;
- private readonly IStoreMappingService _storeMappingService;
private readonly IPictureService _pictureService;
private readonly ILocalizedEntityService _localizedEntityService;
private readonly FileDownloadManager _fileDownloadManager;
- private readonly SeoSettings _seoSettings;
- private readonly DataExchangeSettings _dataExchangeSettings;
+
+ private static readonly Dictionary>> _localizableProperties = new Dictionary>>
+ {
+ { "Name", x => x.Name },
+ { "FullName", x => x.FullName },
+ { "Description", x => x.Description },
+ { "BottomDescription", x => x.BottomDescription },
+ { "MetaKeywords", x => x.MetaKeywords },
+ { "MetaDescription", x => x.MetaDescription },
+ { "MetaTitle", x => x.MetaTitle }
+ };
public CategoryImporter(
IRepository categoryRepository,
- IRepository urlRecordRepository,
IRepository pictureRepository,
ICommonServices services,
- IUrlRecordService urlRecordService,
ICategoryTemplateService categoryTemplateService,
- IStoreMappingService storeMappingService,
IPictureService pictureService,
ILocalizedEntityService localizedEntityService,
- FileDownloadManager fileDownloadManager,
- SeoSettings seoSettings,
- DataExchangeSettings dataExchangeSettings)
+ FileDownloadManager fileDownloadManager)
{
_categoryRepository = categoryRepository;
- _urlRecordRepository = urlRecordRepository;
_pictureRepository = pictureRepository;
_services = services;
- _urlRecordService = urlRecordService;
_categoryTemplateService = categoryTemplateService;
- _storeMappingService = storeMappingService;
_pictureService = pictureService;
_localizedEntityService = localizedEntityService;
_fileDownloadManager = fileDownloadManager;
- _seoSettings = seoSettings;
- _dataExchangeSettings = dataExchangeSettings;
}
- private int ProcessSlugs(IImportExecuteContext context, ImportRow[] batch)
+ protected override void Import(ImportExecuteContext context)
{
- var entityName = typeof(Category).Name;
- var slugMap = new Dictionary();
+ var srcToDestId = new Dictionary();
- Func slugLookup = ((s) =>
- {
- return (slugMap.ContainsKey(s) ? slugMap[s] : null);
- });
+ var templateViewPaths = _categoryTemplateService.GetAllCategoryTemplates().ToDictionarySafe(x => x.ViewPath, x => x.Id);
- foreach (var row in batch)
+ using (var scope = new DbContextScope(ctx: context.Services.DbContext, autoDetectChanges: false, proxyCreation: false, validateOnSave: false))
{
- if (!row.IsNew && !row.NameChanged)
- continue;
+ var segmenter = context.DataSegmenter;
- try
+ Initialize(context);
+
+ while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch())
{
- UrlRecord urlRecord = null;
- var seName = row.GetDataValue("SeName");
- seName = row.Entity.ValidateSeName(seName, row.Entity.Name, true, _urlRecordService, _seoSettings, extraSlugLookup: slugLookup);
+ var batch = segmenter.GetCurrentBatch();
- if (row.IsNew)
+ // Perf: detach all entities
+ _categoryRepository.Context.DetachAll(false);
+
+ context.SetProgress(segmenter.CurrentSegmentFirstRowIndex - 1, segmenter.TotalRows);
+
+ try
{
- // dont't bother validating SeName for new entities.
- urlRecord = new UrlRecord
- {
- EntityId = row.Entity.Id,
- EntityName = entityName,
- Slug = seName,
- LanguageId = 0,
- IsActive = true,
- };
- _urlRecordRepository.Insert(urlRecord);
+ ProcessCategories(context, batch, templateViewPaths, srcToDestId);
}
- else
+ catch (Exception exception)
{
- urlRecord = _urlRecordService.SaveSlug(row.Entity, seName, 0);
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessCategories");
}
- if (urlRecord != null)
+ // reduce batch to saved (valid) products.
+ // No need to perform import operations on errored products.
+ batch = batch.Where(x => x.Entity != null && !x.IsTransient).ToArray();
+
+ // update result object
+ context.Result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient);
+ context.Result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient);
+
+ // process slugs
+ if (segmenter.HasColumn("SeName", true) || batch.Any(x => x.IsNew || x.NameChanged))
{
- // a new record was inserted to the store: keep track of it for this batch.
- slugMap[seName] = urlRecord;
+ try
+ {
+ _categoryRepository.Context.AutoDetectChangesEnabled = true;
+ ProcessSlugs(context, batch, typeof(Category).Name);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessSlugs");
+ }
+ finally
+ {
+ _categoryRepository.Context.AutoDetectChangesEnabled = false;
+ }
}
- foreach (var lang in context.Languages)
+ // process store mappings
+ if (segmenter.HasColumn("StoreIds"))
{
- if (row.Segmenter.HasColumn("SeName", lang.UniqueSeoCode))
+ try
+ {
+ ProcessStoreMappings(context, batch);
+ }
+ catch (Exception exception)
{
- seName = row.GetDataValue("SeName", lang.UniqueSeoCode);
- seName = row.Entity.ValidateSeName(seName, null, false, _urlRecordService, _seoSettings, lang.Id, slugLookup);
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessStoreMappings");
+ }
+ }
- urlRecord = _urlRecordService.SaveSlug(row.Entity, seName, lang.Id);
+ // localizations
+ try
+ {
+ ProcessLocalizations(context, batch, _localizableProperties);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessLocalizedProperties");
+ }
- if (urlRecord != null)
- {
- slugMap[seName] = urlRecord;
- }
+ // process pictures
+ if (srcToDestId.Any() && segmenter.HasColumn("ImageUrl") && !segmenter.IsIgnored("PictureId"))
+ {
+ try
+ {
+ _categoryRepository.Context.AutoDetectChangesEnabled = true;
+ ProcessPictures(context, batch, srcToDestId);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessPictures");
+ }
+ finally
+ {
+ _categoryRepository.Context.AutoDetectChangesEnabled = false;
}
}
}
- catch (Exception exception)
- {
- context.Result.AddWarning(exception.Message, row.GetRowInfo(), "SeName");
- }
- }
-
- // commit whole batch at once
- return _urlRecordRepository.Context.SaveChanges();
- }
- private int ProcessLocalizations(IImportExecuteContext context, ImportRow[] batch)
- {
- foreach (var row in batch)
- {
- foreach (var lang in context.Languages)
+ // map parent id of inserted categories
+ if (srcToDestId.Any() && segmenter.HasColumn("Id") && segmenter.HasColumn("ParentCategoryId") && !segmenter.IsIgnored("ParentCategoryId"))
{
- var name = row.GetDataValue("Name", lang.UniqueSeoCode);
- var fullName = row.GetDataValue("FullName", lang.UniqueSeoCode);
- var description = row.GetDataValue("Description", lang.UniqueSeoCode);
- var bottomDescription = row.GetDataValue("BottomDescription", lang.UniqueSeoCode);
- var metaKeywords = row.GetDataValue("MetaKeywords", lang.UniqueSeoCode);
- var metaDescription = row.GetDataValue("MetaDescription", lang.UniqueSeoCode);
- var metaTitle = row.GetDataValue("MetaTitle", lang.UniqueSeoCode);
-
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.Name, name, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.FullName, fullName, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.Description, description, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.BottomDescription, bottomDescription, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaKeywords, metaKeywords, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaDescription, metaDescription, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaTitle, metaTitle, lang.Id);
- }
- }
-
- var num = _categoryRepository.Context.SaveChanges();
-
- return num;
- }
-
- private int ProcessParentMappings(IImportExecuteContext context,
- ImportRow[] batch,
- Dictionary srcToDestId)
- {
- foreach (var row in batch)
- {
- var id = row.GetDataValue("Id");
- var rawParentId = row.GetDataValue("ParentCategoryId");
- var parentId = rawParentId.ToInt(-1);
+ segmenter.Reset();
- if (id != 0 && parentId != -1 && srcToDestId.ContainsKey(id) && srcToDestId.ContainsKey(parentId))
- {
- // only touch hierarchical data if child and parent were inserted
- if (srcToDestId[id].Inserted && srcToDestId[parentId].Inserted && srcToDestId[id].DestinationId != 0)
+ while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch())
{
- var category = _categoryRepository.GetById(srcToDestId[id].DestinationId);
- if (category != null)
- {
- category.ParentCategoryId = srcToDestId[parentId].DestinationId;
+ var batch = segmenter.GetCurrentBatch();
+ _categoryRepository.Context.DetachAll(false);
- _categoryRepository.Update(category);
+ try
+ {
+ ProcessParentMappings(context, batch, srcToDestId);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessParentMappings");
}
}
}
}
-
- var num = _categoryRepository.Context.SaveChanges();
-
- return num;
}
- private int ProcessPictures(IImportExecuteContext context,
- ImportRow[] batch,
+ protected virtual int ProcessPictures(
+ ImportExecuteContext context,
+ IEnumerable> batch,
Dictionary srcToDestId)
{
Picture picture = null;
@@ -266,23 +255,81 @@ private int ProcessPictures(IImportExecuteContext context,
return num;
}
- private void ProcessStoreMappings(IImportExecuteContext context, ImportRow[] batch)
+ protected virtual int ProcessLocalizations(
+ ImportExecuteContext context,
+ IEnumerable> batch,
+ string[] localizedProperties)
{
+ if (localizedProperties.Length == 0)
+ {
+ return 0;
+ }
+
+ bool shouldSave = false;
+
foreach (var row in batch)
{
- var limitedToStore = row.GetDataValue("LimitedToStores");
+ foreach (var prop in localizedProperties)
+ {
+ var lambda = _localizableProperties[prop];
+ foreach (var lang in context.Languages)
+ {
+ var code = lang.UniqueSeoCode;
+ string value;
- if (limitedToStore)
+ if (row.TryGetDataValue(prop /* ColumnName */, code, out value))
+ {
+ _localizedEntityService.SaveLocalizedValue(row.Entity, lambda, value, lang.Id);
+ shouldSave = true;
+ }
+ }
+ }
+ }
+
+ if (shouldSave)
+ {
+ // commit whole batch at once
+ return context.Services.DbContext.SaveChanges();
+ }
+
+ return 0;
+ }
+
+ protected virtual int ProcessParentMappings(
+ ImportExecuteContext context,
+ IEnumerable> batch,
+ Dictionary srcToDestId)
+ {
+ foreach (var row in batch)
+ {
+ var id = row.GetDataValue("Id");
+ var rawParentId = row.GetDataValue("ParentCategoryId");
+ var parentId = rawParentId.ToInt(-1);
+
+ if (id != 0 && parentId != -1 && srcToDestId.ContainsKey(id) && srcToDestId.ContainsKey(parentId))
{
- var storeIds = row.GetDataValue>("StoreIds");
+ // only touch hierarchical data if child and parent were inserted
+ if (srcToDestId[id].Inserted && srcToDestId[parentId].Inserted && srcToDestId[id].DestinationId != 0)
+ {
+ var category = _categoryRepository.GetById(srcToDestId[id].DestinationId);
+ if (category != null)
+ {
+ category.ParentCategoryId = srcToDestId[parentId].DestinationId;
- _storeMappingService.SaveStoreMappings(row.Entity, storeIds == null ? new int[0] : storeIds.ToArray());
+ _categoryRepository.Update(category);
+ }
+ }
}
}
+
+ var num = _categoryRepository.Context.SaveChanges();
+
+ return num;
}
- private int ProcessCategories(IImportExecuteContext context,
- ImportRow[] batch,
+ protected virtual int ProcessCategories(
+ ImportExecuteContext context,
+ IEnumerable> batch,
Dictionary templateViewPaths,
Dictionary srcToDestId)
{
@@ -335,7 +382,7 @@ private int ProcessCategories(IImportExecuteContext context,
category = new Category();
}
- row.Initialize(category, name);
+ row.Initialize(category, name ?? category.Name);
if (!row.IsNew && !category.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
{
@@ -343,29 +390,34 @@ private int ProcessCategories(IImportExecuteContext context,
row.NameChanged = true;
}
- row.SetProperty(context.Result, category, (x) => x.Name);
- row.SetProperty(context.Result, category, (x) => x.FullName);
- row.SetProperty(context.Result, category, (x) => x.Description);
- row.SetProperty(context.Result, category, (x) => x.BottomDescription);
- row.SetProperty(context.Result, category, (x) => x.MetaKeywords);
- row.SetProperty(context.Result, category, (x) => x.MetaDescription);
- row.SetProperty(context.Result, category, (x) => x.MetaTitle);
- row.SetProperty(context.Result, category, (x) => x.PageSize, 12);
- row.SetProperty(context.Result, category, (x) => x.AllowCustomersToSelectPageSize, true);
- row.SetProperty(context.Result, category, (x) => x.PageSizeOptions);
- row.SetProperty(context.Result, category, (x) => x.PriceRanges);
- row.SetProperty(context.Result, category, (x) => x.ShowOnHomePage);
- row.SetProperty(context.Result, category, (x) => x.HasDiscountsApplied);
- row.SetProperty(context.Result, category, (x) => x.Published, true);
- row.SetProperty(context.Result, category, (x) => x.DisplayOrder);
- row.SetProperty(context.Result, category, (x) => x.LimitedToStores);
- row.SetProperty(context.Result, category, (x) => x.Alias);
- row.SetProperty(context.Result, category, (x) => x.DefaultViewMode);
-
- var tvp = row.GetDataValue("CategoryTemplateViewPath");
- category.CategoryTemplateId = (tvp.HasValue() && templateViewPaths.ContainsKey(tvp) ? templateViewPaths[tvp] : defaultTemplateId);
-
- row.SetProperty(context.Result, category, (x) => x.CreatedOnUtc, UtcNow);
+ row.SetProperty(context.Result, (x) => x.Name);
+ row.SetProperty(context.Result, (x) => x.FullName);
+ row.SetProperty(context.Result, (x) => x.Description);
+ row.SetProperty(context.Result, (x) => x.BottomDescription);
+ row.SetProperty(context.Result, (x) => x.MetaKeywords);
+ row.SetProperty(context.Result, (x) => x.MetaDescription);
+ row.SetProperty(context.Result, (x) => x.MetaTitle);
+ row.SetProperty(context.Result, (x) => x.PageSize, 12);
+ row.SetProperty(context.Result, (x) => x.AllowCustomersToSelectPageSize, true);
+ row.SetProperty(context.Result, (x) => x.PageSizeOptions);
+ row.SetProperty(context.Result, (x) => x.PriceRanges);
+ row.SetProperty(context.Result, (x) => x.ShowOnHomePage);
+ row.SetProperty(context.Result, (x) => x.HasDiscountsApplied);
+ row.SetProperty(context.Result, (x) => x.Published, true);
+ row.SetProperty(context.Result, (x) => x.DisplayOrder);
+ row.SetProperty(context.Result, (x) => x.Alias);
+ row.SetProperty(context.Result, (x) => x.DefaultViewMode);
+ // With new entities, "LimitedToStores" is an implicit field, meaning
+ // it has to be set to true by code if it's absent but "StoreIds" exists.
+ row.SetProperty(context.Result, (x) => x.LimitedToStores, !row.GetDataValue>("StoreIds").IsNullOrEmpty());
+
+ string tvp;
+ if (row.TryGetDataValue("CategoryTemplateViewPath", out tvp, row.IsTransient))
+ {
+ category.CategoryTemplateId = (tvp.HasValue() && templateViewPaths.ContainsKey(tvp) ? templateViewPaths[tvp] : defaultTemplateId);
+ }
+
+ row.SetProperty(context.Result, (x) => x.CreatedOnUtc, UtcNow);
category.UpdatedOnUtc = UtcNow;
if (id != 0 && !srcToDestId.ContainsKey(id))
@@ -427,140 +479,11 @@ public static string[] DefaultKeyFields
}
}
- protected override void Import(IImportExecuteContext context)
+ public class ImportCategoryMapping
{
- var srcToDestId = new Dictionary();
-
- var templateViewPaths = _categoryTemplateService.GetAllCategoryTemplates().ToDictionarySafe(x => x.ViewPath, x => x.Id);
-
- using (var scope = new DbContextScope(ctx: _categoryRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false))
- {
- var segmenter = context.GetSegmenter();
-
- Init(context, _dataExchangeSettings);
-
- context.Result.TotalRecords = segmenter.TotalRows;
-
- while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch())
- {
- var batch = segmenter.CurrentBatch;
-
- // Perf: detach all entities
- _categoryRepository.Context.DetachAll(false);
-
- context.SetProgress(segmenter.CurrentSegmentFirstRowIndex - 1, segmenter.TotalRows);
-
- try
- {
- ProcessCategories(context, batch, templateViewPaths, srcToDestId);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessCategories");
- }
-
- // reduce batch to saved (valid) products.
- // No need to perform import operations on errored products.
- batch = batch.Where(x => x.Entity != null && !x.IsTransient).ToArray();
-
- // update result object
- context.Result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient);
- context.Result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient);
-
- // process slugs
- if (segmenter.HasColumn("SeName") || batch.Any(x => x.IsNew || x.NameChanged))
- {
- try
- {
- _categoryRepository.Context.AutoDetectChangesEnabled = true;
- ProcessSlugs(context, batch);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessSlugs");
- }
- finally
- {
- _categoryRepository.Context.AutoDetectChangesEnabled = false;
- }
- }
-
- // process store mappings
- if (segmenter.HasColumn("LimitedToStores") && segmenter.HasColumn("StoreIds"))
- {
- try
- {
- _categoryRepository.Context.AutoDetectChangesEnabled = true;
- ProcessStoreMappings(context, batch);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessStoreMappings");
- }
- finally
- {
- _categoryRepository.Context.AutoDetectChangesEnabled = false;
- }
- }
-
- // localizations
- try
- {
- ProcessLocalizations(context, batch);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessLocalizedProperties");
- }
-
- // process pictures
- if (srcToDestId.Any() && segmenter.HasColumn("ImageUrl"))
- {
- try
- {
- _categoryRepository.Context.AutoDetectChangesEnabled = true;
- ProcessPictures(context, batch, srcToDestId);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessPictures");
- }
- finally
- {
- _categoryRepository.Context.AutoDetectChangesEnabled = false;
- }
- }
- }
-
- // map parent id of inserted categories
- if (srcToDestId.Any() && segmenter.HasColumn("Id") && segmenter.HasColumn("ParentCategoryId"))
- {
- segmenter.Reset();
-
- while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch())
- {
- var batch = segmenter.CurrentBatch;
-
- _categoryRepository.Context.DetachAll(false);
-
- try
- {
- ProcessParentMappings(context, batch, srcToDestId);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessParentMappings");
- }
- }
- }
- }
+ public int DestinationId { get; set; }
+ public bool Inserted { get; set; }
}
}
-
- internal class ImportCategoryMapping
- {
- public int DestinationId { get; set; }
- public bool Inserted { get; set; }
- }
}
diff --git a/src/Libraries/SmartStore.Services/Catalog/Importer/ProductImporter.cs b/src/Libraries/SmartStore.Services/Catalog/Importer/ProductImporter.cs
index c63ea1fcf9..6228f5b443 100644
--- a/src/Libraries/SmartStore.Services/Catalog/Importer/ProductImporter.cs
+++ b/src/Libraries/SmartStore.Services/Catalog/Importer/ProductImporter.cs
@@ -3,17 +3,15 @@
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Linq.Expressions;
using SmartStore.Core.Async;
using SmartStore.Core.Data;
using SmartStore.Core.Domain.Catalog;
using SmartStore.Core.Domain.DataExchange;
-using SmartStore.Core.Domain.Seo;
using SmartStore.Core.Events;
using SmartStore.Services.DataExchange.Import;
using SmartStore.Services.Localization;
using SmartStore.Services.Media;
-using SmartStore.Services.Seo;
-using SmartStore.Services.Stores;
using SmartStore.Utilities;
namespace SmartStore.Services.Catalog.Importer
@@ -23,7 +21,6 @@ public class ProductImporter : EntityImporterBase
private readonly IRepository _productPictureRepository;
private readonly IRepository _productManufacturerRepository;
private readonly IRepository _productCategoryRepository;
- private readonly IRepository _urlRecordRepository;
private readonly IRepository _productRepository;
private readonly ICommonServices _services;
private readonly ILocalizedEntityService _localizedEntityService;
@@ -31,18 +28,24 @@ public class ProductImporter : EntityImporterBase
private readonly IManufacturerService _manufacturerService;
private readonly ICategoryService _categoryService;
private readonly IProductService _productService;
- private readonly IUrlRecordService _urlRecordService;
private readonly IProductTemplateService _productTemplateService;
- private readonly IStoreMappingService _storeMappingService;
private readonly FileDownloadManager _fileDownloadManager;
- private readonly SeoSettings _seoSettings;
- private readonly DataExchangeSettings _dataExchangeSettings;
+
+ private static readonly Dictionary>> _localizableProperties = new Dictionary>>
+ {
+ { "Name", x => x.Name },
+ { "ShortDescription", x => x.ShortDescription },
+ { "FullDescription", x => x.FullDescription },
+ { "MetaKeywords", x => x.MetaKeywords },
+ { "MetaDescription", x => x.MetaDescription },
+ { "MetaTitle", x => x.MetaTitle },
+ { "BundleTitleText", x => x.BundleTitleText }
+ };
public ProductImporter(
IRepository productPictureRepository,
IRepository productManufacturerRepository,
IRepository productCategoryRepository,
- IRepository urlRecordRepository,
IRepository productRepository,
ICommonServices services,
ILocalizedEntityService localizedEntityService,
@@ -50,17 +53,12 @@ public ProductImporter(
IManufacturerService manufacturerService,
ICategoryService categoryService,
IProductService productService,
- IUrlRecordService urlRecordService,
IProductTemplateService productTemplateService,
- IStoreMappingService storeMappingService,
- FileDownloadManager fileDownloadManager,
- SeoSettings seoSettings,
- DataExchangeSettings dataExchangeSettings)
+ FileDownloadManager fileDownloadManager)
{
_productPictureRepository = productPictureRepository;
_productManufacturerRepository = productManufacturerRepository;
_productCategoryRepository = productCategoryRepository;
- _urlRecordRepository = urlRecordRepository;
_productRepository = productRepository;
_services = services;
_localizedEntityService = localizedEntityService;
@@ -68,30 +66,403 @@ public ProductImporter(
_manufacturerService = manufacturerService;
_categoryService = categoryService;
_productService = productService;
- _urlRecordService = urlRecordService;
_productTemplateService = productTemplateService;
- _storeMappingService = storeMappingService;
_fileDownloadManager = fileDownloadManager;
-
- _seoSettings = seoSettings;
- _dataExchangeSettings = dataExchangeSettings;
}
- private int? ZeroToNull(object value, CultureInfo culture)
+ protected override void Import(ImportExecuteContext context)
{
- int result;
- if (CommonHelper.TryConvert(value, culture, out result) && result > 0)
+ var srcToDestId = new Dictionary();
+
+ var templateViewPaths = _productTemplateService.GetAllProductTemplates().ToDictionarySafe(x => x.ViewPath, x => x.Id);
+
+ using (var scope = new DbContextScope(ctx: _productRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false))
{
- return result;
+ var segmenter = context.DataSegmenter;
+
+ Initialize(context);
+
+ while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch())
+ {
+ var batch = segmenter.GetCurrentBatch();
+
+ // Perf: detach all entities
+ _productRepository.Context.DetachAll(false);
+
+ context.SetProgress(segmenter.CurrentSegmentFirstRowIndex - 1, segmenter.TotalRows);
+
+ // ===========================================================================
+ // 1.) Import products
+ // ===========================================================================
+ try
+ {
+ ProcessProducts(context, batch, templateViewPaths, srcToDestId);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, 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).ToArray();
+
+ // update result object
+ context.Result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient);
+ context.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 (segmenter.HasColumn("SeName", true) || batch.Any(x => x.IsNew || x.NameChanged))
+ {
+ try
+ {
+ _productRepository.Context.AutoDetectChangesEnabled = true;
+ ProcessSlugs(context, batch, typeof(Product).Name);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessSlugs");
+ }
+ finally
+ {
+ _productRepository.Context.AutoDetectChangesEnabled = false;
+ }
+ }
+
+ // ===========================================================================
+ // 3.) Import StoreMappings
+ // ===========================================================================
+ if (segmenter.HasColumn("StoreIds"))
+ {
+ try
+ {
+ ProcessStoreMappings(context, batch);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessStoreMappings");
+ }
+ }
+
+ // ===========================================================================
+ // 4.) Import Localizations
+ // ===========================================================================
+ try
+ {
+ ProcessLocalizations(context, batch, _localizableProperties);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessLocalizations");
+ }
+
+ // ===========================================================================
+ // 5.) Import product category mappings
+ // ===========================================================================
+ if (segmenter.HasColumn("CategoryIds"))
+ {
+ try
+ {
+ ProcessProductCategories(context, batch);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessProductCategories");
+ }
+ }
+
+ // ===========================================================================
+ // 6.) Import product manufacturer mappings
+ // ===========================================================================
+ if (segmenter.HasColumn("ManufacturerIds"))
+ {
+ try
+ {
+ ProcessProductManufacturers(context, batch);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessProductManufacturers");
+ }
+ }
+
+ // ===========================================================================
+ // 7.) Import product picture mappings
+ // ===========================================================================
+ if (segmenter.HasColumn("ImageUrls"))
+ {
+ try
+ {
+ ProcessProductPictures(context, batch);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessProductPictures");
+ }
+ }
+ }
+
+ // ===========================================================================
+ // 8.) Map parent id of inserted products
+ // ===========================================================================
+ if (srcToDestId.Any() && segmenter.HasColumn("Id") && segmenter.HasColumn("ParentGroupedProductId") && !segmenter.IsIgnored("ParentGroupedProductId"))
+ {
+ segmenter.Reset();
+
+ while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch())
+ {
+ var batch = segmenter.GetCurrentBatch();
+
+ _productRepository.Context.DetachAll(false);
+
+ try
+ {
+ ProcessProductMappings(context, batch, srcToDestId);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessParentMappings");
+ }
+ }
+ }
}
+ }
- return (int?)null;
+ protected virtual int ProcessProducts(
+ ImportExecuteContext context,
+ IEnumerable> batch,
+ Dictionary templateViewPaths,
+ Dictionary srcToDestId)
+ {
+ _productRepository.AutoCommitEnabled = false;
+
+ Product lastInserted = null;
+ Product lastUpdated = null;
+ var defaultTemplateId = templateViewPaths["ProductTemplate.Simple"];
+
+ foreach (var row in batch)
+ {
+ Product product = null;
+ var id = row.GetDataValue("Id");
+
+ foreach (var keyName in context.KeyFieldNames)
+ {
+ var keyValue = row.GetDataValue(keyName);
+
+ if (keyValue.HasValue() || id > 0)
+ {
+ switch (keyName)
+ {
+ case "Id":
+ product = _productService.GetProductById(id);
+ break;
+ case "Sku":
+ product = _productService.GetProductBySku(keyValue);
+ break;
+ case "Gtin":
+ product = _productService.GetProductByGtin(keyValue);
+ break;
+ case "ManufacturerPartNumber":
+ product = _productService.GetProductByManufacturerPartNumber(keyValue);
+ break;
+ case "Name":
+ product = _productService.GetProductByName(keyValue);
+ break;
+ }
+ }
+
+ if (product != null)
+ break;
+ }
+
+ if (product == null)
+ {
+ if (context.UpdateOnly)
+ {
+ ++context.Result.SkippedRecords;
+ continue;
+ }
+
+ // a Name is required for new products.
+ if (!row.HasDataValue("Name"))
+ {
+ ++context.Result.SkippedRecords;
+ context.Result.AddError("The 'Name' field is required for new products. Skipping row.", row.GetRowInfo(), "Name");
+ continue;
+ }
+
+ product = new Product();
+ }
+
+ var name = row.GetDataValue("Name");
+
+ row.Initialize(product, name ?? product.Name);
+
+ if (!row.IsNew)
+ {
+ if (!product.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
+ {
+ // Perf: use this later for SeName updates.
+ row.NameChanged = true;
+ }
+ }
+
+ row.SetProperty(context.Result, (x) => x.ProductTypeId, (int)ProductType.SimpleProduct);
+ row.SetProperty(context.Result, (x) => x.VisibleIndividually, true);
+ row.SetProperty(context.Result, (x) => x.Name);
+ row.SetProperty(context.Result, (x) => x.ShortDescription);
+ row.SetProperty(context.Result, (x) => x.FullDescription);
+ row.SetProperty(context.Result, (x) => x.AdminComment);
+ row.SetProperty(context.Result, (x) => x.ShowOnHomePage);
+ row.SetProperty(context.Result, (x) => x.HomePageDisplayOrder);
+ row.SetProperty(context.Result, (x) => x.MetaKeywords);
+ row.SetProperty(context.Result, (x) => x.MetaDescription);
+ row.SetProperty(context.Result, (x) => x.MetaTitle);
+ row.SetProperty(context.Result, (x) => x.AllowCustomerReviews, true);
+ row.SetProperty(context.Result, (x) => x.ApprovedRatingSum);
+ row.SetProperty(context.Result, (x) => x.NotApprovedRatingSum);
+ row.SetProperty(context.Result, (x) => x.ApprovedTotalReviews);
+ row.SetProperty(context.Result, (x) => x.NotApprovedTotalReviews);
+ row.SetProperty(context.Result, (x) => x.Published, true);
+ row.SetProperty(context.Result, (x) => x.Sku);
+ row.SetProperty(context.Result, (x) => x.ManufacturerPartNumber);
+ row.SetProperty(context.Result, (x) => x.Gtin);
+ row.SetProperty(context.Result, (x) => x.IsGiftCard);
+ row.SetProperty(context.Result, (x) => x.GiftCardTypeId);
+ row.SetProperty(context.Result, (x) => x.RequireOtherProducts);
+ row.SetProperty(context.Result, (x) => x.RequiredProductIds); // TODO: global scope
+ row.SetProperty(context.Result, (x) => x.AutomaticallyAddRequiredProducts);
+ row.SetProperty(context.Result, (x) => x.IsDownload);
+ row.SetProperty(context.Result, (x) => x.DownloadId);
+ row.SetProperty(context.Result, (x) => x.UnlimitedDownloads, true);
+ row.SetProperty(context.Result, (x) => x.MaxNumberOfDownloads, 10);
+ row.SetProperty(context.Result, (x) => x.DownloadExpirationDays);
+ row.SetProperty(context.Result, (x) => x.DownloadActivationTypeId, 1);
+ row.SetProperty(context.Result, (x) => x.HasSampleDownload);
+ row.SetProperty(context.Result, (x) => x.SampleDownloadId, (int?)null, ZeroToNull); // TODO: global scope
+ row.SetProperty(context.Result, (x) => x.HasUserAgreement);
+ row.SetProperty(context.Result, (x) => x.UserAgreementText);
+ row.SetProperty(context.Result, (x) => x.IsRecurring);
+ row.SetProperty(context.Result, (x) => x.RecurringCycleLength, 100);
+ row.SetProperty(context.Result, (x) => x.RecurringCyclePeriodId);
+ row.SetProperty(context.Result, (x) => x.RecurringTotalCycles, 10);
+ row.SetProperty(context.Result, (x) => x.IsShipEnabled, true);
+ row.SetProperty(context.Result, (x) => x.IsFreeShipping);
+ row.SetProperty(context.Result, (x) => x.AdditionalShippingCharge);
+ row.SetProperty(context.Result, (x) => x.IsEsd);
+ row.SetProperty(context.Result, (x) => x.IsTaxExempt);
+ row.SetProperty(context.Result, (x) => x.TaxCategoryId, 1); // TODO: global scope
+ row.SetProperty(context.Result, (x) => x.ManageInventoryMethodId);
+ row.SetProperty(context.Result, (x) => x.StockQuantity, 10000);
+ row.SetProperty(context.Result, (x) => x.DisplayStockAvailability);
+ row.SetProperty(context.Result, (x) => x.DisplayStockQuantity);
+ row.SetProperty(context.Result, (x) => x.MinStockQuantity);
+ row.SetProperty(context.Result, (x) => x.LowStockActivityId);
+ row.SetProperty(context.Result, (x) => x.NotifyAdminForQuantityBelow, 1);
+ row.SetProperty(context.Result, (x) => x.BackorderModeId);
+ row.SetProperty(context.Result, (x) => x.AllowBackInStockSubscriptions);
+ row.SetProperty(context.Result, (x) => x.OrderMinimumQuantity, 1);
+ row.SetProperty(context.Result, (x) => x.OrderMaximumQuantity, 10000);
+ row.SetProperty(context.Result, (x) => x.AllowedQuantities);
+ row.SetProperty(context.Result, (x) => x.DisableBuyButton);
+ row.SetProperty(context.Result, (x) => x.DisableWishlistButton);
+ row.SetProperty(context.Result, (x) => x.AvailableForPreOrder);
+ row.SetProperty(context.Result, (x) => x.CallForPrice);
+ row.SetProperty(context.Result, (x) => x.Price);
+ row.SetProperty(context.Result, (x) => x.OldPrice);
+ row.SetProperty(context.Result, (x) => x.ProductCost);
+ row.SetProperty(context.Result, (x) => x.SpecialPrice);
+ row.SetProperty(context.Result, (x) => x.SpecialPriceStartDateTimeUtc);
+ row.SetProperty(context.Result, (x) => x.SpecialPriceEndDateTimeUtc);
+ row.SetProperty(context.Result, (x) => x.CustomerEntersPrice);
+ row.SetProperty(context.Result, (x) => x.MinimumCustomerEnteredPrice);
+ row.SetProperty(context.Result, (x) => x.MaximumCustomerEnteredPrice, 1000);
+ // HasTierPrices... ignore as long as no tier prices are imported
+ // LowestAttributeCombinationPrice... ignore as long as no combinations are imported
+ row.SetProperty(context.Result, (x) => x.Weight);
+ row.SetProperty(context.Result, (x) => x.Length);
+ row.SetProperty(context.Result, (x) => x.Width);
+ row.SetProperty(context.Result, (x) => x.Height);
+ row.SetProperty(context.Result, (x) => x.DisplayOrder);
+ row.SetProperty(context.Result, (x) => x.DeliveryTimeId); // TODO: global scope
+ row.SetProperty(context.Result, (x) => x.QuantityUnitId); // TODO: global scope
+ row.SetProperty(context.Result, (x) => x.BasePriceEnabled);
+ row.SetProperty(context.Result, (x) => x.BasePriceMeasureUnit);
+ row.SetProperty(context.Result, (x) => x.BasePriceAmount);
+ row.SetProperty(context.Result, (x) => x.BasePriceBaseAmount);
+ row.SetProperty(context.Result, (x) => x.BundleTitleText);
+ row.SetProperty(context.Result, (x) => x.BundlePerItemShipping);
+ row.SetProperty(context.Result, (x) => x.BundlePerItemPricing);
+ row.SetProperty(context.Result, (x) => x.BundlePerItemShoppingCart);
+ row.SetProperty(context.Result, (x) => x.AvailableStartDateTimeUtc);
+ row.SetProperty(context.Result, (x) => x.AvailableEndDateTimeUtc);
+ // With new entities, "LimitedToStores" is an implicit field, meaning
+ // it has to be set to true by code if it's absent but "StoreIds" exists.
+ row.SetProperty(context.Result, (x) => x.LimitedToStores, !row.GetDataValue>("StoreIds").IsNullOrEmpty());
+
+ string tvp;
+ if (row.TryGetDataValue("ProductTemplateViewPath", out tvp, row.IsTransient))
+ {
+ product.ProductTemplateId = (tvp.HasValue() && templateViewPaths.ContainsKey(tvp) ? templateViewPaths[tvp] : defaultTemplateId);
+ }
+
+ row.SetProperty(context.Result, (x) => x.CreatedOnUtc, UtcNow);
+ product.UpdatedOnUtc = UtcNow;
+
+ if (id != 0 && !srcToDestId.ContainsKey(id))
+ {
+ srcToDestId.Add(id, new ImportProductMapping { Inserted = row.IsTransient });
+ }
+
+ if (row.IsTransient)
+ {
+ _productRepository.Insert(product);
+ lastInserted = product;
+ }
+ else
+ {
+ _productRepository.Update(product);
+ lastUpdated = product;
+ }
+ }
+
+ // commit whole batch at once
+ var num = _productRepository.Context.SaveChanges();
+
+ // get new product ids
+ foreach (var row in batch)
+ {
+ var id = row.GetDataValue("Id");
+
+ if (id != 0 && srcToDestId.ContainsKey(id))
+ srcToDestId[id].DestinationId = row.Entity.Id;
+ }
+
+ // Perf: notify only about LAST insertion and update
+ if (lastInserted != null)
+ {
+ _services.EventPublisher.EntityInserted(lastInserted);
+ }
+
+ if (lastUpdated != null)
+ {
+ _services.EventPublisher.EntityUpdated(lastUpdated);
+ }
+
+ return num;
}
- private int ProcessProductMappings(IImportExecuteContext context,
- ImportRow[] batch,
+ protected virtual int ProcessProductMappings(
+ ImportExecuteContext context,
+ IEnumerable> batch,
Dictionary srcToDestId)
{
+ _productRepository.AutoCommitEnabled = false;
+
foreach (var row in batch)
{
var id = row.GetDataValue("Id");
@@ -106,7 +477,6 @@ private int ProcessProductMappings(IImportExecuteContext context,
if (product != null)
{
product.ParentGroupedProductId = srcToDestId[parentGroupedProductId].DestinationId;
-
_productRepository.Update(product);
}
}
@@ -118,18 +488,19 @@ private int ProcessProductMappings(IImportExecuteContext context,
return num;
}
- private void ProcessProductPictures(IImportExecuteContext context, ImportRow[] batch)
+ protected virtual void ProcessProductPictures(ImportExecuteContext context, IEnumerable> batch)
{
// true, cause pictures must be saved and assigned an id prior adding a mapping.
_productPictureRepository.AutoCommitEnabled = true;
ProductPicture lastInserted = null;
var equalPictureId = 0;
+ var numberOfPictures = (context.ExtraData.NumberOfPictures ?? int.MaxValue);
foreach (var row in batch)
{
var imageUrls = row.GetDataValue>("ImageUrls");
- if (imageUrls == null || !imageUrls.Any())
+ if (imageUrls.IsNullOrEmpty())
continue;
var imageNumber = 0;
@@ -144,6 +515,9 @@ private void ProcessProductPictures(IImportExecuteContext context, ImportRow= numberOfPictures)
+ break;
}
// download images
@@ -225,78 +599,7 @@ private void ProcessProductPictures(IImportExecuteContext context, ImportRow[] batch)
- {
- // true, cause pictures must be saved and assigned an id prior adding a mapping.
- _productPictureRepository.AutoCommitEnabled = true;
-
- ProductPicture lastInserted = null;
- var equalPictureId = 0;
-
- foreach (var row in batch)
- {
- var count = -1;
- var thumbPaths = row.GetDataValue>("PictureThumbPaths");
-
- if (thumbPaths == null)
- continue;
-
- foreach (var path in thumbPaths.Where(x => x.HasValue() && File.Exists(x)))
- {
- try
- {
- var currentProductPictures = _productPictureRepository.TableUntracked.Expand(x => x.Picture)
- .Where(x => x.ProductId == row.Entity.Id)
- .ToList();
-
- var currentPictures = currentProductPictures
- .Select(x => x.Picture)
- .ToList();
-
- if (count == -1)
- {
- count = (currentProductPictures.Any() ? currentProductPictures.Select(x => x.DisplayOrder).Max() : 0);
- }
-
- var pictureBinary = _pictureService.FindEqualPicture(path, currentPictures, out equalPictureId);
-
- if (pictureBinary != null && pictureBinary.Length > 0)
- {
- // no equal picture found in sequence
- var newPicture = _pictureService.InsertPicture(pictureBinary, "image/jpeg", _pictureService.GetPictureSeName(row.EntityDisplayName), true, false, false);
- if (newPicture != null)
- {
- var mapping = new ProductPicture
- {
- ProductId = row.Entity.Id,
- PictureId = newPicture.Id,
- DisplayOrder = ++count
- };
-
- _productPictureRepository.Insert(mapping);
- lastInserted = mapping;
- }
- }
- else
- {
- var idx = thumbPaths.IndexOf(path) + 1;
- context.Result.AddInfo("Found equal picture in data store. Skipping field.", row.GetRowInfo(), "PictureThumbPaths" + idx.ToString());
- }
- }
- catch (Exception exception)
- {
- var idx = thumbPaths.IndexOf(path) + 1;
- context.Result.AddWarning(exception.Message, row.GetRowInfo(), "PictureThumbPaths" + idx.ToString());
- }
- }
- }
-
- // Perf: notify only about LAST insertion and update
- if (lastInserted != null)
- _services.EventPublisher.EntityInserted(lastInserted);
- }
-
- private int ProcessProductManufacturers(IImportExecuteContext context, ImportRow[] batch)
+ protected virtual int ProcessProductManufacturers(ImportExecuteContext context, IEnumerable> batch)
{
_productManufacturerRepository.AutoCommitEnabled = false;
@@ -305,7 +608,7 @@ private int ProcessProductManufacturers(IImportExecuteContext context, ImportRow
foreach (var row in batch)
{
var manufacturerIds = row.GetDataValue>("ManufacturerIds");
- if (manufacturerIds != null && manufacturerIds.Any())
+ if (!manufacturerIds.IsNullOrEmpty())
{
try
{
@@ -347,7 +650,7 @@ private int ProcessProductManufacturers(IImportExecuteContext context, ImportRow
return num;
}
- private int ProcessProductCategories(IImportExecuteContext context, ImportRow[] batch)
+ protected virtual int ProcessProductCategories(ImportExecuteContext context, IEnumerable> batch)
{
_productCategoryRepository.AutoCommitEnabled = false;
@@ -356,7 +659,7 @@ private int ProcessProductCategories(IImportExecuteContext context, ImportRow>("CategoryIds");
- if (categoryIds != null && categoryIds.Any())
+ if (!categoryIds.IsNullOrEmpty())
{
try
{
@@ -398,334 +701,16 @@ private int ProcessProductCategories(IImportExecuteContext context, ImportRow[] batch)
- {
- foreach (var row in batch)
- {
- foreach (var lang in context.Languages)
- {
- var name = row.GetDataValue("Name", lang.UniqueSeoCode);
- var shortDescription = row.GetDataValue("ShortDescription", lang.UniqueSeoCode);
- var fullDescription = row.GetDataValue("FullDescription", lang.UniqueSeoCode);
- var metaKeywords = row.GetDataValue("MetaKeywords", lang.UniqueSeoCode);
- var metaDescription = row.GetDataValue("MetaDescription", lang.UniqueSeoCode);
- var metaTitle = row.GetDataValue("MetaTitle", lang.UniqueSeoCode);
- var bundleTitleText = row.GetDataValue("BundleTitleText", lang.UniqueSeoCode);
-
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.Name, name, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.ShortDescription, shortDescription, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.FullDescription, fullDescription, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaKeywords, metaKeywords, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaDescription, metaDescription, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaTitle, metaTitle, lang.Id);
- _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.BundleTitleText, bundleTitleText, lang.Id);
- }
- }
-
- // commit whole batch at once
- var num = _productManufacturerRepository.Context.SaveChanges();
-
- return num;
- }
-
- private int ProcessSlugs(IImportExecuteContext context, ImportRow[] batch)
- {
- var entityName = typeof(Product).Name;
- var slugMap = new Dictionary();
-
- Func slugLookup = ((s) =>
- {
- return (slugMap.ContainsKey(s) ? slugMap[s] : null);
- });
-
- foreach (var row in batch)
- {
- if (!row.IsNew && !row.NameChanged)
- continue;
-
- try
- {
- UrlRecord urlRecord = null;
- var seName = row.GetDataValue("SeName");
- seName = row.Entity.ValidateSeName(seName, row.Entity.Name, true, _urlRecordService, _seoSettings, extraSlugLookup: slugLookup);
-
- if (row.IsNew)
- {
- // dont't bother validating SeName for new entities.
- urlRecord = new UrlRecord
- {
- EntityId = row.Entity.Id,
- EntityName = entityName,
- Slug = seName,
- LanguageId = 0,
- IsActive = true,
- };
- _urlRecordRepository.Insert(urlRecord);
- }
- else
- {
- urlRecord = _urlRecordService.SaveSlug(row.Entity, seName, 0);
- }
-
- if (urlRecord != null)
- {
- // a new record was inserted to the store: keep track of it for this batch.
- slugMap[seName] = urlRecord;
- }
-
- foreach (var lang in context.Languages)
- {
- if (row.Segmenter.HasColumn("SeName", lang.UniqueSeoCode))
- {
- seName = row.GetDataValue("SeName", lang.UniqueSeoCode);
- seName = row.Entity.ValidateSeName(seName, null, false, _urlRecordService, _seoSettings, lang.Id, slugLookup);
-
- urlRecord = _urlRecordService.SaveSlug(row.Entity, seName, lang.Id);
-
- if (urlRecord != null)
- {
- slugMap[seName] = urlRecord;
- }
- }
- }
- }
- catch (Exception exception)
- {
- context.Result.AddWarning(exception.Message, row.GetRowInfo(), "SeName");
- }
- }
-
- // commit whole batch at once
- return _urlRecordRepository.Context.SaveChanges();
- }
- private void ProcessStoreMappings(IImportExecuteContext context, ImportRow[] batch)
- {
- foreach (var row in batch)
- {
- var limitedToStore = row.GetDataValue("LimitedToStores");
-
- if (limitedToStore)
- {
- var storeIds = row.GetDataValue>("StoreIds");
-
- _storeMappingService.SaveStoreMappings(row.Entity, storeIds == null ? new int[0] : storeIds.ToArray());
- }
- }
- }
-
- private int ProcessProducts(
- IImportExecuteContext context,
- ImportRow[] batch,
- Dictionary templateViewPaths,
- Dictionary srcToDestId)
+ private int? ZeroToNull(object value, CultureInfo culture)
{
- _productRepository.AutoCommitEnabled = true;
-
- Product lastInserted = null;
- Product lastUpdated = null;
- var defaultTemplateId = templateViewPaths["ProductTemplate.Simple"];
-
- foreach (var row in batch)
- {
- Product product = null;
- var id = row.GetDataValue("Id");
-
- foreach (var keyName in context.KeyFieldNames)
- {
- switch (keyName)
- {
- case "Id":
- product = _productService.GetProductById(id);
- break;
- case "Sku":
- product = _productService.GetProductBySku(row.GetDataValue("Sku"));
- break;
- case "Gtin":
- product = _productService.GetProductByGtin(row.GetDataValue("Gtin"));
- break;
- case "ManufacturerPartNumber":
- product = _productService.GetProductByManufacturerPartNumber(row.GetDataValue("ManufacturerPartNumber"));
- break;
- case "Name":
- product = _productService.GetProductByName(row.GetDataValue("Name"));
- break;
- }
-
- if (product != null)
- break;
- }
-
- if (product == null)
- {
- if (context.UpdateOnly)
- {
- ++context.Result.SkippedRecords;
- continue;
- }
-
- // a Name is required with new products.
- if (!row.Segmenter.HasColumn("Name"))
- {
- ++context.Result.SkippedRecords;
- context.Result.AddError("The 'Name' field is required for new products. Skipping row.", row.GetRowInfo(), "Name");
- continue;
- }
-
- product = new Product();
- }
-
- var name = row.GetDataValue("Name");
-
- row.Initialize(product, name);
-
- if (!row.IsNew)
- {
- if (!product.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
- {
- // Perf: use this later for SeName updates.
- row.NameChanged = true;
- }
- }
-
- row.SetProperty(context.Result, product, (x) => x.ProductTypeId, (int)ProductType.SimpleProduct);
- row.SetProperty(context.Result, product, (x) => x.VisibleIndividually, true);
- row.SetProperty(context.Result, product, (x) => x.Name);
- row.SetProperty(context.Result, product, (x) => x.ShortDescription);
- row.SetProperty(context.Result, product, (x) => x.FullDescription);
- row.SetProperty(context.Result, product, (x) => x.AdminComment);
- row.SetProperty(context.Result, product, (x) => x.ShowOnHomePage);
- row.SetProperty(context.Result, product, (x) => x.HomePageDisplayOrder);
- row.SetProperty(context.Result, product, (x) => x.MetaKeywords);
- row.SetProperty(context.Result, product, (x) => x.MetaDescription);
- row.SetProperty(context.Result, product, (x) => x.MetaTitle);
- row.SetProperty(context.Result, product, (x) => x.AllowCustomerReviews, true);
- row.SetProperty(context.Result, product, (x) => x.ApprovedRatingSum);
- row.SetProperty(context.Result, product, (x) => x.NotApprovedRatingSum);
- row.SetProperty(context.Result, product, (x) => x.ApprovedTotalReviews);
- row.SetProperty(context.Result, product, (x) => x.NotApprovedTotalReviews);
- row.SetProperty(context.Result, product, (x) => x.Published, true);
- row.SetProperty(context.Result, product, (x) => x.Sku);
- row.SetProperty(context.Result, product, (x) => x.ManufacturerPartNumber);
- row.SetProperty(context.Result, product, (x) => x.Gtin);
- row.SetProperty(context.Result, product, (x) => x.IsGiftCard);
- row.SetProperty(context.Result, product, (x) => x.GiftCardTypeId);
- row.SetProperty(context.Result, product, (x) => x.RequireOtherProducts);
- row.SetProperty(context.Result, product, (x) => x.RequiredProductIds); // TODO: global scope
- row.SetProperty(context.Result, product, (x) => x.AutomaticallyAddRequiredProducts);
- row.SetProperty(context.Result, product, (x) => x.IsDownload);
- row.SetProperty(context.Result, product, (x) => x.DownloadId);
- row.SetProperty(context.Result, product, (x) => x.UnlimitedDownloads, true);
- row.SetProperty(context.Result, product, (x) => x.MaxNumberOfDownloads, 10);
- row.SetProperty(context.Result, product, (x) => x.DownloadExpirationDays);
- row.SetProperty(context.Result, product, (x) => x.DownloadActivationTypeId, 1);
- row.SetProperty(context.Result, product, (x) => x.HasSampleDownload);
- row.SetProperty(context.Result, product, (x) => x.SampleDownloadId, (int?)null, ZeroToNull); // TODO: global scope
- row.SetProperty(context.Result, product, (x) => x.HasUserAgreement);
- row.SetProperty(context.Result, product, (x) => x.UserAgreementText);
- row.SetProperty(context.Result, product, (x) => x.IsRecurring);
- row.SetProperty(context.Result, product, (x) => x.RecurringCycleLength, 100);
- row.SetProperty(context.Result, product, (x) => x.RecurringCyclePeriodId);
- row.SetProperty(context.Result, product, (x) => x.RecurringTotalCycles, 10);
- row.SetProperty(context.Result, product, (x) => x.IsShipEnabled, true);
- row.SetProperty(context.Result, product, (x) => x.IsFreeShipping);
- row.SetProperty(context.Result, product, (x) => x.AdditionalShippingCharge);
- row.SetProperty(context.Result, product, (x) => x.IsEsd);
- row.SetProperty(context.Result, product, (x) => x.IsTaxExempt);
- row.SetProperty(context.Result, product, (x) => x.TaxCategoryId, 1); // TODO: global scope
- row.SetProperty(context.Result, product, (x) => x.ManageInventoryMethodId);
- row.SetProperty(context.Result, product, (x) => x.StockQuantity, 10000);
- row.SetProperty(context.Result, product, (x) => x.DisplayStockAvailability);
- row.SetProperty(context.Result, product, (x) => x.DisplayStockQuantity);
- row.SetProperty(context.Result, product, (x) => x.MinStockQuantity);
- row.SetProperty(context.Result, product, (x) => x.LowStockActivityId);
- row.SetProperty(context.Result, product, (x) => x.NotifyAdminForQuantityBelow, 1);
- row.SetProperty(context.Result, product, (x) => x.BackorderModeId);
- row.SetProperty(context.Result, product, (x) => x.AllowBackInStockSubscriptions);
- row.SetProperty(context.Result, product, (x) => x.OrderMinimumQuantity, 1);
- row.SetProperty(context.Result, product, (x) => x.OrderMaximumQuantity, 10000);
- row.SetProperty(context.Result, product, (x) => x.AllowedQuantities);
- row.SetProperty(context.Result, product, (x) => x.DisableBuyButton);
- row.SetProperty(context.Result, product, (x) => x.DisableWishlistButton);
- row.SetProperty(context.Result, product, (x) => x.AvailableForPreOrder);
- row.SetProperty(context.Result, product, (x) => x.CallForPrice);
- row.SetProperty(context.Result, product, (x) => x.Price);
- row.SetProperty(context.Result, product, (x) => x.OldPrice);
- row.SetProperty(context.Result, product, (x) => x.ProductCost);
- row.SetProperty(context.Result, product, (x) => x.SpecialPrice);
- row.SetProperty(context.Result, product, (x) => x.SpecialPriceStartDateTimeUtc);
- row.SetProperty(context.Result, product, (x) => x.SpecialPriceEndDateTimeUtc);
- row.SetProperty(context.Result, product, (x) => x.CustomerEntersPrice);
- row.SetProperty(context.Result, product, (x) => x.MinimumCustomerEnteredPrice);
- row.SetProperty(context.Result, product, (x) => x.MaximumCustomerEnteredPrice, 1000);
- // HasTierPrices... ignore as long as no tier prices are imported
- // LowestAttributeCombinationPrice... ignore as long as no combinations are imported
- row.SetProperty(context.Result, product, (x) => x.Weight);
- row.SetProperty(context.Result, product, (x) => x.Length);
- row.SetProperty(context.Result, product, (x) => x.Width);
- row.SetProperty(context.Result, product, (x) => x.Height);
- row.SetProperty(context.Result, product, (x) => x.DisplayOrder);
- row.SetProperty(context.Result, product, (x) => x.DeliveryTimeId); // TODO: global scope
- row.SetProperty(context.Result, product, (x) => x.QuantityUnitId); // TODO: global scope
- row.SetProperty(context.Result, product, (x) => x.BasePriceEnabled);
- row.SetProperty(context.Result, product, (x) => x.BasePriceMeasureUnit);
- row.SetProperty(context.Result, product, (x) => x.BasePriceAmount);
- row.SetProperty(context.Result, product, (x) => x.BasePriceBaseAmount);
- row.SetProperty(context.Result, product, (x) => x.BundleTitleText);
- row.SetProperty(context.Result, product, (x) => x.BundlePerItemShipping);
- row.SetProperty(context.Result, product, (x) => x.BundlePerItemPricing);
- row.SetProperty(context.Result, product, (x) => x.BundlePerItemShoppingCart);
- row.SetProperty(context.Result, product, (x) => x.AvailableStartDateTimeUtc);
- row.SetProperty(context.Result, product, (x) => x.AvailableEndDateTimeUtc);
- row.SetProperty(context.Result, product, (x) => x.LimitedToStores);
-
- var tvp = row.GetDataValue("ProductTemplateViewPath");
- product.ProductTemplateId = (tvp.HasValue() && templateViewPaths.ContainsKey(tvp) ? templateViewPaths[tvp] : defaultTemplateId);
-
- row.SetProperty(context.Result, product, (x) => x.CreatedOnUtc, UtcNow);
- product.UpdatedOnUtc = UtcNow;
-
- if (id != 0 && !srcToDestId.ContainsKey(id))
- {
- srcToDestId.Add(id, new ImportProductMapping { Inserted = row.IsTransient });
- }
-
- if (row.IsTransient)
- {
- _productRepository.Insert(product);
- lastInserted = product;
- }
- else
- {
- _productRepository.Update(product);
- lastUpdated = product;
- }
- }
-
- // commit whole batch at once
- var num = _productRepository.Context.SaveChanges();
-
- // get new product ids
- foreach (var row in batch)
- {
- var id = row.GetDataValue("Id");
-
- if (id != 0 && srcToDestId.ContainsKey(id))
- srcToDestId[id].DestinationId = row.Entity.Id;
- }
-
- // Perf: notify only about LAST insertion and update
- if (lastInserted != null)
- {
- _services.EventPublisher.EntityInserted(lastInserted);
- }
-
- if (lastUpdated != null)
+ int result;
+ if (CommonHelper.TryConvert(value, culture, out result) && result > 0)
{
- _services.EventPublisher.EntityUpdated(lastUpdated);
+ return result;
}
- return num;
+ return (int?)null;
}
public static string[] SupportedKeyFields
@@ -744,177 +729,10 @@ public static string[] DefaultKeyFields
}
}
- protected override void Import(IImportExecuteContext context)
+ public class ImportProductMapping
{
- var srcToDestId = new Dictionary();
-
- var templateViewPaths = _productTemplateService.GetAllProductTemplates().ToDictionarySafe(x => x.ViewPath, x => x.Id);
-
- using (var scope = new DbContextScope(ctx: _productRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false))
- {
- var segmenter = context.GetSegmenter();
-
- Init(context, _dataExchangeSettings);
-
- context.Result.TotalRecords = segmenter.TotalRows;
-
- while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch())
- {
- var batch = segmenter.CurrentBatch;
-
- // Perf: detach all entities
- _productRepository.Context.DetachAll(false);
-
- context.SetProgress(segmenter.CurrentSegmentFirstRowIndex - 1, segmenter.TotalRows);
-
- // ===========================================================================
- // 1.) Import products
- // ===========================================================================
- try
- {
- ProcessProducts(context, batch, templateViewPaths, srcToDestId);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, 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).ToArray();
-
- // update result object
- context.Result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient);
- context.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 (segmenter.HasColumn("SeName") || batch.Any(x => x.IsNew || x.NameChanged))
- {
- try
- {
- _productRepository.Context.AutoDetectChangesEnabled = true;
- ProcessSlugs(context, batch);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessSlugs");
- }
- finally
- {
- _productRepository.Context.AutoDetectChangesEnabled = false;
- }
- }
-
- if (segmenter.HasColumn("LimitedToStores") && segmenter.HasColumn("StoreIds"))
- {
- try
- {
- _productRepository.Context.AutoDetectChangesEnabled = true;
- ProcessStoreMappings(context, batch);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessStoreMappings");
- }
- finally
- {
- _productRepository.Context.AutoDetectChangesEnabled = false;
- }
- }
-
- // ===========================================================================
- // 3.) Import Localizations
- // ===========================================================================
- try
- {
- ProcessLocalizations(context, batch);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessLocalizations");
- }
-
- // ===========================================================================
- // 4.) Import product category mappings
- // ===========================================================================
- if (segmenter.HasColumn("CategoryIds"))
- {
- try
- {
- ProcessProductCategories(context, batch);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessProductCategories");
- }
- }
-
- // ===========================================================================
- // 5.) Import product manufacturer mappings
- // ===========================================================================
- if (segmenter.HasColumn("ManufacturerIds"))
- {
- try
- {
- ProcessProductManufacturers(context, batch);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessProductManufacturers");
- }
- }
-
- // ===========================================================================
- // 6.) Import product picture mappings
- // ===========================================================================
- if (segmenter.HasColumn("ImageUrls"))
- {
- try
- {
- ProcessProductPictures(context, batch);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessProductPictures");
- }
- }
- }
-
- // ===========================================================================
- // 7.) Map parent id of inserted products
- // ===========================================================================
- if (srcToDestId.Any() && segmenter.HasColumn("Id") && segmenter.HasColumn("ParentGroupedProductId"))
- {
- segmenter.Reset();
-
- while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch())
- {
- var batch = segmenter.CurrentBatch;
-
- _productRepository.Context.DetachAll(false);
-
- try
- {
- ProcessProductMappings(context, batch, srcToDestId);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessParentMappings");
- }
- }
- }
- }
+ public int DestinationId { get; set; }
+ public bool Inserted { get; set; }
}
}
-
-
- internal class ImportProductMapping
- {
- public int DestinationId { get; set; }
- public bool Inserted { get; set; }
- }
}
diff --git a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs
index 7a06368334..ca45f495d7 100644
--- a/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs
+++ b/src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs
@@ -251,6 +251,12 @@ protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationC
if (selectedCombination != null && selectedCombination.IsActive && selectedCombination.Price.HasValue)
{
product.MergedDataValues = new Dictionary { { "Price", selectedCombination.Price.Value } };
+
+ if (selectedCombination.BasePriceAmount.HasValue)
+ product.MergedDataValues.Add("BasePriceAmount", selectedCombination.BasePriceAmount.Value);
+
+ if (selectedCombination.BasePriceBaseAmount.HasValue)
+ product.MergedDataValues.Add("BasePriceBaseAmount", selectedCombination.BasePriceBaseAmount.Value);
}
}
@@ -758,10 +764,12 @@ public virtual decimal GetUnitPrice(OrganizedShoppingCartItem shoppingCartItem,
var attributesTotalPrice = decimal.Zero;
- var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.Item.AttributesXml).ToList();
+ var pvaValuesEnum = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.Item.AttributesXml);
- if (pvaValues != null)
+ if (pvaValuesEnum != null)
{
+ var pvaValues = pvaValuesEnum.ToList();
+
foreach (var pvaValue in pvaValues)
{
attributesTotalPrice += GetProductVariantAttributeValuePriceAdjustment(pvaValue);
diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs
index 23ee794f0b..cf4531f322 100644
--- a/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs
+++ b/src/Libraries/SmartStore.Services/Catalog/ProductAttributeParser.cs
@@ -13,14 +13,13 @@
using SmartStore.Core.Caching;
using SmartStore.Core.Data;
using SmartStore.Core.Domain.Catalog;
-using SmartStore.Services.Localization;
namespace SmartStore.Services.Catalog
{
- ///
- /// Product attribute parser
- ///
- public partial class ProductAttributeParser : IProductAttributeParser
+ ///
+ /// Product attribute parser
+ ///
+ public partial class ProductAttributeParser : IProductAttributeParser
{
// 0 = ProductId, 1 = AttributeXml Hash
private const string ATTRIBUTECOMBINATION_BY_ID_HASH = "SmartStore.parsedattributecombination.id-{0}-{1}";
@@ -194,21 +193,20 @@ where id.HasValue()
return values;
}
- public IList ParseProductVariantAttributeValues(string attributesXml, IEnumerable attributes, int languageId = 0)
+ public virtual IList ParseProductVariantAttributeValues(Multimap attributeCombination, IEnumerable attributes)
{
- var values = new List();
+ var result = new List();
- if (attributesXml.IsEmpty())
- return values;
+ if (attributeCombination == null || !attributeCombination.Any())
+ return result;
var allValueIds = new List();
- var combinedAttributes = DeserializeProductVariantAttributes(attributesXml);
foreach (var pva in attributes.Where(x => x.ShouldHaveValues()).OrderBy(x => x.DisplayOrder))
{
- if (combinedAttributes.ContainsKey(pva.Id))
+ if (attributeCombination.ContainsKey(pva.Id))
{
- var pvaValuesStr = combinedAttributes[pva.Id];
+ var pvaValuesStr = attributeCombination[pva.Id];
var ids = pvaValuesStr.Where(x => x.HasValue()).Select(x => x.ToInt());
allValueIds.AddRange(ids);
@@ -220,28 +218,24 @@ public IList ParseProductVariantAttributeValues(string attributesXml, IE
foreach (var attribute in attributes)
{
var attributeValue = attribute.ProductVariantAttributeValues.FirstOrDefault(x => x.Id == id);
- if (attributeValue != null)
+ if (attributeValue != null && !result.Any(x => x.Id == attributeValue.Id))
{
- var value = attributeValue.GetLocalized(x => x.Name, languageId, true, false);
-
- if (!values.Any(x => x.IsCaseInsensitiveEqual(value)))
- values.Add(value);
+ result.Add(attributeValue);
break;
}
}
}
- return values;
+ return result;
}
-
- ///
- /// Gets selected product variant attribute value
- ///
- /// Attributes
- /// Product variant attribute identifier
- /// Product variant attribute value
- public virtual IList ParseValues(string attributesXml, int productVariantAttributeId)
+ ///
+ /// Gets selected product variant attribute value
+ ///
+ /// Attributes
+ /// Product variant attribute identifier
+ /// Product variant attribute value
+ public virtual IList ParseValues(string attributesXml, int productVariantAttributeId)
{
var selectedProductVariantAttributeValues = new List();
try
@@ -374,15 +368,20 @@ public virtual ProductVariantAttributeCombination FindProductVariantAttributeCom
public virtual List> DeserializeQueryData(string jsonData)
{
- if (jsonData.HasValue())
+ try
{
- if (jsonData.StartsWith("["))
+ if (jsonData.HasValue())
{
- return JsonConvert.DeserializeObject>>(jsonData);
- }
+ if (jsonData.StartsWith("["))
+ {
+ return JsonConvert.DeserializeObject>>(jsonData);
+ }
- return new List> { JsonConvert.DeserializeObject>(jsonData) };
+ return new List> { JsonConvert.DeserializeObject>(jsonData) };
+ }
}
+ catch { }
+
return new List>();
}
diff --git a/src/Libraries/SmartStore.Services/Catalog/ProductExtensions.cs b/src/Libraries/SmartStore.Services/Catalog/ProductExtensions.cs
index 85b55cfb4f..051fc841f2 100644
--- a/src/Libraries/SmartStore.Services/Catalog/ProductExtensions.cs
+++ b/src/Libraries/SmartStore.Services/Catalog/ProductExtensions.cs
@@ -14,7 +14,7 @@
namespace SmartStore.Services.Catalog
{
- public static class ProductExtensions
+ public static class ProductExtensions
{
public static ProductVariantAttributeCombination MergeWithCombination(this Product product, string selectedAttributes)
{
@@ -299,7 +299,7 @@ public static int[] ParseRequiredProductIds(this Product product)
}
///
- /// Gets the base price
+ /// Gets the base price info
///
/// Product
/// Localization service
@@ -309,17 +309,23 @@ public static int[] ParseRequiredProductIds(this Product product)
/// Price calculation service
/// Target currency
/// Price adjustment
- /// Whether the result string should be language independent
- /// The base price
- public static string GetBasePriceInfo(this Product product, ILocalizationService localizationService, IPriceFormatter priceFormatter,
- ICurrencyService currencyService, ITaxService taxService, IPriceCalculationService priceCalculationService,
- Currency currency, decimal priceAdjustment = decimal.Zero, bool languageIndependent = false)
+ /// Whether the result string should be language insensitive
+ /// The base price info
+ public static string GetBasePriceInfo(this Product product,
+ ILocalizationService localizationService,
+ IPriceFormatter priceFormatter,
+ ICurrencyService currencyService,
+ ITaxService taxService,
+ IPriceCalculationService priceCalculationService,
+ Currency currency,
+ decimal priceAdjustment = decimal.Zero,
+ bool languageInsensitive = false)
{
- if (product == null)
- throw new ArgumentNullException("product");
-
- if (localizationService == null && !languageIndependent)
- throw new ArgumentNullException("localizationService");
+ Guard.ArgumentNotNull(() => product);
+ Guard.ArgumentNotNull(() => currencyService);
+ Guard.ArgumentNotNull(() => taxService);
+ Guard.ArgumentNotNull(() => priceCalculationService);
+ Guard.ArgumentNotNull(() => currency);
if (product.BasePriceHasValue && product.BasePriceAmount != Decimal.Zero)
{
@@ -327,24 +333,58 @@ public static string GetBasePriceInfo(this Product product, ILocalizationService
var taxrate = decimal.Zero;
var currentPrice = priceCalculationService.GetFinalPrice(product, workContext.CurrentCustomer, true);
- decimal price = taxService.GetProductPrice(product, decimal.Add(currentPrice, priceAdjustment), out taxrate);
+ var price = taxService.GetProductPrice(product, decimal.Add(currentPrice, priceAdjustment), out taxrate);
price = currencyService.ConvertFromPrimaryStoreCurrency(price, currency);
- decimal basePriceValue = Convert.ToDecimal((price / product.BasePriceAmount) * product.BasePriceBaseAmount);
+ return product.GetBasePriceInfo(price, localizationService, priceFormatter, currency, languageInsensitive);
+ }
- string basePrice = priceFormatter.FormatPrice(basePriceValue, true, currency);
- string unit = "{0} {1}".FormatWith(product.BasePriceBaseAmount, product.BasePriceMeasureUnit);
+ return "";
+ }
- if (languageIndependent)
- {
- return "{0} / {1}".FormatWith(basePrice, unit);
- }
+ ///
+ /// Gets the base price info
+ ///
+ /// Product
+ /// The calculated product price
+ /// Localization service
+ /// Price formatter
+ /// Target currency
+ /// Whether the result string should be language insensitive
+ /// The base price info
+ public static string GetBasePriceInfo(this Product product,
+ decimal productPrice,
+ ILocalizationService localizationService,
+ IPriceFormatter priceFormatter,
+ Currency currency,
+ bool languageInsensitive = false)
+ {
+ Guard.ArgumentNotNull(() => product);
+ Guard.ArgumentNotNull(() => localizationService);
+ Guard.ArgumentNotNull(() => priceFormatter);
+ Guard.ArgumentNotNull(() => currency);
+
+ if (product.BasePriceHasValue && product.BasePriceAmount != Decimal.Zero)
+ {
+ var value = Convert.ToDecimal((productPrice / product.BasePriceAmount) * product.BasePriceBaseAmount);
+ var valueFormatted = priceFormatter.FormatPrice(value, true, currency);
+ var amountFormatted = Math.Round(product.BasePriceAmount.Value, 2).ToString("G29");
+
+ var infoTemplate = localizationService.GetResource(languageInsensitive ? "Products.BasePriceInfo.LanguageInsensitive" : "Products.BasePriceInfo");
+
+ var result = infoTemplate.FormatInvariant(
+ amountFormatted,
+ product.BasePriceMeasureUnit,
+ valueFormatted,
+ product.BasePriceBaseAmount
+ );
+
+ return result;
+ }
- return localizationService.GetResource("Products.BasePriceInfo").FormatWith(basePrice, unit);
- }
return "";
- }
+ }
public static string GetProductTypeLabel(this Product product, ILocalizationService localizationService)
{
diff --git a/src/Libraries/SmartStore.Services/Common/AddressExtentions.cs b/src/Libraries/SmartStore.Services/Common/AddressExtentions.cs
index 73afed9723..1055aaa340 100644
--- a/src/Libraries/SmartStore.Services/Common/AddressExtentions.cs
+++ b/src/Libraries/SmartStore.Services/Common/AddressExtentions.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Collections.Generic;
using System.Text;
using SmartStore.Core.Domain.Common;
@@ -7,50 +8,13 @@ namespace SmartStore.Services.Common
{
public static class AddressExtentions
{
- ///
- /// Find an address
- ///
- /// Source
- /// First name
- /// Last name
- /// Phone number
- /// Email
- /// Fax number
- /// Company
- /// Address 1
- /// Address 2
- /// City
- /// State/province identifier
- /// Zip postal code
- /// Country identifier
- /// Address
- public static Address FindAddress(this List source,
- string firstName, string lastName, string phoneNumber,
- string email, string faxNumber, string company, string address1,
- string address2, string city, int? stateProvinceId,
- string zipPostalCode, int? countryId)
- {
- return source.Find((a) => ((String.IsNullOrEmpty(a.FirstName) && String.IsNullOrEmpty(firstName)) || a.FirstName == firstName) &&
- ((String.IsNullOrEmpty(a.LastName) && String.IsNullOrEmpty(lastName)) || a.LastName == lastName) &&
- ((String.IsNullOrEmpty(a.PhoneNumber) && String.IsNullOrEmpty(phoneNumber)) || a.PhoneNumber == phoneNumber) &&
- ((String.IsNullOrEmpty(a.Email) && String.IsNullOrEmpty(email)) || a.Email == email) &&
- ((String.IsNullOrEmpty(a.FaxNumber) && String.IsNullOrEmpty(faxNumber)) || a.FaxNumber == faxNumber) &&
- ((String.IsNullOrEmpty(a.Company) && String.IsNullOrEmpty(company)) || a.Company == company) &&
- ((String.IsNullOrEmpty(a.Address1) && String.IsNullOrEmpty(address1)) || a.Address1 == address1) &&
- ((String.IsNullOrEmpty(a.Address2) && String.IsNullOrEmpty(address2)) || a.Address2 == address2) &&
- ((String.IsNullOrEmpty(a.City) && String.IsNullOrEmpty(city)) || a.City == city) &&
- ((a.StateProvinceId.IsNullOrDefault() && stateProvinceId.IsNullOrDefault()) || a.StateProvinceId == stateProvinceId) &&
- ((String.IsNullOrEmpty(a.ZipPostalCode) && String.IsNullOrEmpty(zipPostalCode)) || a.ZipPostalCode == zipPostalCode) &&
- ((a.CountryId.IsNullOrDefault() && countryId.IsNullOrDefault()) || a.CountryId == countryId));
- }
-
///
- /// Find first occurrence of address
+ /// Find first occurrence of an address
///
/// Addresses to be searched
/// Address to find
/// First occurrence of address
- public static Address FindAddress(this List source, Address address)
+ public static Address FindAddress(this ICollection source, Address address)
{
return source.FindAddress(
address.FirstName,
@@ -68,6 +32,57 @@ public static Address FindAddress(this List source, Address address)
);
}
+ ///
+ /// Find an address
+ ///
+ /// Source
+ /// First name
+ /// Last name
+ /// Phone number
+ /// Email
+ /// Fax number
+ /// Company
+ /// Address 1
+ /// Address 2
+ /// City
+ /// State/province identifier
+ /// Zip postal code
+ /// Country identifier
+ /// Address
+ public static Address FindAddress(
+ this ICollection source,
+ string firstName,
+ string lastName,
+ string phoneNumber,
+ string email,
+ string faxNumber,
+ string company,
+ string address1,
+ string address2,
+ string city,
+ int? stateProvinceId,
+ string zipPostalCode,
+ int? countryId)
+ {
+ Func addressMatcher = (x) =>
+ {
+ return x.Email.IsCaseInsensitiveEqual(email)
+ && x.LastName.IsCaseInsensitiveEqual(lastName)
+ && x.FirstName.IsCaseInsensitiveEqual(firstName)
+ && x.Address1.IsCaseInsensitiveEqual(address1)
+ && x.Address2.IsCaseInsensitiveEqual(address2)
+ && x.Company.IsCaseInsensitiveEqual(company)
+ && x.ZipPostalCode.IsCaseInsensitiveEqual(zipPostalCode)
+ && x.City.IsCaseInsensitiveEqual(city)
+ && x.PhoneNumber.IsCaseInsensitiveEqual(phoneNumber)
+ && x.FaxNumber.IsCaseInsensitiveEqual(faxNumber)
+ && x.StateProvinceId == stateProvinceId
+ && x.CountryId == countryId;
+ };
+
+ return source.FirstOrDefault(addressMatcher);
+ }
+
/// Returns the full name of the address.
public static string GetFullName(this Address address)
{
diff --git a/src/Libraries/SmartStore.Services/Common/GenericAttributeService.cs b/src/Libraries/SmartStore.Services/Common/GenericAttributeService.cs
index d57222a18a..8f23424525 100644
--- a/src/Libraries/SmartStore.Services/Common/GenericAttributeService.cs
+++ b/src/Libraries/SmartStore.Services/Common/GenericAttributeService.cs
@@ -229,12 +229,12 @@ public virtual void SaveAttribute(int entityId, string key, string ke
{
if (string.IsNullOrWhiteSpace(valueStr))
{
- //delete
+ // delete
DeleteAttribute(prop);
}
else
{
- //update
+ // update
prop.Value = valueStr;
UpdateAttribute(prop);
}
@@ -243,7 +243,7 @@ public virtual void SaveAttribute(int entityId, string key, string ke
{
if (!string.IsNullOrWhiteSpace(valueStr))
{
- //insert
+ // insert
prop = new GenericAttribute
{
EntityId = entityId,
diff --git a/src/Libraries/SmartStore.Services/Common/UAParserUserAgent.cs b/src/Libraries/SmartStore.Services/Common/UAParserUserAgent.cs
index 060c127d3f..a6b8e24305 100644
--- a/src/Libraries/SmartStore.Services/Common/UAParserUserAgent.cs
+++ b/src/Libraries/SmartStore.Services/Common/UAParserUserAgent.cs
@@ -205,7 +205,8 @@ public virtual bool IsBot
{
if (!_isBot.HasValue)
{
- _isBot = _httpContext.Request.Browser.Crawler || this.Device.IsBot || this.UserAgent.IsBot;
+ // empty useragent > bad bot!
+ _isBot = this.RawValue.IsEmpty() || _httpContext.Request.Browser.Crawler || this.Device.IsBot || this.UserAgent.IsBot;
}
return _isBot.Value;
}
diff --git a/src/Libraries/SmartStore.Services/Customers/CustomerExtentions.cs b/src/Libraries/SmartStore.Services/Customers/CustomerExtentions.cs
index 719f144ed5..afc1acdbe0 100644
--- a/src/Libraries/SmartStore.Services/Customers/CustomerExtentions.cs
+++ b/src/Libraries/SmartStore.Services/Customers/CustomerExtentions.cs
@@ -53,7 +53,7 @@ public static bool IsBackgroundTaskAccount(this Customer customer)
}
///
- /// Gets a value indicating whether customer a search engine
+ /// Gets a value indicating whether customer is a search engine
///
/// Customer
/// Result
@@ -84,13 +84,13 @@ public static bool IsPdfConverter(this Customer customer)
return result;
}
- ///
- /// Gets a value indicating whether customer is administrator
- ///
- /// Customer
- /// A value indicating whether we should look only in active customer roles
- /// Result
- public static bool IsAdmin(this Customer customer, bool onlyActiveCustomerRoles = true)
+ ///
+ /// Gets a value indicating whether customer is administrator
+ ///
+ /// Customer
+ /// A value indicating whether we should look only in active customer roles
+ /// Result
+ public static bool IsAdmin(this Customer customer, bool onlyActiveCustomerRoles = true)
{
return IsInCustomerRole(customer, SystemCustomerRoleNames.Administrators, onlyActiveCustomerRoles);
}
@@ -287,14 +287,15 @@ public static int CountProductsInCart(this Customer customer, ShoppingCartType c
return count;
}
- public static List GetCartItems(this Customer customer, ShoppingCartType cartType, int? storeId = null, bool orderById = false)
+
+ public static List GetCartItems(this Customer customer, ShoppingCartType cartType, int? storeId = null)
{
var rawItems = customer.ShoppingCartItems.Filter(cartType, storeId);
- if (orderById)
- rawItems = rawItems.OrderByDescending(x => x.Id);
-
- var organizedItems = rawItems.ToList().Organize();
+ var organizedItems = rawItems
+ .OrderByDescending(x => x.Id)
+ .ToList()
+ .Organize();
return organizedItems.ToList();
}
diff --git a/src/Libraries/SmartStore.Services/Customers/CustomerService.cs b/src/Libraries/SmartStore.Services/Customers/CustomerService.cs
index 3e60ff4baa..d48fe10d6c 100644
--- a/src/Libraries/SmartStore.Services/Customers/CustomerService.cs
+++ b/src/Libraries/SmartStore.Services/Customers/CustomerService.cs
@@ -4,6 +4,7 @@
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
+using System.Web;
using SmartStore.Collections;
using SmartStore.Core;
using SmartStore.Core.Caching;
@@ -16,6 +17,7 @@
using SmartStore.Core.Domain.Shipping;
using SmartStore.Core.Events;
using SmartStore.Core.Localization;
+using SmartStore.Core.Fakes;
using SmartStore.Services.Common;
using SmartStore.Services.Localization;
@@ -26,9 +28,9 @@ namespace SmartStore.Services.Customers
///
public partial class CustomerService : ICustomerService
{
- #region Constants
+ #region Constants
- private const string CUSTOMERROLES_ALL_KEY = "SmartStore.customerrole.all-{0}";
+ 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.";
@@ -41,31 +43,38 @@ public partial class CustomerService : ICustomerService
private readonly IRepository _gaRepository;
private readonly IRepository _rewardPointsHistoryRepository;
private readonly IGenericAttributeService _genericAttributeService;
- private readonly ICacheManager _cacheManager;
- private readonly IEventPublisher _eventPublisher;
+ private readonly ICommonServices _services;
+ private readonly ICacheManager _cache;
private readonly RewardPointsSettings _rewardPointsSettings;
+ private readonly HttpContextBase _httpContext;
+ private readonly IUserAgent _userAgent;
- #endregion
+ #endregion
- #region Ctor
+ #region Ctor
- public CustomerService(ICacheManager cacheManager,
+ public CustomerService(
IRepository customerRepository,
IRepository customerRoleRepository,
IRepository gaRepository,
IRepository rewardPointsHistoryRepository,
IGenericAttributeService genericAttributeService,
- IEventPublisher eventPublisher,
- RewardPointsSettings rewardPointsSettings)
+ ICommonServices services,
+ ICacheManager cache,
+ RewardPointsSettings rewardPointsSettings,
+ HttpContextBase httpContext,
+ IUserAgent userAgent)
{
- this._cacheManager = cacheManager;
this._customerRepository = customerRepository;
this._customerRoleRepository = customerRoleRepository;
this._gaRepository = gaRepository;
this._rewardPointsHistoryRepository = rewardPointsHistoryRepository;
this._genericAttributeService = genericAttributeService;
- this._eventPublisher = eventPublisher;
+ this._services = services;
+ this._cache = cache;
this._rewardPointsSettings = rewardPointsSettings;
+ this._httpContext = httpContext;
+ this._userAgent = userAgent;
T = NullLocalizer.Instance;
}
@@ -332,6 +341,7 @@ orderby c.Id
where c.SystemName == systemName
select c;
var customer = query.FirstOrDefault();
+
return customer;
}
@@ -349,27 +359,62 @@ orderby c.Id
return customer;
}
- public virtual Customer InsertGuestCustomer()
+ public virtual Customer InsertGuestCustomer(Guid? customerGuid = null)
{
var customer = new Customer
{
- CustomerGuid = Guid.NewGuid(),
+ CustomerGuid = customerGuid ?? Guid.NewGuid(),
Active = true,
CreatedOnUtc = DateTime.UtcNow,
LastActivityDateUtc = DateTime.UtcNow,
};
- //add to 'Guests' role
+ // add to 'Guests' role
var guestRole = GetCustomerRoleBySystemName(SystemCustomerRoleNames.Guests);
if (guestRole == null)
throw new SmartException("'Guests' role could not be loaded");
customer.CustomerRoles.Add(guestRole);
- _customerRepository.Insert(customer);
+ _customerRepository.Insert(customer);
+
+ var clientIdent = _services.WebHelper.GetClientIdent();
+ if (clientIdent.HasValue())
+ {
+ //_genericAttributeService.SaveAttribute(customer, "ClientIdent", clientIdent);
+ }
return customer;
}
+
+ public virtual Customer FindGuestCustomerByClientIdent(string clientIdent = null, int maxAgeSeconds = 60)
+ {
+ if (_httpContext.IsFakeContext() || _userAgent.IsBot || _userAgent.IsPdfConverter)
+ {
+ return null;
+ }
+
+ clientIdent = clientIdent.NullEmpty() ?? _services.WebHelper.GetClientIdent();
+ if (clientIdent.IsEmpty())
+ {
+ return null;
+ }
+
+ var dateFrom = DateTime.UtcNow.AddSeconds(maxAgeSeconds * -1);
+
+ var query = from a in _gaRepository.TableUntracked
+ join c in _customerRepository.Table on a.EntityId equals c.Id into Customers
+ from c in Customers.DefaultIfEmpty()
+ where c.LastActivityDateUtc >= dateFrom
+ && c.Username == null
+ && c.Email == null
+ && a.KeyGroup == "Customer"
+ && a.Key == "ClientIdent"
+ && a.Value == clientIdent
+ select c;
+
+ return query.FirstOrDefault();
+ }
public virtual void InsertCustomer(Customer customer)
{
@@ -378,8 +423,7 @@ public virtual void InsertCustomer(Customer customer)
_customerRepository.Insert(customer);
- //event notification
- _eventPublisher.EntityInserted(customer);
+ _services.EventPublisher.EntityInserted(customer);
}
public virtual void UpdateCustomer(Customer customer)
@@ -389,8 +433,7 @@ public virtual void UpdateCustomer(Customer customer)
_customerRepository.Update(customer);
- //event notification
- _eventPublisher.EntityUpdated(customer);
+ _services.EventPublisher.EntityUpdated(customer);
}
public virtual void ResetCheckoutData(Customer customer, int storeId,
@@ -569,10 +612,9 @@ public virtual void DeleteCustomerRole(CustomerRole customerRole)
_customerRoleRepository.Delete(customerRole);
- _cacheManager.RemoveByPattern(CUSTOMERROLES_PATTERN_KEY);
+ _cache.RemoveByPattern(CUSTOMERROLES_PATTERN_KEY);
- //event notification
- _eventPublisher.EntityDeleted(customerRole);
+ _services.EventPublisher.EntityDeleted(customerRole);
}
public virtual CustomerRole GetCustomerRoleById(int customerRoleId)
@@ -589,7 +631,7 @@ public virtual CustomerRole GetCustomerRoleBySystemName(string systemName)
return null;
string key = string.Format(CUSTOMERROLES_BY_SYSTEMNAME_KEY, systemName);
- return _cacheManager.Get(key, () =>
+ return _cache.Get(key, () =>
{
var query = from cr in _customerRoleRepository.Table
orderby cr.Id
@@ -603,7 +645,7 @@ orderby cr.Id
public virtual IList GetAllCustomerRoles(bool showHidden = false)
{
string key = string.Format(CUSTOMERROLES_ALL_KEY, showHidden);
- return _cacheManager.Get(key, () =>
+ return _cache.Get(key, () =>
{
var query = from cr in _customerRoleRepository.Table
orderby cr.Name
@@ -621,10 +663,9 @@ public virtual void InsertCustomerRole(CustomerRole customerRole)
_customerRoleRepository.Insert(customerRole);
- _cacheManager.RemoveByPattern(CUSTOMERROLES_PATTERN_KEY);
+ _cache.RemoveByPattern(CUSTOMERROLES_PATTERN_KEY);
- //event notification
- _eventPublisher.EntityInserted(customerRole);
+ _services.EventPublisher.EntityInserted(customerRole);
}
public virtual void UpdateCustomerRole(CustomerRole customerRole)
@@ -634,10 +675,9 @@ public virtual void UpdateCustomerRole(CustomerRole customerRole)
_customerRoleRepository.Update(customerRole);
- _cacheManager.RemoveByPattern(CUSTOMERROLES_PATTERN_KEY);
+ _cache.RemoveByPattern(CUSTOMERROLES_PATTERN_KEY);
- //event notification
- _eventPublisher.EntityUpdated(customerRole);
+ _services.EventPublisher.EntityUpdated(customerRole);
}
#endregion
diff --git a/src/Libraries/SmartStore.Services/Customers/ICustomerService.cs b/src/Libraries/SmartStore.Services/Customers/ICustomerService.cs
index 0f7a914a77..57a2c6f8c9 100644
--- a/src/Libraries/SmartStore.Services/Customers/ICustomerService.cs
+++ b/src/Libraries/SmartStore.Services/Customers/ICustomerService.cs
@@ -125,14 +125,26 @@ IPagedList GetOnlineCustomers(DateTime lastActivityFromUtc,
///
/// Insert a guest customer
///
+ /// The customer GUID. Pass null to create a random one.
/// Customer
- Customer InsertGuestCustomer();
+ Customer InsertGuestCustomer(Guid? customerGuid = null);
- ///
- /// Insert a customer
- ///
- /// Customer
- void InsertCustomer(Customer customer);
+ ///
+ /// Tries to find a guest/anonymous customer record by client ident. This method should be called when an
+ /// anonymous visitor rejects cookies and therefore cannot be identified automatically.
+ ///
+ ///
+ /// The client ident string, which is a hashed combination of client IP address and user agent.
+ /// Call to obtain an ident string, or pass null to let this method obtain it automatically.
+ /// The max age of the newly created guest customer record. The shorter, the better (default is 1 min.)
+ /// The identified customer or null
+ Customer FindGuestCustomerByClientIdent(string clientIdent = null, int maxAgeSeconds = 60);
+
+ ///
+ /// Insert a customer
+ ///
+ /// Customer
+ void InsertCustomer(Customer customer);
///
/// Updates the customer
diff --git a/src/Libraries/SmartStore.Services/Customers/Importer/CustomerImporter.cs b/src/Libraries/SmartStore.Services/Customers/Importer/CustomerImporter.cs
index c50e3cad9d..452f281fb8 100644
--- a/src/Libraries/SmartStore.Services/Customers/Importer/CustomerImporter.cs
+++ b/src/Libraries/SmartStore.Services/Customers/Importer/CustomerImporter.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Linq.Expressions;
using SmartStore.Core.Async;
using SmartStore.Core.Data;
using SmartStore.Core.Domain.Common;
@@ -38,7 +39,6 @@ public class CustomerImporter : EntityImporterBase
private readonly CustomerSettings _customerSettings;
private readonly DateTimeSettings _dateTimeSettings;
private readonly ForumSettings _forumSettings;
- private readonly DataExchangeSettings _dataExchangeSettings;
public CustomerImporter(
IRepository customerRepository,
@@ -53,8 +53,7 @@ public CustomerImporter(
FileDownloadManager fileDownloadManager,
CustomerSettings customerSettings,
DateTimeSettings dateTimeSettings,
- ForumSettings forumSettings,
- DataExchangeSettings dataExchangeSettings)
+ ForumSettings forumSettings)
{
_customerRepository = customerRepository;
_pictureRepository = pictureRepository;
@@ -69,171 +68,363 @@ public CustomerImporter(
_customerSettings = customerSettings;
_dateTimeSettings = dateTimeSettings;
_forumSettings = forumSettings;
- _dataExchangeSettings = dataExchangeSettings;
}
- private int? CountryCodeToId(Dictionary allCountries, string code)
+
+ protected override void Import(ImportExecuteContext context)
{
- if (code.HasValue() && allCountries.ContainsKey(code))
+ var customer = _services.WorkContext.CurrentCustomer;
+ var allowManagingCustomerRoles = _services.Permissions.Authorize(StandardPermissionProvider.ManageCustomerRoles, customer);
+
+ var allAffiliateIds = _affiliateService.GetAllAffiliates(true)
+ .Select(x => x.Id)
+ .ToList();
+
+ var allCountries = new Dictionary();
+ foreach (var country in _countryService.GetAllCountries(true))
{
- var countryId = allCountries[code];
+ if (!allCountries.ContainsKey(country.TwoLetterIsoCode))
+ allCountries.Add(country.TwoLetterIsoCode, country.Id);
- if (countryId != 0)
- return countryId;
+ if (!allCountries.ContainsKey(country.ThreeLetterIsoCode))
+ allCountries.Add(country.ThreeLetterIsoCode, country.Id);
}
- return null;
- }
- private int? StateAbbreviationToId(Dictionary, int> allStateProvinces, int? countryId, string abbreviation)
- {
- if (countryId.HasValue && abbreviation.HasValue())
+ var allStateProvinces = _stateProvinceService.GetAllStateProvinces(true)
+ .ToDictionarySafe(x => new Tuple(x.CountryId, x.Abbreviation), x => x.Id);
+
+ var allCustomerNumbers = new HashSet(
+ _genericAttributeService.GetAttributes(SystemCustomerAttributeNames.CustomerNumber, _attributeKeyGroup).Select(x => x.Value),
+ StringComparer.OrdinalIgnoreCase);
+
+ using (var scope = new DbContextScope(ctx: _services.DbContext, autoDetectChanges: false, proxyCreation: false, validateOnSave: false, autoCommit: false))
{
- var key = Tuple.Create(countryId.Value, abbreviation);
+ var segmenter = context.DataSegmenter;
- if (allStateProvinces.ContainsKey(key))
+ Initialize(context);
+
+ while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch())
{
- var stateId = allStateProvinces[key];
+ var batch = segmenter.GetCurrentBatch();
- if (stateId != 0)
- return stateId;
- }
- }
- return null;
- }
+ _customerRepository.Context.DetachAll(false);
- private void SaveAttribute(ImportRow row, string key)
- {
- _genericAttributeService.SaveAttribute(row.Entity.Id, key, _attributeKeyGroup, row.GetDataValue(key));
- }
+ context.SetProgress(segmenter.CurrentSegmentFirstRowIndex - 1, segmenter.TotalRows);
- private void UpsertRole(ImportRow row, CustomerRole role, bool value)
- {
- if (role != null)
- {
- var hasRole = row.Entity.CustomerRoles.Any(x => x.SystemName == role.SystemName);
+ // ===========================================================================
+ // Process customers
+ // ===========================================================================
+ try
+ {
+ ProcessCustomers(context, batch, allAffiliateIds);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessCustomers");
+ }
+
+ // reduce batch to saved (valid) records.
+ // No need to perform import operations on errored records.
+ batch = batch.Where(x => x.Entity != null && !x.IsTransient).ToArray();
+
+ // update result object
+ context.Result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient);
+ context.Result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient);
+
+ // ===========================================================================
+ // Process generic attributes
+ // ===========================================================================
+ try
+ {
+ ProcessGenericAttributes(context, batch, allCountries, allStateProvinces, allCustomerNumbers);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessGenericAttributes");
+ }
+
+ // ===========================================================================
+ // Process avatars
+ // ===========================================================================
+ if (_customerSettings.AllowCustomersToUploadAvatars)
+ {
+ try
+ {
+ ProcessAvatars(context, batch);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessAvatars");
+ }
+ }
- if (value && !hasRole)
- row.Entity.CustomerRoles.Add(role);
- else if (!value && hasRole)
- row.Entity.CustomerRoles.Remove(role);
+ // ===========================================================================
+ // Process addresses
+ // ===========================================================================
+ try
+ {
+ _services.DbContext.AutoDetectChangesEnabled = true;
+ ProcessAddresses(context, batch, allCountries, allStateProvinces);
+ }
+ catch (Exception exception)
+ {
+ context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessAddresses");
+ }
+ finally
+ {
+ _services.DbContext.AutoDetectChangesEnabled = false;
+ }
+ }
}
}
- private void ImportAvatar(IImportExecuteContext context, ImportRow row)
+ protected virtual int ProcessCustomers(
+ ImportExecuteContext context,
+ IEnumerable> batch,
+ List allAffiliateIds)
{
- var urlOrPath = row.GetDataValue("AvatarPictureUrl");
- if (urlOrPath.IsEmpty())
- return;
+ _customerRepository.AutoCommitEnabled = true;
- Picture picture = null;
- var equalPictureId = 0;
- var currentPictures = new List();
- var seoName = _pictureService.GetPictureSeName(row.EntityDisplayName);
- var image = CreateDownloadImage(urlOrPath, seoName, 1);
+ Customer lastInserted = null;
+ Customer lastUpdated = null;
+ var currentCustomer = _services.WorkContext.CurrentCustomer;
- if (image == null)
- return;
+ var guestRole = _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Guests);
+ var registeredRole = _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Registered);
+ var forumModeratorRole = _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.ForumModerators);
- if (image.Url.HasValue() && !image.Success.HasValue)
- {
- AsyncRunner.RunSync(() => _fileDownloadManager.DownloadAsync(DownloaderContext, new FileDownloadManagerItem[] { image }));
- }
+ var customerQuery = _customerRepository.Table.Expand(x => x.Addresses);
- if ((image.Success ?? false) && File.Exists(image.Path))
+ foreach (var row in batch)
{
- Succeeded(image);
- var pictureBinary = File.ReadAllBytes(image.Path);
+ Customer customer = null;
+ var id = row.GetDataValue("Id");
+ var email = row.GetDataValue("Email");
- if (pictureBinary != null && pictureBinary.Length > 0)
+ foreach (var keyName in context.KeyFieldNames)
{
- var currentPictureId = row.Entity.GetAttribute(SystemCustomerAttributeNames.AvatarPictureId);
- if (currentPictureId != 0 && (picture = _pictureRepository.GetById(currentPictureId)) != null)
- currentPictures.Add(picture);
+ switch (keyName)
+ {
+ case "Id":
+ if (id != 0)
+ {
+ customer = customerQuery.FirstOrDefault(x => x.Id == id);
+ }
+ break;
+ case "CustomerGuid":
+ var customerGuid = row.GetDataValue("CustomerGuid");
+ if (customerGuid.HasValue())
+ {
+ var guid = new Guid(customerGuid);
+ customer = customerQuery.FirstOrDefault(x => x.CustomerGuid == guid);
+ }
+ break;
+ case "Email":
+ if (email.HasValue())
+ {
+ customer = customerQuery.FirstOrDefault(x => x.Email == email);
+ }
+ break;
+ case "Username":
+ var userName = row.GetDataValue("Username");
+ if (userName.HasValue())
+ {
+ customer = customerQuery.FirstOrDefault(x => x.Username == userName);
+ }
+ break;
+ }
- pictureBinary = _pictureService.ValidatePicture(pictureBinary);
- pictureBinary = _pictureService.FindEqualPicture(pictureBinary, currentPictures, out equalPictureId);
+ if (customer != null)
+ break;
+ }
- if (pictureBinary != null && pictureBinary.Length > 0)
+ if (customer == null)
+ {
+ if (context.UpdateOnly)
{
- if ((picture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, false, false)) != null)
- {
- _pictureRepository.Context.SaveChanges();
-
- _genericAttributeService.SaveAttribute(row.Entity.Id, SystemCustomerAttributeNames.AvatarPictureId, _attributeKeyGroup, picture.Id.ToString());
- }
+ ++context.Result.SkippedRecords;
+ continue;
}
- else
+
+ customer = new Customer
{
- context.Result.AddInfo("Found equal picture in data store. Skipping field.", row.GetRowInfo(), "AvatarPictureUrl");
- }
+ CustomerGuid = new Guid(),
+ AffiliateId = 0,
+ Active = true
+ };
+ }
+ else
+ {
+ _customerRepository.Context.LoadCollection(customer, (Customer x) => x.CustomerRoles);
+ }
+
+ var isGuest = row.GetDataValue("IsGuest");
+ var isRegistered = row.GetDataValue("IsRegistered");
+ var isAdmin = row.GetDataValue("IsAdministrator");
+ var isForumModerator = row.GetDataValue("IsForumModerator");
+ var affiliateId = row.GetDataValue("AffiliateId");
+
+ row.Initialize(customer, email ?? id.ToString());
+
+ row.SetProperty(context.Result, (x) => x.CustomerGuid);
+ row.SetProperty(context.Result, (x) => x.Username);
+ row.SetProperty(context.Result, (x) => x.Email);
+
+ if (email.HasValue() && currentCustomer.Email.IsCaseInsensitiveEqual(email))
+ {
+ context.Result.AddInfo("Security. Ignored password of current customer (who started this import).", row.GetRowInfo(), "Password");
+ }
+ else
+ {
+ row.SetProperty(context.Result, (x) => x.Password);
+ row.SetProperty(context.Result, (x) => x.PasswordFormatId);
+ row.SetProperty(context.Result, (x) => x.PasswordSalt);
+ }
+
+ row.SetProperty(context.Result, (x) => x.AdminComment);
+ row.SetProperty(context.Result, (x) => x.IsTaxExempt);
+ row.SetProperty(context.Result, (x) => x.Active);
+
+ row.SetProperty(context.Result, (x) => x.CreatedOnUtc, UtcNow);
+ row.SetProperty(context.Result, (x) => x.LastActivityDateUtc, UtcNow);
+
+ if (affiliateId > 0 && allAffiliateIds.Contains(affiliateId))
+ {
+ customer.AffiliateId = affiliateId;
+ }
+
+ if (isAdmin)
+ {
+ context.Result.AddInfo("Security. Ignored administrator role.", row.GetRowInfo(), "IsAdministrator");
+ }
+
+ UpsertRole(row, guestRole, isGuest);
+ UpsertRole(row, registeredRole, isRegistered);
+ UpsertRole(row, forumModeratorRole, isForumModerator);
+
+ if (row.IsTransient)
+ {
+ _customerRepository.Insert(customer);
+ lastInserted = customer;
+ }
+ else
+ {
+ _customerRepository.Update(customer);
+ lastUpdated = customer;
}
}
- else
+
+ var num = _customerRepository.Context.SaveChanges();
+
+ if (lastInserted != null)
{
- context.Result.AddInfo("Download of an image failed.", row.GetRowInfo(), "AvatarPictureUrl");
+ _services.EventPublisher.EntityInserted(lastInserted);
}
+
+ if (lastUpdated != null)
+ {
+ _services.EventPublisher.EntityUpdated(lastUpdated);
+ }
+
+ return num;
+ }
+
+ protected virtual int ProcessAddresses(
+ ImportExecuteContext context,
+ IEnumerable> batch,
+ Dictionary allCountries,
+ Dictionary, int> allStateProvinces)
+ {
+ foreach (var row in batch)
+ {
+ ImportAddress("BillingAddress.", row, context, allCountries, allStateProvinces);
+ ImportAddress("ShippingAddress.", row, context, allCountries, allStateProvinces);
+ }
+
+ return _services.DbContext.SaveChanges();
}
private void ImportAddress(
string fieldPrefix,
ImportRow row,
+ ImportExecuteContext context,
Dictionary allCountries,
Dictionary, int> allStateProvinces)
{
- // last name is mandatory for an address to be imported
- var lastName = row.GetDataValue(fieldPrefix + "LastName");
- if (lastName.IsEmpty())
+ // last name is mandatory for an address to be imported or updated
+ if (!row.HasDataValue(fieldPrefix + "LastName"))
return;
- var countryId = CountryCodeToId(allCountries, row.GetDataValue(fieldPrefix + "CountryCode"));
- var stateId = StateAbbreviationToId(allStateProvinces, countryId, row.GetDataValue(fieldPrefix + "StateAbbreviation"));
-
- var importAddress = new Address
+ var address = new Address
{
- FirstName = row.GetDataValue(fieldPrefix + "FirstName"),
- LastName = lastName,
- Email = row.GetDataValue(fieldPrefix + "Email"),
- Company = row.GetDataValue(fieldPrefix + "Company"),
- City = row.GetDataValue(fieldPrefix + "City"),
- Address1 = row.GetDataValue(fieldPrefix + "Address1"),
- Address2 = row.GetDataValue(fieldPrefix + "Address2"),
- ZipPostalCode = row.GetDataValue(fieldPrefix + "ZipPostalCode"),
- PhoneNumber = row.GetDataValue(fieldPrefix + "PhoneNumber"),
- FaxNumber = row.GetDataValue(fieldPrefix + "FaxNumber"),
- CreatedOnUtc = UtcNow,
- CountryId = countryId,
- StateProvinceId = stateId
+ CreatedOnUtc = UtcNow
};
- var appliedAddress = row.Entity.Addresses
- .ToList()
- .FindAddress(importAddress);
+ var childRow = new ImportRow(row.Segmenter, row.DataRow, row.Position);
+ childRow.Initialize(address, row.EntityDisplayName);
+
+ childRow.SetProperty(context.Result, fieldPrefix + "LastName", x => x.LastName);
+ childRow.SetProperty(context.Result, fieldPrefix + "FirstName", x => x.FirstName);
+ childRow.SetProperty(context.Result, fieldPrefix + "Email", x => x.Email);
+ childRow.SetProperty(context.Result, fieldPrefix + "Company", x => x.Company);
+ childRow.SetProperty(context.Result, fieldPrefix + "City", x => x.City);
+ childRow.SetProperty(context.Result, fieldPrefix + "Address1", x => x.Address1);
+ childRow.SetProperty(context.Result, fieldPrefix + "Address2", x => x.Address2);
+ childRow.SetProperty(context.Result, fieldPrefix + "ZipPostalCode", x => x.ZipPostalCode);
+ childRow.SetProperty(context.Result, fieldPrefix + "PhoneNumber", x => x.PhoneNumber);
+ childRow.SetProperty(context.Result, fieldPrefix + "FaxNumber", x => x.FaxNumber);
+
+ childRow.SetProperty(context.Result, fieldPrefix + "CountryId", x => x.CountryId);
+ if (childRow.Entity.CountryId == null)
+ {
+ // try with country code
+ childRow.SetProperty(context.Result, fieldPrefix + "CountryCode", x => x.CountryId, converter: (val, ci) => CountryCodeToId(allCountries, val.ToString()));
+ }
+
+ var countryId = childRow.Entity.CountryId;
+
+ if (countryId.HasValue)
+ {
+ childRow.SetProperty(context.Result, fieldPrefix + "StateProvinceId", x => x.StateProvinceId);
+ if (childRow.Entity.StateProvinceId == null)
+ {
+ // try with state abbreviation
+ childRow.SetProperty(context.Result, fieldPrefix + "StateAbbreviation", x => x.StateProvinceId, converter: (val, ci) => StateAbbreviationToId(allStateProvinces, countryId, val.ToString()));
+ }
+ }
+
+ if (!childRow.IsDirty)
+ {
+ // Not one single property could be set. Get out!
+ return;
+ }
+
+ var appliedAddress = row.Entity.Addresses.FindAddress(address);
if (appliedAddress == null)
{
- appliedAddress = importAddress;
+ appliedAddress = address;
row.Entity.Addresses.Add(appliedAddress);
}
- if (fieldPrefix.IsCaseInsensitiveEqual("BillTo"))
+ if (fieldPrefix == "BillingAddress.")
{
row.Entity.BillingAddress = appliedAddress;
}
- else if (fieldPrefix.IsCaseInsensitiveEqual("ShipTo"))
+ else if (fieldPrefix == "ShippingAddress.")
{
row.Entity.ShippingAddress = appliedAddress;
}
- _customerService.UpdateCustomer(row.Entity);
-
- _services.DbContext.SaveChanges();
+ _customerRepository.Update(row.Entity);
}
- private void ProcessGenericAttributes(IImportExecuteContext context,
- ImportRow[] batch,
+ protected virtual int ProcessGenericAttributes(
+ ImportExecuteContext context,
+ IEnumerable> batch,
Dictionary allCountries,
Dictionary, int> allStateProvinces,
- List allCustomerNumbers)
+ HashSet allCustomerNumbers)
{
foreach (var row in batch)
{
@@ -247,7 +438,7 @@ private void ProcessGenericAttributes(IImportExecuteContext context,
SaveAttribute(row, SystemCustomerAttributeNames.Gender);
if (_customerSettings.DateOfBirthEnabled)
- SaveAttribute(row, SystemCustomerAttributeNames.DateOfBirth);
+ SaveAttribute(row, SystemCustomerAttributeNames.DateOfBirth);
if (_customerSettings.CompanyEnabled)
SaveAttribute(row, SystemCustomerAttributeNames.Company);
@@ -265,10 +456,10 @@ private void ProcessGenericAttributes(IImportExecuteContext context,
SaveAttribute(row, SystemCustomerAttributeNames.City);
if (_customerSettings.CountryEnabled)
- SaveAttribute(row, SystemCustomerAttributeNames.CountryId);
+ SaveAttribute(row, SystemCustomerAttributeNames.CountryId);
if (_customerSettings.CountryEnabled && _customerSettings.StateProvinceEnabled)
- SaveAttribute(row, SystemCustomerAttributeNames.StateProvinceId);
+ SaveAttribute(row, SystemCustomerAttributeNames.StateProvinceId);
if (_customerSettings.PhoneEnabled)
SaveAttribute(row, SystemCustomerAttributeNames.Phone);
@@ -277,7 +468,7 @@ private void ProcessGenericAttributes(IImportExecuteContext context,
SaveAttribute(row, SystemCustomerAttributeNames.Fax);
if (_forumSettings.ForumsEnabled)
- SaveAttribute(row, SystemCustomerAttributeNames.ForumPostCount);
+ SaveAttribute(row, SystemCustomerAttributeNames.ForumPostCount);
if (_forumSettings.SignaturesEnabled)
SaveAttribute(row, SystemCustomerAttributeNames.Signature);
@@ -287,12 +478,12 @@ private void ProcessGenericAttributes(IImportExecuteContext context,
if (countryId.HasValue)
{
- _genericAttributeService.SaveAttribute(row.Entity.Id, SystemCustomerAttributeNames.CountryId, _attributeKeyGroup, countryId.Value);
+ SaveAttribute(row, SystemCustomerAttributeNames.CountryId, countryId.Value);
}
if (stateId.HasValue)
{
- _genericAttributeService.SaveAttribute(row.Entity.Id, SystemCustomerAttributeNames.StateProvinceId, _attributeKeyGroup, stateId.Value);
+ SaveAttribute(row, SystemCustomerAttributeNames.StateProvinceId, stateId.Value);
}
string customerNumber = null;
@@ -302,164 +493,79 @@ private void ProcessGenericAttributes(IImportExecuteContext context,
else
customerNumber = row.GetDataValue("CustomerNumber");
- if (customerNumber.IsEmpty() || !allCustomerNumbers.Any(x => x.IsCaseInsensitiveEqual(customerNumber)))
+ if (customerNumber.IsEmpty() || !allCustomerNumbers.Contains(customerNumber))
{
- _genericAttributeService.SaveAttribute(row.Entity.Id, SystemCustomerAttributeNames.CustomerNumber, _attributeKeyGroup, customerNumber);
+ SaveAttribute(row, SystemCustomerAttributeNames.CustomerNumber, customerNumber);
if (!customerNumber.IsEmpty())
allCustomerNumbers.Add(customerNumber);
}
-
- if (_customerSettings.AllowCustomersToUploadAvatars)
- {
- ImportAvatar(context, row);
- }
-
- _services.DbContext.SaveChanges();
}
+
+ return _services.DbContext.SaveChanges();
}
- private int ProcessCustomers(IImportExecuteContext context,
- ImportRow[] batch,
- List allAffiliateIds,
- IList allCustomerRoles)
+ protected virtual int ProcessAvatars(
+ ImportExecuteContext context,
+ IEnumerable> batch)
{
- _customerRepository.AutoCommitEnabled = true;
-
- Customer lastInserted = null;
- Customer lastUpdated = null;
- var currentCustomer = _services.WorkContext.CurrentCustomer;
-
- var guestRole = allCustomerRoles.FirstOrDefault(x => x.SystemName == SystemCustomerRoleNames.Guests);
- var registeredRole = allCustomerRoles.FirstOrDefault(x => x.SystemName == SystemCustomerRoleNames.Registered);
- var forumModeratorRole = allCustomerRoles.FirstOrDefault(x => x.SystemName == SystemCustomerRoleNames.ForumModerators);
-
foreach (var row in batch)
{
- if (row.GetDataValue("IsSystemAccount"))
- {
- ++context.Result.SkippedRecords;
- context.Result.AddInfo("Skipped system account.", row.GetRowInfo(), "IsSystemAccount");
+ var urlOrPath = row.GetDataValue("AvatarPictureUrl");
+ if (urlOrPath.IsEmpty())
continue;
- }
-
- Customer customer = null;
- var id = row.GetDataValue("Id");
- var email = row.GetDataValue("Email");
-
- foreach (var keyName in context.KeyFieldNames)
- {
- switch (keyName)
- {
- case "Id":
- customer = _customerService.GetCustomerById(id);
- break;
- case "CustomerGuid":
- var guid = row.GetDataValue("CustomerGuid");
- if (guid.HasValue())
- customer = _customerService.GetCustomerByGuid(new Guid(guid));
- break;
- case "Email":
- customer = _customerService.GetCustomerByEmail(email);
- break;
- case "Username":
- customer = _customerService.GetCustomerByUsername(row.GetDataValue("Username"));
- break;
- }
- if (customer != null)
- break;
- }
+ Picture picture = null;
+ var equalPictureId = 0;
+ var currentPictures = new List();
+ var seoName = _pictureService.GetPictureSeName(row.EntityDisplayName);
- if (customer == null)
- {
- if (context.UpdateOnly)
- {
- ++context.Result.SkippedRecords;
- continue;
- }
+ var image = CreateDownloadImage(urlOrPath, seoName, 1);
+ if (image == null)
+ continue;
- customer = new Customer
- {
- CustomerGuid = new Guid(),
- AffiliateId = 0,
- Active = true
- };
- }
- else
+ if (image.Url.HasValue() && !image.Success.HasValue)
{
- _customerRepository.Context.LoadCollection(customer, (Customer x) => x.CustomerRoles);
+ AsyncRunner.RunSync(() => _fileDownloadManager.DownloadAsync(DownloaderContext, new FileDownloadManagerItem[] { image }));
}
- var isGuest = row.GetDataValue("IsGuest");
- var isRegistered = row.GetDataValue("IsRegistered");
- var isAdmin = row.GetDataValue("IsAdministrator");
- var isForumModerator = row.GetDataValue("IsForumModerator");
- var affiliateId = row.GetDataValue("AffiliateId");
-
- row.Initialize(customer, email.HasValue() ? email : id.ToString());
-
- row.SetProperty(context.Result, customer, (x) => x.CustomerGuid);
- row.SetProperty(context.Result, customer, (x) => x.Username);
- row.SetProperty(context.Result, customer, (x) => x.Email);
-
- if (email.HasValue() && currentCustomer.Email.IsCaseInsensitiveEqual(email))
+ if ((image.Success ?? false) && File.Exists(image.Path))
{
- context.Result.AddInfo("Security. Ignored password of current customer (who started this import).", row.GetRowInfo(), "Password");
- }
- else
- {
- row.SetProperty(context.Result, customer, (x) => x.Password);
- row.SetProperty(context.Result, customer, (x) => x.PasswordFormatId);
- row.SetProperty(context.Result, customer, (x) => x.PasswordSalt);
- }
-
- row.SetProperty(context.Result, customer, (x) => x.AdminComment);
- row.SetProperty(context.Result, customer, (x) => x.IsTaxExempt);
- row.SetProperty(context.Result, customer, (x) => x.Active);
- row.SetProperty(context.Result, customer, (x) => x.IsSystemAccount);
- row.SetProperty(context.Result, customer, (x) => x.SystemName);
- row.SetProperty(context.Result, customer, (x) => x.LastIpAddress);
- row.SetProperty(context.Result, customer, (x) => x.LastLoginDateUtc);
- row.SetProperty(context.Result, customer, (x) => x.LastActivityDateUtc);
-
- row.SetProperty(context.Result, customer, (x) => x.CreatedOnUtc, UtcNow);
- row.SetProperty(context.Result, customer, (x) => x.LastActivityDateUtc, UtcNow);
+ Succeeded(image);
+ var pictureBinary = File.ReadAllBytes(image.Path);
- if (affiliateId > 0 && allAffiliateIds.Contains(affiliateId))
- {
- customer.AffiliateId = affiliateId;
- }
+ if (pictureBinary != null && pictureBinary.Length > 0)
+ {
+ var currentPictureId = row.Entity.GetAttribute(SystemCustomerAttributeNames.AvatarPictureId);
+ if (currentPictureId != 0 && (picture = _pictureRepository.GetById(currentPictureId)) != null)
+ {
+ currentPictures.Add(picture);
+ }
- if (isAdmin)
- {
- context.Result.AddInfo("Security. Ignored administrator role.", row.GetRowInfo(), "IsAdministrator");
- }
+ pictureBinary = _pictureService.ValidatePicture(pictureBinary);
+ pictureBinary = _pictureService.FindEqualPicture(pictureBinary, currentPictures, out equalPictureId);
- UpsertRole(row, guestRole, isGuest);
- UpsertRole(row, registeredRole, isRegistered);
- UpsertRole(row, forumModeratorRole, isForumModerator);
-
- if (row.IsTransient)
- {
- _customerRepository.Insert(customer);
- lastInserted = customer;
+ if (pictureBinary != null && pictureBinary.Length > 0)
+ {
+ if ((picture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, false, false)) != null)
+ {
+ _pictureRepository.Context.SaveChanges();
+ SaveAttribute(row, SystemCustomerAttributeNames.AvatarPictureId, picture.Id);
+ }
+ }
+ else
+ {
+ context.Result.AddInfo("Found equal picture in data store. Skipping field.", row.GetRowInfo(), "AvatarPictureUrl");
+ }
+ }
}
else
{
- _customerRepository.Update(customer);
- lastUpdated = customer;
+ context.Result.AddInfo("Download of an image failed.", row.GetRowInfo(), "AvatarPictureUrl");
}
}
- var num = _customerRepository.Context.SaveChanges();
-
- if (lastInserted != null)
- _services.EventPublisher.EntityInserted(lastInserted);
- if (lastUpdated != null)
- _services.EventPublisher.EntityUpdated(lastUpdated);
-
- return num;
+ return _services.DbContext.SaveChanges();
}
public static string[] SupportedKeyFields
@@ -478,104 +584,69 @@ public static string[] DefaultKeyFields
}
}
- protected override void Import(IImportExecuteContext context)
+ private int? CountryCodeToId(Dictionary allCountries, string code)
{
- var customer = _services.WorkContext.CurrentCustomer;
- var allowManagingCustomerRoles = _services.Permissions.Authorize(StandardPermissionProvider.ManageCustomerRoles, customer);
-
- var allCustomerRoles = _customerService.GetAllCustomerRoles(true);
-
- var allAffiliateIds = _affiliateService.GetAllAffiliates(true)
- .Select(x => x.Id)
- .ToList();
-
- var allCountries = new Dictionary();
- foreach (var country in _countryService.GetAllCountries(true))
+ int countryId;
+ if (code.HasValue() && allCountries.TryGetValue(code, out countryId) && countryId != 0)
{
- if (!allCountries.ContainsKey(country.TwoLetterIsoCode))
- allCountries.Add(country.TwoLetterIsoCode, country.Id);
-
- if (!allCountries.ContainsKey(country.ThreeLetterIsoCode))
- allCountries.Add(country.ThreeLetterIsoCode, country.Id);
+ return countryId;
}
- var allStateProvinces = _stateProvinceService.GetAllStateProvinces(true)
- .ToDictionarySafe(x => new Tuple(x.CountryId, x.Abbreviation), x => x.Id);
-
- var allCustomerNumbers = _genericAttributeService.GetAttributes(SystemCustomerAttributeNames.CustomerNumber, _attributeKeyGroup)
- .Select(x => x.Value)
- .ToList();
+ return null;
+ }
- using (var scope = new DbContextScope(ctx: _services.DbContext, autoDetectChanges: false, proxyCreation: false, validateOnSave: false, autoCommit: false))
+ private int? StateAbbreviationToId(Dictionary, int> allStateProvinces, int? countryId, string abbreviation)
+ {
+ if (countryId.HasValue && abbreviation.HasValue())
{
- var segmenter = context.GetSegmenter();
-
- Init(context, _dataExchangeSettings);
-
- context.Result.TotalRecords = segmenter.TotalRows;
+ var key = Tuple.Create(countryId.Value, abbreviation);
- while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch())
+ int stateId;
+ if (allStateProvinces.TryGetValue(key, out stateId) && stateId != 0)
{
- var batch = segmenter.CurrentBatch;
+ return stateId;
+ }
+ }
- _customerRepository.Context.DetachAll(false);
+ return null;
+ }
- context.SetProgress(segmenter.CurrentSegmentFirstRowIndex - 1, segmenter.TotalRows);
+ private void SaveAttribute(ImportRow row, string key)
+ {
+ SaveAttribute(row, key, row.GetDataValue(key));
+ }
- try
- {
- ProcessCustomers(context, batch, allAffiliateIds, allCustomerRoles);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessCustomers");
- }
+ private void SaveAttribute(ImportRow row, string key)
+ {
- // reduce batch to saved (valid) records.
- // No need to perform import operations on errored records.
- batch = batch.Where(x => x.Entity != null && !x.IsTransient).ToArray();
+ SaveAttribute(row, key, row.GetDataValue(key));
+ }
- // update result object
- context.Result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient);
- context.Result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient);
+ private void SaveAttribute(ImportRow row, string key, TPropType value)
+ {
+ if (row.IsTransient)
+ return;
- try
- {
- _services.DbContext.AutoDetectChangesEnabled = true;
+ if (row.IsNew || value != null)
+ {
+ _genericAttributeService.SaveAttribute(row.Entity.Id, key, _attributeKeyGroup, value);
+ }
+ }
- ProcessGenericAttributes(context, batch, allCountries, allStateProvinces, allCustomerNumbers);
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessGenericAttributes");
- }
- finally
- {
- _services.DbContext.AutoDetectChangesEnabled = false;
- }
+ private void UpsertRole(ImportRow row, CustomerRole role, bool value)
+ {
+ if (role == null)
+ return;
- if (segmenter.HasColumn("BillToLastName") || segmenter.HasColumn("ShipToLastName"))
- {
- try
- {
- _services.DbContext.AutoDetectChangesEnabled = true;
+ var hasRole = row.Entity.CustomerRoles.Any(x => x.SystemName == role.SystemName);
- foreach (var row in batch)
- {
- ImportAddress("BillTo", row, allCountries, allStateProvinces);
- ImportAddress("ShipTo", row, allCountries, allStateProvinces);
- }
- }
- catch (Exception exception)
- {
- context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessAddresses");
- }
- finally
- {
- _services.DbContext.AutoDetectChangesEnabled = false;
- }
- }
- }
+ if (value && !hasRole)
+ {
+ row.Entity.CustomerRoles.Add(role);
+ }
+ else if (!value && hasRole)
+ {
+ row.Entity.CustomerRoles.Remove(role);
}
}
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Csv/CsvWriter.cs b/src/Libraries/SmartStore.Services/DataExchange/Csv/CsvWriter.cs
index 83eee20228..8bb9942052 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Csv/CsvWriter.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Csv/CsvWriter.cs
@@ -51,7 +51,7 @@ public CsvConfiguration Configuration
/// to complete writing of the current row.
///
/// The fields to write.
- public virtual void WriteFields(string[] fields)
+ public virtual void WriteFields(IEnumerable fields)
{
Guard.ArgumentNotNull(() => fields);
fields.Each(x => WriteField(x));
@@ -69,7 +69,7 @@ public virtual void WriteFields(string[] fields)
///
/// The fields to write.
/// True to quote the fields, otherwise false.
- public virtual void WriteFields(string[] fields, bool shouldQuote)
+ public virtual void WriteFields(IEnumerable fields, bool shouldQuote)
{
Guard.ArgumentNotNull(() => fields);
fields.Each(x => WriteField(x, shouldQuote));
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Deployment/FileSystemFilePublisher.cs b/src/Libraries/SmartStore.Services/DataExchange/Deployment/FileSystemFilePublisher.cs
deleted file mode 100644
index fb9750120f..0000000000
--- a/src/Libraries/SmartStore.Services/DataExchange/Deployment/FileSystemFilePublisher.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System.IO;
-using System.Web;
-using SmartStore.Core.Domain;
-using SmartStore.Core.Logging;
-using SmartStore.Utilities;
-
-namespace SmartStore.Services.DataExchange.Export.Deployment
-{
- public class FileSystemFilePublisher : IFilePublisher
- {
- public virtual void Publish(ExportDeploymentContext context, ExportDeployment deployment)
- {
- string folderDestination = null;
-
- if (deployment.IsPublic)
- {
- folderDestination = Path.Combine(HttpRuntime.AppDomainAppPath, DataExporter.PublicFolder);
- }
- else if (deployment.FileSystemPath.IsEmpty())
- {
- return;
- }
- else if (deployment.FileSystemPath.StartsWith("/") || deployment.FileSystemPath.StartsWith("\\") || !Path.IsPathRooted(deployment.FileSystemPath))
- {
- folderDestination = CommonHelper.MapPath(deployment.FileSystemPath);
- }
- else
- {
- folderDestination = deployment.FileSystemPath;
- }
-
- if (!System.IO.Directory.Exists(folderDestination))
- {
- System.IO.Directory.CreateDirectory(folderDestination);
- }
-
- if (deployment.CreateZip)
- {
- var path = Path.Combine(folderDestination, deployment.Profile.FolderName + ".zip");
-
- if (FileSystemHelper.Copy(context.ZipPath, path))
- context.Log.Information("Copied ZIP archive " + path);
- }
- else
- {
- FileSystemHelper.CopyDirectory(new DirectoryInfo(context.FolderContent), new DirectoryInfo(folderDestination));
-
- context.Log.Information("Copied export data files to " + folderDestination);
- }
- }
- }
-}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Deployment/IFilePublisher.cs b/src/Libraries/SmartStore.Services/DataExchange/Deployment/IFilePublisher.cs
deleted file mode 100644
index 25ffddcaa7..0000000000
--- a/src/Libraries/SmartStore.Services/DataExchange/Deployment/IFilePublisher.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using SmartStore.Core.Domain;
-using SmartStore.Core.Logging;
-
-namespace SmartStore.Services.DataExchange.Export.Deployment
-{
- public interface IFilePublisher
- {
- void Publish(ExportDeploymentContext context, ExportDeployment deployment);
- }
-
-
- public class ExportDeploymentContext
- {
- public ILogger Log { get; set; }
-
- public string[] DeploymentFiles { get; set; }
-
- public string FolderContent { get; set; }
-
- public string ZipPath { get; set; }
- }
-}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Excel/ExcelDataReader.cs b/src/Libraries/SmartStore.Services/DataExchange/Excel/ExcelDataReader.cs
index d5eb02d5a9..d46879193c 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Excel/ExcelDataReader.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Excel/ExcelDataReader.cs
@@ -6,8 +6,6 @@
using System.Globalization;
using System.IO;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using OfficeOpenXml;
namespace SmartStore.Services.DataExchange.Excel
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/DataExportResult.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/DataExportResult.cs
index d7e0d9fa6a..c9d3fa26f2 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Export/DataExportResult.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/DataExportResult.cs
@@ -37,17 +37,11 @@ public bool Succeeded
[XmlIgnore]
public string FileFolder { get; set; }
- ///
- /// Suggested download file name
- ///
- [XmlIgnore]
- public string DownloadFileName { get; set; }
-
[Serializable]
public class ExportFileInfo
{
///
- /// Store identifier
+ /// Store identifier, can be 0.
///
public int StoreId { get; set; }
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/DataExporter.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/DataExporter.cs
index 09d444655a..e6b182c270 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Export/DataExporter.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/DataExporter.cs
@@ -61,7 +61,8 @@ public partial class DataExporter : IDataExporter
private readonly Lazy _productAttributeParser;
private readonly Lazy _productAttributeService;
private readonly Lazy _productTemplateService;
- private readonly Lazy _productService;
+ private readonly Lazy _categoryTemplateService;
+ private readonly Lazy _productService;
private readonly Lazy _orderService;
private readonly Lazy _manufacturerService;
private readonly ICustomerService _customerService;
@@ -101,6 +102,7 @@ public DataExporter(
Lazy productAttributeParser,
Lazy productAttributeService,
Lazy productTemplateService,
+ Lazy categoryTemplateService,
Lazy productService,
Lazy orderService,
Lazy manufacturerService,
@@ -138,6 +140,7 @@ public DataExporter(
_productAttributeParser = productAttributeParser;
_productAttributeService = productAttributeService;
_productTemplateService = productTemplateService;
+ _categoryTemplateService = categoryTemplateService;
_productService = productService;
_orderService = orderService;
_manufacturerService = manufacturerService;
@@ -182,9 +185,7 @@ private void SetProgress(DataExporterContext ctx, int loadedRecords)
totalRecords = ctx.Request.Profile.Limit;
ctx.RecordCount = Math.Min(ctx.RecordCount + loadedRecords, totalRecords);
-
var msg = ctx.ProgressInfo.FormatInvariant(ctx.RecordCount, totalRecords);
-
ctx.Request.ProgressValueSetter.Invoke(ctx.RecordCount, totalRecords, msg);
}
}
@@ -275,17 +276,14 @@ private void DetachAllEntitiesAndClear(DataExporterContext ctx)
private IExportDataSegmenterProvider CreateSegmenter(DataExporterContext ctx, int pageIndex = 0)
{
var offset = Math.Max(ctx.Request.Profile.Offset, 0) + (pageIndex * PageSize);
-
var limit = (ctx.IsPreview ? PageSize : Math.Max(ctx.Request.Profile.Limit, 0));
-
var recordsPerSegment = (ctx.IsPreview ? 0 : Math.Max(ctx.Request.Profile.BatchSize, 0));
-
var totalCount = Math.Max(ctx.Request.Profile.Offset, 0) + ctx.RecordsPerStore.First(x => x.Key == ctx.Store.Id).Value;
switch (ctx.Request.Provider.Value.EntityType)
{
case ExportEntityType.Product:
- ctx.ExecuteContext.Segmenter = new ExportDataSegmenter
+ ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter
(
skip => GetProducts(ctx, skip),
entities =>
@@ -295,7 +293,7 @@ private IExportDataSegmenterProvider CreateSegmenter(DataExporterContext ctx, in
x => _productAttributeService.Value.GetProductVariantAttributesByProductIds(x, null),
x => _productAttributeService.Value.GetProductVariantAttributeCombinations(x),
x => _productService.Value.GetTierPricesByProductIds(x, (ctx.Projection.CurrencyId ?? 0) != 0 ? ctx.ContextCustomer : null, ctx.Store.Id),
- x => _categoryService.Value.GetProductCategoriesByProductIds(x),
+ x => _categoryService.Value.GetProductCategoriesByProductIds(x, null, true),
x => _manufacturerService.Value.GetProductManufacturersByProductIds(x),
x => _productService.Value.GetProductPicturesByProductIds(x),
x => _productService.Value.GetProductTagsByProductIds(x),
@@ -310,7 +308,7 @@ private IExportDataSegmenterProvider CreateSegmenter(DataExporterContext ctx, in
break;
case ExportEntityType.Order:
- ctx.ExecuteContext.Segmenter = new ExportDataSegmenter
+ ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter
(
skip => GetOrders(ctx, skip),
entities =>
@@ -329,7 +327,7 @@ private IExportDataSegmenterProvider CreateSegmenter(DataExporterContext ctx, in
break;
case ExportEntityType.Manufacturer:
- ctx.ExecuteContext.Segmenter = new ExportDataSegmenter
+ ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter
(
skip => GetManufacturers(ctx, skip),
entities =>
@@ -345,7 +343,7 @@ private IExportDataSegmenterProvider CreateSegmenter(DataExporterContext ctx, in
break;
case ExportEntityType.Category:
- ctx.ExecuteContext.Segmenter = new ExportDataSegmenter
+ ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter
(
skip => GetCategories(ctx, skip),
entities =>
@@ -361,7 +359,7 @@ private IExportDataSegmenterProvider CreateSegmenter(DataExporterContext ctx, in
break;
case ExportEntityType.Customer:
- ctx.ExecuteContext.Segmenter = new ExportDataSegmenter
+ ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter
(
skip => GetCustomers(ctx, skip),
entities =>
@@ -376,7 +374,7 @@ private IExportDataSegmenterProvider CreateSegmenter(DataExporterContext ctx, in
break;
case ExportEntityType.NewsLetterSubscription:
- ctx.ExecuteContext.Segmenter = new ExportDataSegmenter
+ ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter
(
skip => GetNewsLetterSubscriptions(ctx, skip),
null,
@@ -386,11 +384,11 @@ private IExportDataSegmenterProvider CreateSegmenter(DataExporterContext ctx, in
break;
default:
- ctx.ExecuteContext.Segmenter = null;
+ ctx.ExecuteContext.DataSegmenter = null;
break;
}
- return ctx.ExecuteContext.Segmenter as IExportDataSegmenterProvider;
+ return ctx.ExecuteContext.DataSegmenter as IExportDataSegmenterProvider;
}
private bool CallProvider(DataExporterContext ctx, string streamId, string method, string path)
@@ -416,7 +414,9 @@ private bool CallProvider(DataExporterContext ctx, string streamId, string metho
if (ctx.IsFileBasedExport && path.HasValue() && ctx.ExecuteContext.DataStream.Length > 0)
{
if (!ctx.ExecuteContext.DataStream.CanSeek)
+ {
ctx.Log.Warning("Data stream seems to be closed!");
+ }
ctx.ExecuteContext.DataStream.Seek(0, SeekOrigin.Begin);
@@ -424,7 +424,6 @@ private bool CallProvider(DataExporterContext ctx, string streamId, string metho
using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
ctx.Log.Information("Creating file {0}.".FormatInvariant(path));
-
ctx.ExecuteContext.DataStream.CopyTo(fileStream);
}
}
@@ -443,61 +442,90 @@ private bool CallProvider(DataExporterContext ctx, string streamId, string metho
ctx.ExecuteContext.DataStream.Dispose();
ctx.ExecuteContext.DataStream = null;
}
+
+ if (ctx.ExecuteContext.Abort == DataExchangeAbortion.Hard && ctx.IsFileBasedExport && path.HasValue())
+ {
+ FileSystemHelper.Delete(path);
+ }
}
return (ctx.ExecuteContext.Abort != DataExchangeAbortion.Hard);
}
- private void Deploy(DataExporterContext ctx, string zipPath)
+ private bool Deploy(DataExporterContext ctx, string zipPath)
{
- var allFiles = System.IO.Directory.GetFiles(ctx.FolderContent, "*.*", SearchOption.AllDirectories);
+ var allSucceeded = true;
+ var deployments = ctx.Request.Profile.Deployments.OrderBy(x => x.DeploymentTypeId).Where(x => x.Enabled);
+
+ if (deployments.Count() == 0)
+ return false;
var context = new ExportDeploymentContext
{
+ T = T,
Log = ctx.Log,
FolderContent = ctx.FolderContent,
- ZipPath = zipPath
- };
+ ZipPath = zipPath,
+ CreateZipArchive = ctx.Request.Profile.CreateZipArchive
+ };
- foreach (var deployment in ctx.Request.Profile.Deployments.OrderBy(x => x.DeploymentTypeId).Where(x => x.Enabled))
+ foreach (var deployment in deployments)
{
- if (deployment.CreateZip)
- context.DeploymentFiles = new string[] { zipPath };
- else
- context.DeploymentFiles = allFiles;
+ IFilePublisher publisher = null;
- try
+ context.Result = new DataDeploymentResult
{
- IFilePublisher publisher = null;
+ LastExecutionUtc = DateTime.UtcNow
+ };
- if (deployment.DeploymentType == ExportDeploymentType.Email)
- {
- publisher = new EmailFilePublisher(_emailAccountService.Value, _queuedEmailService.Value);
- }
- else if (deployment.DeploymentType == ExportDeploymentType.FileSystem)
- {
- publisher = new FileSystemFilePublisher();
- }
- else if (deployment.DeploymentType == ExportDeploymentType.Ftp)
- {
- publisher = new FtpFilePublisher();
- }
- else if (deployment.DeploymentType == ExportDeploymentType.Http)
+ try
+ {
+ switch (deployment.DeploymentType)
{
- publisher = new HttpFilePublisher();
+ case ExportDeploymentType.Email:
+ publisher = new EmailFilePublisher(_emailAccountService.Value, _queuedEmailService.Value);
+ break;
+ case ExportDeploymentType.FileSystem:
+ publisher = new FileSystemFilePublisher();
+ break;
+ case ExportDeploymentType.Ftp:
+ publisher = new FtpFilePublisher();
+ break;
+ case ExportDeploymentType.Http:
+ publisher = new HttpFilePublisher();
+ break;
+ case ExportDeploymentType.PublicFolder:
+ publisher = new PublicFolderPublisher();
+ break;
}
if (publisher != null)
{
publisher.Publish(context, deployment);
+
+ if (!context.Result.Succeeded)
+ allSucceeded = false;
}
}
catch (Exception exception)
{
+ allSucceeded = false;
+
+ if (context.Result != null)
+ {
+ context.Result.LastError = exception.ToAllMessages();
+ }
+
ctx.Log.Error("Deployment \"{0}\" of type {1} failed: {2}".FormatInvariant(
deployment.Name, deployment.DeploymentType.ToString(), exception.Message), exception);
}
+
+ deployment.ResultInfo = XmlHelper.Serialize(context.Result);
+
+ _exportProfileService.Value.UpdateExportDeployment(deployment);
}
+
+ return allSucceeded;
}
private void SendCompletionEmail(DataExporterContext ctx, string zipPath)
@@ -507,7 +535,7 @@ private void SendCompletionEmail(DataExporterContext ctx, string zipPath)
if (emailAccount == null)
emailAccount = _emailAccountService.Value.GetDefaultEmailAccount();
- var downloadUrl = "{0}Admin/Export/DownloadExportFile/{1}?name=".FormatInvariant(_services.WebHelper.GetStoreLocation(false), ctx.Request.Profile.Id);
+ var downloadUrl = "{0}Admin/Export/DownloadExportFile/{1}?name=".FormatInvariant(_services.WebHelper.GetStoreLocation(ctx.Store.SslEnabled), ctx.Request.Profile.Id);
var languageId = ctx.Projection.LanguageId ?? 0;
var smtpContext = new SmtpContext(emailAccount);
@@ -525,15 +553,15 @@ private void SendCompletionEmail(DataExporterContext ctx, string zipPath)
if (ctx.IsFileBasedExport && File.Exists(zipPath))
{
var fileName = Path.GetFileName(zipPath);
- body.AppendFormat("{1}
", downloadUrl + HttpUtility.UrlDecode(fileName), fileName);
+ body.AppendFormat("{2}
", downloadUrl, HttpUtility.UrlEncode(fileName), fileName);
}
- if (ctx.IsFileBasedExport && ctx.Result.Files.Count > 0)
+ if (ctx.IsFileBasedExport && ctx.Result.Files.Any())
{
body.Append("");
foreach (var file in ctx.Result.Files)
{
- body.AppendFormat("
", downloadUrl + HttpUtility.UrlDecode(file.FileName), file.FileName);
+ body.AppendFormat("", downloadUrl, HttpUtility.UrlEncode(file.FileName), file.FileName);
}
body.Append("
");
}
@@ -543,9 +571,6 @@ private void SendCompletionEmail(DataExporterContext ctx, string zipPath)
if (ctx.Request.Profile.CompletedEmailAddresses.HasValue())
message.To.AddRange(ctx.Request.Profile.CompletedEmailAddresses.SplitSafe(",").Where(x => x.IsEmail()).Select(x => new EmailAddress(x)));
- if (message.To.Count == 0 && _contactDataSettings.Value.WebmasterEmailAddress.HasValue())
- message.To.Add(new EmailAddress(_contactDataSettings.Value.WebmasterEmailAddress));
-
if (message.To.Count == 0 && _contactDataSettings.Value.CompanyEmailAddress.HasValue())
message.To.Add(new EmailAddress(_contactDataSettings.Value.CompanyEmailAddress));
@@ -661,7 +686,7 @@ private List GetProducts(DataExporterContext ctx, int skip)
OrderBy = ProductSortingEnum.Position,
PageSize = int.MaxValue,
StoreId = (ctx.Request.Profile.PerStore ? ctx.Store.Id : ctx.Filter.StoreId),
- VisibleIndividuallyOnly = false,
+ VisibleIndividuallyOnly = true,
ParentGroupedProductId = product.Id
};
@@ -739,7 +764,7 @@ private IQueryable GetManufacturerQuery(DataExporterContext ctx, i
var query = _manufacturerService.Value.GetManufacturers(showHidden, storeId);
- if (ctx.Request.EntitiesToExport.Count > 0)
+ if (ctx.Request.EntitiesToExport.Any())
query = query.Where(x => ctx.Request.EntitiesToExport.Contains(x.Id));
query = query.OrderBy(x => x.DisplayOrder);
@@ -1029,7 +1054,10 @@ private void ExportCoreInner(DataExporterContext ctx, Store store)
logHead.Append("Export profile:\t\t" + ctx.Request.Profile.Name);
logHead.AppendLine(ctx.Request.Profile.Id == 0 ? " (volatile)" : " (Id {0})".FormatInvariant(ctx.Request.Profile.Id));
- logHead.AppendLine("Export provider:\t{0} ({1})".FormatInvariant(ctx.Request.Provider.Metadata.FriendlyName, ctx.Request.Profile.ProviderSystemName));
+ if (ctx.Request.Provider.Metadata.FriendlyName.HasValue())
+ logHead.AppendLine("Export provider:\t{0} ({1})".FormatInvariant(ctx.Request.Provider.Metadata.FriendlyName, ctx.Request.Profile.ProviderSystemName));
+ else
+ logHead.AppendLine("Export provider:\t{0}".FormatInvariant(ctx.Request.Profile.ProviderSystemName));
var plugin = ctx.Request.Provider.Metadata.PluginDescriptor;
logHead.Append("Plugin:\t\t\t");
@@ -1037,8 +1065,12 @@ private void ExportCoreInner(DataExporterContext ctx, Store store)
logHead.AppendLine("Entity:\t\t\t" + ctx.Request.Provider.Value.EntityType.ToString());
- var storeInfo = (ctx.Request.Profile.PerStore ? "{0} (Id {1})".FormatInvariant(ctx.Store.Name, ctx.Store.Id) : "All stores");
- logHead.AppendLine("Store:\t\t\t" + storeInfo);
+ try
+ {
+ var uri = new Uri(store.Url);
+ logHead.AppendLine("Store:\t\t\t{0} (Id {1})".FormatInvariant(uri.DnsSafeHost.NaIfEmpty(), ctx.Store.Id));
+ }
+ catch { }
var customer = _services.WorkContext.CurrentCustomer;
logHead.Append("Executed by:\t\t" + (customer.Email.HasValue() ? customer.Email : customer.SystemName));
@@ -1047,12 +1079,11 @@ private void ExportCoreInner(DataExporterContext ctx, Store store)
}
ctx.ExecuteContext.Store = ToDynamic(ctx, ctx.Store);
-
ctx.ExecuteContext.MaxFileNameLength = dataExchangeSettings.MaxFileNameLength;
- ctx.ExecuteContext.HasPublicDeployment = ctx.Request.Profile.Deployments.Any(x => x.IsPublic && x.DeploymentType == ExportDeploymentType.FileSystem);
-
- ctx.ExecuteContext.PublicFolderPath = (ctx.ExecuteContext.HasPublicDeployment ? Path.Combine(HttpRuntime.AppDomainAppPath, PublicFolder) : null);
+ var publicDeployment = ctx.Request.Profile.Deployments.FirstOrDefault(x => x.DeploymentType == ExportDeploymentType.PublicFolder);
+ ctx.ExecuteContext.HasPublicDeployment = (publicDeployment != null);
+ ctx.ExecuteContext.PublicFolderPath = publicDeployment.GetDeploymentFolder(true);
var fileExtension = (ctx.Request.Provider.Value.FileExtension.HasValue() ? ctx.Request.Provider.Value.FileExtension.ToLower().EnsureStartsWith(".") : "");
@@ -1082,17 +1113,13 @@ private void ExportCoreInner(DataExporterContext ctx, Store store)
ctx.ExecuteContext.FileName = resolvedPattern + fileExtension;
path = Path.Combine(ctx.ExecuteContext.Folder, ctx.ExecuteContext.FileName);
-
- if (ctx.ExecuteContext.HasPublicDeployment)
- ctx.ExecuteContext.PublicFileUrl = ctx.Store.Url.EnsureEndsWith("/") + PublicFolder.EnsureEndsWith("/") + ctx.ExecuteContext.FileName;
}
if (CallProvider(ctx, null, "Execute", path))
{
ctx.Log.Information("Provider reports {0} successfully exported record(s).".FormatInvariant(ctx.ExecuteContext.RecordsSucceeded));
- // create info for deployment list in profile edit
- if (ctx.IsFileBasedExport)
+ if (ctx.IsFileBasedExport && File.Exists(path))
{
ctx.Result.Files.Add(new DataExportResult.ExportFileInfo
{
@@ -1116,17 +1143,16 @@ private void ExportCoreInner(DataExporterContext ctx, Store store)
if (ctx.ExecuteContext.Abort != DataExchangeAbortion.Hard)
{
// always call OnExecuted
- if (ctx.ExecuteContext.ExtraDataStreams.Count == 0)
- ctx.ExecuteContext.ExtraDataStreams.Add(new ExportExtraStreams());
+ if (ctx.ExecuteContext.ExtraDataUnits.Count == 0)
+ ctx.ExecuteContext.ExtraDataUnits.Add(new ExportDataUnit());
- ctx.ExecuteContext.ExtraDataStreams.ForEach(x =>
+ ctx.ExecuteContext.ExtraDataUnits.ForEach(x =>
{
var path = (x.FileName.HasValue() ? Path.Combine(ctx.ExecuteContext.Folder, x.FileName) : null);
-
CallProvider(ctx, x.Id, "OnExecuted", path);
});
- ctx.ExecuteContext.ExtraDataStreams.Clear();
+ ctx.ExecuteContext.ExtraDataUnits.Clear();
}
}
}
@@ -1177,7 +1203,8 @@ private void ExportCoreOuter(DataExporterContext ctx)
{
ctx.DeliveryTimes = _deliveryTimeService.Value.GetAllDeliveryTimes().ToDictionary(x => x.Id);
ctx.QuantityUnits = _quantityUnitService.Value.GetAllQuantityUnits().ToDictionary(x => x.Id);
- ctx.ProductTemplates = _productTemplateService.Value.GetAllProductTemplates().ToDictionary(x => x.Id);
+ ctx.ProductTemplates = _productTemplateService.Value.GetAllProductTemplates().ToDictionary(x => x.Id, x => x.ViewPath);
+ ctx.CategoryTemplates = _categoryTemplateService.Value.GetAllCategoryTemplates().ToDictionary(x => x.Id, x => x.ViewPath);
if (ctx.Request.Provider.Value.EntityType == ExportEntityType.Product)
{
@@ -1214,16 +1241,23 @@ private void ExportCoreOuter(DataExporterContext ctx)
{
if (ctx.IsFileBasedExport)
{
- if (ctx.Request.Profile.CreateZipArchive || ctx.Request.Profile.Deployments.Any(x => x.Enabled && x.CreateZip))
+ if (ctx.Request.Profile.CreateZipArchive)
{
- ZipFile.CreateFromDirectory(ctx.FolderContent, zipPath, CompressionLevel.Fastest, true);
+ ZipFile.CreateFromDirectory(ctx.FolderContent, zipPath, CompressionLevel.Fastest, false);
}
if (ctx.Request.Profile.Deployments.Any(x => x.Enabled))
{
- SetProgress(ctx, T("Common.Deployment"));
+ SetProgress(ctx, T("Common.Publishing"));
- Deploy(ctx, zipPath);
+ var allDeploymentsSucceeded = Deploy(ctx, zipPath);
+
+ if (allDeploymentsSucceeded && ctx.Request.Profile.Cleanup)
+ {
+ logger.Information("Cleaning up export folder");
+
+ FileSystemHelper.ClearDirectory(ctx.FolderContent, false);
+ }
}
}
@@ -1248,7 +1282,7 @@ private void ExportCoreOuter(DataExporterContext ctx)
{
if (!ctx.IsPreview && ctx.Request.Profile.Id != 0)
{
- ctx.Request.Profile.ResultInfo = XmlHelper.Serialize(ctx.Result);
+ ctx.Request.Profile.ResultInfo = XmlHelper.Serialize(ctx.Result);
_exportProfileService.Value.UpdateExportProfile(ctx.Request.Profile);
}
@@ -1258,24 +1292,13 @@ private void ExportCoreOuter(DataExporterContext ctx)
logger.ErrorsAll(exception);
}
- try
- {
- if (ctx.IsFileBasedExport && ctx.ExecuteContext.Abort != DataExchangeAbortion.Hard && ctx.Request.Profile.Cleanup)
- {
- FileSystemHelper.ClearDirectory(ctx.FolderContent, false);
- }
- }
- catch (Exception exception)
- {
- logger.ErrorsAll(exception);
- }
-
DetachAllEntitiesAndClear(ctx);
try
{
ctx.NewsletterSubscriptions.Clear();
ctx.ProductTemplates.Clear();
+ ctx.CategoryTemplates.Clear();
ctx.Countries.Clear();
ctx.Languages.Clear();
ctx.QuantityUnits.Clear();
@@ -1301,7 +1324,7 @@ private void ExportCoreOuter(DataExporterContext ctx)
return;
// post process order entities
- if (ctx.EntityIdsLoaded.Count > 0 && ctx.Request.Provider.Value.EntityType == ExportEntityType.Order && ctx.Projection.OrderStatusChange != ExportOrderStatusChange.None)
+ if (ctx.EntityIdsLoaded.Any() && ctx.Request.Provider.Value.EntityType == ExportEntityType.Order && ctx.Projection.OrderStatusChange != ExportOrderStatusChange.None)
{
using (var logger = new TraceLogger(logPath))
{
@@ -1356,38 +1379,6 @@ public DataExportResult Export(DataExportRequest request, CancellationToken canc
ExportCoreOuter(ctx);
- if (ctx.Result != null && ctx.Result.Succeeded && ctx.Result.Files.Count > 0)
- {
- string prefix = null;
- string suffix = null;
- var extension = Path.GetExtension(ctx.Result.Files.First().FileName);
- var provider = request.Provider.Value;
-
- if (provider.EntityType == ExportEntityType.Product)
- prefix = T("Admin.Catalog.Products");
- else if (provider.EntityType == ExportEntityType.Order)
- prefix = T("Admin.Orders");
- else if (provider.EntityType == ExportEntityType.Category)
- prefix = T("Admin.Catalog.Categories");
- else if (provider.EntityType == ExportEntityType.Manufacturer)
- prefix = T("Admin.Catalog.Manufacturers");
- else if (provider.EntityType == ExportEntityType.Customer)
- prefix = T("Admin.Customers");
- else if (provider.EntityType == ExportEntityType.NewsLetterSubscription)
- prefix = T("Admin.Promotions.NewsLetterSubscriptions");
- else
- prefix = provider.EntityType.ToString();
-
- var selectedEntityCount = (request.EntitiesToExport == null ? 0 : request.EntitiesToExport.Count);
-
- if (selectedEntityCount == 0)
- suffix = T("Common.All");
- else
- suffix = (selectedEntityCount == 1 ? request.EntitiesToExport.First().ToString() : T("Admin.Common.Selected").Text);
-
- ctx.Result.DownloadFileName = string.Concat(prefix, "-", suffix).ToLower().ToValidFileName() + extension;
- }
-
cancellationToken.ThrowIfCancellationRequested();
return ctx.Result;
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/DataDeploymentResult.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/DataDeploymentResult.cs
new file mode 100644
index 0000000000..7fff7a46e5
--- /dev/null
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/DataDeploymentResult.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace SmartStore.Services.DataExchange.Export.Deployment
+{
+ [Serializable]
+ public class DataDeploymentResult
+ {
+ ///
+ /// Whether the deployment succeeded
+ ///
+ public bool Succeeded
+ {
+ get { return LastError.IsEmpty(); }
+ }
+
+ public string LastError { get; set; }
+
+ ///
+ /// Last execution date
+ ///
+ public DateTime LastExecutionUtc { get; set; }
+ }
+}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Deployment/EmailFilePublisher.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/EmailFilePublisher.cs
similarity index 88%
rename from src/Libraries/SmartStore.Services/DataExchange/Deployment/EmailFilePublisher.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/EmailFilePublisher.cs
index 0294229103..298d476c41 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Deployment/EmailFilePublisher.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/EmailFilePublisher.cs
@@ -35,21 +35,21 @@ public virtual void Publish(ExportDeploymentContext context, ExportDeployment de
{
From = emailAccount.Email,
FromName = emailAccount.DisplayName,
- SendManually = true,
+ SendManually = false,
To = email,
Subject = deployment.EmailSubject.NaIfEmpty(),
CreatedOnUtc = DateTime.UtcNow,
EmailAccountId = deployment.EmailAccountId
};
- foreach (string path in context.DeploymentFiles)
+ foreach (var path in context.GetDeploymentFiles())
{
- string name = Path.GetFileName(path);
+ var name = Path.GetFileName(path);
queuedEmail.Attachments.Add(new QueuedEmailAttachment
{
- StorageLocation = EmailAttachmentStorageLocation.Path,
- Path = path,
+ StorageLocation = EmailAttachmentStorageLocation.Blob,
+ Data = File.ReadAllBytes(path),
Name = name,
MimeType = MimeTypes.MapNameToMimeType(name)
});
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/FileSystemFilePublisher.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/FileSystemFilePublisher.cs
new file mode 100644
index 0000000000..6bb56682e1
--- /dev/null
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/FileSystemFilePublisher.cs
@@ -0,0 +1,22 @@
+using System.IO;
+using SmartStore.Core.Domain;
+using SmartStore.Core.Logging;
+using SmartStore.Utilities;
+
+namespace SmartStore.Services.DataExchange.Export.Deployment
+{
+ public class FileSystemFilePublisher : IFilePublisher
+ {
+ public virtual void Publish(ExportDeploymentContext context, ExportDeployment deployment)
+ {
+ var targetFolder = deployment.GetDeploymentFolder(true);
+
+ if (!FileSystemHelper.CopyDirectory(new DirectoryInfo(context.FolderContent), new DirectoryInfo(targetFolder)))
+ {
+ context.Result.LastError = context.T("Admin.DataExchange.Export.Deployment.CopyFileFailed");
+ }
+
+ context.Log.Information("Copied export data files to " + targetFolder);
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Deployment/FtpFilePublisher.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/FtpFilePublisher.cs
similarity index 82%
rename from src/Libraries/SmartStore.Services/DataExchange/Deployment/FtpFilePublisher.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/FtpFilePublisher.cs
index 2352d7250f..7a0954a1c7 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Deployment/FtpFilePublisher.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/FtpFilePublisher.cs
@@ -16,7 +16,7 @@ public virtual void Publish(ExportDeploymentContext context, ExportDeployment de
var url = deployment.Url;
var buffLength = 32768;
byte[] buff = new byte[buffLength];
- var deploymentFiles = context.DeploymentFiles.ToList();
+ var deploymentFiles = context.GetDeploymentFiles().ToList();
var lastIndex = (deploymentFiles.Count - 1);
if (!url.StartsWith("ftp://", StringComparison.InvariantCultureIgnoreCase))
@@ -26,7 +26,7 @@ public virtual void Publish(ExportDeploymentContext context, ExportDeployment de
{
var fileUrl = url.EnsureEndsWith("/") + Path.GetFileName(path);
- var request = (FtpWebRequest)System.Net.WebRequest.Create(fileUrl);
+ var request = (FtpWebRequest)WebRequest.Create(fileUrl);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.KeepAlive = (deploymentFiles.IndexOf(path) != lastIndex);
request.UseBinary = true;
@@ -61,10 +61,9 @@ public virtual void Publish(ExportDeploymentContext context, ExportDeployment de
}
else
{
- var msg = "The FTP transfer might fail. {0} ({1}), {2}. File {3}".FormatInvariant(
- response.StatusCode.ToString(), statusCode, response.StatusDescription.NaIfEmpty(), path);
+ context.Result.LastError = context.T("Admin.Common.FtpStatus", statusCode, response.StatusCode.ToString());
- context.Log.Error(msg);
+ context.Log.Error("The FTP transfer failed. FTP status {0} ({1}). File {3}".FormatInvariant(statusCode, response.StatusCode.ToString(), path));
}
}
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Deployment/HttpFilePublisher.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/HttpFilePublisher.cs
similarity index 73%
rename from src/Libraries/SmartStore.Services/DataExchange/Deployment/HttpFilePublisher.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/HttpFilePublisher.cs
index 48303bd200..4f0d9df8d8 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Deployment/HttpFilePublisher.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/HttpFilePublisher.cs
@@ -12,7 +12,7 @@ public class HttpFilePublisher : IFilePublisher
{
public virtual void Publish(ExportDeploymentContext context, ExportDeployment deployment)
{
- var succeeded = 0;
+ var succeededFiles = 0;
var url = deployment.Url;
if (!url.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) && !url.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase))
@@ -20,7 +20,7 @@ public virtual void Publish(ExportDeploymentContext context, ExportDeployment de
if (deployment.HttpTransmissionType == ExportHttpTransmissionType.MultipartFormDataPost)
{
- var count = 0;
+ var countFiles = 0;
ICredentials credentials = null;
if (deployment.Username.HasValue())
@@ -30,24 +30,26 @@ public virtual void Publish(ExportDeploymentContext context, ExportDeployment de
using (var client = new HttpClient(handler))
using (var formData = new MultipartFormDataContent())
{
- foreach (var path in context.DeploymentFiles)
+ foreach (var path in context.GetDeploymentFiles())
{
byte[] fileData = File.ReadAllBytes(path);
- formData.Add(new ByteArrayContent(fileData), "file {0}".FormatInvariant(++count), Path.GetFileName(path));
+ formData.Add(new ByteArrayContent(fileData), "file {0}".FormatInvariant(++countFiles), Path.GetFileName(path));
}
var response = client.PostAsync(url, formData).Result;
if (response.IsSuccessStatusCode)
{
- succeeded = count;
+ succeededFiles = countFiles;
}
else if (response.Content != null)
{
+ context.Result.LastError = context.T("Admin.Common.HttpStatus", (int)response.StatusCode, response.StatusCode.ToString());
+
var content = response.Content.ReadAsStringAsync().Result;
- var msg = "Multipart form data upload failed. {0} ({1}). Response: {2}".FormatInvariant(
- response.StatusCode.ToString(), (int)response.StatusCode, content.NaIfEmpty().Truncate(2000, "..."));
+ var msg = "Multipart form data upload failed. HTTP status {0} ({1}). Response: {2}".FormatInvariant(
+ (int)response.StatusCode, response.StatusCode.ToString(), content.NaIfEmpty().Truncate(2000, "..."));
context.Log.Error(msg);
}
@@ -60,16 +62,16 @@ public virtual void Publish(ExportDeploymentContext context, ExportDeployment de
if (deployment.Username.HasValue())
webClient.Credentials = new NetworkCredential(deployment.Username, deployment.Password);
- foreach (var path in context.DeploymentFiles)
+ foreach (var path in context.GetDeploymentFiles())
{
webClient.UploadFile(url, path);
- ++succeeded;
+ ++succeededFiles;
}
}
}
- context.Log.Information("{0} file(s) successfully uploaded via HTTP ({1}).".FormatInvariant(succeeded, deployment.HttpTransmissionType.ToString()));
+ context.Log.Information("{0} file(s) successfully uploaded via HTTP ({1}).".FormatInvariant(succeededFiles, deployment.HttpTransmissionType.ToString()));
}
}
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/IFilePublisher.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/IFilePublisher.cs
new file mode 100644
index 0000000000..1ae3301ec4
--- /dev/null
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/IFilePublisher.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using System.IO;
+using SmartStore.Core.Domain;
+using SmartStore.Core.Localization;
+using SmartStore.Core.Logging;
+
+namespace SmartStore.Services.DataExchange.Export.Deployment
+{
+ public interface IFilePublisher
+ {
+ void Publish(ExportDeploymentContext context, ExportDeployment deployment);
+ }
+
+
+ public class ExportDeploymentContext
+ {
+ public Localizer T { get; set; }
+ public ILogger Log { get; set; }
+
+ public string FolderContent { get; set; }
+
+ public string ZipPath { get; set; }
+ public bool CreateZipArchive { get; set; }
+
+ public DataDeploymentResult Result { get; set; }
+
+ public IEnumerable GetDeploymentFiles()
+ {
+ if (!CreateZipArchive)
+ {
+ return System.IO.Directory.EnumerateFiles(FolderContent, "*", SearchOption.AllDirectories);
+ }
+
+ if (File.Exists(ZipPath))
+ {
+ return new string[] { ZipPath };
+ }
+
+ return new string[0];
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/PublicFolderPublisher.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/PublicFolderPublisher.cs
new file mode 100644
index 0000000000..d438e808a2
--- /dev/null
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/Deployment/PublicFolderPublisher.cs
@@ -0,0 +1,44 @@
+using System.IO;
+using SmartStore.Core.Domain;
+using SmartStore.Core.Logging;
+using SmartStore.Utilities;
+
+namespace SmartStore.Services.DataExchange.Export.Deployment
+{
+ public class PublicFolderPublisher : IFilePublisher
+ {
+ public virtual void Publish(ExportDeploymentContext context, ExportDeployment deployment)
+ {
+ var destinationFolder = deployment.GetDeploymentFolder(true);
+
+ if (destinationFolder.IsEmpty())
+ return;
+
+ if (!System.IO.Directory.Exists(destinationFolder))
+ {
+ System.IO.Directory.CreateDirectory(destinationFolder);
+ }
+
+ if (context.CreateZipArchive)
+ {
+ if (File.Exists(context.ZipPath))
+ {
+ var destinationFile = Path.Combine(destinationFolder, Path.GetFileName(context.ZipPath));
+
+ File.Copy(context.ZipPath, destinationFile, true);
+
+ context.Log.Information("Copied zipped export data to " + destinationFile);
+ }
+ }
+ else
+ {
+ if (!FileSystemHelper.CopyDirectory(new DirectoryInfo(context.FolderContent), new DirectoryInfo(destinationFolder)))
+ {
+ context.Result.LastError = context.T("Admin.DataExchange.Export.Deployment.CopyFileFailed");
+ }
+
+ context.Log.Information("Copied export data files to " + destinationFolder);
+ }
+ }
+ }
+}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/DynamicEntityHelper.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/DynamicEntityHelper.cs
index 232e2ee864..1917084af2 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Export/DynamicEntityHelper.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/DynamicEntityHelper.cs
@@ -136,15 +136,30 @@ private void PrepareProductDescription(DataExporterContext ctx, dynamic dynObjec
return price;
}
- private decimal CalculatePrice(DataExporterContext ctx, Product product, bool forAttributeCombination)
+ private decimal CalculatePrice(
+ DataExporterContext ctx,
+ Product product,
+ ProductVariantAttributeCombination combination,
+ IList attributeValues)
{
- decimal price = product.Price;
+ var price = product.Price;
+ var priceCalculationContext = ctx.ProductExportContext as PriceCalculationContext;
- // price type
- if (ctx.Projection.PriceType.HasValue && !forAttributeCombination)
+ if (combination != null)
{
- var priceCalculationContext = ctx.ProductExportContext as PriceCalculationContext;
+ // price for attribute combination
+ var attributesTotalPriceBase = decimal.Zero;
+ if (attributeValues != null)
+ {
+ attributeValues.Each(x => attributesTotalPriceBase += _priceCalculationService.Value.GetProductVariantAttributeValuePriceAdjustment(x));
+ }
+
+ price = _priceCalculationService.Value.GetFinalPrice(product, null, ctx.ContextCustomer, attributesTotalPriceBase, true, 1, null, priceCalculationContext);
+ }
+ else if (ctx.Projection.PriceType.HasValue)
+ {
+ // price for product
if (ctx.Projection.PriceType.Value == PriceDisplayType.LowestPrice)
{
bool displayFromMessage;
@@ -163,7 +178,6 @@ private decimal CalculatePrice(DataExporterContext ctx, Product product, bool fo
return ConvertPrice(ctx, product, price) ?? price;
}
-
private List GetLocalized(DataExporterContext ctx, T entity, params Expression>[] keySelectors)
where T : BaseEntity, ILocalizedEntity
{
@@ -487,6 +501,11 @@ private dynamic ToDynamic(DataExporterContext ctx, Category category)
result.Picture = null;
+ if (ctx.CategoryTemplates.ContainsKey(category.CategoryTemplateId))
+ result._CategoryTemplateViewPath = ctx.CategoryTemplates[category.CategoryTemplateId];
+ else
+ result._CategoryTemplateViewPath = "";
+
result._Localized = GetLocalized(ctx, category,
x => x.Name,
x => x.FullName,
@@ -547,7 +566,6 @@ private dynamic ToDynamic(
product.MergeWithCombination(combination);
var languageId = (ctx.Projection.LanguageId ?? 0);
- var productTemplate = ctx.ProductTemplates.FirstOrDefault(x => x.Key == product.ProductTemplateId);
var pictureSize = _mediaSettings.Value.ProductDetailsPictureSize;
var numberOfPictures = (ctx.Projection.NumberOfPictures ?? int.MaxValue);
int[] pictureIds = (combination == null ? new int[0] : combination.GetAssignedPictureIds());
@@ -563,10 +581,11 @@ private dynamic ToDynamic(
var productTags = ctx.ProductExportContext.ProductTags.Load(product.Id);
var specificationAttributes = ctx.ProductExportContext.ProductSpecificationAttributes.Load(product.Id);
+ var variantAttributes = (combination != null ? _productAttributeParser.Value.DeserializeProductVariantAttributes(combination.AttributesXml) : null);
+ var variantAttributeValues = (combination != null ? _productAttributeParser.Value.ParseProductVariantAttributeValues(variantAttributes, productAttributes) : null);
+
if (pictureIds.Length > 0)
- {
productPictures = productPictures.Where(x => pictureIds.Contains(x.PictureId));
- }
productPictures = productPictures.Take(numberOfPictures);
@@ -574,35 +593,53 @@ private dynamic ToDynamic(
#region gerneral data
- dynObject.Price = CalculatePrice(ctx, product, combination != null);
-
- if (combination != null && ctx.Projection.AttributeCombinationValueMerging == ExportAttributeValueMerging.AppendAllValuesToName)
- {
- var values = _productAttributeParser.Value.ParseProductVariantAttributeValues(combination.AttributesXml, productAttributes, ctx.Projection.LanguageId ?? 0);
+ dynObject._CategoryName = null;
+ dynObject._CategoryPath = null;
+ dynObject._AttributeCombination = null;
+ dynObject._AttributeCombinationValues = null;
+ dynObject._AttributeCombinationId = (combination == null ? 0 : combination.Id);
+ dynObject._DetailUrl = ctx.Store.Url.EnsureEndsWith("/") + (string)dynObject.SeName;
+
+ if (combination == null)
+ dynObject._UniqueId = product.Id.ToString();
+ else
+ dynObject._UniqueId = string.Concat(product.Id, "-", combination.Id);
- dynObject.Name = ((string)dynObject.Name).Grow(string.Join(", ", values), " ");
- }
+ dynObject.Price = CalculatePrice(ctx, product, combination, variantAttributeValues);
dynObject._BasePriceInfo = product.GetBasePriceInfo(_services.Localization, _priceFormatter.Value, _currencyService.Value, _taxService.Value,
_priceCalculationService.Value, ctx.ContextCurrency, decimal.Zero, true);
- dynObject._ProductTemplateViewPath = (productTemplate.Value == null ? "" : productTemplate.Value.ViewPath);
-
- var detailUrl = ctx.Store.Url.EnsureEndsWith("/") + (string)dynObject.SeName;
+ if (ctx.ProductTemplates.ContainsKey(product.ProductTemplateId))
+ dynObject._ProductTemplateViewPath = ctx.ProductTemplates[product.ProductTemplateId];
+ else
+ dynObject._ProductTemplateViewPath = "";
if (combination != null)
{
+ if (ctx.Supports(ExportFeatures.UsesAttributeCombination))
+ {
+ dynObject._AttributeCombination = variantAttributes;
+ dynObject._AttributeCombinationValues = variantAttributeValues;
+ }
+
+ if (ctx.Projection.AttributeCombinationValueMerging == ExportAttributeValueMerging.AppendAllValuesToName)
+ {
+ var valueNames = variantAttributeValues
+ .Select(x => x.GetLocalized(y => y.Name, languageId, true, false))
+ .ToList();
+
+ dynObject.Name = ((string)dynObject.Name).Grow(string.Join(", ", valueNames), " ");
+ }
+
var attributeQueryString = _productAttributeParser.Value.SerializeQueryData(combination.AttributesXml, product.Id);
if (attributeQueryString.HasValue())
{
- detailUrl = string.Concat(detailUrl, detailUrl.Contains("?") ? "&" : "?", "attributes=", attributeQueryString);
+ var url = (string)dynObject._DetailUrl;
+ dynObject._DetailUrl = string.Concat(url, url.Contains("?") ? "&" : "?", "attributes=", attributeQueryString);
}
}
- dynObject._DetailUrl = detailUrl;
-
- dynObject._CategoryName = null;
-
if (ctx.Categories.Count > 0)
{
dynObject._CategoryPath = _categoryService.Value.GetCategoryPath(
@@ -614,13 +651,8 @@ private dynamic ToDynamic(
productCategories.OrderBy(x => x.DisplayOrder).FirstOrDefault()
);
}
- else
- {
- dynObject._CategoryPath = null;
- }
ToDeliveryTime(ctx, dynObject, product.DeliveryTimeId);
-
ToQuantityUnit(ctx, dynObject, product.QuantityUnitId);
dynObject.ProductPictures = productPictures
@@ -841,20 +873,32 @@ private dynamic ToDynamic(
if (ctx.Supports(ExportFeatures.UsesSpecialPrice))
{
- dynObject._SpecialPrice = null;
- dynObject._RegularPrice = null; // price if a special price would not exist
+ dynObject._SpecialPrice = null; // special price which is valid now
+ dynObject._FutureSpecialPrice = null; // special price which is valid now and in future
+ dynObject._RegularPrice = null; // price as if a special price would not exist
if (!(product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing))
{
+ if (product.SpecialPrice.HasValue && product.SpecialPriceEndDateTimeUtc.HasValue)
+ {
+ var endDate = DateTime.SpecifyKind(product.SpecialPriceEndDateTimeUtc.Value, DateTimeKind.Utc);
+ if (endDate > DateTime.UtcNow)
+ {
+ dynObject._FutureSpecialPrice = ConvertPrice(ctx, product, product.SpecialPrice.Value);
+ }
+ }
+
var specialPrice = _priceCalculationService.Value.GetSpecialPrice(product);
dynObject._SpecialPrice = ConvertPrice(ctx, product, specialPrice);
- if (specialPrice.HasValue)
+ if (specialPrice.HasValue || dynObject._FutureSpecialPrice != null)
{
decimal tmpSpecialPrice = product.SpecialPrice.Value;
product.SpecialPrice = null;
- dynObject._RegularPrice = CalculatePrice(ctx, product, combination != null);
+
+ dynObject._RegularPrice = CalculatePrice(ctx, product, combination, variantAttributeValues);
+
product.SpecialPrice = tmpSpecialPrice;
}
}
@@ -895,6 +939,8 @@ private dynamic ToDynamic(DataExporterContext ctx, OrderItem orderItem)
dynamic result = new DynamicEntity(orderItem);
+ orderItem.Product.MergeWithCombination(orderItem.AttributesXml, _productAttributeParser.Value);
+
result.Product = ToDynamic(ctx, orderItem.Product);
return result;
@@ -988,19 +1034,17 @@ private List Convert(DataExporterContext ctx, Product product)
//var productValues = new Dictionary();
var dbContext = _dbContext as DbContext;
- product = _dbContext.Attach(product);
-
- var entry = dbContext.Entry(product);
-
- // the returned object is not the entity and is not being tracked by the context.
- // it also does not have any relationships set to other objects.
- // CurrentValues only includes database (thus primitive) values.
- var productClone = entry.CurrentValues.ToObject() as Product;
-
- _dbContext.DetachEntity(product);
-
foreach (var combination in combinations.Where(x => x.IsActive))
{
+ product = _dbContext.Attach(product);
+ var entry = dbContext.Entry(product);
+
+ // the returned object is not the entity and is not being tracked by the context.
+ // it also does not have any relationships set to other objects.
+ // CurrentValues only includes database (thus primitive) values.
+ var productClone = entry.CurrentValues.ToObject() as Product;
+ _dbContext.DetachEntity(product);
+
var dynObject = ToDynamic(ctx, productClone, combinations, combination);
result.Add(dynObject);
}
@@ -1029,10 +1073,13 @@ private List Convert(DataExporterContext ctx, Order order)
{
var result = new List();
- ctx.OrderExportContext.Addresses.Collect(order.ShippingAddressId ?? 0);
+ if (!ctx.IsPreview)
+ {
+ ctx.OrderExportContext.Addresses.Collect(order.ShippingAddressId.HasValue ? order.ShippingAddressId.Value : 0);
+ ctx.OrderExportContext.Addresses.Load(order.BillingAddressId);
+ }
var perfLoadId = (ctx.IsPreview ? 0 : order.Id);
- var addresses = ctx.OrderExportContext.Addresses.Load(ctx.IsPreview ? 0 : order.BillingAddressId);
var customers = ctx.OrderExportContext.Customers.Load(order.CustomerId);
var rewardPointsHistories = ctx.OrderExportContext.RewardPointsHistories.Load(ctx.IsPreview ? 0 : order.CustomerId);
var orderItems = ctx.OrderExportContext.OrderItems.Load(perfLoadId);
@@ -1060,20 +1107,25 @@ private List Convert(DataExporterContext ctx, Order order)
.PointsBalance;
}
- dynObject.BillingAddress = ToDynamic(ctx, addresses.FirstOrDefault(x => x.Id == order.BillingAddressId));
+ if (ctx.OrderExportContext.Addresses.ContainsKey(order.BillingAddressId))
+ {
+ dynObject.BillingAddress = ToDynamic(ctx, ctx.OrderExportContext.Addresses[order.BillingAddressId].FirstOrDefault());
+ }
- if (order.ShippingAddressId.HasValue)
+ if (order.ShippingAddressId.HasValue && ctx.OrderExportContext.Addresses.ContainsKey(order.ShippingAddressId.Value))
{
- dynObject.ShippingAddress = ToDynamic(ctx, addresses.FirstOrDefault(x => x.Id == order.ShippingAddressId.Value));
+ dynObject.ShippingAddress = ToDynamic(ctx, ctx.OrderExportContext.Addresses[order.ShippingAddressId.Value].FirstOrDefault());
}
dynObject.OrderItems = orderItems
.Select(e =>
{
dynamic dyn = ToDynamic(ctx, e);
- var productTemplate = ctx.ProductTemplates.FirstOrDefault(x => x.Key == e.Product.ProductTemplateId);
- dyn.Product._ProductTemplateViewPath = (productTemplate.Value == null ? "" : productTemplate.Value.ViewPath);
+ if (ctx.ProductTemplates.ContainsKey(e.Product.ProductTemplateId))
+ dyn.Product._ProductTemplateViewPath = ctx.ProductTemplates[e.Product.ProductTemplateId];
+ else
+ dyn.Product._ProductTemplateViewPath = "";
dyn.Product._BasePriceInfo = e.Product.GetBasePriceInfo(_services.Localization, _priceFormatter.Value, _currencyService.Value, _taxService.Value,
_priceCalculationService.Value, ctx.ContextCurrency, decimal.Zero, true);
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Events/RowExportingEvent.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Events/RowExportingEvent.cs
similarity index 50%
rename from src/Libraries/SmartStore.Services/DataExchange/Events/RowExportingEvent.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Events/RowExportingEvent.cs
index 7459b9ee3f..0b96526e00 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Events/RowExportingEvent.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/Events/RowExportingEvent.cs
@@ -4,13 +4,32 @@ namespace SmartStore.Services.DataExchange.Export.Events
{
// TODO: Another event message must be implemented, say 'ColumnsBuildingEvent'
// The consumer of this event (most likely a plugin) could push a list of specific column headers
- // into global the export definition.
+ // into the global export definition.
public class RowExportingEvent
{
- public dynamic Row { get; internal set; }
- public ExportEntityType EntityType { get; internal set; }
- public DataExportRequest ExportRequest { get; internal set; }
- public IExportExecuteContext ExecuteContext { get; internal set; }
+ public dynamic Row
+ {
+ get;
+ internal set;
+ }
+
+ public ExportEntityType EntityType
+ {
+ get;
+ internal set;
+ }
+
+ public DataExportRequest ExportRequest
+ {
+ get;
+ internal set;
+ }
+
+ public ExportExecuteContext ExecuteContext
+ {
+ get;
+ internal set;
+ }
}
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/ExportExecuteContext.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/ExportExecuteContext.cs
index 514c223624..d5f2860ff8 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Export/ExportExecuteContext.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/ExportExecuteContext.cs
@@ -7,132 +7,173 @@
namespace SmartStore.Services.DataExchange.Export
{
- public interface IExportExecuteContext
+ public class ExportExecuteContext
{
+ private DataExportResult _result;
+ private CancellationToken _cancellation;
+ private DataExchangeAbortion _providerAbort;
+
+ internal ExportExecuteContext(DataExportResult result, CancellationToken cancellation, string folder)
+ {
+ _result = result;
+ _cancellation = cancellation;
+ Folder = folder;
+ ExtraDataUnits = new List();
+ CustomProperties = new Dictionary();
+ }
+
///
/// Provides the data to be exported
///
- IExportDataSegmenterConsumer Segmenter { get; }
+ public IExportDataSegmenterConsumer DataSegmenter { get; set; }
///
/// The store context to be used for the export
///
- dynamic Store { get; }
+ public dynamic Store { get; internal set; }
///
/// The customer context to be used for the export
///
- dynamic Customer { get; }
+ public dynamic Customer { get; internal set; }
///
/// The currency context to be used for the export
///
- dynamic Currency { get; }
+ public dynamic Currency { get; internal set; }
///
/// The language context to be used for the export
///
- dynamic Language { get; }
+ public dynamic Language { get; internal set; }
///
/// Projection data
///
- ExportProjection Projection { get; }
+ public ExportProjection Projection { get; internal set; }
///
/// To log information into the export log file
///
- ILogger Log { get; }
+ public ILogger Log { get; internal set; }
///
/// Indicates whether and how to abort the export
///
- DataExchangeAbortion Abort { get; set; }
+ public DataExchangeAbortion Abort
+ {
+ get
+ {
+ if (_cancellation.IsCancellationRequested || IsMaxFailures)
+ return DataExchangeAbortion.Hard;
+ return _providerAbort;
+ }
+ set
+ {
+ _providerAbort = value;
+ }
+ }
+
+ public bool IsMaxFailures
+ {
+ get { return RecordsFailed > 11; }
+ }
///
/// Identifier of current data stream. Can be null.
///
- string DataStreamId { get; set; }
+ public string DataStreamId { get; set; }
///
/// Stream used to write data to
///
- Stream DataStream { get; }
+ public Stream DataStream { get; internal set; }
///
- /// List with extra data streams required by provider
+ /// List with extra data units/streams required by provider
///
- List ExtraDataStreams { get; set; }
-
+ public List ExtraDataUnits { get; private set; }
///
/// The maximum allowed file name length
///
- int MaxFileNameLength { get; }
+ public int MaxFileNameLength { get; internal set; }
///
/// The name of the current export file
///
- string FileName { get; }
+ public string FileName { get; internal set; }
///
/// The path of the export content folder
///
- string Folder { get; }
-
+ public string Folder { get; private set; }
///
/// Whether the profile has a public deployment into "Exchange" folder
///
- bool HasPublicDeployment { get; }
+ public bool HasPublicDeployment { get; internal set; }
///
/// The local path to the public export folder "Exchange". null if the profile has no public deployment.
///
- string PublicFolderPath { get; }
-
- ///
- /// The public URL of the export file (accessible through the internet). null if the profile has no public deployment.
- ///
- string PublicFileUrl { get; }
-
+ public string PublicFolderPath { get; internal set; }
///
/// Provider specific configuration data
///
- object ConfigurationData { get; }
+ public object ConfigurationData { get; internal set; }
///
/// Use this dictionary for any custom data required along the export
///
- Dictionary CustomProperties { get; set; }
+ public Dictionary CustomProperties { get; set; }
///
/// Number of successful processed records
///
- int RecordsSucceeded { get; set; }
+ public int RecordsSucceeded { get; set; }
///
/// Number of failed records
///
- int RecordsFailed { get; set; }
+ public int RecordsFailed { get; set; }
///
/// Processes an exception that occurred while exporting a record
///
- /// Exception
- void RecordException(Exception exc, int entityId);
+ /// Exception
+ public void RecordException(Exception exception, int entityId)
+ {
+ ++RecordsFailed;
+
+ Log.Error("Error while processing record with id {0}: {1}".FormatInvariant(entityId, exception.ToAllMessages()), exception);
+
+ if (IsMaxFailures)
+ _result.LastError = exception.ToString();
+ }
+
+ public ProgressValueSetter ProgressValueSetter { get; internal set; }
///
/// Allows to set a progress message
///
/// Output message
- void SetProgress(string message);
+ public void SetProgress(string message)
+ {
+ if (ProgressValueSetter != null && message.HasValue())
+ {
+ try
+ {
+ ProgressValueSetter.Invoke(0, 0, message);
+ }
+ catch { }
+ }
+ }
}
-
- public class ExportExtraStreams
+ public class ExportDataUnit
{
///
/// Your Id to identify this stream within a list of streams
@@ -149,93 +190,4 @@ public class ExportExtraStreams
///
public string FileName { get; set; }
}
-
-
- public class ExportExecuteContext : IExportExecuteContext
- {
- private DataExportResult _result;
- private CancellationToken _cancellation;
- private DataExchangeAbortion _providerAbort;
-
- internal ExportExecuteContext(DataExportResult result, CancellationToken cancellation, string folder)
- {
- _result = result;
- _cancellation = cancellation;
- Folder = folder;
- ExtraDataStreams = new List();
- CustomProperties = new Dictionary();
- }
-
- public IExportDataSegmenterConsumer Segmenter { get; set; }
-
- public dynamic Store { get; internal set; }
- public dynamic Customer { get; internal set; }
- public dynamic Currency { get; internal set; }
- public dynamic Language { get; internal set; }
- public ExportProjection Projection { get; internal set; }
-
- public ILogger Log { get; internal set; }
- public ProgressValueSetter ProgressValueSetter { get; internal set; }
-
- public DataExchangeAbortion Abort
- {
- get
- {
- if (_cancellation.IsCancellationRequested || IsMaxFailures)
- return DataExchangeAbortion.Hard;
-
- return _providerAbort;
- }
- set
- {
- _providerAbort = value;
- }
- }
-
- public bool IsMaxFailures
- {
- get { return RecordsFailed > 11; }
- }
-
- public string DataStreamId { get; set; }
- public Stream DataStream { get; internal set; }
- public List ExtraDataStreams { get; set; }
-
- public int MaxFileNameLength { get; internal set; }
- public string FileName { get; internal set; }
- public string Folder { get; private set; }
-
- public bool HasPublicDeployment { get; internal set; }
- public string PublicFolderPath { get; internal set; }
- public string PublicFileUrl { get; internal set; }
-
- public object ConfigurationData { get; internal set; }
-
- public Dictionary CustomProperties { get; set; }
-
- public int RecordsSucceeded { get; set; }
- public int RecordsFailed { get; set; }
-
- public void RecordException(Exception exc, int entityId)
- {
- ++RecordsFailed;
-
- Log.Error("Error while processing record with id {0}: {1}".FormatInvariant(entityId, exc.ToAllMessages()), exc);
-
- if (IsMaxFailures)
- _result.LastError = exc.ToString();
- }
-
- public void SetProgress(string message)
- {
- if (ProgressValueSetter != null && message.HasValue())
- {
- try
- {
- ProgressValueSetter.Invoke(0, 0, message);
- }
- catch { }
- }
- }
- }
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/ExportExtensions.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/ExportExtensions.cs
index 3d65d673c8..0371702eec 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Export/ExportExtensions.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/ExportExtensions.cs
@@ -4,7 +4,10 @@
using System.IO;
using System.Linq;
using System.Text;
+using System.Web;
+using SmartStore.Core;
using SmartStore.Core.Domain;
+using SmartStore.Core.Domain.DataExchange;
using SmartStore.Core.Domain.Stores;
using SmartStore.Core.Plugins;
using SmartStore.Services.Localization;
@@ -21,7 +24,7 @@ public static class ExportExtensions
/// true provider is valid, false provider is invalid.
public static bool IsValid(this Provider provider)
{
- return provider != null;
+ return provider != null && provider.Value != null;
}
///
@@ -46,7 +49,7 @@ public static string GetName(this Provider provider, ILocalizat
/// Folder path
public static string GetExportFolder(this ExportProfile profile, bool content = false, bool create = false)
{
- var path = CommonHelper.MapPath(string.Concat("~/App_Data/ExportProfiles/", profile.FolderName, content ? "/Content" : ""));
+ var path = CommonHelper.MapPath(string.Concat(profile.FolderName, content ? "/Content" : ""));
if (create && !System.IO.Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
@@ -71,27 +74,48 @@ public static string GetExportLogPath(this ExportProfile profile)
/// ZIP file path
public static string GetExportZipPath(this ExportProfile profile)
{
- return Path.Combine(profile.GetExportFolder(), profile.FolderName + ".zip");
+ var name = (new DirectoryInfo(profile.FolderName)).Name;
+ if (name.IsEmpty())
+ name = "ExportData";
+
+ return Path.Combine(profile.GetExportFolder(), name.ToValidFileName() + ".zip");
}
///
/// Gets existing export files for an export profile
///
/// Export profile
+ /// Export provider
/// List of file names
- public static List GetExportFiles(this ExportProfile profile)
+ public static IEnumerable GetExportFiles(this ExportProfile profile, Provider provider)
{
var exportFolder = profile.GetExportFolder(true);
- if (System.IO.Directory.Exists(exportFolder))
+ if (System.IO.Directory.Exists(exportFolder) && provider.Value.FileExtension.HasValue())
{
- return System.IO.Directory.EnumerateFiles(exportFolder, "*", SearchOption.TopDirectoryOnly)
- .OrderBy(x => x)
- .ToList();
+ var filter = "*.{0}".FormatInvariant(provider.Value.FileExtension.ToLower());
+
+ return System.IO.Directory.EnumerateFiles(exportFolder, filter, SearchOption.AllDirectories).OrderBy(x => x);
}
- return new List();
- }
+ return Enumerable.Empty();
+ }
+
+ ///
+ /// Get number of existing export files
+ ///
+ /// Export profile
+ /// Export provider
+ /// Number of export files
+ public static int GetExportFileCount(this ExportProfile profile, Provider provider)
+ {
+ var result = profile.GetExportFiles(provider).Count();
+
+ if (File.Exists(profile.GetExportZipPath()))
+ ++result;
+
+ return result;
+ }
///
/// Resolves the file name pattern for an export profile
@@ -128,5 +152,107 @@ public static string ResolveFileNamePattern(this ExportProfile profile, Store st
return result;
}
+
+ ///
+ /// Get path of the deployment folder
+ ///
+ /// Export deployment
+ /// Deployment folder path
+ public static string GetDeploymentFolder(this ExportDeployment deployment, bool create = false)
+ {
+ if (deployment == null)
+ return null;
+
+ string path = null;
+
+ if (deployment.DeploymentType == ExportDeploymentType.PublicFolder)
+ {
+ if (deployment.SubFolder.HasValue())
+ path = Path.Combine(HttpRuntime.AppDomainAppPath, DataExporter.PublicFolder, deployment.SubFolder);
+ else
+ path = Path.Combine(HttpRuntime.AppDomainAppPath, DataExporter.PublicFolder);
+ }
+ else if (deployment.DeploymentType == ExportDeploymentType.FileSystem)
+ {
+ if (deployment.FileSystemPath.IsEmpty())
+ return null;
+
+ if (Path.IsPathRooted(deployment.FileSystemPath))
+ {
+ path = deployment.FileSystemPath;
+ }
+ else
+ {
+ path = FileSystemHelper.ValidateRootPath(deployment.FileSystemPath);
+ path = CommonHelper.MapPath(path);
+ }
+ }
+
+ if (create && !System.IO.Directory.Exists(path))
+ System.IO.Directory.CreateDirectory(path);
+
+ return path;
+ }
+
+ ///
+ /// Get url of the public folder and take filtering and projection into consideration
+ ///
+ /// Export deployment
+ /// Common services
+ /// Store entity
+ /// Absolute URL of the public folder (always ends with /) or null
+ public static string GetPublicFolderUrl(this ExportDeployment deployment, ICommonServices services, Store store = null)
+ {
+ if (deployment != null && deployment.DeploymentType == ExportDeploymentType.PublicFolder)
+ {
+ if (store == null)
+ {
+ var filter = XmlHelper.Deserialize(deployment.Profile.Filtering);
+ var storeId = filter.StoreId;
+
+ if (storeId == 0)
+ {
+ var projection = XmlHelper.Deserialize(deployment.Profile.Projection);
+ storeId = (projection.StoreId ?? 0);
+ }
+
+ store = (storeId == 0 ? services.StoreContext.CurrentStore : services.StoreService.GetStoreById(storeId));
+ }
+
+ var url = string.Concat(
+ store.Url.EnsureEndsWith("/"),
+ DataExporter.PublicFolder.EnsureEndsWith("/"),
+ deployment.SubFolder.HasValue() ? deployment.SubFolder.EnsureEndsWith("/") : ""
+ );
+
+ return url;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Get icon class for a deployment type
+ ///
+ /// Deployment type
+ /// Icon class
+ public static string GetIconClass(this ExportDeploymentType type)
+ {
+ switch (type)
+ {
+ 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-files-o";
+ case ExportDeploymentType.PublicFolder:
+ return "fa-unlock";
+ default:
+ return "fa-question";
+ }
+ }
}
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/ExportProfileService.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/ExportProfileService.cs
index eb187c1657..1814ae56ae 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Export/ExportProfileService.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/ExportProfileService.cs
@@ -144,11 +144,11 @@ public virtual ExportProfile InsertExportProfile(
.Replace("/", "")
.Replace("-", "");
- profile.FolderName = SeoHelper.GetSeName(cleanedSystemName, true, false)
+ var folderName = SeoHelper.GetSeName(cleanedSystemName, true, false)
.ToValidPath()
.Truncate(_dataExchangeSettings.MaxFileNameLength);
- profile.FolderName = FileSystemHelper.CreateNonExistingDirectoryName(CommonHelper.MapPath("~/App_Data/ExportProfiles"), profile.FolderName);
+ profile.FolderName = "~/App_Data/ExportProfiles/" + FileSystemHelper.CreateNonExistingDirectoryName(CommonHelper.MapPath("~/App_Data/ExportProfiles"), folderName);
if (profileSystemName.IsEmpty() && isSystemProfile)
profile.SystemName = cleanedSystemName;
@@ -167,13 +167,15 @@ public virtual ExportProfile InsertExportProfile(
{
if (features.HasFlag(ExportFeatures.CreatesInitialPublicDeployment))
{
+ var subFolder = FileSystemHelper.CreateNonExistingDirectoryName(CommonHelper.MapPath("~/" + DataExporter.PublicFolder), folderName);
+
profile.Deployments.Add(new ExportDeployment
{
ProfileId = profile.Id,
Enabled = true,
- IsPublic = true,
- DeploymentType = ExportDeploymentType.FileSystem,
- Name = profile.Name
+ DeploymentType = ExportDeploymentType.PublicFolder,
+ Name = profile.Name,
+ SubFolder = subFolder
});
UpdateExportProfile(profile);
@@ -220,9 +222,7 @@ public virtual void UpdateExportProfile(ExportProfile profile)
if (profile == null)
throw new ArgumentNullException("profile");
- profile.FolderName = profile.FolderName
- .ToValidPath()
- .Truncate(_dataExchangeSettings.MaxFileNameLength);
+ profile.FolderName = FileSystemHelper.ValidateRootPath(profile.FolderName);
_exportProfileRepository.Update(profile);
@@ -342,6 +342,16 @@ public virtual ExportDeployment GetExportDeploymentById(int id)
return deployment;
}
+ public virtual void UpdateExportDeployment(ExportDeployment deployment)
+ {
+ if (deployment == null)
+ throw new ArgumentNullException("deployment");
+
+ _exportDeploymentRepository.Update(deployment);
+
+ _eventPublisher.EntityUpdated(deployment);
+ }
+
public virtual void DeleteExportDeployment(ExportDeployment deployment)
{
if (deployment == null)
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/ExportProviderBase.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/ExportProviderBase.cs
index 2a2d9618f1..c77638f60b 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Export/ExportProviderBase.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/ExportProviderBase.cs
@@ -28,22 +28,22 @@ public virtual ExportConfigurationInfo ConfigurationInfo
get { return null; }
}
+ public void Execute(ExportExecuteContext context)
+ {
+ Export(context);
+ }
+
///
/// Export data to a file
///
/// Export execution context
- protected abstract void Export(IExportExecuteContext context);
-
- public void Execute(IExportExecuteContext context)
- {
- Export(context);
- }
+ protected abstract void Export(ExportExecuteContext context);
///
/// Called once per store when export execution ended
///
/// Export execution context
- public virtual void OnExecuted(IExportExecuteContext context)
+ public virtual void OnExecuted(ExportExecuteContext context)
{
}
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/ExportXmlHelper.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/ExportXmlHelper.cs
index 6f84b5f064..68c8b78d55 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Export/ExportXmlHelper.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/ExportXmlHelper.cs
@@ -49,6 +49,8 @@ public static XmlWriterSettings DefaultSettings
}
}
+ public ExportXmlExclude Exclude { get; set; }
+
public XmlWriter Writer
{
get { return _writer; }
@@ -330,36 +332,41 @@ public void WriteCategory(dynamic category, string node)
}
_writer.Write("Id", entity.Id.ToString());
- _writer.Write("Name", (string)category.Name);
- _writer.Write("FullName", (string)category.FullName);
- _writer.Write("Description", (string)category.Description);
- _writer.Write("BottomDescription", (string)category.BottomDescription);
- _writer.Write("CategoryTemplateId", entity.CategoryTemplateId.ToString());
- _writer.Write("MetaKeywords", (string)category.MetaKeywords);
- _writer.Write("MetaDescription", (string)category.MetaDescription);
- _writer.Write("MetaTitle", (string)category.MetaTitle);
- _writer.Write("SeName", (string)category.SeName);
- _writer.Write("ParentCategoryId", entity.ParentCategoryId.ToString());
- _writer.Write("PictureId", entity.PictureId.HasValue ? entity.PictureId.Value.ToString() : "");
- _writer.Write("PageSize", entity.PageSize.ToString());
- _writer.Write("AllowCustomersToSelectPageSize", entity.AllowCustomersToSelectPageSize.ToString());
- _writer.Write("PageSizeOptions", entity.PageSizeOptions);
- _writer.Write("PriceRanges", entity.PriceRanges);
- _writer.Write("ShowOnHomePage", entity.ShowOnHomePage.ToString());
- _writer.Write("HasDiscountsApplied", entity.HasDiscountsApplied.ToString());
- _writer.Write("Published", entity.Published.ToString());
- _writer.Write("Deleted", entity.Deleted.ToString());
- _writer.Write("DisplayOrder", entity.DisplayOrder.ToString());
- _writer.Write("CreatedOnUtc", entity.CreatedOnUtc.ToString(_culture));
- _writer.Write("UpdatedOnUtc", entity.UpdatedOnUtc.ToString(_culture));
- _writer.Write("SubjectToAcl", entity.SubjectToAcl.ToString());
- _writer.Write("LimitedToStores", entity.LimitedToStores.ToString());
- _writer.Write("Alias", (string)category.Alias);
- _writer.Write("DefaultViewMode", entity.DefaultViewMode);
- WritePicture(category.Picture, "Picture");
+ if (!Exclude.HasFlag(ExportXmlExclude.Category))
+ {
+ _writer.Write("Name", (string)category.Name);
+ _writer.Write("FullName", (string)category.FullName);
+ _writer.Write("Description", (string)category.Description);
+ _writer.Write("BottomDescription", (string)category.BottomDescription);
+ _writer.Write("CategoryTemplateId", entity.CategoryTemplateId.ToString());
+ _writer.Write("CategoryTemplateViewPath", (string)category._CategoryTemplateViewPath);
+ _writer.Write("MetaKeywords", (string)category.MetaKeywords);
+ _writer.Write("MetaDescription", (string)category.MetaDescription);
+ _writer.Write("MetaTitle", (string)category.MetaTitle);
+ _writer.Write("SeName", (string)category.SeName);
+ _writer.Write("ParentCategoryId", entity.ParentCategoryId.ToString());
+ _writer.Write("PictureId", entity.PictureId.HasValue ? entity.PictureId.Value.ToString() : "");
+ _writer.Write("PageSize", entity.PageSize.ToString());
+ _writer.Write("AllowCustomersToSelectPageSize", entity.AllowCustomersToSelectPageSize.ToString());
+ _writer.Write("PageSizeOptions", entity.PageSizeOptions);
+ _writer.Write("PriceRanges", entity.PriceRanges);
+ _writer.Write("ShowOnHomePage", entity.ShowOnHomePage.ToString());
+ _writer.Write("HasDiscountsApplied", entity.HasDiscountsApplied.ToString());
+ _writer.Write("Published", entity.Published.ToString());
+ _writer.Write("Deleted", entity.Deleted.ToString());
+ _writer.Write("DisplayOrder", entity.DisplayOrder.ToString());
+ _writer.Write("CreatedOnUtc", entity.CreatedOnUtc.ToString(_culture));
+ _writer.Write("UpdatedOnUtc", entity.UpdatedOnUtc.ToString(_culture));
+ _writer.Write("SubjectToAcl", entity.SubjectToAcl.ToString());
+ _writer.Write("LimitedToStores", entity.LimitedToStores.ToString());
+ _writer.Write("Alias", (string)category.Alias);
+ _writer.Write("DefaultViewMode", entity.DefaultViewMode);
- WriteLocalized(category);
+ WritePicture(category.Picture, "Picture");
+
+ WriteLocalized(category);
+ }
if (node.HasValue())
{
@@ -897,4 +904,15 @@ public void WriteCustomer(dynamic customer, string node)
}
}
}
+
+
+ ///
+ /// Allows to exclude XML nodes from export
+ ///
+ [Flags]
+ public enum ExportXmlExclude
+ {
+ None = 0,
+ Category = 1
+ }
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/IExportProfileService.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/IExportProfileService.cs
index 7a61a36def..b0b0c8a6bd 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Export/IExportProfileService.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/IExportProfileService.cs
@@ -108,7 +108,13 @@ ExportProfile InsertExportProfile(
ExportDeployment GetExportDeploymentById(int id);
///
- /// Deleted a export deployment
+ /// Update an export deployment
+ ///
+ /// Export deployment
+ void UpdateExportDeployment(ExportDeployment deployment);
+
+ ///
+ /// Deleted an export deployment
///
/// Export deployment
void DeleteExportDeployment(ExportDeployment deployment);
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Export/IExportProvider.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/IExportProvider.cs
index e5248b20ba..60be2e11a9 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Export/IExportProvider.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/IExportProvider.cs
@@ -24,12 +24,12 @@ public partial interface IExportProvider : IProvider, IUserEditable
/// Export data to a file
///
/// Export execution context
- void Execute(IExportExecuteContext context);
+ void Execute(ExportExecuteContext context);
///
/// Called once per store when export execution ended
///
/// Export execution context
- void OnExecuted(IExportExecuteContext context);
+ void OnExecuted(ExportExecuteContext context);
}
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Internal/CategoryExportContext.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Internal/CategoryExportContext.cs
similarity index 100%
rename from src/Libraries/SmartStore.Services/DataExchange/Internal/CategoryExportContext.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Internal/CategoryExportContext.cs
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Internal/CustomerExportContext.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Internal/CustomerExportContext.cs
similarity index 100%
rename from src/Libraries/SmartStore.Services/DataExchange/Internal/CustomerExportContext.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Internal/CustomerExportContext.cs
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Internal/DataExporterContext.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Internal/DataExporterContext.cs
similarity index 94%
rename from src/Libraries/SmartStore.Services/DataExchange/Internal/DataExporterContext.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Internal/DataExporterContext.cs
index f909b93678..5c6c1315dd 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Internal/DataExporterContext.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Export/Internal/DataExporterContext.cs
@@ -34,7 +34,8 @@ public DataExporterContext(
Stores = new Dictionary();
Languages = new Dictionary();
Countries = new Dictionary();
- ProductTemplates = new Dictionary();
+ ProductTemplates = new Dictionary();
+ CategoryTemplates = new Dictionary();
NewsletterSubscriptions = new HashSet();
RecordsPerStore = new Dictionary();
@@ -109,7 +110,8 @@ public bool IsFileBasedExport
public Dictionary Stores { get; set; }
public Dictionary Languages { get; set; }
public Dictionary Countries { get; set; }
- public Dictionary ProductTemplates { get; set; }
+ public Dictionary ProductTemplates { get; set; }
+ public Dictionary CategoryTemplates { get; set; }
public HashSet NewsletterSubscriptions { get; set; }
// data loaded once per page
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Internal/DynamicEntity.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Internal/DynamicEntity.cs
similarity index 100%
rename from src/Libraries/SmartStore.Services/DataExchange/Internal/DynamicEntity.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Internal/DynamicEntity.cs
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Internal/ManufacturerExportContext.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Internal/ManufacturerExportContext.cs
similarity index 100%
rename from src/Libraries/SmartStore.Services/DataExchange/Internal/ManufacturerExportContext.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Internal/ManufacturerExportContext.cs
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Internal/OrderExportContext.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Internal/OrderExportContext.cs
similarity index 100%
rename from src/Libraries/SmartStore.Services/DataExchange/Internal/OrderExportContext.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Internal/OrderExportContext.cs
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Internal/ProductExportContext.cs b/src/Libraries/SmartStore.Services/DataExchange/Export/Internal/ProductExportContext.cs
similarity index 100%
rename from src/Libraries/SmartStore.Services/DataExchange/Internal/ProductExportContext.cs
rename to src/Libraries/SmartStore.Services/DataExchange/Export/Internal/ProductExportContext.cs
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Import/ColumnMapping/ColumnMap.cs b/src/Libraries/SmartStore.Services/DataExchange/Import/ColumnMapping/ColumnMap.cs
index 813f29b021..14a0ac77e9 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Import/ColumnMapping/ColumnMap.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Import/ColumnMapping/ColumnMap.cs
@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
-using System.Linq;
+using Newtonsoft.Json;
namespace SmartStore.Services.DataExchange.Import
{
public class ColumnMap
{
// maps source column to property
- private readonly Dictionary _map = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ private readonly Dictionary _map = new Dictionary(StringComparer.OrdinalIgnoreCase);
private static bool IsIndexed(string name)
{
@@ -24,27 +24,27 @@ private static string CreateSourceName(string name, string index)
return name;
}
- public IReadOnlyDictionary Mappings
+ public IReadOnlyDictionary Mappings
{
get { return _map; }
}
- public static bool ParseSourceColumn(string sourceColumn, out string columnWithoutIndex, out string index)
+ public static bool ParseSourceName(string sourceName, out string nameWithoutIndex, out string index)
{
- columnWithoutIndex = sourceColumn;
+ nameWithoutIndex = sourceName;
index = null;
var result = true;
- if (sourceColumn.HasValue() && IsIndexed(sourceColumn))
+ if (sourceName.HasValue() && IsIndexed(sourceName))
{
- var x1 = sourceColumn.IndexOf('[');
- var x2 = sourceColumn.IndexOf(']', x1);
+ var x1 = sourceName.IndexOf('[');
+ var x2 = sourceName.IndexOf(']', x1);
if (x1 != -1 && x2 != -1 && x2 > x1)
{
- columnWithoutIndex = sourceColumn.Substring(0, x1);
- index = sourceColumn.Substring(x1 + 1, x2 - x1 - 1);
+ nameWithoutIndex = sourceName.Substring(0, x1);
+ index = sourceName.Substring(x1 + 1, x2 - x1 - 1);
}
else
{
@@ -55,128 +55,93 @@ public static bool ParseSourceColumn(string sourceColumn, out string columnWitho
return result;
}
- //public IEnumerable> GetInvalidMappings()
- //{
- // var mappings = Mappings.Where(x =>
- // x.Value.Property.HasValue() &&
- // Mappings.Count(y => y.Value.Property.IsCaseInsensitiveEqual(x.Value.Property)) > 1
- // );
-
- // return mappings;
- //}
-
- public bool AddMapping(string sourceColumn, string entityProperty, string defaultValue = null)
+ public void AddMapping(string sourceName, string mappedName, string defaultValue = null)
{
- return AddMapping(sourceColumn, null, entityProperty, defaultValue);
+ AddMapping(sourceName, null, mappedName, defaultValue);
}
- public bool AddMapping(string sourceColumn, string index, string entityProperty, string defaultValue = null)
+ public void AddMapping(string sourceName, string index, string mappedName, string defaultValue = null)
{
- Guard.ArgumentNotEmpty(() => sourceColumn);
-
- var isAlreadyMapped = (entityProperty.HasValue() && _map.Any(x => x.Value.Property.IsCaseInsensitiveEqual(entityProperty)));
+ Guard.ArgumentNotEmpty(() => sourceName);
+ Guard.ArgumentNotEmpty(() => mappedName);
- if (isAlreadyMapped)
- return false;
+ var key = CreateSourceName(sourceName, index);
- _map[CreateSourceName(sourceColumn, index)] = new ColumnMappingValue
+ _map[key] = new ColumnMappingItem
{
- Property = entityProperty,
+ SoureName = key,
+ MappedName = mappedName,
Default = defaultValue
};
-
- return true;
}
///
/// Gets a mapped column value
///
- /// The name of the column to get a mapped value for.
- /// The mapped column value OR - if the name is unmapped - a value with the passed
- public ColumnMappingValue GetMapping(string sourceColumn)
- {
- ColumnMappingValue result;
-
- if (_map.TryGetValue(sourceColumn, out result))
- {
- // a) source column and property are equal or b) property should be ignored
- return result;
- }
-
- var crossPair = _map.FirstOrDefault(x => x.Value.Property.IsCaseInsensitiveEqual(sourceColumn));
-
- if (crossPair.Key.HasValue())
- {
- // source column and property are unequal
- return new ColumnMappingValue
- {
- Property = crossPair.Key,
- Default = (crossPair.Value != null ? crossPair.Value.Default : null)
- };
- }
-
- // there is no mapping at all
- return new ColumnMappingValue { Property = sourceColumn };
- }
-
- ///
- /// Gets a mapped column value
- ///
- /// The name of the column to get a mapped value for.
+ /// The name of the column to get a mapped value for.
/// The column index, e.g. a language code (de, en etc.)
- /// The mapped column value OR - if the name is unmapped - a value with the passed []
- public ColumnMappingValue GetMapping(string sourceColumn, string index)
+ /// The mapped column value OR - if the name is unmapped - a value with the passed []
+ public ColumnMappingItem GetMapping(string sourceName, string index)
{
- return GetMapping(CreateSourceName(sourceColumn, index));
+ return GetMapping(CreateSourceName(sourceName, index));
}
///
- /// Gets a mapped property name
+ /// Gets a mapped column value
///
- /// The name of the column to get a mapped property name for.
- /// The mapped property name OR - if the name is unmapped - the passed []
- public string GetMappedProperty(string sourceColumn)
+ /// The name of the column to get a mapped value for.
+ /// The mapped column value OR - if the name is unmapped - the value of the passed
+ public ColumnMappingItem GetMapping(string sourceName)
{
- ColumnMappingValue result;
+ ColumnMappingItem result;
- if (_map.TryGetValue(sourceColumn, out result))
+ if (_map.TryGetValue(sourceName, out result))
{
- return result.Property;
- }
-
- var crossPair = _map.FirstOrDefault(x => x.Value.Property.IsCaseInsensitiveEqual(sourceColumn));
-
- if (crossPair.Key.HasValue())
- {
- return crossPair.Key;
+ return result;
}
- return sourceColumn;
- }
-
- ///
- /// Gets a mapped property name
- ///
- /// The name of the column to get a mapped property name for.
- /// The column index, e.g. a language code (de, en etc.)
- /// The mapped property name OR - if the name is unmapped - the passed []
- public string GetMappedProperty(string sourceColumn, string index)
- {
- return GetMappedProperty(CreateSourceName(sourceColumn, index));
+ return new ColumnMappingItem { SoureName = sourceName, MappedName = sourceName };
}
}
- public class ColumnMappingValue
+ [JsonObject(MemberSerialization.OptIn)]
+ public class ColumnMappingItem
{
+ private bool? _ignored;
+
+ ///
+ /// The source name
+ ///
+ [JsonIgnore]
+ public string SoureName { get; set; }
+
///
- /// The property name of the target entity
+ /// The mapped name
///
- public string Property { get; set; }
+ [JsonProperty]
+ public string MappedName { get; set; }
///
/// An optional default value
///
+ [JsonProperty]
public string Default { get; set; }
+
+ ///
+ /// Indicates whether to explicitly ignore this property
+ ///
+ public bool IgnoreProperty
+ {
+ get
+ {
+ if (_ignored == null)
+ {
+ _ignored = Default != null && Default == "[IGNOREPROPERTY]";
+ }
+
+ return _ignored.Value;
+ }
+ }
}
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Import/ColumnMapping/ColumnMapConverter.cs b/src/Libraries/SmartStore.Services/DataExchange/Import/ColumnMapping/ColumnMapConverter.cs
index 78cbd7fa13..c46b90b82a 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Import/ColumnMapping/ColumnMapConverter.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Import/ColumnMapping/ColumnMapConverter.cs
@@ -27,12 +27,12 @@ public override object ConvertFrom(CultureInfo culture, object value)
{
if (value is string)
{
- var dict = JsonConvert.DeserializeObject>((string)value);
+ var dict = JsonConvert.DeserializeObject>((string)value);
var map = new ColumnMap();
foreach (var kvp in dict)
{
- map.AddMapping(kvp.Key, null, kvp.Value.Property, kvp.Value.Default);
+ map.AddMapping(kvp.Key, null, kvp.Value.MappedName, kvp.Value.Default);
}
return map;
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Import/DataImporter.cs b/src/Libraries/SmartStore.Services/DataExchange/Import/DataImporter.cs
index 9413254f3d..aeb4b81897 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Import/DataImporter.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Import/DataImporter.cs
@@ -1,166 +1,57 @@
using System;
using System.IO;
-using System.Linq;
using System.Text;
using System.Threading;
+using System.Linq;
using SmartStore.Core;
-using SmartStore.Core.Data;
-using SmartStore.Core.Domain.Catalog;
using SmartStore.Core.Domain.Common;
using SmartStore.Core.Domain.Customers;
using SmartStore.Core.Domain.DataExchange;
-using SmartStore.Core.Domain.Forums;
-using SmartStore.Core.Domain.Media;
-using SmartStore.Core.Domain.Messages;
-using SmartStore.Core.Domain.Seo;
using SmartStore.Core.Email;
using SmartStore.Core.Localization;
using SmartStore.Core.Logging;
-using SmartStore.Services.Affiliates;
-using SmartStore.Services.Catalog;
-using SmartStore.Services.Catalog.Importer;
-using SmartStore.Services.Common;
-using SmartStore.Services.Customers;
-using SmartStore.Services.Customers.Importer;
using SmartStore.Services.DataExchange.Csv;
using SmartStore.Services.DataExchange.Import.Internal;
-using SmartStore.Services.Directory;
-using SmartStore.Services.Helpers;
using SmartStore.Services.Localization;
-using SmartStore.Services.Media;
using SmartStore.Services.Messages;
-using SmartStore.Services.Messages.Importer;
using SmartStore.Services.Security;
-using SmartStore.Services.Seo;
-using SmartStore.Services.Stores;
using SmartStore.Utilities;
namespace SmartStore.Services.DataExchange.Import
{
public partial class DataImporter : IDataImporter
{
- #region Dependencies
-
private readonly ICommonServices _services;
- private readonly ICustomerService _customerService;
private readonly IImportProfileService _importProfileService;
-
- private readonly Lazy> _subscriptionRepository;
- private readonly Lazy> _pictureRepository;
- private readonly Lazy> _productPictureRepository;
- private readonly Lazy> _productManufacturerRepository;
- private readonly Lazy> _productCategoryRepository;
- private readonly Lazy> _urlRecordRepository;
- private readonly Lazy> _productRepository;
- private readonly Lazy> _customerRepository;
- private readonly Lazy> _categoryRepository;
-
- private readonly Lazy _languageService;
- private readonly Lazy _localizedEntityService;
- private readonly Lazy _pictureService;
- private readonly Lazy _manufacturerService;
- private readonly Lazy _categoryService;
- private readonly Lazy _categoryTemplateService;
- private readonly Lazy _productTemplateService;
- private readonly Lazy _productService;
- private readonly Lazy _urlRecordService;
- private readonly Lazy _storeMappingService;
- private readonly Lazy _genericAttributeService;
- private readonly Lazy _affiliateService;
- private readonly Lazy _countryService;
- private readonly Lazy _stateProvinceService;
+ private readonly ILanguageService _languageService;
+ private readonly Func _importerFactory;
private readonly Lazy _emailAccountService;
private readonly Lazy _emailSender;
- private readonly Lazy _fileDownloadManager;
-
- private readonly Lazy _seoSettings;
- private readonly Lazy _customerSettings;
- private readonly Lazy _dateTimeSettings;
- private readonly Lazy _forumSettings;
private readonly Lazy _contactDataSettings;
private readonly Lazy _dataExchangeSettings;
public DataImporter(
ICommonServices services,
- ICustomerService customerService,
IImportProfileService importProfileService,
- Lazy> subscriptionRepository,
- Lazy> pictureRepository,
- Lazy> productPictureRepository,
- Lazy> productManufacturerRepository,
- Lazy> productCategoryRepository,
- Lazy> urlRecordRepository,
- Lazy> productRepository,
- Lazy> customerRepository,
- Lazy> categoryRepository,
- Lazy languageService,
- Lazy localizedEntityService,
- Lazy pictureService,
- Lazy manufacturerService,
- Lazy categoryService,
- Lazy categoryTemplateService,
- Lazy productTemplateService,
- Lazy productService,
- Lazy urlRecordService,
- Lazy storeMappingService,
- Lazy genericAttributeService,
- Lazy affiliateService,
- Lazy countryService,
- Lazy stateProvinceService,
+ ILanguageService languageService,
+ Func importerFactory,
Lazy emailAccountService,
Lazy emailSender,
- Lazy fileDownloadManager,
- Lazy seoSettings,
- Lazy customerSettings,
- Lazy dateTimeSettings,
- Lazy forumSettings,
Lazy contactDataSettings,
Lazy dataExchangeSettings)
{
_services = services;
- _customerService = customerService;
_importProfileService = importProfileService;
-
- _subscriptionRepository = subscriptionRepository;
- _pictureRepository = pictureRepository;
- _productPictureRepository = productPictureRepository;
- _productManufacturerRepository = productManufacturerRepository;
- _productCategoryRepository = productCategoryRepository;
- _urlRecordRepository = urlRecordRepository;
- _productRepository = productRepository;
- _customerRepository = customerRepository;
- _categoryRepository = categoryRepository;
-
_languageService = languageService;
- _localizedEntityService = localizedEntityService;
- _pictureService = pictureService;
- _manufacturerService = manufacturerService;
- _categoryService = categoryService;
- _categoryTemplateService = categoryTemplateService;
- _productTemplateService = productTemplateService;
- _productService = productService;
- _urlRecordService = urlRecordService;
- _storeMappingService = storeMappingService;
- _genericAttributeService = genericAttributeService;
- _affiliateService = affiliateService;
- _countryService = countryService;
- _stateProvinceService = stateProvinceService;
+ _importerFactory = importerFactory;
_emailAccountService = emailAccountService;
_emailSender = emailSender;
- _fileDownloadManager = fileDownloadManager;
-
- _seoSettings = seoSettings;
- _customerSettings = customerSettings;
- _dateTimeSettings = dateTimeSettings;
- _forumSettings = forumSettings;
_contactDataSettings = contactDataSettings;
_dataExchangeSettings = dataExchangeSettings;
T = NullLocalizer.Instance;
}
- #endregion
-
public Localizer T { get; set; }
private bool HasPermission(DataImporterContext ctx)
@@ -310,7 +201,7 @@ private void ImportCoreInner(DataImporterContext ctx, string filePath)
CsvConfiguration csvConfiguration = null;
var extension = Path.GetExtension(filePath);
- if (extension.IsCaseInsensitiveEqual(".csv"))
+ if ((new string[] { ".csv", ".txt", ".tab" }).Contains(extension, StringComparer.OrdinalIgnoreCase))
{
var converter = new CsvConfigurationConverter();
csvConfiguration = converter.ConvertFrom(ctx.Request.Profile.FileTypeConfiguration);
@@ -365,11 +256,14 @@ private void ImportCoreOuter(DataImporterContext ctx)
{
ctx.Log = logger;
+ ctx.ExecuteContext.DataExchangeSettings = _dataExchangeSettings.Value;
+ ctx.ExecuteContext.Services = _services;
ctx.ExecuteContext.Log = logger;
- ctx.ExecuteContext.Languages = _languageService.Value.GetAllLanguages(true);
+ ctx.ExecuteContext.Languages = _languageService.GetAllLanguages(true);
ctx.ExecuteContext.UpdateOnly = ctx.Request.Profile.UpdateOnly;
ctx.ExecuteContext.KeyFieldNames = ctx.Request.Profile.KeyFieldNames.SplitSafe(",");
ctx.ExecuteContext.ImportFolder = ctx.Request.Profile.GetImportFolder();
+ ctx.ExecuteContext.ExtraData = XmlHelper.Deserialize(ctx.Request.Profile.ExtraData);
{
var mapConverter = new ColumnMapConverter();
@@ -379,76 +273,12 @@ private void ImportCoreOuter(DataImporterContext ctx)
var files = ctx.Request.Profile.GetImportFiles();
if (files.Count == 0)
- throw new SmartException("No files to import found.");
+ throw new SmartException("No files to import.");
if (!HasPermission(ctx))
throw new SmartException("You do not have permission to perform the selected import.");
- if (ctx.Request.Profile.EntityType == ImportEntityType.Product)
- {
- ctx.Importer = new ProductImporter(
- _productPictureRepository.Value,
- _productManufacturerRepository.Value,
- _productCategoryRepository.Value,
- _urlRecordRepository.Value,
- _productRepository.Value,
- _services,
- _localizedEntityService.Value,
- _pictureService.Value,
- _manufacturerService.Value,
- _categoryService.Value,
- _productService.Value,
- _urlRecordService.Value,
- _productTemplateService.Value,
- _storeMappingService.Value,
- _fileDownloadManager.Value,
- _seoSettings.Value,
- _dataExchangeSettings.Value);
- }
- else if (ctx.Request.Profile.EntityType == ImportEntityType.Customer)
- {
- ctx.Importer = new CustomerImporter(
- _customerRepository.Value,
- _pictureRepository.Value,
- _services,
- _genericAttributeService.Value,
- _customerService,
- _pictureService.Value,
- _affiliateService.Value,
- _countryService.Value,
- _stateProvinceService.Value,
- _fileDownloadManager.Value,
- _customerSettings.Value,
- _dateTimeSettings.Value,
- _forumSettings.Value,
- _dataExchangeSettings.Value);
- }
- else if (ctx.Request.Profile.EntityType == ImportEntityType.NewsLetterSubscription)
- {
- ctx.Importer = new NewsLetterSubscriptionImporter(
- _services,
- _subscriptionRepository.Value);
- }
- else if (ctx.Request.Profile.EntityType == ImportEntityType.Category)
- {
- ctx.Importer = new CategoryImporter(
- _categoryRepository.Value,
- _urlRecordRepository.Value,
- _pictureRepository.Value,
- _services,
- _urlRecordService.Value,
- _categoryTemplateService.Value,
- _storeMappingService.Value,
- _pictureService.Value,
- _localizedEntityService.Value,
- _fileDownloadManager.Value,
- _seoSettings.Value,
- _dataExchangeSettings.Value);
- }
- else
- {
- throw new SmartException("Unsupported entity type {0}.".FormatInvariant(ctx.Request.Profile.EntityType.ToString()));
- }
+ ctx.Importer = _importerFactory(ctx.Request.Profile.EntityType);
files.ForEach(x => ImportCoreInner(ctx, x));
}
@@ -462,7 +292,7 @@ private void ImportCoreOuter(DataImporterContext ctx)
{
// database context sharing problem: if there are entities in modified state left by the provider due to SaveChanges failure,
// then all subsequent SaveChanges would fail too (e.g. IImportProfileService.UpdateImportProfile, IScheduledTaskService.UpdateTask...).
- // so whatever it is, detach\dispose all that the tracker still has tracked.
+ // so whatever it is, detach\dispose all what the tracker still has tracked.
_services.DbContext.DetachAll(false);
}
diff --git a/src/Libraries/SmartStore.Services/DataExchange/Import/DataTable/LightweightDataTable.cs b/src/Libraries/SmartStore.Services/DataExchange/Import/DataTable/LightweightDataTable.cs
index 68cb99eb9c..52be0a8dfa 100644
--- a/src/Libraries/SmartStore.Services/DataExchange/Import/DataTable/LightweightDataTable.cs
+++ b/src/Libraries/SmartStore.Services/DataExchange/Import/DataTable/LightweightDataTable.cs
@@ -31,6 +31,8 @@ public LightweightDataTable(IList columns, IList