示例#1
0
        public bool IsProductsRegionIntersectionsExists(ArticleService articleService, string productsName, int[] productsIds, string regionsName)
        {
            int productTypesContentId = GetSettingValue(SettingsTitles.PRODUCT_TYPES_CONTENT_ID);

            CheckSiteId(productTypesContentId);

            int contentId = GetSettingValue(SettingsTitles.PRODUCTS_CONTENT_ID);

            Dictionary <int, int[]> productToRegions = articleService.List(contentId, productsIds, true)
                                                       .ToDictionary(x => x.Id, x => x.FieldValues.Single(a => a.Field.Name == regionsName).RelatedItems.ToArray());

            Dictionary <int, HashSet <int> > regionsToProducts = new Dictionary <int, HashSet <int> >();

            foreach (var item in productToRegions)
            {
                foreach (var regionId in item.Value)
                {
                    if (!regionsToProducts.ContainsKey(regionId))
                    {
                        regionsToProducts.Add(regionId, new HashSet <int>());
                    }

                    if (!regionsToProducts[regionId].Contains(item.Key))
                    {
                        regionsToProducts[regionId].Add(item.Key);
                    }
                }
            }

            var resultIds = productToRegions
                            .Where(m => !m.Value.Select(n => regionsToProducts[n].Any(p => p != m.Key))
                                   .Any(n => n))
                            .Select(m => m.Key).
                            ToArray();

            if (!resultIds.Any())
            {
                return(true);
            }

            var result = new ActionTaskResultMessage()
            {
                ResourceClass = ResourceClass,
                ResourceName  = nameof(RemoteValidationMessages.Products_Different_Regions),
                Parameters    = new object[] { string.Join(", ", resultIds) }
            };

            Result.AddModelError(GetPropertyName(productsName), ToString(result));

            return(false);
        }
示例#2
0
        public RemoteValidationResult Validate(RemoteValidationContext model, RemoteValidationResult result)
        {
            var helper = new ValidationHelper(model, result, _provider, _service);

            var productTypeName = _service.GetSetting(SettingsTitles.PRODUCT_TYPES_FIELD_NAME);



            using (new QPConnectionScope(helper.Customer.ConnectionString, (DatabaseType)helper.Customer.DatabaseType))
            {
                var articleSerivce = new ArticleService(helper.Customer.ConnectionString, 1);
                var emptyArticle   = articleSerivce.New(model.ContentId);

                var productsName           = helper.GetRelatedFieldName(emptyArticle, helper.GetSettingValue(SettingsTitles.PRODUCTS_CONTENT_ID));
                var marketingProductTypeId = helper.GetValue <int>(helper.GetClassifierFieldName(emptyArticle));
                var productIds             = helper.GetValue <ListOfInt>(productsName);

                if (productIds != null && AreTypesIncompatible(helper, articleSerivce, marketingProductTypeId, productIds, productTypeName))
                {
                    var message = new ActionTaskResultMessage()
                    {
                        ResourceClass = ValidationHelper.ResourceClass,
                        ResourceName  = nameof(RemoteValidationMessages.SameTypeMarketingProductProducts),
                    };
                    result.AddModelError(helper.GetPropertyName(productsName), helper.ToString(message));
                    return(result);
                }

                if (!GetUniqueAliasExclusions(helper).Contains(marketingProductTypeId))
                {
                    var ids = CheckAliasUniqueness(helper, marketingProductTypeId, articleSerivce, productTypeName);
                    if (!String.IsNullOrEmpty(ids))
                    {
                        var message = new ActionTaskResultMessage()
                        {
                            ResourceClass = ValidationHelper.ResourceClass,
                            ResourceName  = nameof(RemoteValidationMessages.MarketingProduct_Duplicate_Alias),
                            Parameters    = new object[] { ids }
                        };

                        result.AddModelError(
                            helper.GetPropertyName(Constants.FieldAlias), helper.ToString(message)
                            );
                    }
                }
            }

            return(result);
        }
示例#3
0
        public void CheckSiteId(int contentId)
        {
            var siteId = new ContentService(Customer.ConnectionString, 1).Read(contentId).SiteId;

            if (Model.SiteId != siteId)
            {
                var result = new ActionTaskResultMessage()
                {
                    ResourceClass = ResourceClass,
                    ResourceName  = nameof(RemoteValidationMessages.SiteIdInvalid),
                    Parameters    = new object[] { siteId, Model.SiteId }
                };
                throw new ValidationException(result);
            }
        }
示例#4
0
        public T GetValue <T>(string alias)
        {
            var def = GetDefinition(alias);

            if (def == null)
            {
                var result = new ActionTaskResultMessage()
                {
                    ResourceClass = ResourceClass,
                    ResourceName  = nameof(RemoteValidationMessages.DefinitionNotFound),
                    Parameters    = new object[] { alias }
                };
                throw new ValidationException(result);
            }
            return(Model.ProvideValueExact <T>(def));
        }
