fix(dal): исправлен UnitFilterService, фильтровались юниты у которых нет связей, но проверку фильтров они проходили.
This commit is contained in:
@@ -16,9 +16,12 @@ namespace PARR.DAL.DomainServices.UnitFilterService;
|
|||||||
internal class UnitFilterService : IUnitFilterService
|
internal class UnitFilterService : IUnitFilterService
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
private readonly Guid targetUnitId = Guid.Parse("0e84812c-66ee-46fc-bb72-2afbecf354cb");
|
private readonly Guid targetUnitId = Guid.Parse("9d88fff2-a861-487f-b73d-bce1f0218e9f");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
private const int DebugMaxUnitsToLog = 10;
|
||||||
|
private const int DebugMaxRelationsToLog = 5;
|
||||||
|
|
||||||
private readonly int batchSize;
|
private readonly int batchSize;
|
||||||
|
|
||||||
private readonly ILogger<UnitFilterService> logger;
|
private readonly ILogger<UnitFilterService> logger;
|
||||||
@@ -262,9 +265,6 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Применяем фильтры аттрибутов
|
/// Применяем фильтры аттрибутов
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="unitIds"></param>
|
|
||||||
/// <param name="fieldFilters"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task<List<Guid>> ApplyFieldFiltersOnDbAsync(
|
private async Task<List<Guid>> ApplyFieldFiltersOnDbAsync(
|
||||||
List<Guid> unitIds,
|
List<Guid> unitIds,
|
||||||
IEnumerable<JobFieldFilter> fieldFilters,
|
IEnumerable<JobFieldFilter> fieldFilters,
|
||||||
@@ -288,18 +288,7 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
if (string.IsNullOrEmpty(valueMask))
|
if (string.IsNullOrEmpty(valueMask))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Обработка маски LIKE
|
string dbValueMask = NormalizeLikeMask(valueMask);
|
||||||
bool isStartsWith = valueMask.EndsWith("%") && !valueMask.EndsWith("%%");
|
|
||||||
bool isEndsWith = valueMask.StartsWith("%") && !valueMask.StartsWith("%%");
|
|
||||||
string dbValueMask;
|
|
||||||
if (isStartsWith && isEndsWith)
|
|
||||||
dbValueMask = $"%{valueMask.Trim('%')}%";
|
|
||||||
else if (isStartsWith)
|
|
||||||
dbValueMask = $"{valueMask.TrimEnd('%')}%";
|
|
||||||
else if (isEndsWith)
|
|
||||||
dbValueMask = $"%{valueMask.TrimStart('%')}";
|
|
||||||
else
|
|
||||||
dbValueMask = valueMask;
|
|
||||||
|
|
||||||
var fieldName = fieldFilter.UnitField?.AihitName ?? $"FieldId={fieldFilter.FieldId}";
|
var fieldName = fieldFilter.UnitField?.AihitName ?? $"FieldId={fieldFilter.FieldId}";
|
||||||
logger.LogDebug(" FieldFilter #{Index}: Поле='{FieldName}', Маска='{Mask}', IsInverse={IsInverse}",
|
logger.LogDebug(" FieldFilter #{Index}: Поле='{FieldName}', Маска='{Mask}', IsInverse={IsInverse}",
|
||||||
@@ -317,6 +306,30 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
v.FieldId == fieldFilter.FieldId &&
|
v.FieldId == fieldFilter.FieldId &&
|
||||||
EF.Functions.ILike(v.Value.Value, dbValueMask)));
|
EF.Functions.ILike(v.Value.Value, dbValueMask)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (unitIds.Contains(targetUnitId))
|
||||||
|
{
|
||||||
|
var unitHasField = await unitInValueService.Get()
|
||||||
|
.AsNoTracking()
|
||||||
|
.AnyAsync(uiv => uiv.UnitId == targetUnitId && uiv.FieldId == fieldFilter.FieldId, cancellationToken);
|
||||||
|
|
||||||
|
var unitValue = await unitInValueService.Get()
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(uiv => uiv.UnitId == targetUnitId && uiv.FieldId == fieldFilter.FieldId)
|
||||||
|
.Select(uiv => uiv.Value.Value)
|
||||||
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
|
|
||||||
|
var intermediateResult = await query.Select(u => u.Id).ToListAsync(cancellationToken);
|
||||||
|
var passes = intermediateResult.Contains(targetUnitId);
|
||||||
|
|
||||||
|
logger.LogDebug(" DEBUG: Юнит {TargetUnitId}: Поле={FieldName}, Значение={Value}, Маска={Mask}, HasField={HasField}, Проходит={Passes}",
|
||||||
|
targetUnitId, fieldName, unitValue ?? "null", dbValueMask, unitHasField, passes);
|
||||||
|
|
||||||
|
query = unitService.Get().AsNoTracking()
|
||||||
|
.Where(u => intermediateResult.Contains(u.Id));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await query.Select(u => u.Id).ToListAsync(cancellationToken);
|
var result = await query.Select(u => u.Id).ToListAsync(cancellationToken);
|
||||||
@@ -329,9 +342,6 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Применяем фильтры аттрибутов у связанных ЭК
|
/// Применяем фильтры аттрибутов у связанных ЭК
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="unitIds"></param>
|
|
||||||
/// <param name="relationshipFilters"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task<List<FilteredUnitContext>> ProcessRelationshipFiltersAsync(
|
private async Task<List<FilteredUnitContext>> ProcessRelationshipFiltersAsync(
|
||||||
List<Guid> unitIds,
|
List<Guid> unitIds,
|
||||||
IEnumerable<JobRelationshipFilter> relationshipFilters,
|
IEnumerable<JobRelationshipFilter> relationshipFilters,
|
||||||
@@ -347,12 +357,18 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
logger.LogDebug("ProcessRelationshipFiltersAsync: вход {UnitCount} юнитов, фильтров: {FilterCount}",
|
logger.LogDebug("ProcessRelationshipFiltersAsync: вход {UnitCount} юнитов, фильтров: {FilterCount}",
|
||||||
unitIds.Count, relationshipFilters.Count());
|
unitIds.Count, relationshipFilters.Count());
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (unitIds.Contains(targetUnitId))
|
||||||
|
{
|
||||||
|
logger.LogDebug("DEBUG: Юнит {TargetUnitId} найден во входных данных ProcessRelationshipFiltersAsync", targetUnitId);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
var resultContexts = unitIds.ToDictionary(id => id, id => new FilteredUnitContext { UnitId = id });
|
var resultContexts = unitIds.ToDictionary(id => id, id => new FilteredUnitContext { UnitId = id });
|
||||||
|
|
||||||
var parentRelFilters = relationshipFilters.Where(rf => rf.IsParent).ToList();
|
var parentRelFilters = relationshipFilters.Where(rf => rf.IsParent).ToList();
|
||||||
var childRelFilters = relationshipFilters.Where(rf => !rf.IsParent).ToList();
|
var childRelFilters = relationshipFilters.Where(rf => !rf.IsParent).ToList();
|
||||||
|
|
||||||
// Обработка родительских фильтров
|
|
||||||
if (parentRelFilters.Any())
|
if (parentRelFilters.Any())
|
||||||
{
|
{
|
||||||
await ApplyRelationshipFiltersOnDbAsync(
|
await ApplyRelationshipFiltersOnDbAsync(
|
||||||
@@ -363,7 +379,6 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обработка дочерних фильтров
|
|
||||||
if (childRelFilters.Any())
|
if (childRelFilters.Any())
|
||||||
{
|
{
|
||||||
await ApplyRelationshipFiltersOnDbAsync(
|
await ApplyRelationshipFiltersOnDbAsync(
|
||||||
@@ -374,120 +389,137 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Если фильтры были — оставляем только юниты со связями
|
#if DEBUG
|
||||||
// Если фильтров не было — оставляем все юниты
|
var unitsWithAnyConnections = resultContexts.Values.Count(c => c.ValidParentIds.Any() || c.ValidChildIds.Any());
|
||||||
bool hasRelationshipFilters = parentRelFilters.Any() || childRelFilters.Any();
|
var unitsWithoutConnections = resultContexts.Values.Count(c => !c.ValidParentIds.Any() && !c.ValidChildIds.Any());
|
||||||
|
logger.LogDebug("DEBUG: После ApplyRelationshipFiltersOnDbAsync: {WithConnections} юнитов со связями, {WithoutConnections} без связей",
|
||||||
|
unitsWithAnyConnections, unitsWithoutConnections);
|
||||||
|
|
||||||
var unitsWithRelationships = hasRelationshipFilters
|
var targetContext = resultContexts.Values.FirstOrDefault(c => c.UnitId == targetUnitId);
|
||||||
? resultContexts.Values.Where(c => c.ValidParentIds.Any() || c.ValidChildIds.Any()).ToList()
|
if (targetContext != null)
|
||||||
: resultContexts.Values.ToList();
|
{
|
||||||
|
logger.LogDebug("DEBUG: Юнит {TargetUnitId}: Родителей={ParentCount}, Детей={ChildCount}, PassesFilter={Passes}",
|
||||||
|
targetUnitId,
|
||||||
|
targetContext.ValidParentIds.Count,
|
||||||
|
targetContext.ValidChildIds.Count,
|
||||||
|
targetContext.ValidParentIds.Any() || targetContext.ValidChildIds.Any());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var result = resultContexts.Values.ToList();
|
||||||
|
|
||||||
var result = unitsWithRelationships;
|
|
||||||
logger.LogDebug("ProcessRelationshipFiltersAsync: выход {ContextCount} контекстов (из {InitialCount})",
|
logger.LogDebug("ProcessRelationshipFiltersAsync: выход {ContextCount} контекстов (из {InitialCount})",
|
||||||
result.Count, resultContexts.Count);
|
result.Count, resultContexts.Count);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
// Собираем все UnitId для пакетной загрузки (основные + родители + дети)
|
if (unitIds.Contains(targetUnitId))
|
||||||
var allUnitIds = result.Select(c => c.UnitId)
|
|
||||||
.Concat(result.SelectMany(c => c.ValidParentIds))
|
|
||||||
.Concat(result.SelectMany(c => c.ValidChildIds))
|
|
||||||
.Distinct()
|
|
||||||
.ToList(); // ← Убрали .Take(100)
|
|
||||||
|
|
||||||
// Пакетная загрузка всех юнитов
|
|
||||||
var unitsMap = await unitService.Get().AsNoTracking()
|
|
||||||
.Where(u => allUnitIds.Contains(u.Id))
|
|
||||||
.ToDictionaryAsync(u => u.Id, cancellationToken);
|
|
||||||
|
|
||||||
// Получаем все FieldId из фильтров для отображения значений
|
|
||||||
var parentFieldIds = relationshipFilters.Where(rf => rf.IsParent).Select(rf => rf.FieldId).Distinct().ToList();
|
|
||||||
var childFieldIds = relationshipFilters.Where(rf => !rf.IsParent).Select(rf => rf.FieldId).Distinct().ToList();
|
|
||||||
var allFieldIds = parentFieldIds.Concat(childFieldIds).Distinct().ToList();
|
|
||||||
|
|
||||||
// ПАКЕТНАЯ загрузка значений для ВСЕХ юнитов сразу
|
|
||||||
var allValues = await unitInValueService.GetByUnitIdsAndFieldIdsAsync(allUnitIds, allFieldIds);
|
|
||||||
var valuesByUnit = allValues.GroupBy(v => v.UnitId)
|
|
||||||
.ToDictionary(g => g.Key, g => g.ToList());
|
|
||||||
|
|
||||||
// ПАКЕТНАЯ загрузка имён полей
|
|
||||||
var fieldsMap = await unitFieldService.Get()
|
|
||||||
.AsNoTracking()
|
|
||||||
.Where(f => allFieldIds.Contains(f.Id))
|
|
||||||
.ToDictionaryAsync(f => f.Id, f => f.AihitName, cancellationToken);
|
|
||||||
|
|
||||||
// Логируем только первые 10 юнитов (чтобы не засорять лог)
|
|
||||||
foreach (var context in result.Take(10))
|
|
||||||
{
|
{
|
||||||
var u = unitsMap.GetValueOrDefault(context.UnitId);
|
var targetContextInResult = result.FirstOrDefault(c => c.UnitId == targetUnitId);
|
||||||
|
if (targetContextInResult != null)
|
||||||
if (u == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
logger.LogDebug("Найден ЭК {UnitName} (Id={UnitId})", u.Name, u.Id);
|
|
||||||
|
|
||||||
// === РОДИТЕЛИ ===
|
|
||||||
if (context.ValidParentIds.Any())
|
|
||||||
{
|
{
|
||||||
logger.LogDebug("\tФильтрам соответствуют {ParentsCount} родителей:", context.ValidParentIds.Count);
|
logger.LogDebug("DEBUG: Юнит {TargetUnitId} в результатах ProcessRelationshipFiltersAsync. Родителей: {ParentCount}, Детей: {ChildCount}",
|
||||||
|
targetUnitId, targetContextInResult.ValidParentIds.Count, targetContextInResult.ValidChildIds.Count);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogDebug("DEBUG: Юнит {TargetUnitId} НЕ в результатах ProcessRelationshipFiltersAsync (удалён)", targetUnitId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Логируем только первые 5 родителей (чтобы не засорять лог)
|
if (logger.IsEnabled(LogLevel.Debug))
|
||||||
foreach (var parentId in context.ValidParentIds.Take(5))
|
{
|
||||||
|
var allUnitIds = result.Select(c => c.UnitId)
|
||||||
|
.Concat(result.SelectMany(c => c.ValidParentIds))
|
||||||
|
.Concat(result.SelectMany(c => c.ValidChildIds))
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var unitsMap = await unitService.Get().AsNoTracking()
|
||||||
|
.Where(u => allUnitIds.Contains(u.Id))
|
||||||
|
.ToDictionaryAsync(u => u.Id, cancellationToken);
|
||||||
|
|
||||||
|
var parentFieldIds = relationshipFilters.Where(rf => rf.IsParent).Select(rf => rf.FieldId).Distinct().ToList();
|
||||||
|
var childFieldIds = relationshipFilters.Where(rf => !rf.IsParent).Select(rf => rf.FieldId).Distinct().ToList();
|
||||||
|
var allFieldIds = parentFieldIds.Concat(childFieldIds).Distinct().ToList();
|
||||||
|
|
||||||
|
var allValues = await unitInValueService.GetByUnitIdsAndFieldIdsAsync(allUnitIds, allFieldIds);
|
||||||
|
var valuesByUnit = allValues.GroupBy(v => v.UnitId)
|
||||||
|
.ToDictionary(g => g.Key, g => g.ToList());
|
||||||
|
|
||||||
|
var fieldsMap = await unitFieldService.Get()
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(f => allFieldIds.Contains(f.Id))
|
||||||
|
.ToDictionaryAsync(f => f.Id, f => f.AihitName, cancellationToken);
|
||||||
|
|
||||||
|
foreach (var context in result.Take(DebugMaxUnitsToLog))
|
||||||
|
{
|
||||||
|
var u = unitsMap.GetValueOrDefault(context.UnitId);
|
||||||
|
if (u == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
logger.LogDebug("Найден ЭК {UnitName} (Id={UnitId})", u.Name, u.Id);
|
||||||
|
|
||||||
|
if (context.ValidParentIds.Any())
|
||||||
{
|
{
|
||||||
var p = unitsMap.GetValueOrDefault(parentId);
|
logger.LogDebug("\tФильтрам соответствуют {ParentsCount} родителей:", context.ValidParentIds.Count);
|
||||||
logger.LogDebug("\t\t{ParentName} (Id={ParentId})", p?.Name ?? "null", parentId);
|
|
||||||
|
|
||||||
if (parentFieldIds.Any() && valuesByUnit.TryGetValue(parentId, out var parentValues))
|
foreach (var parentId in context.ValidParentIds.Take(DebugMaxRelationsToLog))
|
||||||
{
|
{
|
||||||
foreach (var pv in parentValues.Where(v => parentFieldIds.Contains(v.FieldId)))
|
var p = unitsMap.GetValueOrDefault(parentId);
|
||||||
|
logger.LogDebug("\t\t{ParentName} (Id={ParentId})", p?.Name ?? "null", parentId);
|
||||||
|
|
||||||
|
if (parentFieldIds.Any() && valuesByUnit.TryGetValue(parentId, out var parentValues))
|
||||||
{
|
{
|
||||||
var fieldName = fieldsMap.GetValueOrDefault(pv.FieldId) ?? $"FieldId={pv.FieldId}";
|
foreach (var pv in parentValues.Where(v => parentFieldIds.Contains(v.FieldId)))
|
||||||
logger.LogDebug("\t\t {FieldName} = {FieldValue}",
|
{
|
||||||
fieldName,
|
var fieldName = fieldsMap.GetValueOrDefault(pv.FieldId) ?? $"FieldId={pv.FieldId}";
|
||||||
pv.Value?.Value ?? "null");
|
logger.LogDebug("\t\t {FieldName} = {FieldValue}",
|
||||||
|
fieldName,
|
||||||
|
pv.Value?.Value ?? "null");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (context.ValidParentIds.Count > 5)
|
if (context.ValidParentIds.Count > DebugMaxRelationsToLog)
|
||||||
{
|
|
||||||
logger.LogDebug("\t\t... и ещё {Count} родителей", context.ValidParentIds.Count - 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (parentRelFilters.Any())
|
|
||||||
{
|
|
||||||
logger.LogDebug("\tРодительские фильтры заданы, но подходящих родителей не найдено");
|
|
||||||
}
|
|
||||||
|
|
||||||
// === ДЕТИ ===
|
|
||||||
if (context.ValidChildIds.Any())
|
|
||||||
{
|
|
||||||
logger.LogDebug("\tФильтрам соответствуют {ChildrenCount} детей:", context.ValidChildIds.Count);
|
|
||||||
|
|
||||||
foreach (var childId in context.ValidChildIds.Take(5))
|
|
||||||
{
|
|
||||||
var c = unitsMap.GetValueOrDefault(childId);
|
|
||||||
logger.LogDebug("\t\t{ChildName} (Id={ChildId})", c?.Name ?? "null", childId);
|
|
||||||
|
|
||||||
if (childFieldIds.Any() && valuesByUnit.TryGetValue(childId, out var childValues))
|
|
||||||
{
|
{
|
||||||
foreach (var cv in childValues.Where(v => childFieldIds.Contains(v.FieldId)))
|
logger.LogDebug("\t\t... и ещё {Count} родителей", context.ValidParentIds.Count - DebugMaxRelationsToLog);
|
||||||
{
|
|
||||||
var fieldName = fieldsMap.GetValueOrDefault(cv.FieldId) ?? $"FieldId={cv.FieldId}";
|
|
||||||
logger.LogDebug("\t\t {FieldName} = {FieldValue}",
|
|
||||||
fieldName,
|
|
||||||
cv.Value?.Value ?? "null");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (parentRelFilters.Any())
|
||||||
if (context.ValidChildIds.Count > 5)
|
|
||||||
{
|
{
|
||||||
logger.LogDebug("\t\t... и ещё {Count} детей", context.ValidChildIds.Count - 5);
|
logger.LogDebug("\tРодительские фильтры заданы, но подходящих родителей не найдено");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.ValidChildIds.Any())
|
||||||
|
{
|
||||||
|
logger.LogDebug("\tФильтрам соответствуют {ChildrenCount} детей:", context.ValidChildIds.Count);
|
||||||
|
|
||||||
|
foreach (var childId in context.ValidChildIds.Take(DebugMaxRelationsToLog))
|
||||||
|
{
|
||||||
|
var c = unitsMap.GetValueOrDefault(childId);
|
||||||
|
logger.LogDebug("\t\t{ChildName} (Id={ChildId})", c?.Name ?? "null", childId);
|
||||||
|
|
||||||
|
if (childFieldIds.Any() && valuesByUnit.TryGetValue(childId, out var childValues))
|
||||||
|
{
|
||||||
|
foreach (var cv in childValues.Where(v => childFieldIds.Contains(v.FieldId)))
|
||||||
|
{
|
||||||
|
var fieldName = fieldsMap.GetValueOrDefault(cv.FieldId) ?? $"FieldId={cv.FieldId}";
|
||||||
|
logger.LogDebug("\t\t {FieldName} = {FieldValue}",
|
||||||
|
fieldName,
|
||||||
|
cv.Value?.Value ?? "null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.ValidChildIds.Count > DebugMaxRelationsToLog)
|
||||||
|
{
|
||||||
|
logger.LogDebug("\t\t... и ещё {Count} детей", context.ValidChildIds.Count - DebugMaxRelationsToLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (childRelFilters.Any())
|
||||||
|
{
|
||||||
|
logger.LogDebug("\tДочерние фильтры заданы, но подходящих детей не найдено");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (childRelFilters.Any())
|
|
||||||
{
|
|
||||||
logger.LogDebug("\tДочерние фильтры заданы, но подходящих детей не найдено");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -752,7 +784,6 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
#region вспомогательные методы
|
#region вспомогательные методы
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Применяет фильтры к связям (родителям или детям)
|
/// Применяет фильтры к связям (родителям или детям)
|
||||||
/// Связь должна пройти ВСЕ фильтры направления
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task ApplyRelationshipFiltersOnDbAsync(
|
private async Task ApplyRelationshipFiltersOnDbAsync(
|
||||||
List<Guid> unitIds,
|
List<Guid> unitIds,
|
||||||
@@ -796,17 +827,7 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
if (string.IsNullOrWhiteSpace(valueMask))
|
if (string.IsNullOrWhiteSpace(valueMask))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool isStartsWith = valueMask.EndsWith("%") && !valueMask.EndsWith("%%");
|
string dbValueMask = NormalizeLikeMask(valueMask);
|
||||||
bool isEndsWith = valueMask.StartsWith("%") && !valueMask.StartsWith("%%");
|
|
||||||
string dbValueMask;
|
|
||||||
if (isStartsWith && isEndsWith)
|
|
||||||
dbValueMask = $"%{valueMask.Trim('%')}%";
|
|
||||||
else if (isStartsWith)
|
|
||||||
dbValueMask = $"{valueMask.TrimEnd('%')}%";
|
|
||||||
else if (isEndsWith)
|
|
||||||
dbValueMask = $"%{valueMask.TrimStart('%')}";
|
|
||||||
else
|
|
||||||
dbValueMask = valueMask;
|
|
||||||
|
|
||||||
var fieldName = relFilter.UnitField?.AihitName ?? $"FieldId={relFilter.FieldId}";
|
var fieldName = relFilter.UnitField?.AihitName ?? $"FieldId={relFilter.FieldId}";
|
||||||
logger.LogDebug(" RelationshipFilter ({Direction}): Поле='{FieldName}', Маска='{Mask}', IsInverse={IsInverse}, IsFullMatch={IsFullMatch}",
|
logger.LogDebug(" RelationshipFilter ({Direction}): Поле='{FieldName}', Маска='{Mask}', IsInverse={IsInverse}, IsFullMatch={IsFullMatch}",
|
||||||
@@ -938,6 +959,7 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private async Task<List<Guid>> GetUnitIdsFromCacheOrDbAsync(JobUnitFilter filter, CancellationToken cancellationToken = default)
|
private async Task<List<Guid>> GetUnitIdsFromCacheOrDbAsync(JobUnitFilter filter, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var cacheKey = cacheService.GetKey(new[] { "uf_ids", filter.UnitFilter }, isUseHash: true);
|
var cacheKey = cacheService.GetKey(new[] { "uf_ids", filter.UnitFilter }, isUseHash: true);
|
||||||
@@ -948,8 +970,10 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
return cachedData.Data.UnitIds;
|
return cachedData.Data.UnitIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dbValueMask = NormalizeLikeMask(filter.UnitFilter);
|
||||||
|
|
||||||
var initialUnitIds = await unitService.Get().AsNoTracking()
|
var initialUnitIds = await unitService.Get().AsNoTracking()
|
||||||
.Where(unit => EF.Functions.ILike(unit.Name, filter.UnitFilter))
|
.Where(unit => EF.Functions.ILike(unit.Name, dbValueMask))
|
||||||
.Select(u => u.Id)
|
.Select(u => u.Id)
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
@@ -965,5 +989,29 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
return initialUnitIds;
|
return initialUnitIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Обрабатывает маску LIKE для корректной работы с SQL
|
||||||
|
/// </summary>
|
||||||
|
private static string NormalizeLikeMask(string valueMask)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(valueMask))
|
||||||
|
return valueMask;
|
||||||
|
|
||||||
|
valueMask = valueMask.Trim();
|
||||||
|
bool isStartsWith = valueMask.EndsWith("%") && !valueMask.EndsWith("%%");
|
||||||
|
bool isEndsWith = valueMask.StartsWith("%") && !valueMask.StartsWith("%%");
|
||||||
|
|
||||||
|
if (isStartsWith && isEndsWith)
|
||||||
|
return $"%{valueMask.Trim('%')}%";
|
||||||
|
else if (isStartsWith)
|
||||||
|
return $"{valueMask.TrimEnd('%')}%";
|
||||||
|
else if (isEndsWith)
|
||||||
|
return $"%{valueMask.TrimStart('%')}";
|
||||||
|
else
|
||||||
|
return valueMask;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -53,6 +53,11 @@ namespace PARR.DAL.Services.Implementations
|
|||||||
// ставить статус Updating можно только если текущий статус == Ok
|
// ставить статус Updating можно только если текущий статус == Ok
|
||||||
if (configuration.TaskStatusCode != (int)TaskStatusEnum.Ok)
|
if (configuration.TaskStatusCode != (int)TaskStatusEnum.Ok)
|
||||||
{
|
{
|
||||||
|
int taskStatusValue = configuration.TaskStatusCode;
|
||||||
|
string taskStatusName = Enum.IsDefined(typeof(TaskStatusEnum), taskStatusValue)
|
||||||
|
? ((TaskStatusEnum)taskStatusValue).ToString()
|
||||||
|
: $"Unknown ({taskStatusValue})";
|
||||||
|
|
||||||
logger.LogInformation("Нельзя установить статус {newStatus} для конфигурации {configurationId}, templateId: {templateId}, так как текущий статус {currentStatus}",
|
logger.LogInformation("Нельзя установить статус {newStatus} для конфигурации {configurationId}, templateId: {templateId}, так как текущий статус {currentStatus}",
|
||||||
updatingStatus, configuration.Id, configuration.TemplateId, configuration.TaskStatusCode);
|
updatingStatus, configuration.Id, configuration.TemplateId, configuration.TaskStatusCode);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user