feat(tempateMatcher,aihitLoader,dal): В UnitFilter добавлен Cache; в данные по ПТК добавлены аттрибуты "Холодный резерв" и "ДОПОЛНИТЕЛЬНАЯ_ИНФОРМАЦИЯ"; в синхронизаторах устанавливается неактуальная работа при деактивации
This commit is contained in:
@@ -94,6 +94,12 @@ namespace PARR.AIHITMainLoader.Models
|
|||||||
[Column("НЕУНИКАЛЬНЫЙ_ЭК")]
|
[Column("НЕУНИКАЛЬНЫЙ_ЭК")]
|
||||||
public string? IsNotUnique { get; set; }
|
public string? IsNotUnique { get; set; }
|
||||||
|
|
||||||
|
[Column("Холодный резерв")]
|
||||||
|
public string? ColdReserve { get; set; }
|
||||||
|
|
||||||
|
[Column("ДОПОЛНИТЕЛЬНАЯ_ИНФОРМАЦИЯ")]
|
||||||
|
public string? AdditionalInformation { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public AihitMainDataMq ToMainData()
|
public AihitMainDataMq ToMainData()
|
||||||
{
|
{
|
||||||
@@ -128,7 +134,9 @@ namespace PARR.AIHITMainLoader.Models
|
|||||||
{"Тип сервера инфраструктуры", InfrastructureServerType },
|
{"Тип сервера инфраструктуры", InfrastructureServerType },
|
||||||
{"Тип сервера мониторинга", MonitoringServerType },
|
{"Тип сервера мониторинга", MonitoringServerType },
|
||||||
{"ОС", OSType },
|
{"ОС", OSType },
|
||||||
{"ЗО_РГ", WorkGroupResponseArea }
|
{"ЗО_РГ", WorkGroupResponseArea },
|
||||||
|
{"Холодный резерв", ColdReserve },
|
||||||
|
{"ДОПОЛНИТЕЛЬНАЯ_ИНФОРМАЦИЯ", AdditionalInformation },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,10 +59,9 @@ namespace PARR.AIHITMainLoader.Models
|
|||||||
public int IsNotUnique { get; set; }
|
public int IsNotUnique { get; set; }
|
||||||
|
|
||||||
[Column("ЗО_РГ")]
|
[Column("ЗО_РГ")]
|
||||||
|
|
||||||
public string? WorkGroupResponseArea { get; set; }
|
public string? WorkGroupResponseArea { get; set; }
|
||||||
[Column("ДОПОЛНИТЕЛЬНАЯ_ИНФОРМАЦИЯ")]
|
|
||||||
|
|
||||||
|
[Column("ДОПОЛНИТЕЛЬНАЯ_ИНФОРМАЦИЯ")]
|
||||||
public string? AdditionalInformation { get; set; }
|
public string? AdditionalInformation { get; set; }
|
||||||
|
|
||||||
[Column("Управляемое_оборудование")]
|
[Column("Управляемое_оборудование")]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using PARR.DAL.CacheServices;
|
||||||
using PARR.DAL.Contracts;
|
using PARR.DAL.Contracts;
|
||||||
using PARR.DAL.DomainServices.Interfaces;
|
using PARR.DAL.DomainServices.Interfaces;
|
||||||
using PARR.DAL.Models.Job;
|
using PARR.DAL.Models.Job;
|
||||||
@@ -15,6 +16,7 @@ namespace PARR.DAL.DomainServices.Implementations
|
|||||||
private readonly IJobService jobService;
|
private readonly IJobService jobService;
|
||||||
private readonly IUnitService unitService;
|
private readonly IUnitService unitService;
|
||||||
private readonly IUnitInUnitService unitInUnitService;
|
private readonly IUnitInUnitService unitInUnitService;
|
||||||
|
private readonly IRedisCacheService cacheService;
|
||||||
private readonly IUnitInValueService unitInValueService;
|
private readonly IUnitInValueService unitInValueService;
|
||||||
|
|
||||||
public UnitFilterService(
|
public UnitFilterService(
|
||||||
@@ -22,12 +24,15 @@ namespace PARR.DAL.DomainServices.Implementations
|
|||||||
IJobService jobService,
|
IJobService jobService,
|
||||||
IUnitService unitService,
|
IUnitService unitService,
|
||||||
IUnitInUnitService unitInUnitService,
|
IUnitInUnitService unitInUnitService,
|
||||||
IUnitInValueService unitInValueService)
|
IUnitInValueService unitInValueService,
|
||||||
|
IRedisCacheService cacheService
|
||||||
|
)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.jobService = jobService;
|
this.jobService = jobService;
|
||||||
this.unitService = unitService;
|
this.unitService = unitService;
|
||||||
this.unitInUnitService = unitInUnitService;
|
this.unitInUnitService = unitInUnitService;
|
||||||
|
this.cacheService = cacheService;
|
||||||
this.unitInValueService = unitInValueService;
|
this.unitInValueService = unitInValueService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +66,15 @@ namespace PARR.DAL.DomainServices.Implementations
|
|||||||
public List<RelatedUnitDto> Children { get; set; } = new();
|
public List<RelatedUnitDto> Children { get; set; } = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class CachedUnitIds
|
||||||
|
{
|
||||||
|
public List<Guid> UnitIds { get; set; } = new();
|
||||||
|
public DateTimeOffset Timestamp { get; set; }
|
||||||
|
public string? Source { get; set; } = "UnitFilterService";
|
||||||
|
public int Version { get; set; } = 1;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public async Task<IEnumerable<Guid>?> GetUnitsIdByJobFilterAsync(Guid jobId, int? takeCount = null)
|
public async Task<IEnumerable<Guid>?> GetUnitsIdByJobFilterAsync(Guid jobId, int? takeCount = null)
|
||||||
@@ -100,10 +114,7 @@ namespace PARR.DAL.DomainServices.Implementations
|
|||||||
logger.LogDebug("Применяем фильтр #{Index} (Id={FilterId})", filterNumber, filter.Id);
|
logger.LogDebug("Применяем фильтр #{Index} (Id={FilterId})", filterNumber, filter.Id);
|
||||||
|
|
||||||
// 1️ Найти ID юнитов по UnitFilter (Name LIKE)
|
// 1️ Найти ID юнитов по UnitFilter (Name LIKE)
|
||||||
var initialUnitIds = await unitService.Get().AsNoTracking()
|
var initialUnitIds = await GetUnitIdsFromCacheOrDbAsync(filter);
|
||||||
.Where(unit => EF.Functions.Like(unit.Name, filter.UnitFilter))
|
|
||||||
.Select(u => u.Id)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
logger.LogDebug("Базовый фильтр по Name '{NameFilter}' дал {Count} юнитов", filter.UnitFilter, initialUnitIds.Count);
|
logger.LogDebug("Базовый фильтр по Name '{NameFilter}' дал {Count} юнитов", filter.UnitFilter, initialUnitIds.Count);
|
||||||
|
|
||||||
@@ -516,6 +527,46 @@ namespace PARR.DAL.DomainServices.Implementations
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<List<Guid>> GetUnitIdsFromCacheOrDbAsync(JobUnitFilter filter)
|
||||||
|
{
|
||||||
|
var cacheKey = $"uf_ids_{ComputeHash(filter.UnitFilter)}";
|
||||||
|
|
||||||
|
var cachedData = await cacheService.GetCachedDataAsync<CachedUnitIds>(cacheKey);
|
||||||
|
if (cachedData != null)
|
||||||
|
{
|
||||||
|
logger.LogDebug("Кэш попал для UnitFilter '{Name}': {Count} юнитов", filter.UnitFilter, cachedData.UnitIds.Count);
|
||||||
|
return cachedData.UnitIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogDebug("Кэш промахнут для UnitFilter '{Name}'. Запрашиваем из БД.", filter.UnitFilter);
|
||||||
|
|
||||||
|
var initialUnitIds = await unitService.Get().AsNoTracking()
|
||||||
|
.Where(unit => EF.Functions.Like(unit.Name, filter.UnitFilter))
|
||||||
|
.Select(u => u.Id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
logger.LogDebug("Загружено {Count} юнитов из БД для UnitFilter '{Name}'", initialUnitIds.Count, filter.UnitFilter);
|
||||||
|
|
||||||
|
var toCache = new CachedUnitIds
|
||||||
|
{
|
||||||
|
UnitIds = initialUnitIds,
|
||||||
|
Timestamp = DateTimeOffset.UtcNow,
|
||||||
|
Source = GetType().Name,
|
||||||
|
Version = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
await cacheService.SetCachedDataAsync(cacheKey, toCache, TimeSpan.FromHours(1));
|
||||||
|
|
||||||
|
return initialUnitIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ComputeHash(string input)
|
||||||
|
{
|
||||||
|
using var sha256 = System.Security.Cryptography.SHA256.Create();
|
||||||
|
var hashedBytes = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input));
|
||||||
|
return Convert.ToBase64String(hashedBytes).Replace('+', '-').Replace('/', '_').Substring(0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,6 +41,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
private readonly IEsppScheduleTransformService esppScheduleTransformService;
|
private readonly IEsppScheduleTransformService esppScheduleTransformService;
|
||||||
private readonly IUnitRegionalEkPtkGroupService regionalEkPtkGroupService;
|
private readonly IUnitRegionalEkPtkGroupService regionalEkPtkGroupService;
|
||||||
private readonly IUnitFieldService unitFieldService;
|
private readonly IUnitFieldService unitFieldService;
|
||||||
|
private readonly IJobService jobService;
|
||||||
|
|
||||||
public GroupedTemplateSynchronizer(
|
public GroupedTemplateSynchronizer(
|
||||||
ILogger<GroupedTemplateSynchronizer> logger,
|
ILogger<GroupedTemplateSynchronizer> logger,
|
||||||
@@ -56,7 +57,8 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
IShortcodesService shortcodesService,
|
IShortcodesService shortcodesService,
|
||||||
IEsppScheduleTransformService esppScheduleTransformService,
|
IEsppScheduleTransformService esppScheduleTransformService,
|
||||||
IUnitRegionalEkPtkGroupService regionalEkPtkGroupService,
|
IUnitRegionalEkPtkGroupService regionalEkPtkGroupService,
|
||||||
IUnitFieldService unitFieldService
|
IUnitFieldService unitFieldService,
|
||||||
|
IJobService jobService
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
@@ -73,6 +75,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
this.esppScheduleTransformService = esppScheduleTransformService;
|
this.esppScheduleTransformService = esppScheduleTransformService;
|
||||||
this.regionalEkPtkGroupService = regionalEkPtkGroupService;
|
this.regionalEkPtkGroupService = regionalEkPtkGroupService;
|
||||||
this.unitFieldService = unitFieldService;
|
this.unitFieldService = unitFieldService;
|
||||||
|
this.jobService = jobService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SyncTemplatesForJobAsync(Guid jobId, HistoryInitiator initiator)
|
public async Task SyncTemplatesForJobAsync(Guid jobId, HistoryInitiator initiator)
|
||||||
@@ -105,7 +108,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
|
|
||||||
var jobsInGroup = jobGroup.Jobs.ToList();
|
var jobsInGroup = jobGroup.Jobs.ToList();
|
||||||
|
|
||||||
// --- НОВАЯ ЛОГИКА: Получение FieldId и разрешённых значений для "РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК" ---
|
// --- Получение FieldId и разрешённых значений для "РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК" ---
|
||||||
var workGroupField = await unitFieldService.GetByAihitNameAsync("РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК");
|
var workGroupField = await unitFieldService.GetByAihitNameAsync("РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК");
|
||||||
if (workGroupField == null)
|
if (workGroupField == null)
|
||||||
{
|
{
|
||||||
@@ -120,6 +123,17 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
|
|
||||||
logger.LogDebug("Найдено {Count} значений из UnitRegionalEkPtkGroup для проверки поля 'РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК'.", regionalGroupValueIds.Count);
|
logger.LogDebug("Найдено {Count} значений из UnitRegionalEkPtkGroup для проверки поля 'РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК'.", regionalGroupValueIds.Count);
|
||||||
|
|
||||||
|
|
||||||
|
// Загружаем заранее подготовленный Job (например, для неиспользуемых шаблонов)
|
||||||
|
var unusedJobId = Guid.Parse("8f85a91c-a223-4686-bb69-1f0ee73624f2");
|
||||||
|
|
||||||
|
var unusedJob = await jobService.Get()
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(j => j.Tnk)
|
||||||
|
.Include(j => j.Group)
|
||||||
|
.ThenInclude(g => g.GroupType)
|
||||||
|
.FirstOrDefaultAsync(j => j.Id == unusedJobId);
|
||||||
|
|
||||||
// 2. Найти Job с максимальным MaxValueRelationships
|
// 2. Найти Job с максимальным MaxValueRelationships
|
||||||
var maxJob = jobsInGroup
|
var maxJob = jobsInGroup
|
||||||
.Where(j => j.MaxValueRelationships.HasValue)
|
.Where(j => j.MaxValueRelationships.HasValue)
|
||||||
@@ -387,7 +401,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
logger.LogDebug("Связанный юнит {RegionalUnitId}: разбит на {GroupCount} подгрупп.", relationshipUnitId, childUnitGroups.Count);
|
logger.LogDebug("Связанный юнит {RegionalUnitId}: разбит на {GroupCount} подгрупп.", relationshipUnitId, childUnitGroups.Count);
|
||||||
|
|
||||||
// Для каждой подгруппы:
|
// Для каждой подгруппы:
|
||||||
for (int i = 1; i <= childUnitGroups.Count; i++)
|
for (int i = 0; i < childUnitGroups.Count; i++)
|
||||||
{
|
{
|
||||||
var subGroup = childUnitGroups[i];
|
var subGroup = childUnitGroups[i];
|
||||||
var subGroupSize = subGroup.Count;
|
var subGroupSize = subGroup.Count;
|
||||||
@@ -401,7 +415,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
var existingTemplatesForRelationship = await templateService.Get()
|
var existingTemplatesForRelationship = await templateService.Get()
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Include(t => t.UnitsInTemplate)
|
.Include(t => t.UnitsInTemplate)
|
||||||
.Where(t => t.JobId == targetJob.Id && t.UnitId == relationshipUnitId && t.Index == i)
|
.Where(t => t.JobId == targetJob.Id && t.UnitId == relationshipUnitId && t.Index == i && t.StatusTypeId == TemplateStatusTypeEnum.Used)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var existingTemplateForSubGroup = existingTemplatesForRelationship.FirstOrDefault();
|
var existingTemplateForSubGroup = existingTemplatesForRelationship.FirstOrDefault();
|
||||||
@@ -416,7 +430,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
{
|
{
|
||||||
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);
|
var expectedName = await GetNormalizedTemplateNameAsync(targetJob, relationshipUnitId, i, subGroup);
|
||||||
if (!string.Equals(existingTemplateForSubGroup.Name, expectedName, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(existingTemplateForSubGroup.Name, expectedName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@@ -434,7 +448,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
IsActiveSchedule = existingTemplateForSubGroup.IsActiveSchedule,
|
IsActiveSchedule = existingTemplateForSubGroup.IsActiveSchedule,
|
||||||
LastRun = existingTemplateForSubGroup.LastRun,
|
LastRun = existingTemplateForSubGroup.LastRun,
|
||||||
NextRun = nextRun,
|
NextRun = nextRun,
|
||||||
Index = i,
|
Index = i ,
|
||||||
StatusTypeId = TemplateStatusTypeEnum.Used,
|
StatusTypeId = TemplateStatusTypeEnum.Used,
|
||||||
Initiator = initiator,
|
Initiator = initiator,
|
||||||
UnitsInTemplate = subGroup
|
UnitsInTemplate = subGroup
|
||||||
@@ -539,7 +553,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
if (!expectedTemplateKeys.Contains(key))
|
if (!expectedTemplateKeys.Contains(key))
|
||||||
{
|
{
|
||||||
logger.LogInformation("Деактивация лишнего шаблона {TemplateId} (Job {JobId}, Regional {UnitId}, Index {Index}).", existingTemplate.Id, existingTemplate.JobId, existingTemplate.UnitId, existingTemplate.Index);
|
logger.LogInformation("Деактивация лишнего шаблона {TemplateId} (Job {JobId}, Regional {UnitId}, Index {Index}).", existingTemplate.Id, existingTemplate.JobId, existingTemplate.UnitId, existingTemplate.Index);
|
||||||
await DeactivateTemplateAsync(existingTemplate, existingTemplate.JobId, initiator);
|
await DeactivateTemplateAsync(existingTemplate, existingTemplate.JobId, unusedJob, initiator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,10 +658,11 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
private async Task<bool> DeactivateTemplateAsync(
|
private async Task<bool> DeactivateTemplateAsync(
|
||||||
Template template,
|
Template template,
|
||||||
Guid jobId,
|
Guid jobId,
|
||||||
|
Job unusedJob,
|
||||||
HistoryInitiator initiator)
|
HistoryInitiator initiator)
|
||||||
{
|
{
|
||||||
if (template.StatusTypeId == TemplateStatusTypeEnum.Updating)
|
if (template.StatusTypeId == TemplateStatusTypeEnum.Updating)
|
||||||
return true; // уже в обработке
|
return true;
|
||||||
|
|
||||||
if (template.StatusTypeId == TemplateStatusTypeEnum.Unused)
|
if (template.StatusTypeId == TemplateStatusTypeEnum.Unused)
|
||||||
{
|
{
|
||||||
@@ -667,17 +682,26 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unusedJob == null)
|
||||||
|
{
|
||||||
|
logger.LogError("Job для деактивированных шаблонов не найден.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вычисляем имя шаблона с новым Job
|
||||||
|
var expectedName = await GetNormalizedTemplateNameAsync(unusedJob, template.UnitId);
|
||||||
|
|
||||||
var updateRequest = new TemplateUpdaterMq
|
var updateRequest = new TemplateUpdaterMq
|
||||||
{
|
{
|
||||||
TemplateId = template.Id,
|
TemplateId = template.Id,
|
||||||
JobId = jobId,
|
JobId = unusedJob.Id,
|
||||||
UnitId = template.UnitId,
|
UnitId = template.UnitId,
|
||||||
Name = GetTemplateNameForUnused(template.Name),
|
Name = GetTemplateNameForUnused(expectedName),
|
||||||
IsActiveTemplate = DefaultUnusedTemplateState,
|
IsActiveTemplate = DefaultUnusedTemplateState,
|
||||||
IsActiveSchedule = DefaultUnusedScheduleState,
|
IsActiveSchedule = DefaultUnusedScheduleState,
|
||||||
LastRun = template.LastRun,
|
LastRun = template.LastRun,
|
||||||
NextRun = template.NextRun,
|
NextRun = template.NextRun,
|
||||||
Index = template.Index,
|
Index = null,
|
||||||
StatusTypeId = TemplateStatusTypeEnum.Unused,
|
StatusTypeId = TemplateStatusTypeEnum.Unused,
|
||||||
Initiator = initiator,
|
Initiator = initiator,
|
||||||
UnitsInTemplate = new List<Guid>()
|
UnitsInTemplate = new List<Guid>()
|
||||||
@@ -717,7 +741,7 @@ internal class GroupedTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
var templateForShortcodes = new TemplateForShortcodes
|
var templateForShortcodes = new TemplateForShortcodes
|
||||||
{
|
{
|
||||||
Id = Guid.Empty, // Не используется в подстановке, но нужен для структуры
|
Id = Guid.Empty, // Не используется в подстановке, но нужен для структуры
|
||||||
Index = index,
|
Index = index+1,
|
||||||
JobId = targetJob.Id,
|
JobId = targetJob.Id,
|
||||||
UnitId = unitId,
|
UnitId = unitId,
|
||||||
Job = new JobForShortcodes
|
Job = new JobForShortcodes
|
||||||
|
|||||||
@@ -69,6 +69,16 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
{
|
{
|
||||||
logger.LogDebug("Начало синхронизации шаблонов для JobId {JobId}", jobId);
|
logger.LogDebug("Начало синхронизации шаблонов для JobId {JobId}", jobId);
|
||||||
|
|
||||||
|
// Загружаем заранее подготовленный Job (например, для неиспользуемых шаблонов)
|
||||||
|
var unusedJobId = Guid.Parse("8f85a91c-a223-4686-bb69-1f0ee73624f2");
|
||||||
|
|
||||||
|
var unusedJob = await jobService.Get()
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(j => j.Tnk)
|
||||||
|
.Include(j => j.Group)
|
||||||
|
.ThenInclude(g => g.GroupType)
|
||||||
|
.FirstOrDefaultAsync(j => j.Id == unusedJobId);
|
||||||
|
|
||||||
var expectedUnitIds = await GetExpectedUnitIdsAsync(jobId) ?? new HashSet<Guid>();
|
var expectedUnitIds = await GetExpectedUnitIdsAsync(jobId) ?? new HashSet<Guid>();
|
||||||
logger.LogDebug("JobId {JobId}: найдено {Count} UnitId по фильтрам.", jobId, expectedUnitIds.Count);
|
logger.LogDebug("JobId {JobId}: найдено {Count} UnitId по фильтрам.", jobId, expectedUnitIds.Count);
|
||||||
|
|
||||||
@@ -106,7 +116,7 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
|
|
||||||
foreach (var template in existingTemplates)
|
foreach (var template in existingTemplates)
|
||||||
{
|
{
|
||||||
await DeactivateTemplateAsync(template, jobId, initiator);
|
await DeactivateTemplateAsync(template, jobId, unusedJob, initiator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -125,14 +135,14 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
|
|
||||||
foreach (var template in templatesToDeactivate)
|
foreach (var template in templatesToDeactivate)
|
||||||
{
|
{
|
||||||
await DeactivateTemplateAsync(template, jobId, initiator);
|
await DeactivateTemplateAsync(template, jobId, unusedJob, initiator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Перечитываем шаблоны после деактивации
|
// Перечитываем шаблоны после деактивации
|
||||||
existingTemplates = await templateService.Get()
|
existingTemplates = await templateService.Get()
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Include(t=>t.Job)
|
.Include(t => t.Job)
|
||||||
.ThenInclude(t=>t.Tnk)
|
.ThenInclude(t => t.Tnk)
|
||||||
.Where(t => t.JobId == jobId)
|
.Where(t => t.JobId == jobId)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@@ -202,6 +212,16 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
{
|
{
|
||||||
logger.LogDebug("Начало обновления шаблонов для JobId {JobId}", jobId);
|
logger.LogDebug("Начало обновления шаблонов для JobId {JobId}", jobId);
|
||||||
|
|
||||||
|
// Загружаем заранее подготовленный Job (например, для неиспользуемых шаблонов)
|
||||||
|
var unusedJobId = Guid.Parse("8f85a91c-a223-4686-bb69-1f0ee73624f2");
|
||||||
|
|
||||||
|
var unusedJob = await jobService.Get()
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(j => j.Tnk)
|
||||||
|
.Include(j => j.Group)
|
||||||
|
.ThenInclude(g => g.GroupType)
|
||||||
|
.FirstOrDefaultAsync(j => j.Id == unusedJobId);
|
||||||
|
|
||||||
var existingTemplates = await templateService.Get()
|
var existingTemplates = await templateService.Get()
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(t => t.JobId == jobId)
|
.Where(t => t.JobId == jobId)
|
||||||
@@ -237,7 +257,18 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
targetStatus = TemplateStatusTypeEnum.Unused;
|
targetStatus = TemplateStatusTypeEnum.Unused;
|
||||||
targetIsActiveTemplate = DefaultUnusedTemplateState;
|
targetIsActiveTemplate = DefaultUnusedTemplateState;
|
||||||
targetIsActiveSchedule = DefaultUnusedScheduleState;
|
targetIsActiveSchedule = DefaultUnusedScheduleState;
|
||||||
expectedName = GetTemplateNameForUnused(expectedName);
|
|
||||||
|
// ✅ Вычисляем имя шаблона с новым unusedJob
|
||||||
|
if (unusedJob != null)
|
||||||
|
{
|
||||||
|
expectedName = await GetNormalizedTemplateNameAsync(unusedJob, template.UnitId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogError("Job для деактивированных шаблонов не найден.");
|
||||||
|
expectedName = GetTemplateNameForUnused(template.Name);
|
||||||
|
}
|
||||||
|
|
||||||
logger.LogInformation("Шаблон {TemplateId} (UnitId {UnitId}) → деактивация.", template.Id, template.UnitId);
|
logger.LogInformation("Шаблон {TemplateId} (UnitId {UnitId}) → деактивация.", template.Id, template.UnitId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +301,7 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
var updateRequest = new TemplateUpdaterMq
|
var updateRequest = new TemplateUpdaterMq
|
||||||
{
|
{
|
||||||
TemplateId = template.Id,
|
TemplateId = template.Id,
|
||||||
JobId = jobId,
|
JobId = unitStillInFilter ? jobId : unusedJob?.Id ?? jobId, // ✅ Используем unusedJob.Id, если деактивация
|
||||||
UnitId = template.UnitId,
|
UnitId = template.UnitId,
|
||||||
Name = expectedName,
|
Name = expectedName,
|
||||||
IsActiveTemplate = targetIsActiveTemplate,
|
IsActiveTemplate = targetIsActiveTemplate,
|
||||||
@@ -293,6 +324,7 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
private async Task<bool> DeactivateTemplateAsync(
|
private async Task<bool> DeactivateTemplateAsync(
|
||||||
Template template,
|
Template template,
|
||||||
Guid jobId,
|
Guid jobId,
|
||||||
|
Job unusedJob,
|
||||||
HistoryInitiator initiator)
|
HistoryInitiator initiator)
|
||||||
{
|
{
|
||||||
if (template.StatusTypeId == TemplateStatusTypeEnum.Updating)
|
if (template.StatusTypeId == TemplateStatusTypeEnum.Updating)
|
||||||
@@ -316,12 +348,21 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unusedJob == null)
|
||||||
|
{
|
||||||
|
logger.LogError("Job для деактивированных шаблонов не найден.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Вычисляем имя шаблона с новым Job
|
||||||
|
var expectedName = await GetNormalizedTemplateNameAsync(unusedJob, template.UnitId);
|
||||||
|
|
||||||
var updateRequest = new TemplateUpdaterMq
|
var updateRequest = new TemplateUpdaterMq
|
||||||
{
|
{
|
||||||
TemplateId = template.Id,
|
TemplateId = template.Id,
|
||||||
JobId = jobId,
|
JobId = unusedJob.Id, // ✅ Используем unusedJob.Id
|
||||||
UnitId = template.UnitId,
|
UnitId = template.UnitId,
|
||||||
Name = GetTemplateNameForUnused(template.Name),
|
Name = GetTemplateNameForUnused(expectedName), // ✅ Используем новое имя
|
||||||
IsActiveTemplate = DefaultUnusedTemplateState,
|
IsActiveTemplate = DefaultUnusedTemplateState,
|
||||||
IsActiveSchedule = DefaultUnusedScheduleState,
|
IsActiveSchedule = DefaultUnusedScheduleState,
|
||||||
LastRun = template.LastRun,
|
LastRun = template.LastRun,
|
||||||
@@ -434,7 +475,7 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
{
|
{
|
||||||
return await jobService.Get()
|
return await jobService.Get()
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Include(j=>j.Tnk)
|
.Include(j => j.Tnk)
|
||||||
.Include(j => j.Group)
|
.Include(j => j.Group)
|
||||||
.ThenInclude(j => j.GroupType)
|
.ThenInclude(j => j.GroupType)
|
||||||
.Include(j => j.AutoControl)
|
.Include(j => j.AutoControl)
|
||||||
@@ -453,8 +494,8 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
var templateForShortcodes = new TemplateForShortcodes
|
var templateForShortcodes = new TemplateForShortcodes
|
||||||
{
|
{
|
||||||
Id = Guid.Empty, // шаблон ещё не создан
|
Id = Guid.Empty, // шаблон ещё не создан
|
||||||
Index = null,
|
Index = null,
|
||||||
JobId = job.Id,
|
JobId = job.Id,
|
||||||
UnitId = unitId,
|
UnitId = unitId,
|
||||||
Job = new JobForShortcodes
|
Job = new JobForShortcodes
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ internal class TemplateReuser : ITemplateReuser
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var unusedCandidates = await templateService.Get()
|
var unusedCandidates = await templateService.Get()
|
||||||
.AsNoTracking()
|
|
||||||
.Where(t => t.StatusTypeId == TemplateStatusTypeEnum.Unused)
|
.Where(t => t.StatusTypeId == TemplateStatusTypeEnum.Unused)
|
||||||
.OrderBy(t => t.DateModified ?? t.DateCreated)
|
.OrderBy(t => t.DateModified ?? t.DateCreated)
|
||||||
.Take(UnusedCandidateBatchSize)
|
.Take(UnusedCandidateBatchSize)
|
||||||
|
|||||||
Reference in New Issue
Block a user