feat(all): ! Критические изменения логики работы всех сервисорв, База Данных имееет неокончательную версию. Template, Scheduler переведены на работу с Unit+Job+JobGroup вместо Host+ApplicationsInWork

This commit is contained in:
Mikhail Kuznetsov
2025-06-25 14:17:34 +10:00
parent 1b867585d8
commit 03c7852378
54 changed files with 5176 additions and 989 deletions

View File

@@ -0,0 +1,17 @@
namespace PARR.API.Contracts.V1.Responses
{
public class JobBaseResponse
{
public Guid Id { get; set; }
public required string Name { get; set; }
public required string TemplateNameMask { get; set; }
public TnkResponse? Tnk { get; set; }
}
public class JobResponse : JobBaseResponse
{
}
}

View File

@@ -31,7 +31,7 @@
public required string TnkEsppId { get; set; } public required string TnkEsppId { get; set; }
public required string WorkName { get; set; } public required string WorkName { get; set; }
public required string WorkEsppId { get; set; } //public required string WorkEsppId { get; set; }
} }

View File

@@ -2,7 +2,7 @@
{ {
public class StatHostTemplateResponse public class StatHostTemplateResponse
{ {
public int AllHosts { get; set; } public int AllUnits { get; set; }
public int HostsInTemplates { get; set; } public int HostsInTemplates { get; set; }
} }
} }

View File

@@ -25,9 +25,12 @@
public bool IsAutoDistributionEnabled { get; set; } public bool IsAutoDistributionEnabled { get; set; }
public HostTemplateResponse? Host { get; set; } //public HostTemplateResponse? Host { get; set; }
public UnitBaseResponse? Unit { get; set; }
public WorkResponse? Work { get; set; } public JobBaseResponse? Job { get; set; }
//public WorkResponse? Work { get; set; }
public ProcessResponse? Process { get; set; } public ProcessResponse? Process { get; set; }
public SubprocessResponse? Subprocess { get; set; } public SubprocessResponse? Subprocess { get; set; }
public TnkResponse? Tnk { get; set; } public TnkResponse? Tnk { get; set; }

View File

@@ -22,15 +22,4 @@
public List<AttributeResponse>? Attributes { get; set; } public List<AttributeResponse>? Attributes { get; set; }
} }
} }

View File

@@ -15,6 +15,7 @@ using PARR.Constants;
using PARR.DAL.DomainModels; using PARR.DAL.DomainModels;
using PARR.DAL.Models; using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Unit;
namespace PARR.API.Controllers.V1 namespace PARR.API.Controllers.V1
{ {
@@ -29,6 +30,7 @@ namespace PARR.API.Controllers.V1
private readonly IMapper mapper; private readonly IMapper mapper;
private readonly ITemplateService templateService; private readonly ITemplateService templateService;
private readonly IClientService clientService; private readonly IClientService clientService;
private readonly IUnitService unitService;
private readonly ILogger<AgentHistoryController> logger; private readonly ILogger<AgentHistoryController> logger;
public AgentHistoryController( public AgentHistoryController(
@@ -38,6 +40,7 @@ namespace PARR.API.Controllers.V1
IMapper mapper, IMapper mapper,
ITemplateService templateService, ITemplateService templateService,
IClientService clientService, IClientService clientService,
IUnitService unitService,
ILogger<AgentHistoryController> logger ILogger<AgentHistoryController> logger
) )
{ {
@@ -47,6 +50,7 @@ namespace PARR.API.Controllers.V1
this.mapper = mapper; this.mapper = mapper;
this.templateService = templateService; this.templateService = templateService;
this.clientService = clientService; this.clientService = clientService;
this.unitService = unitService;
this.logger = logger; this.logger = logger;
} }
@@ -121,16 +125,22 @@ namespace PARR.API.Controllers.V1
var clientIp = clientService.GetClientIp()?.ToString(); var clientIp = clientService.GetClientIp()?.ToString();
var template = await templateService.Get().Include(t => t.Host).FirstOrDefaultAsync(t => t.Id == request.TemplateId); var template = await templateService.Get()
.Include(t => t.Unit)
.ThenInclude(t => t!.UnitValues)
.FirstOrDefaultAsync(t => t.Id == request.TemplateId);
if (template == null) if (template == null)
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { FieldName = nameof(request.TemplateId), Message = $"Не найден шаблон с Id: {request.TemplateId}" } })); return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { FieldName = nameof(request.TemplateId), Message = $"Не найден шаблон с Id: {request.TemplateId}" } }));
//проверять что этот этот шаблон привязан к этому серверу по ip //проверять что этот этот шаблон привязан к этому серверу по ip
if (template.Host?.IP != clientIp) var unit = await unitService.GetWithIncludes().AsNoTracking().FirstOrDefaultAsync(t => t.Id == template.UnitId);
var unitIp = unit?.UnitValues.FirstOrDefault(t => t.Field!.AihitName == "IP_АДРЕС")!.Value!.Value;
if (unitIp != clientIp)
{ {
logger.LogWarning($"Клиент с ip: {clientIp} пытается записать историю агента для templateId: {request.TemplateId}, " + logger.LogWarning($"Клиент с ip: {clientIp} пытается записать историю агента для templateId: {request.TemplateId}, " +
$"но у шаблона ip: {template.Host?.IP}, доступ запрещен так как их ip не равны."); $"но у шаблона ip: {unitIp}, доступ запрещен так как их ip не равны.");
return Forbid(); return Forbid();
} }

View File