示例#5
0
        public string GetSettingStringValue(SettingsTitles key)
        {
            var valueStr = _settingsService.GetSetting(key);

            if (string.IsNullOrEmpty(valueStr))
            {
                var result = new ActionTaskResultMessage()
                {
                    ResourceClass = ResourceClass,
                    ResourceName  = nameof(RemoteValidationMessages.Settings_Missing),
                    Parameters    = new object[] { key }
                };
                throw new ValidationException(result);
            }
            return(valueStr);
        }
示例#6
0
        public RemotePropertyDefinition GetDefinition(string alias, bool addError = true)
        {
            var def = Model.Definitions.FirstOrDefault(x => x.Alias == alias);

            if (def == null && addError)
            {
                var result = new ActionTaskResultMessage()
                {
                    ResourceClass = ResourceClass,
                    ResourceName  = nameof(RemoteValidationMessages.MissingParam),
                    Parameters    = new object[] { alias }
                };
                Result.AddErrorMessage(
                    ToString(result));
            }
            return(def);
        }
示例#7
0
        public void CheckArchivedRelatedEntity(ArticleService articleService, IEnumerable <string> relIdsList, int productId, string idFieldName, int contentId)
        {
            var ids      = relIdsList.Where(n => !string.IsNullOrEmpty(n)).Select(int.Parse).Distinct().ToArray();
            var articles = articleService.List(contentId, ids);
            var relIds   = articles.Where(w => w.Archived).Select(s => s.Id).ToList();

            if (relIds.Any())
            {
                var result = new ActionTaskResultMessage()
                {
                    ResourceClass = ResourceClass,
                    ResourceName  = nameof(RemoteValidationMessages.RelatedEntityIsArchived),
                    Parameters    = new object[] { string.Join(",", relIds.Distinct()) }
                };

                Result.AddModelError(GetPropertyName(idFieldName), ToString(result));
            }
        }
示例#8
0
        public void CheckRelationProductsDuplicate(ArticleService articleService, string idFieldName, int contentProductsId, int[] relationsIds)
        {
            var servicesFieldName  = GetSettingStringValue(SettingsTitles.SERVICE_FIELD_NAME);
            var relatedProductsIds = articleService.List(contentProductsId, relationsIds, true).Select(x =>
                                                                                                       x.FieldValues.Single(a => a.Field.Name == servicesFieldName))
                                     .Select(s => int.Parse(s.Value)).ToArray();
            var duplicateServices = relatedProductsIds.Where(relId => relatedProductsIds.Count(r => r == relId) > 1).Distinct().ToArray();

            if (duplicateServices.Any())
            {
                var result = new ActionTaskResultMessage()
                {
                    ResourceClass = ResourceClass,
                    ResourceName  = nameof(RemoteValidationMessages.DuplicateRelationsProducts),
                    Parameters    = new object[] { string.Join(",", duplicateServices) }
                };

                Result.AddModelError(GetPropertyName(idFieldName), ToString(result));
            }
        }
示例#9
0
        public RemoteValidationResult Validate(RemoteValidationContext context, RemoteValidationResult result)
        {
            var filterDefinition = context.Definitions.FirstOrDefault(x => x.Alias == FieldFilter);

            if (filterDefinition == null)
            {
                var message = new ActionTaskResultMessage()
                {
                    ResourceClass = ValidationHelper.ResourceClass,
                    ResourceName  = nameof(RemoteValidationMessages.MissingParam),
                    Parameters    = new object[] { FieldFilter }
                };
                result.AddErrorMessage(ValidationHelper.ToString(context, message));
            }
            else
            {
                var filter = context.ProvideValueExact <string>(filterDefinition);
                if (string.IsNullOrEmpty(filter))
                {
                    return(result);
                }
                var normalizedFilter = DPathProcessor.NormalizeExpression(filter);
                if (!DPathProcessor.IsExpressionValid(normalizedFilter))
                {
                    var message = new ActionTaskResultMessage()
                    {
                        ResourceClass = ValidationHelper.ResourceClass,
                        ResourceName  = nameof(RemoteValidationMessages.InvalidFilter),
                        Parameters    = new object[] { normalizedFilter }
                    };
                    result.AddModelError(filterDefinition.PropertyName, ValidationHelper.ToString(context, message));
                }
            }


            return(result);
        }
示例#10
0
        public void IsProductsRegionsWithModifierIntersectionsExist(ArticleService articleService, int productId, int[] regionsIds, int[] productsIds,
                                                                    string regionsName, string modifiersName, int dataOptionId)
        {
            int contentId    = GetSettingValue(SettingsTitles.PRODUCTS_CONTENT_ID);
            var productsList = articleService.List(contentId, productsIds, true).Where(w => !w.Archived).ToArray();

            Lookup <int, int[]> productToRegions = (Lookup <int, int[]>)productsList
                                                   .ToLookup(x => x.Id, x => x.FieldValues.Single(a => a.Field.Name == regionsName).RelatedItems.ToArray());
            Lookup <int, int[]> modifiersToProducts = (Lookup <int, int[]>)productsList
                                                      .ToLookup(x => x.Id, x => x.FieldValues.Single(a => a.Field.Name == modifiersName).RelatedItems.ToArray());
            var resultIds = new List <int>();

            foreach (var item in productToRegions)
            {
                if (item.Key != productId)
                {
                    if (!modifiersToProducts[item.Key].Any() || !modifiersToProducts[item.Key].Contains(new[] { dataOptionId }))
                    {
                        if (regionsIds.Intersect(item.SelectMany(s => s)).Any())
                        {
                            resultIds.Add(item.Key);
                        }
                    }
                }
            }
            if (resultIds.Any())
            {
                var message = new ActionTaskResultMessage()
                {
                    ResourceClass = ResourceClass,
                    ResourceName  = nameof(RemoteValidationMessages.ProductsRepeatingRegions),
                    Parameters    = new object[] { String.Join(", ", resultIds) }
                };

                Result.AddModelError(GetPropertyName(regionsName), ToString(message));
            }
        }
