fix(dal): ShortcodeService теперь возвращает значения мультиполей через запятую, NULL как "null". Добавлены отсутствующие навигационные данные

This commit is contained in:
Mikhail Kuznetsov
2025-12-10 14:12:38 +10:00
parent 3a136f5bf4
commit 03683a13d3
3 changed files with 32 additions and 18 deletions

View File

@@ -218,23 +218,36 @@ namespace PARR.DAL.DomainServices.Implementations
private async Task<string> ReplaceFieldValues(Guid unitId, string resultName, List<Match> shortcodesInMask) private async Task<string> ReplaceFieldValues(Guid unitId, string resultName, List<Match> shortcodesInMask)
{ {
// 1. Извлекаем имена полей из шорткодов: %IP_АДРЕС% → "IP_АДРЕС" // 1. Извлекаем имена полей из шорткодов
var requiredFieldNames = shortcodesInMask var requiredFieldNames = shortcodesInMask
.Select(m => m.Value.Trim('%').ToUpper()) .Select(m => m.Value.Trim('%').ToUpperInvariant())
.ToList(); .ToList();
if (requiredFieldNames.Count == 0) if (requiredFieldNames.Count == 0)
return resultName; return resultName;
// 2. Получаем только нужные значения // 2. Получаем значения (может быть дубль)
var fieldValueMap = await unitInValueService.GetFieldValuesAsync(unitId, requiredFieldNames); var fieldValues = await unitInValueService.GetFieldValuesAsync(unitId, requiredFieldNames);
// 3. Подставляем значения // 3. Группируем по FieldName → список значений
var fieldValuesMap = fieldValues
.GroupBy(x => x.FieldName, StringComparer.OrdinalIgnoreCase)
.ToDictionary(
g => g.Key,
g => g.Select(x => x.Value).ToList(), // список значений (может быть null)
StringComparer.OrdinalIgnoreCase);
// 4. Объединяем значения через запятую (null → "null") и подставляем
foreach (var match in shortcodesInMask) foreach (var match in shortcodesInMask)
{ {
var fieldName = match.Value.Trim('%').ToUpper(); var fieldName = match.Value.Trim('%').ToUpperInvariant();
if (fieldValueMap.TryGetValue(fieldName, out var fieldValue))
resultName = resultName.Replace(match.Value, fieldValue); if (fieldValuesMap.TryGetValue(fieldName, out var values))
{
// Объединяем все значения через запятую, null заменяем на строку "null"
var combinedValue = string.Join(", ", values.Select(v => v ?? "null"));
resultName = resultName.Replace(match.Value, combinedValue);
}
else else
{ {
logger.LogWarning("Поле '{FieldName}' не найдено для unitId={UnitId} при подстановке шорткода '{Shortcode}'", logger.LogWarning("Поле '{FieldName}' не найдено для unitId={UnitId} при подстановке шорткода '{Shortcode}'",

View File

@@ -37,26 +37,27 @@ namespace PARR.DAL.Services.Implementations.Unit
} }
public async Task<Dictionary<string, string>> GetFieldValuesAsync(Guid unitId, IReadOnlyCollection<string> aihitNames) public async Task<List<(string FieldName, string? Value)>> GetFieldValuesAsync(
Guid unitId,
IReadOnlyCollection<string> aihitNames)
{ {
if (aihitNames == null || aihitNames.Count == 0) if (aihitNames == null || aihitNames.Count == 0)
return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); return new List<(string, string?)>();
var result = await dataContext.UnitInValues var keyValuePairs = await dataContext.UnitInValues
.AsNoTracking() .AsNoTracking()
.AsSplitQuery() .AsSplitQuery()
.Where(uiv => uiv.UnitId == unitId .Where(uiv => uiv.UnitId == unitId
&& uiv.Field != null && uiv.Field != null
&& uiv.Value != null && uiv.Value != null
&& aihitNames.Contains(uiv.Field.AihitName.ToUpper())) && aihitNames.Contains(uiv.Field.AihitName.ToUpper()))
.ToDictionaryAsync( .Select(uiv => new { Key = uiv.Field!.AihitName.ToUpper(), Value = uiv.Value!.Value })
uiv => uiv.Field!.AihitName.ToUpper(), .ToListAsync();
uiv => uiv.Value!.Value ?? "",
StringComparer.OrdinalIgnoreCase);
// Журналируем если не нашли поля // Журналируем если не нашли поля
var foundFieldNames = keyValuePairs.Select(kvp => kvp.Key).ToHashSet(StringComparer.OrdinalIgnoreCase);
var missing = aihitNames var missing = aihitNames
.Where(name => !result.ContainsKey(name.ToUpper())) .Where(name => !foundFieldNames.Contains(name.ToUpper()))
.ToList(); .ToList();
if (missing.Any()) if (missing.Any())
{ {
@@ -64,7 +65,7 @@ namespace PARR.DAL.Services.Implementations.Unit
unitId, string.Join(", ", missing)); unitId, string.Join(", ", missing));
} }
return result; return keyValuePairs.Select(kvp => (kvp.Key, kvp.Value)).ToList();
} }
} }
} }

View File

@@ -6,6 +6,6 @@ namespace PARR.DAL.Services.Interfaces.Unit
{ {
Task<List<UnitInValue>> GetByUnitIdsAsync(IEnumerable<Guid> unitIds); Task<List<UnitInValue>> GetByUnitIdsAsync(IEnumerable<Guid> unitIds);
Task<List<UnitInValue>> GetByUnitIdAsync(Guid unitId); Task<List<UnitInValue>> GetByUnitIdAsync(Guid unitId);
Task<Dictionary<string, string>> GetFieldValuesAsync(Guid unitId, IReadOnlyCollection<string> aihitNames); Task<List<(string FieldName, string? Value)>> GetFieldValuesAsync(Guid unitId, IReadOnlyCollection<string> aihitNames);
} }
} }