@@ -10,6 +10,7 @@ using PARR.API.Services.Interfaces;
using PARR.Constants; using PARR.Constants;
using PARR.DAL.Contracts; using PARR.DAL.Contracts;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Unit;
using PARR.DAL.TransformServices; using PARR.DAL.TransformServices;
namespace PARR.API.Controllers.V1 namespace PARR.API.Controllers.V1
@@ -22,18 +23,21 @@ namespace PARR.API.Controllers.V1
{ {
private readonly IClientService clientService; private readonly IClientService clientService;
private readonly ITemplateService templateService; private readonly ITemplateService templateService;
private readonly IUnitService unitService;
private readonly IEsppScheduleTransformService esppScheduleTransformService; private readonly IEsppScheduleTransformService esppScheduleTransformService;
private readonly ILogger<AgentTaskController> logger; private readonly ILogger<AgentTaskController> logger;
public AgentTaskController( public AgentTaskController(
IClientService clientService, IClientService clientService,
ITemplateService templateService, ITemplateService templateService,
IUnitService unitService,
IEsppScheduleTransformService esppScheduleTransformService, IEsppScheduleTransformService esppScheduleTransformService,
ILogger<AgentTaskController> logger ILogger<AgentTaskController> logger
) )
{ {
this.clientService = clientService; this.clientService = clientService;
this.templateService = templateService; this.templateService = templateService;
this.unitService = unitService;
this.esppScheduleTransformService = esppScheduleTransformService; this.esppScheduleTransformService = esppScheduleTransformService;
this.logger = logger; this.logger = logger;
} }
@@ -62,19 +66,21 @@ namespace PARR.API.Controllers.V1
//Агент получает задания, если `IsAgent = true`, шаблон и расписания активны, и статус синхронизации шаблона и расписания `= Ok`, и `NextRun = сегодня`, так же если у ApplicationInWork есть расписание. //Агент получает задания, если `IsAgent = true`, шаблон и расписания активны, и статус синхронизации шаблона и расписания `= Ok`, и `NextRun = сегодня`, так же если у ApplicationInWork есть расписание.
// С одним IP может быть несколько информационных систем, так что может быть несколько хостов // С одним IP может быть несколько информационных систем, так что может быть несколько хостов
var units = await unitService.GetWithIncludes().AsNoTracking().Where(t => t.UnitValues.Any(v => v.Field!.AihitName == "IP_АДРЕС" && v.Value!.Value == ip)).ToListAsync();
var templates = await templateService.Get() var templates = await templateService.Get()
.Include(t => t.RobotConfigurations) .Include(t => t.RobotConfigurations)
.Include(t => t.ApplicationsInWork) .Include(t => t.Job)
.ThenInclude(t => t!.EsppSchValues) .ThenInclude(t=>t!.Group)
.Include(t => t.Host) .ThenInclude(t => t!.EsppSchValues)
.Where(t => t.Host!.IP == ip .Include(t => t.Unit)
&& t.ApplicationsInWork!.IsAgent == true .Where(t => units.Any(u=>u.Id == t.UnitId)
//&& t.ApplicationsInWork!.IsAgent == true//TODO Migration to job
&& t.IsActiveTemplate == true && t.IsActiveTemplate == true
&& t.IsActiveSchedule == true && t.IsActiveSchedule == true
//&& t.ApplicationsInWork!.NextRun.DateTime.Date == date.Date.Date //&& t.ApplicationsInWork!.NextRun.DateTime.Date == date.Date.Date
&& t.NextRun.DateTime.Date == date.Date.Date && t.NextRun.DateTime.Date == date.Date.Date
&& t.RobotConfigurations.All(c => c.TaskStatusCode == (int)TaskStatusEnum.Ok) && t.RobotConfigurations.All(c => c.TaskStatusCode == (int)TaskStatusEnum.Ok)
&& t.ApplicationsInWork.EsppSchValues.Any() && t.Job!.Group!.EsppSchValues.Any()//.ApplicationsInWork.EsppSchValues.Any()
).ToListAsync(); ).ToListAsync();
if (!templates.Any()) if (!templates.Any())
@@ -88,26 +94,26 @@ namespace PARR.API.Controllers.V1
foreach (var template in templates) foreach (var template in templates)
{ {
//var templateSchedule = await esppScheduleTransformService.GetNextScheduleAsync(template.ApplicationInWorkId, template.ApplicationsInWork!.LastRun ?? template.ApplicationsInWork!.NextRun); //var templateSchedule = await esppScheduleTransformService.GetNextScheduleAsync(template.ApplicationInWorkId, template.ApplicationsInWork!.LastRun ?? template.ApplicationsInWork!.NextRun);
var templateSchedule = await esppScheduleTransformService.GetNextScheduleAsync(template.ApplicationInWorkId, template.NextRun); var templateSchedule = await esppScheduleTransformService.GetNextScheduleAsync(template.Job!.GroupId, template.NextRun);
if (!templateSchedule.Any()) if (!templateSchedule.Any())
{ {
logger.LogWarning($"Запросили раписание для агента по NextRun и вернулся пустой список! Такого не должно быть! " + logger.LogWarning($"Запросили раписание для агента по NextRun и вернулся пустой список! Такого не должно быть! " +
$"ApplicationInWorkId: {template.ApplicationInWorkId}, latRun: {template.LastRun}, NextRun: {template.NextRun}, ip: {ip}, date: {date}"); $"JobGroupId: {template.Job.GroupId}, latRun: {template.LastRun}, NextRun: {template.NextRun}, ip: {ip}, date: {date}");
continue; continue;
} }
if (string.IsNullOrEmpty(template.ApplicationsInWork.AgentName) && string.IsNullOrEmpty(template.ApplicationsInWork.AgentScript)) if (string.IsNullOrEmpty(template.Job.Group!.AgentName) && string.IsNullOrEmpty(template.Job.Group!.AgentScript))
{ {
logger.LogWarning($"Запросили задание для агента с пустыми значениями AgentName && AgentScript. Такого не должно быть! " + logger.LogWarning($"Запросили задание для агента с пустыми значениями AgentName && AgentScript. Такого не должно быть! " +
$"ApplicationInWorkId: {template.ApplicationInWorkId}, AgentName: {template.ApplicationsInWork.AgentName}, AgentScript: {template.ApplicationsInWork.AgentScript} , ip: {ip}, date: {date}"); $"JobGroupId: {template.Job.GroupId}, AgentName: {template.Job.Group.AgentName}, AgentScript: {template.Job.Group.AgentScript} , ip: {ip}, date: {date}");
continue; continue;
} }
templateSchedule.ForEach(item => response.Scheduled.Add(new AgentTaskMinScheduleResponse templateSchedule.ForEach(item => response.Scheduled.Add(new AgentTaskMinScheduleResponse
{ {
Name = template.ApplicationsInWork!.AgentName ?? "", Name = template.Job.Group.AgentName ?? "",
Script = template.ApplicationsInWork!.AgentScript ?? "", Script = template.Job.Group.AgentScript ?? "",
StartAt = item, StartAt = item,
TemplateId = template.Id TemplateId = template.Id
})); }));

View File

@@ -62,53 +62,53 @@ namespace PARR.API.Controllers.V1
/// Получить список заданий на выполнение работ(ApplicationInWork) постранично /// Получить список заданий на выполнение работ(ApplicationInWork) постранично
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpGet(ApiRoutes.Job.GetAll)] //[HttpGet(ApiRoutes.Job.GetAll)]
public async Task<IActionResult> GetAll([FromQuery] PaginationQuery paginationQuery, [FromQuery] ApplicationInWorkQuery filter) //public async Task<IActionResult> GetAll([FromQuery] PaginationQuery paginationQuery, [FromQuery] ApplicationInWorkQuery filter)
{ //{
var paginationFilter = mapper.Map<PaginationFilter>(paginationQuery); // var paginationFilter = mapper.Map<PaginationFilter>(paginationQuery);
IQueryable<ApplicationsInWork> query = applicationsInWorkService.Get().Include(t => t.Application).ThenInclude(t => t!.ApplicationType); // IQueryable<ApplicationsInWork> query = applicationsInWorkService.Get().Include(t => t.Application).ThenInclude(t => t!.ApplicationType);
if (filter.IsLight != true) // if (filter.IsLight != true)
{ // {
query = query // query = query
.Include(t => t.Work) // .Include(t => t.Work)
//.Include(t => t.Templates) - большой запрос, делаем его отдельно // //.Include(t => t.Templates) - большой запрос, делаем его отдельно
.Include(t => t.WorkGroups).ThenInclude(t => t.WorkGroup) // .Include(t => t.WorkGroups).ThenInclude(t => t.WorkGroup)
.Include(t => t.JobAutoControl); // .Include(t => t.JobAutoControl);
} // }
query = query.OrderBy(t => t.ShortDescription).ThenBy(t => t.Application!.Name); // query = query.OrderBy(t => t.ShortDescription).ThenBy(t => t.Application!.Name);
if (!string.IsNullOrEmpty(filter.ShortDescription)) // if (!string.IsNullOrEmpty(filter.ShortDescription))
query = query.Where(t => t.ShortDescription.ToLower().Contains(filter.ShortDescription.ToLower())); // query = query.Where(t => t.ShortDescription.ToLower().Contains(filter.ShortDescription.ToLower()));
if (filter.WorkId.HasValue) // if (filter.WorkId.HasValue)
query = query.Where(t => t.WorkId == filter.WorkId.Value); // query = query.Where(t => t.WorkId == filter.WorkId.Value);
var appInWorks = await applicationsInWorkService.GetPage(query, paginationFilter).ToListAsync(); // var appInWorks = await applicationsInWorkService.GetPage(query, paginationFilter).ToListAsync();
if (!appInWorks.Any()) // if (!appInWorks.Any())
return NoContent(); // return NoContent();
var response = mapper.Map<List<ApplicationInWorkResponse>>(appInWorks); // var response = mapper.Map<List<ApplicationInWorkResponse>>(appInWorks);//TODO Migration to job
if (filter.IsLight != true) // if (filter.IsLight != true)
{ // {
//Если запрос не легкий, загружаем кол-во шаблонов отдельно, это значительно ускоряет запрос // //Если запрос не легкий, загружаем кол-во шаблонов отдельно, это значительно ускоряет запрос
foreach (var item in response) // foreach (var item in response)
{ // {
item.TemplatesCount = await templateService.Get().CountAsync(t => t.ApplicationInWorkId == item.Id); // item.TemplatesCount = await templateService.Get().CountAsync(t => t.JobId == item.Id);
var statistics = await GetStatisticsAsync(item.Id); // var statistics = await GetStatisticsAsync(item.Id);
BindStatistics(item, statistics); // BindStatistics(item, statistics);
} // }
} // }
var paginationResponse = new PagedResponse<ApplicationInWorkResponse>(response, true).GetPaginatedProps(paginationFilter, query); // var paginationResponse = new PagedResponse<ApplicationInWorkResponse>(response, true).GetPaginatedProps(paginationFilter, query);
return Ok(paginationResponse); // return Ok(paginationResponse);
} //}
/// <summary> /// <summary>
@@ -116,28 +116,28 @@ namespace PARR.API.Controllers.V1
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet(ApiRoutes.Job.Get)] //[HttpGet(ApiRoutes.Job.Get)]
public async Task<IActionResult> GetById([FromRoute] Guid id) //public async Task<IActionResult> GetById([FromRoute] Guid id)
{ //{
var applicationInWork = await applicationsInWorkService.Get() // var applicationInWork = await applicationsInWorkService.Get()
.Include(t => t.Application).ThenInclude(t => t!.ApplicationType) // .Include(t => t.Application).ThenInclude(t => t!.ApplicationType)
.Include(t => t.Work) // .Include(t => t.Work)
//.Include(t => t.Templates) // //.Include(t => t.Templates)
.Include(t => t.WorkGroups).ThenInclude(t => t.WorkGroup) // .Include(t => t.WorkGroups).ThenInclude(t => t.WorkGroup)
.Include(t => t.JobAutoControl) // .Include(t => t.JobAutoControl)
.FirstOrDefaultAsync(t => t.Id == id); // .FirstOrDefaultAsync(t => t.Id == id);
if (applicationInWork == null) // if (applicationInWork == null)
return NotFound(); // return NotFound();
var response = mapper.Map<ApplicationInWorkResponse>(applicationInWork); // var response = mapper.Map<ApplicationInWorkResponse>(applicationInWork);
response.TemplatesCount = await templateService.Get().CountAsync(t => t.ApplicationInWorkId == id); // response.TemplatesCount = await templateService.Get().CountAsync(t => t.ApplicationInWorkId == id);
var statistics = await GetStatisticsAsync(response.Id); // var statistics = await GetStatisticsAsync(response.Id);
BindStatistics(response, statistics); // BindStatistics(response, statistics);
return Ok(new Response<ApplicationInWorkResponse>(response, true)); // return Ok(new Response<ApplicationInWorkResponse>(response, true));
} //}
/// <summary> /// <summary>
@@ -145,80 +145,80 @@ namespace PARR.API.Controllers.V1
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="request"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost(ApiRoutes.Job.Create)] //[HttpPost(ApiRoutes.Job.Create)]
public async Task<IActionResult> Create([FromBody] ApplicationInWorkRequest request) //public async Task<IActionResult> Create([FromBody] ApplicationInWorkRequest request)
{ //{
var resultValidate = await validator.ValidateAsync(request); // var resultValidate = await validator.ValidateAsync(request);
if (!resultValidate.IsValid) // if (!resultValidate.IsValid)
return BadRequest(new Response(resultValidate.Errors)); // return BadRequest(new Response(resultValidate.Errors));
//уникальная запись по полям ApplicationId, WorkId // //уникальная запись по полям ApplicationId, WorkId
var existSameAiW = await applicationsInWorkService.GetAsync(request.ApplicationId, request.WorkId); // var existSameAiW = await applicationsInWorkService.GetAsync(request.ApplicationId, request.WorkId);
if (existSameAiW != null) // if (existSameAiW != null)
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Задание на выполнение работ с такими ПО и работой уже существует" } })); // return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Задание на выполнение работ с такими ПО и работой уже существует" } }));
var applicationInWork = new ApplicationsInWork // var applicationInWork = new ApplicationsInWork
{ // {
Id = Guid.NewGuid(), // Id = Guid.NewGuid(),
WorkId = request.WorkId, // WorkId = request.WorkId,
ApplicationId = request.ApplicationId, // ApplicationId = request.ApplicationId,
TemplateDuration = request.TemplateDuration, // TemplateDuration = request.TemplateDuration,
ShortDescription = request.ShortDescription.Trim(), // ShortDescription = request.ShortDescription.Trim(),
FullDescription = request.FullDescription.Trim(), // FullDescription = request.FullDescription.Trim(),
Solution = request.Solution.Trim(), // Solution = request.Solution.Trim(),
//NextRun = request.NextRun, // //NextRun = request.NextRun,
IsAutoDistributionEnabled = request.IsAutoDistributionEnabled, // IsAutoDistributionEnabled = request.IsAutoDistributionEnabled,
ReferenceDate = request.ReferenceDate, // ReferenceDate = request.ReferenceDate,
IsAgent = request.IsAgent, // IsAgent = request.IsAgent,
AgentName = request.AgentName?.Trim(), // AgentName = request.AgentName?.Trim(),
AgentTimeOutSec = request.AgentTimeOutSec, // AgentTimeOutSec = request.AgentTimeOutSec,
AgentScript = request.AgentScript?.Trim() // AgentScript = request.AgentScript?.Trim()
}; // };
//Добавляем настройки планировщика // //Добавляем настройки планировщика
request.Schedule.ForEach(item => // request.Schedule.ForEach(item =>
{ // {
applicationInWork.EsppSchValues.Add(new EsppSchValue // applicationInWork.EsppSchValues.Add(new EsppSchValue
{ // {
ApplicationsInWorkId = applicationInWork.Id, // ApplicationsInWorkId = applicationInWork.Id,
TypeConfigId = item.TypeConfigId, // TypeConfigId = item.TypeConfigId,
TypeValueId = item.TypeValueId // TypeValueId = item.TypeValueId
}); // });
}); // });
//Добавляем рабочие группы // //Добавляем рабочие группы
request.WorkGroups.ForEach(workGroupId => // request.WorkGroups.ForEach(workGroupId =>
{ // {
applicationInWork.WorkGroups.Add(new AppInWorkInWorkGroup // applicationInWork.WorkGroups.Add(new AppInWorkInWorkGroup
{ // {
ApplicationsInWorkId = applicationInWork.Id, // ApplicationsInWorkId = applicationInWork.Id,
WorkGroupId = workGroupId // WorkGroupId = workGroupId
}); // });
}); // });
if (!await applicationsInWorkService.CreateAsync(applicationInWork) || !await applicationsInWorkService.CommitAsync()) // if (!await applicationsInWorkService.CreateAsync(applicationInWork) || !await applicationsInWorkService.CommitAsync())
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Ошибка при созании задания на выполнение работ" } })); // return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Ошибка при созании задания на выполнение работ" } }));
logger.LogInformation($"Пользователь {User.Identity?.Name} добавил задание на выполнение работ: {applicationInWork.Id}, {applicationInWork.ShortDescription}, {applicationInWork.Solution}"); // logger.LogInformation($"Пользователь {User.Identity?.Name} добавил задание на выполнение работ: {applicationInWork.Id}, {applicationInWork.ShortDescription}, {applicationInWork.Solution}");
var createdApplicationInWork = await applicationsInWorkService.Get() // var createdApplicationInWork = await applicationsInWorkService.Get()
.Include(t => t.Application).ThenInclude(t => t!.ApplicationType) // .Include(t => t.Application).ThenInclude(t => t!.ApplicationType)
.Include(t => t.Work) // .Include(t => t.Work)
//.Include(t => t.Templates) // //.Include(t => t.Templates)
.Include(t => t.WorkGroups).ThenInclude(t => t.WorkGroup) // .Include(t => t.WorkGroups).ThenInclude(t => t.WorkGroup)
.Include(t => t.JobAutoControl) // .Include(t => t.JobAutoControl)
.FirstAsync(t => t.Id == applicationInWork.Id); // .FirstAsync(t => t.Id == applicationInWork.Id);
var locationUri = uriService.GetUri(ApiRoutes.Job.Get, ApiRoutes.Job.getParam, createdApplicationInWork.Id); // var locationUri = uriService.GetUri(ApiRoutes.Job.Get, ApiRoutes.Job.getParam, createdApplicationInWork.Id);
var response = mapper.Map<ApplicationInWorkResponse>(createdApplicationInWork); // var response = mapper.Map<ApplicationInWorkResponse>(createdApplicationInWork);
// так как мы только что создали AppInW, то у него нет шаблонов, смело ставим = 0 (ускоряем запрос) // // так как мы только что создали AppInW, то у него нет шаблонов, смело ставим = 0 (ускоряем запрос)
response.TemplatesCount = 0; // response.TemplatesCount = 0;
return Created(locationUri, new Response<ApplicationInWorkResponse>(response, true)); // return Created(locationUri, new Response<ApplicationInWorkResponse>(response, true));
} //}
/// <summary> /// <summary>
@@ -227,114 +227,114 @@ namespace PARR.API.Controllers.V1
/// <param name="id"></param> /// <param name="id"></param>
/// <param name="request"></param> /// <param name="request"></param>
/// <returns></returns> /// <returns></returns>
[HttpPut(ApiRoutes.Job.Update)] //[HttpPut(ApiRoutes.Job.Update)]
public async Task<IActionResult> Update([FromRoute] Guid id, [FromBody] ApplicationInWorkRequest request) //public async Task<IActionResult> Update([FromRoute] Guid id, [FromBody] ApplicationInWorkRequest request)
{ //{
var resultValidate = await validator.ValidateAsync(request); // var resultValidate = await validator.ValidateAsync(request);
if (!resultValidate.IsValid) // if (!resultValidate.IsValid)
return BadRequest(new Response(resultValidate.Errors)); // return BadRequest(new Response(resultValidate.Errors));
//уникальная запись по полям ApplicationId, WorkId у которой id!=[FromRoute]id // //уникальная запись по полям ApplicationId, WorkId у которой id!=[FromRoute]id
var existSameAiW = await applicationsInWorkService.Get() // var existSameAiW = await applicationsInWorkService.Get()
.FirstOrDefaultAsync(t => t.Id != id && t.ApplicationId == request.ApplicationId && t.WorkId == request.WorkId); // .FirstOrDefaultAsync(t => t.Id != id && t.ApplicationId == request.ApplicationId && t.WorkId == request.WorkId);
if (existSameAiW != null) // if (existSameAiW != null)
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Задание на выполнение работ с такими ПО и работой уже существует" } })); // return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Задание на выполнение работ с такими ПО и работой уже существует" } }));
var orig = await applicationsInWorkService.Get() // var orig = await applicationsInWorkService.Get()
.Include(t => t.WorkGroups) // .Include(t => t.WorkGroups)
.Include(t => t.EsppSchValues) // .Include(t => t.EsppSchValues)
.FirstOrDefaultAsync(t => t.Id == id); // .FirstOrDefaultAsync(t => t.Id == id);
if (orig == null) // if (orig == null)
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = $"Ошибка при изменении задания на выполнение работ. Не найдено задание с Id: {id}" } })); // return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = $"Ошибка при изменении задания на выполнение работ. Не найдено задание с Id: {id}" } }));
//Расписание было изменено, ниже добавим задание в очередь на обновление расписаний у связанных шаблонов // //Расписание было изменено, ниже добавим задание в очередь на обновление расписаний у связанных шаблонов
var isScheduleChanged = IsScheduleChanged(orig, request); // var isScheduleChanged = IsScheduleChanged(orig, request);
orig.WorkId = request.WorkId; // orig.WorkId = request.WorkId;
orig.ApplicationId = request.ApplicationId; // orig.ApplicationId = request.ApplicationId;
orig.TemplateDuration = request.TemplateDuration; // orig.TemplateDuration = request.TemplateDuration;
orig.ShortDescription = request.ShortDescription.Trim(); // orig.ShortDescription = request.ShortDescription.Trim();
orig.FullDescription = request.FullDescription.Trim(); // orig.FullDescription = request.FullDescription.Trim();
orig.Solution = request.Solution.Trim(); // orig.Solution = request.Solution.Trim();
//orig.NextRun = request.NextRun; // //orig.NextRun = request.NextRun;
orig.ReferenceDate = request.ReferenceDate; // orig.ReferenceDate = request.ReferenceDate;
orig.IsAutoDistributionEnabled = request.IsAutoDistributionEnabled; // orig.IsAutoDistributionEnabled = request.IsAutoDistributionEnabled;
orig.IsAgent = request.IsAgent; // orig.IsAgent = request.IsAgent;
orig.AgentName = request.AgentName?.Trim(); // orig.AgentName = request.AgentName?.Trim();
orig.AgentTimeOutSec = request.AgentTimeOutSec; // orig.AgentTimeOutSec = request.AgentTimeOutSec;
orig.AgentScript = request.AgentScript?.Trim(); // orig.AgentScript = request.AgentScript?.Trim();
orig.DateModified = DateTimeOffset.UtcNow; // orig.DateModified = DateTimeOffset.UtcNow;
//обновляем планировщик // //обновляем планировщик
orig.EsppSchValues.Clear(); // orig.EsppSchValues.Clear();
request.Schedule.ForEach(item => // request.Schedule.ForEach(item =>
{ // {
orig.EsppSchValues.Add(new EsppSchValue // orig.EsppSchValues.Add(new EsppSchValue
{ // {
ApplicationsInWorkId = orig.Id, // ApplicationsInWorkId = orig.Id,
TypeConfigId = item.TypeConfigId, // TypeConfigId = item.TypeConfigId,
TypeValueId = item.TypeValueId // TypeValueId = item.TypeValueId
}); // });
}); // });
//Обновляем рабочие группы // //Обновляем рабочие группы
orig.WorkGroups.Clear(); // orig.WorkGroups.Clear();
request.WorkGroups.ForEach(workGroupId => // request.WorkGroups.ForEach(workGroupId =>
{ // {
orig.WorkGroups.Add(new AppInWorkInWorkGroup // orig.WorkGroups.Add(new AppInWorkInWorkGroup
{ // {
ApplicationsInWorkId = orig.Id, // ApplicationsInWorkId = orig.Id,
WorkGroupId = workGroupId // WorkGroupId = workGroupId
}); // });
}); // });
if (!await applicationsInWorkService.CommitAsync()) // if (!await applicationsInWorkService.CommitAsync())
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Ошибка при изменении задания на выполнение работ." } })); // return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Ошибка при изменении задания на выполнение работ." } }));
logger.LogInformation($"Пользователь {User.Identity?.Name} обновил задание на выполнение работ: {orig.Id}," + // logger.LogInformation($"Пользователь {User.Identity?.Name} обновил задание на выполнение работ: {orig.Id}," +
$" {orig.WorkId}, {orig.ApplicationId}, {orig.TemplateDuration}, {orig.ShortDescription}," + // $" {orig.WorkId}, {orig.ApplicationId}, {orig.TemplateDuration}, {orig.ShortDescription}," +
$" {orig.FullDescription}, {orig.Solution}, {nameof(orig.IsAutoDistributionEnabled)}: {orig.IsAutoDistributionEnabled}, {orig.IsAgent}, {orig.AgentName}, {orig.AgentTimeOutSec}, {orig.AgentScript}"); // $" {orig.FullDescription}, {orig.Solution}, {nameof(orig.IsAutoDistributionEnabled)}: {orig.IsAutoDistributionEnabled}, {orig.IsAgent}, {orig.AgentName}, {orig.AgentTimeOutSec}, {orig.AgentScript}");
if (isScheduleChanged) // if (isScheduleChanged)
{ // {
//расписание было обновлено, отправим задание в очередь на перерасчет NextRun // //расписание было обновлено, отправим задание в очередь на перерасчет NextRun
var requestToMq = new TemplateDistributorMq // var requestToMq = new TemplateDistributorMq
{ // {
ApplicationInWorkId = id // ApplicationInWorkId = id
}; // };
var msg = JsonSerializer.Serialize(requestToMq); // var msg = JsonSerializer.Serialize(requestToMq);
logger.LogDebug($"Расписание в РР applicationInWorkId: {id} было изменено. Отправляем задание в очередь на перерасчет NextRun"); // logger.LogDebug($"Расписание в РР applicationInWorkId: {id} было изменено. Отправляем задание в очередь на перерасчет NextRun");
var sendResult = mqService.Send(mqSettings.TemplateDistributor, new[] { msg }); // var sendResult = mqService.Send(mqSettings.TemplateDistributor, new[] { msg });
if (sendResult.IsSuccess) // if (sendResult.IsSuccess)
logger.LogInformation($"Задание на перерасчет NextRun успешно отправлено в очередь MQ {mqSettings.TemplateDistributor.QueueName}"); // logger.LogInformation($"Задание на перерасчет NextRun успешно отправлено в очередь MQ {mqSettings.TemplateDistributor.QueueName}");
else // else
logger.LogError($"Ошибка при отправке задания на перерасчет NextRun в очередь MQ {mqSettings.TemplateDistributor.QueueName}"); // logger.LogError($"Ошибка при отправке задания на перерасчет NextRun в очередь MQ {mqSettings.TemplateDistributor.QueueName}");
} // }
var updatedApplicationInWork = await applicationsInWorkService.Get() // var updatedApplicationInWork = await applicationsInWorkService.Get()
.Include(t => t.Application).ThenInclude(t => t!.ApplicationType) // .Include(t => t.Application).ThenInclude(t => t!.ApplicationType)
.Include(t => t.Work) // .Include(t => t.Work)
//.Include(t => t.Templates) // //.Include(t => t.Templates)
.Include(t => t.WorkGroups).ThenInclude(t => t.WorkGroup) // .Include(t => t.WorkGroups).ThenInclude(t => t.WorkGroup)
.Include(t => t.JobAutoControl) // .Include(t => t.JobAutoControl)
.FirstAsync(t => t.Id == orig.Id); // .FirstAsync(t => t.Id == orig.Id);
var response = mapper.Map<ApplicationInWorkResponse>(updatedApplicationInWork); // var response = mapper.Map<ApplicationInWorkResponse>(updatedApplicationInWork);
response.TemplatesCount = await templateService.Get().CountAsync(t => t.ApplicationInWorkId == id); // response.TemplatesCount = await templateService.Get().CountAsync(t => t.ApplicationInWorkId == id);
var statistics = await GetStatisticsAsync(response.Id); // var statistics = await GetStatisticsAsync(response.Id);
BindStatistics(response, statistics); // BindStatistics(response, statistics);
return Ok(new Response<ApplicationInWorkResponse>(response, true)); // return Ok(new Response<ApplicationInWorkResponse>(response, true));
} //}
/// <summary> /// <summary>
@@ -342,38 +342,38 @@ namespace PARR.API.Controllers.V1
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
[HttpDelete(ApiRoutes.Job.Delete)] //[HttpDelete(ApiRoutes.Job.Delete)]
public async Task<IActionResult> Delete([FromRoute] Guid id) //public async Task<IActionResult> Delete([FromRoute] Guid id)
{ //{
var applicationsInWork = await applicationsInWorkService.Get() // var applicationsInWork = await applicationsInWorkService.Get()
//.Include(t => t.Templates) // //.Include(t => t.Templates)
.FirstOrDefaultAsync(t => t.Id == id); // .FirstOrDefaultAsync(t => t.Id == id);
if (applicationsInWork == null) // if (applicationsInWork == null)
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { // return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel {
Message = $"Ошибка при удалении задания на выполнение работ. Не найдено задание на выполнение работ Id: {id}" // Message = $"Ошибка при удалении задания на выполнение работ. Не найдено задание на выполнение работ Id: {id}"
} })); // } }));
var templateCount = await templateService.Get().CountAsync(t => t.ApplicationInWorkId == id); // var templateCount = await templateService.Get().CountAsync(t => t.ApplicationInWorkId == id);
//if (applicationsInWork.Templates.Any()) // //if (applicationsInWork.Templates.Any())
if (templateCount > 0) // if (templateCount > 0)
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { // return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel {
Message = $"Ошибка при удалении задания на выполнение работ. С данным заданием связаны шаблоны: {templateCount} шт." // Message = $"Ошибка при удалении задания на выполнение работ. С данным заданием связаны шаблоны: {templateCount} шт."
} })); // } }));
if (!applicationsInWorkService.Delete(applicationsInWork) || !await applicationsInWorkService.CommitAsync()) // if (!applicationsInWorkService.Delete(applicationsInWork) || !await applicationsInWorkService.CommitAsync())
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { // return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel {
Message = $"Ошибка при удалении задания на выполнение работ" // Message = $"Ошибка при удалении задания на выполнение работ"
} })); // } }));
logger.LogInformation($"Пользователь {User.Identity?.Name} удалил задание на выполнение работ: {applicationsInWork.Id},{applicationsInWork.WorkId}," + // logger.LogInformation($"Пользователь {User.Identity?.Name} удалил задание на выполнение работ: {applicationsInWork.Id},{applicationsInWork.WorkId}," +
$" {applicationsInWork.ApplicationId}, {applicationsInWork.TemplateDuration}, {applicationsInWork.ShortDescription}," + // $" {applicationsInWork.ApplicationId}, {applicationsInWork.TemplateDuration}, {applicationsInWork.ShortDescription}," +
$" {applicationsInWork.FullDescription}, {applicationsInWork.Solution}, {nameof(applicationsInWork.IsAutoDistributionEnabled)}: {applicationsInWork.IsAutoDistributionEnabled}, {applicationsInWork.IsAgent}," + // $" {applicationsInWork.FullDescription}, {applicationsInWork.Solution}, {nameof(applicationsInWork.IsAutoDistributionEnabled)}: {applicationsInWork.IsAutoDistributionEnabled}, {applicationsInWork.IsAgent}," +
$" {applicationsInWork.AgentName}, {applicationsInWork.AgentTimeOutSec}, {applicationsInWork.AgentScript}"); // $" {applicationsInWork.AgentName}, {applicationsInWork.AgentTimeOutSec}, {applicationsInWork.AgentScript}");
return NoContent(); // return NoContent();
} //}
/// <summary> /// <summary>
@@ -382,31 +382,31 @@ namespace PARR.API.Controllers.V1
/// <param name="orig"></param> /// <param name="orig"></param>
/// <param name="request"></param> /// <param name="request"></param>
/// <returns></returns> /// <returns></returns>
private bool IsScheduleChanged(ApplicationsInWork orig, ApplicationInWorkRequest request) //private bool IsScheduleChanged(ApplicationsInWork orig, ApplicationInWorkRequest request)
{ //{
var isScheduleChanged = false; // var isScheduleChanged = false;
if (orig.ReferenceDate != request.ReferenceDate) // if (orig.ReferenceDate != request.ReferenceDate)
isScheduleChanged = true; // isScheduleChanged = true;
if (request.Schedule.Count() != orig.EsppSchValues.Count()) // if (request.Schedule.Count() != orig.EsppSchValues.Count())
isScheduleChanged = true; // isScheduleChanged = true;
if (request.IsAutoDistributionEnabled != orig.IsAutoDistributionEnabled) // if (request.IsAutoDistributionEnabled != orig.IsAutoDistributionEnabled)
isScheduleChanged = true; // isScheduleChanged = true;
request.Schedule.ForEach(requestSchedule => // request.Schedule.ForEach(requestSchedule =>
{ // {
var schExist = orig.EsppSchValues.FirstOrDefault(t => t.ApplicationsInWorkId == orig.Id // var schExist = orig.EsppSchValues.FirstOrDefault(t => t.ApplicationsInWorkId == orig.Id
&& t.TypeValueId == requestSchedule.TypeValueId // && t.TypeValueId == requestSchedule.TypeValueId
&& t.TypeConfigId == requestSchedule.TypeConfigId); // && t.TypeConfigId == requestSchedule.TypeConfigId);
if (schExist == null) // if (schExist == null)
isScheduleChanged = true; // isScheduleChanged = true;
}); // });
return isScheduleChanged; // return isScheduleChanged;
} //}
/// <summary> /// <summary>
@@ -414,28 +414,28 @@ namespace PARR.API.Controllers.V1
/// </summary> /// </summary>
/// <param name="applicationInWorkId"></param> /// <param name="applicationInWorkId"></param>
/// <returns></returns> /// <returns></returns>
private async Task<AppInWorkStatModel> GetStatisticsAsync(Guid applicationInWorkId) //private async Task<AppInWorkStatModel> GetStatisticsAsync(Guid applicationInWorkId)
{ //{
var statResult = await applicationsInWorkService.Get() // var statResult = await applicationsInWorkService.Get()
.Include(t => t.Templates).ThenInclude(t => t.RobotConfigurations) // .Include(t => t.Templates).ThenInclude(t => t.RobotConfigurations)
.Where(x => x.Id == applicationInWorkId) // .Where(x => x.Id == applicationInWorkId)
.Select(t => new // .Select(t => new
{ // {
TemplateActivated = t.Templates.Count(x => x.IsActiveTemplate), // TemplateActivated = t.Templates.Count(x => x.IsActiveTemplate),
TemplateSynchronized = t.Templates.Count(x => x.RobotConfigurations.Any(c => c.TaskStatusCode == (int)TaskStatusEnum.Ok && c.RobotCode == (int)RobotsEnum.TemplateOrder)), // TemplateSynchronized = t.Templates.Count(x => x.RobotConfigurations.Any(c => c.TaskStatusCode == (int)TaskStatusEnum.Ok && c.RobotCode == (int)RobotsEnum.TemplateOrder)),
TemplateErrors = t.Templates.Count(x => x.RobotConfigurations.Any(c => c.RobotStatusCode == (int)RobotStatusEnum.Error && c.RobotCode == (int)RobotsEnum.TemplateOrder)), // TemplateErrors = t.Templates.Count(x => x.RobotConfigurations.Any(c => c.RobotStatusCode == (int)RobotStatusEnum.Error && c.RobotCode == (int)RobotsEnum.TemplateOrder)),
ScheduleActivated = t.Templates.Count(x => x.IsActiveSchedule), // ScheduleActivated = t.Templates.Count(x => x.IsActiveSchedule),
ScheduleSynchronized = t.Templates.Count(x => x.RobotConfigurations.Any(c => c.TaskStatusCode == (int)TaskStatusEnum.Ok && c.RobotCode == (int)RobotsEnum.ScheduleOrder)), // ScheduleSynchronized = t.Templates.Count(x => x.RobotConfigurations.Any(c => c.TaskStatusCode == (int)TaskStatusEnum.Ok && c.RobotCode == (int)RobotsEnum.ScheduleOrder)),
ScheduleErrors = t.Templates.Count(x => x.RobotConfigurations.Any(c => c.RobotStatusCode == (int)RobotStatusEnum.Error && c.RobotCode == (int)RobotsEnum.ScheduleOrder)) // ScheduleErrors = t.Templates.Count(x => x.RobotConfigurations.Any(c => c.RobotStatusCode == (int)RobotStatusEnum.Error && c.RobotCode == (int)RobotsEnum.ScheduleOrder))
}).FirstOrDefaultAsync(); // }).FirstOrDefaultAsync();
return new AppInWorkStatModel // return new AppInWorkStatModel
{ // {
ScheduleStatistics = new ScheduleStats { Activated = statResult?.ScheduleActivated ?? 0, Errors = statResult?.ScheduleErrors ?? 0, Synchronized = statResult?.ScheduleSynchronized ?? 0 }, // ScheduleStatistics = new ScheduleStats { Activated = statResult?.ScheduleActivated ?? 0, Errors = statResult?.ScheduleErrors ?? 0, Synchronized = statResult?.ScheduleSynchronized ?? 0 },
TemplateStatistics = new TemplateStats { Activated = statResult?.TemplateActivated ?? 0, Errors = statResult?.TemplateErrors ?? 0, Synchronized = statResult?.TemplateSynchronized ?? 0 } // TemplateStatistics = new TemplateStats { Activated = statResult?.TemplateActivated ?? 0, Errors = statResult?.TemplateErrors ?? 0, Synchronized = statResult?.TemplateSynchronized ?? 0 }
}; // };
} //}
private void BindStatistics(ApplicationInWorkResponse applicationsInWork, AppInWorkStatModel statistics) private void BindStatistics(ApplicationInWorkResponse applicationsInWork, AppInWorkStatModel statistics)

View File

