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