2025-12-09 16:50:35 +10:00
using Microsoft.EntityFrameworkCore ;
using Microsoft.Extensions.Logging ;
2026-04-30 10:35:31 +10:00
using PARR.Core.Repositories.Interfaces.Unit ;
2025-12-09 16:50:35 +10:00
using PARR.DAL.Context ;
2026-04-30 10:35:31 +10:00
using PARR.Domain.Entities.Unit ;
2025-12-09 16:50:35 +10:00
2026-04-30 10:35:31 +10:00
namespace PARR.DAL.Repositories.Unit
2025-12-09 16:50:35 +10:00
{
2026-04-30 10:35:31 +10:00
internal class UnitInValueRepository : IUnitInValueRepository
2025-12-09 16:50:35 +10:00
{
2026-04-30 10:35:31 +10:00
private readonly ILogger < UnitInValueRepository > logger ;
2025-12-09 16:50:35 +10:00
private readonly DataContext dataContext ;
2026-04-30 10:35:31 +10:00
public UnitInValueRepository (
ILogger < UnitInValueRepository > logger ,
2025-12-09 16:50:35 +10:00
DataContext dataContext
)
{
this . logger = logger ;
this . dataContext = dataContext ;
}
2026-05-14 16:31:03 +10:00
public async Task < List < UnitInValue > > GetByUnitIdAsync ( Guid unitId , CancellationToken ct = default )
2025-12-09 16:50:35 +10:00
{
2025-12-09 17:53:54 +10:00
return await dataContext . UnitInValues . AsNoTracking ( )
. Include ( t = > t . Value )
2025-12-09 16:50:35 +10:00
. Where ( uv = > uv . UnitId = = unitId )
2026-05-14 16:31:03 +10:00
. ToListAsync ( ct ) ;
2025-12-09 16:50:35 +10:00
}
2026-05-14 16:31:03 +10:00
public async Task < List < UnitInValue > > GetByUnitIdsAsync ( IEnumerable < Guid > unitIds , CancellationToken ct = default )
2025-12-09 16:50:35 +10:00
{
2025-12-09 17:53:54 +10:00
return await dataContext . UnitInValues . AsNoTracking ( )
2025-12-10 11:55:58 +10:00
. Include ( t = > t . Value )
2025-12-09 16:50:35 +10:00
. Where ( uv = > unitIds . Contains ( uv . UnitId ) )
2026-05-14 16:31:03 +10:00
. ToListAsync ( ct ) ;
2025-12-09 16:50:35 +10:00
}
2025-12-10 11:55:58 +10:00
2025-12-10 14:12:38 +10:00
public async Task < List < ( string FieldName , string? Value ) > > GetFieldValuesAsync (
Guid unitId ,
2026-05-14 16:31:03 +10:00
IReadOnlyCollection < string > aihitNames
, CancellationToken ct = default )
2025-12-10 11:55:58 +10:00
{
if ( aihitNames = = null | | aihitNames . Count = = 0 )
2025-12-10 14:12:38 +10:00
return new List < ( string , string? ) > ( ) ;
2025-12-10 11:55:58 +10:00
2025-12-10 14:12:38 +10:00
var keyValuePairs = await dataContext . UnitInValues
2025-12-10 11:55:58 +10:00
. AsNoTracking ( )
. AsSplitQuery ( )
. Where ( uiv = > uiv . UnitId = = unitId
& & uiv . Field ! = null
& & uiv . Value ! = null
& & aihitNames . Contains ( uiv . Field . AihitName . ToUpper ( ) ) )
2025-12-10 14:12:38 +10:00
. Select ( uiv = > new { Key = uiv . Field ! . AihitName . ToUpper ( ) , Value = uiv . Value ! . Value } )
2026-05-14 16:31:03 +10:00
. ToListAsync ( ct ) ;
2025-12-10 11:55:58 +10:00
// Журналируем если не нашли поля
2025-12-10 14:12:38 +10:00
var foundFieldNames = keyValuePairs . Select ( kvp = > kvp . Key ) . ToHashSet ( StringComparer . OrdinalIgnoreCase ) ;
2025-12-10 11:55:58 +10:00
var missing = aihitNames
2025-12-10 14:12:38 +10:00
. Where ( name = > ! foundFieldNames . Contains ( name . ToUpper ( ) ) )
2025-12-10 11:55:58 +10:00
. ToList ( ) ;
if ( missing . Any ( ) )
{
logger . LogDebug ( "UnitInValueService: поля не найдены для unitId={UnitId}: {Fields}" ,
unitId , string . Join ( ", " , missing ) ) ;
}
2025-12-10 14:12:38 +10:00
return keyValuePairs . Select ( kvp = > ( kvp . Key , kvp . Value ) ) . ToList ( ) ;
2025-12-10 11:55:58 +10:00
}
2025-12-15 11:50:12 +10:00
2026-05-14 16:31:03 +10:00
public async Task < List < UnitInValue > > GetByUnitIdsAndFieldIdsAsync ( IEnumerable < Guid > unitIds , IEnumerable < Guid > fieldIds , CancellationToken ct = default )
2025-12-15 11:50:12 +10:00
{
var unitIdSet = unitIds . ToHashSet ( ) ;
var fieldIdSet = fieldIds . ToHashSet ( ) ;
return await dataContext . UnitInValues
. AsNoTracking ( )
2025-12-23 18:27:31 +10:00
. Include ( uv = > uv . Value )
2025-12-15 11:50:12 +10:00
. Where ( uv = > unitIdSet . Contains ( uv . UnitId ) & & fieldIdSet . Contains ( uv . FieldId ) )
2026-05-14 16:31:03 +10:00
. ToListAsync ( ct ) ;
2025-12-15 11:50:12 +10:00
}
2025-12-19 19:15:58 +10:00
public IQueryable < UnitInValue > Get ( )
{
return dataContext . UnitInValues ;
}
2025-12-23 18:27:31 +10:00
2026-05-14 16:31:03 +10:00
public async Task < string? > GetMostFrequentValueForFieldAsync ( List < Guid > unitIds , string fieldName , CancellationToken ct )
2025-12-23 18:27:31 +10:00
{
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 )
2026-05-14 16:31:03 +10:00
. FirstOrDefaultAsync ( ct ) ;
2025-12-23 18:27:31 +10:00
var mostFrequentValue = result ? . Value ;
logger . LogDebug ( "Наиболее частое значение для поля '{FieldName}': {Value}" , fieldName , mostFrequentValue ) ;
return mostFrequentValue ;
}
2026-05-04 11:55:07 +10:00
public IQueryable < Guid > GetMatchingTargetIds ( Guid fieldId , string valueMask )
{
return Get ( )
. AsNoTracking ( )
. Where ( uiv = > uiv . FieldId = = fieldId )
. Where ( uiv = > EF . Functions . ILike ( uiv . Value . Value , valueMask ) )
. Select ( uiv = > uiv . UnitId )
. Distinct ( ) ;
}
2025-12-09 16:50:35 +10:00
}
}