@@ -71,11 +71,11 @@ namespace PARR.API.Controllers.V1
case RobotsEnum.TemplateOrder: case RobotsEnum.TemplateOrder:
// шаблоны // шаблоны
query = query.Include(t => t.Template) query = query.Include(t => t.Template)
.ThenInclude(t => t!.Host).ThenInclude(t => t!.ResponseArea) .ThenInclude(t => t!.Unit)
.ThenInclude(t => t!.Hosts).ThenInclude(t => t.WorkGroup).ThenInclude(t => t!.ResponseArea) //.ThenInclude(t => t!.Hosts).ThenInclude(t => t.WorkGroup).ThenInclude(t => t!.ResponseArea)
.Include(t => t.Template) .Include(t => t.Template)
.ThenInclude(a => a!.ApplicationsInWork) .ThenInclude(a => a!.Job)
.ThenInclude(w => w!.Work) //.ThenInclude(w => w!.Work)
.ThenInclude(t => t!.Tnk) .ThenInclude(t => t!.Tnk)
.ThenInclude(s => s!.Subprocess) .ThenInclude(s => s!.Subprocess)
.ThenInclude(p => p!.Process); .ThenInclude(p => p!.Process);
@@ -84,10 +84,12 @@ namespace PARR.API.Controllers.V1
//расписание //расписание
// тут не делаем AsSplitQuery, не может подтянуть все таблицы // тут не делаем AsSplitQuery, не может подтянуть все таблицы
query = query.Include(t => t.Template) query = query.Include(t => t.Template)
.ThenInclude(t => t!.Host).ThenInclude(t => t!.ResponseArea) .ThenInclude(t => t!.Unit)//.ThenInclude(t => t!.ResponseArea)
.ThenInclude(t => t!.Hosts).ThenInclude(t => t.WorkGroup) //.ThenInclude(t => t!.Hosts).ThenInclude(t => t.WorkGroup)
.Include(t => t.Template) .Include(t => t.Template)
.ThenInclude(t => t!.ApplicationsInWork) .ThenInclude(t => t!.Job)
.ThenInclude(t => t!.Group)
//.ThenInclude(t => t!.ApplicationsInWork)
.ThenInclude(t => t!.EsppSchValues) .ThenInclude(t => t!.EsppSchValues)
.ThenInclude(t => t!.EsppSchTypeConfig) .ThenInclude(t => t!.EsppSchTypeConfig)
.ThenInclude(t => t!.EsppSchTypeSchedule); .ThenInclude(t => t!.EsppSchTypeSchedule);
@@ -169,7 +171,7 @@ namespace PARR.API.Controllers.V1
// передаем LastRun, если его нет, то NextRun // передаем LastRun, если его нет, то NextRun
//var nextRun = await esppScheduleTransformService.GetNextDateAsync(task.Template!.ApplicationInWorkId, task.Template.ApplicationsInWork!.LastRun ?? task.Template.ApplicationsInWork.NextRun); //var nextRun = await esppScheduleTransformService.GetNextDateAsync(task.Template!.ApplicationInWorkId, task.Template.ApplicationsInWork!.LastRun ?? task.Template.ApplicationsInWork.NextRun);
// всегда считаем по nextRun // всегда считаем по nextRun
var nextRun = await esppScheduleTransformService.GetNextDateAsync(template.ApplicationInWorkId, template.NextRun); var nextRun = await esppScheduleTransformService.GetNextDateAsync(template.Job!.GroupId, template.NextRun);
if (nextRun != template.NextRun) if (nextRun != template.NextRun)
{ {

View File

@@ -9,6 +9,7 @@ using PARR.API.Controllers.V1.Base;
using PARR.BLL.Services.Interfaces; using PARR.BLL.Services.Interfaces;
using PARR.Constants; using PARR.Constants;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Unit;
namespace PARR.API.Controllers.V1.Statistics namespace PARR.API.Controllers.V1.Statistics
{ {
@@ -19,11 +20,17 @@ namespace PARR.API.Controllers.V1.Statistics
public class StatHostController : BaseApiController public class StatHostController : BaseApiController
{ {
private readonly IHostService hostService; private readonly IHostService hostService;
private readonly IUnitService unitService;
private readonly ICalendarService calendarService; private readonly ICalendarService calendarService;
public StatHostController(IHostService hostService, ICalendarService calendarService) public StatHostController(
IHostService hostService,
IUnitService unitService,
ICalendarService calendarService
)
{ {
this.hostService = hostService; this.hostService = hostService;
this.unitService = unitService;
this.calendarService = calendarService; this.calendarService = calendarService;
} }
@@ -103,8 +110,8 @@ namespace PARR.API.Controllers.V1.Statistics
var response = new StatHostTemplateResponse var response = new StatHostTemplateResponse
{ {
AllHosts = await hostService.Get().CountAsync(), AllUnits = await unitService.Get().CountAsync(),
HostsInTemplates = await hostService.Get().Include(t => t.Templates).CountAsync(t => t.Templates.Any()) HostsInTemplates = await unitService.Get().Include(t => t.Templates).CountAsync(t => t.Templates.Any())
}; };
return Ok(new Response<StatHostTemplateResponse>(response, true)); return Ok(new Response<StatHostTemplateResponse>(response, true));

View File

@@ -40,88 +40,88 @@ namespace PARR.API.Controllers.V1.Statistics
} }
/// <summary> ///// <summary>
/// Статистика загрузки РР по всем ЗО ///// Статистика загрузки РР по всем ЗО
/// </summary> ///// </summary>
/// <returns></returns> ///// <returns></returns>
[HttpGet(ApiRoutes.StatResponseAreaWorkLoad.GetAll)] //[HttpGet(ApiRoutes.StatResponseAreaWorkLoad.GetAll)]
public async Task<IActionResult> GetAll([FromQuery] WorkloadBaseQuery requestQuery) //public async Task<IActionResult> GetAll([FromQuery] WorkloadBaseQuery requestQuery)
{ //{
var response = await GetStatisticsAsync(requestQuery); // var response = await GetStatisticsAsync(requestQuery);
return Ok(new Response<List<StatResponseAreaWorkLoadResponse>>(response, true)); // return Ok(new Response<List<StatResponseAreaWorkLoadResponse>>(response, true));
} //}
/// <summary> ///// <summary>
/// Статистика загрузки РР по списку ЗО ///// Статистика загрузки РР по списку ЗО
/// </summary> ///// </summary>
/// <returns></returns> ///// <returns></returns>
[HttpPost(ApiRoutes.StatResponseAreaWorkLoad.GetByResponseAreas)] //[HttpPost(ApiRoutes.StatResponseAreaWorkLoad.GetByResponseAreas)]
public async Task<IActionResult> GetByResponseAreas([FromBody] StatResponseAreaWorkloadRequest request) //public async Task<IActionResult> GetByResponseAreas([FromBody] StatResponseAreaWorkloadRequest request)
{ //{
var response = await GetStatisticsAsync(request.Filter, request.ResponseAreas); // var response = await GetStatisticsAsync(request.Filter, request.ResponseAreas);
return Ok(new Response<List<StatResponseAreaWorkLoadResponse>>(response, true)); // return Ok(new Response<List<StatResponseAreaWorkLoadResponse>>(response, true));
} //}
private async Task<List<StatResponseAreaWorkLoadResponse>> GetStatisticsAsync(WorkloadBaseQuery requestQuery, List<int>? responseAreas = null) //private async Task<List<StatResponseAreaWorkLoadResponse>> GetStatisticsAsync(WorkloadBaseQuery requestQuery, List<int>? responseAreas = null)
{ //{
var daysList = workLoadService.GetDatesForPeriod(requestQuery); // var daysList = workLoadService.GetDatesForPeriod(requestQuery);
IQueryable<DAL.Models.Template> query = templateService.Get() // IQueryable<DAL.Models.Template> query = templateService.Get()
.Include(t => t.Host).ThenInclude(t => t.WorkGroup); // .Include(t => t.Host).ThenInclude(t => t.WorkGroup);
query = workLoadService.FilterTemplatesQuery(query, requestQuery); // query = workLoadService.FilterTemplatesQuery(query, requestQuery);
if (responseAreas != null && responseAreas.Count() > 0) // if (responseAreas != null && responseAreas.Count() > 0)
query = query.Where(t => responseAreas.Any(x => x == t.Host.WorkGroup.ResponseAreaCode)); // query = query.Where(t => responseAreas.Any(x => x == t.Host.WorkGroup.ResponseAreaCode));
//var groupedQuery = query.GroupBy(t => new { t.NextRun.DateTime.Date, t.Host!.WorkGroup!.ResponseAreaCode }) // //var groupedQuery = query.GroupBy(t => new { t.NextRun.DateTime.Date, t.Host!.WorkGroup!.ResponseAreaCode })
var groupedQuery = query.GroupBy(t => new { t.NextRun.AddHours(requestQuery.TimeZoneOffsetHours).DateTime.Date, t.Host!.WorkGroup!.ResponseAreaCode }) // var groupedQuery = query.GroupBy(t => new { t.NextRun.AddHours(requestQuery.TimeZoneOffsetHours).DateTime.Date, t.Host!.WorkGroup!.ResponseAreaCode })
.Select(t => new // .Select(t => new
{ // {
ResponseAreaCode = t.Key.ResponseAreaCode, // ResponseAreaCode = t.Key.ResponseAreaCode,
Date = t.Key.Date, // Date = t.Key.Date,
TemplateCount = t.Count() // TemplateCount = t.Count()
}); // });
var queryResult = await groupedQuery.ToListAsync(); // var queryResult = await groupedQuery.ToListAsync();
var responseAreaQuery = responseAreaService.Get(); // var responseAreaQuery = responseAreaService.Get();
if (responseAreas != null && responseAreas.Count() > 0) // if (responseAreas != null && responseAreas.Count() > 0)
responseAreaQuery = responseAreaQuery.Where(t => responseAreas.Any(x => x == t.Code)); // responseAreaQuery = responseAreaQuery.Where(t => responseAreas.Any(x => x == t.Code));
var allResponseArea = await responseAreaQuery.ToListAsync(); // var allResponseArea = await responseAreaQuery.ToListAsync();
//if (!allResponseArea.Any()) // //if (!allResponseArea.Any())
// return NoContent(); // // return NoContent();
var response = new List<StatResponseAreaWorkLoadResponse>(); // var response = new List<StatResponseAreaWorkLoadResponse>();
allResponseArea.ForEach(respArea => // allResponseArea.ForEach(respArea =>
{ // {
var workLoads = daysList.Select(t => new StatWorkLoadDataResponse // var workLoads = daysList.Select(t => new StatWorkLoadDataResponse
{ // {
Date = t, // Date = t,
TemplateCount = queryResult.FirstOrDefault(x => x.ResponseAreaCode == respArea.Code && DateOnly.FromDateTime(x.Date) == t)?.TemplateCount ?? 0 // TemplateCount = queryResult.FirstOrDefault(x => x.ResponseAreaCode == respArea.Code && DateOnly.FromDateTime(x.Date) == t)?.TemplateCount ?? 0
}).OrderBy(t => t.Date).ToList(); // }).OrderBy(t => t.Date).ToList();
response.Add( // response.Add(
new StatResponseAreaWorkLoadResponse // new StatResponseAreaWorkLoadResponse
{ // {
ResponseArea = mapper.Map<ResponseAreaResponse>(respArea), // ResponseArea = mapper.Map<ResponseAreaResponse>(respArea),
WorkLoad = workLoads // WorkLoad = workLoads
}); // });
}); // });
response = response.OrderBy(t => t.ResponseArea.Code).ToList(); // response = response.OrderBy(t => t.ResponseArea.Code).ToList();
return response; // return response;
} //}
} }
} }

View File

@@ -32,66 +32,66 @@ namespace PARR.API.Controllers.V1.Statistics
this.calendarService = calendarService; this.calendarService = calendarService;
} }
/// <summary> ///// <summary>
/// Статистика по шаблонам ///// Статистика по шаблонам
/// </summary> ///// </summary>
/// <returns></returns> ///// <returns></returns>
[HttpGet(ApiRoutes.StatTemplate.Get)] //[HttpGet(ApiRoutes.StatTemplate.Get)]
public async Task<IActionResult> Get() //public async Task<IActionResult> Get()
{ //{
var response = new StatTemplateResponse // var response = new StatTemplateResponse
{ // {
ActivateScheduleCount = await templateService.Get().CountAsync(t => t.IsActiveSchedule), // ActivateScheduleCount = await templateService.Get().CountAsync(t => t.IsActiveSchedule),
ActivateTemplateCount = await templateService.Get().CountAsync(t => t.IsActiveTemplate), // ActivateTemplateCount = await templateService.Get().CountAsync(t => t.IsActiveTemplate),
TemplateAgentCount = await templateService.Get().Include(t => t.ApplicationsInWork).CountAsync(t => t.ApplicationsInWork!.IsAgent), // TemplateAgentCount = await templateService.Get().Include(t => t.ApplicationsInWork).CountAsync(t => t.ApplicationsInWork!.IsAgent),
TemplateCount = await templateService.Get().CountAsync(), // TemplateCount = await templateService.Get().CountAsync(),
SyncEsppScheduleCount = await templateService.Get().Include(t => t.RobotConfigurations).CountAsync(t => t.RobotConfigurations.Any(c => c.RobotCode == (int)RobotsEnum.ScheduleOrder && c.TaskStatusCode == (int)TaskStatusEnum.Ok)), // SyncEsppScheduleCount = await templateService.Get().Include(t => t.RobotConfigurations).CountAsync(t => t.RobotConfigurations.Any(c => c.RobotCode == (int)RobotsEnum.ScheduleOrder && c.TaskStatusCode == (int)TaskStatusEnum.Ok)),
SyncEsppTemplatesCount = await templateService.Get().Include(t => t.RobotConfigurations).CountAsync(t => t.RobotConfigurations.Any(c => c.RobotCode == (int)RobotsEnum.TemplateOrder && c.TaskStatusCode == (int)TaskStatusEnum.Ok)) // SyncEsppTemplatesCount = await templateService.Get().Include(t => t.RobotConfigurations).CountAsync(t => t.RobotConfigurations.Any(c => c.RobotCode == (int)RobotsEnum.TemplateOrder && c.TaskStatusCode == (int)TaskStatusEnum.Ok))
}; // };
return Ok(new Response<StatTemplateResponse>(response, true)); // return Ok(new Response<StatTemplateResponse>(response, true));
} //}
/// <summary> ///// <summary>
/// Получить статистику созданных шаблонов (расписаний) в БД ПАРР ///// Получить статистику созданных шаблонов (расписаний) в БД ПАРР
/// </summary> ///// </summary>
/// <param name="timeZoneQuery"></param> ///// <param name="timeZoneQuery"></param>
/// <param name="startPeriodDays"></param> ///// <param name="startPeriodDays"></param>
/// <returns></returns> ///// <returns></returns>
[HttpGet(ApiRoutes.StatTemplate.GetForPeriod)] //[HttpGet(ApiRoutes.StatTemplate.GetForPeriod)]
public async Task<IActionResult> GetForPeriod([FromQuery] TimeZoneOffsetClient timeZoneQuery, [FromQuery] int startPeriodDays = 3) //public async Task<IActionResult> GetForPeriod([FromQuery] TimeZoneOffsetClient timeZoneQuery, [FromQuery] int startPeriodDays = 3)
{ //{
var endPeriod = calendarService.GetDateWithTimeZoneOffset(DateTimeOffset.UtcNow, timeZoneQuery.TimeZoneOffsetHours); // var endPeriod = calendarService.GetDateWithTimeZoneOffset(DateTimeOffset.UtcNow, timeZoneQuery.TimeZoneOffsetHours);
var startPeriod = endPeriod.AddDays(-startPeriodDays); // var startPeriod = endPeriod.AddDays(-startPeriodDays);
var query = templateService.Get() // var query = templateService.Get()
.Where(t => // .Where(t =>
t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date >= startPeriod.Date // t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date >= startPeriod.Date
&& t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date <= endPeriod.Date // && t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date <= endPeriod.Date
).GroupBy(t => t.DateCreated.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date) // ).GroupBy(t => t.DateCreated.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date)
.Select(t => new // .Select(t => new
{ // {
Date = t.Key, // Date = t.Key,
CreatedObjs = t.Count() // CreatedObjs = t.Count()
}); // });
var result = await query.ToListAsync(); // var result = await query.ToListAsync();
var daysList = calendarService.GetDatesForPeriod(startPeriod, endPeriod); // var daysList = calendarService.GetDatesForPeriod(startPeriod, endPeriod);
var response = new List<StatTemplatePeriodResponse>(); // var response = new List<StatTemplatePeriodResponse>();
daysList.ForEach(date => response.Add(new StatTemplatePeriodResponse // daysList.ForEach(date => response.Add(new StatTemplatePeriodResponse
{ // {
Date = date, // Date = date,
CreatedTemplatesCount = result.FirstOrDefault(t => DateOnly.FromDateTime(t.Date) == date)?.CreatedObjs ?? 0 // CreatedTemplatesCount = result.FirstOrDefault(t => DateOnly.FromDateTime(t.Date) == date)?.CreatedObjs ?? 0
})); // }));
response = response.OrderBy(t => t.Date).ToList(); // response = response.OrderBy(t => t.Date).ToList();
return Ok(new Response<List<StatTemplatePeriodResponse>>(response, true)); // return Ok(new Response<List<StatTemplatePeriodResponse>>(response, true));
} //}
} }

View File

@@ -37,20 +37,20 @@ namespace PARR.API.Controllers.V1.Statistics
/// <summary> /// <summary>
/// Статистика распределения шаблонов по JobId (ApplicationInWorkId) /// Статистика распределения шаблонов по JobId (ApplicationInWorkId)
/// </summary> /// </summary>
/// <param name="applicationInWorkId"></param> /// <param name="JobId"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet(ApiRoutes.StatTemplateDistribution.Get)] [HttpGet(ApiRoutes.StatTemplateDistribution.Get)]
public async Task<IActionResult> Get([FromRoute] Guid applicationInWorkId) public async Task<IActionResult> Get([FromRoute] Guid jobId)
{ {
// f87dbe9f-cabf-4108-9c93-12068d4b48a5 // f87dbe9f-cabf-4108-9c93-12068d4b48a5
var query = templateService.Get() var query = templateService.Get()
.Include(t => t.Host) .Include(t => t.Unit)
.Where(t => t.ApplicationInWorkId == applicationInWorkId) .Where(t => t.JobId == jobId)
.GroupBy(t => t.Host!.WorkGroupId) .GroupBy(t => t.Unit!.BaseFields!.WorkGroup)
.Select(x => new .Select(x => new
{ {
WorkGroupId = x.Key, WorkGroup = x.Key,
CountTemplates = x.Count(), CountTemplates = x.Count(),
IsActivatedAllCount = x.Count(t => t.IsActiveTemplate && t.IsActiveSchedule), IsActivatedAllCount = x.Count(t => t.IsActiveTemplate && t.IsActiveSchedule),
IsDeactivatedAllCount = x.Count(t => !t.IsActiveTemplate || !t.IsActiveSchedule || (!t.IsActiveTemplate && !t.IsActiveSchedule)), IsDeactivatedAllCount = x.Count(t => !t.IsActiveTemplate || !t.IsActiveSchedule || (!t.IsActiveTemplate && !t.IsActiveSchedule)),
@@ -73,13 +73,13 @@ namespace PARR.API.Controllers.V1.Statistics
var workGroups = await workGroupService.Get() var workGroups = await workGroupService.Get()
.Include(t => t.ResponseArea) .Include(t => t.ResponseArea)
.Where(t => statResult.Select(x => x.WorkGroupId).Any(w => w == t.Id)) .Where(t => statResult.Select(x => x.WorkGroup).Any(w => w == t.Name))
.ToListAsync(); .ToListAsync();
var response = statResult.Select(stat => new StatTemplateDistributorResponse var response = statResult.Select(stat => new StatTemplateDistributorResponse
{ {
WorkGroup = mapper.Map<WorkGroupResponse>(workGroups.FirstOrDefault(x => x.Id == stat.WorkGroupId)), WorkGroup = mapper.Map<WorkGroupResponse>(workGroups.FirstOrDefault(x => x.Name == stat.WorkGroup)),//TODO Migration to job
AllCount = stat.CountTemplates, AllCount = stat.CountTemplates,
IsActivatedAllCount = stat.IsActivatedAllCount, IsActivatedAllCount = stat.IsActivatedAllCount,
IsDeactivatedAllCount = stat.IsDeactivatedAllCount, IsDeactivatedAllCount = stat.IsDeactivatedAllCount,

View File

@@ -39,7 +39,7 @@ namespace PARR.API.Controllers.V1.Statistics
this.logger = logger; this.logger = logger;
} }
/*
/// <summary> /// <summary>
/// Статистика загрузки регламентными работами рабочих групп по ЗО /// Статистика загрузки регламентными работами рабочих групп по ЗО
/// </summary> /// </summary>
@@ -54,7 +54,7 @@ namespace PARR.API.Controllers.V1.Statistics
return Ok(new Response<List<StatWorkGroupWorkLoadResponse>>(response, true)); return Ok(new Response<List<StatWorkGroupWorkLoadResponse>>(response, true));
} }
/// <summary> /// <summary>
/// Статистика загрузки РГ по списку РГ /// Статистика загрузки РГ по списку РГ
/// </summary> /// </summary>
@@ -137,6 +137,6 @@ namespace PARR.API.Controllers.V1.Statistics
return response; return response;
} }
*/
} }
} }

View File

@@ -40,132 +40,132 @@ namespace PARR.API.Controllers.V1.Statistics
this.workGroupService = workGroupService; this.workGroupService = workGroupService;
} }
///// <summary>
///// Статистика загрузки регламентными работами по Видам работ(ApplicationInWorks)
///// </summary>
///// <param name="workGroupId"></param>
///// <param name="requestQuery"></param>
///// <returns></returns>
//[HttpGet(ApiRoutes.StatWorkWorkLoad.Get)]
//public async Task<IActionResult> Get([FromRoute] Guid workGroupId, [FromQuery] WorkloadBaseQuery requestQuery)
//{
// var response = await GetStatisticsAsync(workGroupId, requestQuery);
/// <summary> // return Ok(new Response<List<StatWorkWorkLoadResponse>>(response, true));
/// Статистика загрузки регламентными работами по Видам работ(ApplicationInWorks) //}
/// </summary>
/// <param name="workGroupId"></param>
/// <param name="requestQuery"></param>
/// <returns></returns>
[HttpGet(ApiRoutes.StatWorkWorkLoad.Get)]
public async Task<IActionResult> Get([FromRoute] Guid workGroupId, [FromQuery] WorkloadBaseQuery requestQuery)
{
var response = await GetStatisticsAsync(workGroupId, requestQuery);
return Ok(new Response<List<StatWorkWorkLoadResponse>>(response, true));
}
/// <summary> ///// <summary>
/// Статистика загрузки РР по списку РР ///// Статистика загрузки РР по списку РР
/// </summary> ///// </summary>
/// <param name="requestBody"></param> ///// <param name="requestBody"></param>
/// <returns></returns> ///// <returns></returns>
[HttpPost(ApiRoutes.StatWorkWorkLoad.GetByApplicationInWork)] //[HttpPost(ApiRoutes.StatWorkWorkLoad.GetByApplicationInWork)]
public async Task<IActionResult> GetByApplicationInWork([FromBody] StatWorkWorkLoadRequest requestBody) //public async Task<IActionResult> GetByApplicationInWork([FromBody] StatWorkWorkLoadRequest requestBody)
{ //{
var response = await GetStatisticsAsync(null, requestBody.Filter, requestBody.JobsRequests); // var response = await GetStatisticsAsync(null, requestBody.Filter, requestBody.JobsRequests);
return Ok(new Response<List<StatWorkWorkLoadResponse>>(response, true)); // return Ok(new Response<List<StatWorkWorkLoadResponse>>(response, true));
} //}
private async Task<List<StatWorkWorkLoadResponse>> GetStatisticsAsync(Guid? workGroupId, WorkloadBaseQuery requestQuery, List<StatWorkWorkLoadJobRequest>? jobsRequests = null) //private async Task<List<StatWorkWorkLoadResponse>> GetStatisticsAsync(Guid? workGroupId, WorkloadBaseQuery requestQuery, List<StatWorkWorkLoadJobRequest>? jobsRequests = null)
{ //{
//защита от дурака, чтоб не выгрузить всю БД // //защита от дурака, чтоб не выгрузить всю БД
if (workGroupId == null && (jobsRequests == null || jobsRequests.Count() == 0)) // if (workGroupId == null && (jobsRequests == null || jobsRequests.Count() == 0))
{ // {
logger.LogWarning($"Пытались выполнить запрос получения статситики с нулевыми параметрами {nameof(workGroupId)}, {nameof(jobsRequests)}. Controller {nameof(StatWorkWorkLoadController)}"); // logger.LogWarning($"Пытались выполнить запрос получения статситики с нулевыми параметрами {nameof(workGroupId)}, {nameof(jobsRequests)}. Controller {nameof(StatWorkWorkLoadController)}");
return new List<StatWorkWorkLoadResponse>(); // return new List<StatWorkWorkLoadResponse>();
} // }
var daysList = workLoadService.GetDatesForPeriod(requestQuery); // var daysList = workLoadService.GetDatesForPeriod(requestQuery);
IQueryable<DAL.Models.Template> query = templateService.Get() // IQueryable<DAL.Models.Template> query = templateService.Get()
.Include(t => t.Host); // .Include(t => t.Host);
query = workLoadService.FilterTemplatesQuery(query, requestQuery); // query = workLoadService.FilterTemplatesQuery(query, requestQuery);
if (workGroupId.HasValue) // if (workGroupId.HasValue)
query = query.Where(t => t.Host!.WorkGroupId == workGroupId.Value); // query = query.Where(t => t.Host!.WorkGroupId == workGroupId.Value);
if (jobsRequests != null && jobsRequests.Count() > 0) // if (jobsRequests != null && jobsRequests.Count() > 0)
//query = query.Where(t => jobsRequests.Any(x => x.JobId == t.ApplicationInWorkId && x.WorkGroupId == t.Host!.WorkGroupId.Value)); /*&& x.WorkGroupId == t.Host!.WorkGroupId.Value*/ // //query = query.Where(t => jobsRequests.Any(x => x.JobId == t.ApplicationInWorkId && x.WorkGroupId == t.Host!.WorkGroupId.Value)); /*&& x.WorkGroupId == t.Host!.WorkGroupId.Value*/
query = query.Where(t => jobsRequests.Select(t => t.JobId).Any(x => x == t.ApplicationInWorkId) && jobsRequests.Select(t => t.WorkGroupId).Any(x => x == t.Host!.WorkGroupId.Value)); // query = query.Where(t => jobsRequests.Select(t => t.JobId).Any(x => x == t.ApplicationInWorkId) && jobsRequests.Select(t => t.WorkGroupId).Any(x => x == t.Host!.WorkGroupId.Value));
//var groupedQuery = query.GroupBy(t => new { t.NextRun.DateTime.Date, t.ApplicationInWorkId, t.Host.WorkGroupId }) // //var groupedQuery = query.GroupBy(t => new { t.NextRun.DateTime.Date, t.ApplicationInWorkId, t.Host.WorkGroupId })
var groupedQuery = query.GroupBy(t => new { t.NextRun.AddHours(requestQuery.TimeZoneOffsetHours).DateTime.Date, t.ApplicationInWorkId, t.Host.WorkGroupId }) // var groupedQuery = query.GroupBy(t => new { t.NextRun.AddHours(requestQuery.TimeZoneOffsetHours).DateTime.Date, t.ApplicationInWorkId, t.Host.WorkGroupId })
.Select(t => new // .Select(t => new
{ // {
ApplicationInWorkId = t.Key.ApplicationInWorkId, // ApplicationInWorkId = t.Key.ApplicationInWorkId,
WorkGroupId = t.Key.WorkGroupId, // WorkGroupId = t.Key.WorkGroupId,
Date = t.Key.Date, // Date = t.Key.Date,
TemplateCount = t.Count() // TemplateCount = t.Count()
}); // });
var queryResult = await groupedQuery.ToListAsync(); // var queryResult = await groupedQuery.ToListAsync();
// получаем только работы по которым есть шаблоны (активированные/деакт) и за любой период // // получаем только работы по которым есть шаблоны (активированные/деакт) и за любой период
IQueryable<DAL.Models.Template> appInWorksQuery = templateService.Get() // IQueryable<DAL.Models.Template> appInWorksQuery = templateService.Get()
.Include(t => t.Host) // .Include(t => t.Host)
.Include(t => t.ApplicationsInWork).ThenInclude(t => t.Application).ThenInclude(t => t.ApplicationType); // .Include(t => t.ApplicationsInWork).ThenInclude(t => t.Application).ThenInclude(t => t.ApplicationType);
IQueryable<WorkGroup> workGroupsQuery = workGroupService.Get() // IQueryable<WorkGroup> workGroupsQuery = workGroupService.Get()
.Include(t => t.ResponseArea); // .Include(t => t.ResponseArea);
if (workGroupId.HasValue) // if (workGroupId.HasValue)
{ // {
appInWorksQuery = appInWorksQuery.Where(t => t.Host.WorkGroupId == workGroupId); // appInWorksQuery = appInWorksQuery.Where(t => t.Host.WorkGroupId == workGroupId);
workGroupsQuery = workGroupsQuery.Where(t => t.Id == workGroupId.Value); // workGroupsQuery = workGroupsQuery.Where(t => t.Id == workGroupId.Value);
} // }
if (jobsRequests != null && jobsRequests.Count() > 0) // if (jobsRequests != null && jobsRequests.Count() > 0)
{ // {
//appInWorksQuery = appInWorksQuery.Where(t => jobsRequests.Any(x => x.JobId == t.ApplicationInWorkId)); // //appInWorksQuery = appInWorksQuery.Where(t => jobsRequests.Any(x => x.JobId == t.ApplicationInWorkId));
appInWorksQuery = appInWorksQuery.Where(t => jobsRequests.Select(j => j.JobId).Any(x => x == t.ApplicationInWorkId)); // appInWorksQuery = appInWorksQuery.Where(t => jobsRequests.Select(j => j.JobId).Any(x => x == t.ApplicationInWorkId));
workGroupsQuery = workGroupsQuery.Where(t => jobsRequests.Select(w => w.WorkGroupId).Any(x => x == t.Id)); // workGroupsQuery = workGroupsQuery.Where(t => jobsRequests.Select(w => w.WorkGroupId).Any(x => x == t.Id));
} // }
var appInWorks = await appInWorksQuery.Select(t => t.ApplicationsInWork) // var appInWorks = await appInWorksQuery.Select(t => t.ApplicationsInWork)
.Distinct() // .Distinct()
.ToListAsync(); // .ToListAsync();
var workGroups = await workGroupsQuery.Distinct().ToListAsync(); // var workGroups = await workGroupsQuery.Distinct().ToListAsync();
var response = new List<StatWorkWorkLoadResponse>(); // var response = new List<StatWorkWorkLoadResponse>();
appInWorks.ForEach(appInWork => // appInWorks.ForEach(appInWork =>
{ // {
workGroups.ForEach(workGroup => // workGroups.ForEach(workGroup =>
{ // {
var workLoads = daysList.Select(t => new StatWorkLoadDataResponse // var workLoads = daysList.Select(t => new StatWorkLoadDataResponse
{ // {
Date = t, // Date = t,
TemplateCount = queryResult.FirstOrDefault(x => x.ApplicationInWorkId == appInWork.Id && DateOnly.FromDateTime(x.Date) == t && x.WorkGroupId == workGroup.Id)?.TemplateCount ?? 0 // TemplateCount = queryResult.FirstOrDefault(x => x.ApplicationInWorkId == appInWork.Id && DateOnly.FromDateTime(x.Date) == t && x.WorkGroupId == workGroup.Id)?.TemplateCount ?? 0
}).OrderBy(t => t.Date).ToList(); // }).OrderBy(t => t.Date).ToList();
response.Add(new StatWorkWorkLoadResponse // response.Add(new StatWorkWorkLoadResponse
{ // {
Job = mapper.Map<ApplicationInWorkBaseResponse>(appInWork), // Job = mapper.Map<ApplicationInWorkBaseResponse>(appInWork),
WorkGroup = mapper.Map<WorkGroupResponse>(workGroup), // WorkGroup = mapper.Map<WorkGroupResponse>(workGroup),
WorkLoad = workLoads // WorkLoad = workLoads
}); // });
}); // });
}); // });
// убираем не нужные значения так как запрос в SQL (query) был с несколькими Any // // убираем не нужные значения так как запрос в SQL (query) был с несколькими Any
if (jobsRequests != null && jobsRequests.Count() > 0) // if (jobsRequests != null && jobsRequests.Count() > 0)
response = response.Where(t => jobsRequests.Any(x => x.WorkGroupId == t.WorkGroup.Id && x.JobId == t.Job.Id)).ToList(); // response = response.Where(t => jobsRequests.Any(x => x.WorkGroupId == t.WorkGroup.Id && x.JobId == t.Job.Id)).ToList();
response = response.OrderBy(t => t.Job.ShortDescription).ThenBy(t => t.Job.Application?.Name).ThenBy(t => t.WorkGroup.Name).ToList(); // response = response.OrderBy(t => t.Job.ShortDescription).ThenBy(t => t.Job.Application?.Name).ThenBy(t => t.WorkGroup.Name).ToList();
return response; // return response;
} //}
} }
} }

