diff --git a/PARR.Core/Services/RobotTask/Implementations/RobotTaskService.cs b/PARR.Core/Services/RobotTask/Implementations/RobotTaskService.cs index d058a5c3..0cb55db5 100644 --- a/PARR.Core/Services/RobotTask/Implementations/RobotTaskService.cs +++ b/PARR.Core/Services/RobotTask/Implementations/RobotTaskService.cs @@ -335,38 +335,64 @@ namespace PARR.Core.Services.RobotTask.Implementations && t.LastRobotStatusUpdated < endDate) ).ToList(); + // Проверим StatusTypeId у старых шаблонов в процессе переименования + // 1. Находим задачи переименования, у которых StatusTypeId шаблона != Used + var invalidRenameTasks = allowedTasks + .Where(t => t.Template != null && t.Template.StatusTypeId != TemplateStatusTypeEnum.Used) + .ToList(); + + // 2. Создаем словарь для быстрого поиска и логирования: OldName -> StatusTypeId + var invalidOldNamesWithStatus = invalidRenameTasks + .Where(t => templateIdToOldName.ContainsKey(t.TemplateId)) + .Select(t => new { OldName = templateIdToOldName[t.TemplateId], StatusTypeId = t.Template!.StatusTypeId }) + .ToDictionary(x => x.OldName, x => x.StatusTypeId); + + // 3. Оставляем для подмены только те задачи, у которых StatusTypeId == 0 + var validAllowedTasks = allowedTasks + .Where(t => t.Template != null && t.Template.StatusTypeId == TemplateStatusTypeEnum.Used) + .ToList(); + // Формируем список заданий - var originalCount = tasks.Count; // Запоминаем сколько было изначально - + var originalCount = tasks.Count; var errorTaskIdsSet = tasksToSetErrorStatus.ToHashSet(); - - // Из исходных тасков удалить те которым установлен статус ошибки - var filteredOriginalTasks = tasks.Where(t => !errorTaskIdsSet.Contains(t.TaskId)).ToList(); var errorCount = errorTaskIdsSet.Count; - // Создаем словарь, где КЛЮЧОМ является OldName (который совпадает с task.TemplateName), - // а не текущее имя шаблона (которое уже новое). - var renameTasksToDictionary = allowedTasks - .Where(t => templateIdToOldName.ContainsKey(t.TemplateId)) - .GroupBy(t => templateIdToOldName[t.TemplateId]) // Группируем по OldName! - .ToDictionary( - g => g.Key, // Ключ = OldName (например, "СтароеИмя") - g => new RobotTaskDetails(g.First().Id, g.First().Template!.Name, g.First().Template!.NextRun) - ); + // Создаем словарь подмены ТОЛЬКО из валидных задач (где StatusTypeId == Used) + var renameTasksToDictionary = validAllowedTasks + .Where(t => templateIdToOldName.ContainsKey(t.TemplateId)) + .GroupBy(t => templateIdToOldName[t.TemplateId]) + .ToDictionary( + g => g.Key, + g => new RobotTaskDetails(g.First().Id, g.First().Template!.Name, g.First().Template!.NextRun) + ); - // Проходим по ИСХОДНОМУ списку, чтобы сохранить порядок сортировки и корректно подменить задачи + // Проходим по ИСХОДНОМУ списку, чтобы сохранить порядок сортировки var finalTasks = new List(tasks.Count); int replacedCount = 0; + int excludedByStatusCount = 0; // Счетчик для логов foreach (var task in tasks) { - // Если задаче нужно поставить ошибку, просто пропускаем ее (она не попадет в итоговый список) + // 1. Если задаче нужно поставить ошибку, пропускаем ее if (errorTaskIdsSet.Contains(task.TaskId)) { continue; } - // ключ в словаре - это OldName, который равен task.TemplateName + // 2. Если этот шаблон связан с переименованием, но у старого шаблона StatusTypeId != Used + if (invalidOldNamesWithStatus.TryGetValue(task.TemplateName, out var badStatusId)) + { + _logger.LogWarning( + "Задача для шаблона '{TemplateName}' (TaskId: {TaskId}) ИСКЛЮЧЕНА из выдачи. " + + "Связанный шаблон в процессе переименования имеет недопустимый StatusTypeId = {StatusTypeId} (ожидалось Used). " + + "Исходная задача также не выполняется.", + task.TemplateName, task.TaskId, badStatusId); + + excludedByStatusCount++; + continue; // Не добавляем ни старую, ни новую задачу в итоговый список + } + + // 3. Если для этого имени шаблона есть разрешенная задача на переименование (и она валидна) - вставляем ее if (renameTasksToDictionary.TryGetValue(task.TemplateName, out var renameTask)) { finalTasks.Add(renameTask); @@ -382,10 +408,11 @@ namespace PARR.Core.Services.RobotTask.Implementations // Логируем итоговую статистику трансформации пула задач _logger.LogInformation( "Трансформация пула задач завершена. Исходных: {OriginalCount} шт. " + - "Отклонено (ошибка): {ErrorCount} шт. Заменено на старые: {ReplacedCount} шт. " + - "Итого к выдаче: {FinalCount} шт.", - originalCount, errorCount, replacedCount, finalTasks.Count); + "Отклонено (ошибка): {ErrorCount} шт. Исключено (невалидный StatusTypeId): {ExcludedCount} шт. " + + "Заменено на старые: {ReplacedCount} шт. Итого к выдаче: {FinalCount} шт.", + originalCount, errorCount, excludedByStatusCount, replacedCount, finalTasks.Count); + // Возвращаем без дополнительной сортировки по NextRun. Порядок сохранен начального списка return finalTasks; } @@ -429,7 +456,7 @@ namespace PARR.Core.Services.RobotTask.Implementations await _robotHistoryRepository.CreateAsync(history); _logger.LogInformation("Для целевого задания {TaskId} (шаблон '{TemplateName}') установлен статус ошибки, " + - "так как связанное задание со старым шаблоном не было успешно выполнено.", + "так как связанное задание со старым шаблоном не было успешно выполнено.", task.Id, task.Template!.Name); }