示例#11
0
        public void CheckTariffAreaDuplicateExist(IEnumerable <Article> parameters, string parametersFieldName, bool isMatrix = false)
        {
            var resultIds        = new List <int>();
            var names            = new HashSet <string>(GetListOfParametersNames());
            var tariffDirections = parameters.ToDictionary(
                k => k.Id,
                s => string.Join(",", GetParameterTariffDirectionIds(s, names))
                );

            var checkedDirections = new Dictionary <string, int>();

            foreach (var tariffDirection in tariffDirections)
            {
                if (!checkedDirections.ContainsKey(tariffDirection.Value))
                {
                    checkedDirections.Add(tariffDirection.Value, tariffDirection.Key);
                }
                else
                {
                    resultIds.Add(tariffDirection.Key);
                    resultIds.Add(checkedDirections[tariffDirection.Value]);
                }
            }

            if (resultIds.Any())
            {
                var result = new ActionTaskResultMessage()
                {
                    ResourceClass = ResourceClass,
                    ResourceName  = isMatrix ? nameof(RemoteValidationMessages.DuplicateTariffsAreasMatrix) : nameof(RemoteValidationMessages.DuplicateTariffsAreas),
                    Parameters    = new object[] { string.Join(", ", resultIds.Distinct()) }
                };

                Result.AddModelError(GetPropertyName(parametersFieldName), ToString(result));
            }
        }
示例#12
0
 public ValidationException(ActionTaskResultMessage message, Exception innerException)
     : base(message.ResourceName, innerException)
 {
     ResultMessage = message;
 }
示例#13
0
 public ValidationException(ActionTaskResultMessage message)
     : base(message.ResourceName)
 {
     ResultMessage = message;
 }
