From 19820b79ec8896b4ae5f6ddf0b7b7b06859b5d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Mon, 14 Aug 2023 11:54:30 +0500 Subject: [PATCH 01/13] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=B8=D0=B0=D0=BF=D0=B0=D0=B7?= =?UTF-8?q?=D0=BE=D0=BD=D0=B0=20=D0=B4=D0=B0=D1=82=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=81=D1=83=D1=82=D0=BE=D1=87=D0=BD=D1=8B=D1=85=20=D0=BE=D1=82?= =?UTF-8?q?=D1=87=D1=91=D1=82=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IAutoGeneratedDailyReportService.cs | 10 +++++- .../AutoGeneratedDailyReportService.cs | 32 ++++++++++++------- .../AutoGeneratedDailyReportController.cs | 20 ++++++++++-- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportService.cs b/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportService.cs index 16cdaed6..13bdb1ea 100644 --- a/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportService.cs +++ b/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportService.cs @@ -31,6 +31,14 @@ public interface IAutoGeneratedDailyReportService /// /// /// - Task<(string fileName, Stream stream)> GenerateReportAsync(int idWell, DateOnly reportDate, + Task<(string fileName, Stream stream)> GenerateAsync(int idWell, DateOnly reportDate, CancellationToken cancellationToken); + + /// + /// Получение диапазона дат + /// + /// + /// + /// + Task GetDatesRangeAsync(int idWell, CancellationToken cancellationToken); } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs b/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs index 514b0b66..edf3641b 100644 --- a/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs +++ b/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Data.AutogeneratedDailyReport; -using AsbCloudApp.Data.SAUB; using AsbCloudApp.Data.Subsystems; using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; @@ -15,7 +14,6 @@ using AsbCloudApp.Services; using AsbCloudApp.Services.AutoGeneratedDailyReports; using AsbCloudApp.Services.Subsystems; using AsbCloudDb.Model; -using AsbCloudInfrastructure.Services.SAUB; namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports; @@ -25,7 +23,6 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService private readonly IWellService wellService; private readonly IWellOperationRepository wellOperationRepository; - private readonly TelemetryDataCache telemetryDataCache; private readonly ISubsystemOperationTimeService subsystemOperationTimeService; private readonly ICrudRepository subsystemRepository; private readonly ILimitingParameterService limitingParameterService; @@ -33,7 +30,6 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService public AutoGeneratedDailyReportService(IWellService wellService, IWellOperationRepository wellOperationRepository, - TelemetryDataCache telemetryDataCache, ISubsystemOperationTimeService subsystemOperationTimeService, ICrudRepository subsystemRepository, ILimitingParameterService limitingParameterService, @@ -41,7 +37,6 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService { this.wellOperationRepository = wellOperationRepository; this.wellService = wellService; - this.telemetryDataCache = telemetryDataCache; this.subsystemOperationTimeService = subsystemOperationTimeService; this.subsystemRepository = subsystemRepository; this.limitingParameterService = limitingParameterService; @@ -67,9 +62,9 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService if (!well.IdTelemetry.HasValue) throw new ArgumentInvalidException("Телеметрия для скважины отсутствует", nameof(idWell)); - var datesRange = telemetryDataCache.GetOrDefaultDataDateRange(well.IdTelemetry.Value); - - if (datesRange is null) + var datesRange = await GetDatesRangeAsync(idWell, cancellationToken); + + if (datesRange is null) return result; result.Count = (int)(Math.Ceiling((datesRange.To - DateTime.UnixEpoch).TotalDays) - Math.Floor((datesRange.From - DateTime.UnixEpoch).TotalDays)); @@ -109,7 +104,7 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService return result; } - public async Task<(string fileName, Stream stream)> GenerateReportAsync(int idWell, DateOnly reportDate, + public async Task<(string fileName, Stream stream)> GenerateAsync(int idWell, DateOnly reportDate, CancellationToken cancellationToken) { var startDate = new DateTime(reportDate.Year, reportDate.Month, reportDate.Day); @@ -144,6 +139,21 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService return (report.FileName, stream); } + public async Task GetDatesRangeAsync(int idWell, CancellationToken cancellationToken) + { + var factOperations = await GetFactOperationsAsync(idWell, null, null, + cancellationToken); + + if (!factOperations.Any()) + return null; + + return new DatesRangeDto + { + From = factOperations.First().DateStart, + To = factOperations.Last().DateStart + }; + } + private HeadBlockDto CreateHeadBlock(WellDto well, IEnumerable factOperations) { var customer = well.Companies.FirstOrDefault(company => company.IdCompanyType == 1); @@ -199,8 +209,8 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService }); } - private Task> GetFactOperationsAsync(int idWell, DateTime startDate, - DateTime finishDate, CancellationToken cancellationToken) + private Task> GetFactOperationsAsync(int idWell, DateTime? startDate, + DateTime? finishDate, CancellationToken cancellationToken) { var request = new WellOperationRequest { diff --git a/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs b/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs index f38a3ea8..de26e843 100644 --- a/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs +++ b/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs @@ -49,7 +49,7 @@ public class AutoGeneratedDailyReportController : ControllerBase if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) return Forbid(); - var reportFile = await autoGeneratedDailyReportService.GenerateReportAsync(idWell, + var reportFile = await autoGeneratedDailyReportService.GenerateAsync(idWell, reportDate, cancellationToken); @@ -78,7 +78,23 @@ public class AutoGeneratedDailyReportController : ControllerBase return Ok(reports); } - + + /// + /// Диапазон дат для формирования суточных отчётов + /// + /// + /// + /// + [HttpGet("datesRange")] + [ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)] + public async Task GetDatesRangeAsync(int idWell, CancellationToken cancellationToken) + { + if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) + return Forbid(); + + return Ok(await autoGeneratedDailyReportService.GetDatesRangeAsync(idWell, cancellationToken)); + } + private async Task CanUserAccessToWellAsync(int idWell, CancellationToken cancellationToken) { int? idCompany = User.GetCompanyId(); From 04c2266591f2fea9b2692c9f99299dc45a84475e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Mon, 14 Aug 2023 18:30:31 +0500 Subject: [PATCH 02/13] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE=D0=BD=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D1=81=D1=82=D0=B2=D0=BE=D0=BB=D0=B0=20=D1=81=D0=BA=D0=B2?= =?UTF-8?q?=D0=B0=D0=B6=D0=B8=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/WellboreDto.cs | 64 +++++++++++++ .../Repositories/IWellOperationRepository.cs | 18 ++++ AsbCloudApp/Requests/WellboreRequest.cs | 14 +++ .../Repository/WellOperationRepository.cs | 73 +++++++++++++++ .../Controllers/WellboreController.cs | 90 +++++++++++++++++++ 5 files changed, 259 insertions(+) create mode 100644 AsbCloudApp/Data/WellboreDto.cs create mode 100644 AsbCloudApp/Requests/WellboreRequest.cs create mode 100644 AsbCloudWebApi/Controllers/WellboreController.cs diff --git a/AsbCloudApp/Data/WellboreDto.cs b/AsbCloudApp/Data/WellboreDto.cs new file mode 100644 index 00000000..ea542bf8 --- /dev/null +++ b/AsbCloudApp/Data/WellboreDto.cs @@ -0,0 +1,64 @@ +using System; + +namespace AsbCloudApp.Data; + +/// +/// Ствол скважины +/// +public class WellboreDto +{ + /// + /// Идентификатор + /// + public int? Id { get; set; } + + /// + /// Название + /// + public string? Name { get; set; } + + /// + /// Идентификатор скважины + /// + public int IdWell { get; set; } + + /// + /// Состояние скважины + /// + public int IdWellState { get; set; } + + /// + /// Идентификатор телеметрии + /// + public int? IdWellTelemetry { get; set; } + + /// + /// Временная зона скважины + /// + public SimpleTimezoneDto? WellTimezone { get; set; } + + /// + /// Название скважины + /// + public string WellName { get; set; } = null!; + + /// + /// Начальная глубина ствола + /// + public double? DepthFrom { get; set; } + + /// + /// Конечная глубина скважины + /// + public double? DepthTo { get; set; } + + /// + /// Дата начала первой операции + /// + public DateTimeOffset? DateFrom { get; set; } + + /// + /// Дата завершения последней операции + /// + public DateTimeOffset? DateTo { get; set; } +} \ No newline at end of file diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs index b02d3e42..60ddfd80 100644 --- a/AsbCloudApp/Repositories/IWellOperationRepository.cs +++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs @@ -73,6 +73,24 @@ namespace AsbCloudApp.Repositories Task> GetGroupOperationsStatAsync( WellOperationRequest request, CancellationToken token); + + /// + /// Получение ствола скважины + /// + /// + /// + /// + /// + Task GetWellboreAsync(int idWell, int? idWellSectionType, CancellationToken cancellationToken); + + /// + /// Получение стволов скважин + /// + /// + /// + /// + Task> GetWellboresAsync(WellboreRequest request, + CancellationToken cancellationToken); /// /// Добавить несколько операций за один раз diff --git a/AsbCloudApp/Requests/WellboreRequest.cs b/AsbCloudApp/Requests/WellboreRequest.cs new file mode 100644 index 00000000..dadcc7cc --- /dev/null +++ b/AsbCloudApp/Requests/WellboreRequest.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace AsbCloudApp.Requests; + +/// +/// Параметры запроса для ствола скважины +/// +public class WellboreRequest : RequestBase +{ + /// + /// Пары идентификаторов скважины и секции + /// + public IEnumerable<(int idWell, int? idWellSectionType)> Ids { get; set; } = null!; +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index f0eb5f6d..458b93ab 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -255,6 +255,79 @@ namespace AsbCloudInfrastructure.Repository return dtos; } + public async Task GetWellboreAsync(int idWell, int? idWellSectionType, + CancellationToken cancellationToken) + { + var well = await db.Wells.Include(w => w.WellOperations) + .FirstOrDefaultAsync(w => w.Id == idWell, cancellationToken); + + if (well is null) + return null; + + var factOperations = well.WellOperations.AsQueryable(); + + var section = await db.WellSectionTypes + .FirstOrDefaultAsync(w => w.Id == idWellSectionType, cancellationToken); + + if (section is not null) + factOperations = factOperations.Where(w => w.IdWellSectionType == section.Id); + + factOperations = factOperations.OrderBy(f => f.DateStart); + + var firstOperation = factOperations.FirstOrDefault(); + var lastOperation = factOperations.LastOrDefault(); + + return new WellboreDto + { + Id = section?.Id, + Name = section?.Caption, + IdWell = well.Id, + WellName = well.Caption, + IdWellState = well.IdState, + IdWellTelemetry = well.IdTelemetry, + WellTimezone = well.Timezone.Adapt(), + DepthFrom = firstOperation?.DepthStart, + DepthTo = lastOperation?.DepthEnd, + DateFrom = firstOperation?.DateStart, + DateTo = lastOperation?.DateStart.AddHours(lastOperation.DurationHours), + }; + } + + public async Task> GetWellboresAsync(WellboreRequest request, + CancellationToken cancellationToken) + { + var wellbores = new List(); + + var skip = request.Skip ?? 0; + var take = request.Take ?? 10; + + foreach (var id in request.Ids) + { + var wellbore = await GetWellboreAsync(id.idWell, + id.idWellSectionType, + cancellationToken); + + if (wellbore is null) + continue; + + wellbores.Add(wellbore); + } + + var result = new PaginationContainer + { + Skip = skip, + Take = take, + Count = wellbores.Count + }; + + if (result.Count < skip) + return result; + + result.Items = wellbores.Skip(skip).Take(take).ToList(); + + return result; + } + /// public async Task InsertRangeAsync( IEnumerable wellOperationDtos, diff --git a/AsbCloudWebApi/Controllers/WellboreController.cs b/AsbCloudWebApi/Controllers/WellboreController.cs new file mode 100644 index 00000000..be562213 --- /dev/null +++ b/AsbCloudWebApi/Controllers/WellboreController.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data; +using AsbCloudApp.Exceptions; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace AsbCloudWebApi.Controllers; + +/// +/// Ствол скважины +/// +[Authorize] +[ApiController] +[Route("api/well/[controller]")] +public class WellboreController : ControllerBase +{ + private readonly IWellOperationRepository wellOperationRepository; + + public WellboreController(IWellOperationRepository wellOperationRepository) + { + this.wellOperationRepository = wellOperationRepository; + } + + /// + /// Получение ствола скважины + /// + /// Id скважины + /// Опциональный параметр. Id типа секции + /// + /// + + [HttpGet("{idWell:int}")] + [ProducesResponseType(typeof(WellboreDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAsync(int idWell, int? idSectionType, CancellationToken cancellationToken) + { + return Ok(await wellOperationRepository.GetWellboreAsync(idWell, idSectionType, cancellationToken)); + } + + /// + /// Получение списка стволов скважин + /// + /// Пары идентификаторов скважины и секции + /// Опциональный параметр. Количество пропускаемых записей + /// Опциональный параметр. Количество получаемых записей + /// + /// + [HttpGet] + [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAllAsync([FromQuery] IEnumerable ids, + int? skip, + int? take, + CancellationToken cancellationToken) + { + var request = new WellboreRequest + { + Ids = ParseIds(ids), + Skip = skip, + Take = take + }; + + return Ok(await wellOperationRepository.GetWellboresAsync(request, cancellationToken)); + } + + private static IEnumerable<(int, int?)> ParseIds(IEnumerable ids) + { + var result = new List<(int, int?)>(); + + foreach (var id in ids) + { + var idPair = id.Split(','); + + if (!int.TryParse(idPair[0], out var idWell)) + throw new ArgumentInvalidException("Не удалось получить Id скважины", nameof(ids)); + + if (idPair.Length < 2 || !int.TryParse(idPair[1], out var idWellSectionType)) + { + result.Add((idWell, null)); + continue; + } + + result.Add((idWell, idWellSectionType)); + } + + return result; + } +} \ No newline at end of file From 3702cf2e8c71a5b403ac13998eec2a72bf0187a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Tue, 15 Aug 2023 12:28:39 +0500 Subject: [PATCH 03/13] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20+=20=D0=B4=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Переделал логику получения стволов скважин. 2. Поправил контроллер. 3. Рефакторинг DTO ствола. --- AsbCloudApp/Data/WellboreDto.cs | 12 +-- .../Repositories/IWellOperationRepository.cs | 7 +- AsbCloudApp/Requests/WellboreRequest.cs | 2 +- .../Repository/WellOperationRepository.cs | 96 +++++++++++-------- .../Controllers/WellboreController.cs | 19 ++-- 5 files changed, 77 insertions(+), 59 deletions(-) diff --git a/AsbCloudApp/Data/WellboreDto.cs b/AsbCloudApp/Data/WellboreDto.cs index ea542bf8..091f5b07 100644 --- a/AsbCloudApp/Data/WellboreDto.cs +++ b/AsbCloudApp/Data/WellboreDto.cs @@ -10,12 +10,12 @@ public class WellboreDto /// /// Идентификатор /// - public int? Id { get; set; } + public int Id { get; set; } /// /// Название /// - public string? Name { get; set; } + public string Name { get; set; } = null!; /// /// Идентификатор скважины @@ -45,20 +45,20 @@ public class WellboreDto /// /// Начальная глубина ствола /// - public double? DepthFrom { get; set; } + public double DepthFrom { get; set; } /// /// Конечная глубина скважины /// - public double? DepthTo { get; set; } + public double DepthTo { get; set; } /// /// Дата начала первой операции /// - public DateTimeOffset? DateFrom { get; set; } + public DateTimeOffset DateFrom { get; set; } /// /// Дата завершения последней операции /// - public DateTimeOffset? DateTo { get; set; } + public DateTimeOffset DateTo { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs index 60ddfd80..634bc56f 100644 --- a/AsbCloudApp/Repositories/IWellOperationRepository.cs +++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs @@ -78,10 +78,10 @@ namespace AsbCloudApp.Repositories /// Получение ствола скважины /// /// - /// + /// /// /// - Task GetWellboreAsync(int idWell, int? idWellSectionType, CancellationToken cancellationToken); + Task GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken); /// /// Получение стволов скважин @@ -89,8 +89,7 @@ namespace AsbCloudApp.Repositories /// /// /// - Task> GetWellboresAsync(WellboreRequest request, - CancellationToken cancellationToken); + Task> GetWellboresAsync(WellboreRequest request, CancellationToken cancellationToken); /// /// Добавить несколько операций за один раз diff --git a/AsbCloudApp/Requests/WellboreRequest.cs b/AsbCloudApp/Requests/WellboreRequest.cs index dadcc7cc..32b4cbe2 100644 --- a/AsbCloudApp/Requests/WellboreRequest.cs +++ b/AsbCloudApp/Requests/WellboreRequest.cs @@ -10,5 +10,5 @@ public class WellboreRequest : RequestBase /// /// Пары идентификаторов скважины и секции /// - public IEnumerable<(int idWell, int? idWellSectionType)> Ids { get; set; } = null!; + public IEnumerable<(int idWell, int? idSection)> Ids { get; set; } = null!; } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index 458b93ab..ce0b68af 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -255,77 +255,89 @@ namespace AsbCloudInfrastructure.Repository return dtos; } - public async Task GetWellboreAsync(int idWell, int? idWellSectionType, - CancellationToken cancellationToken) + public async Task GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken) { var well = await db.Wells.Include(w => w.WellOperations) .FirstOrDefaultAsync(w => w.Id == idWell, cancellationToken); - if (well is null) + var section = await db.WellSectionTypes + .FirstOrDefaultAsync(w => w.Id == idSection, cancellationToken); + + if (well is null || section is null) return null; - var factOperations = well.WellOperations.AsQueryable(); + var factOperations = well.WellOperations + .Where(o => o.IdType == WellOperation.IdOperationTypeFact && + o.IdWellSectionType == section.Id) + .OrderBy(o => o.DateStart); - var section = await db.WellSectionTypes - .FirstOrDefaultAsync(w => w.Id == idWellSectionType, cancellationToken); - - if (section is not null) - factOperations = factOperations.Where(w => w.IdWellSectionType == section.Id); - - factOperations = factOperations.OrderBy(f => f.DateStart); - - var firstOperation = factOperations.FirstOrDefault(); - var lastOperation = factOperations.LastOrDefault(); + if (!factOperations.Any()) + return null; + + var firstOperation = factOperations.First(); + var lastOperation = factOperations.Last(); return new WellboreDto { - Id = section?.Id, - Name = section?.Caption, + Id = section.Id, + Name = section.Caption, IdWell = well.Id, WellName = well.Caption, IdWellState = well.IdState, IdWellTelemetry = well.IdTelemetry, WellTimezone = well.Timezone.Adapt(), - DepthFrom = firstOperation?.DepthStart, - DepthTo = lastOperation?.DepthEnd, - DateFrom = firstOperation?.DateStart, - DateTo = lastOperation?.DateStart.AddHours(lastOperation.DurationHours), + DepthFrom = firstOperation.DepthStart, + DepthTo = lastOperation.DepthEnd, + DateFrom = firstOperation.DateStart, + DateTo = lastOperation.DateStart.AddHours(lastOperation.DurationHours), }; } - public async Task> GetWellboresAsync(WellboreRequest request, - CancellationToken cancellationToken) + public async Task> GetWellboresAsync(WellboreRequest request, CancellationToken cancellationToken) { var wellbores = new List(); - var skip = request.Skip ?? 0; var take = request.Take ?? 10; + + var sections = GetSectionTypes() + .ToDictionary(w => w.Id, w => w); - foreach (var id in request.Ids) + foreach (var (idWell, idSection) in request.Ids) { - var wellbore = await GetWellboreAsync(id.idWell, - id.idWellSectionType, - cancellationToken); + var well = await db.Wells.Include(w => w.WellOperations) + .FirstOrDefaultAsync(w => w.Id == idWell, cancellationToken); - if (wellbore is null) + if (well is null) continue; + + var factOperations = well.WellOperations + .Where(o => o.IdType == WellOperation.IdOperationTypeFact) + .OrderBy(o => o.DateStart) + .GroupBy(o => o.IdWellSectionType); - wellbores.Add(wellbore); + if(idSection.HasValue) + factOperations = factOperations.Where(w => w.Key == idSection); + + wellbores.AddRange(from factOperation in factOperations + let firstOperation = factOperation.First() + let lastOperation = factOperation.Last() + select new WellboreDto + { + Id = sections[factOperation.Key].Id, + Name = sections[factOperation.Key].Caption, + IdWell = well.Id, + WellName = well.Caption, + IdWellState = well.IdState, + IdWellTelemetry = well.IdTelemetry, + WellTimezone = well.Timezone.Adapt(), + DepthFrom = firstOperation.DepthStart, + DepthTo = lastOperation.DepthEnd, + DateFrom = firstOperation.DateStart, + DateTo = lastOperation.DateStart.AddHours(lastOperation.DurationHours), + }); } - var result = new PaginationContainer - { - Skip = skip, - Take = take, - Count = wellbores.Count - }; - - if (result.Count < skip) - return result; - - result.Items = wellbores.Skip(skip).Take(take).ToList(); - - return result; + return wellbores.Skip(skip).Take(take); } /// diff --git a/AsbCloudWebApi/Controllers/WellboreController.cs b/AsbCloudWebApi/Controllers/WellboreController.cs index be562213..aeca9e8d 100644 --- a/AsbCloudWebApi/Controllers/WellboreController.cs +++ b/AsbCloudWebApi/Controllers/WellboreController.cs @@ -6,6 +6,7 @@ using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace AsbCloudWebApi.Controllers; @@ -29,15 +30,21 @@ public class WellboreController : ControllerBase /// Получение ствола скважины /// /// Id скважины - /// Опциональный параметр. Id типа секции + /// Id типа секции скважины /// /// - [HttpGet("{idWell:int}")] - [ProducesResponseType(typeof(WellboreDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAsync(int idWell, int? idSectionType, CancellationToken cancellationToken) + [HttpGet("{idWell:int}/{idSection:int}")] + [ProducesResponseType(typeof(WellboreDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task GetAsync(int idWell, int idSection, CancellationToken cancellationToken) { - return Ok(await wellOperationRepository.GetWellboreAsync(idWell, idSectionType, cancellationToken)); + var wellbore = await wellOperationRepository.GetWellboreAsync(idWell, idSection, cancellationToken); + + if (wellbore is null) + return NoContent(); + + return Ok(wellbore); } /// @@ -49,7 +56,7 @@ public class WellboreController : ControllerBase /// /// [HttpGet] - [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] public async Task GetAllAsync([FromQuery] IEnumerable ids, int? skip, int? take, From 36ec92f055ca5b1d286f58c225e9fe34db21fc03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Tue, 15 Aug 2023 13:39:04 +0500 Subject: [PATCH 04/13] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AutoGeneratedDailyReportService.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs b/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs index edf3641b..03a19c44 100644 --- a/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs +++ b/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs @@ -149,8 +149,8 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService return new DatesRangeDto { - From = factOperations.First().DateStart, - To = factOperations.Last().DateStart + From = factOperations.Min(o => o.DateStart), + To = factOperations.Max(o => o.DateStart) }; } @@ -209,7 +209,7 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService }); } - private Task> GetFactOperationsAsync(int idWell, DateTime? startDate, + private async Task> GetFactOperationsAsync(int idWell, DateTime? startDate, DateTime? finishDate, CancellationToken cancellationToken) { var request = new WellOperationRequest @@ -221,7 +221,8 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService SortFields = new[] { "DateStart asc" }, }; - return wellOperationRepository.GetAsync(request, cancellationToken); + return (await wellOperationRepository.GetAsync(request, cancellationToken)) + .OrderBy(w => w.DateStart); } private Task?> GetSubsystemStatsAsync(int idWell, DateTime startDate, From 24637f52540618aa6cb57d8370fb2c6839c856a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Tue, 15 Aug 2023 14:20:28 +0500 Subject: [PATCH 05/13] =?UTF-8?q?=D0=92=D1=8B=D0=BD=D0=B5=D1=81=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D0=B8=D0=BA=D1=83=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=D1=82=D0=B2=D0=BE=D0=BB=D0=B0?= =?UTF-8?q?=20=D1=81=D0=BA=D0=B2=D0=B0=D0=B6=D0=B8=D0=BD=D1=8B=20=D0=B2=20?= =?UTF-8?q?=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D1=81?= =?UTF-8?q?=D0=B5=D1=80=D0=B2=D0=B8=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repositories/IWellOperationRepository.cs | 17 --- AsbCloudApp/Services/IWellboreService.cs | 30 +++++ AsbCloudInfrastructure/DependencyInjection.cs | 2 + .../Repository/WellOperationRepository.cs | 85 ------------- .../Services/WellboreService.cs | 117 ++++++++++++++++++ .../Controllers/WellboreController.cs | 12 +- 6 files changed, 155 insertions(+), 108 deletions(-) create mode 100644 AsbCloudApp/Services/IWellboreService.cs create mode 100644 AsbCloudInfrastructure/Services/WellboreService.cs diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs index 634bc56f..b02d3e42 100644 --- a/AsbCloudApp/Repositories/IWellOperationRepository.cs +++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs @@ -73,23 +73,6 @@ namespace AsbCloudApp.Repositories Task> GetGroupOperationsStatAsync( WellOperationRequest request, CancellationToken token); - - /// - /// Получение ствола скважины - /// - /// - /// - /// - /// - Task GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken); - - /// - /// Получение стволов скважин - /// - /// - /// - /// - Task> GetWellboresAsync(WellboreRequest request, CancellationToken cancellationToken); /// /// Добавить несколько операций за один раз diff --git a/AsbCloudApp/Services/IWellboreService.cs b/AsbCloudApp/Services/IWellboreService.cs new file mode 100644 index 00000000..f42485ae --- /dev/null +++ b/AsbCloudApp/Services/IWellboreService.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data; +using AsbCloudApp.Requests; + +namespace AsbCloudApp.Services; + +/// +/// Сервис для ствола скважины +/// +public interface IWellboreService +{ + /// + /// Получение ствола скважины + /// + /// + /// + /// + /// + Task GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken); + + /// + /// Получение стволов скважин + /// + /// + /// + /// + Task> GetWellboresAsync(WellboreRequest request, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 601d05e7..bb894d63 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -222,6 +222,8 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); + services.AddTransient(); + return services; } diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index ce0b68af..f0eb5f6d 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -255,91 +255,6 @@ namespace AsbCloudInfrastructure.Repository return dtos; } - public async Task GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken) - { - var well = await db.Wells.Include(w => w.WellOperations) - .FirstOrDefaultAsync(w => w.Id == idWell, cancellationToken); - - var section = await db.WellSectionTypes - .FirstOrDefaultAsync(w => w.Id == idSection, cancellationToken); - - if (well is null || section is null) - return null; - - var factOperations = well.WellOperations - .Where(o => o.IdType == WellOperation.IdOperationTypeFact && - o.IdWellSectionType == section.Id) - .OrderBy(o => o.DateStart); - - if (!factOperations.Any()) - return null; - - var firstOperation = factOperations.First(); - var lastOperation = factOperations.Last(); - - return new WellboreDto - { - Id = section.Id, - Name = section.Caption, - IdWell = well.Id, - WellName = well.Caption, - IdWellState = well.IdState, - IdWellTelemetry = well.IdTelemetry, - WellTimezone = well.Timezone.Adapt(), - DepthFrom = firstOperation.DepthStart, - DepthTo = lastOperation.DepthEnd, - DateFrom = firstOperation.DateStart, - DateTo = lastOperation.DateStart.AddHours(lastOperation.DurationHours), - }; - } - - public async Task> GetWellboresAsync(WellboreRequest request, CancellationToken cancellationToken) - { - var wellbores = new List(); - var skip = request.Skip ?? 0; - var take = request.Take ?? 10; - - var sections = GetSectionTypes() - .ToDictionary(w => w.Id, w => w); - - foreach (var (idWell, idSection) in request.Ids) - { - var well = await db.Wells.Include(w => w.WellOperations) - .FirstOrDefaultAsync(w => w.Id == idWell, cancellationToken); - - if (well is null) - continue; - - var factOperations = well.WellOperations - .Where(o => o.IdType == WellOperation.IdOperationTypeFact) - .OrderBy(o => o.DateStart) - .GroupBy(o => o.IdWellSectionType); - - if(idSection.HasValue) - factOperations = factOperations.Where(w => w.Key == idSection); - - wellbores.AddRange(from factOperation in factOperations - let firstOperation = factOperation.First() - let lastOperation = factOperation.Last() - select new WellboreDto - { - Id = sections[factOperation.Key].Id, - Name = sections[factOperation.Key].Caption, - IdWell = well.Id, - WellName = well.Caption, - IdWellState = well.IdState, - IdWellTelemetry = well.IdTelemetry, - WellTimezone = well.Timezone.Adapt(), - DepthFrom = firstOperation.DepthStart, - DepthTo = lastOperation.DepthEnd, - DateFrom = firstOperation.DateStart, - DateTo = lastOperation.DateStart.AddHours(lastOperation.DurationHours), - }); - } - - return wellbores.Skip(skip).Take(take); - } - /// public async Task InsertRangeAsync( IEnumerable wellOperationDtos, diff --git a/AsbCloudInfrastructure/Services/WellboreService.cs b/AsbCloudInfrastructure/Services/WellboreService.cs new file mode 100644 index 00000000..eb4fa767 --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellboreService.cs @@ -0,0 +1,117 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using AsbCloudDb.Model; +using Mapster; + +namespace AsbCloudInfrastructure.Services; + +public class WellboreService : IWellboreService +{ + private readonly IWellService wellService; + private readonly IWellOperationRepository wellOperationRepository; + + public WellboreService(IWellService wellService, IWellOperationRepository wellOperationRepository) + { + this.wellService = wellService; + this.wellOperationRepository = wellOperationRepository; + } + + public async Task GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken) + { + var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken); + + var section = wellOperationRepository.GetSectionTypes() + .FirstOrDefault(w => w.Id == idSection); + + if (well is null || section is null) + return null; + + var factOperations = await GetFactOperationsAsync(idWell, idSection, cancellationToken); + + if (!factOperations.Any()) + return null; + + var firstOperation = factOperations.First(); + var lastOperation = factOperations.Last(); + + return new WellboreDto + { + Id = section.Id, + Name = section.Caption, + IdWell = well.Id, + WellName = well.Caption, + IdWellState = well.IdState, + IdWellTelemetry = well.IdTelemetry, + WellTimezone = well.Timezone.Adapt(), + DepthFrom = firstOperation.DepthStart, + DepthTo = lastOperation.DepthEnd, + DateFrom = firstOperation.DateStart, + DateTo = lastOperation.DateStart.AddHours(lastOperation.DurationHours), + }; + } + + public async Task> GetWellboresAsync(WellboreRequest request, + CancellationToken cancellationToken) + { + var wellbores = new List(); + var skip = request.Skip ?? 0; + var take = request.Take ?? 10; + + var sections = wellOperationRepository.GetSectionTypes() + .ToDictionary(w => w.Id, w => w); + + foreach (var (idWell, idSection) in request.Ids) + { + var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken); + + if (well is null) + continue; + + var factOperations = (await GetFactOperationsAsync(well.Id, idSection, cancellationToken)) + .GroupBy(o => o.IdWellSectionType); + + wellbores.AddRange(from factOperation in factOperations + let firstOperation = factOperation.First() + let lastOperation = factOperation.Last() + select new WellboreDto + { + Id = sections[factOperation.Key].Id, + Name = sections[factOperation.Key].Caption, + IdWell = well.Id, + WellName = well.Caption, + IdWellState = well.IdState, + IdWellTelemetry = well.IdTelemetry, + WellTimezone = well.Timezone.Adapt(), + DepthFrom = firstOperation.DepthStart, + DepthTo = lastOperation.DepthEnd, + DateFrom = firstOperation.DateStart, + DateTo = lastOperation.DateStart.AddHours(lastOperation.DurationHours), + }); + } + + return wellbores.Skip(skip).Take(take); + } + + private async Task> GetFactOperationsAsync(int idWell, int? idSection, + CancellationToken cancellationToken) + { + var request = new WellOperationRequest + { + IdWell = idWell, + OperationType = WellOperation.IdOperationTypeFact, + SortFields = new[] { "DateStart asc" }, + }; + + if (idSection.HasValue) + request.SectionTypeIds = new[] { idSection.Value }; + + return (await wellOperationRepository.GetAsync(request, cancellationToken)) + .OrderBy(o => o.DateStart); + } +} \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/WellboreController.cs b/AsbCloudWebApi/Controllers/WellboreController.cs index aeca9e8d..2780ed5b 100644 --- a/AsbCloudWebApi/Controllers/WellboreController.cs +++ b/AsbCloudWebApi/Controllers/WellboreController.cs @@ -3,8 +3,8 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Exceptions; -using AsbCloudApp.Repositories; using AsbCloudApp.Requests; +using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -19,11 +19,11 @@ namespace AsbCloudWebApi.Controllers; [Route("api/well/[controller]")] public class WellboreController : ControllerBase { - private readonly IWellOperationRepository wellOperationRepository; + private readonly IWellboreService wellboreService; - public WellboreController(IWellOperationRepository wellOperationRepository) + public WellboreController(IWellboreService wellboreService) { - this.wellOperationRepository = wellOperationRepository; + this.wellboreService = wellboreService; } /// @@ -39,7 +39,7 @@ public class WellboreController : ControllerBase [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task GetAsync(int idWell, int idSection, CancellationToken cancellationToken) { - var wellbore = await wellOperationRepository.GetWellboreAsync(idWell, idSection, cancellationToken); + var wellbore = await wellboreService.GetWellboreAsync(idWell, idSection, cancellationToken); if (wellbore is null) return NoContent(); @@ -69,7 +69,7 @@ public class WellboreController : ControllerBase Take = take }; - return Ok(await wellOperationRepository.GetWellboresAsync(request, cancellationToken)); + return Ok(await wellboreService.GetWellboresAsync(request, cancellationToken)); } private static IEnumerable<(int, int?)> ParseIds(IEnumerable ids) From b43a8691f2b4dee6f81dad9653bf785234cd61e0 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 15 Aug 2023 16:08:51 +0500 Subject: [PATCH 06/13] WellboreService refactoring --- AsbCloudApp/Data/WellboreDto.cs | 8 +- .../Services/WellboreService.cs | 90 +++++++------------ .../Controllers/WellboreController.cs | 39 ++++---- AsbCloudWebApi/Rest/wellbore.http | 15 ++++ 4 files changed, 70 insertions(+), 82 deletions(-) create mode 100644 AsbCloudWebApi/Rest/wellbore.http diff --git a/AsbCloudApp/Data/WellboreDto.cs b/AsbCloudApp/Data/WellboreDto.cs index 091f5b07..e64a188f 100644 --- a/AsbCloudApp/Data/WellboreDto.cs +++ b/AsbCloudApp/Data/WellboreDto.cs @@ -45,20 +45,20 @@ public class WellboreDto /// /// Начальная глубина ствола /// - public double DepthFrom { get; set; } + public double DepthStart { get; set; } /// /// Конечная глубина скважины /// - public double DepthTo { get; set; } + public double DepthEnd { get; set; } /// /// Дата начала первой операции /// - public DateTimeOffset DateFrom { get; set; } + public DateTimeOffset DateStart { get; set; } /// /// Дата завершения последней операции /// - public DateTimeOffset DateTo { get; set; } + public DateTimeOffset DateEnd { get; set; } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellboreService.cs b/AsbCloudInfrastructure/Services/WellboreService.cs index eb4fa767..727878dc 100644 --- a/AsbCloudInfrastructure/Services/WellboreService.cs +++ b/AsbCloudInfrastructure/Services/WellboreService.cs @@ -7,7 +7,6 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; -using Mapster; namespace AsbCloudInfrastructure.Services; @@ -24,81 +23,59 @@ public class WellboreService : IWellboreService public async Task GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken) { - var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken); - - var section = wellOperationRepository.GetSectionTypes() - .FirstOrDefault(w => w.Id == idSection); - - if (well is null || section is null) - return null; - - var factOperations = await GetFactOperationsAsync(idWell, idSection, cancellationToken); - - if (!factOperations.Any()) - return null; - - var firstOperation = factOperations.First(); - var lastOperation = factOperations.Last(); - - return new WellboreDto + var request = new WellboreRequest { - Id = section.Id, - Name = section.Caption, - IdWell = well.Id, - WellName = well.Caption, - IdWellState = well.IdState, - IdWellTelemetry = well.IdTelemetry, - WellTimezone = well.Timezone.Adapt(), - DepthFrom = firstOperation.DepthStart, - DepthTo = lastOperation.DepthEnd, - DateFrom = firstOperation.DateStart, - DateTo = lastOperation.DateStart.AddHours(lastOperation.DurationHours), + Ids = new (int, int?)[] { (idWell, idSection) }, + Take = 1, }; - } + var data = await GetWellboresAsync(request, cancellationToken); + return data.FirstOrDefault(); + } public async Task> GetWellboresAsync(WellboreRequest request, CancellationToken cancellationToken) { - var wellbores = new List(); + var wellbores = new List(request.Ids.Count()); var skip = request.Skip ?? 0; var take = request.Take ?? 10; var sections = wellOperationRepository.GetSectionTypes() .ToDictionary(w => w.Id, w => w); - foreach (var (idWell, idSection) in request.Ids) + var ids = request.Ids.GroupBy(i => i.idWell); + + foreach (var id in ids) { - var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken); + var well = await wellService.GetOrDefaultAsync(id.Key, cancellationToken); if (well is null) continue; - var factOperations = (await GetFactOperationsAsync(well.Id, idSection, cancellationToken)) - .GroupBy(o => o.IdWellSectionType); + var wellOperations = await GetFactOperationsAsync(well.Id, id.Select(i => i.idSection), cancellationToken); + var groupedOperations = wellOperations.GroupBy(o => o.IdWellSectionType); + var wellWellbores = groupedOperations.Select(group => new WellboreDto { + Id = group.Key, + IdWell = well.Id, + IdWellState = well.IdState, + IdWellTelemetry = well.IdTelemetry, + Name = sections[group.Key].Caption, + WellName = well.Caption, + WellTimezone = well.Timezone, - wellbores.AddRange(from factOperation in factOperations - let firstOperation = factOperation.First() - let lastOperation = factOperation.Last() - select new WellboreDto - { - Id = sections[factOperation.Key].Id, - Name = sections[factOperation.Key].Caption, - IdWell = well.Id, - WellName = well.Caption, - IdWellState = well.IdState, - IdWellTelemetry = well.IdTelemetry, - WellTimezone = well.Timezone.Adapt(), - DepthFrom = firstOperation.DepthStart, - DepthTo = lastOperation.DepthEnd, - DateFrom = firstOperation.DateStart, - DateTo = lastOperation.DateStart.AddHours(lastOperation.DurationHours), - }); + DateStart = group.Min(operation => operation.DateStart), + DateEnd = group.Max(operation => operation.DateStart.AddHours(operation.DurationHours)), + DepthStart = group.Min(operation => operation.DepthStart), + DepthEnd = group.Max(operation => operation.DepthEnd), + }); + wellbores.AddRange(wellWellbores); } - return wellbores.Skip(skip).Take(take); + return wellbores + .OrderBy(w =>w.IdWell).ThenBy(w=>w.Id) + .Skip(skip).Take(take); } - private async Task> GetFactOperationsAsync(int idWell, int? idSection, + private async Task> GetFactOperationsAsync(int idWell, IEnumerable idsSections, CancellationToken cancellationToken) { var request = new WellOperationRequest @@ -108,8 +85,9 @@ public class WellboreService : IWellboreService SortFields = new[] { "DateStart asc" }, }; - if (idSection.HasValue) - request.SectionTypeIds = new[] { idSection.Value }; + request.SectionTypeIds = idsSections.All(i => i.HasValue) + ? idsSections.Select(i => i!.Value) + : null; return (await wellOperationRepository.GetAsync(request, cancellationToken)) .OrderBy(o => o.DateStart); diff --git a/AsbCloudWebApi/Controllers/WellboreController.cs b/AsbCloudWebApi/Controllers/WellboreController.cs index 2780ed5b..7c8bdaf3 100644 --- a/AsbCloudWebApi/Controllers/WellboreController.cs +++ b/AsbCloudWebApi/Controllers/WellboreController.cs @@ -1,10 +1,12 @@ using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Exceptions; using AsbCloudApp.Requests; using AsbCloudApp.Services; +using AsbCloudDb.Model; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -64,34 +66,27 @@ public class WellboreController : ControllerBase { var request = new WellboreRequest { - Ids = ParseIds(ids), + Ids = ids.Select(id => ParseId(id)), Skip = skip, Take = take }; return Ok(await wellboreService.GetWellboresAsync(request, cancellationToken)); } - - private static IEnumerable<(int, int?)> ParseIds(IEnumerable ids) + + private static (int, int?) ParseId(string id) { - var result = new List<(int, int?)>(); - - foreach (var id in ids) + var idPair = id.Split(','); + if (!int.TryParse(idPair[0], out var idWell)) + throw new ArgumentInvalidException($"Не удалось получить Id скважины \"{idPair[0]}\"", nameof(id)); + + if (idPair.Length > 1) { - var idPair = id.Split(','); - - if (!int.TryParse(idPair[0], out var idWell)) - throw new ArgumentInvalidException("Не удалось получить Id скважины", nameof(ids)); - - if (idPair.Length < 2 || !int.TryParse(idPair[1], out var idWellSectionType)) - { - result.Add((idWell, null)); - continue; - } - - result.Add((idWell, idWellSectionType)); - } - - return result; - } + if (int.TryParse(idPair[1], out int idWellSectionType)) + return (idWell, idWellSectionType); + else + throw new ArgumentInvalidException($"Не удалось получить Id ствола \"{idPair[1]}\"", nameof(id)); + } + return (idWell, null); + } } \ No newline at end of file diff --git a/AsbCloudWebApi/Rest/wellbore.http b/AsbCloudWebApi/Rest/wellbore.http new file mode 100644 index 00000000..9a7918ac --- /dev/null +++ b/AsbCloudWebApi/Rest/wellbore.http @@ -0,0 +1,15 @@ +@baseUrl = http://127.0.0.1:5000 +@contentType = application/json +@auth = Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2NjI1NDgxNjIsImV4cCI6MTY5NDEwNTc2MiwiaXNzIjoiYSIsImF1ZCI6ImEifQ.OEAlNzxi7Jat6pzDBTAjTbChskc-tdJthJexyWwwUKE + +@uid = 20210101_000000000 +@idCluster = 1 +@idWell = 1 + +# https://marketplace.visualstudio.com/items?itemName=humao.rest-client + +### +GET {{baseUrl}}/api/well/wellbore?ids=1,2 +Content-Type: {{contentType}} +accept: */* +Authorization: {{auth}} From 3a1779de947ca95bf470b9347dc0f83561387f48 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 15 Aug 2023 17:08:33 +0500 Subject: [PATCH 07/13] TelemetryDataBaseController add GetRangeAsync method. for witsml --- AsbCloudApp/Services/ITelemetryDataService.cs | 10 +++++ .../Services/SAUB/TelemetryDataBaseService.cs | 43 ++++++++++++++++++- .../SAUB/TelemetryDataBaseController.cs | 32 ++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/AsbCloudApp/Services/ITelemetryDataService.cs b/AsbCloudApp/Services/ITelemetryDataService.cs index 20ac7f90..c1704509 100644 --- a/AsbCloudApp/Services/ITelemetryDataService.cs +++ b/AsbCloudApp/Services/ITelemetryDataService.cs @@ -26,6 +26,16 @@ namespace AsbCloudApp.Services DateTime dateBegin = default, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default); + /// + /// Получение статистики за период + /// + /// + /// + /// + /// + /// + Task GetRangeAsync(int idWell, DateTimeOffset start, DateTimeOffset end, CancellationToken token); + /// /// добавить/изменить данные тех. процесса (используется панелью) /// diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs index ffd6416c..8d76ee70 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs @@ -1,4 +1,5 @@ -using AsbCloudApp.Services; +using AsbCloudApp.Data; +using AsbCloudApp.Services; using AsbCloudDb; using AsbCloudDb.Model; using Microsoft.EntityFrameworkCore; @@ -13,7 +14,7 @@ namespace AsbCloudInfrastructure.Services.SAUB { public abstract class TelemetryDataBaseService : ITelemetryDataService where TDto : AsbCloudApp.Data.ITelemetryData - where TEntity : class, ITelemetryData + where TEntity : class, AsbCloudDb.Model.ITelemetryData { protected readonly IAsbCloudDbContext db; protected readonly ITelemetryService telemetryService; @@ -146,6 +147,44 @@ namespace AsbCloudInfrastructure.Services.SAUB return dtos; } + /// + public virtual async Task GetRangeAsync( + int idWell, + DateTimeOffset start, + DateTimeOffset end, + CancellationToken token) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + if (telemetry is null) + return default; + + var timezone = telemetryService.GetTimezone(telemetry.Id); + var startUtc = start.ToOffset(TimeSpan.Zero); + var endUtc = end.ToOffset(TimeSpan.Zero); + + var dbSet = db.Set(); + var query = dbSet + .Where(i => i.IdTelemetry == telemetry.Id) + .Where(i => i.DateTime >= startUtc) + .Where(i => i.DateTime <= endUtc) + .GroupBy(i => i.IdTelemetry) + .Select(g => new + { + DateStart = g.Min(i => i.DateTime), + DateEnd = g.Max(i => i.DateTime), + }); + + var data = await query.FirstOrDefaultAsync(token); + if (data is null) + return default; + + return new DatesRangeDto + { + From = data.DateStart.ToRemoteDateTime(timezone.Hours), + To = data.DateEnd.ToRemoteDateTime(timezone.Hours), + }; + } + public abstract TDto Convert(TEntity src, double timezoneOffset); public abstract TEntity Convert(TDto src, double timezoneOffset); diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs index 05af2b9a..f80693a1 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -95,6 +96,37 @@ namespace AsbCloudWebApi.Controllers.SAUB return Ok(content); } + /// + /// Возвращает диапазон дат за которые есть телеметрия за период времени + /// + /// + /// + /// + /// + /// + [HttpGet("{idWell}/dateRange")] + public virtual async Task> GetRangeAsync( + [FromRoute] int idWell, + [Required] DateTimeOffset start, + [Required] DateTimeOffset end, + CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + + if (!isCompanyOwnsWell) + return Forbid(); + + var content = await telemetryDataService.GetRangeAsync(idWell, start, end, token); + + return Ok(content); + } + /// /// Возвращает диапазон дат сохраненных данных. /// From a36736731b03c08ff2682aca92867c06d14ee907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Tue, 15 Aug 2023 17:36:47 +0500 Subject: [PATCH 08/13] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/ProcessMap/ProcessMapPlanDto.cs | 5 ----- .../Services/ProcessMap/ProcessMapPlanImportService.cs | 4 +++- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapPlanDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapPlanDto.cs index 8849e13d..0a4c1044 100644 --- a/AsbCloudApp/Data/ProcessMap/ProcessMapPlanDto.cs +++ b/AsbCloudApp/Data/ProcessMap/ProcessMapPlanDto.cs @@ -87,10 +87,5 @@ namespace AsbCloudApp.Data.ProcessMap /// Плановый процент использования spin master /// public double UsageSpin { get; set; } - - /// - /// DTO типа секции - /// - public WellSectionTypeDto WellSectionType { get; set; } = null!; } } diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs index dc5d87b3..fd0ce38b 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs @@ -75,6 +75,8 @@ public class ProcessMapPlanImportService : IProcessMapPlanImportService public async Task ExportAsync(int idWell, CancellationToken cancellationToken) { + sections = (await wellSectionTypeRepository.GetAllAsync(cancellationToken)).ToArray(); + var processMapPlans = (await processMapPlanRepository.GetByIdWellAsync(idWell, cancellationToken)).ToArray(); @@ -120,7 +122,7 @@ public class ProcessMapPlanImportService : IProcessMapPlanImportService private void AddToRow(IXLRow row, ProcessMapPlanDto processMap) { - row.Cell(columnWellSectionType).Value = processMap.WellSectionType.Caption; + row.Cell(columnWellSectionType).Value = sections.FirstOrDefault(x => x.Id == processMap.IdWellSectionType)?.Caption; row.Cell(columnMode).Value = GetModeCaption(processMap.IdMode); row.Cell(columnDepthStart).Value = processMap.DepthStart; row.Cell(columnDepthEnd).Value = processMap.DepthEnd; From 5ff75e519fb5d68391eb519a3e586c0a6e76f1b8 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 15 Aug 2023 17:43:49 +0500 Subject: [PATCH 09/13] fix wellbore controller route --- AsbCloudWebApi/Controllers/WellboreController.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AsbCloudWebApi/Controllers/WellboreController.cs b/AsbCloudWebApi/Controllers/WellboreController.cs index 7c8bdaf3..e9a590a0 100644 --- a/AsbCloudWebApi/Controllers/WellboreController.cs +++ b/AsbCloudWebApi/Controllers/WellboreController.cs @@ -6,7 +6,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Exceptions; using AsbCloudApp.Requests; using AsbCloudApp.Services; -using AsbCloudDb.Model; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -18,7 +17,7 @@ namespace AsbCloudWebApi.Controllers; /// [Authorize] [ApiController] -[Route("api/well/[controller]")] +[Route("api/[controller]")] public class WellboreController : ControllerBase { private readonly IWellboreService wellboreService; From d62866919fe9e5111a7aa1a119615934ec204f54 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 15 Aug 2023 18:00:35 +0500 Subject: [PATCH 10/13] refactor WellboreDto --- AsbCloudApp/Data/WellDto.cs | 17 +++++++++ AsbCloudApp/Data/WellboreDto.cs | 35 ++++--------------- .../Services/WellboreService.cs | 10 ++---- 3 files changed, 26 insertions(+), 36 deletions(-) diff --git a/AsbCloudApp/Data/WellDto.cs b/AsbCloudApp/Data/WellDto.cs index 4ffd262e..b347bdd8 100644 --- a/AsbCloudApp/Data/WellDto.cs +++ b/AsbCloudApp/Data/WellDto.cs @@ -5,6 +5,23 @@ using System.Linq; namespace AsbCloudApp.Data { + /// + /// базовая информация о скважине + /// + public class WellWithTimezoneDto : WellInfoDto + { + /// + [Required] + public SimpleTimezoneDto Timezone { get; set; } = null!; + + /// + /// 0 - неизвестно, + /// 1 - в работе, + /// 2 - завершена + /// + public int IdState { get; set; } + } + /// /// Скважина /// diff --git a/AsbCloudApp/Data/WellboreDto.cs b/AsbCloudApp/Data/WellboreDto.cs index e64a188f..dbd9b697 100644 --- a/AsbCloudApp/Data/WellboreDto.cs +++ b/AsbCloudApp/Data/WellboreDto.cs @@ -7,41 +7,18 @@ namespace AsbCloudApp.Data; /// public class WellboreDto { - /// - /// Идентификатор - /// - public int Id { get; set; } + public WellWithTimezoneDto Well { get; set; } + + /// + /// Идентификатор + /// + public int Id { get; set; } /// /// Название /// public string Name { get; set; } = null!; - /// - /// Идентификатор скважины - /// - public int IdWell { get; set; } - - /// - /// Состояние скважины - /// - public int IdWellState { get; set; } - - /// - /// Идентификатор телеметрии - /// - public int? IdWellTelemetry { get; set; } - - /// - /// Временная зона скважины - /// - public SimpleTimezoneDto? WellTimezone { get; set; } - - /// - /// Название скважины - /// - public string WellName { get; set; } = null!; - /// /// Начальная глубина ствола /// diff --git a/AsbCloudInfrastructure/Services/WellboreService.cs b/AsbCloudInfrastructure/Services/WellboreService.cs index 727878dc..79ef8a3c 100644 --- a/AsbCloudInfrastructure/Services/WellboreService.cs +++ b/AsbCloudInfrastructure/Services/WellboreService.cs @@ -7,6 +7,7 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; +using Mapster; namespace AsbCloudInfrastructure.Services; @@ -55,13 +56,8 @@ public class WellboreService : IWellboreService var groupedOperations = wellOperations.GroupBy(o => o.IdWellSectionType); var wellWellbores = groupedOperations.Select(group => new WellboreDto { Id = group.Key, - IdWell = well.Id, - IdWellState = well.IdState, - IdWellTelemetry = well.IdTelemetry, Name = sections[group.Key].Caption, - WellName = well.Caption, - WellTimezone = well.Timezone, - + Well = well.Adapt(), DateStart = group.Min(operation => operation.DateStart), DateEnd = group.Max(operation => operation.DateStart.AddHours(operation.DurationHours)), DepthStart = group.Min(operation => operation.DepthStart), @@ -71,7 +67,7 @@ public class WellboreService : IWellboreService } return wellbores - .OrderBy(w =>w.IdWell).ThenBy(w=>w.Id) + .OrderBy(w => w.Well.Id).ThenBy(w => w.Id) .Skip(skip).Take(take); } From ab3ad0ae280c5a6c9917155bb91c638425a05a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Wed, 16 Aug 2023 15:59:25 +0500 Subject: [PATCH 11/13] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B7=D0=B0=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D1=81=D0=B5=D0=BA=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/ProcessMap/ProcessMapPlanImportService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs index fd0ce38b..21f118a8 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs @@ -122,7 +122,7 @@ public class ProcessMapPlanImportService : IProcessMapPlanImportService private void AddToRow(IXLRow row, ProcessMapPlanDto processMap) { - row.Cell(columnWellSectionType).Value = sections.FirstOrDefault(x => x.Id == processMap.IdWellSectionType)?.Caption; + row.Cell(columnWellSectionType).Value = sections.First(x => x.Id == processMap.IdWellSectionType).Caption; row.Cell(columnMode).Value = GetModeCaption(processMap.IdMode); row.Cell(columnDepthStart).Value = processMap.DepthStart; row.Cell(columnDepthEnd).Value = processMap.DepthEnd; From 2ee10e8e704639ad7a43acde9691deb3d408605e Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Mon, 21 Aug 2023 15:51:51 +0500 Subject: [PATCH 12/13] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D0=BF=D0=BE=20=D0=BC=D0=BE=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=BA=D0=B5=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D0=B2:=20=D0=B2=20=D1=81=D0=BF=D0=B8=D1=81=D0=BE=D0=BA?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B0=D0=BA=D1=82=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=BB=D0=B6=D0=BD=D1=8B=20=D0=BF=D0=BE=D0=BF=D0=B0?= =?UTF-8?q?=D0=B4=D0=B0=D1=82=D1=8C=20=D1=82=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE?= =?UTF-8?q?=20=D0=B0=D0=BA=D1=82=D0=B8=D0=B2=D0=BD=D1=8B=D0=B5=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/WellContactService.cs | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/AsbCloudInfrastructure/Services/WellContactService.cs b/AsbCloudInfrastructure/Services/WellContactService.cs index a8e280da..261ed9f9 100644 --- a/AsbCloudInfrastructure/Services/WellContactService.cs +++ b/AsbCloudInfrastructure/Services/WellContactService.cs @@ -29,18 +29,21 @@ namespace AsbCloudInfrastructure.Services { Caption = c.Caption, Id = c.Id, - Users = c.Users.Select(u => new UserContactDto() - { - Id = u.Id, - Name = u.Name, - Patronymic = u.Patronymic, - Surname = u.Surname, - Company = u.Company.Adapt(), - Email = u.Email, - Phone = u.Phone, - Position = u.Position, - IsContact = u.RelationContactsWells.Any(rel => rel.IdWell == wellId) - }) + Users = c.Users + .Where(u => u.IdState == 1) + .OrderBy(u => u.Surname) + .Select(u => new UserContactDto() + { + Id = u.Id, + Name = u.Name, + Patronymic = u.Patronymic, + Surname = u.Surname, + Company = u.Company.Adapt(), + Email = u.Email, + Phone = u.Phone, + Position = u.Position, + IsContact = u.RelationContactsWells.Any(rel => rel.IdWell == wellId) + }) }); var entities = await query.AsNoTracking() From 6aa643b0d35d055fb59d57ede60766cc7036cecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Wed, 23 Aug 2023 11:38:54 +0500 Subject: [PATCH 13/13] =?UTF-8?q?=D0=9D=D0=B5=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=D1=8C=D0=BD=D0=BE=20=D1=81=D1=87=D0=B8=D1=82=D0=B0?= =?UTF-8?q?=D0=BB=D1=81=D1=8F=20Count=20=D0=BF=D1=80=D0=B8=20=D1=84=D0=BE?= =?UTF-8?q?=D1=80=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8=20?= =?UTF-8?q?=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0=20=D1=81=D1=83=D1=82=D0=BE?= =?UTF-8?q?=D1=87=D0=BD=D1=8B=D1=85=20=D0=BE=D1=82=D1=87=D1=91=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=20+=20=D1=84=D0=B8=D0=BA=D1=81=20=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B2?= =?UTF-8?q?=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B8?= =?UTF-8?q?=D0=BD=D1=82=D0=B5=D1=80=D0=B2=D0=B0=D0=BB=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AutoGeneratedDailyReportService.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs b/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs index 03a19c44..0e364319 100644 --- a/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs +++ b/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs @@ -66,8 +66,6 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService if (datesRange is null) return result; - - result.Count = (int)(Math.Ceiling((datesRange.To - DateTime.UnixEpoch).TotalDays) - Math.Floor((datesRange.From - DateTime.UnixEpoch).TotalDays)); if (request.StartDate.HasValue) { @@ -87,6 +85,9 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService datesRange.To = finishDate; } + if (datesRange.From.AddDays(result.Skip) <= datesRange.To) + result.Count = (int)(Math.Ceiling((datesRange.To - DateTime.UnixEpoch).TotalDays) - Math.Floor((datesRange.From - DateTime.UnixEpoch).TotalDays)); + for (int day = result.Skip; (day - result.Skip) < result.Take && (datesRange.From.AddDays(day)) <= datesRange.To; day++) { var reportDate = DateOnly.FromDateTime(datesRange.From.AddDays(day)); @@ -149,8 +150,8 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService return new DatesRangeDto { - From = factOperations.Min(o => o.DateStart), - To = factOperations.Max(o => o.DateStart) + From = factOperations.Min(o => o.DateStart).Date, + To = factOperations.Max(o => o.DateStart).Date }; }