feat(templateMatcher): Убран хардкод РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК при формировании шаблонов; добавлен метод для поиска аттрибутов ЭК по значению Code.

This commit is contained in:
Mikhail Kuznetsov
2026-05-28 16:54:51 +10:00
parent 04237cc826
commit 51bb383d06
5 changed files with 185 additions and 43 deletions

View File

@@ -3,9 +3,20 @@ using Microsoft.Extensions.Logging;
using PARR.Core.Repositories.Interfaces.Job;
using PARR.Domain.Entities.Base.History;
using PARR.Domain.Entities.Job;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace PARR.Core.Common.Helpers;
/// <summary>
/// Сервис для синхронизации свойств Job внутри JobGroup.
/// Эталоном считается Job с максимальным MaxValueRelationships.
/// Синхронизируются: WorkName, маски, IsParentRelationships, AutoControl, UnitFilters.
/// НЕ синхронизируются: Id, Name, MinValueRelationships, MaxValueRelationships, TnkId.
/// </summary>
public class JobGroupUnitFilterSynchronizeHelper
{
private readonly IJobRepository jobRepository;
@@ -25,12 +36,13 @@ public class JobGroupUnitFilterSynchronizeHelper
.ThenInclude(uf => uf.FieldFilters)
.Include(j => j.UnitFilters)
.ThenInclude(uf => uf.RelationshipFilters)
.Include(j => j.AutoControl)
.Where(j => j.GroupId == jobGroupId)
.ToListAsync(ct);
if (jobs == null || jobs.Count < 2)
{
logger.LogDebug("JobGroup {JobGroupId} содержит менее двух Job. Синхронизация фильтров не требуется.", jobGroupId);
logger.LogDebug("JobGroup {JobGroupId} содержит менее двух Job. Синхронизация не требуется.", jobGroupId);
return;
}
@@ -41,7 +53,7 @@ public class JobGroupUnitFilterSynchronizeHelper
return;
}
logger.LogInformation("Начало синхронизации фильтров для JobGroup {JobGroupId}. Эталонный Job: {ReferenceJobId}.", jobGroupId, referenceJob.Id);
logger.LogInformation("Начало синхронизации для JobGroup {JobGroupId}. Эталонный Job: {ReferenceJobId}.", jobGroupId, referenceJob.Id);
foreach (var job in jobs)
{
@@ -49,31 +61,84 @@ public class JobGroupUnitFilterSynchronizeHelper
if (job.Id == referenceJob.Id) continue;
if (!AreUnitFiltersIdentical(job.UnitFilters, referenceJob.UnitFilters))
if (!AreJobsIdentical(job, referenceJob))
{
logger.LogDebug("Фильтры Job {JobId} отличаются от эталона. Запуск обновления.", job.Id);
await ApplyFilterCorrectionAsync(job.Id, referenceJob.UnitFilters ?? Enumerable.Empty<JobUnitFilter>(), initiator, ct);
logger.LogDebug("Свойства Job {JobId} отличаются от эталона. Запуск обновления.", job.Id);
await ApplyJobCorrectionAsync(job.Id, referenceJob, initiator, ct);
}
else
{
logger.LogDebug("Фильтры Job {JobId} идентичны эталону. Пропуск.", job.Id);
logger.LogDebug("Свойства Job {JobId} идентичны эталону. Пропуск.", job.Id);
}
}
logger.LogInformation("Синхронизация фильтров для JobGroup {JobGroupId} завершена.", jobGroupId);
logger.LogInformation("Синхронизация для JobGroup {JobGroupId} завершена.", jobGroupId);
}
private async Task ApplyFilterCorrectionAsync(Guid jobId, IEnumerable<JobUnitFilter> referenceFilters, HistoryInitiator initiator, CancellationToken ct)
private bool AreJobsIdentical(Job current, Job reference)
{
// Сравнение скалярных полей (кроме Id, Name, Min/MaxValueRelationships, TnkId)
if (current.WorkName != reference.WorkName) return false;
if (current.IsParentRelationships != reference.IsParentRelationships) return false;
if (current.TemplateNameMask != reference.TemplateNameMask) return false;
if (current.WorkGroupMask != reference.WorkGroupMask) return false;
if (current.ResponseAreaMask != reference.ResponseAreaMask) return false;
// Сравнение AutoControl
if (current.AutoControl == null && reference.AutoControl != null) return false;
if (current.AutoControl != null && reference.AutoControl == null) return false;
if (current.AutoControl != null && reference.AutoControl != null)
{
if (current.AutoControl.InitUsedTemplateState != reference.AutoControl.InitUsedTemplateState) return false;
if (current.AutoControl.InitUsedScheduleState != reference.AutoControl.InitUsedScheduleState) return false;
}
// Сравнение фильтров
if (!AreUnitFiltersIdentical(current.UnitFilters, reference.UnitFilters)) return false;
return true;
}
private async Task ApplyJobCorrectionAsync(Guid jobId, Job referenceJob, HistoryInitiator initiator, CancellationToken ct)
{
var job = await jobRepository.Get()
.Include(j => j.UnitFilters)
.ThenInclude(uf => uf.FieldFilters)
.Include(j => j.UnitFilters)
.ThenInclude(uf => uf.RelationshipFilters)
.Include(j => j.AutoControl)
.FirstOrDefaultAsync(j => j.Id == jobId, ct);
if (job == null) return;
// 1. Обновляем скалярные поля
job.WorkName = referenceJob.WorkName;
job.IsParentRelationships = referenceJob.IsParentRelationships;
job.TemplateNameMask = referenceJob.TemplateNameMask;
job.WorkGroupMask = referenceJob.WorkGroupMask;
job.ResponseAreaMask = referenceJob.ResponseAreaMask;
job.DateModified = DateTimeOffset.UtcNow;
// 2. Обновляем AutoControl
if (referenceJob.AutoControl != null)
{
if (job.AutoControl == null)
{
job.AutoControl = new JobAutoControl
{
JobId = job.Id,
InitUsedTemplateState = referenceJob.AutoControl.InitUsedTemplateState,
InitUsedScheduleState = referenceJob.AutoControl.InitUsedScheduleState
};
}
else
{
job.AutoControl.InitUsedTemplateState = referenceJob.AutoControl.InitUsedTemplateState;
job.AutoControl.InitUsedScheduleState = referenceJob.AutoControl.InitUsedScheduleState;
}
}
// 3. Обновляем UnitFilters
if (job.UnitFilters == null)
{
job.UnitFilters = new List<JobUnitFilter>();
@@ -83,14 +148,14 @@ public class JobGroupUnitFilterSynchronizeHelper
job.UnitFilters.Clear();
}
var clonedFilters = CloneFilters(referenceFilters, job.Id);
var clonedFilters = CloneFilters(referenceJob.UnitFilters ?? Enumerable.Empty<JobUnitFilter>(), job.Id);
foreach (var filter in clonedFilters)
{
job.UnitFilters!.Add(filter);
}
await jobRepository.CommitAsync(initiator);
logger.LogInformation("Фильтры Job {JobId} успешно обновлены.", jobId);
logger.LogInformation("Job {JobId} успешно синхронизирован с эталоном.", jobId);
}
private bool AreUnitFiltersIdentical(IEnumerable<JobUnitFilter>? current, IEnumerable<JobUnitFilter>? reference)