feat(master): логика присвоения истории агента нарядам. Изменение статуса наряда. Отправка в MQ.
This commit is contained in:
10
PARR.BLL/Domain/Mq/OrderManageMq.cs
Normal file
10
PARR.BLL/Domain/Mq/OrderManageMq.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace PARR.BLL.Domain.Mq
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Модель в MQ, запрос на изменение Наряда в ЕСПП
|
||||||
|
/// </summary>
|
||||||
|
public class OrderManageMq
|
||||||
|
{
|
||||||
|
public Guid OrderId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using PARR.Master.Services;
|
||||||
using PARR.Master.Settings;
|
using PARR.Master.Settings;
|
||||||
|
|
||||||
namespace PARR.Master
|
namespace PARR.Master
|
||||||
@@ -7,14 +9,17 @@ namespace PARR.Master
|
|||||||
{
|
{
|
||||||
private readonly WorkerSettings settings;
|
private readonly WorkerSettings settings;
|
||||||
private readonly ILogger<Master> logger;
|
private readonly ILogger<Master> logger;
|
||||||
|
private readonly IServiceProvider serviceProvider;
|
||||||
|
|
||||||
public Master(
|
public Master(
|
||||||
WorkerSettings settings,
|
WorkerSettings settings,
|
||||||
ILogger<Master> logger
|
ILogger<Master> logger,
|
||||||
|
IServiceProvider serviceProvider
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -30,8 +35,7 @@ namespace PARR.Master
|
|||||||
{
|
{
|
||||||
logger.LogInformation("Запуск по расписанию.");
|
logger.LogInformation("Запуск по расписанию.");
|
||||||
|
|
||||||
//todo:
|
await ManageOrdersAsync();
|
||||||
// await Tratata();
|
|
||||||
|
|
||||||
nextStart = DateTime.Now.Add(settings.RepeatEvery);
|
nextStart = DateTime.Now.Add(settings.RepeatEvery);
|
||||||
logger.LogInformation($"Следующая дата запуска: {nextStart}");
|
logger.LogInformation($"Следующая дата запуска: {nextStart}");
|
||||||
@@ -41,5 +45,19 @@ namespace PARR.Master
|
|||||||
await Task.Delay(60 * 1000);
|
await Task.Delay(60 * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task ManageOrdersAsync()
|
||||||
|
{
|
||||||
|
using (var scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
var orderMasterService = scope.ServiceProvider.GetService<IOrderMasterService>();
|
||||||
|
if (orderMasterService == null)
|
||||||
|
throw new Exception("Не смог получить серивс IOrderMasterService, scope.ServiceProvider.GetService<IOrderMasterService>()");
|
||||||
|
|
||||||
|
await orderMasterService.ManageOrdersAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,4 @@
|
|||||||
<ProjectReference Include="..\PARR.DAL\PARR.DAL.csproj" />
|
<ProjectReference Include="..\PARR.DAL\PARR.DAL.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Services\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using PARR.BLL;
|
using PARR.BLL;
|
||||||
using PARR.DAL;
|
using PARR.DAL;
|
||||||
|
using PARR.Master.Services;
|
||||||
using PARR.Master.Settings;
|
using PARR.Master.Settings;
|
||||||
|
|
||||||
namespace PARR.Master
|
namespace PARR.Master
|
||||||
@@ -21,8 +22,13 @@ namespace PARR.Master
|
|||||||
configuration.GetSection(nameof(MqSettings)).Bind(mqSettings);
|
configuration.GetSection(nameof(MqSettings)).Bind(mqSettings);
|
||||||
services.AddSingleton(mqSettings);
|
services.AddSingleton(mqSettings);
|
||||||
|
|
||||||
|
var orderManageSettings = new OrderManageSettings();
|
||||||
|
configuration.GetSection(nameof(OrderManageSettings)).Bind(orderManageSettings);
|
||||||
|
services.AddSingleton(orderManageSettings);
|
||||||
|
|
||||||
//add other services
|
//add other services
|
||||||
services.AddTransient<IMaster, Master>();
|
services.AddTransient<IMaster, Master>();
|
||||||
|
services.AddTransient<IOrderMasterService, OrderMasterService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IConfigurationBuilder AddMasterConfigurations(this IConfigurationBuilder builder, IServiceCollection services)
|
public static IConfigurationBuilder AddMasterConfigurations(this IConfigurationBuilder builder, IServiceCollection services)
|
||||||
|
|||||||
7
PARR.Master/Services/IOrderMasterService.cs
Normal file
7
PARR.Master/Services/IOrderMasterService.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace PARR.Master.Services
|
||||||
|
{
|
||||||
|
internal interface IOrderMasterService
|
||||||
|
{
|
||||||
|
Task ManageOrdersAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
179
PARR.Master/Services/OrderMasterService.cs
Normal file
179
PARR.Master/Services/OrderMasterService.cs
Normal file
@@ -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<OrderMasterService> logger;
|
||||||
|
private readonly IOrderService orderService;
|
||||||
|
private readonly IAgentHistoryService agentHistoryService;
|
||||||
|
private readonly OrderManageSettings orderManageSettings;
|
||||||
|
private readonly MqSettings mqSettings;
|
||||||
|
private readonly IMqService mqService;
|
||||||
|
|
||||||
|
public OrderMasterService(
|
||||||
|
ILogger<OrderMasterService> 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($"=== Конец работы с нарядами=== ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Находит наряды в статусе 1 и 2, присваивает им историю работы агента, меняет стаус наряда
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="order"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
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}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить список нарядов, со статусами 1 или 2
|
||||||
|
/// </summary>
|
||||||
|
private async Task<List<Order>> GetOrdersNewOrWorkStatusesAsync()
|
||||||
|
{
|
||||||
|
return await GetOrdres()
|
||||||
|
.Where(t => t.StatusCode == (int)OrderStatusEnum.New || t.StatusCode == (int)OrderStatusEnum.InWork)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить список нарядов, у которых StatusCode!=NextStatusCode
|
||||||
|
/// </summary>
|
||||||
|
private async Task<List<Order>> GetOrdresWithStatusCodeNotEqualAsync()
|
||||||
|
{
|
||||||
|
return await GetOrdres()
|
||||||
|
.Where(t => t.NextStatusCode.HasValue && t.NextStatusCode.Value != t.StatusCode)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Основной запрос на получения списка нарядов со связями, по базовому условию
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private IQueryable<Order> 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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
PARR.Master/Settings/OrderManageSettings.cs
Normal file
10
PARR.Master/Settings/OrderManageSettings.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace PARR.Master.Settings
|
||||||
|
{
|
||||||
|
internal class OrderManageSettings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Смещение, относительно которого начинается поиск истории агента для привязки к времени генерации наряда
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan FindAgentHistoryStartOffset { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,5 +34,8 @@
|
|||||||
},
|
},
|
||||||
"WorkerSettings": {
|
"WorkerSettings": {
|
||||||
"RepeatEvery": "0:30:00"
|
"RepeatEvery": "0:30:00"
|
||||||
|
},
|
||||||
|
"OrderManageSettings": {
|
||||||
|
"FindAgentHistoryStartOffset": "0:05:00"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user