View File

@@ -71,7 +71,7 @@ namespace PARR.API.Controllers.V1
query = query.Where(t => EF.Functions.Like(t.Name.ToLower(), SqlHelpers.RegexToLike(filter.Mask))); query = query.Where(t => EF.Functions.Like(t.Name.ToLower(), SqlHelpers.RegexToLike(filter.Mask)));
if (filter.AppInWorkId.HasValue) if (filter.AppInWorkId.HasValue)
query = query.Where(t => t.ApplicationInWorkId == filter.AppInWorkId.Value); query = query.Where(t => t.JobId == filter.AppInWorkId.Value);//TODO Migration to job
var templates = await templateService.GetPage(query, paginationFilter).ToListAsync(); var templates = await templateService.GetPage(query, paginationFilter).ToListAsync();

View File

@@ -23,7 +23,7 @@ namespace PARR.API.Controllers.V1
private readonly IUnitService unitService; private readonly IUnitService unitService;
private readonly IFieldFilterService fieldFilterService; private readonly IFieldFilterService fieldFilterService;
private readonly IJobService jobService; private readonly IJobService jobService;
private readonly IJobDetailsService jobDetailsService; private readonly IJobUnitFilterService jobUnitFilterService;
public TestController( public TestController(
IClientService clientService, IClientService clientService,
@@ -33,7 +33,7 @@ namespace PARR.API.Controllers.V1
IUnitService unitService, IUnitService unitService,
IFieldFilterService fieldFilterService, IFieldFilterService fieldFilterService,
IJobService jobService, IJobService jobService,
IJobDetailsService jobDetailsService IJobUnitFilterService jobUnitFilterService
) )
{ {
this.clientService = clientService; this.clientService = clientService;
@@ -43,7 +43,7 @@ namespace PARR.API.Controllers.V1
this.unitService = unitService; this.unitService = unitService;
this.fieldFilterService = fieldFilterService; this.fieldFilterService = fieldFilterService;
this.jobService = jobService; this.jobService = jobService;
this.jobDetailsService = jobDetailsService; this.jobUnitFilterService = jobUnitFilterService;
} }

View File

@@ -7,6 +7,7 @@ using PARR.Constants.Shortcodes;
using PARR.DAL.DomainModels; using PARR.DAL.DomainModels;
using PARR.DAL.Extensions; using PARR.DAL.Extensions;
using PARR.DAL.Models; using PARR.DAL.Models;
using PARR.DAL.Models.Job;
using PARR.DAL.Models.Unit; using PARR.DAL.Models.Unit;
namespace PARR.API.MappingProfiles namespace PARR.API.MappingProfiles
@@ -19,27 +20,27 @@ namespace PARR.API.MappingProfiles
// --- Template --- // --- Template ---
CreateMap<Template, TemplateResponse>() CreateMap<Template, TemplateResponse>()
.ForMember(d => d.Work, o => o.MapFrom(s => s.ApplicationsInWork!.Work)) .ForMember(d => d.Job, o => o.MapFrom(s => s.Job))
.ForMember(d => d.Host, o => o.MapFrom(s => s.Host)) .ForMember(d => d.Unit, o => o.MapFrom(s => s.Unit))
.ForMember(d => d.Process, o => o.MapFrom(s => s.ApplicationsInWork!.Work!.Tnk!.Subprocess!.Process)) .ForMember(d => d.Process, o => o.MapFrom(s => s.Job!.Tnk!.Subprocess!.Process))
.ForMember(d => d.Subprocess, o => o.MapFrom(s => s.ApplicationsInWork!.Work!.Tnk!.Subprocess)) .ForMember(d => d.Subprocess, o => o.MapFrom(s => s.Job!.Tnk!.Subprocess))
.ForMember(d => d.Tnk, o => o.MapFrom(s => s.ApplicationsInWork!.Work!.Tnk)) .ForMember(d => d.Tnk, o => o.MapFrom(s => s.Job!.Tnk))
.ForMember(d => d.ShortDescription, o => o.MapFrom(s => s.ApplicationsInWork!.ShortDescription)) .ForMember(d => d.ShortDescription, o => o.MapFrom(s => s.Job!.Group!.ShortDescription))
.ForMember(d => d.FullDescription, o => o.MapFrom(s => s.ApplicationsInWork!.FullDescription)) .ForMember(d => d.FullDescription, o => o.MapFrom(s => s.Job!.Group!.FullDescription))
.ForMember(d => d.Solution, o => o.MapFrom(s => s.ApplicationsInWork!.Solution)) .ForMember(d => d.Solution, o => o.MapFrom(s => s.Job!.Group!.Solution))
.ForMember(d => d.TemplateDuration, o => o.MapFrom(s => s.ApplicationsInWork!.TemplateDuration)) .ForMember(d => d.TemplateDuration, o => o.MapFrom(s => s.Job!.Group!.TemplateDuration))
.ForMember(d => d.Initiator, o => o.MapFrom<TemplateInitiatorResolver>()) .ForMember(d => d.Initiator, o => o.MapFrom<TemplateInitiatorResolver>())
.ForMember(d => d.ClosingCode, o => o.MapFrom<TemplateClosingCodeResolver>()) .ForMember(d => d.ClosingCode, o => o.MapFrom<TemplateClosingCodeResolver>())
.ForMember(d => d.Category, o => o.MapFrom<TemplateCategoryResolver>()) .ForMember(d => d.Category, o => o.MapFrom<TemplateCategoryResolver>())
.ForMember(d => d.SyncStatus, o => o.MapFrom(s => s.RobotConfigurations.OrderBy(t => t.RobotCode))) .ForMember(d => d.SyncStatus, o => o.MapFrom(s => s.RobotConfigurations.OrderBy(t => t.RobotCode)))
.ForMember(d => d.Schedule, o => o.MapFrom<TemplateScheduleResolver>()) .ForMember(d => d.Schedule, o => o.MapFrom<TemplateScheduleResolver>())
.ForMember(d => d.Agent, o => o.MapFrom(s => s.ApplicationsInWork)) .ForMember(d => d.Agent, o => o.MapFrom(s => s.Job!.Group!))
//.ForMember(d => d.NextRun, o => o.MapFrom(s => s.ApplicationsInWork!.NextRun)) //.ForMember(d => d.NextRun, o => o.MapFrom(s => s.ApplicationsInWork!.NextRun))
//.ForMember(d => d.LastRun, o => o.MapFrom(s => s.ApplicationsInWork!.LastRun)) //.ForMember(d => d.LastRun, o => o.MapFrom(s => s.ApplicationsInWork!.LastRun))
.ForMember(d => d.NextRun, o => o.MapFrom(s => s.NextRun)) .ForMember(d => d.NextRun, o => o.MapFrom(s => s.NextRun))
.ForMember(d => d.LastRun, o => o.MapFrom(s => s.LastRun)) .ForMember(d => d.LastRun, o => o.MapFrom(s => s.LastRun))
.ForMember(d => d.OrderCount, o => o.MapFrom(s => s.Orders.Count())) .ForMember(d => d.OrderCount, o => o.MapFrom(s => s.Orders.Count()))
.ForMember(d => d.IsAutoDistributionEnabled, o => o.MapFrom(s => s.ApplicationsInWork!.IsAutoDistributionEnabled)); .ForMember(d => d.IsAutoDistributionEnabled, o => o.MapFrom(s => s.Job!.Group!.IsAutoDistributionEnabled));
// === Template === // === Template ===
@@ -156,36 +157,36 @@ namespace PARR.API.MappingProfiles
CreateMap<RobotConfiguration, RobotTaskTemplateResponse>() CreateMap<RobotConfiguration, RobotTaskTemplateResponse>()
.ForMember(d => d.IsActive, o => o.MapFrom(s => s.Template!.IsActiveTemplate)) .ForMember(d => d.IsActive, o => o.MapFrom(s => s.Template!.IsActiveTemplate))
.ForMember(d => d.ClosingCode, o => o.MapFrom<RobotTaskTemplateClosingCodeResolver>()) .ForMember(d => d.ClosingCode, o => o.MapFrom<RobotTaskTemplateClosingCodeResolver>())
.ForMember(d => d.FullDescription, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.FullDescription)) .ForMember(d => d.FullDescription, o => o.MapFrom(s => s.Template!.Job!.Group!.FullDescription))
.ForMember(d => d.ShortDescription, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.ShortDescription.ApplyShortcode(ShortcodeEnum.EK, s.Template!.Host!.Ek))) .ForMember(d => d.ShortDescription, o => o.MapFrom(s => s.Template!.Job!.Group!.ShortDescription.ApplyShortcode(ShortcodeEnum.EK, s.Template!.Unit!.Name)))
.ForMember(d => d.Solution, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.Solution)) .ForMember(d => d.Solution, o => o.MapFrom(s => s.Template!.Job!.Group!.Solution))
//.ForMember(d => d.ResponseArea, o => o.MapFrom(s => s.Template!.Host!.ResponseArea!.Name)) //.ForMember(d => d.ResponseArea, o => o.MapFrom(s => s.Template!.Host!.ResponseArea!.Name))
//ЗО берем у группы а не у хоста //ЗО берем у группы а не у хоста
.ForMember(d => d.ResponseArea, o => o.MapFrom(s => s.Template!.Host!.WorkGroup!.ResponseArea!.Name)) .ForMember(d => d.ResponseArea, o => o.MapFrom(s => s.Template!.Unit.BaseFields.ResponseArea))
.ForMember(d => d.TemplateDuration, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.TemplateDuration)) .ForMember(d => d.TemplateDuration, o => o.MapFrom(s => s.Template!.Job!.Group!.TemplateDuration))
.ForMember(d => d.Initiator, o => o.MapFrom<RobotTaskTemplateInitiatorResolver>()) .ForMember(d => d.Initiator, o => o.MapFrom<RobotTaskTemplateInitiatorResolver>())
.ForMember(d => d.Category, o => o.MapFrom<RobotTaskTemplateCategoryResolver>()) .ForMember(d => d.Category, o => o.MapFrom<RobotTaskTemplateCategoryResolver>())
.ForMember(d => d.WorkGroup, o => o.MapFrom(s => s.Template!.Host!.WorkGroup!.Name)) .ForMember(d => d.WorkGroup, o => o.MapFrom(s => s.Template!.Unit.BaseFields.WorkGroup))
.ForMember(d => d.Ek, o => o.MapFrom(s => s.Template!.Host!.Ek)) .ForMember(d => d.Ek, o => o.MapFrom(s => s.Template!.Unit.Name))
.ForMember(d => d.Name, o => o.MapFrom(s => s.Template!.Name)) .ForMember(d => d.Name, o => o.MapFrom(s => s.Template!.Name))
.ForMember(d => d.ProcessName, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.Work!.Tnk!.Subprocess!.Process!.Name)) .ForMember(d => d.ProcessName, o => o.MapFrom(s => s.Template!.Job!.Tnk!.Subprocess!.Process!.Name))
.ForMember(d => d.ProcessEsppId, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.Work!.Tnk!.Subprocess!.Process!.EsppId)) .ForMember(d => d.ProcessEsppId, o => o.MapFrom(s => s.Template!.Job!.Tnk!.Subprocess!.Process!.EsppId))
.ForMember(d => d.SubprocessName, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.Work!.Tnk!.Subprocess!.Name)) .ForMember(d => d.SubprocessName, o => o.MapFrom(s => s.Template!.Job!.Tnk!.Subprocess!.Name))
.ForMember(d => d.SubprocessEsppId, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.Work!.Tnk!.Subprocess!.EsppId)) .ForMember(d => d.SubprocessEsppId, o => o.MapFrom(s => s.Template!.Job!.Tnk!.Subprocess!.EsppId))
.ForMember(d => d.TnkName, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.Work!.Tnk!.Name.ApplyShortcode(ShortcodeEnum.EK, s.Template!.Host!.Ek))) .ForMember(d => d.TnkName, o => o.MapFrom(s => s.Template!.Job!.Tnk!.Name.ApplyShortcode(ShortcodeEnum.EK, s.Template!.Unit!.Name)))
.ForMember(d => d.TnkEsppId, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.Work!.Tnk!.EsppId)) .ForMember(d => d.TnkEsppId, o => o.MapFrom(s => s.Template!.Job!.Tnk!.EsppId))
.ForMember(d => d.WorkName, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.Work!.Name.ApplyShortcode(ShortcodeEnum.EK, s.Template!.Host!.Ek))) .ForMember(d => d.WorkName, o => o.MapFrom(s => s.Template!.Job!.Name.ApplyShortcode(ShortcodeEnum.EK, s.Template!.Unit!.Name)))
.ForMember(d => d.WorkEsppId, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.Work!.EsppId)) //.ForMember(d => d.WorkEsppId, o => o.MapFrom(s => s.Template!.Job!.EsppId))
.ForMember(d => d.ScheduleEsppId, o => o.MapFrom(s => s.Template!.ScheduleEsppId)); .ForMember(d => d.ScheduleEsppId, o => o.MapFrom(s => s.Template!.ScheduleEsppId));
CreateMap<RobotConfiguration, RobotTaskScheduleResponse>() CreateMap<RobotConfiguration, RobotTaskScheduleResponse>()
.ForMember(d => d.EsppId, o => o.MapFrom(s => s.Template!.ScheduleEsppId)) .ForMember(d => d.EsppId, o => o.MapFrom(s => s.Template!.ScheduleEsppId))
.ForMember(d => d.ScheduleName, o => o.MapFrom(s => s.Template!.Name)) .ForMember(d => d.ScheduleName, o => o.MapFrom(s => s.Template!.Name))
.ForMember(d => d.IsActive, o => o.MapFrom(s => s.Template!.IsActiveSchedule)) .ForMember(d => d.IsActive, o => o.MapFrom(s => s.Template!.IsActiveSchedule))
.ForMember(d => d.ResponseArea, o => o.MapFrom(s => s.Template!.Host!.ResponseArea!.Name)) .ForMember(d => d.ResponseArea, o => o.MapFrom(s => s.Template!.Unit!.BaseFields!.ResponseArea))
.ForMember(d => d.TemplateName, o => o.MapFrom(s => s.Template!.Name)) .ForMember(d => d.TemplateName, o => o.MapFrom(s => s.Template!.Name))
.ForMember(d => d.TemplateId, o => o.MapFrom(s => s.Template!.Id)) .ForMember(d => d.TemplateId, o => o.MapFrom(s => s.Template!.Id))
.ForMember(d => d.WorkGroup, o => o.MapFrom(s => s.Template!.Host!.WorkGroup!.Name)) .ForMember(d => d.WorkGroup, o => o.MapFrom(s => s.Template!.Unit!.BaseFields!.WorkGroup))
.ForMember(d => d.Exclude, o => o.MapFrom<RobotTaskScheduleExcludeResolver>()) .ForMember(d => d.Exclude, o => o.MapFrom<RobotTaskScheduleExcludeResolver>())
.ForMember(d => d.Timezone, o => o.MapFrom<RobotTaskScheduleTimezoneResolver>()) .ForMember(d => d.Timezone, o => o.MapFrom<RobotTaskScheduleTimezoneResolver>())
.ForMember(d => d.RepeatRange, o => o.MapFrom<RobotTaskScheduleRepeatRangeResolver>()) .ForMember(d => d.RepeatRange, o => o.MapFrom<RobotTaskScheduleRepeatRangeResolver>())
@@ -195,9 +196,9 @@ namespace PARR.API.MappingProfiles
//.ForMember(d => d.NextStart, o => o.MapFrom(s => EsppScheduleHelpers.GetNextRun(s.Template!.NextRun))) //.ForMember(d => d.NextStart, o => o.MapFrom(s => EsppScheduleHelpers.GetNextRun(s.Template!.NextRun)))
.ForMember(d => d.NextStart, o => o.MapFrom<RobotTaskScheduleNextStartResolver>()) .ForMember(d => d.NextStart, o => o.MapFrom<RobotTaskScheduleNextStartResolver>())
.ForMember(d => d.ScheduleType, o => o.MapFrom(s => .ForMember(d => d.ScheduleType, o => o.MapFrom(s =>
s.Template!.ApplicationsInWork!.EsppSchValues!.First()!.EsppSchTypeConfig!.EsppSchTypeSchedule!.Description)) s.Template!.Job!.Group!.EsppSchValues!.First()!.EsppSchTypeConfig!.EsppSchTypeSchedule!.Description))
.ForMember(d => d.ScheduleTypeCode, o => o.MapFrom(s => .ForMember(d => d.ScheduleTypeCode, o => o.MapFrom(s =>
s.Template!.ApplicationsInWork!.EsppSchValues!.First()!.EsppSchTypeConfig!.EsppSchTypeSchedule!.Id)) s.Template!.Job!.Group!.EsppSchValues!.First()!.EsppSchTypeConfig!.EsppSchTypeSchedule!.Id))
.ForMember(d => d.Schedule, o => o.MapFrom<RobotTaskScheduleSchResolver>()); .ForMember(d => d.Schedule, o => o.MapFrom<RobotTaskScheduleSchResolver>());
// === RobotConfiguration === // === RobotConfiguration ===
#endregion #endregion
@@ -291,13 +292,20 @@ namespace PARR.API.MappingProfiles
CreateMap<ApplicationsInWork, ApplicationInWorkResponse>() CreateMap<ApplicationsInWork, ApplicationInWorkResponse>()
.ForMember(d => d.Work, o => o.MapFrom(s => s.Work)) .ForMember(d => d.Work, o => o.MapFrom(s => s.Work))
.ForMember(d => d.TemplatesCount, o => o.MapFrom(s => s.Templates.Count())) //.ForMember(d => d.TemplatesCount, o => o.MapFrom(s => s.Templates.Count()))
.ForMember(d => d.Schedule, o => o.MapFrom<ApplicationInWorkScheduleResolver>()) .ForMember(d => d.Schedule, o => o.MapFrom<ApplicationInWorkScheduleResolver>())
.ForMember(d => d.WorkGroups, o => o.MapFrom(s => s.WorkGroups.OrderBy(t => t.WorkGroup.Name).Select(t => t.WorkGroup))) .ForMember(d => d.WorkGroups, o => o.MapFrom(s => s.WorkGroups.OrderBy(t => t.WorkGroup!.Name).Select(t => t.WorkGroup)))
.ForMember(d => d.AutoControl, o => o.MapFrom(s => s.JobAutoControl)); .ForMember(d => d.AutoControl, o => o.MapFrom(s => s.JobAutoControl));
#endregion #endregion
#region Job
CreateMap<Job, JobBaseResponse>()
.Include<Job, JobResponse>();
CreateMap<Job, JobResponse>();
#endregion
#region JobAutoControl #region JobAutoControl
CreateMap<JobAutoControl, JobAutoControlBaseResponse>() CreateMap<JobAutoControl, JobAutoControlBaseResponse>()
@@ -306,7 +314,7 @@ namespace PARR.API.MappingProfiles
CreateMap<JobAutoControl, JobAutoControlResponse>() CreateMap<JobAutoControl, JobAutoControlResponse>()
.ForMember(d => d.EkMasks, o => o.MapFrom(s => s.JobEkMasks.OrderBy(t => t.Name))) .ForMember(d => d.EkMasks, o => o.MapFrom(s => s.JobEkMasks.OrderBy(t => t.Name)))
.ForMember(d => d.EnabledEkStatuses, o => o.MapFrom(s => s.JobAutoControlInEkStatuses.Select(t => t.EkStatus).OrderBy(t => t.Name))) .ForMember(d => d.EnabledEkStatuses, o => o.MapFrom(s => s.JobAutoControlInEkStatuses.Select(t => t.EkStatus).OrderBy(t => t.Name)))
.ForMember(d => d.WorkGroups, o => o.MapFrom(s => s.ApplicationsInWork.WorkGroups.Select(t => t.WorkGroup).OrderBy(t => t.Name))); .ForMember(d => d.WorkGroups, o => o.MapFrom(s => s.ApplicationsInWork!.WorkGroups.Select(t => t.WorkGroup).OrderBy(t => t.Name)));
#endregion #endregion

