diff --git a/CommonAssemblyInfo.cs b/CommonAssemblyInfo.cs index 76989aaae..265d6e647 100644 --- a/CommonAssemblyInfo.cs +++ b/CommonAssemblyInfo.cs @@ -15,8 +15,8 @@ [assembly: AssemblyProduct("Virto Commerce Catalog Module")] [assembly: AssemblyCopyright("Copyright © VirtoCommerce 2011-2018")] -[assembly: AssemblyFileVersion("2.22.2.0")] -[assembly: AssemblyVersion("2.22.2.0")] +[assembly: AssemblyFileVersion("2.23.13.0")] +[assembly: AssemblyVersion("2.23.13.0")] #if DEBUG [assembly: AssemblyConfiguration("Debug")] diff --git a/VirtoCommerce.CatalogModule.Data/CatalogConstants.cs b/VirtoCommerce.CatalogModule.Data/CatalogConstants.cs index e90c081c5..53b42644f 100644 --- a/VirtoCommerce.CatalogModule.Data/CatalogConstants.cs +++ b/VirtoCommerce.CatalogModule.Data/CatalogConstants.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,5 +9,6 @@ namespace VirtoCommerce.CatalogModule.Data public static class CatalogConstants { public const string CacheRegion = "CatalogModuleRegion"; + public const string DictionaryItemsCacheRegion = "DictionaryItemCacheRegion"; } } diff --git a/VirtoCommerce.CatalogModule.Data/Migrations/201809190617321_DictionaryShemaRedesign.cs b/VirtoCommerce.CatalogModule.Data/Migrations/201809190617321_DictionaryShemaRedesign.cs index 1db6a0fbb..331ae0c9b 100644 --- a/VirtoCommerce.CatalogModule.Data/Migrations/201809190617321_DictionaryShemaRedesign.cs +++ b/VirtoCommerce.CatalogModule.Data/Migrations/201809190617321_DictionaryShemaRedesign.cs @@ -7,6 +7,8 @@ public partial class DictionaryShemaRedesign : DbMigration { public override void Up() { + Sql("UPDATE dbo.PropertyDictionaryValue SET Alias = Value WHERE Alias IS NULL"); + DropForeignKey("dbo.PropertyDictionaryValue", "PropertyId", "dbo.Property"); DropIndex("dbo.PropertyDictionaryValue", new[] { "PropertyId" }); CreateTable( diff --git a/VirtoCommerce.CatalogModule.Data/Migrations/201809200853133_RemoveDuplicatedDitionaryValues.Designer.cs b/VirtoCommerce.CatalogModule.Data/Migrations/201809200853133_RemoveDuplicatedDitionaryValues.Designer.cs new file mode 100644 index 000000000..583ca022a --- /dev/null +++ b/VirtoCommerce.CatalogModule.Data/Migrations/201809200853133_RemoveDuplicatedDitionaryValues.Designer.cs @@ -0,0 +1,29 @@ +// +namespace VirtoCommerce.CatalogModule.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.2.0-61023")] + public sealed partial class RemoveDuplicatedDitionaryValues : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(RemoveDuplicatedDitionaryValues)); + + string IMigrationMetadata.Id + { + get { return "201809200853133_RemoveDuplicatedDitionaryValues"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/VirtoCommerce.CatalogModule.Data/Migrations/201809200853133_RemoveDuplicatedDitionaryValues.cs b/VirtoCommerce.CatalogModule.Data/Migrations/201809200853133_RemoveDuplicatedDitionaryValues.cs new file mode 100644 index 000000000..ca5de9bc5 --- /dev/null +++ b/VirtoCommerce.CatalogModule.Data/Migrations/201809200853133_RemoveDuplicatedDitionaryValues.cs @@ -0,0 +1,25 @@ +namespace VirtoCommerce.CatalogModule.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class RemoveDuplicatedDitionaryValues : DbMigration + { + public override void Up() + { + Sql(@" + WITH cte AS( + SELECT *, + row_number() OVER(PARTITION BY Value, Locale, DictionaryItemId ORDER BY DictionaryItemId) AS[rn] + + FROM [dbo].[PropertyDictionaryValue] + + ) + Delete from cte WHERE[rn] > 1"); + } + + public override void Down() + { + } + } +} diff --git a/VirtoCommerce.CatalogModule.Data/Migrations/201809200853133_RemoveDuplicatedDitionaryValues.resx b/VirtoCommerce.CatalogModule.Data/Migrations/201809200853133_RemoveDuplicatedDitionaryValues.resx new file mode 100644 index 000000000..21864369b --- /dev/null +++ b/VirtoCommerce.CatalogModule.Data/Migrations/201809200853133_RemoveDuplicatedDitionaryValues.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/VirtoCommerce.CatalogModule.Data/Migrations/201809270711531_PropertyValueCascadeDelete.Designer.cs b/VirtoCommerce.CatalogModule.Data/Migrations/201809270711531_PropertyValueCascadeDelete.Designer.cs new file mode 100644 index 000000000..72b769984 --- /dev/null +++ b/VirtoCommerce.CatalogModule.Data/Migrations/201809270711531_PropertyValueCascadeDelete.Designer.cs @@ -0,0 +1,29 @@ +// +namespace VirtoCommerce.CatalogModule.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.2.0-61023")] + public sealed partial class PropertyValueCascadeDelete : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(PropertyValueCascadeDelete)); + + string IMigrationMetadata.Id + { + get { return "201809270711531_PropertyValueCascadeDelete"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/VirtoCommerce.CatalogModule.Data/Migrations/201809270711531_PropertyValueCascadeDelete.cs b/VirtoCommerce.CatalogModule.Data/Migrations/201809270711531_PropertyValueCascadeDelete.cs new file mode 100644 index 000000000..6e0057ce9 --- /dev/null +++ b/VirtoCommerce.CatalogModule.Data/Migrations/201809270711531_PropertyValueCascadeDelete.cs @@ -0,0 +1,20 @@ +namespace VirtoCommerce.CatalogModule.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class PropertyValueCascadeDelete : DbMigration + { + public override void Up() + { + DropForeignKey("dbo.PropertyValue", "DictionaryItemId", "dbo.PropertyDictionaryItem"); + AddForeignKey("dbo.PropertyValue", "DictionaryItemId", "dbo.PropertyDictionaryItem", "Id", cascadeDelete: true); + } + + public override void Down() + { + DropForeignKey("dbo.PropertyValue", "DictionaryItemId", "dbo.PropertyDictionaryItem"); + AddForeignKey("dbo.PropertyValue", "DictionaryItemId", "dbo.PropertyDictionaryItem", "Id"); + } + } +} diff --git a/VirtoCommerce.CatalogModule.Data/Migrations/201809270711531_PropertyValueCascadeDelete.resx b/VirtoCommerce.CatalogModule.Data/Migrations/201809270711531_PropertyValueCascadeDelete.resx new file mode 100644 index 000000000..fcdc783ba --- /dev/null +++ b/VirtoCommerce.CatalogModule.Data/Migrations/201809270711531_PropertyValueCascadeDelete.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/VirtoCommerce.CatalogModule.Data/Migrations/201812131122560_CatalogPropertyDictionaryItemSortOrder.Designer.cs b/VirtoCommerce.CatalogModule.Data/Migrations/201812131122560_CatalogPropertyDictionaryItemSortOrder.Designer.cs new file mode 100644 index 000000000..e652e4161 --- /dev/null +++ b/VirtoCommerce.CatalogModule.Data/Migrations/201812131122560_CatalogPropertyDictionaryItemSortOrder.Designer.cs @@ -0,0 +1,29 @@ +// +namespace VirtoCommerce.CatalogModule.Data.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.2.0-61023")] + public sealed partial class CatalogPropertyDictionaryItemSortOrder : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(CatalogPropertyDictionaryItemSortOrder)); + + string IMigrationMetadata.Id + { + get { return "201812131122560_CatalogPropertyDictionaryItemSortOrder"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/VirtoCommerce.CatalogModule.Data/Migrations/201812131122560_CatalogPropertyDictionaryItemSortOrder.cs b/VirtoCommerce.CatalogModule.Data/Migrations/201812131122560_CatalogPropertyDictionaryItemSortOrder.cs new file mode 100644 index 000000000..fa83234d1 --- /dev/null +++ b/VirtoCommerce.CatalogModule.Data/Migrations/201812131122560_CatalogPropertyDictionaryItemSortOrder.cs @@ -0,0 +1,18 @@ +namespace VirtoCommerce.CatalogModule.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class CatalogPropertyDictionaryItemSortOrder : DbMigration + { + public override void Up() + { + AddColumn("dbo.PropertyDictionaryItem", "SortOrder", c => c.Int(nullable: false)); + } + + public override void Down() + { + DropColumn("dbo.PropertyDictionaryItem", "SortOrder"); + } + } +} diff --git a/VirtoCommerce.CatalogModule.Data/Migrations/201812131122560_CatalogPropertyDictionaryItemSortOrder.resx b/VirtoCommerce.CatalogModule.Data/Migrations/201812131122560_CatalogPropertyDictionaryItemSortOrder.resx new file mode 100644 index 000000000..f9026a520 --- /dev/null +++ b/VirtoCommerce.CatalogModule.Data/Migrations/201812131122560_CatalogPropertyDictionaryItemSortOrder.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/VirtoCommerce.CatalogModule.Data/Model/CatalogEntity.cs b/VirtoCommerce.CatalogModule.Data/Model/CatalogEntity.cs index 294e07e3c..fb1bba83b 100644 --- a/VirtoCommerce.CatalogModule.Data/Model/CatalogEntity.cs +++ b/VirtoCommerce.CatalogModule.Data/Model/CatalogEntity.cs @@ -60,7 +60,10 @@ public virtual Catalog ToModel(Catalog catalog) } //item property values - catalog.PropertyValues = CatalogPropertyValues.OrderBy(x => x.Name).SelectMany(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); + catalog.PropertyValues = CatalogPropertyValues + .OrderBy(x => x.DictionaryItem?.SortOrder) + .ThenBy(x => x.Name) + .SelectMany(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); //Self properties catalog.Properties = Properties.Where(x => x.CategoryId == null) diff --git a/VirtoCommerce.CatalogModule.Data/Model/CategoryEntity.cs b/VirtoCommerce.CatalogModule.Data/Model/CategoryEntity.cs index 4b34985e8..0e7cb0692 100644 --- a/VirtoCommerce.CatalogModule.Data/Model/CategoryEntity.cs +++ b/VirtoCommerce.CatalogModule.Data/Model/CategoryEntity.cs @@ -105,7 +105,10 @@ public virtual Category ToModel(Category category) category.Properties = Properties.Select(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); //category property values - category.PropertyValues = CategoryPropertyValues.OrderBy(x => x.Name).SelectMany(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); + category.PropertyValues = CategoryPropertyValues + .OrderBy(x => x.DictionaryItem?.SortOrder) + .ThenBy(x => x.Name) + .SelectMany(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); return category; } diff --git a/VirtoCommerce.CatalogModule.Data/Model/ItemEntity.cs b/VirtoCommerce.CatalogModule.Data/Model/ItemEntity.cs index 2a45a20de..94ff58695 100644 --- a/VirtoCommerce.CatalogModule.Data/Model/ItemEntity.cs +++ b/VirtoCommerce.CatalogModule.Data/Model/ItemEntity.cs @@ -179,7 +179,10 @@ public virtual CatalogProduct ToModel(CatalogProduct product, bool convertChildr } //item property values - product.PropertyValues = ItemPropertyValues.OrderBy(x => x.Name).SelectMany(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); + product.PropertyValues = ItemPropertyValues + .OrderBy(x => x.DictionaryItem?.SortOrder) + .ThenBy(x => x.Name) + .SelectMany(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); if (Parent != null) { diff --git a/VirtoCommerce.CatalogModule.Data/Model/PropertyDictionaryItemEntity.cs b/VirtoCommerce.CatalogModule.Data/Model/PropertyDictionaryItemEntity.cs index c3491b363..adc1ee138 100644 --- a/VirtoCommerce.CatalogModule.Data/Model/PropertyDictionaryItemEntity.cs +++ b/VirtoCommerce.CatalogModule.Data/Model/PropertyDictionaryItemEntity.cs @@ -21,6 +21,8 @@ public PropertyDictionaryItemEntity() [Index("IX_AliasAndPropertyId", 1, IsUnique = true)] public string Alias { get; set; } + public int SortOrder { get; set; } + #region Navigation Properties [Index("IX_AliasAndPropertyId", 2, IsUnique = true)] public string PropertyId { get; set; } @@ -29,22 +31,42 @@ public PropertyDictionaryItemEntity() public virtual ObservableCollection DictionaryItemValues { get; set; } #endregion - public virtual PropertyDictionaryValue ToModel(PropertyDictionaryValue propDictValue) + public virtual PropertyDictionaryItem ToModel(PropertyDictionaryItem propDictItem) { - if (propDictValue == null) + if (propDictItem == null) { - throw new ArgumentNullException(nameof(propDictValue)); + throw new ArgumentNullException(nameof(propDictItem)); } - propDictValue.Id = Id; - propDictValue.Alias = Alias; - propDictValue.PropertyId = PropertyId; - propDictValue.Value = Alias; - propDictValue.ValueId = Id; + propDictItem.Id = Id; + propDictItem.Alias = Alias; + propDictItem.SortOrder = SortOrder; + propDictItem.PropertyId = PropertyId; + propDictItem.LocalizedValues = DictionaryItemValues.Select(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); - return propDictValue; + return propDictItem; } + public virtual PropertyDictionaryItemEntity FromModel(PropertyDictionaryItem propDictItem, PrimaryKeyResolvingMap pkMap) + { + if (propDictItem == null) + { + throw new ArgumentNullException(nameof(propDictItem)); + } + pkMap.AddPair(propDictItem, this); + + Id = propDictItem.Id; + Alias = propDictItem.Alias; + SortOrder = propDictItem.SortOrder; + PropertyId = propDictItem.PropertyId; + if (propDictItem.LocalizedValues != null) + { + DictionaryItemValues = new ObservableCollection(propDictItem.LocalizedValues.Select(x => AbstractTypeFactory.TryCreateInstance().FromModel(x, pkMap))); + } + return this; + } + //Left only for backward compatibility when dictionary items used to save within property + [Obsolete] public static IEnumerable FromModels(IEnumerable dictValues, PrimaryKeyResolvingMap pkMap) { if (dictValues == null) @@ -55,7 +77,7 @@ public static IEnumerable FromModels(IEnumerable

