diff --git a/changelog.md b/changelog.md index ee4dac3816..54b3446ec3 100644 --- a/changelog.md +++ b/changelog.md @@ -33,7 +33,7 @@ * (Developer) Moved _PublicControllerBase_ to SmartStore.Web.Framework * (Developer) Moved 'AdminControllerBase' to SmartStore.Web.Framework * #384 Web API: Inserting sluged recources like products require an URL record -* Promotion feed plugins: Asynchronous feed creation +* #382 Promotion feed plugins: Asynchronous feed creation, more options and improvements ###Bugfixes### * Twitter Auth: fixed _SecurityTransparent_ error diff --git a/src/Libraries/SmartStore.Core/Data/IDbContext.cs b/src/Libraries/SmartStore.Core/Data/IDbContext.cs index 435f028db7..b44aa4398b 100644 --- a/src/Libraries/SmartStore.Core/Data/IDbContext.cs +++ b/src/Libraries/SmartStore.Core/Data/IDbContext.cs @@ -85,5 +85,21 @@ IList ExecuteStoredProcedureList(string commandText, params ob /// /// The count of detached entities int DetachAll(); + + /// + /// Change the state of an entity object + /// + /// Type of entity + /// The entity instance + /// The new state + void ChangeState(TEntity entity, System.Data.Entity.EntityState newState); + + /// + /// Changes the object state to unchanged + /// + /// Type of entity + /// The entity instance + /// true on success, false on failure + bool SetToUnchanged(TEntity entity); } } diff --git a/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs index e6c43295f1..fe91de3eef 100644 --- a/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/MiscExtensions.cs @@ -6,6 +6,7 @@ using System.ComponentModel; using System.Web.Routing; using SmartStore.Core; +using System.Globalization; namespace SmartStore { @@ -138,5 +139,16 @@ public static void Grow(this StringBuilder sb, string grow, string delimiter) sb.AppendFormat("{0}{1}", delimiter, grow); } } + + /// + /// Rounds and formats a decimal culture invariant + /// + /// The decimal + /// Rounding decimal number + /// Formated value + public static string FormatInvariant(this decimal value, int decimals = 2) + { + return Math.Round(value, decimals).ToString("0.00", CultureInfo.InvariantCulture); + } } } diff --git a/src/Libraries/SmartStore.Core/Extensions/StringExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/StringExtensions.cs index fd86ff3305..f70a9ac1c4 100644 --- a/src/Libraries/SmartStore.Core/Extensions/StringExtensions.cs +++ b/src/Libraries/SmartStore.Core/Extensions/StringExtensions.cs @@ -712,8 +712,6 @@ public static string RemoveEncloser(this string value, string start, string end, return value; } - // codehint: sm-add (begin) - /// Debug.WriteLine /// codehint: sm-add [DebuggerStepThrough] @@ -999,7 +997,19 @@ public static string RemoveInvalidXmlChars(this string s) return Regex.Replace(s, @"[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD]", "", RegexOptions.Compiled); } - // codehint: sm-add (end) + [DebuggerStepThrough] + public static string ReplaceCsvChars(this string s) + { + if (s.HasValue()) + { + s = s.Replace(';', ','); + s = s.Replace('\r', ' '); + s = s.Replace('\n', ' '); + return s.Replace("'", ""); + } + return ""; + } + #endregion #region Helper diff --git a/src/Libraries/SmartStore.Data/ObjectContextBase.cs b/src/Libraries/SmartStore.Data/ObjectContextBase.cs index 8e50f448e3..ea02ce336d 100644 --- a/src/Libraries/SmartStore.Data/ObjectContextBase.cs +++ b/src/Libraries/SmartStore.Data/ObjectContextBase.cs @@ -519,6 +519,25 @@ public int DetachAll() return attachedEntities.Count; } + public void ChangeState(TEntity entity, System.Data.Entity.EntityState newState) + { + ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.ChangeObjectState(entity, newState); + } + + public bool SetToUnchanged(TEntity entity) + { + try + { + ChangeState(entity, System.Data.Entity.EntityState.Unchanged); + return true; + } + catch (Exception exc) + { + exc.Dump(); + return false; + } + } + private string FormatValidationExceptionMessage(IEnumerable results) { var sb = new StringBuilder(); diff --git a/src/Plugins/Feed.Froogle/Description.txt b/src/Plugins/Feed.Froogle/Description.txt index d1ee45ff55..696044b1c7 100644 --- a/src/Plugins/Feed.Froogle/Description.txt +++ b/src/Plugins/Feed.Froogle/Description.txt @@ -1,6 +1,6 @@ FriendlyName: Google Merchant Center (GMC) SystemName: PromotionFeed.Froogle -Version: 2.2 +Version: 2.21 MinAppVersion: 2.0.0 Author: SmartStore AG DisplayOrder: 1 diff --git a/src/Plugins/Feed.Froogle/FroogleFeedPlugin.cs b/src/Plugins/Feed.Froogle/FroogleFeedPlugin.cs index b466b0dbf9..6f28b6f27e 100644 --- a/src/Plugins/Feed.Froogle/FroogleFeedPlugin.cs +++ b/src/Plugins/Feed.Froogle/FroogleFeedPlugin.cs @@ -23,10 +23,10 @@ public class FroogleFeedPlugin : BasePlugin, IMiscPlugin GoogleProductObjectContext objectContext, ILocalizationService localizationService) { - this._googleService = googleService; - this._settingService = settingService; - this._objectContext = objectContext; - this._localizationService = localizationService; + _googleService = googleService; + _settingService = settingService; + _objectContext = objectContext; + _localizationService = localizationService; } /// @@ -69,7 +69,7 @@ public override void Uninstall() _settingService.DeleteSetting(); - _localizationService.DeleteLocaleStringResources(this.PluginDescriptor.ResourceRootKey); + _localizationService.DeletePluginStringResources(this.PluginDescriptor); var migrator = new DbMigrator(new Configuration()); migrator.Update(DbMigrator.InitialDatabase); diff --git a/src/Plugins/Feed.Froogle/Localization/resources.de-de.xml b/src/Plugins/Feed.Froogle/Localization/resources.de-de.xml index c0b2a68a8c..cd62e58d7f 100644 --- a/src/Plugins/Feed.Froogle/Localization/resources.de-de.xml +++ b/src/Plugins/Feed.Froogle/Localization/resources.de-de.xml @@ -266,4 +266,16 @@ Aktivieren Sie diese Option, wenn Sie denGrundpreis des Produkt exportieren möchten. + + Netto- in Bruttopreise umrechnen + + + Legt fest, dass Netto- in Bruttopreise umgerechnet werden sollen. + + + Sprache + + + Legt die Sprache fest, in der sprachabhängige Werte (z.B. der Produktname) exportiert werden sollen. + \ No newline at end of file diff --git a/src/Plugins/Feed.Froogle/Localization/resources.en-us.xml b/src/Plugins/Feed.Froogle/Localization/resources.en-us.xml index 570b734049..a0349ff79b 100644 --- a/src/Plugins/Feed.Froogle/Localization/resources.en-us.xml +++ b/src/Plugins/Feed.Froogle/Localization/resources.en-us.xml @@ -266,4 +266,16 @@ Activate this option if you want to export the base price of the product. + + Convert net into gross prices + + + Determines to convert net into gross prices. + + + Language + + + Determines which language to use to export language dependent values (for instance the product name). + \ No newline at end of file diff --git a/src/Plugins/Feed.Froogle/Models/FeedFroogleModel.cs b/src/Plugins/Feed.Froogle/Models/FeedFroogleModel.cs index 4ef68dcad0..4e2d621dcf 100644 --- a/src/Plugins/Feed.Froogle/Models/FeedFroogleModel.cs +++ b/src/Plugins/Feed.Froogle/Models/FeedFroogleModel.cs @@ -106,6 +106,12 @@ public string AvailableGoogleCategoriesAsJson [SmartResourceDisplayName("Plugins.Feed.Froogle.ExportBasePrice")] public bool ExportBasePrice { get; set; } + [SmartResourceDisplayName("Plugins.Feed.Froogle.ConvertNetToGrossPrices")] + public bool ConvertNetToGrossPrices { get; set; } + + [SmartResourceDisplayName("Plugins.Feed.Froogle.LanguageId")] + public int LanguageId { get; set; } + public void Copy(FroogleSettings settings, bool fromSettings) { if (fromSettings) @@ -137,6 +143,8 @@ public void Copy(FroogleSettings settings, bool fromSettings) ExpirationDays = settings.ExpirationDays; ExportShipping = settings.ExportShipping; ExportBasePrice = settings.ExportBasePrice; + ConvertNetToGrossPrices = settings.ConvertNetToGrossPrices; + LanguageId = settings.LanguageId; } else { @@ -167,6 +175,8 @@ public void Copy(FroogleSettings settings, bool fromSettings) settings.ExpirationDays = ExpirationDays; settings.ExportShipping = ExportShipping; settings.ExportBasePrice = ExportBasePrice; + settings.ConvertNetToGrossPrices = ConvertNetToGrossPrices; + settings.LanguageId = LanguageId; } } } diff --git a/src/Plugins/Feed.Froogle/Services/GoogleFeedService.cs b/src/Plugins/Feed.Froogle/Services/GoogleFeedService.cs index 0e8e02eceb..eaf83698eb 100644 --- a/src/Plugins/Feed.Froogle/Services/GoogleFeedService.cs +++ b/src/Plugins/Feed.Froogle/Services/GoogleFeedService.cs @@ -1,31 +1,26 @@ +using Autofac; +using Telerik.Web.Mvc; using System; using System.IO; using System.Linq; using System.Text; using System.Xml; +using System.Web; +using System.Web.Mvc; +using System.Collections.Generic; using System.Globalization; +using SmartStore.Web.Framework.Plugins; +using SmartStore.Plugin.Feed.Froogle.Domain; +using SmartStore.Plugin.Feed.Froogle.Models; using SmartStore.Core.Data; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Directory; -using SmartStore.Services.Catalog; -using SmartStore.Plugin.Feed.Froogle.Domain; -using SmartStore.Plugin.Feed.Froogle.Models; -using SmartStore.Web.Framework.Plugins; -using Telerik.Web.Mvc; -using SmartStore.Core.Domain.Tasks; -using SmartStore.Services.Stores; using SmartStore.Core.Domain.Stores; -using System.Web.Mvc; -using System.Collections.Generic; -using SmartStore.Web.Framework; -using SmartStore.Services.Directory; -using SmartStore.Core; using SmartStore.Core.Logging; -using Autofac; -using System.Threading; -using SmartStore.Core.Async; -using System.Web; +using SmartStore.Services.Catalog; +using SmartStore.Services.Directory; using SmartStore.Services.Tasks; +using SmartStore.Services.Localization; namespace SmartStore.Plugin.Feed.Froogle.Services { @@ -37,36 +32,27 @@ public partial class GoogleFeedService : IGoogleFeedService private readonly IRepository _gpRepository; private readonly IProductService _productService; private readonly IManufacturerService _manufacturerService; - private readonly IStoreService _storeService; - private readonly ICategoryService _categoryService; private readonly IMeasureService _measureService; private readonly MeasureSettings _measureSettings; - private readonly IPriceCalculationService _priceCalculationService; - private readonly IWorkContext _workContext; + private readonly IDbContext _dbContext; public GoogleFeedService( IRepository gpRepository, IProductService productService, IManufacturerService manufacturerService, - IStoreService storeService, - ICategoryService categoryService, FroogleSettings settings, IMeasureService measureService, MeasureSettings measureSettings, - IPriceCalculationService priceCalculationService, - IWorkContext workContext, + IDbContext dbContext, IComponentContext ctx) { _gpRepository = gpRepository; _productService = productService; _manufacturerService = manufacturerService; - _storeService = storeService; - _categoryService = categoryService; Settings = settings; _measureService = measureService; _measureSettings = measureSettings; - _priceCalculationService = priceCalculationService; - _workContext = workContext; + _dbContext = dbContext; _helper = new FeedPluginHelper(ctx, "PromotionFeed.Froogle", "SmartStore.Plugin.Feed.Froogle", () => { @@ -306,7 +292,12 @@ private string WriteItem(XmlWriter writer, Store store, Product product, Currenc if (category.IsNullOrEmpty()) return Helper.GetResource("MissingDefaultCategory"); - var brand = (manu != null && manu.Manufacturer.Name.HasValue() ? manu.Manufacturer.Name : Settings.Brand); + string manuName = (manu != null ? manu.Manufacturer.GetLocalized(x => x.Name, Settings.LanguageId, true, false) : null); + string productName = product.GetLocalized(x => x.Name, Settings.LanguageId, true, false); + string shortDescription = product.GetLocalized(x => x.ShortDescription, Settings.LanguageId, true, false); + string fullDescription = product.GetLocalized(x => x.FullDescription, Settings.LanguageId, true, false); + + var brand = (manuName ?? Settings.Brand); var mpn = Helper.GetManufacturerPartNumber(product); bool identifierExists = product.Gtin.HasValue() || brand.HasValue() || mpn.HasValue(); @@ -314,12 +305,12 @@ private string WriteItem(XmlWriter writer, Store store, Product product, Currenc writer.WriteElementString("g", "id", _googleNamespace, product.Id.ToString()); writer.WriteStartElement("title"); - writer.WriteCData(product.Name.Truncate(70)); + writer.WriteCData(productName.Truncate(70)); writer.WriteEndElement(); - var description = Helper.BuildProductDescription(product, manu, d => + var description = Helper.BuildProductDescription(productName, shortDescription, fullDescription, manuName, d => { - if (product.FullDescription.IsNullOrEmpty() && product.ShortDescription.IsNullOrEmpty()) + if (fullDescription.IsNullOrEmpty() && shortDescription.IsNullOrEmpty()) { var rnd = new Random(); @@ -362,24 +353,24 @@ private string WriteItem(XmlWriter writer, Store store, Product product, Currenc writer.WriteElementString("g", "condition", _googleNamespace, Condition()); writer.WriteElementString("g", "availability", _googleNamespace, Availability(product)); - decimal priceBase = _priceCalculationService.GetFinalPrice(product, null, _workContext.CurrentCustomer, decimal.Zero, true, 1); - decimal price = Helper.ConvertFromStoreCurrency(priceBase, currency); + decimal price = Helper.GetProductPrice(product, currency); string specialPriceDate; if (SpecialPrice(product, out specialPriceDate)) { - writer.WriteElementString("g", "sale_price", _googleNamespace, Helper.DecimalUsFormat(price) + " " + currency.CurrencyCode); + writer.WriteElementString("g", "sale_price", _googleNamespace, price.FormatInvariant() + " " + currency.CurrencyCode); writer.WriteElementString("g", "sale_price_effective_date", _googleNamespace, specialPriceDate); - // get regular price + // get regular price ignoring any special price decimal specialPrice = product.SpecialPrice.Value; product.SpecialPrice = null; - priceBase = _priceCalculationService.GetFinalPrice(product, null, _workContext.CurrentCustomer, decimal.Zero, true, 1); + price = Helper.GetProductPrice(product, currency); product.SpecialPrice = specialPrice; - price = Helper.ConvertFromStoreCurrency(priceBase, currency); + + _dbContext.SetToUnchanged(product); } - writer.WriteElementString("g", "price", _googleNamespace, Helper.DecimalUsFormat(price) + " " + currency.CurrencyCode); + writer.WriteElementString("g", "price", _googleNamespace, price.FormatInvariant() + " " + currency.CurrencyCode); writer.WriteCData("gtin", product.Gtin, "g", _googleNamespace); writer.WriteCData("brand", brand, "g", _googleNamespace); @@ -403,7 +394,7 @@ private string WriteItem(XmlWriter writer, Store store, Product product, Currenc if (Settings.ExportShipping) { - string weightInfo, weight = Helper.DecimalUsFormat(product.Weight); + string weightInfo, weight = product.Weight.FormatInvariant(); if (measureWeightSystemKey.IsCaseInsensitiveEqual("gram")) weightInfo = weight + " g"; @@ -423,7 +414,7 @@ private string WriteItem(XmlWriter writer, Store store, Product product, Currenc if (BasePriceSupported(product.BasePriceBaseAmount ?? 0, measureUnit)) { - string basePriceMeasure = "{0} {1}".FormatWith(Helper.DecimalUsFormat(product.BasePriceAmount ?? decimal.Zero), measureUnit); + string basePriceMeasure = "{0} {1}".FormatWith((product.BasePriceAmount ?? decimal.Zero).FormatInvariant(), measureUnit); string basePriceBaseMeasure = "{0} {1}".FormatWith(product.BasePriceBaseAmount, measureUnit); writer.WriteElementString("g", "unit_pricing_measure", _googleNamespace, basePriceMeasure); diff --git a/src/Plugins/Feed.Froogle/Views/FeedFroogle/Configure.cshtml b/src/Plugins/Feed.Froogle/Views/FeedFroogle/Configure.cshtml index 3d15b0f11b..e3f687db16 100644 --- a/src/Plugins/Feed.Froogle/Views/FeedFroogle/Configure.cshtml +++ b/src/Plugins/Feed.Froogle/Views/FeedFroogle/Configure.cshtml @@ -58,12 +58,15 @@ @foreach (var group in Model.GeneratedFiles.GroupBy(x => x.StoreId)) { + var firstFile = group.First();

