diff --git a/PARR.Master/Services/OrderMasterService.cs b/PARR.Master/Services/OrderMasterService.cs index 81909d7a..8b6b3259 100644 --- a/PARR.Master/Services/OrderMasterService.cs +++ b/PARR.Master/Services/OrderMasterService.cs @@ -87,20 +87,73 @@ namespace PARR.Master.Services /// private async Task SetHistoryAndUpdateOrderStatus(Order order) { - var agentHistory = await agentHistoryService.Get() - .Where(t => - t.TemplateId == order.TemplateId - && t.DateCreated > order.GenerateDate!.Value.Add(-orderManageSettings.FindAgentHistoryStartOffset) - //&& t.DateCreated <= order.GenerateDate!.Value.AddSeconds(order.Template!.ApplicationsInWork!.AgentTimeOutSec!.Value) - && t.DateCreated <= order.GenerateDate!.Value.Add(order.Template!.ApplicationsInWork!.TemplateDurationTimeSpan!.Value) - && t.OrderId == null - ) - .OrderBy(t => t.DateCreated) - .ToListAsync(); + // получаем историю агента, которая не присовена этому наряду + var newAgentHistory = await GetNewAgentHistoryByOrderAsync(order); - logger.LogInformation($"Для наряда {order.Id}, {order.Number} найдено новых историй агентов: {agentHistory.Count()} шт."); + logger.LogInformation($"Для наряда {order.Id}, {order.Number} найдено новых историй агентов: {newAgentHistory.Count()} шт."); - foreach (var historyItem in agentHistory) + // присваиваем наряду + SetOrderToAgentHistory(ref newAgentHistory, ref order); + + // совмещенный список истории агента по этому наряду + var allHistory = newAgentHistory; + order.AgentHistories.ToList().ForEach(item => allHistory.Add(item)); + allHistory = allHistory.OrderBy(t => t.DateCreated).ToList(); + + // смотрим историю агента, и тут же меняем статус наряда + + // Ищем статус "Агент начал выполнять задание" + var isAgentStarted = allHistory.Any(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.Start); + + // Ищем статус "Агент завершил выполнение задания" + var isAgentEnded = allHistory.Any(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.End); + + // Закрыть наряд + if (isAgentEnded) + ChangeNextStatus(ref order, OrderStatusEnum.Complete, ""); + + // Наряд в работу + if (isAgentStarted && !isAgentEnded && order.StatusCode == (int)OrderStatusEnum.New) + ChangeNextStatus(ref order, OrderStatusEnum.InWork, ""); + + // Закрываем по таймауту. Если есть начало, и нет завершения по АгентТаймаут, то закрываем наряд. + if (isAgentStarted == true && isAgentEnded == false) + { + var lastStrartDate = allHistory.Last(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.Start).DateCreated; + var timeout = (double)order.Template!.ApplicationsInWork!.AgentTimeOutSec!; + + if (lastStrartDate.AddSeconds(timeout) <= DateTimeOffset.UtcNow) + { + var logMsg = $"Закрываю наряд по таймауту ожидания агента. Время старта агента: {lastStrartDate}, допустимый timeOut: {timeout} сек."; + ChangeNextStatus(ref order, OrderStatusEnum.Complete, logMsg); + } + else + logger.LogDebug($"Для наряда {order.Id}, {order.Number} оставляю статус прежним, ожидаю завершение работы агента. Время старта агента: {lastStrartDate}, допустимый timeOut: {timeout} сек."); + } + + //TODO: тут можно подумать, и закрывать наряды, у которых нет истории агента. сейчас мы такие наряды пропускаем, их будет закрывать руками админ. + if (!allHistory.Any()) + { + logger.LogInformation($"Для наряда {order.Id}, {order.Number} нет истории агента. Ничего не делаем."); + + //TODO: тут бы помечать эти наряды, у которых крайний срок вышел и нет истории + } + + if (!await orderService.CommitAsync()) + { + logger.LogError($"Ошибка при сохранении наряда, id: {order.Id}"); + } + + logger.LogInformation($"Закончил работу с нарядом {order.Id}, {order.Number}"); + } + + + /// + /// Присваивает истории агента идентивикатор наряда + /// + private void SetOrderToAgentHistory(ref List newAgentHistory, ref Order order) + { + foreach (var historyItem in newAgentHistory) { historyItem.OrderId = order.Id; logger.LogDebug($"Для наряда {order.Id}, {order.Number} добавил истрию агента {historyItem.Id}, {historyItem.HistoryLevelId}"); @@ -114,66 +167,48 @@ namespace PARR.Master.Services } //отбрасываем все записи которые не добавлены этому наряду - agentHistory = agentHistory.Where(t => t.OrderId.HasValue).ToList(); - - // совмещенный список истории агента по этому наряду - var allHistory = agentHistory; - order.AgentHistories.ToList().ForEach(item => allHistory.Add(item)); - allHistory = allHistory.OrderBy(t => t.DateCreated).ToList(); + newAgentHistory = newAgentHistory.Where(t => t.OrderId.HasValue).ToList(); + } - // смотрим историю агента, и тут же меняем статус наряда + /// + /// Получить историю агента не привязанную к наряду, попадающую в дельту существования наряда + /// + /// + /// + private async Task> GetNewAgentHistoryByOrderAsync(Order order) + { + var agentHistory = await agentHistoryService.Get() + .Where(t => + t.TemplateId == order.TemplateId + && t.DateCreated > order.GenerateDate!.Value.Add(-orderManageSettings.FindAgentHistoryStartOffset) + //&& t.DateCreated <= order.GenerateDate!.Value.AddSeconds(order.Template!.ApplicationsInWork!.AgentTimeOutSec!.Value) + && t.DateCreated <= order.GenerateDate!.Value.Add(order.Template!.ApplicationsInWork!.TemplateDurationTimeSpan!.Value) + && t.OrderId == null + ) + .OrderBy(t => t.DateCreated) + .ToListAsync(); - //1 Ищем статус "Агент начал выполнять задание" - var isAgentStarted = allHistory.Any(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.Start); - - //2 Ищем статус "Агент завершил выполнение задания" - var isAgentEnded = allHistory.Any(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.End); + return agentHistory; + } - //todo: !!! если nextStatus= желаемому статусу, то не заходить внутрь ИФА!!! - - if (isAgentEnded) + /// + /// Изменить статус наряда + /// + /// + /// + private void ChangeNextStatus(ref Order order, OrderStatusEnum nextStatus, string logCompleteMsg) + { + if (order.NextStatusCode != (int)nextStatus) { - order.NextStatusCode = (int)OrderStatusEnum.Complete; - logger.LogInformation($"Для наряда {order.Id}, {order.Number} меняю статус на {OrderStatusEnum.Complete}"); + order.NextStatusCode = (int)nextStatus; + logger.LogInformation($"Для наряда {order.Id}, {order.Number} меняю статус на {nextStatus}. {logCompleteMsg}"); } - - if (isAgentStarted && !isAgentEnded && order.StatusCode == (int)OrderStatusEnum.New) + else { - order.NextStatusCode = (int)OrderStatusEnum.InWork; - logger.LogInformation($"Для наряда {order.Id}, {order.Number} меняю статус на {OrderStatusEnum.InWork}"); + logger.LogDebug($"Для наряда {order.Id}, {order.Number} оставляю статус {nextStatus}, он соответствует дейстивительности."); } - - //закрываем по таймауту. Если есть начало, и нет завершения по АгентТаймаут, то закрываем наряд. - if (isAgentStarted == true && isAgentEnded == false) - { - var lastStrartDate = allHistory.Last(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.Start).DateCreated; - var timeout = (double)order.Template!.ApplicationsInWork!.AgentTimeOutSec!; - - if (lastStrartDate.AddSeconds(timeout) <= DateTimeOffset.UtcNow) - { - order.NextStatusCode = (int)OrderStatusEnum.Complete; - logger.LogInformation($"Для наряда {order.Id}, {order.Number} меняю статус на {OrderStatusEnum.Complete}, закрываю наряд по таймауту ожидания агента. Время старта агента: {lastStrartDate}, допустимый timeOut: {timeout} сек."); - } - else - { - logger.LogDebug($"Для наряда {order.Id}, {order.Number} оставляю статус прежним, ожидаю завершение работы агента. Время старта агента: {lastStrartDate}, допустимый timeOut: {timeout} сек."); - } - } - - //TODO: тут можно подумать, и закрывать наряды, у которых нет истории агента. сейчас мы такие наряды пропускаем, их будет закрывать руками админ. - if (!allHistory.Any()) - { - logger.LogInformation($"Для наряда {order.Id}, {order.Number} нет истории агента. Ничего не делаем."); - } - - if (!await orderService.CommitAsync()) - { - logger.LogError($"Ошибка при сохранении НАРЯДА, id: {order.Id}"); - } - - logger.LogInformation($"Закончил работу с нарядом {order.Id}, {order.Number}"); }