using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using PARR.DAL.Context; using PARR.DAL.Models.Unit; using PARR.DAL.Services.Interfaces.Unit; namespace PARR.DAL.Services.Implementations.Unit { internal class UnitInValueService : IUnitInValueService { private readonly ILogger logger; private readonly DataContext dataContext; public UnitInValueService( ILogger logger, DataContext dataContext ) { this.logger = logger; this.dataContext = dataContext; } public async Task> GetByUnitIdAsync(Guid unitId) { return await dataContext.UnitInValues.AsNoTracking() .Include(t => t.Value) .Where(uv => uv.UnitId == unitId) .ToListAsync(); } public async Task> GetByUnitIdsAsync(IEnumerable unitIds) { return await dataContext.UnitInValues.AsNoTracking() .Include(t => t.Value) .Where(uv => unitIds.Contains(uv.UnitId)) .ToListAsync(); } public async Task> GetFieldValuesAsync( Guid unitId, IReadOnlyCollection aihitNames) { if (aihitNames == null || aihitNames.Count == 0) return new List<(string, string?)>(); var keyValuePairs = await dataContext.UnitInValues .AsNoTracking() .AsSplitQuery() .Where(uiv => uiv.UnitId == unitId && uiv.Field != null && uiv.Value != null && aihitNames.Contains(uiv.Field.AihitName.ToUpper())) .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 => !foundFieldNames.Contains(name.ToUpper())) .ToList(); if (missing.Any()) { logger.LogDebug("UnitInValueService: поля не найдены для unitId={UnitId}: {Fields}", unitId, string.Join(", ", missing)); } return keyValuePairs.Select(kvp => (kvp.Key, kvp.Value)).ToList(); } public async Task> GetByUnitIdsAndFieldIdsAsync(IEnumerable unitIds, IEnumerable fieldIds) { var unitIdSet = unitIds.ToHashSet(); var fieldIdSet = fieldIds.ToHashSet(); return await dataContext.UnitInValues .AsNoTracking() .Include(uv => uv.Value) .Where(uv => unitIdSet.Contains(uv.UnitId) && fieldIdSet.Contains(uv.FieldId)) .ToListAsync(); } public IQueryable Get() { return dataContext.UnitInValues; } public async Task GetMostFrequentValueForFieldAsync(List unitIds, string fieldName) { if (unitIds == null || !unitIds.Any() || string.IsNullOrWhiteSpace(fieldName)) { logger.LogDebug("GetMostFrequentValueForFieldAsync: пустой список юнитов или имя поля. unitIds count: {Count}, fieldName: {FieldName}", unitIds?.Count ?? 0, fieldName); return null; } logger.LogDebug("Поиск наиболее частого значения для поля '{FieldName}' среди {Count} юнитов.", fieldName, unitIds.Count); var result = await dataContext.UnitInValues .AsNoTracking() .Where(uv => unitIds.Contains(uv.UnitId) ) .Join( dataContext.UnitFields, uv => uv.FieldId, f => f.Id, (uv, f) => new { uv, f } ) .Where(x => EF.Functions.ILike(x.f.AihitName, fieldName) ) .Join( dataContext.UnitFieldValues, x => x.uv.ValueId, v => v.Id, (x, v) => new { x.uv.UnitId, v.Value } ) .Where(x => !string.IsNullOrWhiteSpace(x.Value)) .GroupBy(x => x.Value) .Select(g => new { Value = g.Key, Count = g.Count() }) .OrderByDescending(x => x.Count) .ThenBy(x => x.Value) .FirstOrDefaultAsync(); var mostFrequentValue = result?.Value; logger.LogDebug("Наиболее частое значение для поля '{FieldName}': {Value}", fieldName, mostFrequentValue); return mostFrequentValue; } } }