2021-08-24 10:59:10 +05:00
using AsbCloudApp.Data ;
2023-02-15 17:02:43 +05:00
using AsbCloudApp.Repositories ;
2022-12-21 18:02:22 +05:00
using AsbCloudApp.Requests ;
2021-08-13 17:25:06 +05:00
using AsbCloudApp.Services ;
2022-12-21 18:02:22 +05:00
using AsbCloudDb ;
2021-08-13 17:25:06 +05:00
using AsbCloudDb.Model ;
using Mapster ;
2021-08-24 10:59:10 +05:00
using Microsoft.EntityFrameworkCore ;
2022-11-18 15:17:04 +05:00
using Microsoft.Extensions.Caching.Memory ;
2021-08-18 16:57:20 +05:00
using System ;
2021-08-24 10:59:10 +05:00
using System.Collections.Generic ;
2024-01-25 10:35:16 +05:00
using System.ComponentModel.DataAnnotations ;
2024-02-19 11:42:59 +05:00
using System.Diagnostics ;
2021-08-24 10:59:10 +05:00
using System.Linq ;
2022-12-28 17:38:53 +05:00
using System.Threading ;
2023-02-15 17:02:43 +05:00
using System.Threading.Tasks ;
2021-08-13 17:25:06 +05:00
2023-10-06 15:19:02 +05:00
namespace AsbCloudInfrastructure.Repository ;
/// <summary>
/// репозиторий операций по скважине
/// </summary>
public class WellOperationRepository : IWellOperationRepository
2021-08-13 17:25:06 +05:00
{
2023-10-06 15:19:02 +05:00
private const string KeyCacheSections = "OperationsBySectionSummarties" ;
2024-01-24 11:18:58 +05:00
private const int Gap = 90 ;
2023-10-06 15:19:02 +05:00
private readonly IAsbCloudDbContext db ;
private readonly IMemoryCache memoryCache ;
private readonly IWellService wellService ;
2024-02-08 11:38:25 +05:00
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository ;
2023-04-18 16:22:53 +05:00
2024-02-08 11:38:25 +05:00
public WellOperationRepository ( IAsbCloudDbContext db , IMemoryCache memoryCache , IWellService wellService , IWellOperationCategoryRepository wellOperationCategoryRepository )
2023-10-06 15:19:02 +05:00
{
this . db = db ;
this . memoryCache = memoryCache ;
this . wellService = wellService ;
2024-02-08 11:38:25 +05:00
this . wellOperationCategoryRepository = wellOperationCategoryRepository ;
2023-10-06 15:19:02 +05:00
}
/// <inheritdoc/>
public IEnumerable < WellOperationCategoryDto > GetCategories ( bool includeParents )
2021-08-13 17:25:06 +05:00
{
2024-02-08 11:38:25 +05:00
return wellOperationCategoryRepository . Get ( includeParents ) ;
2023-10-06 15:19:02 +05:00
}
/// <inheritdoc/>
public IEnumerable < WellSectionTypeDto > GetSectionTypes ( ) = >
memoryCache
. GetOrCreateBasic ( db . Set < WellSectionType > ( ) )
. OrderBy ( s = > s . Order )
. Select ( s = > s . Adapt < WellSectionTypeDto > ( ) ) ;
2023-02-15 18:02:36 +05:00
2023-10-06 15:19:02 +05:00
public async Task < WellOperationPlanDto > GetOperationsPlanAsync ( int idWell , DateTime ? currentDate , CancellationToken token )
{
var timezone = wellService . GetTimezone ( idWell ) ;
var request = new WellOperationRequest ( )
{
IdWell = idWell ,
OperationType = WellOperation . IdOperationTypePlan ,
} ;
2022-12-09 18:32:18 +05:00
2023-10-06 15:19:02 +05:00
var entities = await BuildQuery ( request )
. AsNoTracking ( )
. ToArrayAsync ( token )
. ConfigureAwait ( false ) ;
2022-12-09 18:32:18 +05:00
2023-10-06 15:19:02 +05:00
var dateLastAssosiatedPlanOperation = await GetDateLastAssosiatedPlanOperationAsync ( idWell , currentDate , timezone . Hours , token ) ;
2021-08-13 17:25:06 +05:00
2023-10-06 15:19:02 +05:00
var result = new WellOperationPlanDto ( )
{
WellOperationsPlan = entities ,
DateLastAssosiatedPlanOperation = dateLastAssosiatedPlanOperation
} ;
2023-07-19 16:39:17 +05:00
2023-10-06 15:19:02 +05:00
return result ;
}
2023-07-19 16:39:17 +05:00
2023-10-06 15:19:02 +05:00
private async Task < DateTime ? > GetDateLastAssosiatedPlanOperationAsync (
2024-01-24 09:21:07 +05:00
int idWell ,
DateTime ? lessThenDate ,
double timeZoneHours ,
2023-10-06 15:19:02 +05:00
CancellationToken token )
{
2024-01-24 09:21:07 +05:00
if ( lessThenDate is null )
2023-10-06 15:19:02 +05:00
return null ;
2024-01-24 09:21:07 +05:00
2023-10-06 15:19:02 +05:00
var currentDateOffset = lessThenDate . Value . ToUtcDateTimeOffset ( timeZoneHours ) ;
var timeZoneOffset = TimeSpan . FromHours ( timeZoneHours ) ;
var lastFactOperation = await db . WellOperations
. Where ( o = > o . IdWell = = idWell )
. Where ( o = > o . IdType = = WellOperation . IdOperationTypeFact )
. Where ( o = > o . IdPlan ! = null )
. Where ( o = > o . DateStart < currentDateOffset )
. Include ( x = > x . OperationPlan )
. OrderByDescending ( x = > x . DateStart )
. FirstOrDefaultAsync ( token )
. ConfigureAwait ( false ) ;
if ( lastFactOperation is not null )
2023-12-05 14:48:56 +05:00
return DateTime . SpecifyKind ( lastFactOperation . OperationPlan ! . DateStart . UtcDateTime + timeZoneOffset , DateTimeKind . Unspecified ) ;
2023-10-06 15:19:02 +05:00
return null ;
}
2022-12-28 17:38:53 +05:00
2023-10-06 15:19:02 +05:00
/// <inheritdoc/>
public async Task < IEnumerable < SectionByOperationsDto > > GetSectionsAsync ( IEnumerable < int > idsWells , CancellationToken token )
{
var cache = await memoryCache . GetOrCreateAsync ( KeyCacheSections , async ( entry ) = >
2023-02-15 17:02:43 +05:00
{
2023-10-06 15:19:02 +05:00
entry . AbsoluteExpirationRelativeToNow = TimeSpan . FromMinutes ( 30 ) ;
var query = db . Set < WellOperation > ( )
. GroupBy ( operation = > new
{
operation . IdWell ,
operation . IdType ,
operation . IdWellSectionType ,
2023-10-27 12:02:19 +05:00
operation . WellSectionType . Caption ,
2023-10-06 15:19:02 +05:00
} )
. Select ( group = > new
{
group . Key . IdWell ,
group . Key . IdType ,
group . Key . IdWellSectionType ,
2023-10-27 12:02:19 +05:00
group . Key . Caption ,
2023-10-06 15:19:02 +05:00
First = group
. OrderBy ( operation = > operation . DateStart )
. Select ( operation = > new
{
operation . DateStart ,
operation . DepthStart ,
} )
. First ( ) ,
Last = group
. OrderByDescending ( operation = > operation . DateStart )
. Select ( operation = > new
{
operation . DateStart ,
operation . DurationHours ,
operation . DepthEnd ,
} )
. First ( ) ,
} ) ;
var dbData = await query . ToArrayAsync ( token ) ;
var sections = dbData . Select (
item = > new SectionByOperationsDto
{
IdWell = item . IdWell ,
IdType = item . IdType ,
IdWellSectionType = item . IdWellSectionType ,
2023-02-21 16:15:36 +05:00
2023-10-27 12:02:19 +05:00
Caption = item . Caption ,
2023-10-06 15:19:02 +05:00
DateStart = item . First . DateStart ,
DepthStart = item . First . DepthStart ,
2023-02-21 16:15:36 +05:00
2023-10-06 15:19:02 +05:00
DateEnd = item . Last . DateStart . AddHours ( item . Last . DurationHours ) ,
DepthEnd = item . Last . DepthEnd ,
} )
. ToArray ( )
. AsEnumerable ( ) ;
2023-02-20 15:17:49 +05:00
2023-10-06 15:19:02 +05:00
entry . Value = sections ;
return sections ;
} ) ;
2023-02-16 09:51:55 +05:00
2023-10-06 15:19:02 +05:00
var sections = cache . Where ( s = > idsWells . Contains ( s . IdWell ) ) ;
return sections ;
}
2023-02-15 17:02:43 +05:00
2023-12-11 10:58:03 +05:00
public async Task < DatesRangeDto ? > GetDatesRangeAsync ( int idWell , int idType , CancellationToken cancellationToken )
{
2023-12-20 16:42:39 +05:00
var timezone = wellService . GetTimezone ( idWell ) ;
2024-01-24 09:21:07 +05:00
2023-12-11 10:58:03 +05:00
var query = db . WellOperations . Where ( o = > o . IdWell = = idWell & & o . IdType = = idType ) ;
if ( ! await query . AnyAsync ( cancellationToken ) )
return null ;
2023-12-20 16:42:39 +05:00
var minDate = await query . MinAsync ( o = > o . DateStart , cancellationToken ) ;
var maxDate = await query . MaxAsync ( o = > o . DateStart , cancellationToken ) ;
2024-01-24 09:21:07 +05:00
2023-12-11 10:58:03 +05:00
return new DatesRangeDto
{
2023-12-20 16:42:39 +05:00
From = minDate . ToRemoteDateTime ( timezone . Hours ) ,
To = maxDate . ToRemoteDateTime ( timezone . Hours )
2023-12-11 10:58:03 +05:00
} ;
}
2023-10-06 15:19:02 +05:00
/// <inheritdoc/>
public DateTimeOffset ? FirstOperationDate ( int idWell )
{
var sections = GetSectionsAsync ( new [ ] { idWell } , CancellationToken . None ) . Result ;
var first = sections . FirstOrDefault ( section = > section . IdType = = WellOperation . IdOperationTypeFact )
? ? sections . FirstOrDefault ( section = > section . IdType = = WellOperation . IdOperationTypePlan ) ;
2023-02-21 16:15:36 +05:00
2023-10-06 15:19:02 +05:00
return first ? . DateStart ;
}
2022-05-06 16:35:16 +05:00
2023-10-06 15:19:02 +05:00
/// <inheritdoc/>
public async Task < IEnumerable < WellOperationDto > > GetAsync (
WellOperationRequest request ,
CancellationToken token )
{
var query = BuildQuery ( request )
. AsNoTracking ( ) ;
2024-02-05 08:54:18 +05:00
var dtos = await query . ToArrayAsync ( token ) ;
return dtos ;
2023-10-06 15:19:02 +05:00
}
/// <inheritdoc/>
public async Task < PaginationContainer < WellOperationDto > > GetPageAsync (
WellOperationRequest request ,
CancellationToken token )
{
var query = BuildQuery ( request )
. AsNoTracking ( ) ;
2022-01-05 17:50:45 +05:00
2023-10-06 15:19:02 +05:00
var result = new PaginationContainer < WellOperationDto >
2022-12-28 17:38:53 +05:00
{
2023-10-06 15:19:02 +05:00
Skip = request . Skip ? ? 0 ,
Take = request . Take ? ? 32 ,
Count = await query . CountAsync ( token ) . ConfigureAwait ( false ) ,
} ;
2021-08-18 16:57:20 +05:00
2023-10-06 15:19:02 +05:00
query = query
. Skip ( result . Skip )
. Take ( result . Take ) ;
2021-08-13 17:25:06 +05:00
2023-10-06 15:19:02 +05:00
result . Items = await query . ToArrayAsync ( token ) ;
return result ;
}
2021-08-13 17:25:06 +05:00
2023-10-06 15:19:02 +05:00
/// <inheritdoc/>
public async Task < WellOperationDto ? > GetOrDefaultAsync ( int id ,
CancellationToken token )
{
var entity = await db . WellOperations
. Include ( s = > s . WellSectionType )
. Include ( s = > s . OperationCategory )
. FirstOrDefaultAsync ( e = > e . Id = = id , token )
. ConfigureAwait ( false ) ;
2021-08-16 14:19:43 +05:00
2023-10-06 15:19:02 +05:00
if ( entity is null )
return null ;
2022-12-27 14:30:52 +05:00
2023-10-06 15:19:02 +05:00
var timezone = wellService . GetTimezone ( entity . IdWell ) ;
2022-12-21 18:02:22 +05:00
2023-10-06 15:19:02 +05:00
var dto = entity . Adapt < WellOperationDto > ( ) ;
dto . WellSectionTypeName = entity . WellSectionType . Caption ;
dto . DateStart = entity . DateStart . ToRemoteDateTime ( timezone . Hours ) ;
dto . CategoryName = entity . OperationCategory . Name ;
return dto ;
}
/// <inheritdoc/>
public async Task < IEnumerable < WellGroupOpertionDto > > GetGroupOperationsStatAsync (
WellOperationRequest request ,
CancellationToken token )
{
// TODO: Rename controller method
request . OperationType = WellOperation . IdOperationTypeFact ;
var query = BuildQuery ( request ) ;
var entities = await query
. Select ( o = > new
2022-12-02 15:54:55 +05:00
{
2023-10-06 15:19:02 +05:00
o . IdCategory ,
DurationMinutes = o . DurationHours * 60 ,
DurationDepth = o . DepthEnd - o . DepthStart
} )
. ToListAsync ( token ) ;
var parentRelationDictionary = GetCategories ( true )
. ToDictionary ( c = > c . Id , c = > new
{
c . Name ,
c . IdParent
} ) ;
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
var dtos = entities
. GroupBy ( o = > o . IdCategory )
. Select ( g = > new WellGroupOpertionDto
{
IdCategory = g . Key ,
Category = parentRelationDictionary [ g . Key ] . Name ,
Count = g . Count ( ) ,
MinutesAverage = g . Average ( o = > o . DurationMinutes ) ,
MinutesMin = g . Min ( o = > o . DurationMinutes ) ,
MinutesMax = g . Max ( o = > o . DurationMinutes ) ,
TotalMinutes = g . Sum ( o = > o . DurationMinutes ) ,
DeltaDepth = g . Sum ( o = > o . DurationDepth ) ,
IdParent = parentRelationDictionary [ g . Key ] . IdParent
} ) ;
2024-01-24 09:21:07 +05:00
2023-10-06 15:19:02 +05:00
while ( dtos . All ( x = > x . IdParent ! = null ) )
2021-08-16 14:19:43 +05:00
{
2023-10-06 15:19:02 +05:00
dtos = dtos
. GroupBy ( o = > o . IdParent ! )
2024-01-24 09:21:07 +05:00
. Select ( g = >
{
2023-10-06 15:19:02 +05:00
var idCategory = g . Key ? ? int . MinValue ;
var category = parentRelationDictionary . GetValueOrDefault ( idCategory ) ;
var newDto = new WellGroupOpertionDto
{
IdCategory = idCategory ,
Category = category ? . Name ? ? "unknown" ,
Count = g . Sum ( o = > o . Count ) ,
DeltaDepth = g . Sum ( o = > o . DeltaDepth ) ,
TotalMinutes = g . Sum ( o = > o . TotalMinutes ) ,
Items = g . ToList ( ) ,
IdParent = category ? . IdParent ,
} ;
return newDto ;
} ) ;
}
return dtos ;
}
2022-12-21 18:02:22 +05:00
2023-10-06 15:19:02 +05:00
/// <inheritdoc/>
public async Task < int > InsertRangeAsync (
IEnumerable < WellOperationDto > wellOperationDtos ,
CancellationToken token )
{
var firstOperation = wellOperationDtos
. FirstOrDefault ( ) ;
if ( firstOperation is null )
return 0 ;
2022-12-21 18:02:22 +05:00
2023-10-06 15:19:02 +05:00
var idWell = firstOperation . IdWell ;
2021-08-16 14:19:43 +05:00
2023-10-06 15:19:02 +05:00
var timezone = wellService . GetTimezone ( idWell ) ;
foreach ( var dto in wellOperationDtos )
2021-08-16 14:19:43 +05:00
{
2022-01-05 17:50:45 +05:00
var entity = dto . Adapt < WellOperation > ( ) ;
2023-10-06 15:19:02 +05:00
entity . Id = default ;
2024-02-05 08:54:18 +05:00
entity . DateStart = dto . DateStart . DateTime . ToUtcDateTimeOffset ( timezone . Hours ) ;
2023-10-06 15:19:02 +05:00
entity . IdWell = idWell ;
2024-02-05 08:54:18 +05:00
entity . LastUpdateDate = DateTimeOffset . UtcNow ;
2023-10-06 15:19:02 +05:00
db . WellOperations . Add ( entity ) ;
2021-08-16 14:19:43 +05:00
}
2023-10-06 15:19:02 +05:00
var result = await db . SaveChangesAsync ( token ) ;
if ( result > 0 )
memoryCache . Remove ( KeyCacheSections ) ;
return result ;
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
}
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
/// <inheritdoc/>
public async Task < int > UpdateAsync (
WellOperationDto dto , CancellationToken token )
{
var timezone = wellService . GetTimezone ( dto . IdWell ) ;
var entity = dto . Adapt < WellOperation > ( ) ;
2024-02-05 08:54:18 +05:00
entity . DateStart = dto . DateStart . DateTime . ToUtcDateTimeOffset ( timezone . Hours ) ;
entity . LastUpdateDate = DateTimeOffset . UtcNow ;
2023-10-06 15:19:02 +05:00
db . WellOperations . Update ( entity ) ;
var result = await db . SaveChangesAsync ( token ) ;
if ( result > 0 )
memoryCache . Remove ( KeyCacheSections ) ;
return result ;
}
2022-12-28 17:38:53 +05:00
2023-10-06 15:19:02 +05:00
/// <inheritdoc/>
public async Task < int > DeleteAsync ( IEnumerable < int > ids ,
CancellationToken token )
{
var query = db . WellOperations . Where ( e = > ids . Contains ( e . Id ) ) ;
db . WellOperations . RemoveRange ( query ) ;
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
var result = await db . SaveChangesAsync ( token ) ;
if ( result > 0 )
memoryCache . Remove ( KeyCacheSections ) ;
return result ;
}
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
/// <summary>
/// В результате попрежнему требуется конвертировать дату
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private IQueryable < WellOperationDto > BuildQuery ( WellOperationRequest request )
{
var timezone = wellService . GetTimezone ( request . IdWell ) ;
var timeZoneOffset = TimeSpan . FromHours ( timezone . Hours ) ;
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
var query = db . WellOperations
. Include ( s = > s . WellSectionType )
. Include ( s = > s . OperationCategory )
. Where ( o = > o . IdWell = = request . IdWell ) ;
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
if ( request . OperationType . HasValue )
query = query . Where ( e = > e . IdType = = request . OperationType . Value ) ;
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
if ( request . SectionTypeIds ? . Any ( ) = = true )
query = query . Where ( e = > request . SectionTypeIds . Contains ( e . IdWellSectionType ) ) ;
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
if ( request . OperationCategoryIds ? . Any ( ) = = true )
query = query . Where ( e = > request . OperationCategoryIds . Contains ( e . IdCategory ) ) ;
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
if ( request . GeDepth . HasValue )
query = query . Where ( e = > e . DepthEnd > = request . GeDepth . Value ) ;
2023-02-17 09:25:34 +05:00
2023-10-06 15:19:02 +05:00
if ( request . LeDepth . HasValue )
query = query . Where ( e = > e . DepthEnd < = request . LeDepth . Value ) ;
2023-02-17 09:25:34 +05:00
2023-10-06 15:19:02 +05:00
if ( request . GeDate . HasValue )
{
var geDateOffset = request . GeDate . Value . ToUtcDateTimeOffset ( timezone . Hours ) ;
query = query . Where ( e = > e . DateStart > = geDateOffset ) ;
}
2023-02-17 09:25:34 +05:00
2023-10-06 15:19:02 +05:00
if ( request . LtDate . HasValue )
{
var ltDateOffset = request . LtDate . Value . ToUtcDateTimeOffset ( timezone . Hours ) ;
query = query . Where ( e = > e . DateStart < ltDateOffset ) ;
}
var currentWellOperations = db . WellOperations
. Where ( subOp = > subOp . IdWell = = request . IdWell ) ;
2022-12-02 15:54:55 +05:00
2023-10-06 15:19:02 +05:00
var wellOperationsWithCategoryNPT = currentWellOperations
. Where ( subOp = > subOp . IdType = = 1 )
. Where ( subOp = > WellOperationCategory . NonProductiveTimeSubIds . Contains ( subOp . IdCategory ) ) ;
2024-02-05 08:54:18 +05:00
var dtos = query . Select ( o = > new WellOperationDto
2023-10-06 15:19:02 +05:00
{
Id = o . Id ,
IdPlan = o . IdPlan ,
IdType = o . IdType ,
IdWell = o . IdWell ,
IdWellSectionType = o . IdWellSectionType ,
IdCategory = o . IdCategory ,
IdParentCategory = o . OperationCategory . IdParent ,
CategoryName = o . OperationCategory . Name ,
WellSectionTypeName = o . WellSectionType . Caption ,
DateStart = DateTime . SpecifyKind ( o . DateStart . UtcDateTime + timeZoneOffset , DateTimeKind . Unspecified ) ,
DepthStart = o . DepthStart ,
DepthEnd = o . DepthEnd ,
DurationHours = o . DurationHours ,
CategoryInfo = o . CategoryInfo ,
Comment = o . Comment ,
NptHours = wellOperationsWithCategoryNPT
. Where ( subOp = > subOp . DateStart < = o . DateStart )
. Select ( subOp = > subOp . DurationHours )
. Sum ( ) ,
Day = ( o . DateStart - currentWellOperations
. Where ( subOp = > subOp . IdType = = o . IdType )
. Where ( subOp = > subOp . DateStart < = o . DateStart )
. Min ( subOp = > subOp . DateStart ) )
. TotalDays ,
IdUser = o . IdUser ,
2024-02-05 08:54:18 +05:00
LastUpdateDate = DateTime . SpecifyKind ( o . LastUpdateDate . UtcDateTime + timeZoneOffset , DateTimeKind . Unspecified )
2023-10-06 15:19:02 +05:00
} ) ;
if ( request . SortFields ? . Any ( ) = = true )
{
2024-02-05 08:54:18 +05:00
dtos = dtos . SortBy ( request . SortFields ) ;
2022-12-02 15:54:55 +05:00
}
2023-10-06 15:19:02 +05:00
else
{
2024-02-05 08:54:18 +05:00
dtos = dtos
2023-10-06 15:19:02 +05:00
. OrderBy ( e = > e . DateStart )
. ThenBy ( e = > e . DepthEnd )
. ThenBy ( e = > e . Id ) ;
2024-02-05 08:54:18 +05:00
}
return dtos ;
2023-10-06 15:19:02 +05:00
}
2024-02-16 17:26:49 +05:00
2024-02-19 11:42:59 +05:00
public async Task < int > RemoveDuplicates ( Action < string , double? > onProgressCallback , CancellationToken token )
2024-02-16 17:26:49 +05:00
{
2024-02-19 11:42:59 +05:00
IQueryable < WellOperation > dbset = db . Set < WellOperation > ( ) ;
var query = dbset
2024-02-16 17:26:49 +05:00
. GroupBy ( o = > new { o . IdWell , o . IdType } )
2024-02-19 11:42:59 +05:00
. Select ( g = > new { g . Key . IdWell , g . Key . IdType } ) ;
var groups = await query
2024-02-16 17:26:49 +05:00
. ToArrayAsync ( token ) ;
2024-02-19 11:42:59 +05:00
var count = groups . Count ( ) ;
var i = 0 ;
var totalRemoved = 0 ;
var total = 0 ;
foreach ( var group in groups )
{
var result = await RemoveDuplicatesInGroup ( group . IdWell , group . IdType , token ) ;
totalRemoved + = result . removed ;
total + = result . total ;
var percent = i + + / count ;
var message = $"RemoveDuplicates [{i} of {count}] wellId: {group.IdWell}, opType: {group.IdType}, affected: {result.removed} of {result.total}" ;
onProgressCallback ? . Invoke ( message , percent ) ;
Trace . TraceInformation ( message ) ;
}
var messageDone = $"RemoveDuplicates done [{i} of {count}] totalAffected: {totalRemoved} of {total}" ;
Trace . TraceInformation ( messageDone ) ;
onProgressCallback ? . Invoke ( messageDone , 1 ) ;
return totalRemoved ;
2024-02-16 17:26:49 +05:00
}
2024-02-19 11:42:59 +05:00
private async Task < ( int removed , int total ) > RemoveDuplicatesInGroup ( int idWell , int idType , CancellationToken token )
2024-02-16 17:26:49 +05:00
{
var dbset = db . Set < WellOperation > ( ) ;
2024-02-19 11:42:59 +05:00
var entities = await dbset
2024-02-16 17:26:49 +05:00
. Where ( o = > o . IdWell = = idWell & & o . IdType = = idType )
. OrderBy ( o = > o . DateStart )
2024-02-19 11:42:59 +05:00
. ToListAsync ( token ) ;
using var entitiesEnumerator = entities . GetEnumerator ( ) ;
2024-02-16 17:26:49 +05:00
2024-02-19 11:42:59 +05:00
if ( ! entitiesEnumerator . MoveNext ( ) )
return ( 0 , 0 ) ;
2024-02-16 17:26:49 +05:00
2024-02-19 11:42:59 +05:00
var preEntity = entitiesEnumerator . Current ;
while ( entitiesEnumerator . MoveNext ( ) )
2024-02-16 17:26:49 +05:00
{
2024-02-19 11:42:59 +05:00
var entity = entitiesEnumerator . Current ;
if ( preEntity . IsSame ( entity ) )
dbset . Remove ( entity ) ;
2024-02-16 17:26:49 +05:00
else
2024-02-19 11:42:59 +05:00
preEntity = entity ;
2024-02-16 17:26:49 +05:00
}
2024-02-19 11:42:59 +05:00
var removed = await db . SaveChangesAsync ( token ) ;
return ( removed , entities . Count ) ;
2024-02-16 17:26:49 +05:00
}
2024-02-19 11:42:59 +05:00
public async Task < int > TrimOverlapping ( DateTimeOffset ? geDate , DateTimeOffset leDate , Action < string , double? > onProgressCallback , CancellationToken token )
2024-02-16 17:26:49 +05:00
{
var leDateUtc = leDate . ToUniversalTime ( ) ;
2024-02-19 11:42:59 +05:00
IQueryable < WellOperation > query = db . Set < WellOperation > ( ) ;
if ( geDate . HasValue )
{
var geDateUtc = geDate . Value . ToUniversalTime ( ) ;
query = query . Where ( e = > e . DateStart > = geDateUtc ) ;
}
var groups = await query
2024-02-16 17:26:49 +05:00
. GroupBy ( o = > new { o . IdWell , o . IdType } )
. Select ( g = > new {
MaxDate = g . Max ( o = > o . DateStart ) ,
g . Key . IdWell ,
g . Key . IdType ,
} )
2024-02-19 11:42:59 +05:00
. Where ( g = > g . MaxDate < = leDateUtc )
2024-02-16 17:26:49 +05:00
. ToArrayAsync ( token ) ;
2024-02-19 11:42:59 +05:00
var count = groups . Count ( ) ;
var i = 0 ;
( int takeover , int trimmed , int total ) totalResult = ( 0 , 0 , 0 ) ;
2024-02-16 17:26:49 +05:00
foreach ( var group in groups )
2024-02-19 11:42:59 +05:00
{
var result = await TrimOverlapping ( group . IdWell , group . IdType , token ) ;
totalResult . takeover + = result . takeover ;
totalResult . trimmed + = result . trimmed ;
totalResult . total + = result . total ;
var percent = i + + / count ;
var message = $"TrimOverlapping [{i} of {count}] wellId: {group.IdWell}, opType: {group.IdType}, takeover:{result.takeover}, trimmed:{result.trimmed}, of {result.total}" ;
onProgressCallback ? . Invoke ( message , percent ) ;
Trace . TraceInformation ( message ) ;
}
var messageDone = $"TrimOverlapping done [{i} of {count}] total takeover:{totalResult.takeover}, total trimmed:{totalResult.trimmed} of {totalResult.total}" ;
Trace . TraceInformation ( messageDone ) ;
onProgressCallback ? . Invoke ( messageDone , 1 ) ;
return totalResult . takeover + totalResult . trimmed ;
2024-02-16 17:26:49 +05:00
}
2024-02-19 11:42:59 +05:00
private async Task < ( int takeover , int trimmed , int total ) > TrimOverlapping ( int idWell , int idType , CancellationToken token )
2024-02-16 17:26:49 +05:00
{
2024-02-19 11:42:59 +05:00
var dbset = db . Set < WellOperation > ( ) ;
var query = dbset
. Where ( o = > o . IdWell = = idWell )
. Where ( o = > o . IdType = = idType )
. OrderBy ( o = > o . DateStart )
. ThenBy ( o = > o . DepthStart ) ;
var entities = await query
. ToListAsync ( token ) ;
using var entitiesEnumerator = entities . GetEnumerator ( ) ;
if ( ! entitiesEnumerator . MoveNext ( ) )
return ( 0 , 0 , 0 ) ;
int takeover = 0 ;
int trimmed = 0 ;
var preEntity = entitiesEnumerator . Current ;
while ( entitiesEnumerator . MoveNext ( ) )
{
var entity = entitiesEnumerator . Current ;
var preDepth = preEntity . DepthEnd ;
if ( preEntity . DepthEnd > = entity . DepthEnd )
{
dbset . Remove ( entity ) ;
takeover + + ;
continue ;
}
if ( preEntity . DepthEnd > entity . DepthStart )
{
entity . DepthStart = preEntity . DepthEnd ;
trimmed + + ;
}
var preDate = preEntity . DateStart . AddHours ( preEntity . DurationHours ) ;
if ( preDate > = entity . DateStart . AddHours ( entity . DurationHours ) )
{
dbset . Remove ( entity ) ;
takeover + + ;
continue ;
}
if ( preDate > entity . DateStart )
{
var entityDateEnd = entity . DateStart . AddHours ( entity . DurationHours ) ;
entity . DateStart = preDate ;
entity . DurationHours = ( entityDateEnd - entity . DateStart ) . TotalHours ;
trimmed + + ;
}
preEntity = entity ;
}
var affected = await db . SaveChangesAsync ( token ) ;
return ( takeover , trimmed , entities . Count ) ;
2024-02-16 17:26:49 +05:00
}
2021-08-13 17:25:06 +05:00
}