Пример #1
0
        protected override async Task <IEnumerable <RuleDescriptor> > LoadDescriptorsAsync()
        {
            var language   = _services.WorkContext.WorkingLanguage;
            var oneStarStr = T("Search.Facet.1StarAndMore").Value;
            var xStarsStr  = T("Search.Facet.XStarsAndMore").Value;

            var stores = _services.StoreContext.GetAllStores()
                         .Select(x => new RuleValueSelectListOption {
                Value = x.Id.ToString(), Text = x.Name
            })
                         .ToArray();

            var visibilities = ((ProductVisibility[])Enum.GetValues(typeof(ProductVisibility)))
                               .Select(x => new RuleValueSelectListOption {
                Value = ((int)x).ToString(), Text = _localizedEntityHelper.GetLocalizedEnum(x)
            })
                               .ToArray();

            var productTypes = ((ProductType[])Enum.GetValues(typeof(ProductType)))
                               .Select(x => new RuleValueSelectListOption {
                Value = ((int)x).ToString(), Text = _localizedEntityHelper.GetLocalizedEnum(x)
            })
                               .ToArray();

            var ratings = FacetUtility.GetRatings()
                          .Reverse()
                          .Skip(1)
                          .Select(x => new RuleValueSelectListOption
            {
                Value = ((double)x.Value).ToString(CultureInfo.InvariantCulture),
                Text  = (double)x.Value == 1 ? oneStarStr : xStarsStr.FormatInvariant(x.Value)
            })
                          .ToArray();

            var categoryTree = _catalogSettings.ShowProductsFromSubcategories
                ? await _categoryService.GetCategoryTreeAsync(includeHidden : true)
                : null;

            #region Special filters

            CatalogSearchQuery categoryFilter(SearchFilterContext ctx, int[] x)
            {
                if (x?.Any() ?? false)
                {
                    var ids = new HashSet <int>(x);

                    if (_catalogSettings.ShowProductsFromSubcategories)
                    {
                        foreach (var id in x)
                        {
                            var node = categoryTree.SelectNodeById(id);
                            if (node != null)
                            {
                                ids.AddRange(node.Flatten(false).Select(y => y.Id));
                            }
                        }
                    }

                    return(ctx.Query.WithCategoryIds(_catalogSettings.IncludeFeaturedProductsInNormalLists ? (bool?)null : false, ids.ToArray()));
                }

                return(ctx.Query);
            };

            CatalogSearchQuery stockQuantityFilter(SearchFilterContext ctx, int x)
            {
                if (ctx.Expression.Operator == RuleOperator.IsEqualTo || ctx.Expression.Operator == RuleOperator.IsNotEqualTo)
                {
                    return(ctx.Query.WithStockQuantity(x, x, ctx.Expression.Operator == RuleOperator.IsEqualTo, ctx.Expression.Operator == RuleOperator.IsEqualTo));
                }
                else if (ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo || ctx.Expression.Operator == RuleOperator.GreaterThan)
                {
                    return(ctx.Query.WithStockQuantity(x, null, ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo, null));
                }
                else if (ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo || ctx.Expression.Operator == RuleOperator.LessThan)
                {
                    return(ctx.Query.WithStockQuantity(null, x, null, ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo));
                }

                return(ctx.Query);
            };

            CatalogSearchQuery priceFilter(SearchFilterContext ctx, decimal x)
            {
                if (ctx.Expression.Operator == RuleOperator.IsEqualTo || ctx.Expression.Operator == RuleOperator.IsNotEqualTo)
                {
                    return(ctx.Query.PriceBetween(x, x, ctx.Expression.Operator == RuleOperator.IsEqualTo, ctx.Expression.Operator == RuleOperator.IsEqualTo));
                }
                else if (ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo || ctx.Expression.Operator == RuleOperator.GreaterThan)
                {
                    return(ctx.Query.PriceBetween(x, null, ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo, null));
                }
                else if (ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo || ctx.Expression.Operator == RuleOperator.LessThan)
                {
                    return(ctx.Query.PriceBetween(null, x, null, ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo));
                }

                return(ctx.Query);
            };

            CatalogSearchQuery createdFilter(SearchFilterContext ctx, DateTime x)
            {
                if (ctx.Expression.Operator == RuleOperator.IsEqualTo || ctx.Expression.Operator == RuleOperator.IsNotEqualTo)
                {
                    return(ctx.Query.CreatedBetween(x, x, ctx.Expression.Operator == RuleOperator.IsEqualTo, ctx.Expression.Operator == RuleOperator.IsEqualTo));
                }
                else if (ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo || ctx.Expression.Operator == RuleOperator.GreaterThan)
                {
                    return(ctx.Query.CreatedBetween(x, null, ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo, null));
                }
                else if (ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo || ctx.Expression.Operator == RuleOperator.LessThan)
                {
                    return(ctx.Query.CreatedBetween(null, x, null, ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo));
                }

                return(ctx.Query);
            };

            #endregion

            var descriptors = new List <SearchFilterDescriptor>
            {
                new SearchFilterDescriptor <int>((ctx, x) => ctx.Query.HasStoreId(x))
                {
                    Name        = "Store",
                    DisplayName = T("Admin.Rules.FilterDescriptor.Store"),
                    RuleType    = RuleType.Int,
                    SelectList  = new LocalRuleValueSelectList(stores),
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.AllowedCustomerRoles(x))
                {
                    Name        = "CustomerRole",
                    DisplayName = T("Admin.Rules.FilterDescriptor.IsInCustomerRole"),
                    RuleType    = RuleType.IntArray,
                    SelectList  = new RemoteRuleValueSelectList("CustomerRole")
                    {
                        Multiple = true
                    },
                    Operators = new RuleOperator[] { RuleOperator.In }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.PublishedOnly(x))
                {
                    Name        = "Published",
                    DisplayName = T("Admin.Catalog.Products.Fields.Published"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.AvailableOnly(x))
                {
                    Name        = "AvailableByStock",
                    DisplayName = T("Products.Availability.InStock"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.AvailableByDate(x))
                {
                    Name        = "AvailableByDate",
                    DisplayName = T("Admin.Rules.FilterDescriptor.AvailableByDate"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <int>((ctx, x) => ctx.Query.WithVisibility((ProductVisibility)x))
                {
                    Name        = "Visibility",
                    DisplayName = T("Admin.Catalog.Products.Fields.Visibility"),
                    RuleType    = RuleType.Int,
                    SelectList  = new LocalRuleValueSelectList(visibilities),
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithProductIds(x))
                {
                    Name        = "Product",
                    DisplayName = T("Common.Entity.Product"),
                    RuleType    = RuleType.IntArray,
                    SelectList  = new RemoteRuleValueSelectList("Product")
                    {
                        Multiple = true
                    },
                    Operators = new RuleOperator[] { RuleOperator.In }
                },
                new SearchFilterDescriptor <int>((ctx, x) => ctx.Query.IsProductType((ProductType)x))
                {
                    Name        = "ProductType",
                    DisplayName = T("Admin.Catalog.Products.Fields.ProductType"),
                    RuleType    = RuleType.Int,
                    SelectList  = new LocalRuleValueSelectList(productTypes),
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <int[]>(categoryFilter)
                {
                    Name        = "Category",
                    DisplayName = T("Common.Entity.Category"),
                    RuleType    = RuleType.IntArray,
                    SelectList  = new RemoteRuleValueSelectList("Category")
                    {
                        Multiple = true
                    },
                    Operators = new RuleOperator[] { RuleOperator.In }
                },
                new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithManufacturerIds(null, x))
                {
                    Name        = "Manufacturer",
                    DisplayName = T("Common.Entity.Manufacturer"),
                    RuleType    = RuleType.IntArray,
                    SelectList  = new RemoteRuleValueSelectList("Manufacturer")
                    {
                        Multiple = true
                    },
                    Operators = new RuleOperator[] { RuleOperator.In }
                },
                // Same logic as the filter above product list.
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.HasAnyCategory(!x))
                {
                    Name        = "WithoutCategory",
                    DisplayName = T("Admin.Catalog.Products.List.SearchWithoutCategories"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.HasAnyManufacturer(!x))
                {
                    Name        = "WithoutManufacturer",
                    DisplayName = T("Admin.Catalog.Products.List.SearchWithoutManufacturers"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithProductTagIds(x))
                {
                    Name        = "ProductTag",
                    DisplayName = T("Admin.Catalog.Products.Fields.ProductTags"),
                    RuleType    = RuleType.IntArray,
                    SelectList  = new RemoteRuleValueSelectList("ProductTag")
                    {
                        Multiple = true
                    },
                    Operators = new RuleOperator[] { RuleOperator.In }
                },
                new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithDeliveryTimeIds(x))
                {
                    Name        = "DeliveryTime",
                    DisplayName = T("Admin.Catalog.Products.Fields.DeliveryTime"),
                    RuleType    = RuleType.IntArray,
                    Operators   = new RuleOperator[] { RuleOperator.In },
                    SelectList  = new RemoteRuleValueSelectList("DeliveryTime")
                    {
                        Multiple = true
                    }
                },
                new SearchFilterDescriptor <int>(stockQuantityFilter)
                {
                    Name        = "StockQuantity",
                    DisplayName = T("Admin.Catalog.Products.Fields.StockQuantity"),
                    RuleType    = RuleType.Int
                },
                new SearchFilterDescriptor <decimal>(priceFilter)
                {
                    Name        = "Price",
                    DisplayName = T("Admin.Catalog.Products.Fields.Price"),
                    RuleType    = RuleType.Money
                },
                new SearchFilterDescriptor <DateTime>(createdFilter)
                {
                    Name        = "CreatedOn",
                    DisplayName = T("Common.CreatedOn"),
                    RuleType    = RuleType.DateTime
                },
                new SearchFilterDescriptor <double>((ctx, x) => ctx.Query.WithRating(x, null))
                {
                    Name        = "Rating",
                    DisplayName = T("Admin.Catalog.ProductReviews.Fields.Rating"),
                    RuleType    = RuleType.Float,
                    Operators   = new RuleOperator[] { RuleOperator.GreaterThanOrEqualTo },
                    SelectList  = new LocalRuleValueSelectList(ratings)
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.HomePageProductsOnly(x))
                {
                    Name        = "HomepageProduct",
                    DisplayName = T("Admin.Catalog.Products.Fields.ShowOnHomePage"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.DownloadOnly(x))
                {
                    Name        = "Download",
                    DisplayName = T("Admin.Catalog.Products.Fields.IsDownload"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.RecurringOnly(x))
                {
                    Name        = "Recurring",
                    DisplayName = T("Admin.Catalog.Products.Fields.IsRecurring"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.ShipEnabledOnly(x))
                {
                    Name        = "ShipEnabled",
                    DisplayName = T("Admin.Catalog.Products.Fields.IsShipEnabled"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.FreeShippingOnly(x))
                {
                    Name        = "FreeShipping",
                    DisplayName = T("Admin.Catalog.Products.Fields.IsFreeShipping"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.TaxExemptOnly(x))
                {
                    Name        = "TaxExempt",
                    DisplayName = T("Admin.Catalog.Products.Fields.IsTaxExempt"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.EsdOnly(x))
                {
                    Name        = "Esd",
                    DisplayName = T("Admin.Catalog.Products.Fields.IsEsd"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                },
                new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.HasDiscount(x))
                {
                    Name        = "Discount",
                    DisplayName = T("Admin.Catalog.Products.Fields.HasDiscountsApplied"),
                    RuleType    = RuleType.Boolean,
                    Operators   = new RuleOperator[] { RuleOperator.IsEqualTo }
                }
            };

            if (_services.ApplicationContext.ModuleCatalog.GetModuleByName("SmartStore.MegaSearchPlus") != null)
            {
                ISearchFilter[] filters(string fieldName, int parentId, int[] valueIds)
                {
                    return(valueIds.Select(id => SearchFilter.ByField(fieldName, id).ExactMatch().NotAnalyzed().HasParent(parentId)).ToArray());
                }

                // Sort by display order!
                var pageIndex     = -1;
                var variantsQuery = _services.DbContext.ProductAttributes
                                    .AsNoTracking()
                                    .Where(x => x.AllowFiltering)
                                    .OrderBy(x => x.DisplayOrder);

                while (true)
                {
                    var variants = await PagedList.Create(variantsQuery, ++pageIndex, 1000).LoadAsync();

                    foreach (var variant in variants)
                    {
                        var descriptor = new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithFilter(SearchFilter.Combined(filters("variantvalueid", variant.Id, x))))
                        {
                            Name        = $"Variant{variant.Id}",
                            DisplayName = variant.GetLocalized(x => x.Name, language, true, false),
                            GroupKey    = "Admin.Catalog.Attributes.ProductAttributes",
                            RuleType    = RuleType.IntArray,
                            SelectList  = new RemoteRuleValueSelectList("VariantValue")
                            {
                                Multiple = true
                            },
                            Operators = new RuleOperator[] { RuleOperator.In }
                        };
                        descriptor.Metadata["ParentId"] = variant.Id;

                        descriptors.Add(descriptor);
                    }
                    if (!variants.HasNextPage)
                    {
                        break;
                    }
                }

                pageIndex = -1;
                var attributesQuery = _services.DbContext.SpecificationAttributes
                                      .AsNoTracking()
                                      .Where(x => x.AllowFiltering)
                                      .OrderBy(x => x.DisplayOrder);

                while (true)
                {
                    var attributes = await PagedList.Create(attributesQuery, ++pageIndex, 1000).LoadAsync();

                    foreach (var attribute in attributes)
                    {
                        var descriptor = new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithFilter(SearchFilter.Combined(filters("attrvalueid", attribute.Id, x))))
                        {
                            Name        = $"Attribute{attribute.Id}",
                            DisplayName = attribute.GetLocalized(x => x.Name, language, true, false),
                            GroupKey    = "Admin.Catalog.Attributes.SpecificationAttributes",
                            RuleType    = RuleType.IntArray,
                            SelectList  = new RemoteRuleValueSelectList("AttributeOption")
                            {
                                Multiple = true
                            },
                            Operators = new RuleOperator[] { RuleOperator.In }
                        };
                        descriptor.Metadata["ParentId"] = attribute.Id;

                        descriptors.Add(descriptor);
                    }
                    if (!attributes.HasNextPage)
                    {
                        break;
                    }
                }
            }

            descriptors
            .Where(x => x.RuleType == RuleType.Money)
            .Each(x => x.Metadata["postfix"] = _services.StoreContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode);

            return(descriptors.Cast <RuleDescriptor>());
        }
Пример #2
0
        protected override Task <IEnumerable <RuleDescriptor> > LoadDescriptorsAsync()
        {
            var stores = _storeContext.GetAllStores()
                         .Select(x => new RuleValueSelectListOption {
                Value = x.Id.ToString(), Text = x.Name
            })
                         .ToArray();

            var vatNumberStatus = ((VatNumberStatus[])Enum.GetValues(typeof(VatNumberStatus)))
                                  .Select(x => new RuleValueSelectListOption {
                Value = ((int)x).ToString(), Text = _localizedEntityHelper.GetLocalizedEnum(x)
            })
                                  .ToArray();

            var taxDisplayTypes = ((TaxDisplayType[])Enum.GetValues(typeof(TaxDisplayType)))
                                  .Select(x => new RuleValueSelectListOption {
                Value = ((int)x).ToString(), Text = _localizedEntityHelper.GetLocalizedEnum(x)
            })
                                  .ToArray();

            var shippingStatus = ((ShippingStatus[])Enum.GetValues(typeof(ShippingStatus)))
                                 .Select(x => new RuleValueSelectListOption {
                Value = ((int)x).ToString(), Text = _localizedEntityHelper.GetLocalizedEnum(x)
            })
                                 .ToArray();

            var paymentStatus = ((PaymentStatus[])Enum.GetValues(typeof(PaymentStatus)))
                                .Select(x => new RuleValueSelectListOption {
                Value = ((int)x).ToString(), Text = _localizedEntityHelper.GetLocalizedEnum(x)
            })
                                .ToArray();

            var descriptors = new List <FilterDescriptor>
            {
                new FilterDescriptor <Customer, bool>(x => x.Active)
                {
                    Name        = "Active",
                    DisplayName = T("Admin.Rules.FilterDescriptor.Active"),
                    RuleType    = RuleType.Boolean
                },
                new FilterDescriptor <Customer, string>(x => x.Salutation)
                {
                    Name        = "Salutation",
                    DisplayName = T("Admin.Rules.FilterDescriptor.Salutation"),
                    RuleType    = RuleType.String
                },
                new FilterDescriptor <Customer, string>(x => x.Title)
                {
                    Name        = "Title",
                    DisplayName = T("Admin.Rules.FilterDescriptor.Title"),
                    RuleType    = RuleType.String
                },
                new FilterDescriptor <Customer, string>(x => x.Company)
                {
                    Name        = "Company",
                    DisplayName = T("Admin.Rules.FilterDescriptor.Company"),
                    RuleType    = RuleType.String
                },
                new FilterDescriptor <Customer, string>(x => x.Gender)
                {
                    Name        = "Gender",
                    DisplayName = T("Admin.Rules.FilterDescriptor.Gender"),
                    RuleType    = RuleType.String
                },
                new FilterDescriptor <Customer, string>(x => x.CustomerNumber)
                {
                    Name        = "CustomerNumber",
                    DisplayName = T("Admin.Rules.FilterDescriptor.CustomerNumber"),
                    RuleType    = RuleType.String
                },
                new AnyFilterDescriptor <Customer, CustomerRoleMapping, int>(x => x.CustomerRoleMappings, rm => rm.CustomerRoleId)
                {
                    Name        = "IsInCustomerRole",
                    DisplayName = T("Admin.Rules.FilterDescriptor.IsInCustomerRole"),
                    RuleType    = RuleType.IntArray,
                    SelectList  = new RemoteRuleValueSelectList("CustomerRole")
                    {
                        Multiple = true
                    }
                },
                new FilterDescriptor <Customer, bool>(x => x.IsTaxExempt)
                {
                    Name        = "TaxExempt",
                    DisplayName = T("Admin.Rules.FilterDescriptor.TaxExempt"),
                    RuleType    = RuleType.Boolean
                },
                new FilterDescriptor <Customer, int>(x => x.VatNumberStatusId)
                {
                    Name        = "VatNumberStatus",
                    DisplayName = T("Admin.Rules.FilterDescriptor.VatNumberStatus"),
                    RuleType    = RuleType.Int,
                    SelectList  = new LocalRuleValueSelectList(vatNumberStatus)
                },
                new FilterDescriptor <Customer, int>(x => x.TaxDisplayTypeId)
                {
                    Name        = "TaxDisplayType",
                    DisplayName = T("Admin.Rules.FilterDescriptor.TaxDisplayType"),
                    RuleType    = RuleType.Int,
                    SelectList  = new LocalRuleValueSelectList(taxDisplayTypes)
                },
                new FilterDescriptor <Customer, string>(x => x.TimeZoneId)
                {
                    Name        = "TimeZone",
                    DisplayName = T("Admin.Rules.FilterDescriptor.TimeZone"),
                    RuleType    = RuleType.String
                },
                new FilterDescriptor <Customer, string>(x => x.LastUserAgent)
                {
                    Name        = "LastUserAgent",
                    DisplayName = T("Admin.Rules.FilterDescriptor.LastUserAgent"),
                    RuleType    = RuleType.String
                },
                new FilterDescriptor <Customer, int?>(x => x.BillingAddress != null ? x.BillingAddress.CountryId : 0)
                {
                    Name        = "BillingCountry",
                    DisplayName = T("Admin.Rules.FilterDescriptor.BillingCountry"),
                    RuleType    = RuleType.IntArray,
                    SelectList  = new RemoteRuleValueSelectList("Country")
                    {
                        Multiple = true
                    }
                },
                new FilterDescriptor <Customer, int?>(x => x.ShippingAddress != null ? x.ShippingAddress.CountryId : 0)
                {
                    Name        = "ShippingCountry",
                    DisplayName = T("Admin.Rules.FilterDescriptor.ShippingCountry"),
                    RuleType    = RuleType.IntArray,
                    SelectList  = new RemoteRuleValueSelectList("Country")
                    {
                        Multiple = true
                    }
                },
                // TODO: (mg) (core) Complete TargetGroupService (Customer.ReturnRequests required).
                //new FilterDescriptor<Customer, int>(x => x.ReturnRequests.Count())
                //{
                //    Name = "ReturnRequestCount",
                //    DisplayName = T("Admin.Rules.FilterDescriptor.ReturnRequestCount"),
                //    RuleType = RuleType.Int
                //},

                new FilterDescriptor <Customer, int?>(x => EF.Functions.DateDiffDay(x.LastActivityDateUtc, DateTime.UtcNow))
                {
                    Name        = "LastActivityDays",
                    DisplayName = T("Admin.Rules.FilterDescriptor.LastActivityDays"),
                    RuleType    = RuleType.NullableInt
                },
                new FilterDescriptor <Customer, int?>(x => EF.Functions.DateDiffDay(x.LastLoginDateUtc, DateTime.UtcNow))
                {
                    Name        = "LastLoginDays",
                    DisplayName = T("Admin.Rules.FilterDescriptor.LastLoginDays"),
                    RuleType    = RuleType.NullableInt
                },
                new FilterDescriptor <Customer, int?>(x => EF.Functions.DateDiffDay(x.LastForumVisit, DateTime.UtcNow))
                {
                    Name        = "LastForumVisitDays",
                    DisplayName = T("Admin.Rules.FilterDescriptor.LastForumVisit"),
                    RuleType    = RuleType.NullableInt
                },
                new FilterDescriptor <Customer, int?>(x => EF.Functions.DateDiffDay(x.CreatedOnUtc, DateTime.UtcNow))
                {
                    Name        = "CreatedDays",
                    DisplayName = T("Admin.Rules.FilterDescriptor.CreatedDays"),
                    RuleType    = RuleType.NullableInt
                },
                new FilterDescriptor <Customer, int?>(x => EF.Functions.DateDiffDay(x.BirthDate, DateTime.UtcNow))
                {
                    Name        = "BirthDateDays",
                    DisplayName = T("Admin.Rules.FilterDescriptor.BirthDate"),
                    RuleType    = RuleType.NullableInt
                },
                new TargetGroupFilterDescriptor(_ruleService, this)
                {
                    Name        = "RuleSet",
                    DisplayName = T("Admin.Rules.FilterDescriptor.RuleSet"),
                    RuleType    = RuleType.Int,
                    Operators   = new[] { RuleOperator.IsEqualTo, RuleOperator.IsNotEqualTo },
                    SelectList  = new RemoteRuleValueSelectList("TargetGroup")
                },

                new AnyFilterDescriptor <Customer, Order, int>(x => x.Orders, o => o.StoreId)
                {
                    Name        = "OrderInStore",
                    DisplayName = T("Admin.Rules.FilterDescriptor.OrderInStore"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.IntArray,
                    SelectList  = new LocalRuleValueSelectList(stores)
                    {
                        Multiple = true
                    }
                },
                new FilterDescriptor <Customer, int>(x => x.Orders.Count(o => o.OrderStatusId == 10 || o.OrderStatusId == 20))
                {
                    Name        = "NewOrderCount",
                    DisplayName = T("Admin.Rules.FilterDescriptor.NewOrderCount"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.Int
                },
                new FilterDescriptor <Customer, int>(x => x.Orders.Count(o => o.OrderStatusId == 30))
                {
                    Name        = "CompletedOrderCount",
                    DisplayName = T("Admin.Rules.FilterDescriptor.CompletedOrderCount"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.Int
                },
                new FilterDescriptor <Customer, int>(x => x.Orders.Count(o => o.OrderStatusId == 40))
                {
                    Name        = "CancelledOrderCount",
                    DisplayName = T("Admin.Rules.FilterDescriptor.CancelledOrderCount"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.Int
                },
                new FilterDescriptor <Customer, int?>(x => EF.Functions.DateDiffDay(x.Orders.Max(o => o.CreatedOnUtc), DateTime.UtcNow))
                {
                    Name        = "LastOrderDateDays",
                    DisplayName = T("Admin.Rules.FilterDescriptor.LastOrderDateDays"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.NullableInt
                },
                new AnyFilterDescriptor <Customer, Order, decimal>(x => x.Orders, o => o.OrderTotal)
                {
                    Name        = "OrderTotal",
                    DisplayName = T("Admin.Rules.FilterDescriptor.OrderTotal"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.Money
                },
                new AnyFilterDescriptor <Customer, Order, decimal>(x => x.Orders, o => o.OrderSubtotalInclTax)
                {
                    Name        = "OrderSubtotalInclTax",
                    DisplayName = T("Admin.Rules.FilterDescriptor.OrderSubtotalInclTax"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.Money
                },
                new AnyFilterDescriptor <Customer, Order, decimal>(x => x.Orders, o => o.OrderSubtotalExclTax)
                {
                    Name        = "OrderSubtotalExclTax",
                    DisplayName = T("Admin.Rules.FilterDescriptor.OrderSubtotalExclTax"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.Money
                },
                new AnyFilterDescriptor <Customer, Order, int>(x => x.Orders, o => o.ShippingStatusId)
                {
                    Name        = "ShippingStatus",
                    DisplayName = T("Admin.Rules.FilterDescriptor.ShippingStatus"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.Int,
                    SelectList  = new LocalRuleValueSelectList(shippingStatus)
                },
                new AnyFilterDescriptor <Customer, Order, int>(x => x.Orders, o => o.PaymentStatusId)
                {
                    Name        = "PaymentStatus",
                    DisplayName = T("Admin.Rules.FilterDescriptor.PaymentStatus"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.Int,
                    SelectList  = new LocalRuleValueSelectList(paymentStatus)
                },
                new AnyFilterDescriptor <Customer, OrderItem, int>(x => x.Orders.SelectMany(o => o.OrderItems), oi => oi.ProductId)
                {
                    Name        = "HasPurchasedProduct",
                    DisplayName = T("Admin.Rules.FilterDescriptor.HasPurchasedProduct"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.IntArray,
                    SelectList  = new RemoteRuleValueSelectList("Product")
                    {
                        Multiple = true
                    }
                },
                new AllFilterDescriptor <Customer, OrderItem, int>(x => x.Orders.SelectMany(o => o.OrderItems), oi => oi.ProductId)
                {
                    Name        = "HasPurchasedAllProducts",
                    DisplayName = T("Admin.Rules.FilterDescriptor.HasPurchasedAllProducts"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.IntArray,
                    SelectList  = new RemoteRuleValueSelectList("Product")
                    {
                        Multiple = true
                    }
                },
                new AnyFilterDescriptor <Customer, Order, bool>(x => x.Orders, o => o.AcceptThirdPartyEmailHandOver)
                {
                    Name        = "AcceptThirdPartyEmailHandOver",
                    DisplayName = T("Admin.Rules.FilterDescriptor.AcceptThirdPartyEmailHandOver"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.Boolean
                },
                new AnyFilterDescriptor <Customer, Order, string>(x => x.Orders, o => o.CustomerCurrencyCode)
                {
                    Name        = "CurrencyCode",
                    DisplayName = T("Admin.Rules.FilterDescriptor.Currency"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.String,
                    SelectList  = new RemoteRuleValueSelectList("Currency")
                },
                new AnyFilterDescriptor <Customer, Order, int>(x => x.Orders, o => o.CustomerLanguageId)
                {
                    Name        = "OrderLanguage",
                    DisplayName = T("Admin.Rules.FilterDescriptor.Language"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.Int,
                    SelectList  = new RemoteRuleValueSelectList("Language")
                },
                new AnyFilterDescriptor <Customer, Order, string>(x => x.Orders, o => o.PaymentMethodSystemName)
                {
                    Name        = "PaymentMethod",
                    DisplayName = T("Admin.Rules.FilterDescriptor.PaidBy"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.String,
                    SelectList  = new RemoteRuleValueSelectList("PaymentMethod")
                },
                new AnyFilterDescriptor <Customer, Order, string>(x => x.Orders, o => o.ShippingMethod)
                {
                    Name        = "ShippingMethod",
                    DisplayName = T("Admin.Rules.FilterDescriptor.ShippingMethod"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.String,
                    SelectList  = new RemoteRuleValueSelectList("ShippingMethod")
                },
                new AnyFilterDescriptor <Customer, Order, string>(x => x.Orders, o => o.ShippingRateComputationMethodSystemName)
                {
                    Name        = "ShippingRateComputationMethod",
                    DisplayName = T("Admin.Rules.FilterDescriptor.ShippingRateComputationMethod"),
                    GroupKey    = "Admin.Orders",
                    RuleType    = RuleType.String,
                    SelectList  = new RemoteRuleValueSelectList("ShippingRateComputationMethod")
                }
            };

            descriptors
            .Where(x => x.RuleType == RuleType.Money)
            .Each(x => x.Metadata["postfix"] = _storeContext.CurrentStore.PrimaryStoreCurrency.CurrencyCode);

            return(Task.FromResult(descriptors.Cast <RuleDescriptor>()));
        }