示例#14
0
        public RemoteValidationResult Validate(RemoteValidationContext model, RemoteValidationResult result)
        {
            var helper = new ValidationHelper(model, result, _provider, _service);

            int productTypesContentId = helper.GetSettingValue(SettingsTitles.PRODUCT_TYPES_CONTENT_ID);
            var marketingContentId    = helper.GetSettingValue(SettingsTitles.MARKETING_PRODUCT_CONTENT_ID);
            var parametersContentId   = helper.GetSettingValue(SettingsTitles.PRODUCTS_PARAMETERS_CONTENT_ID);
            var regionsContentId      = helper.GetSettingValue(SettingsTitles.REGIONS_CONTENT_ID);

            var contentId = model.ContentId;
            int productId = helper.GetValue <int>(Constants.FieldId);

            using (new QPConnectionScope(helper.Customer.ConnectionString, (DatabaseType)helper.Customer.DatabaseType))
            {
                var articleService = new ArticleService(helper.Customer.ConnectionString, 1);

                var product         = productId > 0 ? articleService.Read(productId) : articleService.New(contentId);
                var markProductName = helper.GetRelatedFieldName(product, marketingContentId);
                var markProductId   = helper.GetValue <int>(markProductName);
                var markProduct     = articleService.Read(markProductId);
                var productsName    = helper.GetRelatedFieldName(markProduct, contentId);

                var productTypeName = helper.GetClassifierFieldName(product);
                int typeId          = helper.GetValue <int>(productTypeName);

                var regionsName = helper.GetRelatedFieldName(product, regionsContentId);

                var parametersName = helper.GetRelatedFieldName(product, parametersContentId);

                int[] regionsIds    = helper.GetValue <ListOfInt>(regionsName).ToArray();
                int[] parametersIds = helper.GetValue <ListOfInt>(parametersName)?.ToArray();


                helper.CheckSiteId(productTypesContentId);

                //Проверка того, что продукт не имеет общих регионов с другими региональными продуктами этого МП
                var productsIds = markProduct
                                  .FieldValues.Where(a => a.Field.Name == productsName)
                                  .SelectMany(a => a.RelatedItems)
                                  .ToArray();

                helper.IsProductsRegionsWithModifierIntersectionsExist(articleService, productId, regionsIds,
                                                                       productsIds,
                                                                       regionsName, Constants.FieldProductModifiers, 0);


                if (productId > 0)
                {
                    //Проверка того, что тарифное направление встречается только один раз в продукте
                    var contentProductsParametersId =
                        helper.GetSettingValue(SettingsTitles.PRODUCTS_PARAMETERS_CONTENT_ID);
                    if (parametersIds != null && parametersIds.Any())
                    {
                        var parameters = helper.GetParameters(articleService, contentProductsParametersId,
                                                              parametersIds, "c.BaseParameter is not null");
                        helper.CheckTariffAreaDuplicateExist(parameters, parametersName);
                    }

                    int    contentServiceOnTariffId = 0;
                    string tariffRelationFieldName  = null;
                    bool   hasServicesOnTariff      = true;

                    try
                    {
                        contentServiceOnTariffId = helper.GetSettingValue(SettingsTitles.SERVICES_ON_TARIFF_CONTENT_ID);
                        tariffRelationFieldName  =
                            helper.GetSettingStringValue(SettingsTitles.TARIFF_RELATION_FIELD_NAME);
                    }
                    catch (ValidationException)
                    {
                        hasServicesOnTariff = false;
                    }

                    if (hasServicesOnTariff)
                    {
                        //Получение id поля Tariffs
                        var fieldService = new FieldService(helper.Customer.ConnectionString, 1);
                        var fieldId      = fieldService.List(contentServiceOnTariffId)
                                           .Where(w => w.Name.Equals(tariffRelationFieldName)).Select(s => s.Id).FirstOrDefault();
                        //Получение Id услуг из контента "Услуги на тарифах"
                        var relationsIds = articleService.GetRelatedItems(fieldId, productId, true)?
                                           .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                           .Select(int.Parse)
                                           .ToArray();
                        if (relationsIds != null && relationsIds.Any())
                        {
                            //Проверка того, что тарифное направление встречается только один раз в связи продуктов
                            helper.CheckRelationServicesProductsTariff(articleService, contentServiceOnTariffId,
                                                                       tariffRelationFieldName, relationsIds, parametersName);

                            //Проверка того, что связь между продуктами встречается единожды
                            helper.CheckRelationProductsDuplicate(articleService, Constants.FieldId,
                                                                  contentServiceOnTariffId, relationsIds);
                        }

                        var relatedIds = new List <string>();

                        //Проверка того, что сущность с другой стороны связи не в архиве
                        var productRelationsContentId = helper.GetSettingValue(SettingsTitles.PRODUCT_RELATIONS_CONTENT_ID);
                        var contentService            = new ContentService(helper.Customer.ConnectionString, 1);

                        //Получение связанных контентов
                        var contents = contentService.Read(productRelationsContentId)
                                       .AggregatedContents
                                       .Where(w => w.Fields
                                              .Count(a => a.ExactType == FieldExactTypes.O2MRelation &&
                                                     a.RelateToContentId == product.ContentId) >= 2).ToArray();
                        foreach (var con in contents)
                        {
                            //Получение полей, по которым может быть связь
                            var productField = con.Fields
                                               .Where(w => w.ExactType == FieldExactTypes.O2MRelation &&
                                                      w.RelateToContentId == product.ContentId
                                                      ).ToArray();
                            foreach (var field in productField)
                            {
                                //Получение ids связанных статей
                                var relatedArticlesId = articleService.GetRelatedItems(field.Id, productId, true)?
                                                        .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                                        .Select(int.Parse)
                                                        .ToArray();

                                if (relatedArticlesId != null && relatedArticlesId.Any())
                                {
                                    var relatedArticles = articleService.List(con.Id, relatedArticlesId, true)
                                                          .Where(w => !w.Archived).Select(s => s).ToList();
                                    var relField = productField.Where(f => f.Name != field.Name).Select(s => s).First();
                                    var rel      = relatedArticles.Select(s =>
                                                                          s.FieldValues.First(f => f.Field.Name == relField.Name).Value).ToArray();
                                    if (rel.Any())
                                    {
                                        relatedIds.AddRange(rel);
                                    }
                                }
                            }
                        }

                        helper.CheckArchivedRelatedEntity(articleService, relatedIds, productId, Constants.FieldId,
                                                          helper.GetSettingValue(SettingsTitles.PRODUCTS_CONTENT_ID));
                    }
                }

                string markProductType =
                    articleService.Read(markProductId)
                    .FieldValues.FirstOrDefault(a => a.Field.Name == productTypeName)?
                    .Value;

                //Проверка, что тип маркетингового продукта и тип продукта -- сопоставимы
                if (!articleService.List(productTypesContentId, null, true).Any(x =>
                                                                                x.FieldValues.FirstOrDefault(a => a.Field.Name == Constants.FieldProductContent)?.Value ==
                                                                                typeId.ToString() &&
                                                                                x.FieldValues.FirstOrDefault(a => a.Field.Name == Constants.FieldMarkProductContent)?.Value ==
                                                                                markProductType))
                {
                    var message = new ActionTaskResultMessage()
                    {
                        ResourceClass = ValidationHelper.ResourceClass,
                        ResourceName  = nameof(RemoteValidationMessages.SameTypeProductMarketingProduct)
                    };

                    result.AddModelError(
                        helper.GetPropertyName(markProductName), helper.ToString(message)
                        );
                }
            }

            return(result);
        }
