feat(dal, templateMatcher): небольшое улучшение быстродействия синхронизации, ShortcodesService добавлен проброс unitInTemplates для корректного подстановки шорткода %МАКС:...%
This commit is contained in:
@@ -355,7 +355,7 @@ namespace PARR.DAL.DomainServices.Shortcodes
|
|||||||
var maxShortcodes = MaxShortcodeRegex.Matches(result);
|
var maxShortcodes = MaxShortcodeRegex.Matches(result);
|
||||||
if (maxShortcodes.Count > 0)
|
if (maxShortcodes.Count > 0)
|
||||||
{
|
{
|
||||||
result = await ReplaceMaxShortcodesAsync(data.Job.Group.Id, data.UnitId, result, maxShortcodes, caller).ConfigureAwait(false);
|
result = await ReplaceMaxShortcodesAsync(data.Job.Group.Id, data.UnitId, result, maxShortcodes, caller, data.UnitsInTemplate).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -675,7 +675,13 @@ namespace PARR.DAL.DomainServices.Shortcodes
|
|||||||
return resultName;
|
return resultName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> ReplaceMaxShortcodesAsync(Guid jobGroupId, Guid unitId, string input, MatchCollection maxShortcodes, string caller)
|
private async Task<string> ReplaceMaxShortcodesAsync(
|
||||||
|
Guid jobGroupId,
|
||||||
|
Guid unitId,
|
||||||
|
string input,
|
||||||
|
MatchCollection maxShortcodes,
|
||||||
|
string caller,
|
||||||
|
List<UnitInTemplateForShortcodes> unitsInTemplateForCurrentTemplate = null)
|
||||||
{
|
{
|
||||||
if (jobGroupId == Guid.Empty)
|
if (jobGroupId == Guid.Empty)
|
||||||
{
|
{
|
||||||
@@ -703,7 +709,7 @@ namespace PARR.DAL.DomainServices.Shortcodes
|
|||||||
logger.LogDebug("[{Caller}] Обработка {Shortcode} для JobGroup {JobGroupId}, Template.UnitId {UnitId}, fieldName {FieldName}",
|
logger.LogDebug("[{Caller}] Обработка {Shortcode} для JobGroup {JobGroupId}, Template.UnitId {UnitId}, fieldName {FieldName}",
|
||||||
caller, fullShortcode, jobGroupId, unitId, fieldName);
|
caller, fullShortcode, jobGroupId, unitId, fieldName);
|
||||||
|
|
||||||
var mostFrequentValue = await GetMaxShortCodeFromCacheOrDbAsync(jobGroupId, unitId, fullShortcode, fieldName, caller).ConfigureAwait(false);
|
var mostFrequentValue = await GetMaxShortCodeFromCacheOrDbAsync(jobGroupId, unitId, fullShortcode, fieldName, caller, unitsInTemplateForCurrentTemplate).ConfigureAwait(false);
|
||||||
|
|
||||||
foreach (var match in matches)
|
foreach (var match in matches)
|
||||||
input = input.Replace(match.Value, mostFrequentValue);
|
input = input.Replace(match.Value, mostFrequentValue);
|
||||||
@@ -712,7 +718,13 @@ namespace PARR.DAL.DomainServices.Shortcodes
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> GetMaxShortCodeFromCacheOrDbAsync(Guid jobGroupId, Guid unitId, string fullShortcode, string fieldName, string caller)
|
private async Task<string> GetMaxShortCodeFromCacheOrDbAsync(
|
||||||
|
Guid jobGroupId,
|
||||||
|
Guid unitId,
|
||||||
|
string fullShortcode,
|
||||||
|
string fieldName,
|
||||||
|
string caller,
|
||||||
|
List<UnitInTemplateForShortcodes> unitsInTemplateForCurrentTemplate = null)
|
||||||
{
|
{
|
||||||
if (jobGroupId == Guid.Empty)
|
if (jobGroupId == Guid.Empty)
|
||||||
{
|
{
|
||||||
@@ -737,21 +749,7 @@ namespace PARR.DAL.DomainServices.Shortcodes
|
|||||||
|
|
||||||
logger.LogDebug("[{Caller}] Кэш промахнут для GroupedShortCode '{Name}'. Запрашиваем из БД.", caller, fullShortcode);
|
logger.LogDebug("[{Caller}] Кэш промахнут для GroupedShortCode '{Name}'. Запрашиваем из БД.", caller, fullShortcode);
|
||||||
|
|
||||||
// Загружаем юниты из БД
|
var effectiveUnitIds = await GetEffectiveUnitIdsAsync(jobGroupId, unitId, unitsInTemplateForCurrentTemplate, caller).ConfigureAwait(false);
|
||||||
var effectiveUnitIds = await jobService.Get()
|
|
||||||
.Where(j => j.GroupId == jobGroupId)
|
|
||||||
.Join(
|
|
||||||
templateService.Get()
|
|
||||||
.Where(t => t.StatusTypeId == TemplateStatusTypeEnum.Used && t.UnitId == unitId)
|
|
||||||
.Include(t => t.UnitsInTemplate),
|
|
||||||
job => job.Id,
|
|
||||||
template => template.JobId,
|
|
||||||
(job, template) => template
|
|
||||||
)
|
|
||||||
.SelectMany(template => template.UnitsInTemplate)
|
|
||||||
.Select(uit => uit.UnitId)
|
|
||||||
.Distinct()
|
|
||||||
.ToListAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
logger.LogDebug("[{Caller}] EffectiveUnitIds: [{Ids}], Count: {Count}", caller, string.Join(", ", effectiveUnitIds), effectiveUnitIds.Count);
|
logger.LogDebug("[{Caller}] EffectiveUnitIds: [{Ids}], Count: {Count}", caller, string.Join(", ", effectiveUnitIds), effectiveUnitIds.Count);
|
||||||
|
|
||||||
@@ -778,6 +776,47 @@ namespace PARR.DAL.DomainServices.Shortcodes
|
|||||||
return NoContent;
|
return NoContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получает список UnitId для подстановки шорткода %МАКС:...%.
|
||||||
|
/// Сначала пробует использовать переданные юниты, затем загружает из БД.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="jobGroupId">ID JobGroup, для которого ищутся юниты</param>
|
||||||
|
/// <param name="unitId">ID ключевого юнита шаблона</param>
|
||||||
|
/// <param name="unitsInTemplateForCurrentTemplate">Юниты, переданные с текущим шаблоном (опционально)</param>
|
||||||
|
/// <param name="caller">Имя вызывающего метода (для логирования)</param>
|
||||||
|
/// <returns>Список UnitId</returns>
|
||||||
|
private async Task<List<Guid>> GetEffectiveUnitIdsAsync(
|
||||||
|
Guid jobGroupId,
|
||||||
|
Guid unitId,
|
||||||
|
List<UnitInTemplateForShortcodes> unitsInTemplateForCurrentTemplate,
|
||||||
|
string caller)
|
||||||
|
{
|
||||||
|
if (unitsInTemplateForCurrentTemplate != null && unitsInTemplateForCurrentTemplate.Count > 0)
|
||||||
|
{
|
||||||
|
logger.LogDebug("[{Caller}] Используем UnitsInTemplate из входных данных.", caller);
|
||||||
|
return unitsInTemplateForCurrentTemplate.Select(uit => uit.UnitId).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogDebug("[{Caller}] Загружаем UnitsInTemplate из БД.", caller);
|
||||||
|
|
||||||
|
var effectiveUnitIds = await jobService.Get()
|
||||||
|
.Where(j => j.GroupId == jobGroupId)
|
||||||
|
.Join(
|
||||||
|
templateService.Get()
|
||||||
|
.Where(t => t.StatusTypeId == TemplateStatusTypeEnum.Used && t.UnitId == unitId)
|
||||||
|
.Include(t => t.UnitsInTemplate),
|
||||||
|
job => job.Id,
|
||||||
|
template => template.JobId,
|
||||||
|
(job, template) => template
|
||||||
|
)
|
||||||
|
.SelectMany(template => template.UnitsInTemplate)
|
||||||
|
.Select(uit => uit.UnitId)
|
||||||
|
.Distinct()
|
||||||
|
.ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return effectiveUnitIds;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<string> ReplaceLettersShortcodesAsync(Guid unitId, string input, MatchCollection lettersShortcodes, string caller)
|
private async Task<string> ReplaceLettersShortcodesAsync(Guid unitId, string input, MatchCollection lettersShortcodes, string caller)
|
||||||
{
|
{
|
||||||
var shortcodeToMatches = lettersShortcodes
|
var shortcodeToMatches = lettersShortcodes
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using PARR.BLL.Services.Interfaces;
|
|||||||
using PARR.Common.Domain;
|
using PARR.Common.Domain;
|
||||||
using PARR.Constants;
|
using PARR.Constants;
|
||||||
using PARR.DAL.Cache.Models;
|
using PARR.DAL.Cache.Models;
|
||||||
|
|
||||||
using PARR.DAL.DomainServices.Interfaces;
|
using PARR.DAL.DomainServices.Interfaces;
|
||||||
using PARR.DAL.DomainServices.UnitFilterService;
|
using PARR.DAL.DomainServices.UnitFilterService;
|
||||||
using PARR.DAL.Models;
|
using PARR.DAL.Models;
|
||||||
@@ -14,10 +15,9 @@ using PARR.DAL.NextRunServices;
|
|||||||
using PARR.DAL.Services.Interfaces;
|
using PARR.DAL.Services.Interfaces;
|
||||||
using PARR.DAL.Services.Interfaces.Job;
|
using PARR.DAL.Services.Interfaces.Job;
|
||||||
using PARR.DAL.Services.Interfaces.Unit;
|
using PARR.DAL.Services.Interfaces.Unit;
|
||||||
using PARR.DAL.TransformServices;
|
|
||||||
using PARR.TemplateMatcher.Services.Interfaces;
|
using PARR.TemplateMatcher.Services.Interfaces;
|
||||||
using PARR.TemplateMatcher.Settings;
|
using PARR.TemplateMatcher.Settings;
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace PARR.TemplateMatcher.Services.Implementations;
|
namespace PARR.TemplateMatcher.Services.Implementations;
|
||||||
|
|
||||||
@@ -36,7 +36,6 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
private readonly ITemplateService templateService;
|
private readonly ITemplateService templateService;
|
||||||
private readonly IJobGroupService jobGroupService;
|
private readonly IJobGroupService jobGroupService;
|
||||||
private readonly ITemplateReuser templateReuser;
|
private readonly ITemplateReuser templateReuser;
|
||||||
//private readonly IEsppScheduleTransformService esppScheduleTransformService;
|
|
||||||
private readonly IUnitRegionalEkPtkGroupService regionalEkPtkGroupService;
|
private readonly IUnitRegionalEkPtkGroupService regionalEkPtkGroupService;
|
||||||
private readonly IUnitFieldService unitFieldService;
|
private readonly IUnitFieldService unitFieldService;
|
||||||
private readonly ITemplateDeactivator templateDeactivator;
|
private readonly ITemplateDeactivator templateDeactivator;
|
||||||
@@ -56,7 +55,6 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
ITemplateService templateService,
|
ITemplateService templateService,
|
||||||
IJobGroupService jobGroupService,
|
IJobGroupService jobGroupService,
|
||||||
ITemplateReuser templateReuser,
|
ITemplateReuser templateReuser,
|
||||||
//IEsppScheduleTransformService esppScheduleTransformService,
|
|
||||||
IUnitRegionalEkPtkGroupService regionalEkPtkGroupService,
|
IUnitRegionalEkPtkGroupService regionalEkPtkGroupService,
|
||||||
IUnitFieldService unitFieldService,
|
IUnitFieldService unitFieldService,
|
||||||
ITemplateDeactivator templateDeactivator,
|
ITemplateDeactivator templateDeactivator,
|
||||||
@@ -76,7 +74,6 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
this.templateService = templateService;
|
this.templateService = templateService;
|
||||||
this.jobGroupService = jobGroupService;
|
this.jobGroupService = jobGroupService;
|
||||||
this.templateReuser = templateReuser;
|
this.templateReuser = templateReuser;
|
||||||
//this.esppScheduleTransformService = esppScheduleTransformService;
|
|
||||||
this.regionalEkPtkGroupService = regionalEkPtkGroupService;
|
this.regionalEkPtkGroupService = regionalEkPtkGroupService;
|
||||||
this.unitFieldService = unitFieldService;
|
this.unitFieldService = unitFieldService;
|
||||||
this.templateDeactivator = templateDeactivator;
|
this.templateDeactivator = templateDeactivator;
|
||||||
@@ -197,12 +194,14 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
|
|
||||||
var groupingFieldId = jobGroup.GroupingUnitFieldId.Value;
|
var groupingFieldId = jobGroup.GroupingUnitFieldId.Value;
|
||||||
|
|
||||||
// Фильтруем юниты по GroupingUnitFieldId используя данные из DTO
|
// --- ОПТИМИЗАЦИЯ: Загрузка значений поля GroupingUnitFieldId отдельно ---
|
||||||
var unitIdsWithValidGroupingFieldSet = filteredUnits
|
logger.LogDebug("Загружаем значения поля GroupingUnitFieldId (FieldId={FieldId}) для {Count} юнитов.", groupingFieldId, expectedUnitIds.Count);
|
||||||
.Where(u => u.Values.Any(v =>
|
|
||||||
v.FieldId == groupingFieldId &&
|
var groupingUnitValues = await unitInValueService.GetByUnitIdsAndFieldIdsAsync(expectedUnitIds, new HashSet<Guid> { groupingFieldId });
|
||||||
!string.IsNullOrEmpty(v.Value)))
|
|
||||||
.Select(u => u.Id)
|
var unitIdsWithValidGroupingFieldSet = groupingUnitValues
|
||||||
|
.Where(uv => uv.Value != null && !string.IsNullOrEmpty(uv.Value.Value))
|
||||||
|
.Select(uv => uv.UnitId)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
logger.LogDebug("После фильтрации по GroupingUnitFieldId осталось {Count} юнитов.", unitIdsWithValidGroupingFieldSet.Count);
|
logger.LogDebug("После фильтрации по GroupingUnitFieldId осталось {Count} юнитов.", unitIdsWithValidGroupingFieldSet.Count);
|
||||||
@@ -214,13 +213,17 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Аналогично для фильтрации по "РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК"
|
// --- Аналогично для фильтрации по "РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК" ---
|
||||||
var unitIdsWithValidWorkGroupFieldSet = filteredUnits
|
// var workGroupFieldId = workGroupField.Id; // УЖЕ ОПРЕДЕЛЕНО РАНЕЕ (строка 157)
|
||||||
.Where(u => u.Values.Any(v =>
|
// var relationshipGroupValueIds = regionalEkPtkGroupService.Get() // УДАЛИТЬ - УЖЕ ОПРЕДЕЛЕНО (строка 161)
|
||||||
v.FieldId == workGroupFieldId &&
|
|
||||||
relationshipGroupValueIds.Contains(v.FieldId) &&
|
logger.LogDebug("Загружаем значения поля 'РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК' (FieldId={FieldId}) для {Count} юнитов.", workGroupFieldId, unitIdsWithValidGroupingFieldSet.Count);
|
||||||
!string.IsNullOrEmpty(v.Value)))
|
|
||||||
.Select(u => u.Id)
|
var workGroupValues = await unitInValueService.GetByUnitIdsAndFieldIdsAsync(unitIdsWithValidGroupingFieldSet, new HashSet<Guid> { workGroupFieldId });
|
||||||
|
|
||||||
|
var unitIdsWithValidWorkGroupFieldSet = workGroupValues
|
||||||
|
.Where(uv => uv.Value != null && relationshipGroupValueIds.Contains(uv.Value.Id))
|
||||||
|
.Select(uv => uv.UnitId)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
logger.LogDebug("После фильтрации по 'РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК' осталось {Count} юнитов.", unitIdsWithValidWorkGroupFieldSet.Count);
|
logger.LogDebug("После фильтрации по 'РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК' осталось {Count} юнитов.", unitIdsWithValidWorkGroupFieldSet.Count);
|
||||||
@@ -232,41 +235,43 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unitIdsWithValidGroupingFieldSet = unitIdsWithValidWorkGroupFieldSet;
|
// --- ИСПОЛЬЗУЕМ ПОСЛЕДНИЙ РЕЗУЛЬТАТ ДАЛЬШЕ ---
|
||||||
|
var finalUnitIds = unitIdsWithValidWorkGroupFieldSet; // Более понятное имя
|
||||||
|
|
||||||
// 5. Получить RelationshipFilters из maxJob
|
// 5. Получить RelationshipFilters из maxJob
|
||||||
var relationshipFilters = maxJob.UnitFilters?.SelectMany(uf => uf.RelationshipFilters).ToList() ?? new List<JobRelationshipFilter>();
|
var relationshipFilters = maxJob.UnitFilters?.SelectMany(uf => uf.RelationshipFilters).ToList() ?? new List<JobRelationshipFilter>();
|
||||||
|
|
||||||
logger.LogDebug("Получение связей UnitInUnit для юнитов, прошедших фильтрацию...");
|
logger.LogDebug("Получение связей UnitInUnit для юнитов, прошедших фильтрацию...");
|
||||||
|
|
||||||
// Используем unitIdsWithValidGroupingFieldSet для получения связей
|
|
||||||
var potentialUnitInUnitLinks = await unitInUnitService.Get()
|
var potentialUnitInUnitLinks = await unitInUnitService.Get()
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(link => unitIdsWithValidGroupingFieldSet.Contains(link.ParentUnitId) || unitIdsWithValidGroupingFieldSet.Contains(link.ChildUnitId))
|
.Where(link => finalUnitIds.Contains(link.ParentUnitId) || finalUnitIds.Contains(link.ChildUnitId))
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
logger.LogDebug("Найдено {Count} потенциальных связей UnitInUnit.", potentialUnitInUnitLinks.Count);
|
logger.LogDebug("Найдено {Count} потенциальных связей UnitInUnit.", potentialUnitInUnitLinks.Count);
|
||||||
|
|
||||||
// Подготавливаем данные для фильтрации связей
|
|
||||||
var allParentIds = potentialUnitInUnitLinks.Select(l => l.ParentUnitId).ToHashSet();
|
var allParentIds = potentialUnitInUnitLinks.Select(l => l.ParentUnitId).ToHashSet();
|
||||||
var allChildIds = potentialUnitInUnitLinks.Select(l => l.ChildUnitId).ToHashSet();
|
var allChildIds = potentialUnitInUnitLinks.Select(l => l.ChildUnitId).ToHashSet();
|
||||||
|
|
||||||
// Фильтруем юниты для получения родительских и дочерних значений
|
// --- Оптимизация: Загрузка всех значений за ОДИН запрос ---
|
||||||
var parentUnits = filteredUnits.Where(u => allParentIds.Contains(u.Id)).ToList();
|
var allRelevantUnitIds = allParentIds.Concat(allChildIds).ToHashSet();
|
||||||
var childUnits = filteredUnits.Where(u => allChildIds.Contains(u.Id)).ToList();
|
|
||||||
|
|
||||||
// Создаем словари значений для родителей и детей
|
var allUnitValues = await unitInValueService.Get()
|
||||||
var parentValuesMap = parentUnits
|
.AsNoTracking()
|
||||||
.ToDictionary(
|
.Include(uv => uv.Field)
|
||||||
u => u.Id,
|
.Include(uv => uv.Value)
|
||||||
u => u.Values.ToDictionary(v => v.FieldId, v => v.Value)
|
.Where(uv => allRelevantUnitIds.Contains(uv.UnitId))
|
||||||
);
|
.ToListAsync();
|
||||||
|
|
||||||
var childValuesMap = childUnits
|
// --- Создание карт значений из одного списка ---
|
||||||
.ToDictionary(
|
var parentValuesMap = allUnitValues
|
||||||
u => u.Id,
|
.Where(uv => allParentIds.Contains(uv.UnitId))
|
||||||
u => u.Values.ToDictionary(v => v.FieldId, v => v.Value)
|
.GroupBy(uv => uv.UnitId)
|
||||||
);
|
.ToDictionary(g => g.Key, g => g.ToList());
|
||||||
|
|
||||||
|
var childValuesMap = allUnitValues
|
||||||
|
.Where(uv => allChildIds.Contains(uv.UnitId))
|
||||||
|
.GroupBy(uv => uv.UnitId)
|
||||||
|
.ToDictionary(g => g.Key, g => g.ToList());
|
||||||
|
|
||||||
logger.LogDebug("Применение {Count} RelationshipFilters к найденным связям.", relationshipFilters.Count);
|
logger.LogDebug("Применение {Count} RelationshipFilters к найденным связям.", relationshipFilters.Count);
|
||||||
|
|
||||||
@@ -276,37 +281,15 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
bool linkMatchesAllFilters = true;
|
bool linkMatchesAllFilters = true;
|
||||||
foreach (var rf in relationshipFilters)
|
foreach (var rf in relationshipFilters)
|
||||||
{
|
{
|
||||||
bool filterMatch;
|
var valuesToCheck = rf.IsParent ? parentValuesMap.GetValueOrDefault(link.ParentUnitId, new List<UnitInValue>()) : childValuesMap.GetValueOrDefault(link.ChildUnitId, new List<UnitInValue>());
|
||||||
if (rf.IsParent)
|
|
||||||
{
|
bool filterMatch = valuesToCheck.Any(uv =>
|
||||||
// Родительские значения
|
uv.FieldId == rf.FieldId &&
|
||||||
if (parentValuesMap.TryGetValue(link.ParentUnitId, out var parentValues) &&
|
uv.Value != null &&
|
||||||
parentValues.TryGetValue(rf.FieldId, out var parentValue) &&
|
uv.Value.Value != null &&
|
||||||
parentValue != null)
|
uv.Value.Value.Contains(rf.ValueMask ?? "", StringComparison.OrdinalIgnoreCase)
|
||||||
{
|
);
|
||||||
filterMatch = parentValue.Contains(rf.ValueMask ?? "", StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
filterMatch = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Дочерние значения
|
|
||||||
if (childValuesMap.TryGetValue(link.ChildUnitId, out var childValues) &&
|
|
||||||
childValues.TryGetValue(rf.FieldId, out var childValue) &&
|
|
||||||
childValue != null)
|
|
||||||
{
|
|
||||||
filterMatch = childValue.Contains(rf.ValueMask ?? "", StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
filterMatch = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Учитываем инверсию фильтра
|
|
||||||
if (rf.IsInverse)
|
if (rf.IsInverse)
|
||||||
filterMatch = !filterMatch;
|
filterMatch = !filterMatch;
|
||||||
|
|
||||||
@@ -332,7 +315,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
var parentUnitId = link.ParentUnitId;
|
var parentUnitId = link.ParentUnitId;
|
||||||
var childUnitId = link.ChildUnitId;
|
var childUnitId = link.ChildUnitId;
|
||||||
|
|
||||||
if (unitIdsWithValidGroupingFieldSet.Contains(parentUnitId))
|
if (finalUnitIds.Contains(parentUnitId))
|
||||||
{
|
{
|
||||||
if (!groupedRelationships.ContainsKey(childUnitId))
|
if (!groupedRelationships.ContainsKey(childUnitId))
|
||||||
{
|
{
|
||||||
@@ -340,7 +323,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
}
|
}
|
||||||
groupedRelationships[childUnitId].Add(parentUnitId);
|
groupedRelationships[childUnitId].Add(parentUnitId);
|
||||||
}
|
}
|
||||||
else if (unitIdsWithValidGroupingFieldSet.Contains(childUnitId))
|
else if (finalUnitIds.Contains(childUnitId))
|
||||||
{
|
{
|
||||||
if (!groupedRelationships.ContainsKey(parentUnitId))
|
if (!groupedRelationships.ContainsKey(parentUnitId))
|
||||||
{
|
{
|
||||||
@@ -375,10 +358,9 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
.Distinct()
|
.Distinct()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Создаем словарь имен для конфликтующих ключей из отфильтрованных юнитов
|
var unitNamesMap = await unitService.Get()
|
||||||
var unitNamesMap = filteredUnits
|
|
||||||
.Where(u => conflictKeys.Contains(u.Id))
|
.Where(u => conflictKeys.Contains(u.Id))
|
||||||
.ToDictionary(u => u.Id, u => u.Name);
|
.ToDictionaryAsync(u => u.Id, u => u.Name ?? string.Empty);
|
||||||
|
|
||||||
foreach (var conflictedUnitEntry in unitToKeys.Where(kvp => kvp.Value.Count > 1))
|
foreach (var conflictedUnitEntry in unitToKeys.Where(kvp => kvp.Value.Count > 1))
|
||||||
{
|
{
|
||||||
@@ -430,10 +412,10 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
|
|
||||||
logger.LogDebug("Обработка связанного юнита {RelationshipUnitId} с {Count} юнитами из списка.", relationshipUnitId, childUnitIds.Count);
|
logger.LogDebug("Обработка связанного юнита {RelationshipUnitId} с {Count} юнитами из списка.", relationshipUnitId, childUnitIds.Count);
|
||||||
|
|
||||||
// Получаем имена юнитов из отфильтрованных данных
|
var childUnitNameMap = await unitService.Get()
|
||||||
var childUnitNameMap = filteredUnits
|
.AsNoTracking()
|
||||||
.Where(u => childUnitIds.Contains(u.Id))
|
.Where(u => childUnitIds.Contains(u.Id))
|
||||||
.ToDictionary(u => u.Id, u => u.Name);
|
.ToDictionaryAsync(u => u.Id, u => u.Name);
|
||||||
|
|
||||||
var sortedChildUnitIds = childUnitIds
|
var sortedChildUnitIds = childUnitIds
|
||||||
.OrderBy(id => childUnitNameMap.GetValueOrDefault(id, id.ToString()))
|
.OrderBy(id => childUnitNameMap.GetValueOrDefault(id, id.ToString()))
|
||||||
@@ -480,11 +462,10 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
|
|
||||||
// === 2. Сравниваем детерминированно с сортировкой по имени ===
|
// === 2. Сравниваем детерминированно с сортировкой по имени ===
|
||||||
var allUnitIdsForSort = currentUnitIds.Concat(proposedUnitIds).Distinct().ToList();
|
var allUnitIdsForSort = currentUnitIds.Concat(proposedUnitIds).Distinct().ToList();
|
||||||
|
var unitNamesForSort = await unitService.Get()
|
||||||
// Получаем имена юнитов из отфильтрованных данных
|
.AsNoTracking()
|
||||||
var unitNamesForSort = filteredUnits
|
|
||||||
.Where(u => allUnitIdsForSort.Contains(u.Id))
|
.Where(u => allUnitIdsForSort.Contains(u.Id))
|
||||||
.ToDictionary(u => u.Id, u => u.Name);
|
.ToDictionaryAsync(u => u.Id, u => u.Name ?? u.Id.ToString());
|
||||||
|
|
||||||
var sortedCurrentUnitIds = currentUnitIds
|
var sortedCurrentUnitIds = currentUnitIds
|
||||||
.OrderBy(id => unitNamesForSort.GetValueOrDefault(id, id.ToString()))
|
.OrderBy(id => unitNamesForSort.GetValueOrDefault(id, id.ToString()))
|
||||||
@@ -505,7 +486,6 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
if (!string.Equals(existingTemplateForSubGroup.Name, expectedName, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(existingTemplateForSubGroup.Name, expectedName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
logger.LogDebug("Шаблон {TemplateId} требует обновления имени.", existingTemplateForSubGroup.Id);
|
logger.LogDebug("Шаблон {TemplateId} требует обновления имени.", existingTemplateForSubGroup.Id);
|
||||||
//var nextRun = await GetNextRunAsync(targetJob, existingTemplateForSubGroup.NextRun);
|
|
||||||
var nextRun = await nextRunService.GetNextRunForTemplateAsync(existingTemplateForSubGroup.Id, false);
|
var nextRun = await nextRunService.GetNextRunForTemplateAsync(existingTemplateForSubGroup.Id, false);
|
||||||
var updateRequest = new TemplateUpdaterMq
|
var updateRequest = new TemplateUpdaterMq
|
||||||
{
|
{
|
||||||
@@ -560,7 +540,6 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
};
|
};
|
||||||
|
|
||||||
var expectedName = await templateNameNormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
|
var expectedName = await templateNameNormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
|
||||||
//var nextRun = await GetNextRunAsync(targetJob);
|
|
||||||
var nextRun = await nextRunService.GetNextRunForTemplateAsync(reusableTemplate.Id, true);
|
var nextRun = await nextRunService.GetNextRunForTemplateAsync(reusableTemplate.Id, true);
|
||||||
|
|
||||||
var updateRequest = new TemplateUpdaterMq
|
var updateRequest = new TemplateUpdaterMq
|
||||||
@@ -595,12 +574,10 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
{
|
{
|
||||||
var relationshipUnitId = kvp.Key;
|
var relationshipUnitId = kvp.Key;
|
||||||
var childUnitIds = kvp.Value;
|
var childUnitIds = kvp.Value;
|
||||||
|
var childUnitNameMapForDeactivate = await unitService.Get()
|
||||||
// Получаем имена юнитов из отфильтрованных данных
|
.AsNoTracking()
|
||||||
var childUnitNameMapForDeactivate = filteredUnits
|
|
||||||
.Where(u => childUnitIds.Contains(u.Id))
|
.Where(u => childUnitIds.Contains(u.Id))
|
||||||
.ToDictionary(u => u.Id, u => u.Name);
|
.ToDictionaryAsync(u => u.Id, u => u.Name);
|
||||||
|
|
||||||
var sortedChildUnitIdsForDeactivate = childUnitIds
|
var sortedChildUnitIdsForDeactivate = childUnitIds
|
||||||
.OrderBy(id => childUnitNameMapForDeactivate.GetValueOrDefault(id, id.ToString()))
|
.OrderBy(id => childUnitNameMapForDeactivate.GetValueOrDefault(id, id.ToString()))
|
||||||
.ToList();
|
.ToList();
|
||||||
@@ -711,7 +688,6 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
};
|
};
|
||||||
|
|
||||||
var expectedName = await templateNameNormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
|
var expectedName = await templateNameNormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
|
||||||
//var nextRun = await GetNextRunAsync(targetJob, template.NextRun);
|
|
||||||
var nextRun = await nextRunService.GetNextRunForTemplateAsync(template.Id, false);
|
var nextRun = await nextRunService.GetNextRunForTemplateAsync(template.Id, false);
|
||||||
var updateRequest = new TemplateUpdaterMq
|
var updateRequest = new TemplateUpdaterMq
|
||||||
{
|
{
|
||||||
@@ -745,18 +721,14 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
HistoryInitiator = initiator
|
HistoryInitiator = initiator
|
||||||
};
|
};
|
||||||
|
|
||||||
var msg = JsonSerializer.Serialize(mqRequest);
|
//var msg = JsonSerializer.Serialize(mqRequest);
|
||||||
var result = await mqService.SendAsync(mqSettings.TemplateGenerator, new[] { msg });
|
//var result = await mqService.SendAsync(mqSettings.TemplateGenerator, new[] { msg });
|
||||||
|
var result = await mqService.SendAsync(mqSettings.TemplateGenerator, new List<object> { mqRequest });
|
||||||
|
|
||||||
if (!result.IsSuccess)
|
if (!result.IsSuccess)
|
||||||
logger.LogError("Ошибка отправки команды создания группового шаблона для Job {JobId}, связанного юнита {RelationshipUnitId}, Index {Index}.", jobId, relationshipUnitId, index);
|
logger.LogError("Ошибка отправки команды создания группового шаблона для Job {JobId}, связанного юнита {RelationshipUnitId}, Index {Index}.", jobId, relationshipUnitId, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
//private async Task<DateTimeOffset> GetNextRunAsync(Job targetJob, DateTimeOffset? currentNextRun = null)
|
|
||||||
//{
|
|
||||||
// var referenceDate = targetJob.Group?.ReferenceDate ?? DateTimeOffset.UtcNow;
|
|
||||||
// return await esppScheduleTransformService.GetNextDateAsync(targetJob.GroupId, referenceDate);
|
|
||||||
//}
|
|
||||||
|
|
||||||
private async Task UpdateMatchingStatusAsync(Guid jobGroupId, string comment)
|
private async Task UpdateMatchingStatusAsync(Guid jobGroupId, string comment)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,10 +15,8 @@ using PARR.DAL.NextRunServices;
|
|||||||
using PARR.DAL.Services.Interfaces;
|
using PARR.DAL.Services.Interfaces;
|
||||||
using PARR.DAL.Services.Interfaces.Job;
|
using PARR.DAL.Services.Interfaces.Job;
|
||||||
using PARR.DAL.Services.Interfaces.Unit;
|
using PARR.DAL.Services.Interfaces.Unit;
|
||||||
using PARR.DAL.TransformServices;
|
|
||||||
using PARR.TemplateMatcher.Services.Interfaces;
|
using PARR.TemplateMatcher.Services.Interfaces;
|
||||||
using PARR.TemplateMatcher.Settings;
|
using PARR.TemplateMatcher.Settings;
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace PARR.TemplateMatcher.Services.Implementations;
|
namespace PARR.TemplateMatcher.Services.Implementations;
|
||||||
|
|
||||||
@@ -41,7 +39,6 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
private readonly ITemplateService templateService;
|
private readonly ITemplateService templateService;
|
||||||
private readonly IJobService jobService;
|
private readonly IJobService jobService;
|
||||||
private readonly ITemplateReuser templateReuser;
|
private readonly ITemplateReuser templateReuser;
|
||||||
//private readonly IEsppScheduleTransformService esppScheduleTransformService;
|
|
||||||
private readonly ITemplateDeactivator templateDeactivator;
|
private readonly ITemplateDeactivator templateDeactivator;
|
||||||
private readonly ITemplateNameNormalizer templateNameNormalizer;
|
private readonly ITemplateNameNormalizer templateNameNormalizer;
|
||||||
private readonly ITemplateUpdaterMqSender templateUpdaterMqSender;
|
private readonly ITemplateUpdaterMqSender templateUpdaterMqSender;
|
||||||
@@ -61,7 +58,6 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
IJobService jobService,
|
IJobService jobService,
|
||||||
ITemplateReuser templateReuser,
|
ITemplateReuser templateReuser,
|
||||||
IShortcodesService shortcodesService,
|
IShortcodesService shortcodesService,
|
||||||
//IEsppScheduleTransformService esppScheduleTransformService,
|
|
||||||
IUnitRegionalEkPtkGroupService regionalEkPtkGroupService,
|
IUnitRegionalEkPtkGroupService regionalEkPtkGroupService,
|
||||||
IUnitFieldService unitFieldService,
|
IUnitFieldService unitFieldService,
|
||||||
ITemplateDeactivator templateDeactivator,
|
ITemplateDeactivator templateDeactivator,
|
||||||
@@ -79,7 +75,6 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
this.templateService = templateService;
|
this.templateService = templateService;
|
||||||
this.jobService = jobService;
|
this.jobService = jobService;
|
||||||
this.templateReuser = templateReuser;
|
this.templateReuser = templateReuser;
|
||||||
//this.esppScheduleTransformService = esppScheduleTransformService;
|
|
||||||
this.templateDeactivator = templateDeactivator;
|
this.templateDeactivator = templateDeactivator;
|
||||||
this.templateNameNormalizer = templateNameNormalizer;
|
this.templateNameNormalizer = templateNameNormalizer;
|
||||||
this.templateUpdaterMqSender = templateUpdaterMqSender;
|
this.templateUpdaterMqSender = templateUpdaterMqSender;
|
||||||
@@ -228,7 +223,6 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
};
|
};
|
||||||
|
|
||||||
var expectedName = await templateNameNormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
|
var expectedName = await templateNameNormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
|
||||||
//var nextRun = await GetNextRunAsync(job);
|
|
||||||
var nextRun = await nextRunService.GetNextRunForTemplateAsync(reusableTemplate.Id, true);
|
var nextRun = await nextRunService.GetNextRunForTemplateAsync(reusableTemplate.Id, true);
|
||||||
|
|
||||||
var updateRequest = new TemplateUpdaterMq
|
var updateRequest = new TemplateUpdaterMq
|
||||||
@@ -264,7 +258,6 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
{
|
{
|
||||||
logger.LogDebug("Шаблон {TemplateId} требует обновления имени: старое = '{OldName}', новое = '{NewName}'", template.Id, template.Name, expectedName);
|
logger.LogDebug("Шаблон {TemplateId} требует обновления имени: старое = '{OldName}', новое = '{NewName}'", template.Id, template.Name, expectedName);
|
||||||
|
|
||||||
//var nextRun = await GetNextRunAsync(job, template.NextRun);
|
|
||||||
var nextRun = await nextRunService.GetNextRunForTemplateAsync(template.Id, false);
|
var nextRun = await nextRunService.GetNextRunForTemplateAsync(template.Id, false);
|
||||||
|
|
||||||
var updateRequest = new TemplateUpdaterMq
|
var updateRequest = new TemplateUpdaterMq
|
||||||
@@ -283,7 +276,7 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
UnitsInTemplate = new List<Guid>() // для простого шаблона
|
UnitsInTemplate = new List<Guid>() // для простого шаблона
|
||||||
};
|
};
|
||||||
|
|
||||||
await templateUpdaterMqSender.SendTemplateUpdateMessageAsync(updateRequest);
|
await templateUpdaterMqSender.SendTemplateUpdateMessageAsync(updateRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -403,7 +396,6 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
{
|
{
|
||||||
logger.LogDebug("Шаблон {TemplateId} требует обновления имени: старое = '{OldName}', новое = '{NewName}'", template.Id, template.Name, expectedName);
|
logger.LogDebug("Шаблон {TemplateId} требует обновления имени: старое = '{OldName}', новое = '{NewName}'", template.Id, template.Name, expectedName);
|
||||||
|
|
||||||
//var nextRun = await GetNextRunAsync(job, template.NextRun);
|
|
||||||
var nextRun = await nextRunService.GetNextRunForTemplateAsync(template.Id, false);
|
var nextRun = await nextRunService.GetNextRunForTemplateAsync(template.Id, false);
|
||||||
|
|
||||||
var updateRequest = new TemplateUpdaterMq
|
var updateRequest = new TemplateUpdaterMq
|
||||||
@@ -510,7 +502,6 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//var nextRun = await GetNextRunAsync(unusedJob);
|
|
||||||
var nextRun = await nextRunService.GetNextRunForTemplateAsync(template.Id, false);
|
var nextRun = await nextRunService.GetNextRunForTemplateAsync(template.Id, false);
|
||||||
|
|
||||||
var updateRequest = new TemplateUpdaterMq
|
var updateRequest = new TemplateUpdaterMq
|
||||||
@@ -546,6 +537,7 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task<string> GenerateUnusedTemplateNameAsync(Template template, Job unusedJob)
|
private async Task<string> GenerateUnusedTemplateNameAsync(Template template, Job unusedJob)
|
||||||
{
|
{
|
||||||
var tempJob = new Job
|
var tempJob = new Job
|
||||||
@@ -583,6 +575,7 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
return await templateNameNormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
|
return await templateNameNormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task CreateSimpleTemplateAsync(Guid jobId, Guid unitId, HistoryInitiator initiator)
|
private async Task CreateSimpleTemplateAsync(Guid jobId, Guid unitId, HistoryInitiator initiator)
|
||||||
{
|
{
|
||||||
logger.LogInformation("Создание нового простого шаблона для Job {JobId}, UnitId {UnitId}.", jobId, unitId);
|
logger.LogInformation("Создание нового простого шаблона для Job {JobId}, UnitId {UnitId}.", jobId, unitId);
|
||||||
@@ -595,18 +588,14 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
HistoryInitiator = initiator
|
HistoryInitiator = initiator
|
||||||
};
|
};
|
||||||
|
|
||||||
var msg = JsonSerializer.Serialize(mqRequest);
|
//var msg = JsonSerializer.Serialize(mqRequest);
|
||||||
var result = await mqService.SendAsync(mqSettings.TemplateGenerator, new[] { msg });
|
//var result = await mqService.SendAsync(mqSettings.TemplateGenerator, new[] { msg });
|
||||||
|
var result = await mqService.SendAsync(mqSettings.TemplateGenerator, new List<object> { mqRequest });
|
||||||
|
|
||||||
if (!result.IsSuccess)
|
if (!result.IsSuccess)
|
||||||
logger.LogError("Ошибка отправки команды создания простого шаблона для Job {JobId}, UnitId {UnitId}.", jobId, unitId);
|
logger.LogError("Ошибка отправки команды создания простого шаблона для Job {JobId}, UnitId {UnitId}.", jobId, unitId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//private async Task<DateTimeOffset> GetNextRunAsync(Job job, DateTimeOffset? currentNextRun = null)
|
|
||||||
//{
|
|
||||||
// var referenceDate = job.Group?.ReferenceDate ?? DateTimeOffset.UtcNow;
|
|
||||||
// return await esppScheduleTransformService.GetNextDateAsync(job.GroupId, referenceDate);
|
|
||||||
//}
|
|
||||||
|
|
||||||
private async Task UpdateMatchingStatusAsync(Guid jobId, string comment)
|
private async Task UpdateMatchingStatusAsync(Guid jobId, string comment)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using PARR.BLL.Domain.Mq;
|
|||||||
using PARR.BLL.Services.Interfaces;
|
using PARR.BLL.Services.Interfaces;
|
||||||
using PARR.TemplateMatcher.Services.Interfaces;
|
using PARR.TemplateMatcher.Services.Interfaces;
|
||||||
using PARR.TemplateMatcher.Settings;
|
using PARR.TemplateMatcher.Settings;
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace PARR.TemplateMatcher.Services.Implementations;
|
namespace PARR.TemplateMatcher.Services.Implementations;
|
||||||
|
|
||||||
@@ -28,8 +27,9 @@ internal class TemplateUpdaterMqSender : ITemplateUpdaterMqSender
|
|||||||
logger.LogDebug("Отправка сообщения в очередь '{Queue}' для шаблона {TemplateId}",
|
logger.LogDebug("Отправка сообщения в очередь '{Queue}' для шаблона {TemplateId}",
|
||||||
mqSettings.TemplateUpdater.QueueName, updateRequest.TemplateId);
|
mqSettings.TemplateUpdater.QueueName, updateRequest.TemplateId);
|
||||||
|
|
||||||
var msg = JsonSerializer.Serialize(updateRequest);
|
//var msg = JsonSerializer.Serialize(updateRequest);
|
||||||
var result = await mqService.SendAsync(mqSettings.TemplateUpdater, new[] { msg });
|
//var result = await mqService.SendAsync(mqSettings.TemplateUpdater, new[] { msg });
|
||||||
|
var result = await mqService.SendAsync(mqSettings.TemplateUpdater, new List<object> { updateRequest });
|
||||||
|
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user