- @(group.First().StoreName): + @(firstFile.StoreName): @foreach (var file in group) {
@file.FileUrl } +
@T("Admin.Configuration.ActivityLog"), + @T("Common.UpdatedOn"): @(firstFile.LastWriteTime)

} @@ -149,6 +152,15 @@ @Html.ValidationMessageFor(model => model.StoreId) + + + @Html.SmartLabelFor(model => model.LanguageId) + + + @Html.DropDownListFor(model => model.LanguageId, Model.AvailableLanguages) + @Html.ValidationMessageFor(model => model.LanguageId) + + @Html.SmartLabelFor(m => m.BuildDescription) @@ -399,6 +411,15 @@ @Html.ValidationMessageFor(m => m.OnlineOnly) + + + @Html.SmartLabelFor(m => m.ConvertNetToGrossPrices) + + + @Html.EditorFor(m => m.ConvertNetToGrossPrices) + @Html.ValidationMessageFor(m => m.ConvertNetToGrossPrices) + + @Html.SmartLabelFor(m => m.TaskEnabled) diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginCore.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginCore.cs index c79c1ca8e9..862f6e441e 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginCore.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginCore.cs @@ -23,6 +23,8 @@ public class PromotionFeedSettings public bool UseOwnProductNo { get; set; } public int StoreId { get; set; } public string ExportFormat { get; set; } + public bool ConvertNetToGrossPrices { get; set; } + public int LanguageId { get; set; } } @@ -43,6 +45,7 @@ public PromotionFeedConfigModel() [SmartResourceDisplayName("Plugins.KnownGroup.PromotionFeed")] public List GeneratedFiles { get; set; } public List AvailableStores { get; set; } + public List AvailableLanguages { get; set; } } @@ -53,6 +56,8 @@ public class FeedFileData : ModelBase public string FilePath { get; set; } public string FileUrl { get; set; } public string LogPath { get; set; } + public string LogUrl { get; set; } + public string LastWriteTime { get; set; } } diff --git a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs index df442cb1b1..bf88e2d41f 100644 --- a/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs +++ b/src/Presentation/SmartStore.Web.Framework/Plugins/FeedPluginHelper.cs @@ -4,7 +4,12 @@ using System.Globalization; using System.IO; using System.Web; +using System.Web.Mvc; +using System.Threading; +using System.Threading.Tasks; using Autofac; +using SmartStore.Core; +using SmartStore.Core.Domain.Directory; using SmartStore.Core.Domain.Catalog; using SmartStore.Core.Domain.Tasks; using SmartStore.Core.Domain.Stores; @@ -16,10 +21,8 @@ using SmartStore.Services.Tasks; using SmartStore.Services.Stores; using SmartStore.Services.Seo; -using System.Web.Mvc; -using System.Threading; -using System.Threading.Tasks; using SmartStore.Services.Localization; +using SmartStore.Services.Tax; namespace SmartStore.Web.Framework.Plugins { @@ -88,6 +91,24 @@ private ILanguageService LanguageService get { return _languageService ?? (_languageService = _ctx.Resolve()); } } + private IPriceCalculationService _priceCalculationService; + private IPriceCalculationService PriceCalculationService + { + get { return _priceCalculationService ?? (_priceCalculationService = _ctx.Resolve()); } + } + + private ITaxService _taxService; + private ITaxService TaxService + { + get { return _taxService ?? (_taxService = _ctx.Resolve()); } + } + + private IWorkContext _workContext; + private IWorkContext WorkContext + { + get { return _workContext ?? (_workContext = _ctx.Resolve()); } + } + #endregion private PromotionFeedSettings BaseSettings @@ -139,66 +160,47 @@ public string RemoveInvalidFeedChars(string input, bool isHtmlEncoded) return input; } - public string ReplaceCsvChars(string value) - { - if (value.HasValue()) - { - value = value.Replace(';', ','); - value = value.Replace('\r', ' '); - value = value.Replace('\n', ' '); - return value.Replace("'", ""); - } - return ""; - } - - public string DecimalUsFormat(decimal value) - { - return Math.Round(value, 2).ToString(new CultureInfo("en-US", false).NumberFormat); - } - - public string BuildProductDescription(Product product, ProductManufacturer manu, Func updateResult = null) + public string BuildProductDescription(string productName, string shortDescription, string fullDescription, string manufacturer, Func updateResult = null) { if (BaseSettings.BuildDescription.IsCaseInsensitiveEqual(NotSpecified)) return ""; string description = ""; - string productName = product.Name; - string manuName = (manu == null ? "" : manu.Manufacturer.Name); if (BaseSettings.BuildDescription.IsNullOrEmpty()) { - description = product.FullDescription; + description = fullDescription; if (description.IsNullOrEmpty()) - description = product.ShortDescription; + description = shortDescription; if (description.IsNullOrEmpty()) description = productName; } else if (BaseSettings.BuildDescription.IsCaseInsensitiveEqual("short")) { - description = product.ShortDescription; + description = shortDescription; } else if (BaseSettings.BuildDescription.IsCaseInsensitiveEqual("long")) { - description = product.FullDescription; + description = fullDescription; } else if (BaseSettings.BuildDescription.IsCaseInsensitiveEqual("titleAndShort")) { - description = productName.Grow(product.ShortDescription, " "); + description = productName.Grow(shortDescription, " "); } else if (BaseSettings.BuildDescription.IsCaseInsensitiveEqual("titleAndLong")) { - description = productName.Grow(product.FullDescription, " "); + description = productName.Grow(fullDescription, " "); } else if (BaseSettings.BuildDescription.IsCaseInsensitiveEqual("manuAndTitleAndShort")) { - description = manuName.Grow(productName, " "); - description = description.Grow(product.ShortDescription, " "); + description = manufacturer.Grow(productName, " "); + description = description.Grow(shortDescription, " "); } else if (BaseSettings.BuildDescription.IsCaseInsensitiveEqual("manuAndTitleAndLong")) { - description = manuName.Grow(productName, " "); - description = description.Grow(product.FullDescription, " "); + description = manufacturer.Grow(productName, " "); + description = description.Grow(fullDescription, " "); } if (updateResult != null) @@ -252,13 +254,45 @@ public string GetShippingCost(Product product, decimal? shippingCost = null) if (decimal.Compare(cost, decimal.Zero) == 0) return ""; - return DecimalUsFormat(cost); + return cost.FormatInvariant(); } public string GetProductDetailUrl(Store store, Product product) { return "{0}{1}".FormatWith(store.Url, product.GetSeName(Language.Id, UrlRecordService, LanguageService)); } + + public decimal GetProductPrice(Product product, Currency currency) + { + decimal priceBase = PriceCalculationService.GetFinalPrice(product, null, WorkContext.CurrentCustomer, decimal.Zero, true, 1); + + if (BaseSettings.ConvertNetToGrossPrices) + { + decimal taxRate; + priceBase = TaxService.GetProductPrice(product, priceBase, true, WorkContext.CurrentCustomer, out taxRate); + } + + decimal price = ConvertFromStoreCurrency(priceBase, currency); + return price; + } + + public decimal? GetOldPrice(Product product, Currency currency) + { + if (!decimal.Equals(product.OldPrice, decimal.Zero) && !decimal.Equals(product.OldPrice, product.Price) && + !(product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing)) + { + decimal price = product.OldPrice; + + if (BaseSettings.ConvertNetToGrossPrices) + { + decimal taxRate; + price = TaxService.GetProductPrice(product, price, true, WorkContext.CurrentCustomer, out taxRate); + } + + return ConvertFromStoreCurrency(price, currency); + } + return null; + } public FeedFileData GetFeedFileByStore(Store store, string secondFileName = null, string extension = null) { @@ -269,7 +303,7 @@ public FeedFileData GetFeedFileByStore(Store store, string secondFileName = null string dir = Path.Combine(HttpRuntime.AppDomainAppPath, "Content\\files\\exportimport"); string fileName = "{0}_{1}".FormatWith(store.Id, BaseSettings.StaticFileName); string logName = Path.GetFileNameWithoutExtension(fileName) + ".txt"; - + if (ext.HasValue()) fileName = Path.GetFileNameWithoutExtension(fileName) + (ext.StartsWith(".") ? "" : ".") + ext; @@ -287,9 +321,19 @@ public FeedFileData GetFeedFileByStore(Store store, string secondFileName = null StoreName = store.Name, FilePath = Path.Combine(dir, fileName), FileUrl = url + fileName, - LogPath = Path.Combine(dir, logName) + LogPath = Path.Combine(dir, logName), + LogUrl = url + logName }; + try + { + feedFile.LastWriteTime = File.GetLastWriteTimeUtc(feedFile.FilePath).RelativeFormat(true, null); + } + catch (Exception) + { + feedFile.LastWriteTime = feedFile.LastWriteTime.NaIfEmpty(); + } + if (secondFileName.HasValue()) { string fname2 = store.Id + "_" + secondFileName; @@ -656,6 +700,18 @@ public void SetupConfigModel(PromotionFeedConfigModel model, string controller, model.AvailableStores.Add(new SelectListItem() { Text = GetResource("Admin.Common.All"), Value = "0" }); model.AvailableStores.AddRange(stores.ToSelectListItems()); + model.AvailableLanguages = new List(); + model.AvailableLanguages.Add(new SelectListItem() { Text = GetResource("Admin.Common.Standard"), Value = "0" }); + + foreach (var language in LanguageService.GetAllLanguages()) + { + model.AvailableLanguages.Add(new SelectListItem() + { + Text = language.Name, + Value = language.Id.ToString() + }); + } + if (!model.IsRunning) model.IsRunning = (ScheduleTask != null && ScheduleTask.IsRunning);