示例#15
0
        public override ActionTaskResult Process(ActionContext context)
        {
            int bundleSize             = GetBundleSize();
            int maxDegreeOfParallelism = GetMaxDegreeOfParallelism();

            string[] channels = context.Parameters.GetChannels();
            bool     localize = context.Parameters.GetLocalize();

            int    marketingProductContentId = int.Parse(_settingsService.GetSetting(SettingsTitles.MARKETING_PRODUCT_CONTENT_ID));
            string productsFieldName         = _settingsService.GetSetting(SettingsTitles.MARKETING_PRODUCT_PRODUCTS_FIELD_NAME);

            Dictionary <int, int[]> articleIdsToCheckRelationsByContentId;

            int[] productIds;

            if (context.ContentItemIds == null || context.ContentItemIds.Length == 0)
            {
                productIds = DoWithLogging(
                    () => Helpers.GetAllProductIds(int.Parse(context.Parameters["site_id"]), context.ContentId, _provider.GetCustomer()),
                    "Getting all products from content {contentId}", context.ContentId
                    );

                articleIdsToCheckRelationsByContentId = new Dictionary <int, int[]>
                {
                    { context.ContentId, productIds }
                };
            }
            else
            {
                productIds = DoWithLogging(
                    () => Helpers.ExtractRegionalProductIdsFromMarketing(context.ContentItemIds, _articleService, marketingProductContentId, productsFieldName),
                    "Getting regional product ids from marketing products content {contentId} using  field {fieldName} and ids {ids}",
                    marketingProductContentId, productsFieldName, context.ContentItemIds
                    );

                articleIdsToCheckRelationsByContentId = Helpers.GetContentIds(productIds, _provider.GetCustomer());
            }

            if (productIds.Length == 0)
            {
                return(ActionTaskResult.Error(new ActionTaskResultMessage()
                {
                    ResourceClass = nameof(SendProductActionStrings),
                    ResourceName = nameof(SendProductActionStrings.NotFound),
                    Extra = string.Join(", ", context.ContentItemIds)
                }, context.ContentItemIds));
            }

            foreach (var articleIdsWithContentId in articleIdsToCheckRelationsByContentId)
            {
                var checkResult =
                    DoWithLogging(
                        () => _articleService.CheckRelationSecurity(articleIdsWithContentId.Key, articleIdsWithContentId.Value, false),
                        "Checking relation security in content {contentId} for articles {ids}",
                        articleIdsWithContentId.Key, articleIdsWithContentId.Value
                        );

                string idsstr = string.Join(", ", checkResult.Where(n => !n.Value));

                if (!string.IsNullOrEmpty(idsstr))
                {
                    return(ActionTaskResult.Error(new ActionTaskResultMessage()
                    {
                        ResourceClass = nameof(SendProductActionStrings),
                        ResourceName = nameof(SendProductActionStrings.NoRelationAccess),
                        Extra = idsstr
                    }, context.ContentItemIds));
                }
            }

            const string skipPublishingKey = "skipPublishing";

            bool skipPublishing = context.Parameters.ContainsKey(skipPublishingKey) && bool.Parse(context.Parameters[skipPublishingKey]);

            const string skipLiveKey = "skipLive";

            bool skipLive = context.Parameters.ContainsKey(skipLiveKey) && bool.Parse(context.Parameters[skipLiveKey]);

            const string ignoredStatusKey = "IgnoredStatus";

            string ignoredStatus = (context.Parameters.ContainsKey(ignoredStatusKey)) ? context.Parameters[ignoredStatusKey] : null;


            float currentPercent = 0;

            object percentLocker = new object();



            var parts = productIds.Section(bundleSize).ToArray();

            var filteredInStage            = new ConcurrentBag <int>();
            var filteredInLive             = new ConcurrentBag <int>();
            var failed                     = new ConcurrentDictionary <int, object>();
            var missing                    = new ConcurrentBag <int>();
            var excluded                   = new ConcurrentBag <int>();
            var frozen                     = new ConcurrentBag <int>();
            var invisibleOrArchivedIds     = new ConcurrentBag <int>();
            var errors                     = new ConcurrentBag <Exception>();
            var validationErrors           = new ConcurrentDictionary <int, ActionTaskResult>();
            var validationErrorsSerialized = new ConcurrentDictionary <int, string>();

            Parallel.ForEach(parts, new ParallelOptions {
                MaxDegreeOfParallelism = maxDegreeOfParallelism
            },
                             () =>
            {
                HttpContextUserProvider.ForcedUserId = context.UserId;
                return(new Local
                {
                    ProductService = ObjectFactoryBase.Resolve <IProductService>(),
                    QpNotificationService = ObjectFactoryBase.Resolve <IQPNotificationService>(),
                    XmlProductService = ObjectFactoryBase.Resolve <IXmlProductService>()
                });
            },
                             (idsToProcess, ps, tl) =>
            {
                try
                {
                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;

                        return(tl);
                    }

                    var localInvisibleOrArchivedIds = new HashSet <int>();


                    Article[] prodsStage = DoWithLogging(
                        () => tl.ProductService.GetProductsByIds(idsToProcess.ToArray()),
                        "Getting products {ids}", idsToProcess.ToArray()
                        );
                    IEnumerable <string> ignoredStatuses = ignoredStatus?.Split(',') ??
                                                           Enumerable.Empty <string>().ToArray();
                    var excludedStage = prodsStage.Where(n => ignoredStatuses.Contains(n.Status)).ToArray();

                    foreach (var item in excludedStage)
                    {
                        excluded.Add(item.Id);
                    }

                    prodsStage = prodsStage.Except(excludedStage).ToArray();

                    var frozenIds = new int[0];

                    if (!skipLive)
                    {
                        var idsToCheck = prodsStage.Select(p => p.Id).ToArray();
                        frozenIds      = DoWithLogging(
                            () => _freezeService.GetFrozenProductIds(idsToCheck),
                            "Getting freezing state for products {ids}", idsToCheck
                            );
                    }

                    prodsStage = prodsStage.Where(p => !frozenIds.Contains(p.Id)).ToArray();

                    foreach (int id in frozenIds)
                    {
                        frozen.Add(id);
                    }

                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;

                        return(tl);
                    }

                    //Валидация продуктов
                    foreach (int id in prodsStage.Where(w => !w.Archived && w.Visible).Select(s => s.Id))
                    {
                        var xamlValidationErrors = DoWithLogging(
                            () => _articleService.XamlValidationById(id, true),
                            "Validating XAML for product {id}", id
                            );
                        var validationResult = ActionTaskResult.FromRulesException(xamlValidationErrors, id);

                        if (!validationResult.IsSuccess)
                        {
                            validationErrors.TryAdd(id, validationResult);
                            validationErrorsSerialized.TryAdd(id, validationResult.ToString());
                        }
                    }
                    prodsStage = prodsStage.Where(w => !validationErrors.Keys.Contains(w.Id)).ToArray();

                    var prodsLive = new Article[] { };

                    if (!skipLive)
                    {
                        if (!skipPublishing)
                        {
                            prodsLive = prodsStage;
                        }
                        else
                        {
                            prodsLive = DoWithLogging(
                                () => tl.ProductService.GetProductsByIds(idsToProcess.ToArray(), true),
                                "Getting separate live products {ids}", idsToProcess.ToArray()
                                );
                        }
                    }


                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;

                        return(tl);
                    }

                    lock (percentLocker)
                    {
                        currentPercent += (float)50 / parts.Length;
                    }

                    TaskContext.SetProgress((byte)currentPercent);

                    // архивные или невидимые продукты следует удалить с витрин
                    foreach (var product in prodsLive.Where(product => product.Archived || !product.Visible))
                    {
                        localInvisibleOrArchivedIds.Add(product.Id);
                    }

                    if (!skipLive)
                    {
                        foreach (var item in idsToProcess.Except(prodsLive.Select(y => y.Id)))
                        {
                            missing.Add(item);
                        }
                    }

                    //неопубликованные или расщепленные публикуем сразу
                    int[] prodsToPublishIds = null;

                    if (!skipPublishing)
                    {
                        prodsToPublishIds = prodsLive
                                            .Where(x =>
                                                   !x.Archived &&
                                                   x.Visible &&
                                                   (
                                                       !x.IsPublished ||
                                                       PublishAction.GetAllArticlesToCheck(x).Any(p => !p.IsPublished) ||
                                                       _freezeService.GetFreezeState(x.Id) == FreezeState.Unfrosen
                                                   )
                                                   )
                                            .Select(x => x.Id)
                                            .ToArray();

                        if (TaskContext.IsCancellationRequested)
                        {
                            TaskContext.IsCancelled = true;

                            return(tl);
                        }

                        // удалим требующие публикации или удаления продукты
                        prodsLive = prodsLive
                                    .Where(p => !prodsToPublishIds.Contains(p.Id) && !localInvisibleOrArchivedIds.Contains(p.Id))
                                    .ToArray();
                    }


                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;

                        return(tl);
                    }

                    lock (percentLocker)
                    {
                        currentPercent += (float)30 / parts.Length;
                    }

                    TaskContext.SetProgress((byte)currentPercent);

                    foreach (var id in localInvisibleOrArchivedIds)
                    {
                        invisibleOrArchivedIds.Add(id);
                    }

                    int sectionSize = Math.Min(bundleSize, 5);

                    var tasks =
                        ArticleFilter.LiveFilter.Filter(prodsLive)
                        .Section(sectionSize)
                        .Select(z => tl.QpNotificationService
                                .SendProductsAsync(z.ToArray(), false, context.UserName, context.UserId,
                                                   localize, false, channels)
                                .ContinueWith(y => UpdateFilteredIds(filteredInLive,
                                                                     y.IsFaulted ? null : y.Result, z, y.Exception, errors, failed)))
                        .Concat(ArticleFilter.DefaultFilter.Filter(prodsStage)
                                .Section(sectionSize)
                                .Select(z => tl.QpNotificationService.SendProductsAsync(z.ToArray(), true,
                                                                                        context.UserName, context.UserId, localize, false, channels)
                                        .ContinueWith(y => UpdateFilteredIds(filteredInStage,
                                                                             y.IsFaulted ? null : y.Result, z, y.Exception, errors, failed))))
                        .ToArray();



                    if (tasks.Length > 0)
                    {
                        float percentsPerTask = (float)10 / parts.Length / tasks.Length;

                        tasks = tasks
                                .Select(x => x.ContinueWith(y =>
                        {
                            lock (percentLocker)
                            {
                                currentPercent += percentsPerTask;
                            }
                            TaskContext.SetProgress((byte)currentPercent);
                        }))
                                .ToArray();

                        DoWithLogging(() => Task.WaitAll(tasks),
                                      "Sending notifications for live ({liveIds}) and stage ({stageIds}) products",
                                      ArticleFilter.LiveFilter.Filter(prodsLive).Select(n => n.Id).ToArray(),
                                      ArticleFilter.DefaultFilter.Filter(prodsStage).Select(n => n.Id).ToArray()
                                      );
                    }
                    else
                    {
                        lock (percentLocker)
                        {
                            currentPercent += (float)10 / parts.Length;
                        }
                        TaskContext.SetProgress((byte)currentPercent);
                    }

                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;

                        return(tl);
                    }

                    // эти продукты имеют неопубликованные или расщепленные статьи
                    if (!skipPublishing && prodsToPublishIds.Length > 0)
                    {
                        var publishAction = ObjectFactoryBase.Resolve <PublishAction>();

                        var publishActionContext = new ActionContext
                        {
                            ContentItemIds = prodsToPublishIds,
                            Parameters     = new Dictionary <string, string>()
                            {
                                { ignoredStatusKey, ignoredStatus }
                            },
                            UserId   = context.UserId,
                            UserName = context.UserName
                        };

                        try
                        {
                            DoWithLogging(
                                () => publishAction.Process(publishActionContext),
                                "Calling PublishAction for products {ids}",
                                prodsToPublishIds
                                );
                        }
                        catch (ActionException ex)
                        {
                            var ids = ex.InnerExceptions.OfType <ProductException>().Select(x => x.ProductId);
                            Logger.Error()
                            .Exception(ex)
                            .Message("Exception has been thrown while publishing products {ids}", prodsToPublishIds)
                            .Write();

                            foreach (var pID in ids)
                            {
                                failed.TryAdd(pID, null);
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Error()
                            .Exception(ex)
                            .Message("Exception has been thrown while publishing products {ids}", prodsToPublishIds)
                            .Write();
                        }
                    }

                    lock (percentLocker)
                    {
                        currentPercent += (float)10 / parts.Length;
                    }

                    TaskContext.SetProgress((byte)currentPercent);

                    return(tl);
                }
                catch (Exception ex)
                {
                    Logger.Error().Message("SendProductAction exception").Exception(ex).Write();

                    foreach (var item in idsToProcess)
                    {
                        failed.TryAdd(item, null);
                    }

                    errors.Add(ex);
                }

                HttpContextUserProvider.ForcedUserId = 0;
                return(tl);
            }, tt => { });

            if (TaskContext.IsCancellationRequested)
            {
                TaskContext.IsCancelled = true;

                return(ActionTaskResult.Error(new ActionTaskResultMessage()
                {
                    ResourceClass = nameof(SendProductActionStrings),
                    ResourceName = nameof(SendProductActionStrings.Cancelled)
                }, context.ContentItemIds));
            }

            var productsToRemove      = new int[0];
            var productsToRemoveCheck = missing
                                        .Concat(invisibleOrArchivedIds)
                                        .Except(excluded)
                                        .Except(frozen)
                                        .Except(validationErrors.Keys)
                                        .ToArray();

            if (productsToRemoveCheck.Length > 0)
            {
                // проверяем, какие из проблемных продуктов присутствуют на витрине
                var cmService = ObjectFactoryBase.Resolve <IList <IConsumerMonitoringService> >();

                productsToRemove = DoWithLogging(
                    () => cmService.SelectMany(s => s.FindExistingProducts(productsToRemoveCheck)).Distinct().ToArray(),
                    "Checking whether products {ids} are missing on fronts", productsToRemoveCheck
                    );

                if (productsToRemove.Length > 0)
                {
                    // эти продукты отсутствуют в DPC или не видны, но остались на витрине
                    // их надо удалить с витрин
                    var service        = ObjectFactoryBase.Resolve <IQPNotificationService>();
                    var productService = ObjectFactoryBase.Resolve <IProductService>();
                    DoWithLogging(
                        () => Task.WhenAll(productsToRemove.Section(20).Select(
                                               s => service.DeleteProductsAsync(
                                                   productService.GetSimpleProductsByIds(s.ToArray()),
                                                   context.UserName,
                                                   context.UserId,
                                                   false)
                                               )
                                           ).Wait(),
                        "Removing missing products from fronts {ids}", productsToRemove
                        );
                }
            }

            DoWithLogging(
                () => _validationService.UpdateValidationInfo(productIds, validationErrorsSerialized),
                "Updating validation info for products {ids}", productIds
                );

            int[] notFound = missing.Except(productsToRemove).Except(excluded).Except(frozen).Except(validationErrors.Keys).ToArray();

            var notSucceeded = failed.Keys.Concat(notFound).Concat(excluded).Concat(frozen)
                               .Concat(validationErrors.Keys).ToArray();

            var result = new ActionTaskResult()
            {
                FailedIds = notSucceeded
            };

            var msg = new ActionTaskResultMessage()
            {
                ResourceClass = nameof(SendProductActionStrings)
            };

            if (notSucceeded.Any())
            {
                msg.ResourceName = nameof(SendProductActionStrings.PartiallySucceededResult);
                msg.Extra        = string.Join(", ", notSucceeded);
                msg.Parameters   = new object[] { productIds.Length - notSucceeded.Length, productIds.Length };
            }

            else
            {
                msg.ResourceName = nameof(SendProductActionStrings.SucceededResult);
                msg.Parameters   = new object[] { productIds.Length };
            }

            result.Messages.Add(msg);

            if (errors.Any())
            {
                result.Messages.Add(new ActionTaskResultMessage()
                {
                    ResourceClass = nameof(SendProductActionStrings),
                    ResourceName  = nameof(SendProductActionStrings.Errors),
                    Extra         = string.Join(", ", errors.Select(x => x.Message).Distinct())
                });
            }

            AddMessages(result, nameof(SendProductActionStrings.ExcludedByStatus), excluded.ToArray());
            AddMessages(result, nameof(SendProductActionStrings.ExcludedWithFreezing), frozen.ToArray());
            AddMessages(result, nameof(SendProductActionStrings.NotFoundInDpc), notFound.ToArray());
            AddMessages(result, nameof(SendProductActionStrings.RemovedFromFronts), productsToRemove.ToArray());
            AddMessages(result, nameof(SendProductActionStrings.NotPassedByStageFiltration), filteredInStage.ToArray());
            AddMessages(result, nameof(SendProductActionStrings.NotPassedByLiveFiltration), filteredInLive.ToArray());

            if (validationErrors.Any())
            {
                result.Messages.AddRange(validationErrors.SelectMany(v => v.Value.Messages));
            }

            TaskContext.Result = result;

            return(result);
        }
        public RemoteValidationResult Validate(RemoteValidationContext context, RemoteValidationResult result)
        {
            var xmlDefinition = context.Definitions.FirstOrDefault(x => x.Alias == FieldXmlDefinition);

            if (xmlDefinition == null)
            {
                var message = new ActionTaskResultMessage()
                {
                    ResourceClass = ValidationHelper.ResourceClass,
                    ResourceName  = nameof(RemoteValidationMessages.FieldNotFound),
                    Parameters    = new object[] { FieldXmlDefinition }
                };
                result.Messages.Add(ValidationHelper.ToString(context, message));
            }

            var xaml = context.ProvideValueExact <string>(xmlDefinition);

            if (!string.IsNullOrWhiteSpace(xaml))
            {
                Content definition;
                try
                {
                    definition = (Content)XamlConfigurationParser.CreateFrom(xaml);
                }
                catch (Exception ex)
                {
                    var message = new ActionTaskResultMessage()
                    {
                        ResourceClass = ValidationHelper.ResourceClass,
                        ResourceName  = nameof(RemoteValidationMessages.NotValidXamlDefinition),
                        Parameters    = new object[] { ex.Message }
                    };
                    result.Messages.Add(ValidationHelper.ToString(context, message));
                    return(result);
                }

                var jsonDefinition = context.Definitions.FirstOrDefault(x => x.Alias == FieldJsonDefinition);
                if (jsonDefinition != null)
                {
                    using (var stream = new MemoryStream())
                    {
                        using (var reader = new StreamReader(stream))
                        {
                            try
                            {
                                _formatter.Write(stream, definition);
                                stream.Position = 0;
                                context.SetValue(result, jsonDefinition, reader.ReadToEnd());
                            }
                            catch (Exception ex)
                            {
                                var message = new ActionTaskResultMessage()
                                {
                                    ResourceClass = ValidationHelper.ResourceClass,
                                    ResourceName  = nameof(RemoteValidationMessages.JsonDefinitionError),
                                    Parameters    = new object[] { ex.Message }
                                };
                                result.Messages.Add(ValidationHelper.ToString(context, message));
                                return(result);
                            }
                        }
                    }
                }
            }

            return(result);
        }
示例#17
0
 public static string ToString(RemoteValidationContext model, ActionTaskResultMessage atrm)
 {
     return(model.LocalizeMessages ? atrm.ToString(new CultureInfo(model.CurrentUICulture)) : JsonConvert.SerializeObject(atrm));
 }
示例#18
0
 public string ToString(ActionTaskResultMessage atrm)
 {
     return(ToString(Model, atrm));
 }