Files
parr_api/PARR.DAL/Services/Implementations/Unit/UnitInValueService.cs

133 lines
5.1 KiB
C#

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<UnitInValueService> logger;
private readonly DataContext dataContext;
public UnitInValueService(
ILogger<UnitInValueService> logger,
DataContext dataContext
)
{
this.logger = logger;
this.dataContext = dataContext;
}
public async Task<List<UnitInValue>> GetByUnitIdAsync(Guid unitId)
{
return await dataContext.UnitInValues.AsNoTracking()
.Include(t => t.Value)
.Where(uv => uv.UnitId == unitId)
.ToListAsync();
}
public async Task<List<UnitInValue>> GetByUnitIdsAsync(IEnumerable<Guid> unitIds)
{
return await dataContext.UnitInValues.AsNoTracking()
.Include(t => t.Value)
.Where(uv => unitIds.Contains(uv.UnitId))
.ToListAsync();
}
public async Task<List<(string FieldName, string? Value)>> GetFieldValuesAsync(
Guid unitId,
IReadOnlyCollection<string> 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<List<UnitInValue>> GetByUnitIdsAndFieldIdsAsync(IEnumerable<Guid> unitIds, IEnumerable<Guid> 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<UnitInValue> Get()
{
return dataContext.UnitInValues;
}
public async Task<string?> GetMostFrequentValueForFieldAsync(List<Guid> 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;
}
}
}