x.Alias)) { var dictItemEntity = AbstractTypeFactory.TryCreateInstance(); - dictItemEntity.Id = dictItemGroup.First().ValueId; + dictItemEntity.Id = dictItemGroup.First().ValueId ?? dictItemGroup.First().Id; dictItemEntity.Alias = dictItemGroup.Key; dictItemEntity.PropertyId = dictItemGroup.First().PropertyId; @@ -77,6 +99,7 @@ public static IEnumerable FromModels(IEnumerable

x.Value + '|' + x.Locale); diff --git a/VirtoCommerce.CatalogModule.Data/Model/PropertyDictionaryValueEntity.cs b/VirtoCommerce.CatalogModule.Data/Model/PropertyDictionaryValueEntity.cs index de2903303..c02f23cfa 100644 --- a/VirtoCommerce.CatalogModule.Data/Model/PropertyDictionaryValueEntity.cs +++ b/VirtoCommerce.CatalogModule.Data/Model/PropertyDictionaryValueEntity.cs @@ -18,6 +18,7 @@ public class PropertyDictionaryValueEntity : Entity public virtual PropertyDictionaryItemEntity DictionaryItem { get; set; } #endregion + [Obsolete] public virtual PropertyDictionaryValue ToModel(PropertyDictionaryValue propDictValue) { if (propDictValue == null) @@ -33,6 +34,28 @@ public virtual PropertyDictionaryValue ToModel(PropertyDictionaryValue propDictV return propDictValue; } + public virtual PropertyDictionaryItemLocalizedValue ToModel(PropertyDictionaryItemLocalizedValue localizedValue) + { + if (localizedValue == null) + { + throw new ArgumentNullException(nameof(localizedValue)); + } + localizedValue.LanguageCode = Locale; + localizedValue.Value = Value; + return localizedValue; + } + + public virtual PropertyDictionaryValueEntity FromModel(PropertyDictionaryItemLocalizedValue localizedValue, PrimaryKeyResolvingMap pkMap) + { + if (localizedValue == null) + { + throw new ArgumentNullException(nameof(localizedValue)); + } + Locale = localizedValue.LanguageCode; + Value = localizedValue.Value; + return this; + } + public virtual void Patch(PropertyDictionaryValueEntity target) { target.Locale = Locale; diff --git a/VirtoCommerce.CatalogModule.Data/Model/PropertyEntity.cs b/VirtoCommerce.CatalogModule.Data/Model/PropertyEntity.cs index a4255edd9..c94a16ccd 100644 --- a/VirtoCommerce.CatalogModule.Data/Model/PropertyEntity.cs +++ b/VirtoCommerce.CatalogModule.Data/Model/PropertyEntity.cs @@ -1,10 +1,8 @@ using System; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations; using System.Linq; using VirtoCommerce.Domain.Catalog.Model; -using VirtoCommerce.Domain.Catalog.Services; using VirtoCommerce.Platform.Core.Common; namespace VirtoCommerce.CatalogModule.Data.Model @@ -94,7 +92,6 @@ public virtual Property ToModel(Property property) property.Attributes = PropertyAttributes.Select(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); property.DisplayNames = DisplayNames.Select(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); property.ValidationRules = ValidationRules.Select(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); - property.DictionaryValues = DictionaryItems.SelectMany(x => x.DictionaryItemValues).Select(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); foreach (var rule in property.ValidationRules) { @@ -134,12 +131,13 @@ public virtual PropertyEntity FromModel(Property property, PrimaryKeyResolvingMa { PropertyAttributes = new ObservableCollection(property.Attributes.Select(x => AbstractTypeFactory.TryCreateInstance().FromModel(x, pkMap))); } - +#pragma warning disable 612, 618 + //Left for backward compatibility, when the dictionary items of the property can only be changed with the property if (property.DictionaryValues != null) { DictionaryItems = new ObservableCollection(PropertyDictionaryItemEntity.FromModels(property.DictionaryValues, pkMap)); } - +#pragma warning restore 612, 618 if (property.DisplayNames != null) { DisplayNames = new ObservableCollection(property.DisplayNames.Select(x => AbstractTypeFactory.TryCreateInstance().FromModel(x))); @@ -162,6 +160,9 @@ public virtual void Patch(PropertyEntity target) target.TargetType = TargetType; target.Name = Name; + target.CatalogId = CatalogId; + target.CategoryId = CategoryId; + if (!PropertyAttributes.IsNullCollection()) { var attributeComparer = AnonymousComparer.Create((PropertyAttributeEntity x) => x.IsTransient() ? x.PropertyAttributeName : x.Id); @@ -169,7 +170,7 @@ public virtual void Patch(PropertyEntity target) } if (!DictionaryItems.IsNullCollection()) { - var dictItemComparer = AnonymousComparer.Create((PropertyDictionaryItemEntity x) => x.IsTransient() ? x.Alias : x.Id); + var dictItemComparer = AnonymousComparer.Create((PropertyDictionaryItemEntity x) => $"{x.Alias}-${x.PropertyId}"); DictionaryItems.Patch(target.DictionaryItems, dictItemComparer, (sourceDictItem, targetDictItem) => sourceDictItem.Patch(targetDictItem)); } if (!DisplayNames.IsNullCollection()) diff --git a/VirtoCommerce.CatalogModule.Data/Model/PropertyValueEntity.cs b/VirtoCommerce.CatalogModule.Data/Model/PropertyValueEntity.cs index 4855ee921..90805910a 100644 --- a/VirtoCommerce.CatalogModule.Data/Model/PropertyValueEntity.cs +++ b/VirtoCommerce.CatalogModule.Data/Model/PropertyValueEntity.cs @@ -71,9 +71,10 @@ public virtual IEnumerable ToModel(PropertyValue propValue) propValue.PropertyName = Name; propValue.ValueId = DictionaryItemId; propValue.ValueType = (PropertyValueType)ValueType; - propValue.Value = GetValue(propValue.ValueType); + propValue.Value = DictionaryItem != null ? DictionaryItem.Alias : GetValue(propValue.ValueType); + propValue.Alias = DictionaryItem?.Alias; //Need to expand all dictionary values - if (DictionaryItem != null) + if (DictionaryItem != null && !DictionaryItem.DictionaryItemValues.IsNullOrEmpty()) { foreach (var dictItemValue in DictionaryItem.DictionaryItemValues) { @@ -98,7 +99,7 @@ public virtual IEnumerable FromModels(IEnumerable !x.IsInherited && x.Value != null && !string.IsNullOrEmpty(x.Value.ToString())) + var groupedValues = propValues.Where(x => !x.IsInherited && (!string.IsNullOrEmpty(x.ValueId) || !string.IsNullOrEmpty(x.Value?.ToString()))) .Select(x => AbstractTypeFactory.TryCreateInstance().FromModel(x, pkMap)) .GroupBy(x => x.DictionaryItemId); var result = new List(); @@ -129,13 +130,14 @@ public virtual PropertyValueEntity FromModel(PropertyValue propValue, PrimaryKey CreatedDate = propValue.CreatedDate; ModifiedBy = propValue.ModifiedBy; ModifiedDate = propValue.ModifiedDate; - Locale = propValue.LanguageCode; Name = propValue.PropertyName; ValueType = (int)propValue.ValueType; DictionaryItemId = propValue.ValueId; //Required for manual reference Alias = propValue.Alias; - SetValue(propValue.ValueType, propValue.Value); + //Store alias as value for dictionary properties values + SetValue(propValue.ValueType, !string.IsNullOrEmpty(DictionaryItemId) ? propValue.Alias : propValue.Value); + Locale = !string.IsNullOrEmpty(DictionaryItemId) ? null : propValue.LanguageCode; return this; } diff --git a/VirtoCommerce.CatalogModule.Data/Repositories/CatalogRepositoryImpl.cs b/VirtoCommerce.CatalogModule.Data/Repositories/CatalogRepositoryImpl.cs index 78fbc0777..04a49d9b3 100644 --- a/VirtoCommerce.CatalogModule.Data/Repositories/CatalogRepositoryImpl.cs +++ b/VirtoCommerce.CatalogModule.Data/Repositories/CatalogRepositoryImpl.cs @@ -7,6 +7,8 @@ using System.Data.SqlClient; using System.Linq; using VirtoCommerce.Domain.Catalog.Model; +using VirtoCommerce.Domain.Catalog.Model.Search; +using VirtoCommerce.Domain.Commerce.Model.Search; using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Data.Infrastructure; using VirtoCommerce.Platform.Data.Infrastructure.Interceptors; @@ -86,7 +88,7 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder) modelBuilder.Entity().HasOptional(m => m.CatalogItem).WithMany(x => x.ItemPropertyValues).HasForeignKey(x => x.ItemId).WillCascadeOnDelete(false); modelBuilder.Entity().HasOptional(m => m.Category).WithMany(x => x.CategoryPropertyValues).HasForeignKey(x => x.CategoryId).WillCascadeOnDelete(false); modelBuilder.Entity().HasOptional(m => m.Catalog).WithMany(x => x.CatalogPropertyValues).HasForeignKey(x => x.CatalogId).WillCascadeOnDelete(false); - modelBuilder.Entity().HasOptional(m => m.DictionaryItem).WithMany().HasForeignKey(x => x.DictionaryItemId).WillCascadeOnDelete(false); + modelBuilder.Entity().HasOptional(m => m.DictionaryItem).WithMany().HasForeignKey(x => x.DictionaryItemId).WillCascadeOnDelete(true); #endregion #region PropertyValidationRule @@ -523,8 +525,119 @@ public void RemoveAllPropertyValues(string propertyId) ObjectContext.ExecuteStoreCommand(commandTemplate); } } - #endregion + public GenericSearchResult SearchAssociations(ProductAssociationSearchCriteria criteria) + { + var result = new GenericSearchResult(); + + var countSqlCommandText = @" + ;WITH Association_CTE AS + ( + SELECT * + FROM Association + WHERE ItemId IN ({0}) + " + + (!string.IsNullOrEmpty(criteria.Group) ? $" AND AssociationType = @group" : string.Empty) + + @"), Category_CTE AS + ( + SELECT AssociatedCategoryId Id + FROM Association_CTE + WHERE AssociatedCategoryId IS NOT NULL + UNION ALL + SELECT c.Id + FROM Category c + INNER JOIN Category_CTE cte ON c.ParentCategoryId = cte.Id + ), + Item_CTE AS + ( + SELECT i.Id + FROM (SELECT DISTINCT Id FROM Category_CTE) c + LEFT JOIN Item i ON c.Id=i.CategoryId WHERE i.ParentId IS NULL + UNION + SELECT AssociatedItemId Id FROM Association_CTE + ) + SELECT COUNT(Id) FROM Item_CTE"; + + var querySqlCommandText = @" + ;WITH Association_CTE AS + ( + SELECT + Id + ,AssociationType + ,Priority + ,ItemId + ,CreatedDate + ,ModifiedDate + ,CreatedBy + ,ModifiedBy + ,Discriminator + ,AssociatedItemId + ,AssociatedCategoryId + ,Tags + ,Quantity + FROM Association + WHERE ItemId IN({0})" + + (!string.IsNullOrEmpty(criteria.Group) ? $" AND AssociationType = @group" : string.Empty) + + @"), Category_CTE AS + ( + SELECT AssociatedCategoryId Id, AssociatedCategoryId + FROM Association_CTE + WHERE AssociatedCategoryId IS NOT NULL + UNION ALL + SELECT c.Id, cte.AssociatedCategoryId + FROM Category c + INNER JOIN Category_CTE cte ON c.ParentCategoryId = cte.Id + ), + Item_CTE AS + ( + SELECT + a.Id + ,a.AssociationType + ,a.Priority + ,a.ItemId + ,a.CreatedDate + ,a.ModifiedDate + ,a.CreatedBy + ,a.ModifiedBy + ,a.Discriminator + ,i.Id AssociatedItemId + ,a.AssociatedCategoryId + ,a.Tags + ,a.Quantity + FROM Category_CTE cat + LEFT JOIN Item i ON cat.Id=i.CategoryId + LEFT JOIN Association a ON cat.AssociatedCategoryId=a.AssociatedCategoryId + WHERE i.ParentId IS NULL + UNION + SELECT * FROM Association_CTE + ) + SELECT * FROM Item_CTE WHERE AssociatedItemId IS NOT NULL ORDER BY Priority " + + $"OFFSET {criteria.Skip} ROWS FETCH NEXT {criteria.Take} ROWS ONLY"; + + var countSqlCommand = CreateCommand(countSqlCommandText, criteria.ObjectIds); + var querySqlCommand = CreateCommand(querySqlCommandText, criteria.ObjectIds); + if (!string.IsNullOrEmpty(criteria.Group)) + { + countSqlCommand.Parameters = countSqlCommand.Parameters.Concat(new[] { new SqlParameter($"@group", criteria.Group) }).ToArray(); + querySqlCommand.Parameters = querySqlCommand.Parameters.Concat(new[] { new SqlParameter($"@group", criteria.Group) }).ToArray(); + } + + result.TotalCount = ObjectContext.ExecuteStoreQuery(countSqlCommand.Text, countSqlCommand.Parameters).FirstOrDefault(); + result.Results = ObjectContext.ExecuteStoreQuery(querySqlCommand.Text, querySqlCommand.Parameters).ToList(); + + return result; + } + + public dataModel.PropertyDictionaryItemEntity[] GetPropertyDictionaryItemsByIds(string[] dictItemIds) + { + if (dictItemIds == null) + { + throw new ArgumentNullException(nameof(dictItemIds)); + } + var result = PropertyDictionaryItems.Include(x => x.DictionaryItemValues).Where(x => dictItemIds.Contains(x.Id)).ToArray(); + return result; + } + #endregion protected virtual void AddBatchDeletedEntities(IList ids) where T : Entity, new() diff --git a/VirtoCommerce.CatalogModule.Data/Repositories/ICatalogRepository.cs b/VirtoCommerce.CatalogModule.Data/Repositories/ICatalogRepository.cs index ee63b37d3..63d52fef1 100644 --- a/VirtoCommerce.CatalogModule.Data/Repositories/ICatalogRepository.cs +++ b/VirtoCommerce.CatalogModule.Data/Repositories/ICatalogRepository.cs @@ -1,4 +1,6 @@ using System.Linq; +using VirtoCommerce.Domain.Catalog.Model.Search; +using VirtoCommerce.Domain.Commerce.Model.Search; using VirtoCommerce.Platform.Core.Common; using dataModel = VirtoCommerce.CatalogModule.Data.Model; using moduleModel = VirtoCommerce.Domain.Catalog.Model; @@ -27,6 +29,10 @@ public interface ICatalogRepository : IRepository dataModel.ItemEntity[] GetItemByIds(string[] itemIds, moduleModel.ItemResponseGroup respGroup); dataModel.PropertyEntity[] GetAllCatalogProperties(string catalogId); dataModel.PropertyEntity[] GetPropertiesByIds(string[] propIds, bool loadDictValues = false); + dataModel.PropertyDictionaryItemEntity[] GetPropertyDictionaryItemsByIds(string[] dictItemIds); + + + GenericSearchResult SearchAssociations(ProductAssociationSearchCriteria criteria); void RemoveItems(string[] ids); void RemoveCategories(string[] ids); diff --git a/VirtoCommerce.CatalogModule.Data/Search/AggregationConverter.cs b/VirtoCommerce.CatalogModule.Data/Search/AggregationConverter.cs index 7bd492d3b..40181b277 100644 --- a/VirtoCommerce.CatalogModule.Data/Search/AggregationConverter.cs +++ b/VirtoCommerce.CatalogModule.Data/Search/AggregationConverter.cs @@ -16,11 +16,13 @@ public class AggregationConverter : IAggregationConverter { private readonly IBrowseFilterService _browseFilterService; private readonly IPropertyService _propertyService; + private readonly IProperyDictionaryItemSearchService _propDictItemsSearchService; - public AggregationConverter(IBrowseFilterService browseFilterService, IPropertyService propertyService) + public AggregationConverter(IBrowseFilterService browseFilterService, IPropertyService propertyService, IProperyDictionaryItemSearchService propDictItemsSearchService) { _browseFilterService = browseFilterService; _propertyService = propertyService; + _propDictItemsSearchService = propDictItemsSearchService; } #region Request converter @@ -77,7 +79,7 @@ protected virtual AggregationRequest GetAttributeFilterAggregationRequest(Attrib return new TermAggregationRequest { FieldName = attributeFilter.Key, - Values = attributeFilter.Values?.Select(v => v.Id).ToArray(), + Values = !attributeFilter.Values.IsNullOrEmpty() ? attributeFilter.Values.Select(v => v.Id).ToArray() : null, Filter = existingFilters.And(), Size = attributeFilter.FacetSize, }; @@ -180,7 +182,7 @@ protected virtual Aggregation GetAttributeAggregation(AttributeFilter attributeF { IList aggregationResponseValues; - if (attributeFilter.Values == null) + if (attributeFilter.Values.IsNullOrEmpty()) { // Return all values aggregationResponseValues = aggregationResponse.Values; @@ -288,43 +290,36 @@ protected virtual void AddLabels(IList aggregations, string catalog foreach (var aggregation in aggregations) { // There can be many properties with the same name - var properties = allProperties - .Where(p => p.Name.EqualsInvariant(aggregation.Field)) - .ToArray(); - - //Load dictionary values for properties - foreach (var dictProperty in properties.Where(x => x.Dictionary && x.DictionaryValues.IsNullOrEmpty())) - { - dictProperty.DictionaryValues = _propertyService.SearchDictionaryValues(dictProperty.Id, null).ToList(); - } + var properties = allProperties.Where(p => p.Name.EqualsInvariant(aggregation.Field)).ToArray(); if (properties.Any()) { - var allPropertyLabels = properties - .SelectMany(p => p.DisplayNames) - .Select(n => new AggregationLabel { Language = n.LanguageCode, Label = n.Name }) - .ToArray(); + var allPropertyLabels = properties.SelectMany(p => p.DisplayNames) + .Select(n => new AggregationLabel { Language = n.LanguageCode, Label = n.Name }) + .ToArray(); aggregation.Labels = GetFirstLabelForEachLanguage(allPropertyLabels); - // Get distinct labels for each dictionary value alias - var allValueLabels = properties - .Where(p => p.Dictionary && p.DictionaryValues != null && p.DictionaryValues.Any()) - .SelectMany(p => p.DictionaryValues) - .Where(v => !string.IsNullOrEmpty(v.Alias)) // Workaround for incorrect data - .GroupBy(v => v.Alias, StringComparer.OrdinalIgnoreCase) - .ToDictionary(g => g.Key, g => GetFirstLabelForEachLanguage(g.Select(v => new AggregationLabel { Language = v.LanguageCode, Label = v.Value })), StringComparer.OrdinalIgnoreCase); + var allDictItemsMap = _propDictItemsSearchService.Search(new PropertyDictionaryItemSearchCriteria { PropertyIds = properties.Select(x => x.Id).ToArray(), Take = int.MaxValue }) + .Results.GroupBy(x => x.Alias) + .ToDictionary(x => x.Key, x => x.SelectMany(dictItem => dictItem.LocalizedValues) + .Select(localizedValue => new AggregationLabel { Language = localizedValue.LanguageCode, Label = localizedValue.Value })); foreach (var aggregationItem in aggregation.Items) { - var valueId = aggregationItem.Value.ToString(); - aggregationItem.Labels = allValueLabels.ContainsKey(valueId) ? allValueLabels[valueId] : null; + var alias = aggregationItem.Value?.ToString(); + if (!string.IsNullOrEmpty(alias)) + { + if (allDictItemsMap.TryGetValue(alias, out var labels)) + { + aggregationItem.Labels = GetFirstLabelForEachLanguage(labels); + } + } } } } } - private static IList GetFirstLabelForEachLanguage(IEnumerable labels) { var result = labels diff --git a/VirtoCommerce.CatalogModule.Data/Search/Indexing/CatalogDocumentBuilder.cs b/VirtoCommerce.CatalogModule.Data/Search/Indexing/CatalogDocumentBuilder.cs index 55b6b2008..4c6713c31 100644 --- a/VirtoCommerce.CatalogModule.Data/Search/Indexing/CatalogDocumentBuilder.cs +++ b/VirtoCommerce.CatalogModule.Data/Search/Indexing/CatalogDocumentBuilder.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using VirtoCommerce.Domain.Catalog.Model; +using VirtoCommerce.Domain.Catalog.Services; using VirtoCommerce.Domain.Search; using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Core.Settings; @@ -40,6 +41,7 @@ protected virtual void IndexCustomProperties(IndexDocument document, ICollection { case PropertyValueType.Boolean: case PropertyValueType.DateTime: + case PropertyValueType.Integer: case PropertyValueType.Number: document.Add(new IndexDocumentField(propertyName, propValue.Value) { IsRetrievable = true, IsFilterable = true, IsCollection = isCollection }); break; @@ -49,8 +51,7 @@ protected virtual void IndexCustomProperties(IndexDocument document, ICollection case PropertyValueType.ShortText: // Index alias when it is available instead of display value. // Do not tokenize small values as they will be used for lookups and filters. - var alias = GetPropertyValueAlias(property, propValue); - var shortTextValue = !string.IsNullOrEmpty(alias) ? alias : propValue.Value.ToString(); + var shortTextValue = propValue.Alias ?? propValue.Value.ToString(); document.Add(new IndexDocumentField(propertyName, shortTextValue) { IsRetrievable = true, IsFilterable = true, IsCollection = isCollection }); break; case PropertyValueType.GeoPoint: @@ -81,13 +82,6 @@ protected virtual void IndexCustomProperties(IndexDocument document, ICollection } } - protected virtual string GetPropertyValueAlias(Property property, PropertyValue propValue) - { - var dictionaryValueAlias = property?.DictionaryValues?.Where(v => v.Id.EqualsInvariant(propValue.ValueId)).Select(v => v.Alias).FirstOrDefault(); - var result = !string.IsNullOrEmpty(dictionaryValueAlias) ? dictionaryValueAlias : propValue.Alias; - return result; - } - protected virtual string[] GetOutlineStrings(IEnumerable outlines) { return outlines diff --git a/VirtoCommerce.CatalogModule.Data/Search/Indexing/CategoryDocumentBuilder.cs b/VirtoCommerce.CatalogModule.Data/Search/Indexing/CategoryDocumentBuilder.cs index a44fe2997..da70a35f5 100644 --- a/VirtoCommerce.CatalogModule.Data/Search/Indexing/CategoryDocumentBuilder.cs +++ b/VirtoCommerce.CatalogModule.Data/Search/Indexing/CategoryDocumentBuilder.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/VirtoCommerce.CatalogModule.Data/Search/Indexing/ProductDocumentBuilder.cs b/VirtoCommerce.CatalogModule.Data/Search/Indexing/ProductDocumentBuilder.cs index 01ce1dbb4..3b848857d 100644 --- a/VirtoCommerce.CatalogModule.Data/Search/Indexing/ProductDocumentBuilder.cs +++ b/VirtoCommerce.CatalogModule.Data/Search/Indexing/ProductDocumentBuilder.cs @@ -15,7 +15,6 @@ public class ProductDocumentBuilder : CatalogDocumentBuilder, IIndexDocumentBuil { private readonly IItemService _itemService; private readonly IBlobUrlResolver _blobUrlResolver; - public ProductDocumentBuilder(ISettingsManager settingsManager, IItemService itemService, IBlobUrlResolver blobUrlResolver) : base(settingsManager) { @@ -54,7 +53,7 @@ protected virtual IndexDocument CreateDocument(CatalogProduct product) IndexIsProperty(document, product.Code); document.Add(new IndexDocumentField("status", statusField) { IsRetrievable = true, IsFilterable = true }); - document.Add(new IndexDocumentField("code", product.Code) { IsRetrievable = true, IsFilterable = true }); + document.Add(new IndexDocumentField("code", product.Code) { IsRetrievable = true, IsFilterable = true, IsCollection = true }); document.Add(new IndexDocumentField("name", product.Name) { IsRetrievable = true, IsFilterable = true }); document.Add(new IndexDocumentField("startdate", product.StartDate) { IsRetrievable = true, IsFilterable = true }); document.Add(new IndexDocumentField("enddate", product.EndDate ?? DateTime.MaxValue) { IsRetrievable = true, IsFilterable = true }); @@ -126,6 +125,9 @@ protected virtual IndexDocument CreateDocument(CatalogProduct product) foreach (var variation in product.Variations) { + document.Add(new IndexDocumentField("code", variation.Code) { IsRetrievable = true, IsFilterable = true, IsCollection = true }); + // add the variation code to content + document.Add(new IndexDocumentField("__content", variation.Code) { IsRetrievable = true, IsSearchable = true, IsCollection = true }); IndexCustomProperties(document, variation.Properties, variation.PropertyValues, contentPropertyTypes); } } diff --git a/VirtoCommerce.CatalogModule.Data/Search/ProductSearchRequestBuilder.cs b/VirtoCommerce.CatalogModule.Data/Search/ProductSearchRequestBuilder.cs index ee861024a..85701d44a 100644 --- a/VirtoCommerce.CatalogModule.Data/Search/ProductSearchRequestBuilder.cs +++ b/VirtoCommerce.CatalogModule.Data/Search/ProductSearchRequestBuilder.cs @@ -42,7 +42,8 @@ public virtual SearchRequest BuildRequest(SearchCriteriaBase criteria) Take = criteria.Take, Aggregations = _aggregationConverter?.GetAggregationRequests(productSearchCriteria, allFilters), IsFuzzySearch = productSearchCriteria.IsFuzzySearch, - }; + RawQuery = productSearchCriteria.RawQuery + }; } return request; @@ -161,7 +162,7 @@ protected virtual IList GetPermanentFilters(ProductSearchCriteria crite if (criteria.PriceRange != null) { var range = criteria.PriceRange; - result.Add(FiltersHelper.CreatePriceRangeFilter(criteria.Currency, null, range.Lower, range.Upper, range.IncludeLower, range.IncludeUpper)); + result.Add(FiltersHelper.CreatePriceRangeFilter(criteria.Currency, criteria.Pricelists, range.Lower, range.Upper, range.IncludeLower, range.IncludeUpper)); } if (criteria.GeoDistanceFilter != null) diff --git a/VirtoCommerce.CatalogModule.Data/Services/CategoryServiceImpl.cs b/VirtoCommerce.CatalogModule.Data/Services/CategoryServiceImpl.cs index beffaf5de..a1d58ce92 100644 --- a/VirtoCommerce.CatalogModule.Data/Services/CategoryServiceImpl.cs +++ b/VirtoCommerce.CatalogModule.Data/Services/CategoryServiceImpl.cs @@ -59,30 +59,7 @@ public virtual Category[] GetByIds(string[] categoryIds, CategoryResponseGroup r //Reduce details according to response group foreach (var category in result) { - if (!responseGroup.HasFlag(CategoryResponseGroup.WithImages)) - { - category.Images = null; - } - if (!responseGroup.HasFlag(CategoryResponseGroup.WithLinks)) - { - category.Links = null; - } - if (!responseGroup.HasFlag(CategoryResponseGroup.WithParents)) - { - category.Parents = null; - } - if (!responseGroup.HasFlag(CategoryResponseGroup.WithProperties)) - { - category.Properties = null; - } - if (!responseGroup.HasFlag(CategoryResponseGroup.WithOutlines)) - { - category.Outlines = null; - } - if (!responseGroup.HasFlag(CategoryResponseGroup.WithSeo)) - { - category.SeoInfos = null; - } + ReduceDetails(category, responseGroup); } return result.ToArray(); @@ -137,6 +114,39 @@ public virtual void Delete(string[] categoryIds) } #endregion + ///

+ /// Reduce category details according to response group + /// + /// + /// + protected virtual void ReduceDetails(Category category, CategoryResponseGroup responseGroup) + { + if (!responseGroup.HasFlag(CategoryResponseGroup.WithImages)) + { + category.Images = null; + } + if (!responseGroup.HasFlag(CategoryResponseGroup.WithLinks)) + { + category.Links = null; + } + if (!responseGroup.HasFlag(CategoryResponseGroup.WithParents)) + { + category.Parents = null; + } + if (!responseGroup.HasFlag(CategoryResponseGroup.WithProperties)) + { + category.Properties = null; + category.PropertyValues = null; + } + if (!responseGroup.HasFlag(CategoryResponseGroup.WithOutlines)) + { + category.Outlines = null; + } + if (!responseGroup.HasFlag(CategoryResponseGroup.WithSeo)) + { + category.SeoInfos = null; + } + } protected virtual void SaveChanges(Category[] categories) { diff --git a/VirtoCommerce.CatalogModule.Data/Services/ItemServiceImpl.cs b/VirtoCommerce.CatalogModule.Data/Services/ItemServiceImpl.cs index 423537063..2ffa5ace3 100644 --- a/VirtoCommerce.CatalogModule.Data/Services/ItemServiceImpl.cs +++ b/VirtoCommerce.CatalogModule.Data/Services/ItemServiceImpl.cs @@ -86,46 +86,7 @@ public virtual CatalogProduct[] GetByIds(string[] itemIds, ItemResponseGroup res //Reduce details according to response group foreach (var product in productsWithVariationsList) { - if (!respGroup.HasFlag(ItemResponseGroup.ItemAssets)) - { - product.Assets = null; - } - if (!respGroup.HasFlag(ItemResponseGroup.ItemAssociations)) - { - product.Associations = null; - } - if (!respGroup.HasFlag(ItemResponseGroup.ReferencedAssociations)) - { - product.ReferencedAssociations = null; - } - if (!respGroup.HasFlag(ItemResponseGroup.ItemEditorialReviews)) - { - product.Reviews = null; - } - if (!respGroup.HasFlag(ItemResponseGroup.Inventory)) - { - product.Inventories = null; - } - if (!respGroup.HasFlag(ItemResponseGroup.ItemProperties)) - { - product.Properties = null; - } - if (!respGroup.HasFlag(ItemResponseGroup.Links)) - { - product.Links = null; - } - if (!respGroup.HasFlag(ItemResponseGroup.Outlines)) - { - product.Outlines = null; - } - if (!respGroup.HasFlag(ItemResponseGroup.Seo)) - { - product.SeoInfos = null; - } - if (!respGroup.HasFlag(ItemResponseGroup.Variations)) - { - product.Variations = null; - } + ReduceDetails(product, respGroup); } return result; @@ -167,6 +128,60 @@ public virtual void Delete(string[] itemIds) } #endregion + /// + /// Reduce product details according to response group + /// + /// + /// + protected virtual void ReduceDetails(CatalogProduct product, ItemResponseGroup respGroup) + { + if (product == null) + { + throw new ArgumentNullException(nameof(product)); + } + + if (!respGroup.HasFlag(ItemResponseGroup.ItemAssets)) + { + product.Assets = null; + } + if (!respGroup.HasFlag(ItemResponseGroup.ItemAssociations)) + { + product.Associations = null; + } + if (!respGroup.HasFlag(ItemResponseGroup.ReferencedAssociations)) + { + product.ReferencedAssociations = null; + } + if (!respGroup.HasFlag(ItemResponseGroup.ItemEditorialReviews)) + { + product.Reviews = null; + } + if (!respGroup.HasFlag(ItemResponseGroup.Inventory)) + { + product.Inventories = null; + } + if (!respGroup.HasFlag(ItemResponseGroup.ItemProperties)) + { + product.Properties = null; + product.PropertyValues = null; + } + if (!respGroup.HasFlag(ItemResponseGroup.Links)) + { + product.Links = null; + } + if (!respGroup.HasFlag(ItemResponseGroup.Outlines)) + { + product.Outlines = null; + } + if (!respGroup.HasFlag(ItemResponseGroup.Seo)) + { + product.SeoInfos = null; + } + if (!respGroup.HasFlag(ItemResponseGroup.Variations)) + { + product.Variations = null; + } + } protected virtual void SaveChanges(CatalogProduct[] products, bool disableValidation = false) { @@ -238,6 +253,10 @@ protected virtual void LoadDependencies(CatalogProduct[] products, bool processV if (product.MainProduct != null) { + if (product.MainProduct.MainProduct != null) + { + throw new OperationCanceledException($"The main product can't contains reference to another main product! It can lead to the infinite recursion."); + } LoadDependencies(new[] { product.MainProduct }, false); } if (processVariations && !product.Variations.IsNullOrEmpty()) diff --git a/VirtoCommerce.CatalogModule.Data/Services/ProductAssociationSearchService.cs b/VirtoCommerce.CatalogModule.Data/Services/ProductAssociationSearchService.cs index 3e62db566..dec1de9ed 100644 --- a/VirtoCommerce.CatalogModule.Data/Services/ProductAssociationSearchService.cs +++ b/VirtoCommerce.CatalogModule.Data/Services/ProductAssociationSearchService.cs @@ -27,37 +27,22 @@ public GenericSearchResult SearchProductAssociations(Product throw new ArgumentNullException(nameof(criteria)); } - var result = new GenericSearchResult(); + if (criteria.ObjectIds.IsNullOrEmpty()) + return new GenericSearchResult(); + using (var repository = _catalogRepositoryFactory()) { //Optimize performance and CPU usage repository.DisableChangesTracking(); - var query = repository.Associations; - - if (!criteria.ObjectIds.IsNullOrEmpty()) - { - query = query.Where(x => criteria.ObjectIds.Contains(x.ItemId)); - } - if (!string.IsNullOrEmpty(criteria.Group)) - { - query = query.Where(x => x.AssociationType == criteria.Group); - } + var result = new GenericSearchResult(); - var sortInfos = criteria.SortInfos; - if (sortInfos.IsNullOrEmpty()) - { - sortInfos = new[] { new SortInfo { SortColumn = "Priority", SortDirection = SortDirection.Descending } }; - } - //TODO: Sort by association priority - query = query.OrderBySortInfos(sortInfos); + var dbResult = repository.SearchAssociations(criteria); - result.TotalCount = query.Count(); - result.Results = query.Skip(criteria.Skip).Take(criteria.Take) - .ToArray().Select(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())) - .ToList(); + result.TotalCount = dbResult.TotalCount; + result.Results = dbResult.Results.Select(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())).ToList(); + return result; } - return result; } } } diff --git a/VirtoCommerce.CatalogModule.Data/Services/PropertyDictionaryItemService.cs b/VirtoCommerce.CatalogModule.Data/Services/PropertyDictionaryItemService.cs new file mode 100644 index 000000000..1ed28d471 --- /dev/null +++ b/VirtoCommerce.CatalogModule.Data/Services/PropertyDictionaryItemService.cs @@ -0,0 +1,142 @@ +using System; +using System.Data.Entity; +using System.Linq; +using CacheManager.Core; +using VirtoCommerce.CatalogModule.Data.Model; +using VirtoCommerce.CatalogModule.Data.Repositories; +using VirtoCommerce.Domain.Catalog.Model; +using VirtoCommerce.Domain.Catalog.Model.Search; +using VirtoCommerce.Domain.Catalog.Services; +using VirtoCommerce.Domain.Commerce.Model.Search; +using VirtoCommerce.Platform.Core.Common; +using VirtoCommerce.Platform.Data.Common; +using VirtoCommerce.Platform.Data.Infrastructure; + +namespace VirtoCommerce.CatalogModule.Data.Services +{ + public class PropertyDictionaryItemService : ServiceBase, IProperyDictionaryItemService, IProperyDictionaryItemSearchService + { + private readonly Func _repositoryFactory; + private readonly ICacheManager _cacheManager; + + public PropertyDictionaryItemService(Func repositoryFactory, ICacheManager cacheManager) + { + _repositoryFactory = repositoryFactory; + _cacheManager = cacheManager; + } + + public PropertyDictionaryItem[] GetByIds(string[] ids) + { + PropertyDictionaryItem[] result; + + using (var repository = _repositoryFactory()) + { + //Optimize performance and CPU usage + repository.DisableChangesTracking(); + + result = repository.GetPropertyDictionaryItemsByIds(ids) + .Select(x => x.ToModel(AbstractTypeFactory.TryCreateInstance())) + .ToArray(); + } + return result; + } + + public void SaveChanges(PropertyDictionaryItem[] dictItems) + { + if (dictItems == null) + { + throw new ArgumentNullException(nameof(dictItems)); + } + + var pkMap = new PrimaryKeyResolvingMap(); + using (var repository = _repositoryFactory()) + using (var changeTracker = GetChangeTracker(repository)) + { + var dbExistEntities = repository.GetPropertyDictionaryItemsByIds(dictItems.Where(x => !x.IsTransient()).Select(x => x.Id).ToArray()); + foreach (var dictItem in dictItems) + { + var originalEntity = dbExistEntities.FirstOrDefault(x => x.Id == dictItem.Id); + var modifiedEntity = AbstractTypeFactory.TryCreateInstance().FromModel(dictItem, pkMap); + if (originalEntity != null) + { + changeTracker.Attach(originalEntity); + modifiedEntity.Patch(originalEntity); + } + else + { + repository.Add(modifiedEntity); + } + } + CommitChanges(repository); + pkMap.ResolvePrimaryKeys(); + } + ResetCache(); + } + + public void Delete(string[] ids) + { + using (var repository = _repositoryFactory()) + { + var dbEntities = repository.GetPropertyDictionaryItemsByIds(ids); + + foreach (var dbEntity in dbEntities) + { + repository.Remove(dbEntity); + } + CommitChanges(repository); + } + ResetCache(); + } + + protected virtual void ResetCache() + { + _cacheManager.ClearRegion(CatalogConstants.DictionaryItemsCacheRegion); + } + + public GenericSearchResult Search(PropertyDictionaryItemSearchCriteria criteria) + { + if (criteria == null) + { + throw new ArgumentNullException(nameof(criteria)); + } + + return _cacheManager.Get($"PropertyDictionaryItemService.Search-{criteria.GetCacheKey()}", CatalogConstants.DictionaryItemsCacheRegion, () => + { + using (var repository = _repositoryFactory()) + { + //Optimize performance and CPU usage + repository.DisableChangesTracking(); + + var result = new GenericSearchResult(); + + var query = repository.PropertyDictionaryItems; + if (!criteria.PropertyIds.IsNullOrEmpty()) + { + query = query.Where(x => criteria.PropertyIds.Contains(x.PropertyId)); + } + if (!string.IsNullOrEmpty(criteria.SearchPhrase)) + { + query = query.Where(x => x.Alias.Contains(criteria.SearchPhrase)); + } + + var sortInfos = criteria.SortInfos; + if (sortInfos.IsNullOrEmpty()) + { + sortInfos = new[] { + new SortInfo { SortColumn = "SortOrder", SortDirection = SortDirection.Ascending }, + new SortInfo { SortColumn = "Alias", SortDirection = SortDirection.Ascending } + }; + } + + query = query.OrderBySortInfos(sortInfos); + + result.TotalCount = query.Count(); + var ids = query.Skip(() => criteria.Skip).Take(() => criteria.Take).Select(x => x.Id).ToArray(); + result.Results = GetByIds(ids).AsQueryable().OrderBySortInfos(sortInfos).ToList(); + return result; + } + }); + } + } +} + diff --git a/VirtoCommerce.CatalogModule.Data/Services/PropertyServiceImpl.cs b/VirtoCommerce.CatalogModule.Data/Services/PropertyServiceImpl.cs index 6cf420d29..0fb88db27 100644 --- a/VirtoCommerce.CatalogModule.Data/Services/PropertyServiceImpl.cs +++ b/VirtoCommerce.CatalogModule.Data/Services/PropertyServiceImpl.cs @@ -112,7 +112,7 @@ public void Delete(string[] propertyIds) _eventPublisher.Publish(new PropertyChangedEvent(changedEntries)); } } - + [Obsolete("Use IProperyDictionaryItemService instead")] public PropertyDictionaryValue[] SearchDictionaryValues(string propertyId, string keyword) { if (propertyId == null) @@ -222,6 +222,7 @@ protected virtual void SaveChanges(Property[] properties) protected virtual void ResetCache() { _cacheManager.ClearRegion(CatalogConstants.CacheRegion); + _cacheManager.ClearRegion(CatalogConstants.DictionaryItemsCacheRegion); } protected virtual IDictionary PreloadAllProperties() diff --git a/VirtoCommerce.CatalogModule.Data/Services/Validation/ProductValidator.cs b/VirtoCommerce.CatalogModule.Data/Services/Validation/ProductValidator.cs index e652e5afe..f521a44a7 100644 --- a/VirtoCommerce.CatalogModule.Data/Services/Validation/ProductValidator.cs +++ b/VirtoCommerce.CatalogModule.Data/Services/Validation/ProductValidator.cs @@ -5,7 +5,7 @@ namespace VirtoCommerce.CatalogModule.Data.Services.Validation { public class ProductValidator : AbstractValidator { - private static readonly char[] _illegalCodeChars = { '$', '+', ';', '=', '%', '{', '}', '[', ']', '|', '\\', '/', '@', '~', '!', '^', '*', '&', '(', ')', ':', '<', '>' }; + private static readonly char[] _illegalCodeChars = { '$', '+', ';', '=', '%', '{', '}', '[', ']', '|', '@', '~', '!', '^', '*', '&', '(', ')', '<', '>' }; public ProductValidator() { diff --git a/VirtoCommerce.CatalogModule.Data/VirtoCommerce.CatalogModule.Data.csproj b/VirtoCommerce.CatalogModule.Data/VirtoCommerce.CatalogModule.Data.csproj index e7c39bbc2..45cc7dd15 100644 --- a/VirtoCommerce.CatalogModule.Data/VirtoCommerce.CatalogModule.Data.csproj +++ b/VirtoCommerce.CatalogModule.Data/VirtoCommerce.CatalogModule.Data.csproj @@ -81,16 +81,14 @@ - - ..\packages\VirtoCommerce.Domain.2.25.14\lib\net461\VirtoCommerce.Domain.dll - True - True + + ..\packages\VirtoCommerce.Domain.2.25.18\lib\net461\VirtoCommerce.Domain.dll - - ..\packages\VirtoCommerce.Platform.Core.2.13.26\lib\net461\VirtoCommerce.Platform.Core.dll + + ..\packages\VirtoCommerce.Platform.Core.2.13.37\lib\net461\VirtoCommerce.Platform.Core.dll - - ..\packages\VirtoCommerce.Platform.Data.2.13.26\lib\net461\VirtoCommerce.Platform.Data.dll + + ..\packages\VirtoCommerce.Platform.Data.2.13.37\lib\net461\VirtoCommerce.Platform.Data.dll @@ -195,6 +193,18 @@ 201809190617321_DictionaryShemaRedesign.cs + + + 201809200853133_RemoveDuplicatedDitionaryValues.cs + + + + 201809270711531_PropertyValueCascadeDelete.cs + + + + 201812131122560_CatalogPropertyDictionaryItemSortOrder.cs + @@ -257,6 +267,7 @@ + @@ -345,6 +356,15 @@ 201809190617321_DictionaryShemaRedesign.cs + + 201809200853133_RemoveDuplicatedDitionaryValues.cs + + + 201809270711531_PropertyValueCascadeDelete.cs + + + 201812131122560_CatalogPropertyDictionaryItemSortOrder.cs + diff --git a/VirtoCommerce.CatalogModule.Data/packages.config b/VirtoCommerce.CatalogModule.Data/packages.config index 9d5ece84b..492349629 100644 --- a/VirtoCommerce.CatalogModule.Data/packages.config +++ b/VirtoCommerce.CatalogModule.Data/packages.config @@ -11,7 +11,7 @@ - - - + + + \ No newline at end of file diff --git a/VirtoCommerce.CatalogModule.Test/AggregationRequestBuilderTests.cs b/VirtoCommerce.CatalogModule.Test/AggregationRequestBuilderTests.cs index 7f627c477..7d525db3e 100644 --- a/VirtoCommerce.CatalogModule.Test/AggregationRequestBuilderTests.cs +++ b/VirtoCommerce.CatalogModule.Test/AggregationRequestBuilderTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using VirtoCommerce.CatalogModule.Data.Search; using VirtoCommerce.Domain.Catalog.Model.Search; using VirtoCommerce.Domain.Search; @@ -66,7 +66,7 @@ public void TestSimpleAggregations(string terms, string expectedFilter1, string private static IAggregationConverter GetAggregationRequestBuilder() { - return new AggregationConverter(GetBrowseFilterService(), null); + return new AggregationConverter(GetBrowseFilterService(), null, null); } } } diff --git a/VirtoCommerce.CatalogModule.Test/ProductSearchRequestBuilderTests.cs b/VirtoCommerce.CatalogModule.Test/ProductSearchRequestBuilderTests.cs new file mode 100644 index 000000000..7844ef7ed --- /dev/null +++ b/VirtoCommerce.CatalogModule.Test/ProductSearchRequestBuilderTests.cs @@ -0,0 +1,66 @@ +using System; +using System.Globalization; +using System.Linq; +using VirtoCommerce.CatalogModule.Data.Search; +using VirtoCommerce.Domain.Catalog.Model.Search; +using VirtoCommerce.Domain.Commerce.Model.Search; +using VirtoCommerce.Domain.Search; +using Xunit; + +namespace VirtoCommerce.CatalogModule.Test +{ + [Trait("Category", "Unit")] + [CLSCompliant(false)] + public class ProductSearchRequestBuilderTests : BrowseFiltersTestBase + { + [Theory] + [InlineData(null, null, null, null, "price:")] + [InlineData(null, null, "", null, "price:")] + [InlineData("0", null, "", null, "price:(0 TO)")] + [InlineData(null, "100", "", null, "price:(TO 100)")] + [InlineData("0", "100", "", null, "price:(0 TO 100)")] + [InlineData("100", "200", "", null, "price:(100 TO 200)")] + [InlineData("100", "200", "USD", null, "price_usd:(100 TO 200)")] + [InlineData("100", "200", "USD", "1", "price_usd_1:(100 TO 200)")] + [InlineData("100", "200", "USD", "1;2", "(price_usd_1:(100 TO 200) OR (NOT(price_usd_1:(0 TO)) AND price_usd_2:(100 TO 200)))")] + [InlineData("100", "200", "USD", "1;2;3", "(price_usd_1:(100 TO 200) OR (NOT(price_usd_1:(0 TO)) AND (price_usd_2:(100 TO 200) OR (NOT(price_usd_2:(0 TO)) AND price_usd_3:(100 TO 200)))))")] + public void TestPriceRangeFilter(string lower, string upper, string currency, string pricelists, string expectedFilter) + { + var criteria = new ProductSearchCriteria + { + PriceRange = new NumericRange + { + Lower = ParseDecimal(lower), + Upper = ParseDecimal(upper), + }, + Currency = currency, + Pricelists = pricelists?.Split(';'), + }; + + var termFilterBuilder = GetSearchRequestBuilder(); + + var searchRequest = termFilterBuilder.BuildRequest(criteria); + + var priceFilter = (searchRequest.Filter as AndFilter)?.ChildFilters.Last().ToString(); + Assert.Equal(expectedFilter, priceFilter); + } + + + private static decimal? ParseDecimal(string str) + { + decimal? result = null; + + if (decimal.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out var value)) + { + result = value; + } + + return result; + } + + private static ISearchRequestBuilder GetSearchRequestBuilder() + { + return new ProductSearchRequestBuilder(null, GetTermFilterBuilder(), null); + } + } +} diff --git a/VirtoCommerce.CatalogModule.Test/PropertyDictionaryItemTest.cs b/VirtoCommerce.CatalogModule.Test/PropertyDictionaryItemTest.cs new file mode 100644 index 000000000..cb6c0963e --- /dev/null +++ b/VirtoCommerce.CatalogModule.Test/PropertyDictionaryItemTest.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using System.Linq; +using Moq; +using VirtoCommerce.CatalogModule.Data.Services; +using VirtoCommerce.Domain.Catalog.Model; +using VirtoCommerce.Domain.Catalog.Model.Search; +using VirtoCommerce.Domain.Catalog.Services; +using VirtoCommerce.Domain.Commerce.Model.Search; +using Xunit; + + +namespace VirtoCommerce.CatalogModule.Test +{ + [Trait("Category", "CI")] + public class PropertyDictionaryItemTest + { + [Fact] + public void Add_New_DictionaryItems_To_Property_And_Then_Choose_DictItem_For_Product() + { + var propDictionaryService = new Moq.Mock().Object; + var propDictionarySearchService = new Moq.Mock(); + var productService = new Moq.Mock(); + + var colorProperty = new Property + { + Id = "Color", + Name = "Color", + CatalogId = "Electronics", + Type = PropertyType.Product, + ValueType = PropertyValueType.ShortText, + Dictionary = true, + Multilanguage = true, + Multivalue = true + }; + + var greenDictItem = new PropertyDictionaryItem + { + Alias = "Green", + PropertyId = colorProperty.Id, + LocalizedValues = new[] + { + new PropertyDictionaryItemLocalizedValue { LanguageCode = "en", Value = "Green" }, + new PropertyDictionaryItemLocalizedValue { LanguageCode = "de", Value = "grün" } + } + }; + propDictionarySearchService.Setup(x => x.Search(It.IsAny())).Returns(new GenericSearchResult { TotalCount = 1, Results = new[] { greenDictItem } }); + productService.Setup(x => x.GetById(It.IsAny(), It.IsAny(), null)).Returns(new CatalogProduct { PropertyValues = new List() }); + //Add the new dictionary item to the property + propDictionaryService.SaveChanges(new[] { greenDictItem }); + + + var product = productService.Object.GetById("Shoes", ItemResponseGroup.ItemProperties); + //Find the desired dictionary value from all available + greenDictItem = propDictionarySearchService.Object.Search(new PropertyDictionaryItemSearchCriteria { PropertyIds = new[] { colorProperty.Id }, SearchPhrase = "Green" }).Results.FirstOrDefault(); + //Choose dictionary item for product property + product.PropertyValues.Add(new PropertyValue { Alias = greenDictItem.Alias, PropertyId = greenDictItem.PropertyId, ValueId = greenDictItem.Id }); + productService.Object.Update(new[] { product }); + + + } + + + } +} diff --git a/VirtoCommerce.CatalogModule.Test/VirtoCommerce.CatalogModule.Test.csproj b/VirtoCommerce.CatalogModule.Test/VirtoCommerce.CatalogModule.Test.csproj index 4cc1fefe4..9edc1a212 100644 --- a/VirtoCommerce.CatalogModule.Test/VirtoCommerce.CatalogModule.Test.csproj +++ b/VirtoCommerce.CatalogModule.Test/VirtoCommerce.CatalogModule.Test.csproj @@ -96,19 +96,17 @@ - - ..\packages\VirtoCommerce.CoreModule.Data.2.25.11\lib\net461\VirtoCommerce.CoreModule.Data.dll + + ..\packages\VirtoCommerce.CoreModule.Data.2.25.16\lib\net461\VirtoCommerce.CoreModule.Data.dll - - ..\packages\VirtoCommerce.Domain.2.25.14\lib\net461\VirtoCommerce.Domain.dll - True - True + + ..\packages\VirtoCommerce.Domain.2.25.18\lib\net461\VirtoCommerce.Domain.dll - - ..\packages\VirtoCommerce.Platform.Core.2.13.26\lib\net461\VirtoCommerce.Platform.Core.dll + + ..\packages\VirtoCommerce.Platform.Core.2.13.37\lib\net461\VirtoCommerce.Platform.Core.dll - - ..\packages\VirtoCommerce.Platform.Data.2.13.26\lib\net461\VirtoCommerce.Platform.Data.dll + + ..\packages\VirtoCommerce.Platform.Data.2.13.37\lib\net461\VirtoCommerce.Platform.Data.dll ..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll @@ -139,6 +137,8 @@ + + diff --git a/VirtoCommerce.CatalogModule.Test/packages.config b/VirtoCommerce.CatalogModule.Test/packages.config index 896c72a1e..a8ccf2aa1 100644 --- a/VirtoCommerce.CatalogModule.Test/packages.config +++ b/VirtoCommerce.CatalogModule.Test/packages.config @@ -14,10 +14,10 @@ - - - - + + + + diff --git a/VirtoCommerce.CatalogModule.Web.Core/Converters/CatalogConverter.cs b/VirtoCommerce.CatalogModule.Web.Core/Converters/CatalogConverter.cs index 9b4cfa4d5..1ea1c6a16 100644 --- a/VirtoCommerce.CatalogModule.Web.Core/Converters/CatalogConverter.cs +++ b/VirtoCommerce.CatalogModule.Web.Core/Converters/CatalogConverter.cs @@ -11,12 +11,14 @@ public static class CatalogConverter { public static webModel.Catalog ToWebModel(this moduleModel.Catalog catalog, bool convertProps = true) { - var retVal = new webModel.Catalog(); - //Do not use omu.InjectFrom for performance reasons - retVal.Id = catalog.Id; - retVal.Name = catalog.Name; - retVal.IsVirtual = catalog.IsVirtual; - retVal.Properties = new List(); + var retVal = new webModel.Catalog + { + //Do not use omu.InjectFrom for performance reasons + Id = catalog.Id, + Name = catalog.Name, + IsVirtual = catalog.IsVirtual, + Properties = new List() + }; if (catalog.Languages != null) { @@ -31,8 +33,6 @@ public static webModel.Catalog ToWebModel(this moduleModel.Catalog catalog, bool foreach (var property in catalog.Properties) { var webModelProperty = property.ToWebModel(); - //Reset dict values to decrease response size - webModelProperty.DictionaryValues = null; webModelProperty.Values = new List(); webModelProperty.IsManageable = true; webModelProperty.IsReadOnly = property.Type != moduleModel.PropertyType.Catalog; diff --git a/VirtoCommerce.CatalogModule.Web.Core/Converters/CategoryConverter.cs b/VirtoCommerce.CatalogModule.Web.Core/Converters/CategoryConverter.cs index 112e49951..a5d731737 100644 --- a/VirtoCommerce.CatalogModule.Web.Core/Converters/CategoryConverter.cs +++ b/VirtoCommerce.CatalogModule.Web.Core/Converters/CategoryConverter.cs @@ -27,6 +27,7 @@ public static webModel.Category ToWebModel(this moduleModel.Category category, I retVal.CreatedDate = category.CreatedDate; retVal.ModifiedBy = category.ModifiedBy; retVal.ModifiedDate = category.ModifiedDate; + retVal.Priority = category.Priority; retVal.SeoInfos = category.SeoInfos; if (!category.Outlines.IsNullOrEmpty()) @@ -36,7 +37,6 @@ public static webModel.Category ToWebModel(this moduleModel.Category category, I } //Init outline and path - var parents = new List(); if (category.Parents != null) { retVal.Outline = string.Join("/", category.Parents.Select(x => x.Id)); @@ -58,8 +58,6 @@ public static webModel.Category ToWebModel(this moduleModel.Category category, I foreach (var property in category.Properties) { var webModelProperty = property.ToWebModel(); - //Reset dict values to decrease response size - webModelProperty.DictionaryValues = null; webModelProperty.Values = new List(); webModelProperty.IsManageable = true; webModelProperty.IsReadOnly = property.Type != moduleModel.PropertyType.Category; diff --git a/VirtoCommerce.CatalogModule.Web.Core/Converters/ProductConverter.cs b/VirtoCommerce.CatalogModule.Web.Core/Converters/ProductConverter.cs index 53c51ef4b..c9383c72f 100644 --- a/VirtoCommerce.CatalogModule.Web.Core/Converters/ProductConverter.cs +++ b/VirtoCommerce.CatalogModule.Web.Core/Converters/ProductConverter.cs @@ -123,8 +123,6 @@ public static webModel.Product ToWebModel(this moduleModel.CatalogProduct produc foreach (var property in product.Properties) { var webModelProperty = property.ToWebModel(); - //Reset dict values to decrease response size - webModelProperty.DictionaryValues = null; webModelProperty.Values = new List(); webModelProperty.IsManageable = true; webModelProperty.IsReadOnly = property.Type != moduleModel.PropertyType.Product && property.Type != moduleModel.PropertyType.Variation; diff --git a/VirtoCommerce.CatalogModule.Web.Core/Converters/PropertyConverter.cs b/VirtoCommerce.CatalogModule.Web.Core/Converters/PropertyConverter.cs index 7a5881951..5cd35a375 100644 --- a/VirtoCommerce.CatalogModule.Web.Core/Converters/PropertyConverter.cs +++ b/VirtoCommerce.CatalogModule.Web.Core/Converters/PropertyConverter.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Omu.ValueInjecter; using coreModel = VirtoCommerce.Domain.Catalog.Model; using webModel = VirtoCommerce.CatalogModule.Web.Model; @@ -10,29 +10,25 @@ public static class PropertyConverter { public static webModel.Property ToWebModel(this coreModel.Property property) { - var retVal = new webModel.Property(); - - retVal.Id = property.Id; - retVal.Name = property.Name; - retVal.Required = property.Required; - retVal.Type = property.Type; - retVal.Multivalue = property.Multivalue; - retVal.CatalogId = property.CatalogId; - retVal.CategoryId = property.CategoryId; - retVal.Dictionary = property.Dictionary; - retVal.ValueType = property.ValueType; + var retVal = new webModel.Property + { + Id = property.Id, + Name = property.Name, + Required = property.Required, + Type = property.Type, + Multivalue = property.Multivalue, + CatalogId = property.CatalogId, + CategoryId = property.CategoryId, + Dictionary = property.Dictionary, + ValueType = property.ValueType + }; retVal.Type = property.Type; retVal.Multilanguage = property.Multilanguage; - retVal.IsInherited = property.IsInherited; + retVal.IsInherited = property.IsInherited; retVal.ValueType = property.ValueType; retVal.Type = property.Type; - if (property.DictionaryValues != null) - { - retVal.DictionaryValues = property.DictionaryValues.Select(x => x.ToWebModel()).ToList(); - } - if (property.Attributes != null) { retVal.Attributes = property.Attributes.Select(x => x.ToWebModel()).ToList(); @@ -52,10 +48,7 @@ public static coreModel.Property ToCoreModel(this webModel.Property property) retVal.ValueType = (coreModel.PropertyValueType)(int)property.ValueType; retVal.Type = (coreModel.PropertyType)(int)property.Type; retVal.DisplayNames = property.DisplayNames; - if (property.DictionaryValues != null) - { - retVal.DictionaryValues = property.DictionaryValues.Select(x => x.ToCoreModel()).ToList(); - } + if (property.Attributes != null) { retVal.Attributes = property.Attributes.Select(x => x.ToCoreModel()).ToList(); diff --git a/VirtoCommerce.CatalogModule.Web.Core/Converters/PropertyDictionaryValueConverter.cs b/VirtoCommerce.CatalogModule.Web.Core/Converters/PropertyDictionaryValueConverter.cs deleted file mode 100644 index 4bfbf335b..000000000 --- a/VirtoCommerce.CatalogModule.Web.Core/Converters/PropertyDictionaryValueConverter.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Omu.ValueInjecter; -using moduleModel = VirtoCommerce.Domain.Catalog.Model; -using webModel = VirtoCommerce.CatalogModule.Web.Model; - -namespace VirtoCommerce.CatalogModule.Web.Converters -{ - public static class PropertyDictionaryValue - { - public static webModel.PropertyDictionaryValue ToWebModel(this moduleModel.PropertyDictionaryValue propDictValue) - { - var retVal = new webModel.PropertyDictionaryValue - { - Id = propDictValue.Id, - PropertyId = propDictValue.PropertyId, - Value = propDictValue.Value, - LanguageCode = propDictValue.LanguageCode, - Alias = propDictValue.Alias, - ValueId = propDictValue.ValueId - }; - - return retVal; - } - - public static moduleModel.PropertyDictionaryValue ToCoreModel(this webModel.PropertyDictionaryValue propDictValue) - { - var retVal = new moduleModel.PropertyDictionaryValue(); - retVal.InjectFrom(propDictValue); - return retVal; - } - } -} diff --git a/VirtoCommerce.CatalogModule.Web.Core/Model/Category.cs b/VirtoCommerce.CatalogModule.Web.Core/Model/Category.cs index f2dee1d43..c71112ef4 100644 --- a/VirtoCommerce.CatalogModule.Web.Core/Model/Category.cs +++ b/VirtoCommerce.CatalogModule.Web.Core/Model/Category.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using VirtoCommerce.Domain.Catalog.Model; using VirtoCommerce.Domain.Commerce.Model; @@ -71,13 +71,18 @@ public class Category : AuditableEntity, ISeoSupport, IHasOutlines /// public bool? IsActive { get; set; } + /// + /// Gets or sets category display order. + /// + public int Priority { get; set; } + /// /// Gets or sets the properties. /// /// /// The properties. /// - public ICollection Properties { get; set; } + public ICollection Properties { get; set; } /// /// Gets or sets the links. /// diff --git a/VirtoCommerce.CatalogModule.Web.Core/Model/Property.cs b/VirtoCommerce.CatalogModule.Web.Core/Model/Property.cs index f8b677083..74aea56aa 100644 --- a/VirtoCommerce.CatalogModule.Web.Core/Model/Property.cs +++ b/VirtoCommerce.CatalogModule.Web.Core/Model/Property.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using VirtoCommerce.Domain.Catalog.Model; @@ -141,14 +141,6 @@ public Property(PropertyValue propValue, string catalogId, PropertyType property /// public ICollection Values { get; set; } - /// - /// Gets or sets the dictionary values. - /// - /// - /// The dictionary values. - /// - public ICollection DictionaryValues { get; set; } - /// /// Gets or sets the attributes. /// diff --git a/VirtoCommerce.CatalogModule.Web.Core/VirtoCommerce.CatalogModule.Web.Core.csproj b/VirtoCommerce.CatalogModule.Web.Core/VirtoCommerce.CatalogModule.Web.Core.csproj index c9a12df0c..d58b255e0 100644 --- a/VirtoCommerce.CatalogModule.Web.Core/VirtoCommerce.CatalogModule.Web.Core.csproj +++ b/VirtoCommerce.CatalogModule.Web.Core/VirtoCommerce.CatalogModule.Web.Core.csproj @@ -49,13 +49,11 @@ - - ..\packages\VirtoCommerce.Domain.2.25.14\lib\net461\VirtoCommerce.Domain.dll - True - True + + ..\packages\VirtoCommerce.Domain.2.25.18\lib\net461\VirtoCommerce.Domain.dll - - ..\packages\VirtoCommerce.Platform.Core.2.13.26\lib\net461\VirtoCommerce.Platform.Core.dll + + ..\packages\VirtoCommerce.Platform.Core.2.13.37\lib\net461\VirtoCommerce.Platform.Core.dll @@ -77,7 +75,6 @@ - diff --git a/VirtoCommerce.CatalogModule.Web.Core/packages.config b/VirtoCommerce.CatalogModule.Web.Core/packages.config index bdf74a69a..703bb45c1 100644 --- a/VirtoCommerce.CatalogModule.Web.Core/packages.config +++ b/VirtoCommerce.CatalogModule.Web.Core/packages.config @@ -2,6 +2,6 @@ - - + + \ No newline at end of file diff --git a/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogBrowseFiltersController.cs b/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogBrowseFiltersController.cs index 88bc7eaef..8e94480fe 100644 --- a/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogBrowseFiltersController.cs +++ b/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogBrowseFiltersController.cs @@ -26,13 +26,16 @@ public class CatalogBrowseFiltersController : CatalogBaseController private readonly IStoreService _storeService; private readonly IPropertyService _propertyService; private readonly IBrowseFilterService _browseFilterService; + private readonly IProperyDictionaryItemSearchService _propDictItemsSearchService; - public CatalogBrowseFiltersController(ISecurityService securityService, IPermissionScopeService permissionScopeService, IStoreService storeService, IPropertyService propertyService, IBrowseFilterService browseFilterService) + + public CatalogBrowseFiltersController(ISecurityService securityService, IPermissionScopeService permissionScopeService, IStoreService storeService, IPropertyService propertyService, IBrowseFilterService browseFilterService, IProperyDictionaryItemSearchService propDictItemsSearchService) : base(securityService, permissionScopeService) { _storeService = storeService; _propertyService = propertyService; _browseFilterService = browseFilterService; + _propDictItemsSearchService = propDictItemsSearchService; } /// @@ -116,7 +119,7 @@ public IHttpActionResult GetPropertyValues(string storeId, string propertyName) var property = _propertyService.GetAllCatalogProperties(store.Catalog).Where(p => p.Name.EqualsInvariant(propertyName) && p.Dictionary).FirstOrDefault(); if (property != null) { - result = _propertyService.SearchDictionaryValues(property.Id, null).Select(x => x.Alias).Distinct().ToArray(); + result = _propDictItemsSearchService.Search(new Domain.Catalog.Model.Search.PropertyDictionaryItemSearchCriteria { PropertyIds = new[] { property.Id }, Take = int.MaxValue }).Results.Select(x => x.Alias).Distinct().ToArray(); } return Ok(result); } diff --git a/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModuleListEntryController.cs b/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModuleListEntryController.cs index c2466ae32..dec38fb58 100644 --- a/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModuleListEntryController.cs +++ b/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModuleListEntryController.cs @@ -70,6 +70,7 @@ public IHttpActionResult ListItemsSearch(webModel.SearchCriteria criteria) //Because products and categories represent in search result as two separated collections for handle paging request //we should join two resulting collection artificially //search categories + var copyRespGroup = coreModelCriteria.ResponseGroup; if ((coreModelCriteria.ResponseGroup & coreModel.SearchResponseGroup.WithCategories) == coreModel.SearchResponseGroup.WithCategories) { coreModelCriteria.ResponseGroup = coreModelCriteria.ResponseGroup & ~coreModel.SearchResponseGroup.WithProducts; @@ -82,10 +83,8 @@ public IHttpActionResult ListItemsSearch(webModel.SearchCriteria criteria) retVal.TotalCount = categoriesTotalCount; retVal.ListEntries.AddRange(categories); - - coreModelCriteria.ResponseGroup = coreModelCriteria.ResponseGroup | coreModel.SearchResponseGroup.WithProducts; } - + coreModelCriteria.ResponseGroup = copyRespGroup; //search products if ((coreModelCriteria.ResponseGroup & coreModel.SearchResponseGroup.WithProducts) == coreModel.SearchResponseGroup.WithProducts) { diff --git a/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModulePropertiesController.cs b/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModulePropertiesController.cs index e7ed00309..e3344976e 100644 --- a/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModulePropertiesController.cs +++ b/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModulePropertiesController.cs @@ -8,7 +8,6 @@ using VirtoCommerce.CatalogModule.Web.Converters; using VirtoCommerce.CatalogModule.Web.Security; using VirtoCommerce.Domain.Catalog.Services; -using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Core.Security; using moduleModel = VirtoCommerce.Domain.Catalog.Model; using webModel = VirtoCommerce.CatalogModule.Web.Model; @@ -21,17 +20,19 @@ public class CatalogModulePropertiesController : CatalogBaseController private readonly IPropertyService _propertyService; private readonly ICategoryService _categoryService; private readonly ICatalogService _catalogService; + private readonly IProperyDictionaryItemSearchService _propertyDictionarySearchService; //Workaround: Bad design to use repository in the controller layer, need to extend in the future IPropertyService.Delete with new parameter DeleteAllValues private readonly Func _repositoryFactory; public CatalogModulePropertiesController(IPropertyService propertyService, ICategoryService categoryService, ICatalogService catalogService, - ISecurityService securityService, IPermissionScopeService permissionScopeService, Func repositoryFactory) + ISecurityService securityService, IPermissionScopeService permissionScopeService, Func repositoryFactory, + IProperyDictionaryItemSearchService propertyDictionarySearchService) : base(securityService, permissionScopeService) { _propertyService = propertyService; _categoryService = categoryService; _catalogService = catalogService; _repositoryFactory = repositoryFactory; - + _propertyDictionarySearchService = propertyDictionarySearchService; } @@ -44,10 +45,12 @@ public CatalogModulePropertiesController(IPropertyService propertyService, ICate [HttpGet] [Route("{propertyId}/values")] [ResponseType(typeof(webModel.PropertyDictionaryValue[]))] + [Obsolete("Use POST api/catalog/properties/dictionaryitems/search instead")] public IHttpActionResult GetPropertyValues(string propertyId, [FromUri]string keyword = null) { - var dictValues = _propertyService.SearchDictionaryValues(propertyId, keyword); - return Ok(dictValues.Select(x => x.ToWebModel()).ToArray()); + var dictValues = _propertyDictionarySearchService.Search(new moduleModel.Search.PropertyDictionaryItemSearchCriteria { SearchPhrase = keyword, PropertyIds = new[] { propertyId }, Take = int.MaxValue }).Results; + + return Ok(dictValues.Select(x => new webModel.PropertyDictionaryValue { Id = x.Id, Alias = x.Alias, ValueId = x.PropertyId, Value = x.Alias }).ToArray()); } @@ -91,7 +94,6 @@ public IHttpActionResult GetNewCatalogProperty(string catalogId) Name = "new property", Type = moduleModel.PropertyType.Catalog, ValueType = moduleModel.PropertyValueType.ShortText, - DictionaryValues = new List(), Attributes = new List(), DisplayNames = catalog.Languages.Select(x => new moduleModel.PropertyDisplayName { LanguageCode = x.LanguageCode }).ToList() }; @@ -121,7 +123,6 @@ public IHttpActionResult GetNewCategoryProperty(string categoryId) Name = "new property", Type = moduleModel.PropertyType.Category, ValueType = moduleModel.PropertyValueType.ShortText, - DictionaryValues = new List(), Attributes = new List(), DisplayNames = category.Catalog.Languages.Select(x => new moduleModel.PropertyDisplayName { LanguageCode = x.LanguageCode }).ToList() }; diff --git a/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModulePropertyDictionaryItemsController.cs b/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModulePropertyDictionaryItemsController.cs new file mode 100644 index 000000000..99067eee7 --- /dev/null +++ b/VirtoCommerce.CatalogModule.Web/Controllers/Api/CatalogModulePropertyDictionaryItemsController.cs @@ -0,0 +1,70 @@ +using System.Linq; +using System.Web.Http; +using System.Web.Http.Description; +using VirtoCommerce.CatalogModule.Web.Converters; +using VirtoCommerce.CatalogModule.Web.Security; +using VirtoCommerce.Domain.Catalog.Model.Search; +using VirtoCommerce.Domain.Catalog.Services; +using VirtoCommerce.Platform.Core.Security; +using VirtoCommerce.Platform.Core.Web.Security; +using moduleModel = VirtoCommerce.Domain.Catalog.Model; + +namespace VirtoCommerce.CatalogModule.Web.Controllers.Api +{ + [RoutePrefix("api/catalog/dictionaryitems")] + public class CatalogModulePropertyDictionaryItemsController : CatalogBaseController + { + private readonly IProperyDictionaryItemSearchService _propertyDictionarySearchService; + private readonly IProperyDictionaryItemService _propertyDictionaryService; + + public CatalogModulePropertyDictionaryItemsController(ISecurityService securityService, IPermissionScopeService permissionScopeService, IProperyDictionaryItemSearchService propertyDictionarySearchService, + IProperyDictionaryItemService propertyDictionaryService) + : base(securityService, permissionScopeService) + { + _propertyDictionarySearchService = propertyDictionarySearchService; + _propertyDictionaryService = propertyDictionaryService; + } + + /// + /// Search property dictionary items + /// + /// The search criteria + /// + [HttpPost] + [Route("search")] + [ResponseType(typeof(moduleModel.PropertyDictionaryItem[]))] + [CheckPermission(Permission = CatalogPredefinedPermissions.Read)] + public IHttpActionResult SearchPropertyDictionaryItems(PropertyDictionaryItemSearchCriteria criteria) + { + var result = _propertyDictionarySearchService.Search(criteria); + return Ok(result); + } + + /// + /// Creates or updates the specified property dictionary items + /// + [HttpPost] + [Route("")] + [ResponseType(typeof(void))] + [CheckPermission(Permission = CatalogPredefinedPermissions.Create)] + public IHttpActionResult SaveChanges(moduleModel.PropertyDictionaryItem[] propertyDictItems) + { + _propertyDictionaryService.SaveChanges(propertyDictItems); + return Ok(); + } + + /// + /// Delete property dictionary items by ids + /// + /// The identifiers of objects that needed to be deleted + [HttpDelete] + [Route("")] + [ResponseType(typeof(void))] + [CheckPermission(Permission = CatalogPredefinedPermissions.Delete)] + public IHttpActionResult Delete([FromUri] string[] ids) + { + _propertyDictionaryService.Delete(ids); + return Ok(); + } + } +} diff --git a/VirtoCommerce.CatalogModule.Web/ExportImport/CatalogExportImport.cs b/VirtoCommerce.CatalogModule.Web/ExportImport/CatalogExportImport.cs index c2def73c2..f2c5133a8 100644 --- a/VirtoCommerce.CatalogModule.Web/ExportImport/CatalogExportImport.cs +++ b/VirtoCommerce.CatalogModule.Web/ExportImport/CatalogExportImport.cs @@ -5,6 +5,7 @@ using System.Text; using Newtonsoft.Json; using VirtoCommerce.Domain.Catalog.Model; +using VirtoCommerce.Domain.Catalog.Model.Search; using VirtoCommerce.Domain.Catalog.Services; using VirtoCommerce.Platform.Core.Assets; using VirtoCommerce.Platform.Core.Common; @@ -24,6 +25,8 @@ public sealed class CatalogExportImport private readonly IAssociationService _associationService; private readonly ISettingsManager _settingsManager; private readonly JsonSerializer _serializer; + private readonly IProperyDictionaryItemSearchService _propertyDictionarySearchService; + private readonly IProperyDictionaryItemService _propertyDictionaryService; private int? _batchSize; @@ -35,7 +38,9 @@ public CatalogExportImport( IPropertyService propertyService, IBlobStorageProvider blobStorageProvider, IAssociationService associationService, - ISettingsManager settingsManager + ISettingsManager settingsManager, + IProperyDictionaryItemSearchService propertyDictionarySearchService, + IProperyDictionaryItemService propertyDictionaryService ) { _blobStorageProvider = blobStorageProvider; @@ -46,11 +51,15 @@ ISettingsManager settingsManager _propertyService = propertyService; _associationService = associationService; _settingsManager = settingsManager; + _propertyDictionarySearchService = propertyDictionarySearchService; + _propertyDictionaryService = propertyDictionaryService; - _serializer = new JsonSerializer(); - _serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; - _serializer.Formatting = Formatting.Indented; - _serializer.NullValueHandling = NullValueHandling.Ignore; + _serializer = new JsonSerializer + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + Formatting = Formatting.Indented, + NullValueHandling = NullValueHandling.Ignore + }; } private int BatchSize @@ -69,17 +78,19 @@ private int BatchSize #region Export/Import methods public void DoExport(Stream outStream, PlatformExportManifest manifest, Action progressCallback) { - var progressInfo = new ExportImportProgressInfo { Description = "loading data..." }; + var progressInfo = new ExportImportProgressInfo { Description = "loading data…" }; progressCallback(progressInfo); - using (StreamWriter sw = new StreamWriter(outStream, Encoding.UTF8)) - using (JsonTextWriter writer = new JsonTextWriter(sw)) + using (var sw = new StreamWriter(outStream, Encoding.UTF8)) + using (var writer = new JsonTextWriter(sw)) { writer.WriteStartObject(); - ExportCatalogs(writer, _serializer, manifest, progressInfo, progressCallback); + // Properties and Property dictionary items should preceed Catalogs and Categories for proper import + ExportProperties(writer, _serializer, progressInfo, progressCallback); + ExportPropertiesDictionaryItems(writer, _serializer, progressInfo, progressCallback); + ExportCatalogs(writer, _serializer, progressInfo, progressCallback); ExportCategories(writer, _serializer, manifest, progressInfo, progressCallback); - ExportProperties(writer, _serializer, manifest, progressInfo, progressCallback); ExportProducts(writer, _serializer, manifest, progressInfo, progressCallback); writer.WriteEndObject(); @@ -91,8 +102,10 @@ public void DoImport(Stream stream, PlatformExportManifest manifest, Action(); + using (var streamReader = new StreamReader(stream)) + using (var reader = new JsonTextReader(streamReader)) { while (reader.Read()) { @@ -102,7 +115,7 @@ public void DoImport(Stream stream, PlatformExportManifest manifest, Action(reader); - progressInfo.Description = $"{ catalogs.Count() } catalogs importing..."; + progressInfo.Description = $"{ catalogs.Count() } catalogs are importing…"; progressCallback(progressInfo); _catalogService.Update(catalogs); } @@ -110,7 +123,7 @@ public void DoImport(Stream stream, PlatformExportManifest manifest, Action(reader); - progressInfo.Description = $"{ categories.Count() } categories importing..."; + progressInfo.Description = $"{ categories.Count() } categories are importing…"; progressCallback(progressInfo); _categoryService.Update(categories); if (manifest.HandleBinaryData) @@ -122,7 +135,17 @@ public void DoImport(Stream stream, PlatformExportManifest manifest, Action(reader); - progressInfo.Description = $"{ properties.Count() } properties importing..."; + foreach (var property in properties) + { + if (property.CategoryId != null || property.CatalogId != null) + { + propertiesWithForeignKeys.Add(property.Clone() as Property); + //Need to reset property foreign keys to prevent FK violation during inserting into database + property.CategoryId = null; + property.CatalogId = null; + } + } + progressInfo.Description = $"{ properties.Count() } properties are importing…"; progressCallback(progressInfo); _propertyService.Update(properties); } @@ -130,6 +153,44 @@ public void DoImport(Stream stream, PlatformExportManifest manifest, Action(); + var propDictItemsCount = 0; + //Import property dcitonary items + while (reader.TokenType != JsonToken.EndArray) + { + var propDictItem = AbstractTypeFactory.TryCreateInstance(); + propDictItem = _serializer.Deserialize(reader, propDictItem.GetType()) as PropertyDictionaryItem; + propDictItems.Add(propDictItem); + propDictItemsCount++; + reader.Read(); + if (propDictItemsCount % BatchSize == 0 || reader.TokenType == JsonToken.EndArray) + { + _propertyDictionaryService.SaveChanges(propDictItems.ToArray()); + propDictItems.Clear(); + if (propDictItemsCount > 0) + { + progressInfo.Description = $"{ propDictItemsCount } of { propDictItemTotalCount } dictionary items have been imported"; + } + else + { + progressInfo.Description = $"{ propDictItemsCount } dictionary items have been imported"; + } + progressCallback(progressInfo); + } + } + } + } else if (reader.Value.ToString() == "Products") { reader.Read(); @@ -167,20 +228,20 @@ public void DoImport(Stream stream, PlatformExportManifest manifest, Action 0) { - progressInfo.Description = $"{ productsCount } of { productsTotalCount } products imported"; + progressInfo.Description = $"{ productsCount } of { productsTotalCount } products have been imported"; } else { - progressInfo.Description = $"{ productsCount } products imported"; + progressInfo.Description = $"{ productsCount } products have been imported"; } progressCallback(progressInfo); } } //Import products associations separately to avoid DB constrain violation - var totalProductsWithAssociationsCount = associationBackupMap.Count(); - progressInfo.Description = $"{ totalProductsWithAssociationsCount } products associations importing..."; + var totalProductsWithAssociationsCount = associationBackupMap.Count; + progressInfo.Description = $"{ totalProductsWithAssociationsCount } products associations are importing…"; progressCallback(progressInfo); - for (int i = 0; i < totalProductsWithAssociationsCount; i += BatchSize) + for (var i = 0; i < totalProductsWithAssociationsCount; i += BatchSize) { var fakeProducts = new List(); foreach (var pair in associationBackupMap.Skip(i).Take(BatchSize)) @@ -199,20 +260,35 @@ public void DoImport(Stream stream, PlatformExportManifest manifest, Action 0) + { + progressInfo.Description = $"Updating {propertiesWithForeignKeys.Count} property associations…"; + progressCallback(progressInfo); + + var totalCount = propertiesWithForeignKeys.Count; + for (var i = 0; i < totalCount; i += BatchSize) + { + _propertyService.Update(propertiesWithForeignKeys.Skip(i).Take(BatchSize).ToArray()); + progressInfo.Description = $"{ Math.Min(totalCount, i + BatchSize) } of { totalCount } property associations updated."; + progressCallback(progressInfo); + } + } } #endregion - private void ExportCatalogs(JsonTextWriter writer, JsonSerializer serializer, PlatformExportManifest manifest, ExportImportProgressInfo progressInfo, Action progressCallback) + private void ExportCatalogs(JsonTextWriter writer, JsonSerializer serializer, ExportImportProgressInfo progressInfo, Action progressCallback) { //Catalogs - progressInfo.Description = string.Format("Catalogs exporting..."); + progressInfo.Description = "Catalogs are exporting…"; progressCallback(progressInfo); var catalogs = _catalogService.GetCatalogsList().ToArray(); writer.WritePropertyName("Catalogs"); writer.WriteStartArray(); - //Reset some props to descrease resulting json size + //Reset some props to decrease resulting json size foreach (var catalog in catalogs) { ResetRedundantReferences(catalog); @@ -221,14 +297,14 @@ private void ExportCatalogs(JsonTextWriter writer, JsonSerializer serializer, Pl writer.WriteEndArray(); - progressInfo.Description = $"{ catalogs.Count() } catalogs exported"; + progressInfo.Description = $"{ catalogs.Count() } catalogs have been exported"; progressCallback(progressInfo); } private void ExportCategories(JsonTextWriter writer, JsonSerializer serializer, PlatformExportManifest manifest, ExportImportProgressInfo progressInfo, Action progressCallback) { //Categories - progressInfo.Description = string.Format("Categories exporting..."); + progressInfo.Description = "Categories are exporting…"; progressCallback(progressInfo); var categorySearchCriteria = new SearchCriteria { WithHidden = true, Skip = 0, Take = 0, ResponseGroup = SearchResponseGroup.WithCategories }; @@ -241,7 +317,7 @@ private void ExportCategories(JsonTextWriter writer, JsonSerializer serializer, writer.WritePropertyName("Categories"); writer.WriteStartArray(); - //reset some properties to decrease resultin JSON size + //reset some properties to decrease resulting JSON size foreach (var category in categories) { ResetRedundantReferences(category); @@ -249,14 +325,14 @@ private void ExportCategories(JsonTextWriter writer, JsonSerializer serializer, } writer.WriteEndArray(); - progressInfo.Description = $"{ categoriesSearchResult.Categories.Count } categories exported"; + progressInfo.Description = $"{ categoriesSearchResult.Categories.Count } categories have been exported"; progressCallback(progressInfo); } - private void ExportProperties(JsonTextWriter writer, JsonSerializer serializer, PlatformExportManifest manifest, ExportImportProgressInfo progressInfo, Action progressCallback) + private void ExportProperties(JsonTextWriter writer, JsonSerializer serializer, ExportImportProgressInfo progressInfo, Action progressCallback) { //Properties - progressInfo.Description = "Properties exporting..."; + progressInfo.Description = "Properties exporting…"; progressCallback(progressInfo); var properties = _propertyService.GetAllProperties(); @@ -265,20 +341,44 @@ private void ExportProperties(JsonTextWriter writer, JsonSerializer serializer, //Load property dictionary values and reset some props to decrease size of the resulting json foreach (var property in properties) { - property.DictionaryValues = _propertyService.SearchDictionaryValues(property.Id, null); ResetRedundantReferences(property); serializer.Serialize(writer, property); } writer.WriteEndArray(); + progressInfo.Description = $"{ properties.Count() } properties have been exported"; + progressCallback(progressInfo); + } - progressInfo.Description = $"{ properties.Count() } properties exported"; + private void ExportPropertiesDictionaryItems(JsonTextWriter writer, JsonSerializer serializer, ExportImportProgressInfo progressInfo, Action progressCallback) + { + progressInfo.Description = "The dictionary items are exporting…"; progressCallback(progressInfo); + + var criteria = new PropertyDictionaryItemSearchCriteria { Take = 0, Skip = 0 }; + var totalCount = _propertyDictionarySearchService.Search(criteria).TotalCount; + writer.WritePropertyName("PropertyDictionaryItemsTotalCount"); + writer.WriteValue(totalCount); + + writer.WritePropertyName("PropertyDictionaryItems"); + writer.WriteStartArray(); + for (var i = 0; i < totalCount; i += BatchSize) + { + var searchResponse = _propertyDictionarySearchService.Search(new PropertyDictionaryItemSearchCriteria { Take = BatchSize, Skip = i }); + foreach (var dictItem in searchResponse.Results) + { + serializer.Serialize(writer, dictItem); + } + writer.Flush(); + progressInfo.Description = $"{ Math.Min(totalCount, i + BatchSize) } of { totalCount } dictionary items have been exported"; + progressCallback(progressInfo); + } + writer.WriteEndArray(); } private void ExportProducts(JsonTextWriter writer, JsonSerializer serializer, PlatformExportManifest manifest, ExportImportProgressInfo progressInfo, Action progressCallback) { //Products - progressInfo.Description = string.Format("Products exporting..."); + progressInfo.Description = "Products are exporting…"; progressCallback(progressInfo); var productSearchCriteria = new SearchCriteria { WithHidden = true, Take = 0, Skip = 0, ResponseGroup = SearchResponseGroup.WithProducts }; @@ -288,7 +388,7 @@ private void ExportProducts(JsonTextWriter writer, JsonSerializer serializer, Pl writer.WritePropertyName("Products"); writer.WriteStartArray(); - for (int i = 0; i < totalProductCount; i += BatchSize) + for (var i = 0; i < totalProductCount; i += BatchSize) { var searchResponse = _catalogSearchService.Search(new SearchCriteria { WithHidden = true, Take = BatchSize, Skip = i, ResponseGroup = SearchResponseGroup.WithProducts }); @@ -303,7 +403,7 @@ private void ExportProducts(JsonTextWriter writer, JsonSerializer serializer, Pl serializer.Serialize(writer, product); } writer.Flush(); - progressInfo.Description = $"{ Math.Min(totalProductCount, i + BatchSize) } of { totalProductCount } products exported"; + progressInfo.Description = $"{ Math.Min(totalProductCount, i + BatchSize) } of { totalProductCount } products have been exported"; progressCallback(progressInfo); } writer.WriteEndArray(); @@ -437,6 +537,5 @@ private void ImportImages(IHasImages[] haveImagesObjects, ExportImportProgressIn } } } - } } diff --git a/VirtoCommerce.CatalogModule.Web/Localizations/de.VirtoCommerce.Catalog.json b/VirtoCommerce.CatalogModule.Web/Localizations/de.VirtoCommerce.Catalog.json index db0bf32b6..633cdd359 100644 --- a/VirtoCommerce.CatalogModule.Web/Localizations/de.VirtoCommerce.Catalog.json +++ b/VirtoCommerce.CatalogModule.Web/Localizations/de.VirtoCommerce.Catalog.json @@ -634,3 +634,4 @@ } } } +} diff --git a/VirtoCommerce.CatalogModule.Web/Localizations/en.VirtoCommerce.Catalog.json b/VirtoCommerce.CatalogModule.Web/Localizations/en.VirtoCommerce.Catalog.json index 79371f790..d6c6412bb 100644 --- a/VirtoCommerce.CatalogModule.Web/Localizations/en.VirtoCommerce.Catalog.json +++ b/VirtoCommerce.CatalogModule.Web/Localizations/en.VirtoCommerce.Catalog.json @@ -92,15 +92,17 @@ "is-active": "Is active", "name": "Name", "code": "Code", - "tax-type": "Tax type" + "tax-type": "Tax type", + "priority": "Priority" }, "validations": { - "code": "Code can't contain $+;=%{}[]|/@ ~!^*&()?:'<>, characters" + "code": "Code can't contain $+;=%{}[]|@~!^*&()?'<>, characters" }, "placeholders": { "name": "Enter category name", "code": "Enter category code", - "select": "Select..." + "select": "Select...", + "priority": "Enter number" } }, "categories-items-add": { @@ -163,6 +165,7 @@ "applies-to": "Applies to", "value-type": "Value Type", "manage-dictionary": "Manage dictionary", + "new-dictionary-property-caution": "You can manage dictionary items only after saving property", "attributes": "Attributes", "manage-attributes": "Manage property attributes" }, @@ -253,9 +256,12 @@ "current-values": "Current values", "value": "Value", "alias": "Alias", + "sort-order": "Sort order", "language-edit": "Edit values", "language-add": "New values", - "dictionary-edit": "Dictionary value edit" + "dictionary-edit": "Dictionary value edit", + "priority": "Priority", + "priority-description": "The lowest value will be used first." }, "validations": { "required": "Required", @@ -263,7 +269,8 @@ }, "placeholders": { "value": "Enter value", - "alias": "Enter an alias" + "alias": "Enter an alias", + "priority": "Enter priority" } }, "item-detail": { @@ -290,7 +297,7 @@ "end-date": "Listing expires on" }, "validations": { - "sku": "SKU can't contain $+;=%{}[]|/@ ~!^*&()?:'<>, characters" + "sku": "SKU can't contain $+;=%{}[]|@~!^*&()?'<>, characters" }, "placeholders": { "sku": "Enter item SKU", @@ -533,6 +540,10 @@ "shallow": "Metadata", "full": "Completely" }, + "property-dictionary-item-delete": { + "message": "Are you sure you want to delete selected dictionary items?", + "warning": "WARNING: this change is permanent and can't be undone afterwards. It can lead to data loss." + }, "virtual-catalog-save": { "title": "Save changes", "message": "The virtual catalog has been modified. Do you want to save changes?" @@ -598,7 +609,7 @@ "code": "Code" }, "validations": { - "code": "Code can't contain $+;=%{}[]|\/@ ~!^*&()?:'<>, characters" + "code": "Code can't contain $+;=%{}[]|@~!^*&()?'<>, characters" }, "placeholders": { "name": "Enter category name", @@ -622,7 +633,7 @@ "seo-information-summary-undefined": "Seo information undefined" }, "validations": { - "sku": "SKU can't contain $+;=%{}[]|\/@ ~!^*&()?:'<>, characters", + "sku": "SKU can't contain $+;=%{}[]|@~!^*&()?'<>, characters", "sku-required": "Required", "name-required": "Required" }, @@ -643,7 +654,7 @@ "upload-images-summary": "{{ count }} image(s) uploaded" }, "validations": { - "sku": "SKU can't contain $+;=%{}[]|\/@ ~!^*&()?:'<>, characters", + "sku": "SKU can't contain $+;=%{}[]|@~!^*&()?'<>, characters", "sku-required": "Required", "name-required": "Required" }, diff --git a/VirtoCommerce.CatalogModule.Web/Localizations/ru.VirtoCommerce.Catalog.json b/VirtoCommerce.CatalogModule.Web/Localizations/ru.VirtoCommerce.Catalog.json index c9a362870..3e5e8ebff 100644 --- a/VirtoCommerce.CatalogModule.Web/Localizations/ru.VirtoCommerce.Catalog.json +++ b/VirtoCommerce.CatalogModule.Web/Localizations/ru.VirtoCommerce.Catalog.json @@ -163,6 +163,7 @@ "applies-to": "Применяется к", "value-type": "Тип значения", "manage-dictionary": "Управление словарем", + "new-dictionary-property-caution": "Для доступа к значениям в начале сохраните свойство", "attributes": "Атрибуты", "manage-attributes": "Управление атрибутами свойств" }, @@ -533,6 +534,10 @@ "shallow": "Метаданные", "full": "Полностью" }, + "property-dictionary-item-delete": { + "message": "Вы уверены, что хотите удалить выбранные справоячные значения?", + "warning": "ПРЕДУПРЕЖДЕНИЕ: это изменение является постоянным и не может быть отменено впоследствии. Это может привести к потере данных." + }, "virtual-catalog-save": { "title": "Сохранение изменений", "message": "Виртуальный каталог был изменен. Вы хотите Сохранение изменений?" diff --git a/VirtoCommerce.CatalogModule.Web/Module.cs b/VirtoCommerce.CatalogModule.Web/Module.cs index 902061950..cf65a6c61 100644 --- a/VirtoCommerce.CatalogModule.Web/Module.cs +++ b/VirtoCommerce.CatalogModule.Web/Module.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Web.Http; using FluentValidation; @@ -50,7 +50,8 @@ public override void SetupDatabase() using (var db = new CatalogRepositoryImpl(_connectionString, _container.Resolve())) { var initializer = new SetupDatabaseInitializer(); - + //The workaround of a known bug with specifying default command timeout within the EF connection string. https://stackoverflow.com/questions/6232633/entity-framework-timeouts/6234593#6234593 + db.Database.CommandTimeout = db.Database.Connection.ConnectionTimeout; initializer.InitializeDatabase(db); } } @@ -98,6 +99,8 @@ public override void Initialize() _container.RegisterType(); _container.RegisterType(); + _container.RegisterType(); + _container.RegisterType(); #endregion diff --git a/VirtoCommerce.CatalogModule.Web/Scripts/blades/category-detail.js b/VirtoCommerce.CatalogModule.Web/Scripts/blades/category-detail.js index 9ef8be843..17983bca4 100644 --- a/VirtoCommerce.CatalogModule.Web/Scripts/blades/category-detail.js +++ b/VirtoCommerce.CatalogModule.Web/Scripts/blades/category-detail.js @@ -1,4 +1,4 @@ -angular.module('virtoCommerce.catalogModule') +angular.module('virtoCommerce.catalogModule') .controller('virtoCommerce.catalogModule.categoryDetailController', ['$rootScope', '$scope', 'platformWebApp.bladeNavigationService', 'platformWebApp.settings', 'virtoCommerce.catalogModule.categories', 'virtoCommerce.catalogModule.catalogs', 'platformWebApp.metaFormsService', function ($rootScope, $scope, bladeNavigationService, settings, categories, catalogs, metaFormsService) { var blade = $scope.blade; blade.updatePermission = 'catalog:update'; @@ -38,7 +38,7 @@ }; blade.codeValidator = function (value) { - var pattern = /[$+;=%{}[\]|\\\/@ ~!^*&()?:'<>,]/; + var pattern = /[$+;=%{}[\]|@~!^*&()?'<>,]/; return !pattern.test(value); }; diff --git a/VirtoCommerce.CatalogModule.Web/Scripts/blades/category-detail.tpl.html b/VirtoCommerce.CatalogModule.Web/Scripts/blades/category-detail.tpl.html index 22b9a9f9a..526553df9 100644 --- a/VirtoCommerce.CatalogModule.Web/Scripts/blades/category-detail.tpl.html +++ b/VirtoCommerce.CatalogModule.Web/Scripts/blades/category-detail.tpl.html @@ -1,17 +1,28 @@ -
+
- -
- -
- +
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
@@ -53,4 +64,4 @@
-
\ No newline at end of file +
diff --git a/VirtoCommerce.CatalogModule.Web/Scripts/blades/common/catalog-items-select.js b/VirtoCommerce.CatalogModule.Web/Scripts/blades/common/catalog-items-select.js index 090bc96d0..a99c0dfc4 100644 --- a/VirtoCommerce.CatalogModule.Web/Scripts/blades/common/catalog-items-select.js +++ b/VirtoCommerce.CatalogModule.Web/Scripts/blades/common/catalog-items-select.js @@ -1,4 +1,4 @@ -angular.module('virtoCommerce.catalogModule') +angular.module('virtoCommerce.catalogModule') .controller('virtoCommerce.catalogModule.catalogItemSelectController', ['$scope', 'virtoCommerce.catalogModule.catalogs', 'virtoCommerce.catalogModule.listEntries', 'platformWebApp.bladeUtils', 'uiGridConstants', 'platformWebApp.uiGridHelper', 'platformWebApp.ui-grid.extension', '$timeout', function ($scope, catalogs, listEntries, bladeUtils, uiGridConstants, uiGridHelper, gridOptionExtension, $timeout) { var blade = $scope.blade; @@ -106,20 +106,19 @@ if ($scope.options.selectItemFn) { $scope.options.selectItemFn(listItem); }; - + var newBlade = { - id: 'CatalogItemsSelect', + id: blade.id, breadcrumbs: blade.breadcrumbs, catalogId: blade.catalogId, catalog: blade.catalog, - controller: 'virtoCommerce.catalogModule.catalogItemSelectController', - template: 'Modules/$(VirtoCommerce.Catalog)/Scripts/blades/common/catalog-items-select.tpl.html', + controller: blade.controller, + template: blade.template, options: $scope.options, searchCriteria: blade.searchCriteria, toolbarCommands: blade.toolbarCommands }; - if ($scope.isCatalogSelectMode()) { newBlade.catalogId = listItem.id; newBlade.catalog = listItem; @@ -140,6 +139,7 @@ }); } else { + //default blade for product details newBlade = { id: "listItemDetail", itemId: listItem.id, @@ -150,6 +150,15 @@ controller: 'virtoCommerce.catalogModule.itemDetailController', template: 'Modules/$(VirtoCommerce.Catalog)/Scripts/blades/item-detail.tpl.html' }; + + //extension point allows to use custom views for product details + if ($scope.options.fnGetBladeForItem) { + var customBlade = $scope.options.fnGetBladeForItem(listItem); + if (customBlade) { + newBlade = customBlade; + } + } + bladeNavigationService.showBlade(newBlade, blade); // setting current categoryId to be globally available @@ -170,9 +179,14 @@ }; $scope.setGridOptions = function (gridId, gridOptions) { - gridOptions.isRowSelectable = function (row) { - return ($scope.options.allowCheckingItem && row.entity.type !== 'category') || ($scope.options.allowCheckingCategory && row.entity.type === 'category'); - }; + gridOptions.isRowSelectable = angular.isFunction($scope.options.isItemSelectable) + ? function(row) { + return $scope.options.isItemSelectable(row.entity); + } + : function(row) { + return $scope.options.allowCheckingItem && row.entity.type !== 'category' || + $scope.options.allowCheckingCategory && row.entity.type === 'category'; + }; gridOptions.columnDefs = gridOptions.columnDefs.concat($scope.options.gridColumns); gridOptionExtension.tryExtendGridOptions(gridId, gridOptions); diff --git a/VirtoCommerce.CatalogModule.Web/Scripts/blades/common/catalog-items-select.tpl.html b/VirtoCommerce.CatalogModule.Web/Scripts/blades/common/catalog-items-select.tpl.html index 5cb46fb5d..8fbccd693 100644 --- a/VirtoCommerce.CatalogModule.Web/Scripts/blades/common/catalog-items-select.tpl.html +++ b/VirtoCommerce.CatalogModule.Web/Scripts/blades/common/catalog-items-select.tpl.html @@ -1,4 +1,4 @@ -
+