diff --git a/PARR.BLL/Domain/Mq/OrderManageMq.cs b/PARR.BLL/Domain/Mq/OrderManageMq.cs
new file mode 100644
index 00000000..06c5e731
--- /dev/null
+++ b/PARR.BLL/Domain/Mq/OrderManageMq.cs
@@ -0,0 +1,10 @@
+namespace PARR.BLL.Domain.Mq
+{
+ ///
+ /// Модель в MQ, запрос на изменение Наряда в ЕСПП
+ ///
+ public class OrderManageMq
+ {
+ public Guid OrderId { get; set; }
+ }
+}
diff --git a/PARR.Master/Master.cs b/PARR.Master/Master.cs
index dd1b3484..cc15614f 100644
--- a/PARR.Master/Master.cs
+++ b/PARR.Master/Master.cs
@@ -1,4 +1,6 @@
-using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using PARR.Master.Services;
using PARR.Master.Settings;
namespace PARR.Master
@@ -7,14 +9,17 @@ namespace PARR.Master
{
private readonly WorkerSettings settings;
private readonly ILogger logger;
+ private readonly IServiceProvider serviceProvider;
public Master(
WorkerSettings settings,
- ILogger logger
+ ILogger logger,
+ IServiceProvider serviceProvider
)
{
this.settings = settings;
this.logger = logger;
+ this.serviceProvider = serviceProvider;
}
@@ -30,8 +35,7 @@ namespace PARR.Master
{
logger.LogInformation("Запуск по расписанию.");
- //todo:
- // await Tratata();
+ await ManageOrdersAsync();
nextStart = DateTime.Now.Add(settings.RepeatEvery);
logger.LogInformation($"Следующая дата запуска: {nextStart}");
@@ -41,5 +45,19 @@ namespace PARR.Master
await Task.Delay(60 * 1000);
}
}
+
+
+ private async Task ManageOrdersAsync()
+ {
+ using (var scope = serviceProvider.CreateScope())
+ {
+ var orderMasterService = scope.ServiceProvider.GetService();
+ if (orderMasterService == null)
+ throw new Exception("Не смог получить серивс IOrderMasterService, scope.ServiceProvider.GetService()");
+
+ await orderMasterService.ManageOrdersAsync();
+ }
+ }
+
}
}
diff --git a/PARR.Master/PARR.Master.csproj b/PARR.Master/PARR.Master.csproj
index 57e11ce6..21190861 100644
--- a/PARR.Master/PARR.Master.csproj
+++ b/PARR.Master/PARR.Master.csproj
@@ -11,8 +11,4 @@
-
-
-
-
diff --git a/PARR.Master/ParrMasterInstaller.cs b/PARR.Master/ParrMasterInstaller.cs
index 486ae39c..a6c150c1 100644
--- a/PARR.Master/ParrMasterInstaller.cs
+++ b/PARR.Master/ParrMasterInstaller.cs
@@ -2,6 +2,7 @@
using Microsoft.Extensions.DependencyInjection;
using PARR.BLL;
using PARR.DAL;
+using PARR.Master.Services;
using PARR.Master.Settings;
namespace PARR.Master
@@ -21,8 +22,13 @@ namespace PARR.Master
configuration.GetSection(nameof(MqSettings)).Bind(mqSettings);
services.AddSingleton(mqSettings);
+ var orderManageSettings = new OrderManageSettings();
+ configuration.GetSection(nameof(OrderManageSettings)).Bind(orderManageSettings);
+ services.AddSingleton(orderManageSettings);
+
//add other services
services.AddTransient();
+ services.AddTransient();
}
public static IConfigurationBuilder AddMasterConfigurations(this IConfigurationBuilder builder, IServiceCollection services)
diff --git a/PARR.Master/Services/IOrderMasterService.cs b/PARR.Master/Services/IOrderMasterService.cs
new file mode 100644
index 00000000..3fc2439a
--- /dev/null
+++ b/PARR.Master/Services/IOrderMasterService.cs
@@ -0,0 +1,7 @@
+namespace PARR.Master.Services
+{
+ internal interface IOrderMasterService
+ {
+ Task ManageOrdersAsync();
+ }
+}
diff --git a/PARR.Master/Services/OrderMasterService.cs b/PARR.Master/Services/OrderMasterService.cs
new file mode 100644
index 00000000..db6991bf
--- /dev/null
+++ b/PARR.Master/Services/OrderMasterService.cs
@@ -0,0 +1,179 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+using PARR.BLL.Domain.Mq;
+using PARR.BLL.Services.Interfaces;
+using PARR.DAL.Contracts;
+using PARR.DAL.Models;
+using PARR.DAL.Services.Interfaces;
+using PARR.Master.Settings;
+using System.Text.Json;
+
+namespace PARR.Master.Services
+{
+ internal class OrderMasterService : IOrderMasterService
+ {
+ private readonly ILogger logger;
+ private readonly IOrderService orderService;
+ private readonly IAgentHistoryService agentHistoryService;
+ private readonly OrderManageSettings orderManageSettings;
+ private readonly MqSettings mqSettings;
+ private readonly IMqService mqService;
+
+ public OrderMasterService(
+ ILogger logger,
+ IOrderService orderService,
+ IAgentHistoryService agentHistoryService,
+ OrderManageSettings orderManageSettings,
+ MqSettings mqSettings,
+ IMqService mqService
+
+ )
+ {
+ this.logger = logger;
+ this.orderService = orderService;
+ this.agentHistoryService = agentHistoryService;
+ this.orderManageSettings = orderManageSettings;
+ this.mqSettings = mqSettings;
+ this.mqService = mqService;
+ }
+
+
+ public async Task ManageOrdersAsync()
+ {
+ logger.LogInformation($"--- Начало поиска нарядов ---");
+
+ //ищем наряды в статусе 1 и 2, присваиваем им историю работы агента, меняем стаус наряда
+ var ordersToManage = await GetOrdersNewOrWorkStatusesAsync();
+
+ logger.LogInformation($"Ищу наряды со статусом 1 и 2. Найдено нарядов: {ordersToManage.Count()} шт.");
+
+ foreach (var order in ordersToManage)
+ {
+ logger.LogInformation($"Найден наряд id: {order.Id}, {order.Number}");
+ await SetHistoryAndUpdateOrderStatus(order);
+ }
+
+
+ //находим наряды где статусы не равны, добавляем их в Rabbit
+ var ordersWithStatusNotEqual = await GetOrdresWithStatusCodeNotEqualAsync();
+ var objs = ordersWithStatusNotEqual.Select(t => JsonSerializer.Serialize(new OrderManageMq { OrderId = t.Id }));
+
+ logger.LogInformation($"Ищу наряды где статусы не равны. Найдено нарядов: {ordersWithStatusNotEqual.Count()}. Добавляю их в RabbitMQ.");
+
+ if (objs.Any())
+ {
+ var sendResult = mqService.Send(mqSettings, objs.ToArray());
+ if (sendResult.IsSuccess)
+ {
+ logger.LogInformation($"Наряды переданы в RabbitMQ: {objs.Count()}");
+ logger.LogDebug($"Список нардов переданных в RabbitMQ: {string.Join(", ", objs)}");
+ }
+ else
+ logger.LogError($"Ошибка при передаче нарядов в Rabbit, неперадынные сообщения: {string.Join(", ", sendResult!.NotSendMessages)}");
+
+ }
+
+ logger.LogInformation($"=== Конец работы с нарядами=== ");
+ }
+
+
+ ///
+ /// Находит наряды в статусе 1 и 2, присваивает им историю работы агента, меняет стаус наряда
+ ///
+ ///
+ ///
+ private async Task SetHistoryAndUpdateOrderStatus(Order order)
+ {
+ //TODO: тут тот таймаут? или надо TemplateDuration
+ 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.OrderId == null
+ )
+ .ToListAsync();
+
+ logger.LogInformation($"Для наряда {order.Id}, {order.Number} надено новых историй агентов: {agentHistory.Count()} шт. Присваиваю истории ИД наряда.");
+
+ foreach (var historyItem in agentHistory)
+ historyItem.OrderId = order.Id;
+
+ // смотрим историю агента, и тут же меняем статус наряда
+
+ //1 Ищем статус "Агент начал выполнять задание"
+ var isAgentStarted = agentHistory.Any(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.Start) || order.AgentHistories.Any(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.Start);
+
+ //2 Ищем статус "Агент завершил выполнение задания"
+ var isAgentEnded = agentHistory.Any(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.End) || order.AgentHistories.Any(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.End);
+
+ if (isAgentEnded)
+ {
+ order.NextStatusCode = (int)OrderStatusEnum.Complete;
+ logger.LogInformation($"Для наряда {order.Id}, {order.Number} меню статус на {OrderStatusEnum.Complete}");
+ }
+
+ if (isAgentStarted && !isAgentEnded && order.StatusCode == (int)OrderStatusEnum.New)
+ {
+ order.NextStatusCode = (int)OrderStatusEnum.InWork;
+ logger.LogInformation($"Для наряда {order.Id}, {order.Number} меню статус на {OrderStatusEnum.InWork}");
+ }
+
+ //TODO: тут подумать про таймаут, по какому таймауту закрывтаь наряд? по таймауту агента, или по TemplateDuration?
+ //timeout
+ //if(isAgentStarted==false && isAgentEnded == false && )
+ //{
+ // // ставим Выполнен, так как превысил таймаут
+ // order.NextStatusCode = (int)OrderStatusEnum.Complete;
+ // logger.LogInformation($"Для наряда {order.Id}, {order.Number} меню статус на {OrderStatusEnum.Complete}");
+ //}
+
+ if (!await orderService.CommitAsync())
+ {
+ logger.LogError($"Ошибка при сохранении НАРЯДА, id: {order.Id}");
+ }
+
+ logger.LogInformation($"Закончил работу с нарядом {order.Id}, {order.Number}");
+ }
+
+
+ ///
+ /// Получить список нарядов, со статусами 1 или 2
+ ///
+ private async Task> GetOrdersNewOrWorkStatusesAsync()
+ {
+ return await GetOrdres()
+ .Where(t => t.StatusCode == (int)OrderStatusEnum.New || t.StatusCode == (int)OrderStatusEnum.InWork)
+ .ToListAsync();
+ }
+
+
+ ///
+ /// Получить список нарядов, у которых StatusCode!=NextStatusCode
+ ///
+ private async Task> GetOrdresWithStatusCodeNotEqualAsync()
+ {
+ return await GetOrdres()
+ .Where(t => t.NextStatusCode.HasValue && t.NextStatusCode.Value != t.StatusCode)
+ .ToListAsync();
+ }
+
+
+ ///
+ /// Основной запрос на получения списка нарядов со связями, по базовому условию
+ ///
+ ///
+ private IQueryable GetOrdres()
+ {
+ return orderService.Get()
+ .Include(t => t.Template).ThenInclude(t => t!.ApplicationsInWork)
+ .Include(t => t.AgentHistories)
+ .Where(t =>
+ t.TemplateId.HasValue
+ && t.Template!.ApplicationsInWork!.IsAgent == true
+ && t.GenerateDate.HasValue
+ && t.Template!.ApplicationsInWork!.AgentTimeOutSec.HasValue
+ );
+ }
+ }
+}
diff --git a/PARR.Master/Settings/OrderManageSettings.cs b/PARR.Master/Settings/OrderManageSettings.cs
new file mode 100644
index 00000000..c32cc5ba
--- /dev/null
+++ b/PARR.Master/Settings/OrderManageSettings.cs
@@ -0,0 +1,10 @@
+namespace PARR.Master.Settings
+{
+ internal class OrderManageSettings
+ {
+ ///
+ /// Смещение, относительно которого начинается поиск истории агента для привязки к времени генерации наряда
+ ///
+ public TimeSpan FindAgentHistoryStartOffset { get; set; }
+ }
+}
diff --git a/PARR.MasterWorker/appsettings.json b/PARR.MasterWorker/appsettings.json
index b70e9302..76e7193a 100644
--- a/PARR.MasterWorker/appsettings.json
+++ b/PARR.MasterWorker/appsettings.json
@@ -34,5 +34,8 @@
},
"WorkerSettings": {
"RepeatEvery": "0:30:00"
+ },
+ "OrderManageSettings": {
+ "FindAgentHistoryStartOffset": "0:05:00"
}
}