From 03683a13d3d592d2de2b587950565774d57d86e7 Mon Sep 17 00:00:00 2001 From: Mikhail Kuznetsov Date: Wed, 10 Dec 2025 14:12:38 +1000 Subject: [PATCH] =?UTF-8?q?fix(dal):=20ShortcodeService=20=D1=82=D0=B5?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D1=8C=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0?= =?UTF-8?q?=D1=89=D0=B0=D0=B5=D1=82=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BC=D1=83=D0=BB=D1=8C=D1=82=D0=B8=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D0=B5=D0=B9=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BF=D1=8F=D1=82=D1=83=D1=8E,=20NULL=20=D0=BA=D0=B0?= =?UTF-8?q?=D0=BA=20"null".=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BE=D1=82=D1=81=D1=83=D1=82=D1=81=D1=82=D0=B2?= =?UTF-8?q?=D1=83=D1=8E=D1=89=D0=B8=D0=B5=20=D0=BD=D0=B0=D0=B2=D0=B8=D0=B3?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implementations/ShortcodesService.cs | 29 ++++++++++++++----- .../Unit/UnitInValueService.cs | 19 ++++++------ .../Interfaces/Unit/IUnitInValueService.cs | 2 +- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/PARR.DAL/DomainServices/Implementations/ShortcodesService.cs b/PARR.DAL/DomainServices/Implementations/ShortcodesService.cs index 27b5dd23..99b33c1c 100644 --- a/PARR.DAL/DomainServices/Implementations/ShortcodesService.cs +++ b/PARR.DAL/DomainServices/Implementations/ShortcodesService.cs @@ -218,23 +218,36 @@ namespace PARR.DAL.DomainServices.Implementations private async Task ReplaceFieldValues(Guid unitId, string resultName, List shortcodesInMask) { - // 1. Извлекаем имена полей из шорткодов: %IP_АДРЕС% → "IP_АДРЕС" + // 1. Извлекаем имена полей из шорткодов var requiredFieldNames = shortcodesInMask - .Select(m => m.Value.Trim('%').ToUpper()) + .Select(m => m.Value.Trim('%').ToUpperInvariant()) .ToList(); if (requiredFieldNames.Count == 0) return resultName; - // 2. Получаем только нужные значения - var fieldValueMap = await unitInValueService.GetFieldValuesAsync(unitId, requiredFieldNames); + // 2. Получаем значения (может быть дубль) + 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) { - var fieldName = match.Value.Trim('%').ToUpper(); - if (fieldValueMap.TryGetValue(fieldName, out var fieldValue)) - resultName = resultName.Replace(match.Value, fieldValue); + var fieldName = match.Value.Trim('%').ToUpperInvariant(); + + 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 { logger.LogWarning("Поле '{FieldName}' не найдено для unitId={UnitId} при подстановке шорткода '{Shortcode}'", diff --git a/PARR.DAL/Services/Implementations/Unit/UnitInValueService.cs b/PARR.DAL/Services/Implementations/Unit/UnitInValueService.cs index aa818669..fb167c7f 100644 --- a/PARR.DAL/Services/Implementations/Unit/UnitInValueService.cs +++ b/PARR.DAL/Services/Implementations/Unit/UnitInValueService.cs @@ -37,26 +37,27 @@ namespace PARR.DAL.Services.Implementations.Unit } - public async Task> GetFieldValuesAsync(Guid unitId, IReadOnlyCollection aihitNames) + public async Task> GetFieldValuesAsync( + Guid unitId, + IReadOnlyCollection aihitNames) { if (aihitNames == null || aihitNames.Count == 0) - return new Dictionary(StringComparer.OrdinalIgnoreCase); + return new List<(string, string?)>(); - var result = await dataContext.UnitInValues + var keyValuePairs = await dataContext.UnitInValues .AsNoTracking() .AsSplitQuery() .Where(uiv => uiv.UnitId == unitId && uiv.Field != null && uiv.Value != null && aihitNames.Contains(uiv.Field.AihitName.ToUpper())) - .ToDictionaryAsync( - uiv => uiv.Field!.AihitName.ToUpper(), - uiv => uiv.Value!.Value ?? "", - StringComparer.OrdinalIgnoreCase); + .Select(uiv => new { Key = uiv.Field!.AihitName.ToUpper(), Value = uiv.Value!.Value }) + .ToListAsync(); // Журналируем если не нашли поля + var foundFieldNames = keyValuePairs.Select(kvp => kvp.Key).ToHashSet(StringComparer.OrdinalIgnoreCase); var missing = aihitNames - .Where(name => !result.ContainsKey(name.ToUpper())) + .Where(name => !foundFieldNames.Contains(name.ToUpper())) .ToList(); if (missing.Any()) { @@ -64,7 +65,7 @@ namespace PARR.DAL.Services.Implementations.Unit unitId, string.Join(", ", missing)); } - return result; + return keyValuePairs.Select(kvp => (kvp.Key, kvp.Value)).ToList(); } } } diff --git a/PARR.DAL/Services/Interfaces/Unit/IUnitInValueService.cs b/PARR.DAL/Services/Interfaces/Unit/IUnitInValueService.cs index ff33d3ee..038308cf 100644 --- a/PARR.DAL/Services/Interfaces/Unit/IUnitInValueService.cs +++ b/PARR.DAL/Services/Interfaces/Unit/IUnitInValueService.cs @@ -6,6 +6,6 @@ namespace PARR.DAL.Services.Interfaces.Unit { Task> GetByUnitIdsAsync(IEnumerable unitIds); Task> GetByUnitIdAsync(Guid unitId); - Task> GetFieldValuesAsync(Guid unitId, IReadOnlyCollection aihitNames); + Task> GetFieldValuesAsync(Guid unitId, IReadOnlyCollection aihitNames); } }