fix(templateMatcher, templateUpdater): исправлена валидация и добавлена проверка имени шаблона
This commit is contained in:
@@ -93,6 +93,8 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
||||
.Include(jg => jg.Jobs)
|
||||
.ThenInclude(j => j.UnitFilters)
|
||||
.ThenInclude(uf => uf.RelationshipFilters)
|
||||
.Include(jg => jg.Jobs)
|
||||
.ThenInclude(jg => jg.Tnk)
|
||||
.FirstOrDefaultAsync(jg => jg.Id == jobGroupId);
|
||||
|
||||
if (jobGroup == null || jobGroup.Jobs == null || !jobGroup.Jobs.Any())
|
||||
@@ -177,7 +179,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
||||
return;
|
||||
}
|
||||
|
||||
// --- НОВАЯ ЛОГИКА: Дополнительная фильтрация по "РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК" ---
|
||||
// --- Дополнительная фильтрация по "РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК" ---
|
||||
var unitIdsWithValidWorkGroupFieldSet = expectedUnitsWithGroupingField
|
||||
.Where(u => unitIdsWithValidGroupingFieldSet.Contains(u.Id) && // Убедимся, что юнит уже прошёл фильтр по GroupingFieldId
|
||||
u.UnitValues.Any(uv =>
|
||||
@@ -274,7 +276,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
||||
|
||||
logger.LogDebug("После применения RelationshipFilters осталось {Count} связей UnitInUnit.", filteredUnitInUnitLinks.Count);
|
||||
|
||||
// --- НОВАЯ ЛОГИКА: Сгруппировать юниты из unitIdsWithValidGroupingFieldSet по связанному юниту ---
|
||||
// --- Сгруппировать юниты из unitIdsWithValidGroupingFieldSet по связанному юниту ---
|
||||
var groupedRelationships = new Dictionary<Guid, List<Guid>>();
|
||||
foreach (var link in filteredUnitInUnitLinks)
|
||||
{
|
||||
@@ -301,7 +303,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
||||
|
||||
logger.LogDebug("Сформировано {Count} групп по связанным юнитам до разрешения конфликтов.", groupedRelationships.Count);
|
||||
|
||||
// --- НОВАЯ ЛОГИКА: Разрешение конфликта - один юнит из unitIdsWithValidGroupingFieldSet только в одном списке значений ---
|
||||
// --- Разрешение конфликта - один юнит из unitIdsWithValidGroupingFieldSet только в одном списке значений ---
|
||||
var unitToKeys = new Dictionary<Guid, List<Guid>>(); // Карта: юнит из списка -> список ключей, где он встречается
|
||||
|
||||
foreach (var kvp in groupedRelationships)
|
||||
@@ -392,30 +394,10 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
||||
|
||||
logger.LogDebug("Обработка подгруппы {Index} связанного юнита {RegionalUnitId}, размер {Size}.", i, relationshipUnitId, subGroupSize);
|
||||
|
||||
// 8. Найти подходящий Job для подгруппы (логика без изменений)
|
||||
Job? targetJob = jobsInGroup
|
||||
.Where(j => j.MaxValueRelationships.HasValue && j.MaxValueRelationships.Value == subGroupSize)
|
||||
.FirstOrDefault();
|
||||
// Выбираем targetJob для подгруппы
|
||||
Job? targetJob = SelectTargetJob(jobsInGroup, subGroupSize, maxJob);
|
||||
|
||||
if (targetJob == null)
|
||||
{
|
||||
targetJob = jobsInGroup
|
||||
.Where(j => j.MaxValueRelationships.HasValue && j.MaxValueRelationships.Value >= subGroupSize)
|
||||
.OrderBy(j => j.MaxValueRelationships!.Value)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
if (targetJob == null)
|
||||
{
|
||||
targetJob = maxJob; // maxJob уже проверен на null ранее
|
||||
logger.LogDebug("Для подгруппы {Index} связанного юнита {RegionalUnitId} не найден подходящий Job, используем maxJob {MaxJobId}.", i, relationshipUnitId, maxJob.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogDebug("Для подгруппы {Index} связанного юнита {RegionalUnitId} выбран Job {TargetJobId} с MaxValueRelationships {MaxValue}.", i, relationshipUnitId, targetJob.Id, targetJob.MaxValueRelationships);
|
||||
}
|
||||
|
||||
// 9. Загрузить существующие шаблоны для targetJob, связанные с regionalUnitId
|
||||
// 9. Загрузить существующие шаблоны для targetJob, связанные с relationshipUnitId
|
||||
var existingTemplatesForRelationship = await templateService.Get()
|
||||
.AsNoTracking()
|
||||
.Include(t => t.UnitsInTemplate)
|
||||
@@ -432,12 +414,53 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
||||
|
||||
if (existingUnitIds.SetEquals(newUnitIds))
|
||||
{
|
||||
logger.LogDebug("Шаблон {TemplateId} (Job {JobId}, Regional {RegionalId}, Index {Index}) актуален.", existingTemplateForSubGroup.Id, targetJob.Id, relationshipUnitId, i);
|
||||
logger.LogDebug("Шаблон {TemplateId} (Job {JobId}, Regional {RegionalId}, Index {Index}) актуален по юнитам.", existingTemplateForSubGroup.Id, targetJob.Id, relationshipUnitId, i);
|
||||
|
||||
// ✅ Проверить, изменилось ли имя шаблона (например, из-за %МАКС:...% или %ТНК-КРАТКО%)
|
||||
var expectedName = await GetNormalizedTemplateNameAsync(targetJob, relationshipUnitId, i, subGroup);
|
||||
if (!string.Equals(existingTemplateForSubGroup.Name, expectedName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.LogDebug("Шаблон {TemplateId} требует обновления имени: старое = '{OldName}', новое = '{NewName}'", existingTemplateForSubGroup.Id, existingTemplateForSubGroup.Name, expectedName);
|
||||
|
||||
var nextRun = await GetNextRunAsync(targetJob, existingTemplateForSubGroup.NextRun);
|
||||
|
||||
var updateRequest = new TemplateUpdaterMq
|
||||
{
|
||||
TemplateId = existingTemplateForSubGroup.Id,
|
||||
JobId = targetJob.Id,
|
||||
UnitId = relationshipUnitId,
|
||||
Name = expectedName,
|
||||
IsActiveTemplate = existingTemplateForSubGroup.IsActiveTemplate,
|
||||
IsActiveSchedule = existingTemplateForSubGroup.IsActiveSchedule,
|
||||
LastRun = existingTemplateForSubGroup.LastRun,
|
||||
NextRun = nextRun,
|
||||
Index = i,
|
||||
StatusTypeId = TemplateStatusTypeEnum.Used,
|
||||
Initiator = initiator,
|
||||
UnitsInTemplate = subGroup
|
||||
};
|
||||
|
||||
await SendTemplateUpdateMessage(updateRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogDebug("Шаблон {TemplateId} полностью актуален (юниты и имя).", existingTemplateForSubGroup.Id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogDebug("Шаблон {TemplateId} (Job {JobId}, Regional {RegionalId}, Index {Index}) требует обновления юнитов.", existingTemplateForSubGroup.Id, targetJob.Id, relationshipUnitId, i);
|
||||
await UpdateTemplateUnitsAsync(existingTemplateForSubGroup, subGroup, targetJob, initiator);
|
||||
|
||||
// Пересчитать targetJob для нового размера subGroup
|
||||
var newTargetJob = SelectTargetJob(jobsInGroup, subGroupSize, maxJob);
|
||||
|
||||
// Если Job изменился — нужно обновить шаблон с новым JobId
|
||||
if (newTargetJob.Id != existingTemplateForSubGroup.JobId)
|
||||
{
|
||||
logger.LogDebug("Job для шаблона {TemplateId} изменился: старый {OldJobId}, новый {NewJobId}.", existingTemplateForSubGroup.Id, existingTemplateForSubGroup.JobId, newTargetJob.Id);
|
||||
}
|
||||
|
||||
await UpdateTemplateUnitsAsync(existingTemplateForSubGroup, subGroup, newTargetJob, initiator);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -495,19 +518,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
||||
var subGroup = childUnitGroups[i];
|
||||
var subGroupSize = subGroup.Count;
|
||||
|
||||
Job? targetJobForExpectedKey = jobsInGroup
|
||||
.Where(j => j.MaxValueRelationships.HasValue && j.MaxValueRelationships.Value == subGroupSize)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (targetJobForExpectedKey == null)
|
||||
{
|
||||
targetJobForExpectedKey = jobsInGroup
|
||||
.Where(j => j.MaxValueRelationships.HasValue && j.MaxValueRelationships.Value >= subGroupSize)
|
||||
.OrderBy(j => j.MaxValueRelationships!.Value)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
if (targetJobForExpectedKey == null) targetJobForExpectedKey = maxJob; // maxJob уже проверен на null
|
||||
Job? targetJobForExpectedKey = SelectTargetJob(jobsInGroup, subGroupSize, maxJob);
|
||||
|
||||
expectedTemplateKeys.Add((targetJobForExpectedKey.Id, regionalUnitId, i));
|
||||
}
|
||||
@@ -542,6 +553,41 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
||||
}
|
||||
|
||||
// --- Вспомогательные методы ---
|
||||
|
||||
/// <summary>
|
||||
/// Выбирает Job, соответствующий размеру подгруппы
|
||||
/// </summary>
|
||||
/// <param name="jobsInGroup">Список Job'ов в группе</param>
|
||||
/// <param name="subGroupSize">Размер подгруппы</param>
|
||||
/// <param name="maxJob">Job с максимальным MaxValueRelationships</param>
|
||||
/// <returns>Найденный Job или maxJob, если не найден подходящий</returns>
|
||||
private Job SelectTargetJob(List<Job> jobsInGroup, int subGroupSize, Job maxJob)
|
||||
{
|
||||
Job? targetJob = jobsInGroup
|
||||
.Where(j => j.MaxValueRelationships.HasValue && j.MaxValueRelationships.Value == subGroupSize)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (targetJob == null)
|
||||
{
|
||||
targetJob = jobsInGroup
|
||||
.Where(j => j.MaxValueRelationships.HasValue && j.MaxValueRelationships.Value >= subGroupSize)
|
||||
.OrderBy(j => j.MaxValueRelationships!.Value)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
if (targetJob == null)
|
||||
{
|
||||
targetJob = maxJob; // maxJob уже проверен на null ранее
|
||||
logger.LogDebug("Для подгруппы размером {Size} не найден подходящий Job, используем maxJob {MaxJobId}.", subGroupSize, maxJob.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogDebug("Для подгруппы размером {Size} выбран Job {TargetJobId} с MaxValueRelationships {MaxValue}.", subGroupSize, targetJob.Id, targetJob.MaxValueRelationships);
|
||||
}
|
||||
|
||||
return targetJob;
|
||||
}
|
||||
|
||||
private async Task UpdateTemplateUnitsAsync(Template template, List<Guid> newUnitIds, Job targetJob, HistoryInitiator initiator)
|
||||
{
|
||||
template.StatusTypeId = TemplateStatusTypeEnum.Updating;
|
||||
@@ -659,7 +705,6 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
||||
return templateName + "_" + DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
}
|
||||
|
||||
// Изменённая сигнатура: добавлен templateUnitIds
|
||||
private async Task<string> GetNormalizedTemplateNameAsync(Job targetJob, Guid unitId, int? index = null, List<Guid>? templateUnitIds = null)
|
||||
{
|
||||
// Подготовка объекта TemplateForShortcodes для передачи в ShortcodesService
|
||||
|
||||
Reference in New Issue
Block a user