View File

@@ -26,7 +26,7 @@ namespace PARR.API.MappingProfiles.Resolvers
public List<RobotTaskScheduleSchResponse>? Resolve(RobotConfiguration source, RobotTaskScheduleResponse destination, List<RobotTaskScheduleSchResponse>? destMember, ResolutionContext context) public List<RobotTaskScheduleSchResponse>? Resolve(RobotConfiguration source, RobotTaskScheduleResponse destination, List<RobotTaskScheduleSchResponse>? destMember, ResolutionContext context)
{ {
var appInWorksId = source.Template!.ApplicationInWorkId; var appInWorksId = source.Template!.JobId;
var schedule = esppConfigService.GetEsppScheduleDto(appInWorksId); var schedule = esppConfigService.GetEsppScheduleDto(appInWorksId);
@@ -45,7 +45,7 @@ namespace PARR.API.MappingProfiles.Resolvers
}).OrderBy(t => t.Order).ToList(); }).OrderBy(t => t.Order).ToList();
//Если задача относится к распределенной модели исполнения за период месяц устанавливаем день равный NextRun //Если задача относится к распределенной модели исполнения за период месяц устанавливаем день равный NextRun
if (source.Template!.ApplicationsInWork!.IsAutoDistributionEnabled && schedule.TypeSchedule.Id == (int)EsppSchTypeScheduleEnum.Monthly) if (source.Template!.Job!.Group!.IsAutoDistributionEnabled && schedule.TypeSchedule.Id == (int)EsppSchTypeScheduleEnum.Monthly)
{ {
var nextRunForRobot = nextRunModifierService.GetNextRunByAccountRobotTimeZone(source.Template.NextRun); var nextRunForRobot = nextRunModifierService.GetNextRunByAccountRobotTimeZone(source.Template.NextRun);

View File

@@ -28,11 +28,11 @@ namespace PARR.API.MappingProfiles.Resolvers
public EsppScheduleResponse? Resolve(Template source, TemplateResponse destination, EsppScheduleResponse? destMember, ResolutionContext context) public EsppScheduleResponse? Resolve(Template source, TemplateResponse destination, EsppScheduleResponse? destMember, ResolutionContext context)
{ {
var schedule = esppConfigService.GetEsppScheduleDto(source.ApplicationInWorkId); var schedule = esppConfigService.GetEsppScheduleDto(source.Job!.GroupId);
if (schedule == null) if (schedule == null)
{ {
logger.LogError($"TemplateScheduleResolver: Не смог замапить расписание для робота, так как оно null. appInWorksId: {source.ApplicationInWorkId}"); logger.LogError($"TemplateScheduleResolver: Не смог замапить расписание для робота, так как оно null. appInWorksId: {source.Job!.GroupId}");
return null; return null;
} }

View File

@@ -91,7 +91,11 @@ namespace PARR.DAL.Context
public DbSet<Job> Jobs { get; set; } public DbSet<Job> Jobs { get; set; }
public DbSet<JobUnitFilter> JobDetails { get; set; } public DbSet<JobUnitFilter> JobUnitFilters { get; set; }
public DbSet<JobGroup> JobGroups { get; set; }
#endregion #endregion

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,192 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace PARR.DAL.Migrations
{
/// <inheritdoc />
public partial class tblTemplatesMigrationFormApplicationInWork : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_EsppSchValues_ApplicationsInWorks_ApplicationsInWorkId",
table: "EsppSchValues");
migrationBuilder.DropForeignKey(
name: "FK_Templates_ApplicationsInWorks_ApplicationInWorkId",
table: "Templates");
migrationBuilder.DropForeignKey(
name: "FK_Templates_Hosts_HostId",
table: "Templates");
migrationBuilder.DropIndex(
name: "IX_Templates_ApplicationInWorkId",
table: "Templates");
migrationBuilder.DropIndex(
name: "IX_Templates_HostId",
table: "Templates");
migrationBuilder.DropColumn(
name: "ApplicationInWorkId",
table: "Templates");
migrationBuilder.DropColumn(
name: "HostId",
table: "Templates");
migrationBuilder.RenameColumn(
name: "Duration",
schema: "job",
table: "Groups",
newName: "TemplateDuration");
migrationBuilder.RenameColumn(
name: "ApplicationsInWorkId",
table: "EsppSchValues",
newName: "JobGroupId");
migrationBuilder.AddColumn<string>(
name: "AgentName",
schema: "job",
table: "Groups",
type: "text",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "AgentScript",
schema: "job",
table: "Groups",
type: "text",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "AgentTimeOutSec",
schema: "job",
table: "Groups",
type: "integer",
nullable: true);
migrationBuilder.AddColumn<bool>(
name: "IsAgent",
schema: "job",
table: "Groups",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<bool>(
name: "IsAutoDistributionEnabled",
schema: "job",
table: "Groups",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddForeignKey(
name: "FK_EsppSchValues_Groups_JobGroupId",
table: "EsppSchValues",
column: "JobGroupId",
principalSchema: "job",
principalTable: "Groups",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_EsppSchValues_Groups_JobGroupId",
table: "EsppSchValues");
migrationBuilder.DropColumn(
name: "AgentName",
schema: "job",
table: "Groups");
migrationBuilder.DropColumn(
name: "AgentScript",
schema: "job",
table: "Groups");
migrationBuilder.DropColumn(
name: "AgentTimeOutSec",
schema: "job",
table: "Groups");
migrationBuilder.DropColumn(
name: "IsAgent",
schema: "job",
table: "Groups");
migrationBuilder.DropColumn(
name: "IsAutoDistributionEnabled",
schema: "job",
table: "Groups");
migrationBuilder.RenameColumn(
name: "TemplateDuration",
schema: "job",
table: "Groups",
newName: "Duration");
migrationBuilder.RenameColumn(
name: "JobGroupId",
table: "EsppSchValues",
newName: "ApplicationsInWorkId");
migrationBuilder.AddColumn<Guid>(
name: "ApplicationInWorkId",
table: "Templates",
type: "uuid",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.AddColumn<Guid>(
name: "HostId",
table: "Templates",
type: "uuid",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.CreateIndex(
name: "IX_Templates_ApplicationInWorkId",
table: "Templates",
column: "ApplicationInWorkId");
migrationBuilder.CreateIndex(
name: "IX_Templates_HostId",
table: "Templates",
column: "HostId");
migrationBuilder.AddForeignKey(
name: "FK_EsppSchValues_ApplicationsInWorks_ApplicationsInWorkId",
table: "EsppSchValues",
column: "ApplicationsInWorkId",
principalTable: "ApplicationsInWorks",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Templates_ApplicationsInWorks_ApplicationInWorkId",
table: "Templates",
column: "ApplicationInWorkId",
principalTable: "ApplicationsInWorks",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Templates_Hosts_HostId",
table: "Templates",
column: "HostId",
principalTable: "Hosts",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@@ -1477,7 +1477,7 @@ namespace PARR.DAL.Migrations
modelBuilder.Entity("PARR.DAL.Models.EsppSchValue", b => modelBuilder.Entity("PARR.DAL.Models.EsppSchValue", b =>
{ {
b.Property<Guid>("ApplicationsInWorkId") b.Property<Guid>("JobGroupId")
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<Guid>("TypeValueId") b.Property<Guid>("TypeValueId")
@@ -1486,7 +1486,7 @@ namespace PARR.DAL.Migrations
b.Property<Guid>("TypeConfigId") b.Property<Guid>("TypeConfigId")
.HasColumnType("uuid"); .HasColumnType("uuid");
b.HasKey("ApplicationsInWorkId", "TypeValueId", "TypeConfigId"); b.HasKey("JobGroupId", "TypeValueId", "TypeConfigId");
b.HasIndex("TypeConfigId"); b.HasIndex("TypeConfigId");
@@ -1629,16 +1629,21 @@ namespace PARR.DAL.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<string>("AgentName")
.HasColumnType("text");
b.Property<string>("AgentScript")
.HasColumnType("text");
b.Property<int?>("AgentTimeOutSec")
.HasColumnType("integer");
b.Property<DateTimeOffset>("DateCreated") b.Property<DateTimeOffset>("DateCreated")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<DateTimeOffset?>("DateModified") b.Property<DateTimeOffset?>("DateModified")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<string>("Duration")
.IsRequired()
.HasColumnType("text");
b.Property<string>("FullDescription") b.Property<string>("FullDescription")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
@@ -1647,6 +1652,12 @@ namespace PARR.DAL.Migrations
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<bool>("IsAgent")
.HasColumnType("boolean");
b.Property<bool>("IsAutoDistributionEnabled")
.HasColumnType("boolean");
b.Property<bool?>("IsUmbrella") b.Property<bool?>("IsUmbrella")
.HasColumnType("boolean"); .HasColumnType("boolean");
@@ -1661,6 +1672,10 @@ namespace PARR.DAL.Migrations
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("TemplateDuration")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Groups", "job", t => b.ToTable("Groups", "job", t =>
@@ -2559,18 +2574,12 @@ namespace PARR.DAL.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<Guid>("ApplicationInWorkId")
.HasColumnType("uuid");
b.Property<DateTimeOffset>("DateCreated") b.Property<DateTimeOffset>("DateCreated")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<DateTimeOffset?>("DateModified") b.Property<DateTimeOffset?>("DateModified")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<Guid>("HostId")
.HasColumnType("uuid");
b.Property<string>("InitiatorComment") b.Property<string>("InitiatorComment")
.HasColumnType("text"); .HasColumnType("text");
@@ -2607,10 +2616,6 @@ namespace PARR.DAL.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("ApplicationInWorkId");
b.HasIndex("HostId");
b.HasIndex("JobId"); b.HasIndex("JobId");
b.HasIndex("Name") b.HasIndex("Name")
@@ -3143,9 +3148,9 @@ namespace PARR.DAL.Migrations
modelBuilder.Entity("PARR.DAL.Models.EsppSchValue", b => modelBuilder.Entity("PARR.DAL.Models.EsppSchValue", b =>
{ {
b.HasOne("PARR.DAL.Models.ApplicationsInWork", "ApplicationsInWork") b.HasOne("PARR.DAL.Models.Job.JobGroup", "JobGroup")
.WithMany("EsppSchValues") .WithMany("EsppSchValues")
.HasForeignKey("ApplicationsInWorkId") .HasForeignKey("JobGroupId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
@@ -3161,11 +3166,11 @@ namespace PARR.DAL.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.Navigation("ApplicationsInWork");
b.Navigation("EsppSchTypeConfig"); b.Navigation("EsppSchTypeConfig");
b.Navigation("EsppSchTypeValue"); b.Navigation("EsppSchTypeValue");
b.Navigation("JobGroup");
}); });
modelBuilder.Entity("PARR.DAL.Models.Host", b => modelBuilder.Entity("PARR.DAL.Models.Host", b =>
@@ -3215,7 +3220,7 @@ namespace PARR.DAL.Migrations
modelBuilder.Entity("PARR.DAL.Models.Job.Job", b => modelBuilder.Entity("PARR.DAL.Models.Job.Job", b =>
{ {
b.HasOne("PARR.DAL.Models.Job.JobGroup", "Group") b.HasOne("PARR.DAL.Models.Job.JobGroup", "Group")
.WithMany("Job") .WithMany("Jobs")
.HasForeignKey("GroupId") .HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
@@ -3381,18 +3386,6 @@ namespace PARR.DAL.Migrations
modelBuilder.Entity("PARR.DAL.Models.Template", b => modelBuilder.Entity("PARR.DAL.Models.Template", b =>
{ {
b.HasOne("PARR.DAL.Models.ApplicationsInWork", "ApplicationsInWork")
.WithMany("Templates")
.HasForeignKey("ApplicationInWorkId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("PARR.DAL.Models.Host", "Host")
.WithMany("Templates")
.HasForeignKey("HostId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("PARR.DAL.Models.Job.Job", "Job") b.HasOne("PARR.DAL.Models.Job.Job", "Job")
.WithMany() .WithMany()
.HasForeignKey("JobId") .HasForeignKey("JobId")
@@ -3400,15 +3393,11 @@ namespace PARR.DAL.Migrations
.IsRequired(); .IsRequired();
b.HasOne("PARR.DAL.Models.Unit.Unit", "Unit") b.HasOne("PARR.DAL.Models.Unit.Unit", "Unit")
.WithMany() .WithMany("Templates")
.HasForeignKey("UnitId") .HasForeignKey("UnitId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.Navigation("ApplicationsInWork");
b.Navigation("Host");
b.Navigation("Job"); b.Navigation("Job");
b.Navigation("Unit"); b.Navigation("Unit");
@@ -3580,12 +3569,8 @@ namespace PARR.DAL.Migrations
modelBuilder.Entity("PARR.DAL.Models.ApplicationsInWork", b => modelBuilder.Entity("PARR.DAL.Models.ApplicationsInWork", b =>
{ {
b.Navigation("EsppSchValues");
b.Navigation("JobAutoControl"); b.Navigation("JobAutoControl");
b.Navigation("Templates");
b.Navigation("WorkGroups"); b.Navigation("WorkGroups");
}); });
@@ -3631,8 +3616,6 @@ namespace PARR.DAL.Migrations
modelBuilder.Entity("PARR.DAL.Models.Host", b => modelBuilder.Entity("PARR.DAL.Models.Host", b =>
{ {
b.Navigation("ApplicationsInHosts"); b.Navigation("ApplicationsInHosts");
b.Navigation("Templates");
}); });
modelBuilder.Entity("PARR.DAL.Models.Job.Job", b => modelBuilder.Entity("PARR.DAL.Models.Job.Job", b =>
@@ -3642,7 +3625,9 @@ namespace PARR.DAL.Migrations
modelBuilder.Entity("PARR.DAL.Models.Job.JobGroup", b => modelBuilder.Entity("PARR.DAL.Models.Job.JobGroup", b =>
{ {
b.Navigation("Job"); b.Navigation("EsppSchValues");
b.Navigation("Jobs");
}); });
modelBuilder.Entity("PARR.DAL.Models.Job.JobUnitFilter", b => modelBuilder.Entity("PARR.DAL.Models.Job.JobUnitFilter", b =>
@@ -3740,6 +3725,8 @@ namespace PARR.DAL.Migrations
b.Navigation("ParentUnits"); b.Navigation("ParentUnits");
b.Navigation("Templates");
b.Navigation("UnitFields"); b.Navigation("UnitFields");
b.Navigation("UnitValues"); b.Navigation("UnitValues");

View File

@@ -111,9 +111,9 @@ namespace PARR.DAL.Models
[ForeignKey(nameof(ApplicationId))] [ForeignKey(nameof(ApplicationId))]
public Application? Application { get; set; } public Application? Application { get; set; }
public ICollection<Template> Templates { get; set; } = new HashSet<Template>(); // public ICollection<Template> Templates { get; set; } = new HashSet<Template>();
public ICollection<EsppSchValue> EsppSchValues { get; set; } = new HashSet<EsppSchValue>(); //public ICollection<EsppSchValue> EsppSchValues { get; set; } = new HashSet<EsppSchValue>();
public ICollection<AppInWorkInWorkGroup> WorkGroups { get; set; } = new HashSet<AppInWorkInWorkGroup>(); public ICollection<AppInWorkInWorkGroup> WorkGroups { get; set; } = new HashSet<AppInWorkInWorkGroup>();

View File

@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using PARR.DAL.Models.Job;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace PARR.DAL.Models namespace PARR.DAL.Models
@@ -8,22 +9,28 @@ namespace PARR.DAL.Models
/// </summary> /// </summary>
[Table("EsppSchValues")] [Table("EsppSchValues")]
//[Index(nameof(ApplicationsInWorkId), nameof(TypeValueId), nameof(TypeConfigId), IsUnique = true)] //[Index(nameof(ApplicationsInWorkId), nameof(TypeValueId), nameof(TypeConfigId), IsUnique = true)]
[PrimaryKey(nameof(ApplicationsInWorkId), nameof(TypeValueId), nameof(TypeConfigId))] //[PrimaryKey(nameof(ApplicationsInWorkId), nameof(TypeValueId), nameof(TypeConfigId))]
[PrimaryKey(nameof(JobGroupId), nameof(TypeValueId), nameof(TypeConfigId))]
public class EsppSchValue public class EsppSchValue
{ {
public Guid ApplicationsInWorkId { get; set; } //public Guid ApplicationsInWorkId { get; set; }
public Guid TypeValueId { get; set; } public Guid TypeValueId { get; set; }
public Guid TypeConfigId { get; set; } public Guid TypeConfigId { get; set; }
[ForeignKey(nameof(ApplicationsInWorkId))] public Guid JobGroupId { get; set; }
public ApplicationsInWork? ApplicationsInWork { get; set; }
//[ForeignKey(nameof(ApplicationsInWorkId))]
//public ApplicationsInWork? ApplicationsInWork { get; set; }
[ForeignKey(nameof(TypeValueId))] [ForeignKey(nameof(TypeValueId))]
public EsppSchTypeValue? EsppSchTypeValue { get; set; } public EsppSchTypeValue? EsppSchTypeValue { get; set; }
[ForeignKey(nameof(TypeConfigId))] [ForeignKey(nameof(TypeConfigId))]
public EsppSchTypeConfig? EsppSchTypeConfig { get; set; } public EsppSchTypeConfig? EsppSchTypeConfig { get; set; }
[ForeignKey(nameof(JobGroupId))]
public JobGroup? JobGroup { get; set; }
} }
} }

View File

@@ -43,7 +43,7 @@ namespace PARR.DAL.Models
public ICollection<ApplicationInHost> ApplicationsInHosts { get; set; } = new HashSet<ApplicationInHost>(); public ICollection<ApplicationInHost> ApplicationsInHosts { get; set; } = new HashSet<ApplicationInHost>();
public ICollection<Template> Templates { get; set; } = new HashSet<Template>(); //public ICollection<Template> Templates { get; set; } = new HashSet<Template>();
[ForeignKey(nameof(EkStatusCode))] [ForeignKey(nameof(EkStatusCode))]

View File

@@ -45,14 +45,61 @@ namespace PARR.DAL.Models.Job
/// <summary> /// <summary>
/// Поле Длительность описания шаблона АСУ ЕСПП /// Поле Длительность описания шаблона АСУ ЕСПП
/// </summary> /// </summary>
public required string Duration { get; set; } public required string TemplateDuration { get; set; }
/// <summary>
/// TemplateDuration в формате TimeSpan
/// </summary>
public TimeSpan? TemplateDurationTimeSpan
{
get
{
try
{
//ЕСПП кривоногие, они почему-то таймспан пишут так "7 00:00:00", а правильно так: "7:00:00:00"
var durationWithTimeSpanFormat = TemplateDuration.Replace(" ", ":");
return TimeSpan.Parse(durationWithTimeSpanFormat);
}
catch
{
return null;
}
}
}
/// <summary> /// <summary>
/// Дата начала работ или дата для отсчёта периода следующего выполнения /// Дата начала работ или дата для отсчёта периода следующего выполнения
/// </summary> /// </summary>
public DateTimeOffset ReferenceDate { get; set; } public DateTimeOffset ReferenceDate { get; set; }
/// <summary>
/// Включить автораспределение
/// </summary>
public bool IsAutoDistributionEnabled { get; set; }
public ICollection<Job> Job { get; set; } = new HashSet<Job>(); /// <summary>
/// Выполняет агент
/// </summary>
public bool IsAgent { get; set; }
/// <summary>
/// Какое-то имя которое мы передаем агенту, пока непонятно что это такое.
/// </summary>
public string? AgentName { get; set; }
/// <summary>
/// Сколько времени ожидать выполнение скрипта агентом (секунд)
/// </summary>
public int? AgentTimeOutSec { get; set; }
/// <summary>
/// Скрипт для автоматического выполнения
/// </summary>
public string? AgentScript { get; set; }
public ICollection<Job> Jobs { get; set; } = new HashSet<Job>();
public ICollection<EsppSchValue> EsppSchValues { get; set; } = new HashSet<EsppSchValue>();
} }
} }

View File

@@ -48,13 +48,13 @@ namespace PARR.DAL.Models
public DateTimeOffset NextRun { get; set; } public DateTimeOffset NextRun { get; set; }
public Guid ApplicationInWorkId { get; set; } //public Guid ApplicationInWorkId { get; set; }
public Guid JobId { get; set; }//TODO Вернуть не NULL!!! public Guid JobId { get; set; }//TODO Вернуть не NULL!!!
public Guid UnitId { get; set; }//TODO Вернуть не NULL!!! public Guid UnitId { get; set; }//TODO Вернуть не NULL!!!
public Guid HostId { get; set; } //public Guid HostId { get; set; }
#region Initiator #region Initiator
public string? InitiatorIp { get; set; } public string? InitiatorIp { get; set; }
@@ -64,11 +64,11 @@ namespace PARR.DAL.Models
public string? InitiatorComment { get; set; } public string? InitiatorComment { get; set; }
#endregion #endregion
[ForeignKey(nameof(ApplicationInWorkId))] //[ForeignKey(nameof(ApplicationInWorkId))]
public ApplicationsInWork? ApplicationsInWork { get; set; } //public ApplicationsInWork? ApplicationsInWork { get; set; }
[ForeignKey(nameof(HostId))] //[ForeignKey(nameof(HostId))]
public Host? Host { get; set; } //public Host? Host { get; set; }
[ForeignKey(nameof(JobId))] [ForeignKey(nameof(JobId))]
public Job.Job? Job { get; set; } public Job.Job? Job { get; set; }

View File

@@ -28,6 +28,28 @@ namespace PARR.DAL.Models.Unit
// todo: добавить еще поля??? (которые есть у всех ЭК) // todo: добавить еще поля??? (которые есть у всех ЭК)
[NotMapped]
public BaseFields? BaseFields
{
get
{
if (UnitValues.Any())
{
var result = new BaseFields();
result.IP = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "IP_АДРЕС")?.Value?.Value;
result.ResponseArea = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "ЗО_РГ")?.Value?.Value;
result.WorkGroup = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "РАБОЧАЯ_ГР_ОТВ_ЗАК")?.Value?.Value;
result.Status = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "СТАТУС")?.Value?.Value;
return result;
}
return null;
}
}
public ICollection<UnitInField> UnitFields { get; set; } = new HashSet<UnitInField>(); public ICollection<UnitInField> UnitFields { get; set; } = new HashSet<UnitInField>();
public ICollection<UnitInValue> UnitValues { get; set; } = new HashSet<UnitInValue>(); public ICollection<UnitInValue> UnitValues { get; set; } = new HashSet<UnitInValue>();
@@ -44,5 +66,19 @@ namespace PARR.DAL.Models.Unit
/// </summary> /// </summary>
[InverseProperty(nameof(UnitInUnit.ParentUnit))] [InverseProperty(nameof(UnitInUnit.ParentUnit))]
public ICollection<UnitInUnit> ChildUnits { get; set; } = new HashSet<UnitInUnit>(); public ICollection<UnitInUnit> ChildUnits { get; set; } = new HashSet<UnitInUnit>();
public ICollection<Template> Templates { get; set; } = new HashSet<Template>();
}
public class BaseFields
{
public string? IP { get; set; }
public string? ResponseArea { get; set; }
public string? WorkGroup { get; set; }
public string? Status { get; set; }
} }
} }

View File

@@ -105,8 +105,10 @@ namespace PARR.DAL
#region Job #region Job
services.AddTransient<IJobService, JobService>(); services.AddTransient<IJobService, JobService>();
services.AddTransient<IJobDetailsService, JobDetailsService>(); services.AddTransient<IJobGroupService, JobGroupService>();
services.AddTransient<IJobUnitFilterService, JobUnitFilterService>();
services.AddTransient<IFieldFilterService, FieldFilterService>(); services.AddTransient<IFieldFilterService, FieldFilterService>();
services.AddTransient<IJobUnitFilterService, JobUnitFilterService>();
#endregion #endregion

View File

@@ -31,17 +31,27 @@ namespace PARR.DAL.Services.Implementations
.ThenInclude(t => t!.EsppSchValues); .ThenInclude(t => t!.EsppSchValues);
} }
public async Task<EsppScheduleDto?> GetEsppScheduleDtoAsync(Guid applicationInWorksId) public async Task<EsppScheduleDto?> GetEsppScheduleDtoAsync(Guid jobGroupId)
{ {
//Формирует расписание в нормальном понятном виде из БД //Формирует расписание в нормальном понятном виде из БД
var test = await dataContext.EsppSchValues
//.Include(t => t.JobGroup)
//.Include(t => t.EsppSchTypeConfig)
// .ThenInclude(t => t!.EsppSchTypeSchedule)
//.Include(t => t.EsppSchTypeConfig)
// .ThenInclude(t => t.EsppSchType)
//.Include(t => t.EsppSchTypeValue)
.ToListAsync();
var schValues = await dataContext.EsppSchValues var schValues = await dataContext.EsppSchValues
.Include(t => t.EsppSchTypeConfig) .Include(t => t.EsppSchTypeConfig)
.ThenInclude(t => t!.EsppSchTypeSchedule) .ThenInclude(t => t!.EsppSchTypeSchedule)
.Include(t => t.EsppSchTypeConfig) .Include(t => t.EsppSchTypeConfig)
.ThenInclude(t=>t.EsppSchType) .ThenInclude(t => t.EsppSchType)
.Include(t => t.EsppSchTypeValue) .Include(t => t.EsppSchTypeValue)
.Where(t => t.ApplicationsInWorkId == applicationInWorksId) .Include(t => t.JobGroup)
.Where(t => t.JobGroup!.Id == jobGroupId)//TODO Migration to job
.OrderBy(t => t.EsppSchTypeConfig!.Order) .OrderBy(t => t.EsppSchTypeConfig!.Order)
.ToListAsync(); .ToListAsync();
@@ -94,11 +104,11 @@ namespace PARR.DAL.Services.Implementations
return dto; return dto;
} }
public EsppScheduleDto? GetEsppScheduleDto(Guid applicationInWorksId) public EsppScheduleDto? GetEsppScheduleDto(Guid jobGroupId)
{ {
var result = Task.Run(async () => var result = Task.Run(async () =>
{ {
return await GetEsppScheduleDtoAsync(applicationInWorksId); return await GetEsppScheduleDtoAsync(jobGroupId);
}).Result; }).Result;
return result; return result;

View File

@@ -7,15 +7,15 @@ using PARR.DAL.Services.Interfaces.Job;
namespace PARR.DAL.Services.Implementations.Job namespace PARR.DAL.Services.Implementations.Job
{ {
internal class JobDetailsService : BaseService<Models.Job.JobUnitFilter>, IJobDetailsService internal class JobUnitFilterService : BaseService<JobUnitFilter>, IJobUnitFilterService
{ {
private readonly DataContext dataContext; private readonly DataContext dataContext;
protected override DbSet<JobUnitFilter> EntitySet => dataContext.JobDetails; protected override DbSet<JobUnitFilter> EntitySet => dataContext.JobUnitFilters;
protected override DataContext EntitiContext => dataContext; protected override DataContext EntitiContext => dataContext;
public JobDetailsService(DataContext dataContext, ILogger<JobDetailsService> logger) : base(logger) public JobUnitFilterService(DataContext dataContext, ILogger<JobUnitFilterService> logger) : base(logger)
{ {
this.dataContext = dataContext; this.dataContext = dataContext;
} }

View File

@@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.DAL.Context;
using PARR.DAL.Models.Job;
using PARR.DAL.Services.Abstracts;
using PARR.DAL.Services.Interfaces.Job;
namespace PARR.DAL.Services.Implementations.Job
{
internal class JobGroupService : BaseService<Models.Job.JobGroup>, IJobGroupService
{
private readonly DataContext dataContext;
public JobGroupService(DataContext dataContext, ILogger<JobGroupService> logger) : base(logger)
{
this.dataContext = dataContext;
}
protected override DbSet<JobGroup> EntitySet => dataContext.JobGroups;
protected override DataContext EntitiContext => dataContext;
}
}

View File

@@ -34,18 +34,24 @@ namespace PARR.DAL.Services.Implementations
public IQueryable<Template> GetWithIncludes() public IQueryable<Template> GetWithIncludes()
{ {
return Get() return Get()
.Include(h => h.Host) .Include(h => h.Unit)
.ThenInclude(t => t!.ResponseArea) .Include(a => a.Job)
.Include(h => h.Host)
.ThenInclude(t => t!.WorkGroup)
.ThenInclude(t => t!.ResponseArea)
.Include(h => h.Host)
.ThenInclude(t => t!.EkStatus)
.Include(a => a.ApplicationsInWork)
.ThenInclude(w => w!.Work)
.ThenInclude(t => t!.Tnk) .ThenInclude(t => t!.Tnk)
.ThenInclude(s => s!.Subprocess) .ThenInclude(s => s!.Subprocess)
.ThenInclude(p => p!.Process); .ThenInclude(p => p!.Process);
//return Get()
// .Include(h => h.Host)
// .ThenInclude(t => t!.ResponseArea)
// .Include(h => h.Host)
// .ThenInclude(t => t!.WorkGroup)
// .ThenInclude(t => t!.ResponseArea)
// .Include(h => h.Host)
// .ThenInclude(t => t!.EkStatus)
// .Include(a => a.ApplicationsInWork)
// .ThenInclude(w => w!.Work)
// .ThenInclude(t => t!.Tnk)
// .ThenInclude(s => s!.Subprocess)
// .ThenInclude(p => p!.Process);
} }
public override Task<bool> CreateAsync(Template obj) public override Task<bool> CreateAsync(Template obj)

View File

@@ -18,5 +18,15 @@ namespace PARR.DAL.Services.Implementations.Unit
{ {
this.dataContext = dataContext; this.dataContext = dataContext;
} }
public IQueryable<Models.Unit.Unit> GetWithIncludes()
{
return Get()
.Include(t => t.UnitValues)
.ThenInclude(t => t.Field)
.Include(t => t.UnitValues)
.ThenInclude(t => t.Value);
}
} }
} }

View File

@@ -9,16 +9,16 @@ namespace PARR.DAL.Services.Interfaces
/// <summary> /// <summary>
/// Формирует расписание в нормальном понятном виде из БД синхронно /// Формирует расписание в нормальном понятном виде из БД синхронно
/// </summary> /// </summary>
/// <param name="applicationInWorksId"></param> /// <param name="jobGroupId"></param>
/// <returns></returns> /// <returns></returns>
EsppScheduleDto? GetEsppScheduleDto(Guid applicationInWorksId); EsppScheduleDto? GetEsppScheduleDto(Guid jobGroupId);
/// <summary> /// <summary>
/// Формирует расписание в нормальном понятном виде из БД асинхронно /// Формирует расписание в нормальном понятном виде из БД асинхронно
/// </summary> /// </summary>
/// <param name="applicationInWorksId"></param> /// <param name="jobGroupId"></param>
/// <returns></returns> /// <returns></returns>
Task<EsppScheduleDto?> GetEsppScheduleDtoAsync(Guid applicationInWorksId); Task<EsppScheduleDto?> GetEsppScheduleDtoAsync(Guid jobGroupId);
IQueryable<EsppSchTypeConfig> GetWithSchIncludes(); IQueryable<EsppSchTypeConfig> GetWithSchIncludes();
} }

View File

@@ -2,7 +2,7 @@
namespace PARR.DAL.Services.Interfaces.Job namespace PARR.DAL.Services.Interfaces.Job
{ {
public interface IJobDetailsService : IBaseService<Models.Job.JobUnitFilter> public interface IJobUnitFilterService : IBaseService<Models.Job.JobUnitFilter>
{ {
} }
} }

View File

@@ -0,0 +1,8 @@
using PARR.DAL.Services.Interfaces.Base;
namespace PARR.DAL.Services.Interfaces.Job
{
public interface IJobGroupService : IBaseService<Models.Job.JobGroup>
{
}
}

View File

@@ -4,5 +4,6 @@ namespace PARR.DAL.Services.Interfaces.Unit
{ {
public interface IUnitService : IBaseService<Models.Unit.Unit> public interface IUnitService : IBaseService<Models.Unit.Unit>
{ {
IQueryable<Models.Unit.Unit> GetWithIncludes();
} }
} }

View File

@@ -6,6 +6,7 @@ using PARR.DAL.Contracts;
using PARR.DAL.DomainModels; using PARR.DAL.DomainModels;
using PARR.DAL.Extensions; using PARR.DAL.Extensions;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Job;
namespace PARR.DAL.TransformServices namespace PARR.DAL.TransformServices
{ {
@@ -15,6 +16,7 @@ namespace PARR.DAL.TransformServices
private readonly IApplicationsInWorkService applicationsInWorkService; private readonly IApplicationsInWorkService applicationsInWorkService;
private readonly IWeekendDayService weekendDayService; private readonly IWeekendDayService weekendDayService;
private readonly INextRunModifierService nextRunModifierService; private readonly INextRunModifierService nextRunModifierService;
private readonly IJobGroupService jobGroupService;
private readonly ILogger<EsppScheduleTransformService> logger; private readonly ILogger<EsppScheduleTransformService> logger;
private readonly Dictionary<string, int> monthDict = new Dictionary<string, int>() private readonly Dictionary<string, int> monthDict = new Dictionary<string, int>()
@@ -59,13 +61,15 @@ namespace PARR.DAL.TransformServices
IEsppSchTypeConfigService esppSchTypeConfigService, IEsppSchTypeConfigService esppSchTypeConfigService,
IApplicationsInWorkService applicationsInWorkService, IApplicationsInWorkService applicationsInWorkService,
IWeekendDayService weekendDayService, IWeekendDayService weekendDayService,
INextRunModifierService nextRunModifierService INextRunModifierService nextRunModifierService,
IJobGroupService jobGroupService
) )
{ {
this.esppSchTypeConfigService = esppSchTypeConfigService; this.esppSchTypeConfigService = esppSchTypeConfigService;
this.applicationsInWorkService = applicationsInWorkService; this.applicationsInWorkService = applicationsInWorkService;
this.weekendDayService = weekendDayService; this.weekendDayService = weekendDayService;
this.nextRunModifierService = nextRunModifierService; this.nextRunModifierService = nextRunModifierService;
this.jobGroupService = jobGroupService;
this.logger = logger; this.logger = logger;
} }
@@ -157,23 +161,28 @@ namespace PARR.DAL.TransformServices
} }
public async Task<DateTimeOffset> GetNextDateAsync(Guid applicationInWorkId, DateTimeOffset lastRun) public async Task<DateTimeOffset> GetNextDateAsync(Guid jobGroupId, DateTimeOffset lastRun)
{ {
//если больше текущего вернуть lastRun. Это и есть следующая дата //если больше текущего вернуть lastRun. Это и есть следующая дата
if (lastRun > DateTimeOffset.UtcNow) if (lastRun > DateTimeOffset.UtcNow)
return await nextRunModifierService.GetWorkDayAsync(lastRun); return await nextRunModifierService.GetWorkDayAsync(lastRun);
var appInWork = await applicationsInWorkService.Get() //var appInWork = await applicationsInWorkService.Get()
.Include(aiw => aiw.EsppSchValues) // .Include(aiw => aiw.EsppSchValues)
.ThenInclude(esv => esv.EsppSchTypeValue) // .ThenInclude(esv => esv.EsppSchTypeValue)
.ThenInclude(etv => etv!.DistributionPeriod) // .ThenInclude(etv => etv!.DistributionPeriod)
.FirstOrDefaultAsync(t => t.Id == applicationInWorkId); // .FirstOrDefaultAsync(t => t.Id == applicationInWorkId);
var jobGroup = await jobGroupService.Get()
.Include(t=>t.EsppSchValues)
.ThenInclude(esv => esv.EsppSchTypeValue)
.ThenInclude(etv => etv!.DistributionPeriod)
.FirstOrDefaultAsync(t => t.Id == jobGroupId);
var esppSchedule = await GetEsppScheduleAsync(applicationInWorkId); var esppSchedule = await GetEsppScheduleAsync(jobGroupId);
if (appInWork!.IsAutoDistributionEnabled) if (jobGroup!.IsAutoDistributionEnabled)
{ {
var period = appInWork.EsppSchValues.FirstOrDefault()?.EsppSchTypeValue?.DistributionPeriod; var period = jobGroup.EsppSchValues.FirstOrDefault()?.EsppSchTypeValue?.DistributionPeriod;
var periodType = ParseDistributionPeriodType(period!.Type); var periodType = ParseDistributionPeriodType(period!.Type);
return GetNextDateForDistributionRun(lastRun, periodType, period.Duration); return GetNextDateForDistributionRun(lastRun, periodType, period.Duration);
@@ -183,24 +192,24 @@ namespace PARR.DAL.TransformServices
} }
public async Task<List<DateTimeOffset>> GetNextScheduleAsync(Guid applicationInWorkId, DateTimeOffset lastRun) public async Task<List<DateTimeOffset>> GetNextScheduleAsync(Guid jobGroupId, DateTimeOffset lastRun)
{ {
//TODO: тут не проверен переход через выходные дни!!! Переход не используется, так как тут не рассчитываем NextRun. //TODO: тут не проверен переход через выходные дни!!! Переход не используется, так как тут не рассчитываем NextRun.
//В общем проверить, когда будем тестировать агента, что с датами все ок //В общем проверить, когда будем тестировать агента, что с датами все ок
var esppSchedule = await GetEsppScheduleAsync(applicationInWorkId); var esppSchedule = await GetEsppScheduleAsync(jobGroupId);
var nextSchedule = GetNextSchedule(esppSchedule, lastRun); var nextSchedule = GetNextSchedule(esppSchedule, lastRun);
return nextSchedule; return nextSchedule;
} }
private async Task<EsppScheduleDto> GetEsppScheduleAsync(Guid applicationInWorkId) private async Task<EsppScheduleDto> GetEsppScheduleAsync(Guid jobGroupId)
{ {
var esppSchedule = await esppSchTypeConfigService.GetEsppScheduleDtoAsync(applicationInWorkId); var esppSchedule = await esppSchTypeConfigService.GetEsppScheduleDtoAsync(jobGroupId);
if (esppSchedule == null) if (esppSchedule == null)
{ {
logger.LogError($"Не найдено расписание в БД, applicationInWorkId: {applicationInWorkId}"); logger.LogError($"Не найдено расписание в БД, jobId: {jobGroupId}");
throw new Exception($"Не найдено расписание в БД, applicationInWorkId: {applicationInWorkId}"); throw new Exception($"Не найдено расписание в БД, jobId: {jobGroupId}");
} }
return esppSchedule; return esppSchedule;
@@ -427,9 +436,9 @@ namespace PARR.DAL.TransformServices
} }
public async Task<DateOnly> GetStartPeriodForDateAsync(Guid applicationInWorkId, DateTimeOffset date, DateTimeOffset referenceDate, DistributionPeriodTypeEnum periodType, string distributionPeriod) public async Task<DateOnly> GetStartPeriodForDateAsync(Guid jobGroupId, DateTimeOffset date, DateTimeOffset referenceDate, DistributionPeriodTypeEnum periodType, string distributionPeriod)
{ {
var esppSchedule = await GetEsppScheduleAsync(applicationInWorkId); var esppSchedule = await GetEsppScheduleAsync(jobGroupId);
var currentStartPeriod = referenceDate; var currentStartPeriod = referenceDate;
var currentEndPeriod = GetNextDateForDistributionRun(currentStartPeriod, periodType, distributionPeriod); var currentEndPeriod = GetNextDateForDistributionRun(currentStartPeriod, periodType, distributionPeriod);

View File

@@ -25,20 +25,20 @@ namespace PARR.DAL.TransformServices
//List<DateTimeOffset> GetNextSchedule(EsppScheduleDto esppSchedule, DateTimeOffset lastRun); //List<DateTimeOffset> GetNextSchedule(EsppScheduleDto esppSchedule, DateTimeOffset lastRun);
/// <summary> /// <summary>
/// Получить следующую дату по applicationInWorkId /// Получить следующую дату по jobGroupId
/// </summary> /// </summary>
/// <param name="applicationInWorkId"></param> /// <param name="jobGroupId"></param>
/// <param name="lastRun"></param> /// <param name="lastRun"></param>
/// <returns></returns> /// <returns></returns>
Task<DateTimeOffset> GetNextDateAsync(Guid applicationInWorkId, DateTimeOffset lastRun); Task<DateTimeOffset> GetNextDateAsync(Guid jobGroupId, DateTimeOffset lastRun);
/// <summary> /// <summary>
/// Получить расписание по applicationInWorkId /// Получить расписание по jobGroupId
/// </summary> /// </summary>
/// <param name="applicationInWorkId"></param> /// <param name="jobGroupId"></param>
/// <param name="lastRun"></param> /// <param name="lastRun"></param>
/// <returns></returns> /// <returns></returns>
Task<List<DateTimeOffset>> GetNextScheduleAsync(Guid applicationInWorkId, DateTimeOffset lastRun); Task<List<DateTimeOffset>> GetNextScheduleAsync(Guid jobGroupId, DateTimeOffset lastRun);
/// <summary> /// <summary>
@@ -49,14 +49,14 @@ namespace PARR.DAL.TransformServices
/// <param name="distributionPeriod"></param> /// <param name="distributionPeriod"></param>
/// <returns></returns> /// <returns></returns>
DateTimeOffset GetNextDateForDistributionRun(DateTimeOffset lastRun, DistributionPeriodTypeEnum periodType, string distributionPeriod); DateTimeOffset GetNextDateForDistributionRun(DateTimeOffset lastRun, DistributionPeriodTypeEnum periodType, string distributionPeriod);
/// <summary> /// <summary>
/// Получить дату начала периода распределения относительно опорной даты (Reference Date) /// Получить дату начала периода распределения относительно опорной даты (Reference Date)
/// </summary> /// </summary>
/// <param name="applicationInWorkId"></param> /// <param name="jobGroupId"></param>
/// <param name="date"></param> /// <param name="date"></param>
/// <returns></returns> /// <returns></returns>
Task<DateOnly> GetStartPeriodForDateAsync(Guid applicationInWorkId, DateTimeOffset date, DateTimeOffset refrenceDate, DistributionPeriodTypeEnum periodType, string distributionPeriod); Task<DateOnly> GetStartPeriodForDateAsync(Guid jobGroupId, DateTimeOffset date, DateTimeOffset refrenceDate, DistributionPeriodTypeEnum periodType, string distributionPeriod);
} }
} }

View File

@@ -37,7 +37,7 @@ namespace PARR.EsppOrderLoader.Services
} }
var template = await templateService.Get() var template = await templateService.Get()
.Include(t => t.ApplicationsInWork) .Include(t => t.Job)
.FirstOrDefaultAsync(t => t.Name.ToLower() == esppOrder.TemplateName.ToLower()); .FirstOrDefaultAsync(t => t.Name.ToLower() == esppOrder.TemplateName.ToLower());
if (template == null) if (template == null)

View File

@@ -86,7 +86,7 @@ namespace PARR.EsppOrderManager
.Include(t => t.AgentHistories).ThenInclude(t => t.AgentHistoryLevel) .Include(t => t.AgentHistories).ThenInclude(t => t.AgentHistoryLevel)
.Include(t => t.OrderStatus) .Include(t => t.OrderStatus)
.Include(t => t.NextStatus) .Include(t => t.NextStatus)
.Include(t => t.Template).ThenInclude(t => t!.ApplicationsInWork).ThenInclude(t => t!.Work).ThenInclude(t => t!.Tnk) .Include(t => t.Template).ThenInclude(t => t!.Job).ThenInclude(t => t!.Tnk)
.FirstOrDefaultAsync(t => t.Id == objFromQuery.OrderId); .FirstOrDefaultAsync(t => t.Id == objFromQuery.OrderId);
if (!IsValidOrder(ref order, ref objFromQuery)) if (!IsValidOrder(ref order, ref objFromQuery))
@@ -162,7 +162,7 @@ namespace PARR.EsppOrderManager
var template = resultTemplateSettings.Template; var template = resultTemplateSettings.Template;
//Поле решение из ApplicationsInWork //Поле решение из ApplicationsInWork
var baseMsg = order.Template!.ApplicationsInWork!.Solution; var baseMsg = order.Template!.Job!.Group!.Solution;
//Формируем сообщения от Агента //Формируем сообщения от Агента
var msgAgent = agentHistory.Any() var msgAgent = agentHistory.Any()

View File

@@ -71,7 +71,7 @@ namespace PARR.EsppOrderManager.Services
// заполняем ТНК // заполняем ТНК
var tnk = new AddMtnkQuery var tnk = new AddMtnkQuery
{ {
JobOperation = order!.Template!.ApplicationsInWork!.Work!.Name, JobOperation = order!.Template!.Job!.WorkName,
RecordId = order.Number, RecordId = order.Number,
Time = duration.ToString("hh\\:mm") Time = duration.ToString("hh\\:mm")
}; };

View File

@@ -86,9 +86,9 @@ namespace PARR.EsppScheduleSync
Code = template.ScheduleEsppId ?? "", Code = template.ScheduleEsppId ?? "",
ScheduleName = template.Name, ScheduleName = template.Name,
IsActive = template.IsActiveSchedule, IsActive = template.IsActiveSchedule,
ResponseArea = template.Host!.ResponseArea!.Name, //ResponseArea = template.Host!.ResponseArea!.Name,//TODO Migration to job
//WorkGroup = template.Host!.WorkGroup!, //WorkGroup = template.Host!.WorkGroup!,
WorkGroup = template.Host!.WorkGroup!.Name, //WorkGroup = template.Host!.WorkGroup!.Name,//TODO Migration to job
//Мы решили, что для всех расписаний "Нет исключений", если что-то поменяется, тут нужно переделать //Мы решили, что для всех расписаний "Нет исключений", если что-то поменяется, тут нужно переделать
TypeV60calendar = settingsFromDb.ScheduleExclude == "Нет исключений" ? "NONE" : "", TypeV60calendar = settingsFromDb.ScheduleExclude == "Нет исключений" ? "NONE" : "",
//Scheduled = EsppScheduleHelpers.GetNextRun(template.NextRun), //Scheduled = EsppScheduleHelpers.GetNextRun(template.NextRun),
@@ -119,7 +119,7 @@ namespace PARR.EsppScheduleSync
if (esppSchTypeConfigService == null) if (esppSchTypeConfigService == null)
throw new Exception($"Не найден сервис: {nameof(IEsppSchTypeConfigService)}"); throw new Exception($"Не найден сервис: {nameof(IEsppSchTypeConfigService)}");
var esppSchedule = esppSchTypeConfigService.GetEsppScheduleDto(template.ApplicationInWorkId); var esppSchedule = esppSchTypeConfigService.GetEsppScheduleDto(template.JobId);
if (esppSchedule == null) if (esppSchedule == null)
{ {
logger.LogError($"Не смог получить расписание из БД для шаблона templateId: {template.Id}, {template.Name}"); logger.LogError($"Не смог получить расписание из БД для шаблона templateId: {template.Id}, {template.Name}");
@@ -144,16 +144,16 @@ namespace PARR.EsppScheduleSync
break; break;
case EsppSchTypeScheduleEnum.Monthly: case EsppSchTypeScheduleEnum.Monthly:
//если включено автораспределение, подставляем дату месяца из NextRun //если включено автораспределение, подставляем дату месяца из NextRun
if (template.ApplicationsInWork?.IsAutoDistributionEnabled == true) //if (template.ApplicationsInWork?.IsAutoDistributionEnabled == true)//TODO Migration to job
{ //{
var nextRunByRobotTimeZone = nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun); // var nextRunByRobotTimeZone = nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun);
esppObject.Dayofmonth = nextRunByRobotTimeZone.Day.ToString(); // esppObject.Dayofmonth = nextRunByRobotTimeZone.Day.ToString();
// esppObject.Dayofmonth = template.NextRun.Day.ToString(); // // esppObject.Dayofmonth = template.NextRun.Day.ToString();
} //}
else //else
{ //{
esppObject.Dayofmonth = esppSchedule.Values.First(t => t.Order == 0).Value.EsppExportValue; esppObject.Dayofmonth = esppSchedule.Values.First(t => t.Order == 0).Value.EsppExportValue;
} //}
break; break;
case EsppSchTypeScheduleEnum.Monthly2: case EsppSchTypeScheduleEnum.Monthly2:
esppObject.Md1 = esppSchedule.Values.First(t => t.Order == 0).Value.EsppExportValue; esppObject.Md1 = esppSchedule.Values.First(t => t.Order == 0).Value.EsppExportValue;

View File

@@ -74,19 +74,19 @@ namespace PARR.EsppTemplateSync
TemplateName = template.Name, TemplateName = template.Name,
IsActive = template.IsActiveTemplate, IsActive = template.IsActiveTemplate,
//WorkGroup = template.Host!.WorkGroup!, //WorkGroup = template.Host!.WorkGroup!,
WorkGroup = template.Host!.WorkGroup!.Name, WorkGroup = template.Unit!.BaseFields!.WorkGroup!,
ShortDescription = Normalize(template.ApplicationsInWork!.ShortDescription.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK,template.Host.Ek)), ShortDescription = Normalize(template.Job.Group.ShortDescription.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK,template.Unit.Name)),
//ResponseArea = template.Host!.ResponseArea!.Name, //ResponseArea = template.Host!.ResponseArea!.Name,
//ЗО берем РГ а не хоста //ЗО берем РГ а не хоста
ResponseArea = template.Host!.WorkGroup!.ResponseArea!.Name, ResponseArea = template.Unit.BaseFields.ResponseArea,
Duration = template.ApplicationsInWork.TemplateDuration, Duration = template.Job.Group.TemplateDuration,
EK = template.Host.Ek, EK = template.Unit.Name,
FullDescription = Normalize(template.ApplicationsInWork.FullDescription), FullDescription = Normalize(template.Job.Group.FullDescription),
Solution = Normalize(template.ApplicationsInWork.Solution), Solution = Normalize(template.Job.Group.Solution),
Process = template.ApplicationsInWork.Work!.Tnk!.Subprocess!.Process!.Name, Process = template.Job.Tnk!.Subprocess!.Process!.Name,
SubProcess = template.ApplicationsInWork.Work.Tnk.Subprocess.Name, SubProcess = template.Job.Tnk.Subprocess.Name,
TNK = template.ApplicationsInWork.Work.Tnk.Name.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK, template.Host.Ek), TNK = template.Job.Tnk.Name.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK, template.Unit.Name),
Work = template.ApplicationsInWork.Work.Name.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK, template.Host.Ek), Work = template.Job.WorkName.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK, template.Unit.Name),
Initiator = settingsFromDb.Initiator Initiator = settingsFromDb.Initiator
}; };

View File

@@ -43,93 +43,94 @@ namespace PARR.GeneratorTemplates.Services
public async Task CreateTemplates(GeneratorTemplateMq query) public async Task CreateTemplates(GeneratorTemplateMq query)
{ {
//В таблице AppInWork находим РР, и смотрим ее рабочие группы. Затем по ним будем фильтровать хосты //TODO Migratin to Job
var appInWorkWg = await applicationsInWorkService.Get() ////В таблице AppInWork находим РР, и смотрим ее рабочие группы. Затем по ним будем фильтровать хосты
.Include(t => t.WorkGroups) //var appInWorkWg = await applicationsInWorkService.Get()
.FirstAsync(t => t.ApplicationId == query.ApplicationId && t.WorkId == query.WorkId); // .Include(t => t.WorkGroups)
// .FirstAsync(t => t.ApplicationId == query.ApplicationId && t.WorkId == query.WorkId);
if (!appInWorkWg.WorkGroups.Any()) //if (!appInWorkWg.WorkGroups.Any())
{ //{
logger.LogWarning($"Не генерирую шаблоны. Нет рабочих групп у ApplicationInWork с id: {appInWorkWg.Id}"); // logger.LogWarning($"Не генерирую шаблоны. Нет рабочих групп у ApplicationInWork с id: {appInWorkWg.Id}");
return; // return;
} //}
var workGroups = appInWorkWg.WorkGroups.ToList(); //var workGroups = appInWorkWg.WorkGroups.ToList();
//Согласно параметрам, находит все ЭК в таблице Hosts. ////Согласно параметрам, находит все ЭК в таблице Hosts.
//Далее проверяет есть ли такие шаблоны в таблице Templates, если нет, то создает, активирует и ставит статус Creating. ////Далее проверяет есть ли такие шаблоны в таблице Templates, если нет, то создает, активирует и ставит статус Creating.
//Если такие шаблоны уже есть, ничего с ними не делает. ////Если такие шаблоны уже есть, ничего с ними не делает.
string ekPattern = SqlHelpers.RegexToLike(query.Ek); //string ekPattern = SqlHelpers.RegexToLike(query.Ek);
// список хостов для создания шаблонов //// список хостов для создания шаблонов
var queryHosts = hostService.Get() //var queryHosts = hostService.Get()
//.Include(t => t.WorkGroupItem) // //.Include(t => t.WorkGroupItem)
.Include(t => t.ApplicationsInHosts) // .Include(t => t.ApplicationsInHosts)
.ThenInclude(t => t.Application).ThenInclude(t => t!.ApplicationsInWorks).ThenInclude(w => w.Work) // .ThenInclude(t => t.Application).ThenInclude(t => t!.ApplicationsInWorks).ThenInclude(w => w.Work)
.Include(t => t.Templates) // .Include(t => t.Templates)
.ThenInclude(w => w.ApplicationsInWork) // .ThenInclude(w => w.ApplicationsInWork)
.Include(t => t.ResponseArea) // .Include(t => t.ResponseArea)
.Where(t => // .Where(t =>
t.ApplicationsInHosts.Any(h => // t.ApplicationsInHosts.Any(h =>
h.ApplicationId == query.ApplicationId // h.ApplicationId == query.ApplicationId
&& h.Application!.ApplicationsInWorks.Any(w => w.WorkId == query.WorkId) // && h.Application!.ApplicationsInWorks.Any(w => w.WorkId == query.WorkId)
) // )
&& EF.Functions.Like(t.Ek.ToLower(), ekPattern) // && EF.Functions.Like(t.Ek.ToLower(), ekPattern)
// смотрим что нет такого шаблона // // смотрим что нет такого шаблона
&& t.Templates.Any(templ => templ.ApplicationsInWork!.WorkId == query.WorkId && templ.ApplicationsInWork.ApplicationId == query.ApplicationId) == false // && t.Templates.Any(templ => templ.ApplicationsInWork!.WorkId == query.WorkId && templ.ApplicationsInWork.ApplicationId == query.ApplicationId) == false
// смотрим что у этих хостов есть нужные группы // // смотрим что у этих хостов есть нужные группы
//&& workGroups.Any(x => x.WorkGroupId == t.WorkGroupId) // //&& workGroups.Any(x => x.WorkGroupId == t.WorkGroupId)
); // );
// статус ЭК //// статус ЭК
if (query.StatusEk > 0) //if (query.StatusEk > 0)
queryHosts = queryHosts.Where(t => t.EkStatusCode == query.StatusEk); // queryHosts = queryHosts.Where(t => t.EkStatusCode == query.StatusEk);
var hosts = await queryHosts //var hosts = await queryHosts
.AsSplitQuery() // .AsSplitQuery()
.ToListAsync(); // .ToListAsync();
// Исключаем хосты у которых нет нужных групп //// Исключаем хосты у которых нет нужных групп
hosts = hosts.Where(t => workGroups.Any(x => x.WorkGroupId == t.WorkGroupId)).ToList(); //hosts = hosts.Where(t => workGroups.Any(x => x.WorkGroupId == t.WorkGroupId)).ToList();
if (!hosts.Any()) //if (!hosts.Any())
{ //{
logger.LogInformation($"Не найдено ЭК попадающих под условие: ${JsonSerializer.Serialize(query)}"); // logger.LogInformation($"Не найдено ЭК попадающих под условие: ${JsonSerializer.Serialize(query)}");
return; // return;
} //}
// хосты группируем по РГ, чтоб потом распределить/рассчитать NextRun //// хосты группируем по РГ, чтоб потом распределить/рассчитать NextRun
var groupingHostByWg = hosts.GroupBy(t => t.WorkGroupId); //var groupingHostByWg = hosts.GroupBy(t => t.WorkGroupId);
foreach (var group in groupingHostByWg) //foreach (var group in groupingHostByWg)
{ //{
var groupingHosts = group.ToList(); // var groupingHosts = group.ToList();
var templates = CreateQueryTemplates(groupingHosts, query); // var templates = CreateQueryTemplates(groupingHosts, query);
//проверяем, что нет шаблонов с такими именами, исключаем их // //проверяем, что нет шаблонов с такими именами, исключаем их
templates = await ExcludeExistTemplatesAsync(templates); // templates = await ExcludeExistTemplatesAsync(templates);
if (!templates.Any()) // if (!templates.Any())
continue; // continue;
//заполняем NextRun // //заполняем NextRun
templates = await templateDistributor.DistributeTemplateAsync(templates, appInWorkWg.Id, (Guid)group.Key!); // templates = await templateDistributor.DistributeTemplateAsync(templates, appInWorkWg.Id, (Guid)group.Key!);
// сохраняем // // сохраняем
foreach (var template in templates) // foreach (var template in templates)
{ // {
if (!await templateService.CreateAsync(template) || !await templateService.CommitAsync(query.HistoryInitiator)) // if (!await templateService.CreateAsync(template) || !await templateService.CommitAsync(query.HistoryInitiator))
{ // {
logger.LogError($"Ошибка при создании шаблона: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, HostId: {template.HostId}"); // logger.LogError($"Ошибка при создании шаблона: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, HostId: {template.HostId}");
} // }
else // else
{ // {
logger.LogInformation($"Создан шаблон: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, " + // logger.LogInformation($"Создан шаблон: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, " +
$"HostId: {template.HostId}"); // $"HostId: {template.HostId}");
} // }
} // }
} //}
#region создавали шаблоны до того, как стали группировать по РГ #region создавали шаблоны до того, как стали группировать по РГ
////Создаем шаблоны ////Создаем шаблоны
@@ -231,8 +232,8 @@ namespace PARR.GeneratorTemplates.Services
), ),
IsActiveTemplate = query.IsActiveTemplate ?? false, IsActiveTemplate = query.IsActiveTemplate ?? false,
IsActiveSchedule = query.IsActiveSchedule ?? false, IsActiveSchedule = query.IsActiveSchedule ?? false,
ApplicationInWorkId = appInWork.Id, JobId = appInWork.Id,//TODO Migratin to Job
HostId = host.Id, UnitId = host.Id,//TODO Migratin to Job
// NextRun не задаем значение, его рассчитаем позже // NextRun не задаем значение, его рассчитаем позже
//NextRun = ???, //NextRun = ???,
LastRun = null LastRun = null
@@ -270,26 +271,26 @@ namespace PARR.GeneratorTemplates.Services
string ekPattern = SqlHelpers.RegexToLike(query.Ek); string ekPattern = SqlHelpers.RegexToLike(query.Ek);
var queryTemplates = templateService.Get() var queryTemplates = templateService.Get()
.Include(t => t.Host) .Include(t => t.Unit)//TODO Migratin to Job
.Include(t => t.ApplicationsInWork) .Include(t => t.Job)//TODO Migratin to Job
.Include(t => t.RobotConfigurations) .Include(t => t.RobotConfigurations)
.Where(t => .Where(t =>
(t.IsActiveTemplate == true || t.IsActiveSchedule == true) (t.IsActiveTemplate == true || t.IsActiveSchedule == true)
&& t.ApplicationsInWork!.ApplicationId == query.ApplicationId //&& t.ApplicationsInWork!.ApplicationId == query.ApplicationId//TODO Migratin to Job
&& t.ApplicationsInWork!.WorkId == query.WorkId //&& t.ApplicationsInWork!.WorkId == query.WorkId//TODO Migratin to Job
&& EF.Functions.Like(t.Host!.Ek.ToLower(), ekPattern) && EF.Functions.Like(t.Unit!.Name.ToLower(), ekPattern)
); );
// статус ЭК // статус ЭК
if (query.StatusEk > 0) if (query.StatusEk > 0)
queryTemplates = queryTemplates.Where(t => t.Host!.EkStatusCode == query.StatusEk); queryTemplates = queryTemplates;//.Where(t => t.Unit!.BaseFields.Status == query.StatusEk);//TODO Migratin to Job
var existTemplates = await queryTemplates var existTemplates = await queryTemplates
.AsSplitQuery() .AsSplitQuery()
.ToListAsync(); .ToListAsync();
// Исключаем хосты у которых нет нужных групп // Исключаем хосты у которых нет нужных групп
existTemplates = existTemplates.Where(t => workGroups.Any(x => x.WorkGroupId == t.Host.WorkGroupId)).ToList(); existTemplates = existTemplates.Where(t => workGroups.Any(x => x.WorkGroup.Name == t.Unit.BaseFields.WorkGroup)).ToList();
if (!existTemplates.Any()) if (!existTemplates.Any())
{ {

View File

@@ -121,7 +121,7 @@ namespace PARR.Master.Services
if (isAgentStarted == true && isAgentEnded == false) if (isAgentStarted == true && isAgentEnded == false)
{ {
var lastStrartDate = allHistory.Last(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.Start).DateCreated; var lastStrartDate = allHistory.Last(t => t.HistoryLevelId == (int)AgentHistoryLevelEnum.Start).DateCreated;
var timeout = (double)order.Template!.ApplicationsInWork!.AgentTimeOutSec!; var timeout = (double)order.Template!.Job!.Group!.AgentTimeOutSec!;
if (lastStrartDate.AddSeconds(timeout) <= DateTimeOffset.UtcNow) if (lastStrartDate.AddSeconds(timeout) <= DateTimeOffset.UtcNow)
{ {
@@ -182,7 +182,7 @@ namespace PARR.Master.Services
t.TemplateId == order.TemplateId t.TemplateId == order.TemplateId
&& t.DateCreated > order.GenerateDate!.Value.Add(-orderManageSettings.FindAgentHistoryStartOffset) && t.DateCreated > order.GenerateDate!.Value.Add(-orderManageSettings.FindAgentHistoryStartOffset)
//&& t.DateCreated <= order.GenerateDate!.Value.AddSeconds(order.Template!.ApplicationsInWork!.AgentTimeOutSec!.Value) //&& t.DateCreated <= order.GenerateDate!.Value.AddSeconds(order.Template!.ApplicationsInWork!.AgentTimeOutSec!.Value)
&& t.DateCreated <= order.GenerateDate!.Value.Add(order.Template!.ApplicationsInWork!.TemplateDurationTimeSpan!.Value) && t.DateCreated <= order.GenerateDate!.Value.Add(order.Template!.Job!.Group!.TemplateDurationTimeSpan!.Value)
&& t.OrderId == null && t.OrderId == null
) )
.OrderBy(t => t.DateCreated) .OrderBy(t => t.DateCreated)
@@ -244,14 +244,14 @@ namespace PARR.Master.Services
private IQueryable<Order> GetOrdres() private IQueryable<Order> GetOrdres()
{ {
return orderService.Get() return orderService.Get()
.Include(t => t.Template).ThenInclude(t => t!.ApplicationsInWork) .Include(t => t.Template).ThenInclude(t => t!.Job)
.Include(t => t.AgentHistories) .Include(t => t.AgentHistories)
.Where(t => .Where(t =>
t.TemplateId.HasValue t.TemplateId.HasValue
&& t.Template!.ApplicationsInWork!.IsAgent == true && t.Template!.Job!.Group!.IsAgent == true
&& t.GenerateDate.HasValue && t.GenerateDate.HasValue
&& t.Template!.ApplicationsInWork!.AgentTimeOutSec.HasValue && t.Template!.Job!.Group!.AgentTimeOutSec.HasValue
&& string.IsNullOrEmpty(t.Template!.ApplicationsInWork!.TemplateDuration) == false && string.IsNullOrEmpty(t.Template!.Job!.Group!.TemplateDuration) == false
&& t.ExpirationDate > DateTimeOffset.UtcNow && t.ExpirationDate > DateTimeOffset.UtcNow
).OrderBy(t => t.DateCreated); ).OrderBy(t => t.DateCreated);
} }

View File

@@ -64,7 +64,7 @@ namespace PARR.NextRun
foreach (var template in templates) foreach (var template in templates)
{ {
var nextRun = await esppScheduleTransformService.GetNextDateAsync(template.ApplicationInWorkId, template.NextRun); var nextRun = await esppScheduleTransformService.GetNextDateAsync(template.JobId, template.NextRun);
template.LastRun = template.NextRun; template.LastRun = template.NextRun;
template.NextRun = nextRun; template.NextRun = nextRun;

View File

@@ -35,11 +35,11 @@ internal class TemplateActivator : ITemplateActivator
} }
public async Task ChangeStateAsync(Guid applicationInWorkId, TemplateActivatorActionsEnum action, IHistoryInitiator? historyInitiator) public async Task ChangeStateAsync(Guid applicationInWorkId, TemplateActivatorActionsEnum action, IHistoryInitiator? historyInitiator)//TODO Migratin to Job
{ {
var query = templateService.Get() var query = templateService.Get()
.Include(t => t.RobotConfigurations).ThenInclude(t => t.Robot) .Include(t => t.RobotConfigurations).ThenInclude(t => t.Robot)
.Where(t => t.ApplicationInWorkId == applicationInWorkId); .Where(t => t.JobId == applicationInWorkId);//TODO Migratin to Job
var changes = 0; var changes = 0;
switch (action) switch (action)
{ {
@@ -121,7 +121,7 @@ internal class TemplateActivator : ITemplateActivator
var changes = 0; var changes = 0;
//Добавляем информацию о рабочих группах для возможности их фильтрации //Добавляем информацию о рабочих группах для возможности их фильтрации
query = query.Include(t => t.Host).ThenInclude(h => h!.WorkGroup); query = query.Include(t => t.Unit);//TODO Migratin to Job
//Получаем настройки авто-контроля //Получаем настройки авто-контроля
var jobAutoControlSettings = await GetJobAutoControlSettingsAsync(applicationInWorkId); var jobAutoControlSettings = await GetJobAutoControlSettingsAsync(applicationInWorkId);
@@ -149,7 +149,7 @@ internal class TemplateActivator : ITemplateActivator
//Фильтруем по рабочим группам //Фильтруем по рабочим группам
var appInWorkWorkGroups = GetApplicationInWorkWorkGroups(applicationInWorkId); var appInWorkWorkGroups = GetApplicationInWorkWorkGroups(applicationInWorkId);
if (appInWorkWorkGroups.Any()) if (appInWorkWorkGroups.Any())
templates = templates.Where(t => appInWorkWorkGroups.Any(awg => t.Host!.WorkGroupId == awg.WorkGroupId)).ToList(); templates = templates.Where(t => appInWorkWorkGroups.Any(awg => t.Unit!.BaseFields!.WorkGroup == awg.WorkGroup!.Name)).ToList();//TODO Migratin to Job
//Фильтруем соответствие статусов ЭК условиям автоконтроля //Фильтруем соответствие статусов ЭК условиям автоконтроля
var checkEkStatus = FilterTemplatesByWrongEkStatus(templates, trueEkStatuses, isActivate); var checkEkStatus = FilterTemplatesByWrongEkStatus(templates, trueEkStatuses, isActivate);
@@ -177,9 +177,9 @@ internal class TemplateActivator : ITemplateActivator
private List<Template> FilterTemplatesByWrongEkStatus(List<Template> templates, ICollection<JobAutoControlInEkStatus> trueEkStatuses, bool isActivate) private List<Template> FilterTemplatesByWrongEkStatus(List<Template> templates, ICollection<JobAutoControlInEkStatus> trueEkStatuses, bool isActivate)
{ {
if (isActivate) if (isActivate)
return templates.Where(t => trueEkStatuses.Any(tes => tes.EkStatusCode == t.Host!.EkStatusCode)).ToList(); return templates.Where(t => trueEkStatuses.Any(tes => tes.EkStatus!.Name == t.Unit!.BaseFields!.Status)).ToList();//TODO Migratin to Job
return templates.Where(t => !trueEkStatuses.Any(tes => tes.EkStatusCode == t.Host!.EkStatusCode)).ToList(); return templates.Where(t => !trueEkStatuses.Any(tes => tes.EkStatus!.Name == t.Unit!.BaseFields!.Status)).ToList();//TODO Migratin to Job
} }
private List<Template> FilterTemplatesByNameNotMatchToMasks(IQueryable<Template> query, ICollection<JobEkMask> trueMasks) private List<Template> FilterTemplatesByNameNotMatchToMasks(IQueryable<Template> query, ICollection<JobEkMask> trueMasks)
@@ -187,7 +187,7 @@ internal class TemplateActivator : ITemplateActivator
var result = new List<Template>(); var result = new List<Template>();
foreach (var mask in trueMasks) foreach (var mask in trueMasks)
{ {
var templates = query.Where(t => EF.Functions.Like(t.Host!.Ek.ToLower(), SqlHelpers.RegexToLike(mask.Name))).ToList(); var templates = query.Where(t => EF.Functions.Like(t.Unit!.Name.ToLower(), SqlHelpers.RegexToLike(mask.Name))).ToList();
result.AddRange(templates); result.AddRange(templates);
} }

View File

@@ -21,27 +21,28 @@ namespace PARR.TemplateDistributor.Services
{ {
using (var scope = serviceProvider.CreateScope()) using (var scope = serviceProvider.CreateScope())
{ {
var service = scope.ServiceProvider.GetService<IApplicationsInWorkService>(); //TODO Migratin to Job
//var service = scope.ServiceProvider.GetService<IApplicationsInWorkService>();
if (service == null) //if (service == null)
throw new Exception($"Не найден сервис: {nameof(IApplicationsInWorkService)}"); // throw new Exception($"Не найден сервис: {nameof(IApplicationsInWorkService)}");
var appInWork = await service.Get() //var appInWork = await service.Get()//TODO Migratin to Job
.Include(aiw => aiw.EsppSchValues) // //.Include(aiw => aiw.EsppSchValues)
.FirstOrDefaultAsync(t => t.Id == applicationInWorkId); // .FirstOrDefaultAsync(t => t.Id == applicationInWorkId);
if (appInWork == null) //if (appInWork == null)
{ //{
logger.LogError($"Не найдена регалментная работа {nameof(applicationInWorkId)}: {applicationInWorkId}"); // logger.LogError($"Не найдена регалментная работа {nameof(applicationInWorkId)}: {applicationInWorkId}");
return false; // return false;
} //}
if (appInWork.IsAutoDistributionEnabled && appInWork.EsppSchValues.Count !=1) //if (appInWork.IsAutoDistributionEnabled && appInWork.EsppSchValues.Count !=1)
{ //{
logger.LogError($"Регалментная работа {nameof(applicationInWorkId)}: {applicationInWorkId} должна иметь только одно значение EsppSchTypeValue" + // logger.LogError($"Регалментная работа {nameof(applicationInWorkId)}: {applicationInWorkId} должна иметь только одно значение EsppSchTypeValue" +
$", соответствующее режиму равномерного распределения по периоду"); // $", соответствующее режиму равномерного распределения по периоду");
return false; // return false;
} //}
return true; return true;
} }

View File

@@ -5,6 +5,7 @@ using PARR.Constants;
using PARR.DAL.Models; using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.DAL.TransformServices; using PARR.DAL.TransformServices;
using System.Reflection.Metadata.Ecma335;
namespace PARR.TemplateDistributor namespace PARR.TemplateDistributor
{ {
@@ -38,20 +39,20 @@ namespace PARR.TemplateDistributor
} }
public async Task UpdateScheduleAsync(Guid applicationInWorkId) public async Task UpdateScheduleAsync(Guid applicationInWorkId)//TODO Migratin to Job
{ {
var appInWork = await applicationsInWorkService.GetAsync(applicationInWorkId); var appInWork = await applicationsInWorkService.GetAsync(applicationInWorkId);
var templates = await templateService.Get() var templates = await templateService.Get()
.Include(t => t.Host) .Include(t => t.Unit)//TODO Migratin to Job
.ThenInclude(h => h!.WorkGroup) //.ThenInclude(h => h!.WorkGroup)
.Where(t => t.ApplicationInWorkId == applicationInWorkId && t.Host!.WorkGroupId != null) .Where(t => t.JobId == applicationInWorkId && t.Unit!.BaseFields!.WorkGroup != null)//TODO Migratin to Job
.ToListAsync(); .ToListAsync();
//Группируем шаблоны по рабочим группам //Группируем шаблоны по рабочим группам
var workGroupsWithTemplates = templates.GroupBy(t => t.Host!.WorkGroupId); var workGroupsWithTemplates = templates.GroupBy(t => t.Unit!.BaseFields!.WorkGroup);
foreach (var workGroupWithTemplates in workGroupsWithTemplates) /*foreach (var workGroupWithTemplates in workGroupsWithTemplates)
{ {
var wgId = (Guid)workGroupWithTemplates.Key!; var wgId = (Guid)workGroupWithTemplates.Key!;
var values = workGroupWithTemplates.ToList(); var values = workGroupWithTemplates.ToList();
@@ -79,163 +80,167 @@ namespace PARR.TemplateDistributor
if (distrTemplates.Any()) if (distrTemplates.Any())
if (!await templateService.CommitAsync()) if (!await templateService.CommitAsync())
logger.LogError($"Ошибка записи изменений в БД при перераспределении NextRun шаблонов РР({applicationInWorkId})"); logger.LogError($"Ошибка записи изменений в БД при перераспределении NextRun шаблонов РР({applicationInWorkId})");
} }*/
// TODO Migratin to Job
} }
public async Task<List<Template>> DistributeTemplateAsync(List<Template> templates, Guid applicationInWorkId, Guid workGroupId) public async Task<List<Template>> DistributeTemplateAsync(List<Template> templates, Guid applicationInWorkId, Guid workGroupId)
{ {
var appInWork = await applicationsInWorkService.Get() // var appInWork = await applicationsInWorkService.Get()
.Include(aiw => aiw.EsppSchValues) // .Include(aiw => aiw.EsppSchValues)
.ThenInclude(esv => esv.EsppSchTypeValue) // .ThenInclude(esv => esv.EsppSchTypeValue)
.ThenInclude(etv => etv!.DistributionPeriod) // .ThenInclude(etv => etv!.DistributionPeriod)
.FirstAsync(t => t.Id == applicationInWorkId); // .FirstAsync(t => t.Id == applicationInWorkId);
var refDate = appInWork.ReferenceDate; // var refDate = appInWork.ReferenceDate;
//Проверяем наличие распределения РР на период // //Проверяем наличие распределения РР на период
if (appInWork.IsAutoDistributionEnabled) // if (appInWork.IsAutoDistributionEnabled)
{ // {
var existingTemplates = await templateService.Get() // var existingTemplates = await templateService.Get()
.Include(t => t.Host) // .Include(t => t.Unit)
.Where(t => t.ApplicationInWorkId == applicationInWorkId && t.Host!.WorkGroupId == workGroupId) // .Where(t => t.JobId == applicationInWorkId
.ToListAsync(); // //&& t.Host!.WorkGroupId == workGroupId//TODO Migratin to Job
// )
// .ToListAsync();
//Удалим из входных шаблонов уже существующие в БД (по идее, такого никогда не должно случиться) // //Удалим из входных шаблонов уже существующие в БД (по идее, такого никогда не должно случиться)
var duplicates = templates.Select(t => t.Id).Where(t => existingTemplates.Any(et => et.Id == t)).ToList(); // var duplicates = templates.Select(t => t.Id).Where(t => existingTemplates.Any(et => et.Id == t)).ToList();
if (duplicates.Count > 0) // if (duplicates.Count > 0)
{ // {
duplicates.ForEach(t => // duplicates.ForEach(t =>
{ // {
logger.LogWarning($"Для распределения AiW({applicationInWorkId}),workGroupId({workGroupId}) передан существующий в базе данных шаблон {t}"); // logger.LogWarning($"Для распределения AiW({applicationInWorkId}),workGroupId({workGroupId}) передан существующий в базе данных шаблон {t}");
}); // });
templates.RemoveAll(t => duplicates.Any(dt => dt == t.Id)); // templates.RemoveAll(t => duplicates.Any(dt => dt == t.Id));
} // }
existingTemplates.AddRange(templates); // existingTemplates.AddRange(templates);
//Если распределенная РР получаем начало // //Если распределенная РР получаем начало
var period = appInWork.EsppSchValues.First()!.EsppSchTypeValue!.DistributionPeriod; // var period = appInWork.EsppSchValues.First()!.EsppSchTypeValue!.DistributionPeriod;
var periodType = ParseDistributionPeriodType(period!.Type); // var periodType = ParseDistributionPeriodType(period!.Type);
var workDays = await GetWorkDaysAsync(appInWork); // var workDays = await GetWorkDaysAsync(appInWork);
var result = new List<Template>(); // var result = new List<Template>();
//распределяем РР отдельно активированные // //распределяем РР отдельно активированные
var activatedTemplates = existingTemplates.Where(t => t.IsActiveTemplate && t.IsActiveSchedule).ToList(); // var activatedTemplates = existingTemplates.Where(t => t.IsActiveTemplate && t.IsActiveSchedule).ToList();
if (activatedTemplates.Count > 0) // if (activatedTemplates.Count > 0)
{ // {
Distribute(ref activatedTemplates, refDate, period, periodType, workDays); // Distribute(ref activatedTemplates, refDate, period, periodType, workDays);
// result.AddRange(activatedTemplates); // // result.AddRange(activatedTemplates);
} // }
//распределяем РР отдельно деактивированные // //распределяем РР отдельно деактивированные
var deactivatedTemplates = existingTemplates.Where(t => // var deactivatedTemplates = existingTemplates.Where(t =>
!t.IsActiveTemplate || !t.IsActiveSchedule || ( // !t.IsActiveTemplate || !t.IsActiveSchedule || (
!t.IsActiveTemplate && !t.IsActiveSchedule // !t.IsActiveTemplate && !t.IsActiveSchedule
)).ToList(); // )).ToList();
if (deactivatedTemplates.Count > 0) // if (deactivatedTemplates.Count > 0)
{ // {
Distribute(ref deactivatedTemplates, refDate, period, periodType, workDays); // Distribute(ref deactivatedTemplates, refDate, period, periodType, workDays);
// result.AddRange(deactivatedTemplates); // // result.AddRange(deactivatedTemplates);
} // }
if (templates.Any()) // if (templates.Any())
{ // {
// это была генерация шаблонов, не нужны все шаблоны, нужны только те которые передал для получения NextRun // // это была генерация шаблонов, не нужны все шаблоны, нужны только те которые передал для получения NextRun
result.AddRange(templates); // result.AddRange(templates);
} // }
else // else
{ // {
// это было распределение шаблонов, добавляем активированные и деактивированные // // это было распределение шаблонов, добавляем активированные и деактивированные
result.AddRange(activatedTemplates); // result.AddRange(activatedTemplates);
result.AddRange(deactivatedTemplates); // result.AddRange(deactivatedTemplates);
} // }
return result; // return result;
#region comments // #region comments
//var d = new Dictionary<DateOnly, List<Template>>(); // //var d = new Dictionary<DateOnly, List<Template>>();
//foreach (var wd in workDays) // //foreach (var wd in workDays)
//{ // //{
// var wrokDateTimeOffset = new DateTimeOffset( // // var wrokDateTimeOffset = new DateTimeOffset(
// wd.Year, wd.Month, wd.Day, // // wd.Year, wd.Month, wd.Day,
// refDate.Hour, refDate.Minute, refDate.Second, // // refDate.Hour, refDate.Minute, refDate.Second,
// new TimeSpan(0, 0, 0)); // // new TimeSpan(0, 0, 0));
// if (wrokDateTimeOffset < DateTimeOffset.UtcNow) // // if (wrokDateTimeOffset < DateTimeOffset.UtcNow)
// wrokDateTimeOffset = esppScheduleTransformService.GetNextDateForDistributionRun(wrokDateTimeOffset, periodType, period.Duration); // // wrokDateTimeOffset = esppScheduleTransformService.GetNextDateForDistributionRun(wrokDateTimeOffset, periodType, period.Duration);
// var assignedTemplates = existingTemplates.Where(t => t.NextRun == wrokDateTimeOffset).ToList(); // // var assignedTemplates = existingTemplates.Where(t => t.NextRun == wrokDateTimeOffset).ToList();
// d.Add(wd, assignedTemplates); // // d.Add(wd, assignedTemplates);
//} // //}
//var templatesPerStep = (double)templates.Count() / workDays.Count();// // //var templatesPerStep = (double)templates.Count() / workDays.Count();//
//var currentTemplateStep = (int)Math.Ceiling(templatesPerStep); // //var currentTemplateStep = (int)Math.Ceiling(templatesPerStep);
//var delta = templatesPerStep - currentTemplateStep; // //var delta = templatesPerStep - currentTemplateStep;
////templates.First().NextRun = currentDay; // ////templates.First().NextRun = currentDay;
//var templateDistributed = 0; // //var templateDistributed = 0;
////Отталкиваясь от количества // ////Отталкиваясь от количества
//while (templateDistributed < templates.Count()) // //while (templateDistributed < templates.Count())
//{ // //{
// var wdCounts = d.Select(wd => wd.Value).OrderBy(count => count).ToArray(); // // var wdCounts = d.Select(wd => wd.Value).OrderBy(count => count).ToArray();
// var templateCountDelta = d.Max(t => t.Value.Count()) - d.Min(t => t.Value.Count()); // // var templateCountDelta = d.Max(t => t.Value.Count()) - d.Min(t => t.Value.Count());
// var addingTemplatesCount = wdCounts.Length > 1 ? // // var addingTemplatesCount = wdCounts.Length > 1 ?
// (templateCountDelta == 0) ? (int)Math.Ceiling(templatesPerStep) : templateCountDelta : // // (templateCountDelta == 0) ? (int)Math.Ceiling(templatesPerStep) : templateCountDelta :
// (int)Math.Ceiling(templatesPerStep); // // (int)Math.Ceiling(templatesPerStep);
// var workDaysWithMinTemplates = d.Where(wd => wd.Value == wdCounts[0]).ToArray(); // // var workDaysWithMinTemplates = d.Where(wd => wd.Value == wdCounts[0]).ToArray();
// if (workDaysWithMinTemplates.Length * addingTemplatesCount < templates.Count()) // // if (workDaysWithMinTemplates.Length * addingTemplatesCount < templates.Count())
// { // // {
// foreach (var wd in workDaysWithMinTemplates) // // foreach (var wd in workDaysWithMinTemplates)
// { // // {
// //Считаем DateTimeOffset, потому что у нас только дата пока // // //Считаем DateTimeOffset, потому что у нас только дата пока
// var currentDay = new DateTimeOffset( // // var currentDay = new DateTimeOffset(
// wd.Key.Year, wd.Key.Month, wd.Key.Day, // // wd.Key.Year, wd.Key.Month, wd.Key.Day,
// refDate.Hour, refDate.Minute, refDate.Second, // // refDate.Hour, refDate.Minute, refDate.Second,
// new TimeSpan(0, 0, 0)); // // new TimeSpan(0, 0, 0));
// templates.Skip(templateDistributed).Take(addingTemplatesCount).ToList().ForEach(t => // // templates.Skip(templateDistributed).Take(addingTemplatesCount).ToList().ForEach(t =>
// { // // {
// t.NextRun = currentDay; // // t.NextRun = currentDay;
// d[wd.Key].Add(t); // // d[wd.Key].Add(t);
// }); // // });
// templateDistributed += addingTemplatesCount; // // templateDistributed += addingTemplatesCount;
// } // // }
// } // // }
// else // // else
// { // // {
// while (templateDistributed < templates.Count()) // // while (templateDistributed < templates.Count())
// { // // {
// var wd = d.Where(wd => wd.Value == d.Min(t => t.Value)).First(); // // var wd = d.Where(wd => wd.Value == d.Min(t => t.Value)).First();
// //Считаем DateTimeOffset, потому что у нас только дата пока // // //Считаем DateTimeOffset, потому что у нас только дата пока
// var currentDay = new DateTimeOffset( // // var currentDay = new DateTimeOffset(
// wd.Key.Year, wd.Key.Month, wd.Key.Day, // // wd.Key.Year, wd.Key.Month, wd.Key.Day,
// refDate.Hour, refDate.Minute, refDate.Second, // // refDate.Hour, refDate.Minute, refDate.Second,
// new TimeSpan(0, 0, 0)); // // new TimeSpan(0, 0, 0));
// templates.Skip(templateDistributed).Take(addingTemplatesCount).ToList().ForEach(t => // // templates.Skip(templateDistributed).Take(addingTemplatesCount).ToList().ForEach(t =>
// { // // {
// t.NextRun = currentDay; // // t.NextRun = currentDay;
// d[wd.Key].Add(t); // // d[wd.Key].Add(t);
// }); // // });
// templateDistributed += addingTemplatesCount; // // templateDistributed += addingTemplatesCount;
// } // // }
// } // // }
//} // //}
#endregion // #endregion
} // }
else // else
// templates.ForEach(t => t.NextRun = appInWork!.ReferenceDate); // // templates.ForEach(t => t.NextRun = appInWork!.ReferenceDate);
// это не автораспределение, по ReferenceDate получаем ближайший рабочий день // // это не автораспределение, по ReferenceDate получаем ближайший рабочий день
templates.ForEach(async t => t.NextRun = await nextRunModifierService.GetWorkDayAsync(appInWork!.ReferenceDate)); // templates.ForEach(async t => t.NextRun = await nextRunModifierService.GetWorkDayAsync(appInWork!.ReferenceDate));
return templates; // return templates;
return new List<Template>();
} }
private void Distribute(ref List<Template> templates, DateTimeOffset refDate, DistributionPeriod period, DistributionPeriodTypeEnum periodType, List<DateOnly> workDays) private void Distribute(ref List<Template> templates, DateTimeOffset refDate, DistributionPeriod period, DistributionPeriodTypeEnum periodType, List<DateOnly> workDays)
@@ -246,9 +251,9 @@ namespace PARR.TemplateDistributor
//Проверяем шаблоны уже распределённые, чтобы не перемещать лишний раз //Проверяем шаблоны уже распределённые, чтобы не перемещать лишний раз
var templateToDistrib = GetTemplatesToDistribute(ref distrPlan, templates); var templateToDistrib = GetTemplatesToDistribute(ref distrPlan, templates);
//logger.LogInformation($"{GetType().Name}(AppInWId:{templates.Select(t => t.ApplicationInWorkId).First()}, WorkGroup:{templates.Select(t => t.Host!.WorkGroup!.Name).First()}) запланировал изменение даты следующего срабатывания у {templateToDistrib.Count()} существующих шаблона(ов), {templates.Count() - templateToDistrib.Count()} остались без изменений");
string? loggerWorkGroup = templates.FirstOrDefault()?.Host?.WorkGroup != null ? templates.FirstOrDefault()?.Host?.WorkGroup?.Name : templates.FirstOrDefault()?.Host?.WorkGroupId?.ToString(); string? loggerWorkGroup = templates.FirstOrDefault()?.Unit?.BaseFields?.WorkGroup != null ? templates.FirstOrDefault()?.Unit.BaseFields.WorkGroup : templates.FirstOrDefault()?.Unit?.BaseFields?.WorkGroup?.ToString();
logger.LogInformation($"{GetType().Name}(AppInWId:{templates.Select(t => t.ApplicationInWorkId).First()}, " + logger.LogInformation($"{GetType().Name}(AppInWId:{templates.Select(t => t.JobId).First()}, " +
$"WorkGroup:{loggerWorkGroup}) " + $"WorkGroup:{loggerWorkGroup}) " +
$"запланировал изменение даты следующего срабатывания у {templateToDistrib.Count()} существующих шаблона(ов), {templates.Count() - templateToDistrib.Count()} остались без изменений"); $"запланировал изменение даты следующего срабатывания у {templateToDistrib.Count()} существующих шаблона(ов), {templates.Count() - templateToDistrib.Count()} остались без изменений");
@@ -288,47 +293,49 @@ namespace PARR.TemplateDistributor
/// <returns></returns> /// <returns></returns>
private async Task<List<DateOnly>> GetWorkDaysAsync(ApplicationsInWork appInWork) private async Task<List<DateOnly>> GetWorkDaysAsync(ApplicationsInWork appInWork)
{ {
var period = appInWork.EsppSchValues.FirstOrDefault()?.EsppSchTypeValue?.DistributionPeriod; //var period = appInWork.EsppSchValues.FirstOrDefault()?.EsppSchTypeValue?.DistributionPeriod;
var periodType = ParseDistributionPeriodType(period!.Type); //var periodType = ParseDistributionPeriodType(period!.Type);
//старт период, берем сейчас, будем получать рабочие дни с вычетом выходных на весь период сразу. ////старт период, берем сейчас, будем получать рабочие дни с вычетом выходных на весь период сразу.
var startPeriod = DateOnly.FromDateTime(DateTimeOffset.UtcNow.Date); //var startPeriod = DateOnly.FromDateTime(DateTimeOffset.UtcNow.Date);
// старт период считаем относительно refDate //// старт период считаем относительно refDate
//var startPeriod = await esppScheduleTransformService.GetStartPeriodForDateAsync(appInWork.Id, appInWork.ReferenceDate, appInWork.ReferenceDate, periodType, period.Duration); ////var startPeriod = await esppScheduleTransformService.GetStartPeriodForDateAsync(appInWork.Id, appInWork.ReferenceDate, appInWork.ReferenceDate, periodType, period.Duration);
var workDays = calendarService.GetWorkDatesForPeriod(startPeriod, TimeOnly.FromDateTime(appInWork.ReferenceDate.DateTime), periodType, period.Duration, weekendDayService.GetWeekends); //var workDays = calendarService.GetWorkDatesForPeriod(startPeriod, TimeOnly.FromDateTime(appInWork.ReferenceDate.DateTime), periodType, period.Duration, weekendDayService.GetWeekends);
#region старая логика //#region старая логика
//var resultWorkDays = new List<DateOnly>(); ////var resultWorkDays = new List<DateOnly>();
//workDays.ForEach(wd => ////workDays.ForEach(wd =>
//{ ////{
// var wrokDateTimeOffset = new DateTimeOffset( //// var wrokDateTimeOffset = new DateTimeOffset(
// wd.Year, wd.Month, wd.Day, //// wd.Year, wd.Month, wd.Day,
// appInWork.ReferenceDate.Hour, appInWork.ReferenceDate.Minute, appInWork.ReferenceDate.Second, //// appInWork.ReferenceDate.Hour, appInWork.ReferenceDate.Minute, appInWork.ReferenceDate.Second,
// new TimeSpan(0, 0, 0)); //// new TimeSpan(0, 0, 0));
// if (wrokDateTimeOffset < DateTimeOffset.UtcNow) //// if (wrokDateTimeOffset < DateTimeOffset.UtcNow)
// { //// {
// wrokDateTimeOffset = esppScheduleTransformService.GetNextDateForDistributionRun(wrokDateTimeOffset, periodType, period.Duration); //// wrokDateTimeOffset = esppScheduleTransformService.GetNextDateForDistributionRun(wrokDateTimeOffset, periodType, period.Duration);
// //wd = DateOnly.FromDateTime(wrokDateTimeOffset.DateTime); //// //wd = DateOnly.FromDateTime(wrokDateTimeOffset.DateTime);
// resultWorkDays.Add(DateOnly.FromDateTime(wrokDateTimeOffset.DateTime)); //// resultWorkDays.Add(DateOnly.FromDateTime(wrokDateTimeOffset.DateTime));
// } //// }
// else //// else
// { //// {
// resultWorkDays.Add(wd); //// resultWorkDays.Add(wd);
// } //// }
//}); ////});
////----- убираем даты, которые могли выйти за конец периода (из-за сдвига NextRun по рабочим дням) //////----- убираем даты, которые могли выйти за конец периода (из-за сдвига NextRun по рабочим дням)
//var endPeriod = calendarService.GetEndPeriodDate(DateOnly.FromDateTime(DateTimeOffset.UtcNow.Date), periodType, period.Duration); ////var endPeriod = calendarService.GetEndPeriodDate(DateOnly.FromDateTime(DateTimeOffset.UtcNow.Date), periodType, period.Duration);
//resultWorkDays = resultWorkDays.Where(t => t <= endPeriod).Distinct().OrderBy(t => t).ToList(); ////resultWorkDays = resultWorkDays.Where(t => t <= endPeriod).Distinct().OrderBy(t => t).ToList();
////----- //////-----
//return resultWorkDays; ////return resultWorkDays;
#endregion //#endregion
return workDays; //return workDays;
return new List<DateOnly>();
} }
/// <summary> /// <summary>

View File

@@ -41,6 +41,28 @@ namespace PARR.Test
#region test #region test
using (var scope = serviceProvider.CreateScope()) using (var scope = serviceProvider.CreateScope())
{ {
var unitService = scope.ServiceProvider.GetService<IUnitService>();
var unitsQuery = unitService!.Get()
.Include(t => t.UnitValues)
.ThenInclude(t => t.Field)
.Include(t => t.UnitValues)
.ThenInclude(t => t.Value)
.Include(t => t.ParentUnits)
.Include(t => t.ChildUnits)
.Where(t => EF.Functions.Like(t.Name, "%-ГВЦ") &&
t.UnitValues.Any(v =>
v.Field!.AihitName == ОДКАТЕГОРИЯ_ЭК" && v.Value!.Value == "система хранения данных (схд)")
&& t.UnitValues.Any(v =>
v.Field!.AihitName == "ТИП_ЭК" && v.Value!.Value == "коммутатор")
//&& t.UnitValues.Any(v =>
// v.Field!.AihitName == "АКТИВЕН" && v.Value!.Value == "1")
// && t.UnitValues.Any(v =>
// v.Field!.AihitName == "НЕУНИКАЛЬНЫЙ_ЭК" && v.Value!.Value == "0")
);
var v1 = await unitsQuery.Where(t => t.UnitValues.Any(v =>
v.Field!.AihitName == "НЕУНИКАЛЬНЫЙ_ЭК" && v.Value!.Value == "0")).ToListAsync();
/*var service = scope.ServiceProvider.GetService<ITemplateNameGeneratorService>(); /*var service = scope.ServiceProvider.GetService<ITemplateNameGeneratorService>();
var ttt = await service.GetTemplateNameAsync(Guid.Parse("ba05948b-b040-48cc-ab77-0accc9c223a0"), Guid.Parse("d4a86f24-6975-4614-98ab-431f26e3eb69"));*/ var ttt = await service.GetTemplateNameAsync(Guid.Parse("ba05948b-b040-48cc-ab77-0accc9c223a0"), Guid.Parse("d4a86f24-6975-4614-98ab-431f26e3eb69"));*/