Compare commits

1 Commits

View File

@@ -103,33 +103,29 @@ internal class GroupedTemplateBuilder : IGroupedTemplateBuilder
// 5. Определяем значения для внутренней группировки // 5. Определяем значения для внутренней группировки
Dictionary<Guid, string> unitIdToGroupingValueMap; Dictionary<Guid, string> unitIdToGroupingValueMap;
// Загружаем список разрешённых региональных ПТК (если не нужно пропускать фильтрацию)
bool skipRegionalFilter = maxJob.WorkGroupMask.Contains("_в_ЗО_РГ", StringComparison.OrdinalIgnoreCase);
HashSet<string>? allowedWorkGroupSet = null;
if (!skipRegionalFilter)
{
var allowedWorkGroupValues = await regionalEkPtkGroupRepository.Get()
.AsNoTracking()
.Include(g => g.FieldValue)
.Where(g => g.FieldValue != null && g.FieldValue.Value != null)
.Select(g => g.FieldValue!.Value!)
.ToListAsync(ct);
allowedWorkGroupSet = new HashSet<string>(allowedWorkGroupValues, StringComparer.OrdinalIgnoreCase);
logger.LogDebug("Загружено {Count} разрешённых значений рабочих групп из RegionalEkPtkGroup.", allowedWorkGroupSet.Count);
}
else
{
logger.LogDebug("Маска содержит тег с '_в_ЗО_РГ'. Фильтрация по списку рабочих групп ПТК пропущена.");
}
if (useWorkGroupMask) if (useWorkGroupMask)
{ {
// Определяем, нужно ли выполнять фильтрацию по списку рабочих групп ПТК.
// Если маска содержит тег с "_в_ЗО_РГ", фильтрация не выполняется.
var skipRegionalFilter = maxJob.WorkGroupMask.Contains("_в_ЗО_РГ", StringComparison.OrdinalIgnoreCase);
HashSet<string>? allowedWorkGroupSet = null;
if (!skipRegionalFilter)
{
// Загружаем разрешённые значения из regionalEkPtkGroupRepository
var allowedWorkGroupValues = await regionalEkPtkGroupRepository.Get()
.AsNoTracking()
.Include(g => g.FieldValue)
.Where(g => g.FieldValue != null && g.FieldValue.Value != null)
.Select(g => g.FieldValue!.Value!)
.ToListAsync(ct);
allowedWorkGroupSet = new HashSet<string>(allowedWorkGroupValues, StringComparer.OrdinalIgnoreCase);
logger.LogDebug("Загружено {Count} разрешённых значений рабочих групп из RegionalEkPtkGroup.", allowedWorkGroupSet.Count);
}
else
{
logger.LogDebug("Маска содержит тег с '_в_ЗО_РГ'. Фильтрация по списку рабочих групп ПТК пропущена.");
}
// Применяем WorkGroupMask для каждого юнита отдельно // Применяем WorkGroupMask для каждого юнита отдельно
unitIdToGroupingValueMap = new Dictionary<Guid, string>(); unitIdToGroupingValueMap = new Dictionary<Guid, string>();
@@ -169,16 +165,16 @@ internal class GroupedTemplateBuilder : IGroupedTemplateBuilder
continue; continue;
} }
// Фильтрация по списку рабочих групп ПТК выполняется только если не используется тег с "_в_ЗО_РГ" // Фильтрация по списку рабочих групп ПТК
if (!skipRegionalFilter && !allowedWorkGroupSet!.Contains(workGroupValue)) if (!skipRegionalFilter && !allowedWorkGroupSet!.Contains(workGroupValue))
{ {
logger.LogDebug( // Изменено с LogDebug на LogInformation для тестирования logger.LogDebug(
"[FILTER] Юнит {UnitId} ИСКЛЮЧЁН: рабочая группа '{WorkGroup}' не найдена в списке разрешённых ({AllowedCount} значений).", "[FILTER] Юнит {UnitId} ИСКЛЮЧЁН: рабочая группа '{WorkGroup}' не найдена в списке разрешённых ({AllowedCount} значений).",
relatedUnitId, workGroupValue, allowedWorkGroupSet!.Count); relatedUnitId, workGroupValue, allowedWorkGroupSet!.Count);
continue; continue;
} }
logger.LogDebug( // Добавляем лог для успешного прохождения logger.LogDebug(
"[FILTER] Юнит {UnitId} ПРОШЁЛ: рабочая группа '{WorkGroup}' для PotentialUnit {PotentialUnitId}.", "[FILTER] Юнит {UnitId} ПРОШЁЛ: рабочая группа '{WorkGroup}' для PotentialUnit {PotentialUnitId}.",
relatedUnitId, workGroupValue, potentialUnitId); relatedUnitId, workGroupValue, potentialUnitId);
@@ -201,9 +197,79 @@ internal class GroupedTemplateBuilder : IGroupedTemplateBuilder
new HashSet<Guid> { innerGroupingFieldId }, new HashSet<Guid> { innerGroupingFieldId },
ct); ct);
unitIdToGroupingValueMap = innerGroupingValues // Собираем значения поля "Ответственный" для группировки
.Where(uv => uv.Value != null && uv.Value.Value != null && !string.IsNullOrEmpty(uv.Value.Value)) var responsibleValueByUnit = innerGroupingValues
.Where(uv => uv.Value != null && !string.IsNullOrEmpty(uv.Value.Value))
.ToDictionary(uv => uv.UnitId, uv => uv.Value!.Value!); .ToDictionary(uv => uv.UnitId, uv => uv.Value!.Value!);
unitIdToGroupingValueMap = new Dictionary<Guid, string>();
// Для каждого юнита дополнительно применяем WorkGroupMask и фильтруем по RegionalEkPtkGroup
foreach (var potentialUnitId in reverseMapping.Keys)
{
var relatedUnitIds = reverseMapping[potentialUnitId]
.Select(e => e.UnitId)
.Distinct()
.ToList();
foreach (var relatedUnitId in relatedUnitIds)
{
// Юнит исключается, если у него нет значения поля "Ответственный"
if (!responsibleValueByUnit.TryGetValue(relatedUnitId, out var responsibleValue))
{
logger.LogDebug(
"Юнит {UnitId} исключён: отсутствует значение поля 'Ответственный за ЭК'.",
relatedUnitId);
continue;
}
// Фильтрация по списку региональных ПТК выполняется только если не используется тег с "_в_ЗО_РГ"
if (!skipRegionalFilter)
{
// Формируем временный шаблон с одним связанным юнитом для применения WorkGroupMask
var tempTemplate = new Template
{
Id = Guid.NewGuid(),
Name = "temp",
JobId = maxJob.Id,
UnitId = potentialUnitId,
Job = maxJob,
UnitsInTemplate = new List<UnitsInTemplate>
{
new UnitsInTemplate { UnitId = relatedUnitId, UnitFieldValueId = Guid.Empty }
}
};
var workGroupValue = await shortcodesService.ApplyShortcodesAsync(
maxJob.WorkGroupMask,
tempTemplate,
nameof(GroupedTemplateBuilder));
if (string.IsNullOrEmpty(workGroupValue))
{
logger.LogDebug(
"Юнит {UnitId} исключён: WorkGroupMask вернула пустую строку.",
relatedUnitId);
continue;
}
if (!allowedWorkGroupSet!.Contains(workGroupValue))
{
logger.LogDebug(
"[FILTER] Юнит {UnitId} ИСКЛЮЧЁН: рабочая группа '{WorkGroup}' не найдена в списке разрешённых ({AllowedCount} значений).",
relatedUnitId, workGroupValue, allowedWorkGroupSet!.Count);
continue;
}
logger.LogDebug(
"[FILTER] Юнит {UnitId} ПРОШЁЛ: рабочая группа '{WorkGroup}' для PotentialUnit {PotentialUnitId}.",
relatedUnitId, workGroupValue, potentialUnitId);
}
// В маппинг группировки пишем значение поля "Ответственный" — по нему идёт группировка в этапе 6
unitIdToGroupingValueMap[relatedUnitId] = responsibleValue;
}
}
} }
// 6. Формируем итоговую структуру // 6. Формируем итоговую структуру