Files
parr_api/PARR.EsppOrderManager/EsppOrderManager.cs

227 lines
9.4 KiB
C#
Raw Permalink Normal View History

using Microsoft.EntityFrameworkCore;
2023-11-20 16:59:58 +10:00
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PARR.Core.Common.Interfaces;
using PARR.Core.Common.Interfaces.RabbitServices;
using PARR.Core.Repositories.Interfaces;
using PARR.Domain.Common.Rabbit.Messages;
using PARR.Domain.Entities;
using PARR.Domain.Enums;
using PARR.EsppOrderManager.Services;
using PARR.EsppOrderManager.Settings;
namespace PARR.EsppOrderManager
{
internal class EsppOrderManager : IEsppOrderManager
{
private readonly MqSettings mqSettings;
private readonly IRabbitService mqService;
private readonly ILogger<EsppOrderManager> logger;
private readonly ITransformService transformService;
private readonly IEsppOrderService esppOrderService;
2023-11-20 16:59:58 +10:00
private readonly IServiceProvider serviceProvider;
private readonly ResultTemplateSettings resultTemplateSettings;
public EsppOrderManager(
MqSettings mqSettings,
IRabbitService mqService,
ILogger<EsppOrderManager> logger,
ITransformService transformService,
2023-11-20 16:59:58 +10:00
IEsppOrderService esppOrderService,
IServiceProvider serviceProvider,
ResultTemplateSettings resultTemplateSettings
)
{
this.mqSettings = mqSettings;
this.mqService = mqService;
this.logger = logger;
this.transformService = transformService;
this.esppOrderService = esppOrderService;
2023-11-20 16:59:58 +10:00
this.serviceProvider = serviceProvider;
this.resultTemplateSettings = resultTemplateSettings;
}
public async Task StartAsync()
{
// логика работы описана в документации
var isConnected = await mqService.InitConsumerAsync(mqSettings, ManageOrderAsync);
if (!isConnected)
throw new Exception("Ошибка при подключении к RabbitMq");
//test, and remove async in method name
//await ManageOrderAsync("{\"OrderId\":\"49191af5-c313-4388-9720-a61fd13f15a8\"}");
}
public async Task StopAsync()
{
await mqService.DisposeAsync();
}
2023-11-20 16:59:58 +10:00
private async Task ManageOrderAsync(string msg)
{
//logger.LogDebug($"Получили сообщение: {msg}");
2023-11-20 16:59:58 +10:00
var objFromQuery = transformService.GetModelFromJson<OrderManageMq>(msg);
if (objFromQuery == null)
return;
2023-11-20 16:59:58 +10:00
using (var scope = serviceProvider.CreateScope())
{
var orderService = scope.ServiceProvider.GetService<IOrderRepository>();
2023-11-20 16:59:58 +10:00
if (orderService == null)
throw new Exception("Не смог получить серивс IOrderService, scope.ServiceProvider.GetService<IOrderService>()");
2023-11-20 16:59:58 +10:00
await ManageOrderToScopeAsync(orderService, objFromQuery);
}
2023-11-20 16:59:58 +10:00
logger.LogDebug($"Закончил работу с сообщением: {msg}");
}
private async Task ManageOrderToScopeAsync(IOrderRepository orderService, OrderManageMq objFromQuery)
2023-11-20 16:59:58 +10:00
{
var order = await orderService.Get()
.Include(t => t.AgentHistories).ThenInclude(t => t.AgentHistoryLevel)
.Include(t => t.OrderStatus)
.Include(t => t.NextStatus)
.Include(t => t.Template).ThenInclude(t => t!.Job).ThenInclude(t => t!.Tnk)
2023-11-20 16:59:58 +10:00
.FirstOrDefaultAsync(t => t.Id == objFromQuery.OrderId);
if (!IsValidOrder(ref order, ref objFromQuery))
return;
2023-11-20 16:59:58 +10:00
logger.LogDebug($"Найден наряд в БД: {order!.Number}");
var resultMsg = GenerateResultMsg(order!);
var workDuration = CalcWorkDuration(order!);
// Изменям статус наряда в ЕСПП
2023-11-20 16:59:58 +10:00
var result = await esppOrderService.ChangeOrderToEsppAsync(order!, resultMsg, workDuration);
if (result)
{
2023-11-20 16:59:58 +10:00
logger.LogInformation($"Статусы наряда {order!.Number} в ЕСПП обновлены. Установлен статус: {order.NextStatus!.Description}");
//обновляем статусы в БД
2023-11-20 16:59:58 +10:00
order.StatusCode = order.NextStatusCode!.Value;
order.DateModified = DateTimeOffset.UtcNow;
if (!await orderService.CommitAsync())
{
logger.LogError($"Ошибка при обновлении статуса в БД у наряда: {order.Number}. Не установлен статус {order.NextStatus!.Description}");
}
}
else
2023-11-20 16:59:58 +10:00
logger.LogError($"Ошибка при обновлении статуса наряда {order!.Number}. Статус не изменен.");
}
2023-11-20 16:59:58 +10:00
private bool IsValidOrder(ref Order? order, ref OrderManageMq query)
{
if (order == null)
{
logger.LogError($"Не найден наряд с OrderId: {query.OrderId}");
return false;
}
if (order.StatusCode == order.NextStatusCode)
{
logger.LogInformation($"У наряда {order.Id}, {order.Number} статусы равны, ничего не делаем. Статус: {order.OrderStatus!.Description}");
return false;
}
if (!order.NextStatusCode.HasValue)
{
logger.LogWarning($"У наряда {order.Id}, {order.Number} не установлено поле {nameof(order.NextStatusCode)}");
return false;
}
return true;
}
/// <summary>
/// Генерирует текст поля Решение, в зависимости от статуса наряда и от истории Агента
/// </summary>
/// <param name="order"></param>
/// <returns></returns>
private string GenerateResultMsg(Order order)
{
var agentHistory = order.AgentHistories
.OrderBy(t => t.DateCreated)
.Select(t => $"{t.DateCreated} :: {t.AgentHistoryLevel?.Name} :: {t.Message}");
//"Template": "{base}\n{msgAgent}",
//"MsgAgent": "Работы выполнены средствами автоматизации.\nЖурнал работы:\n{agentHistory}",
//"MsgAgentEmpty": "Работы должны были выполняться средствами автоматизации. От средств автоматизации не поступило сообщений. Работы не выполнены."
//Шаблон поля Решение
var template = resultTemplateSettings.Template;
//Поле решение из ApplicationsInWork
var baseMsg = order.Template!.Job!.Group!.Solution;
//Формируем сообщения от Агента
var msgAgent = agentHistory.Any()
? resultTemplateSettings.MsgAgent.Replace("{agentHistory}", string.Join("\n", agentHistory))
: resultTemplateSettings.MsgAgentEmpty;
return template.Replace("{base}", baseMsg).Replace("{msgAgent}", msgAgent);
}
/// <summary>
/// Рассчиать трудозатраты
/// </summary>
/// <param name="order"></param>
/// <returns></returns>
private TimeSpan CalcWorkDuration(Order order)
{
var agentHistory = order.AgentHistories
.OrderBy(t => t.DateCreated);
if (!agentHistory.Any())
return GetTnkDurationByScriptDuration(TimeSpan.Zero);
var dateStart = agentHistory.LastOrDefault(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.Start)?.DateCreated;
var dateEnd = agentHistory.LastOrDefault(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.End)?.DateCreated;
if (dateStart.HasValue && dateEnd.HasValue)
{
var duration = dateEnd.Value - dateStart.Value;
logger.LogDebug($"Продолжительность работы скрипта: {duration}");
return GetTnkDurationByScriptDuration(duration);
}
return GetTnkDurationByScriptDuration(TimeSpan.Zero);
}
/// <summary>
/// Получить время для списания ТНК по времени работы скрипта
/// </summary>
/// <param name="scriptDuration"></param>
/// <returns></returns>
private TimeSpan GetTnkDurationByScriptDuration(TimeSpan scriptDuration)
{
// минимальное значение 1 минута
var minDuration = new TimeSpan(0, 1, 0);
if (scriptDuration < minDuration)
{
logger.LogDebug($"Продолжительность меньше минимального, беру минимальное: {minDuration}. {scriptDuration}<{minDuration}");
return minDuration;
}
else
return scriptDuration;
}
}
}