Files
parr_api/PARR.EsppOrderManager/EsppOrderManager.cs

216 lines
8.7 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.BLL.Domain.Mq;
using PARR.BLL.Services.Interfaces;
using PARR.DAL.Contracts;
using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces;
using PARR.EsppOrderManager.Services;
using PARR.EsppOrderManager.Settings;
namespace PARR.EsppOrderManager
{
internal class EsppOrderManager : IEsppOrderManager
{
private readonly MqSettings mqSettings;
private readonly IMqService mqService;
private readonly ILogger<EsppOrderManager> logger;
private readonly ITransformService transformService;
private readonly IEsppOrderService esppOrderService;
private readonly IServiceProvider serviceProvider;
public EsppOrderManager(
MqSettings mqSettings,
IMqService mqService,
ILogger<EsppOrderManager> logger,
ITransformService transformService,
IEsppOrderService esppOrderService,
IServiceProvider serviceProvider
)
{
this.mqSettings = mqSettings;
this.mqService = mqService;
this.logger = logger;
this.transformService = transformService;
this.esppOrderService = esppOrderService;
this.serviceProvider = serviceProvider;
}
public async void Start()
{
// логика работы описана в документации
//var isConnected = mqService.InitConsumer(mqSettings, ManageOrderAsync);
//if (!isConnected)
// throw new Exception("Ошибка при подключении к RabbitMq");
//test, and remove async in method name
await ManageOrderAsync("{\"OrderId\":\"dd04a997-e7b5-4326-b6e1-505719cc46fb\"}");
}
public void Stop()
{
mqService.Dispose();
}
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<IOrderService>();
if (orderService == null)
throw new Exception("Не смог получить серивс IOrderService, scope.ServiceProvider.GetService<IOrderService>()");
await ManageOrderToScopeAsync(orderService, objFromQuery);
}
logger.LogDebug($"Закончил работу с сообщением: {msg}");
}
private async Task ManageOrderToScopeAsync(IOrderService 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!.ApplicationsInWork).ThenInclude(t => t!.Work).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;
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}");
var baseMsg = order.Template!.ApplicationsInWork!.Solution + "\n";
var msgAgent = "Работы выполнены средствами автоматизации. \n" +
"Журнал работы: \n" +
$"{string.Join("\n", agentHistory)}";
var msgAgentEmpty = "Работы должны были выполняться средствами автоматизации. " +
"От средств автоматизации не поступило сообщений. " +
"Работы не выполнены.";
return baseMsg + (agentHistory.Any() ? msgAgent : msgAgentEmpty);
}
/// <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;
}
}
}