Пример #1
0
        public static IPagedList <Customer> ProcessFilter(
            this ITargetGroupService targetGroupService,
            FilterExpression filter,
            int pageIndex = 0,
            int pageSize  = int.MaxValue)
        {
            Guard.NotNull(targetGroupService, nameof(targetGroupService));
            Guard.NotNull(filter, nameof(filter));

            return(targetGroupService.ProcessFilter(new[] { filter }, LogicalRuleOperator.And, pageIndex, pageSize));
        }
Пример #2
0
        public ActionResult Execute(int ruleSetId)
        {
            var success = true;
            var message = string.Empty;

            try
            {
                var entity = _ruleStorage.GetRuleSetById(ruleSetId, false, true);

                switch (entity.Scope)
                {
                case RuleScope.Customer:
                {
                    var provider   = _ruleProvider(entity.Scope) as ITargetGroupService;
                    var expression = _ruleFactory.CreateExpressionGroup(entity, provider, true) as FilterExpression;

                    var result = _targetGroupService.ProcessFilter(new[] { expression }, LogicalRuleOperator.And, 0, 500);

                    message = T("Admin.Rules.Execute.MatchCustomers", result.TotalCount.ToString("N0"));
                }
                break;

                case RuleScope.Cart:
                {
                    var customer   = Services.WorkContext.CurrentCustomer;
                    var provider   = _ruleProvider(entity.Scope) as ICartRuleProvider;
                    var expression = _ruleFactory.CreateExpressionGroup(entity, provider, true) as RuleExpression;

                    var match = provider.RuleMatches(new[] { expression }, LogicalRuleOperator.And);

                    message = T(match ? "Admin.Rules.Execute.MatchCart" : "Admin.Rules.Execute.DoesNotMatchCart", customer.Username.NullEmpty() ?? customer.Email);
                }
                break;
                }
            }
            catch (Exception ex)
            {
                success = false;
                message = ex.Message;
                Logger.Error(ex);
            }

            return(Json(new
            {
                Success = success,
                Message = message.NaIfEmpty()
            }));
        }
        public async Task Run(TaskExecutionContext ctx, CancellationToken cancelToken = default)
        {
            //var count = 0;
            var numDeleted = 0;
            var numAdded   = 0;
            var rolesCount = 0;

            using (var scope = new DbContextScope(_db, autoDetectChanges: false, hooksEnabled: false, deferCommit: true))
            {
                // Delete existing system mappings.
                var deleteQuery = _db.CustomerRoleMappings.Where(x => x.IsSystemMapping);
                if (ctx.Parameters.ContainsKey("CustomerRoleIds"))
                {
                    var roleIds = ctx.Parameters["CustomerRoleIds"].ToIntArray();
                    deleteQuery = deleteQuery.Where(x => roleIds.Contains(x.CustomerRoleId));
                }

                numDeleted = await deleteQuery.BatchDeleteAsync(cancelToken);

                // Insert new customer role mappings.
                var roles = await _db.CustomerRoles
                            .Include(x => x.RuleSets)
                            .AsNoTracking()
                            .Where(x => x.Active && x.RuleSets.Any(y => y.IsActive))
                            .ToListAsync(cancelToken);

                rolesCount = roles.Count;

                foreach (var role in roles)
                {
                    var ruleSetCustomerIds = new HashSet <int>();

                    // TODO: (mg) (core) Complete TargetGroupEvaluatorTask (TaskExecutionContext required).
                    //ctx.SetProgress(++count, roles.Count, $"Add customer assignments for role \"{role.SystemName.NaIfEmpty()}\".");

                    // Execute active rule sets and collect customer ids.
                    foreach (var ruleSet in role.RuleSets.Where(x => x.IsActive))
                    {
                        if (cancelToken.IsCancellationRequested)
                        {
                            return;
                        }

                        var expressionGroup = await _ruleService.CreateExpressionGroupAsync(ruleSet, _targetGroupService);

                        if (expressionGroup is FilterExpression expression)
                        {
                            var filterResult = _targetGroupService.ProcessFilter(expression, 0, 500);
                            var resultPager  = new FastPager <Customer>(filterResult.SourceQuery, 500);

                            while ((await resultPager.ReadNextPageAsync(x => x.Id, x => x)).Out(out var customerIds))
                            {
                                ruleSetCustomerIds.AddRange(customerIds);
                            }
                        }
                    }

                    // Add mappings.
                    if (ruleSetCustomerIds.Any())
                    {
                        foreach (var chunk in ruleSetCustomerIds.Slice(500))
                        {
                            if (cancelToken.IsCancellationRequested)
                            {
                                return;
                            }

                            foreach (var customerId in chunk)
                            {
                                _db.CustomerRoleMappings.Add(new CustomerRoleMapping
                                {
                                    CustomerId      = customerId,
                                    CustomerRoleId  = role.Id,
                                    IsSystemMapping = true
                                });

                                ++numAdded;
                            }

                            await scope.CommitAsync(cancelToken);
                        }

                        try
                        {
                            scope.DbContext.DetachEntities <CustomerRoleMapping>();
                        }
                        catch { }
                    }
                }
            }

            if (numAdded > 0 || numDeleted > 0)
            {
                await _cache.RemoveByPatternAsync(AclService.ACL_SEGMENT_PATTERN);
            }

            Debug.WriteLineIf(numDeleted > 0 || numAdded > 0, $"Deleted {numDeleted} and added {numAdded} customer assignments for {rolesCount} roles.");
        }
        public override async Task ExecuteAsync(TaskExecutionContext ctx)
        {
            var count      = 0;
            var clearCache = false;
            var roleQuery  = _customerRoleRepository.TableUntracked.Expand(x => x.RuleSets);

            if (ctx.Parameters.ContainsKey("CustomerRoleIds"))
            {
                var rolesIds = ctx.Parameters["CustomerRoleIds"].ToIntArray();
                roleQuery = roleQuery.Where(x => rolesIds.Contains(x.Id));
            }

            var roles = await roleQuery.ToListAsync();

            if (!roles.Any())
            {
                return;
            }

            using (var scope = new DbContextScope(ctx: _customerRoleMappingRepository.Context, autoDetectChanges: false, validateOnSave: false, hooksEnabled: false, autoCommit: false))

                foreach (var role in roles)
                {
                    try
                    {
                        ctx.SetProgress(++count, roles.Count, $"Sync customer assignments for role {role.SystemName.NaIfEmpty()}.");

                        _customerRoleMappingRepository.Context.DetachEntities(x => x is CustomerRoleMapping);
                    }
                    catch { }

                    var ruleSetCustomerIds  = new HashSet <int>();
                    var existingCustomerIds = new HashSet <int>();
                    var numDeleted          = 0;
                    var numAdded            = 0;

                    // Execute active rule sets and collect customer ids.
                    // Delete old mappings if the role is inactive or has no assigned rule sets.
                    if (role.Active)
                    {
                        foreach (var ruleSet in role.RuleSets.Where(x => x.IsActive))
                        {
                            if (ctx.CancellationToken.IsCancellationRequested)
                            {
                                return;
                            }

                            var expression = _ruleFactory.CreateExpressionGroup(ruleSet, _targetGroupService) as FilterExpression;
                            if (expression != null)
                            {
                                var filterResult = _targetGroupService.ProcessFilter(expression, 0, 500);
                                var resultPager  = new FastPager <Customer>(filterResult.SourceQuery, 500);

                                for (var i = 0; i < 9999999; ++i)
                                {
                                    var customerIds = await resultPager.ReadNextPageAsync(x => x.Id, x => x);

                                    if (!(customerIds?.Any() ?? false))
                                    {
                                        break;
                                    }

                                    ruleSetCustomerIds.AddRange(customerIds);
                                }
                            }
                        }
                    }

                    // Sync mappings.
                    var query = _customerRoleMappingRepository.Table.Where(x => x.CustomerRoleId == role.Id && x.IsSystemMapping);
                    var pager = new FastPager <CustomerRoleMapping>(query, 500);

                    // Mappings to delete.
                    for (var i = 0; i < 9999999; ++i)
                    {
                        if (ctx.CancellationToken.IsCancellationRequested)
                        {
                            return;
                        }

                        var mappings = await pager.ReadNextPageAsync <CustomerRoleMapping>();

                        if (!(mappings?.Any() ?? false))
                        {
                            break;
                        }

                        foreach (var mapping in mappings)
                        {
                            if (!role.Active || !ruleSetCustomerIds.Contains(mapping.CustomerId))
                            {
                                _customerRoleMappingRepository.Delete(mapping);

                                ++numDeleted;
                                clearCache = true;
                            }
                            else
                            {
                                existingCustomerIds.Add(mapping.CustomerId);
                            }
                        }

                        await scope.CommitAsync();
                    }

                    // Mappings to add.
                    if (role.Active)
                    {
                        var toAdd = ruleSetCustomerIds.Except(existingCustomerIds).ToList();
                        if (toAdd.Any())
                        {
                            foreach (var chunk in toAdd.Slice(500))
                            {
                                if (ctx.CancellationToken.IsCancellationRequested)
                                {
                                    return;
                                }

                                foreach (var customerId in chunk)
                                {
                                    _customerRoleMappingRepository.Insert(new CustomerRoleMapping
                                    {
                                        CustomerId      = customerId,
                                        CustomerRoleId  = role.Id,
                                        IsSystemMapping = true
                                    });

                                    ++numAdded;
                                    clearCache = true;
                                }

                                await scope.CommitAsync();
                            }
                        }
                    }

                    Debug.WriteLineIf(numDeleted > 0 || numAdded > 0, $"Customer assignments for {role.SystemName.NaIfEmpty()}: deleted {numDeleted}, added {numAdded}.");
                }

            if (clearCache)
            {
                _cacheManager.RemoveByPattern(AclService.ACL_SEGMENT_PATTERN);
            }
        }
        public override async Task ExecuteAsync(TaskExecutionContext ctx)
        {
            var count      = 0;
            var numDeleted = 0;
            var numAdded   = 0;
            var roleQuery  = _customerRoleRepository.TableUntracked.Expand(x => x.RuleSets);

            if (ctx.Parameters.ContainsKey("CustomerRoleIds"))
            {
                var roleIds = ctx.Parameters["CustomerRoleIds"].ToIntArray();
                roleQuery = roleQuery.Where(x => roleIds.Contains(x.Id));

                numDeleted = _customerRoleMappingRepository.Context.ExecuteSqlCommand(
                    "Delete From [dbo].[CustomerRoleMapping] Where [CustomerRoleId] In ({0}) And [IsSystemMapping] = 1",
                    false,
                    null,
                    string.Join(",", roleIds));
            }
            else
            {
                numDeleted = _customerRoleMappingRepository.Context.ExecuteSqlCommand("Delete From [dbo].[CustomerRoleMapping] Where [IsSystemMapping] = 1");
            }

            var roles = await roleQuery
                        .Where(x => x.Active && x.RuleSets.Any(y => y.IsActive))
                        .ToListAsync();

            using (var scope = new DbContextScope(ctx: _customerRoleMappingRepository.Context, autoDetectChanges: false, validateOnSave: false, hooksEnabled: false, autoCommit: false))
            {
                foreach (var role in roles)
                {
                    var ruleSetCustomerIds = new HashSet <int>();

                    ctx.SetProgress(++count, roles.Count, $"Add customer assignments for role \"{role.SystemName.NaIfEmpty()}\".");

                    // Execute active rule sets and collect customer ids.
                    foreach (var ruleSet in role.RuleSets.Where(x => x.IsActive))
                    {
                        if (ctx.CancellationToken.IsCancellationRequested)
                        {
                            return;
                        }

                        if (_ruleFactory.CreateExpressionGroup(ruleSet, _targetGroupService) is FilterExpression expression)
                        {
                            var filterResult = _targetGroupService.ProcessFilter(expression, 0, 500);
                            var resultPager  = new FastPager <Customer>(filterResult.SourceQuery, 500);

                            while (true)
                            {
                                var customerIds = await resultPager.ReadNextPageAsync(x => x.Id, x => x);

                                if (!(customerIds?.Any() ?? false))
                                {
                                    break;
                                }

                                ruleSetCustomerIds.AddRange(customerIds);
                            }
                        }
                    }

                    // Add mappings.
                    if (ruleSetCustomerIds.Any())
                    {
                        foreach (var chunk in ruleSetCustomerIds.Slice(500))
                        {
                            if (ctx.CancellationToken.IsCancellationRequested)
                            {
                                return;
                            }

                            foreach (var customerId in chunk)
                            {
                                _customerRoleMappingRepository.Insert(new CustomerRoleMapping
                                {
                                    CustomerId      = customerId,
                                    CustomerRoleId  = role.Id,
                                    IsSystemMapping = true
                                });

                                ++numAdded;
                            }

                            await scope.CommitAsync();
                        }

                        try
                        {
                            _customerRoleMappingRepository.Context.DetachEntities <CustomerRoleMapping>();
                        }
                        catch { }
                    }
                }
            }

            if (numAdded > 0 || numDeleted > 0)
            {
                _cacheManager.RemoveByPattern(AclService.ACL_SEGMENT_PATTERN);
            }

            Debug.WriteLineIf(numDeleted > 0 || numAdded > 0, $"Deleted {numDeleted} and added {numAdded} customer assignments for {roles.Count} roles.");
        }