Files
parr_api/PARR.EsppOrderManager/EsppOrderManager.cs

227 lines
9.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.EntityFrameworkCore;
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;
private readonly IServiceProvider serviceProvider;
private readonly ResultTemplateSettings resultTemplateSettings;
public EsppOrderManager(
MqSettings mqSettings,
IRabbitService mqService,
ILogger<EsppOrderManager> logger,
ITransformService transformService,
IEsppOrderService esppOrderService,
IServiceProvider serviceProvider,
ResultTemplateSettings resultTemplateSettings
)
{
this.mqSettings = mqSettings;
this.mqService = mqService;
this.logger = logger;
this.transformService = transformService;
this.esppOrderService = esppOrderService;
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();
}
private async Task ManageOrderAsync(string msg)
{
//logger.LogDebug($"Получили сообщение: {msg}");
var objFromQuery = transformService.GetModelFromJson<OrderManageMq>(msg);
if (objFromQuery == null)
return;
using (var scope = serviceProvider.CreateScope())
{
var orderService = scope.ServiceProvider.GetService<IOrderRepository>();
if (orderService == null)
throw new Exception("Не смог получить серивс IOrderService, scope.ServiceProvider.GetService<IOrderService>()");
await ManageOrderToScopeAsync(orderService, objFromQuery);
}
logger.LogDebug($"Закончил работу с сообщением: {msg}");
}
private async Task ManageOrderToScopeAsync(IOrderRepository orderService, OrderManageMq objFromQuery)
{
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)
.FirstOrDefaultAsync(t => t.Id == objFromQuery.OrderId);
if (!IsValidOrder(ref order, ref objFromQuery))
return;
logger.LogDebug($"Найден наряд в БД: {order!.Number}");
var resultMsg = GenerateResultMsg(order!);
var workDuration = CalcWorkDuration(order!);
// Изменям статус наряда в ЕСПП
var result = await esppOrderService.ChangeOrderToEsppAsync(order!, resultMsg, workDuration);
if (result)
{
logger.LogInformation($"Статусы наряда {order!.Number} в ЕСПП обновлены. Установлен статус: {order.NextStatus!.Description}");
//обновляем статусы в БД
order.StatusCode = order.NextStatusCode!.Value;
order.DateModified = DateTimeOffset.UtcNow;
if (!await orderService.CommitAsync())
{
logger.LogError($"Ошибка при обновлении статуса в БД у наряда: {order.Number}. Не установлен статус {order.NextStatus!.Description}");
}
}
else
logger.LogError($"Ошибка при обновлении статуса наряда {order!.Number}. Статус не изменен.");
}
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;
}
}
}