diff --git a/AsbCloudApp/Data/WellDto.cs b/AsbCloudApp/Data/WellDto.cs index d88aa631..c1b9a22b 100644 --- a/AsbCloudApp/Data/WellDto.cs +++ b/AsbCloudApp/Data/WellDto.cs @@ -50,6 +50,11 @@ namespace AsbCloudApp.Data /// public int IdState { get; set; } + /// + /// Дата/время первой операции + /// + public DateTime? StartDate { get; set; } + /// /// Дата/время кода приходили данные последний раз /// diff --git a/AsbCloudApp/Services/IWellOperationService.cs b/AsbCloudApp/Services/IWellOperationService.cs index 475ea9bd..d3d3a310 100644 --- a/AsbCloudApp/Services/IWellOperationService.cs +++ b/AsbCloudApp/Services/IWellOperationService.cs @@ -33,5 +33,6 @@ namespace AsbCloudApp.Services Task DeleteAsync(IEnumerable ids, CancellationToken token); IDictionary GetSectionTypes(); + DateTimeOffset? FirstOperationDate(int idWell); } } diff --git a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs index b552717e..55979e96 100644 --- a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs @@ -19,6 +19,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService private readonly CacheTable cachedOperationCategories; private readonly CacheTable cachedSectionTypes; + private Dictionary? firstOperationsCache = null; + public const int idOperationBhaAssembly = 1025; public const int idOperationBhaDisassembly = 1026; public const int idOperationNonProductiveTime = 1043; @@ -49,6 +51,26 @@ namespace AsbCloudInfrastructure.Services.WellOperationService return result; } + public DateTimeOffset? FirstOperationDate(int idWell) + { + if(firstOperationsCache is null) + { + var query = db.WellOperations + .GroupBy(o => o.IdWell) + .Select(g => new Tuple + ( + g.Key, + g.Where(o => o.IdType == idOperationTypePlan).Min(o => o.DateStart), + g.Where(o => o.IdType == idOperationTypeFact).Min(o => o.DateStart) + )); + + firstOperationsCache = query + .ToDictionary(f => f.Item1, f => f.Item3 ?? f.Item2); + } + + return firstOperationsCache?.GetValueOrDefault(idWell); + } + public async Task> GetOperationsAsync( int idWell, int? operationType = default, diff --git a/AsbCloudInfrastructure/Services/WellService.cs b/AsbCloudInfrastructure/Services/WellService.cs index ebe5ca84..44085c81 100644 --- a/AsbCloudInfrastructure/Services/WellService.cs +++ b/AsbCloudInfrastructure/Services/WellService.cs @@ -29,6 +29,7 @@ namespace AsbCloudInfrastructure.Services private readonly CacheTable cacheRelationCompaniesWells; private readonly CacheTable cacheCompanyWellTypes; private readonly ITimezoneService timezoneService; + private readonly Lazy wellOperationService; public ITelemetryService TelemetryService => telemetryService; @@ -37,6 +38,7 @@ namespace AsbCloudInfrastructure.Services { this.telemetryService = telemetryService; this.timezoneService = timezoneService; + this.wellOperationService = new Lazy(() => new WellOperationService.WellOperationService(db, cacheDb, this)); cacheRelationCompaniesWells = cacheDb.GetCachedTable((AsbCloudDbContext)db, nameof(RelationCompanyWell.Company), nameof(RelationCompanyWell.Well)); cacheCompanyWellTypes = cacheDb.GetCachedTable((AsbCloudDbContext)db); Includes.Add($"{nameof(Well.Cluster)}.{nameof(Cluster.Deposit)}"); @@ -48,7 +50,7 @@ namespace AsbCloudInfrastructure.Services public DateTimeOffset GetLastTelemetryDate(int idWell) { var well = Cache.FirstOrDefault(w => w.Id == idWell); - + if (well?.IdTelemetry is null) return DateTimeOffset.MinValue; @@ -63,7 +65,7 @@ namespace AsbCloudInfrastructure.Services var wellsIds = relations.Select(r => r.IdWell); var wells = await Cache.WhereAsync(w => wellsIds.Contains(w.Id), token); - + var dtos = wells.Select(Convert); return dtos; } @@ -202,6 +204,7 @@ namespace AsbCloudInfrastructure.Services if (TryGetTimezone(entity, out var timezone)) dto.Timezone = timezone; + dto.StartDate = wellOperationService.Value.FirstOperationDate(entity.Id)?.ToRemoteDateTime(dto.Timezone.Hours); dto.WellType = entity.WellType?.Caption; dto.Cluster = entity.Cluster?.Caption; dto.Deposit = entity.Cluster?.Deposit?.Caption; diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index fe92aa60..33142088 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -6,21 +6,35 @@ using System.Linq; namespace ConsoleApp1 { + class Cron + { + public DateTimeOffset Origin { get; set; } + public TimeSpan Period { get; set; } + + public DateTimeOffset Next() + { + var delta = DateTimeOffset.Now - Origin; + var n = Math.Ceiling(delta / Period); + return Origin + n * Period; + } + } + class Program { static void Main(/*string[] args*/) { // use ServiceFactory to make services - var db = ServiceFactory.Context; - //var d = db.TelemetryDataSaubStats.ToList(); + var op = ServiceFactory.MakeWellOperationsService(); + var d = op.FirstOperationDate(90); - //db.RefreshMaterializedViewAsync().Wait(); + var period = TimeSpan.FromHours(5); + var c = new Cron + { + Period = period, + Origin = new DateTimeOffset(2022, 5, 8, 0, 0, 7, TimeSpan.FromHours(5)), + }; - var d = db.WellSectionTypes - .Include(e => e.DrillParamsCollection) - .Include(e => e.WellComposites) - .Include(e => e.WellOperations) - .ToList(); + Console.WriteLine($"origin: {c.Origin} next: {c.Next()}"); Console.WriteLine("End of Test"); Console.ReadLine(); diff --git a/ConsoleApp1/ServiceFactory.cs b/ConsoleApp1/ServiceFactory.cs index b71f727e..41cbd9a8 100644 --- a/ConsoleApp1/ServiceFactory.cs +++ b/ConsoleApp1/ServiceFactory.cs @@ -70,6 +70,9 @@ namespace ConsoleApp1 public static WellService MakeWellService() => new WellService(Context, CacheDb, MakeTelemetryService(), TimezoneService); + public static WellOperationService MakeWellOperationsService() + => new WellOperationService(Context, CacheDb, MakeWellService()); + public static OperationsStatService MakeOperationsStatService() => new OperationsStatService(Context, CacheDb, MakeWellService());