From 16645d053ad9c1ac790022b3c2348e9653b7ef76 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?= Date: Fri, 22 Mar 2024 10:42:48 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=BE=D0=B2=D0=B0=D1=8F=20=D1=80=D0=B5?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D1=8D=D0=BA?= =?UTF-8?q?=D0=BF=D0=BE=D1=80=D1=82=D0=B0/=D0=B8=D0=BC=D0=BF=D0=BE=D1=80?= =?UTF-8?q?=D1=82=D0=B0=20=D0=93=D0=93=D0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Изменено апи 2. Добавлен парсер для ГГД 3. Добавлен ссервис экспорта ГГД --- AsbCloudApp/Data/ParserResultDto.cs | 5 + AsbCloudApp/Data/ValidationResultDto.cs | 2 +- .../WellOperationExportRequest.cs | 20 + .../WellOperationParserRequest.cs | 29 + .../AsbCloudInfrastructure.csproj | 12 +- AsbCloudInfrastructure/DependencyInjection.cs | 15 +- .../WellOperationPlanTemplate.cs | 26 + .../WellOperationExportServiceFactory.cs | 43 + .../Factories/WellOperationParserFactory.cs | 43 + .../Templates/WellOperationPlanTemplate.xlsx | Bin 0 -> 68320 bytes .../WellOperations/WellOperationExport.cs | 51 + .../WellOperations/WellOperationParser.cs | 77 ++ .../AsbCloudWebApi.IntegrationTests.csproj | 2 + .../Clients/IWellOperationClient.cs | 29 +- .../Files/FactWellOperations.xlsx | Bin 0 -> 45419 bytes .../Files/PlanWellOperations.xlsx | Bin 0 -> 68419 bytes .../WellOperationControllerTest.cs | 107 +- .../WellOperationExportServiceTest.cs | 216 ---- .../Controllers/WellOperationController.cs | 928 +++++++----------- 19 files changed, 729 insertions(+), 876 deletions(-) create mode 100644 AsbCloudApp/Requests/ExportOptions/WellOperationExportRequest.cs create mode 100644 AsbCloudApp/Requests/ParserOptions/WellOperationParserRequest.cs create mode 100644 AsbCloudInfrastructure/Services/ExcelServices/Templates/WellOperations/WellOperationPlanTemplate.cs create mode 100644 AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs create mode 100644 AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationParserFactory.cs create mode 100644 AsbCloudInfrastructure/Services/WellOperations/Templates/WellOperationPlanTemplate.xlsx create mode 100644 AsbCloudInfrastructure/Services/WellOperations/WellOperationExport.cs create mode 100644 AsbCloudInfrastructure/Services/WellOperations/WellOperationParser.cs create mode 100644 AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/Files/FactWellOperations.xlsx create mode 100644 AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/Files/PlanWellOperations.xlsx rename AsbCloudWebApi.IntegrationTests/Controllers/{ => WellOperations}/WellOperationControllerTest.cs (55%) delete mode 100644 AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs diff --git a/AsbCloudApp/Data/ParserResultDto.cs b/AsbCloudApp/Data/ParserResultDto.cs index 5b6eca8d..ffb24d50 100644 --- a/AsbCloudApp/Data/ParserResultDto.cs +++ b/AsbCloudApp/Data/ParserResultDto.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace AsbCloudApp.Data; @@ -9,4 +10,8 @@ namespace AsbCloudApp.Data; public class ParserResultDto : ValidationResultDto>> where TDto : class, IId { + /// + /// Объекты полученные из файла + /// + public override IEnumerable> Item { get; set; } = Enumerable.Empty>(); } \ No newline at end of file diff --git a/AsbCloudApp/Data/ValidationResultDto.cs b/AsbCloudApp/Data/ValidationResultDto.cs index 0116fe0a..1fe0f918 100644 --- a/AsbCloudApp/Data/ValidationResultDto.cs +++ b/AsbCloudApp/Data/ValidationResultDto.cs @@ -18,7 +18,7 @@ public class ValidationResultDto /// /// Объект валидации /// - public T Item { get; set; } = null!; + public virtual T Item { get; set; } = null!; /// /// Предупреждения diff --git a/AsbCloudApp/Requests/ExportOptions/WellOperationExportRequest.cs b/AsbCloudApp/Requests/ExportOptions/WellOperationExportRequest.cs new file mode 100644 index 00000000..facbba72 --- /dev/null +++ b/AsbCloudApp/Requests/ExportOptions/WellOperationExportRequest.cs @@ -0,0 +1,20 @@ +namespace AsbCloudApp.Requests.ExportOptions; + +/// +/// Параметры экспорта ГГД +/// +public class WellOperationExportRequest : WellRelatedExportRequest +{ + /// + public WellOperationExportRequest(int idWell, + int idType) + : base(idWell) + { + IdType = idType; + } + + /// + /// Тип операций + /// + public int IdType { get; } +} \ No newline at end of file diff --git a/AsbCloudApp/Requests/ParserOptions/WellOperationParserRequest.cs b/AsbCloudApp/Requests/ParserOptions/WellOperationParserRequest.cs new file mode 100644 index 00000000..efb9aad2 --- /dev/null +++ b/AsbCloudApp/Requests/ParserOptions/WellOperationParserRequest.cs @@ -0,0 +1,29 @@ +using AsbCloudApp.Data; + +namespace AsbCloudApp.Requests.ParserOptions; + +/// +/// Параметры парсинга ГГД +/// +public class WellOperationParserRequest : WellRelatedParserRequest +{ + /// + public WellOperationParserRequest(int idWell, + int idType, + SimpleTimezoneDto wellTimezone) + : base(idWell) + { + IdType = idType; + WellTimezone = wellTimezone; + } + + /// + /// Тип операции + /// + public int IdType { get; } + + /// + /// Часовой пояс в котором находится скважина + /// + public SimpleTimezoneDto WellTimezone { get; } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj index 0d56b6bd..371127c4 100644 --- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj +++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj @@ -45,11 +45,9 @@ - - - - + + @@ -77,4 +75,10 @@ CommonLibs\AsbWitsInfo.dll + + + + + + diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 5ee77197..bcde8237 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -14,7 +14,6 @@ using AsbCloudApp.Services.DailyReport; using AsbCloudApp.Services.Notifications; using AsbCloudApp.Services.ProcessMaps; using AsbCloudApp.Services.ProcessMaps.WellDrilling; -using AsbCloudApp.Services.WellOperationImport; using AsbCloudDb.Model; using AsbCloudDb.Model.DailyReports.Blocks.TimeBalance; using AsbCloudDb.Model.Manuals; @@ -36,8 +35,6 @@ using AsbCloudInfrastructure.Services.Subsystems; using AsbCloudInfrastructure.Services.Trajectory; using AsbCloudInfrastructure.Services.Trajectory.Export; using AsbCloudInfrastructure.Services.Trajectory.Parser; -using AsbCloudInfrastructure.Services.WellOperationImport; -using AsbCloudInfrastructure.Services.WellOperationImport.FileParser; using AsbCloudInfrastructure.Services.WellOperationService; using Mapster; using Microsoft.EntityFrameworkCore; @@ -46,6 +43,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System; using AsbCloudInfrastructure.Services.ProcessMapPlan.Export; +using AsbCloudInfrastructure.Services.WellOperations.Factories; namespace AsbCloudInfrastructure { @@ -160,7 +158,6 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddScoped(); - services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -270,13 +267,6 @@ namespace AsbCloudInfrastructure services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - services.AddTransient, WellOperationDefaultExcelParser>(); - services.AddTransient, WellOperationGazpromKhantosExcelParser>(); - services.AddTransient(); services.AddTransient(); @@ -300,6 +290,9 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); + + services.AddTransient(); + services.AddTransient(); return services; } diff --git a/AsbCloudInfrastructure/Services/ExcelServices/Templates/WellOperations/WellOperationPlanTemplate.cs b/AsbCloudInfrastructure/Services/ExcelServices/Templates/WellOperations/WellOperationPlanTemplate.cs new file mode 100644 index 00000000..85e88db7 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/Templates/WellOperations/WellOperationPlanTemplate.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using AsbCloudApp.Data.WellOperation; + +namespace AsbCloudInfrastructure.Services.ExcelServices.Templates.WellOperations; + +public class WellOperationPlanTemplate : ITemplateParameters +{ + public string SheetName => "План"; + + public int HeaderRowsCount => 1; + + public string FileName => "WellOperationPlanTemplate.xlsx"; + + public IDictionary Cells => new Dictionary() + { + { nameof(WellOperationDto.WellSectionTypeCaption), new Cell(1, typeof(string)) }, + { nameof(WellOperationDto.OperationCategoryName), new Cell(2, typeof(string)) }, + { nameof(WellOperationDto.CategoryInfo), new Cell(3, typeof(string)) }, + { nameof(WellOperationDto.DepthStart), new Cell(4, typeof(double)) }, + { nameof(WellOperationDto.DepthEnd), new Cell(5, typeof(double)) }, + { nameof(WellOperationDto.DateStart), new Cell(6, typeof(DateTime)) }, + { nameof(WellOperationDto.DurationHours), new Cell(7, typeof(double)) }, + { nameof(WellOperationDto.Comment), new Cell(8, typeof(string)) } + }; +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs b/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs new file mode 100644 index 00000000..1dc1d2a7 --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests.ExportOptions; +using AsbCloudApp.Services; +using AsbCloudApp.Services.Export; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.WellOperations; +using Microsoft.Extensions.DependencyInjection; + +namespace AsbCloudInfrastructure.Services.WellOperations.Factories; + +public class WellOperationExportServiceFactory : IExportServiceFactory +{ + private readonly IDictionary> exportServices; + + public WellOperationExportServiceFactory(IServiceProvider serviceProvider) + { + var wellOperationRepository = serviceProvider.GetRequiredService(); + var wellService = serviceProvider.GetRequiredService(); + + exportServices = new Dictionary> + { + { + WellOperation.IdOperationTypeFact, + () => new WellOperationExport(wellOperationRepository, wellService) + }, + { + WellOperation.IdOperationTypePlan, + () => new WellOperationExport(wellOperationRepository, wellService) + } + }; + } + + public IExportService CreateExportService(int id) + where TOptions : IExportOptionsRequest + { + var parser = exportServices[id].Invoke(); + + return parser as IExportService + ?? throw new ArgumentNullException(nameof(id), "Не удалось экспортировать файл"); + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationParserFactory.cs b/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationParserFactory.cs new file mode 100644 index 00000000..4107a7dd --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationParserFactory.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using AsbCloudApp.Data.WellOperation; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudApp.Services.Parsers; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.WellOperations; +using Microsoft.Extensions.DependencyInjection; + +namespace AsbCloudInfrastructure.Services.WellOperations.Factories; + +public class WellOperationParserFactory : IParserFactory +{ + private readonly IDictionary> parsers; + + public WellOperationParserFactory(IServiceProvider serviceProvider) + { + var wellOperationRepository = serviceProvider.GetRequiredService(); + var categoryRepository = serviceProvider.GetRequiredService(); + + parsers = new Dictionary> + { + { + WellOperation.IdOperationTypeFact, + () => new WellOperationParser(wellOperationRepository, categoryRepository) + }, + { + WellOperation.IdOperationTypePlan, + () => new WellOperationParser(wellOperationRepository, categoryRepository) + } + }; + } + + public IParserService CreateParser(int id) + where TOptions : IParserOptionsRequest + { + var parser = parsers[id].Invoke(); + + return parser as IParserService + ?? throw new ArgumentNullException(nameof(id), "Не удалось распознать файл"); + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperations/Templates/WellOperationPlanTemplate.xlsx b/AsbCloudInfrastructure/Services/WellOperations/Templates/WellOperationPlanTemplate.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c5d53089457739c709596e91c6dafae799099e27 GIT binary patch literal 68320 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 : ExcelExportService + where TTemplate : class, ITemplateParameters, new() +{ + private readonly IWellService wellService; + private readonly IWellOperationRepository wellOperationRepository; + + public WellOperationExport(IWellOperationRepository wellOperationRepository, + IWellService wellService) + { + this.wellOperationRepository = wellOperationRepository; + this.wellService = wellService; + } + + protected override async Task BuildFileNameAsync(WellOperationExportRequest options, CancellationToken token) + { + var caption = await wellService.GetWellCaptionByIdAsync(options.IdWell, token); + + return options.IdType switch + { + WellOperation.IdOperationTypeFact => $"{caption}_Фактические_операции.xlsx", + WellOperation.IdOperationTypePlan => $"{caption}_Плановые_операции.xlsx", + _ => throw new ArgumentOutOfRangeException(nameof(options.IdType)) + }; + } + + protected override Task> GetDtosAsync(WellOperationExportRequest options, CancellationToken token) + { + var request = new WellOperationRequest + { + IdsWell = new[] { options.IdWell }, + OperationType = options.IdType + }; + + return wellOperationRepository.GetAsync(request, token); + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperations/WellOperationParser.cs b/AsbCloudInfrastructure/Services/WellOperations/WellOperationParser.cs new file mode 100644 index 00000000..65bda0a2 --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellOperations/WellOperationParser.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using AsbCloudApp.Data; +using AsbCloudApp.Data.WellOperation; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudInfrastructure.Services.ExcelServices; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; + +namespace AsbCloudInfrastructure.Services.WellOperations; + +public class WellOperationParser : ExcelWellRelatedParser + where TTemplateParameters : class, ITemplateParameters, new() +{ + private readonly IEnumerable sectionTypes; + private readonly IEnumerable categories; + + public WellOperationParser(IWellOperationRepository wellOperationRepository, + IWellOperationCategoryRepository categoryRepository) + { + categories = categoryRepository.Get(false); + sectionTypes = wellOperationRepository.GetSectionTypes(); + } + + public override ParserResultDto Parse(Stream file, WellOperationParserRequest options) + { + var result = base.Parse(file, options); + + foreach (var dto in result.Item) + { + dto.Item.IdWell = options.IdWell; + dto.Item.IdType = options.IdType; + dto.Item.DateStart = new DateTimeOffset(dto.Item.DateStart.DateTime, options.WellTimezone.Offset); + } + + return result; + } + + protected override WellOperationDto BuildDto(IDictionary row, int rowNumber) + { + var dto = base.BuildDto(row, rowNumber); + + var sectionType = sectionTypes.FirstOrDefault(s => + string.Equals(s.Caption.Trim(), dto.WellSectionTypeCaption?.Trim(), StringComparison.CurrentCultureIgnoreCase)); + + if (sectionType is null) + { + var message = string.Format(XLExtentions.ProblemDetailsTemplate, + TemplateParameters.SheetName, + rowNumber, + TemplateParameters.Cells[nameof(WellOperationDto.WellSectionTypeCaption)], + "Указана некорректная секция"); + throw new FileFormatException(message); + } + + var category = categories.FirstOrDefault(c => + string.Equals(c.Name.Trim(), dto.OperationCategoryName?.Trim(), StringComparison.CurrentCultureIgnoreCase)); + + if (category is null) + { + var message = string.Format(XLExtentions.ProblemDetailsTemplate, + TemplateParameters.SheetName, + rowNumber, + TemplateParameters.Cells[nameof(WellOperationDto.OperationCategoryName)], + "Указана некорректная операция"); + throw new FileFormatException(message); + } + + dto.IdWellSectionType = sectionType.Id; + dto.IdCategory = category.Id; + dto.IdParentCategory = category.IdParent; + + return dto; + } +} \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj b/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj index b97bed80..b23176e3 100644 --- a/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj +++ b/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj @@ -23,6 +23,8 @@ + + diff --git a/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs b/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs index 8e2db98f..e7943144 100644 --- a/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs +++ b/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs @@ -1,5 +1,7 @@ using AsbCloudApp.Data; +using AsbCloudApp.Data.WellOperation; using AsbCloudApp.Requests; +using Microsoft.AspNetCore.Mvc; using Refit; namespace AsbCloudWebApi.IntegrationTests.Clients; @@ -8,20 +10,23 @@ public interface IWellOperationClient { private const string BaseRoute = "/api/well/{idWell}/wellOperations"; - [Post(BaseRoute + "/{idType}/{deleteBeforeInsert}")] - Task> InsertRangeAsync(int idWell, int idType, bool deleteBeforeInsert, [Body] IEnumerable dtos); + [Post(BaseRoute + "/{deleteBeforeInsert}")] + Task> InsertRangeAsync(int idWell, + bool deleteBeforeInsert, + [Body] IEnumerable dtos); - [Put(BaseRoute + "/{idOperation}")] - Task> UpdateAsync(int idWell, int idOperation, [Body] WellOperationDto value, CancellationToken token); + [Put(BaseRoute)] + Task> UpdateRangeAsync(int idWell, [Body] IEnumerable dtos); - [Get(BaseRoute + "/plan")] - Task>> GetPageOperationsPlanAsync(int idWell, - [Query] WellOperationRequestBase request, - CancellationToken token); + [Get(BaseRoute)] + Task>> GetPageOperationsPlanAsync(int idWell, [Query] WellOperationRequest request); [Multipart] - [Post(BaseRoute + "/import/plan/default")] - Task>> ImportPlanDefaultExcelFileAsync(int idWell, - [AliasAs("files")] IEnumerable streams, - CancellationToken token); + [Post(BaseRoute + "/parse/{idType}")] + Task>> ParseAsync(int idWell, + int idType, + [AliasAs("file")] StreamPart file); + + [Get(BaseRoute + "/export")] + Task> ExportAsync(int idWell, int idType); } \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/Files/FactWellOperations.xlsx b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/Files/FactWellOperations.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..45ee8a0bb72a6425cf5d0362aeed27e61025d7af GIT binary patch literal 45419 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 }; //act - var response = await client.InsertRangeAsync(well.Id, 1, false, dtos); + var response = await client.InsertRangeAsync(well.Id, false, dtos); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -56,18 +56,18 @@ public class WellOperationControllerTest : BaseIntegrationTest var dtos = new[] { entity.Adapt() }; //act - var response = await client.InsertRangeAsync(well.Id, 1, true, dtos); + var response = await client.InsertRangeAsync(well.Id, true, dtos); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); } /// - /// Успешное обновление операции + /// Успешное обновление операций /// /// [Fact] - public async Task UpdateAsync_returns_success() + public async Task UpdateRangeAsync_returns_success() { //arrange var well = await dbContext.Wells.FirstAsync(); @@ -75,10 +75,10 @@ public class WellOperationControllerTest : BaseIntegrationTest dbContext.WellOperations.Add(entity); await dbContext.SaveChangesAsync(); - var dto = entity.Adapt(); + var dtos = new[] { entity.Adapt() }; //act - var response = await client.UpdateAsync(well.Id, entity.Id, dto, CancellationToken.None); + var response = await client.UpdateRangeAsync(well.Id, dtos); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -100,66 +100,101 @@ public class WellOperationControllerTest : BaseIntegrationTest var dto = entity.Adapt(); var timezoneOffset = TimeSpan.FromHours(well.Timezone.Hours); dto.DateStart = dto.DateStart.ToOffset(timezoneOffset); + dto.LastUpdateDate = dto.LastUpdateDate?.ToOffset(timezoneOffset); - var request = new WellOperationRequestBase + var request = new WellOperationRequest { OperationType = WellOperation.IdOperationTypePlan }; //act - var response = await client.GetPageOperationsPlanAsync(well.Id, request, CancellationToken.None); + var response = await client.GetPageOperationsPlanAsync(well.Id, request); //assert + Assert.Equal(response.StatusCode, HttpStatusCode.OK); Assert.NotNull(response.Content); Assert.Single(response.Content.Items); var actualDto = response.Content.Items.First(); - var excludeProps = new[] - { - nameof(WellOperationDto.LastUpdateDate) - }; - MatchHelper.Match(dto, actualDto, excludeProps); + MatchHelper.Match(dto, actualDto); } - [Fact] - public async Task ImportPlanDefaultExcelFileAsync_returns_success() + [Theory] + [InlineData(WellOperation.IdOperationTypePlan, "PlanWellOperations.xlsx")] + [InlineData(WellOperation.IdOperationTypeFact, "FactWellOperations.xlsx")] + public async Task ParseAsync_returns_success(int idType, string fileName) { //arrange - var stream = Assembly.GetExecutingAssembly().GetFileCopyStream("WellOperationsPlan.xlsx"); - - var memoryStream = new MemoryStream(); - await stream.CopyToAsync(memoryStream); - memoryStream.Position = 0; - var well = await dbContext.Wells.FirstAsync(); - //act - var streamPart = new StreamPart(memoryStream, "WellOperations.xlsx", "application/octet-stream"); + var expectedDto = new WellOperationDto + { + IdWell = well.Id, + IdWellSectionType = 2, + IdCategory = WellOperationCategory.IdSlide, + IdPlan = null, + CategoryInfo = "Доп.инфо", + IdType = idType, + DepthStart = 10.0, + DepthEnd = 20.0, + DateStart = new DateTimeOffset(new DateTime(2023, 1, 10), TimeSpan.FromHours(well.Timezone.Hours)), + DurationHours = 1.0, + Comment = "123", + }; - var response = await client.ImportPlanDefaultExcelFileAsync(well.Id, new[] { streamPart }, CancellationToken.None); + var stream = Assembly.GetExecutingAssembly().GetFileCopyStream(fileName); + + var streamPart = new StreamPart(stream, fileName, "application/octet-stream"); + + //act + var response = await client.ParseAsync(well.Id, idType, streamPart); //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response.Content); - Assert.Equal(4, response.Content.Count()); - Assert.True(response.Content.All(w => Math.Abs(w.DateStart.Offset.Hours - Defaults.Timezone.Hours) < 0.1)); + + var actualDto = response.Content.Item.First().Item; + + MatchHelper.Match(expectedDto, actualDto); } - private static WellOperation CreateWellOperation(int idWell) => + [Theory] + [InlineData(WellOperation.IdOperationTypePlan)] + [InlineData(WellOperation.IdOperationTypeFact)] + public async Task ExportAsync_returns_success(int idType) + { + //arrange + var well = await dbContext.Wells.FirstAsync(); + + var entity = CreateWellOperation(well.Id, idType); + dbContext.WellOperations.Add(entity); + await dbContext.SaveChangesAsync(); + + //act + var response = await client.ExportAsync(well.Id, idType); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("application/octet-stream", response.ContentHeaders?.ContentType?.MediaType); + Assert.True(response.ContentHeaders?.ContentLength > 0); + } + + private static WellOperation CreateWellOperation(int idWell, int idType = WellOperation.IdOperationTypePlan) => new() { IdWell = idWell, IdWellSectionType = 2, - LastUpdateDate = DateTimeOffset.UtcNow, - IdCategory = 5000, + IdCategory = WellOperationCategory.IdSlide, IdPlan = null, - CategoryInfo = "1", - IdType = 0, + CategoryInfo = "Доп.инфо", + LastUpdateDate = new DateTimeOffset(new DateTime(2023, 1, 10)).ToUniversalTime(), + IdType = idType, DepthStart = 10.0, DepthEnd = 20.0, DateStart = new DateTimeOffset(new DateTime(2023, 1, 10), TimeSpan.FromHours(Defaults.Timezone.Hours)).ToUniversalTime(), DurationHours = 1.0, Comment = "1", - IdUser = 1 + IdUser = 1, }; } \ No newline at end of file diff --git a/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs deleted file mode 100644 index ad3d3895..00000000 --- a/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs +++ /dev/null @@ -1,216 +0,0 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Data.WellOperationImport.Options; -using AsbCloudApp.Repositories; -using AsbCloudApp.Requests; -using AsbCloudApp.Services; -using AsbCloudApp.Services.WellOperationImport; -using AsbCloudDb.Model; -using AsbCloudInfrastructure.Services.WellOperationImport; -using AsbCloudInfrastructure.Services.WellOperationImport.FileParser; -using NSubstitute; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -namespace AsbCloudWebApi.Tests.Services.WellOperationExport -{ - public class WellOperationExportServiceTest - { - private const int idWell = 4; - - private IWellService wellService; - private IWellOperationRepository wellOperationRepository; - private IWellOperationCategoryRepository wellOperationCategoryRepository; - private IWellOperationImportTemplateService wellOperationImportTemplateService; - private WellOperationExportService wellOperationExportService; - private WellOperationImportService wellOperationImportService; - private IWellOperationExcelParser wellOperationDefaultExcelParser; - - private readonly WellSectionTypeDto[] sectionTypes = new WellSectionTypeDto[2] - { - new WellSectionTypeDto() - { - Caption = "1", - Id = 1, - Order = 0 - }, - new WellSectionTypeDto() - { - Caption = "2", - Id = 2, - Order = 1 - } - }; - - private readonly WellOperationCategoryDto[] categories = new WellOperationCategoryDto[2] - { - new WellOperationCategoryDto() - { - Id = 1, - IdParent = 1, - KeyValueName = "1", - KeyValueUnits = "1", - Name = "1" - }, - new WellOperationCategoryDto() - { - Id = 2, - IdParent = 2, - KeyValueName = "2", - KeyValueUnits = "2", - Name = "2" - } - }; - private readonly ITestOutputHelper output; - - public WellOperationExportServiceTest(ITestOutputHelper output) - { - wellService = Substitute.For(); - wellOperationRepository = Substitute.For(); - wellOperationCategoryRepository = Substitute.For(); - wellOperationImportTemplateService = new WellOperationImportTemplateService(); - wellOperationExportService = new WellOperationExportService(wellOperationRepository, wellOperationImportTemplateService, wellOperationCategoryRepository); - - wellOperationImportService = new WellOperationImportService(wellService, wellOperationRepository, wellOperationCategoryRepository); - wellOperationDefaultExcelParser = new WellOperationDefaultExcelParser(); - this.output = output; - - wellService.GetTimezone(idWell).Returns(new SimpleTimezoneDto() - { - Hours = 5 - }); - } - - [Fact] - public async Task Check_Exported_WellOperations_With_Operations_In_Db() - { - var operations = getOperations(); - - var localOperations = operations.ToArray(); - - foreach (var operation in localOperations) - operation.Id = 0; - - wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) - .ReturnsForAnyArgs(localOperations); - wellOperationRepository.GetSectionTypes().Returns(sectionTypes); - wellOperationCategoryRepository.Get(false).Returns(categories); - - var stream = await wellOperationExportService.ExportAsync(idWell, CancellationToken.None); - - var options = new WellOperationImportDefaultOptionsDto - { - IdType = WellOperation.IdOperationTypePlan - }; - var sheet = wellOperationDefaultExcelParser.Parse(stream, options); - var result = wellOperationImportService.Import(idWell, 1, options.IdType, sheet); - - var expected = JsonSerializer.Serialize(localOperations); - var actual = JsonSerializer.Serialize(result); - - Assert.Equal(expected, actual); - } - - [Fact] - public void TestDataContainsNotDefaultProps() - { - var initOk = true; - var operations = getOperations(); - for (int i = 0; i < operations.Length; i++) - { - var operation = operations[i]; - var propsWithDefault = GetPropsWithDefaultValue(operation, - nameof(WellOperationDto.Id), - nameof(WellOperationDto.IdType), - nameof(WellOperationDto.IdPlan), - nameof(WellOperationDto.IdParentCategory), - nameof(WellOperationDto.Day), - nameof(WellOperationDto.NptHours), - nameof(WellOperationDto.UserName), - nameof(WellOperationDto.LastUpdateDate) - ) - .ToArray(); - - if (propsWithDefault.Any()) - { - initOk = false; - foreach (var propertyName in propsWithDefault) - output.WriteLine($"{nameof(operations)}[{i}].{propertyName} is default"); - } - } - - Assert.True(initOk); - } - - private static IEnumerable GetPropsWithDefaultValue(T dto, params string[] excludeProps) - { - IEnumerable props = typeof(T).GetProperties( - BindingFlags.Public - | BindingFlags.Instance); - - props = props - .Where(prop => prop.CanWrite) - .Where(prop => !excludeProps.Contains(prop.Name)); - - foreach (var prop in props) - { - var value = prop.GetValue(dto); - if (prop.PropertyType.IsDefaultValue(value)) - yield return prop.Name; - } - } - - private WellOperationDto[] getOperations() - { - - var timezone = wellService.GetTimezone(idWell); - - DateTimeOffset GetDate(int days) - { - var date = DateTimeOffset.UtcNow.AddDays(days); - return new DateTimeOffset(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, TimeSpan.FromHours(timezone.Hours)); - } - - return new WellOperationDto[2] { - new WellOperationDto() { - Id = 5, - IdWell = idWell, - IdUser = 1, - IdType = 0, - IdWellSectionType = 1, - WellSectionTypeName = "1", - IdCategory = 1, - CategoryName = "1", - CategoryInfo = "CategoryInfo 1", - DepthStart = 10, - DepthEnd = 20, - DateStart = GetDate(days: 0), - DurationHours = 10, - Comment = "Комментарий 1", - }, - new WellOperationDto() { - Id = 6, - IdWell = idWell, - IdUser = 1, - IdType = 0, - IdWellSectionType = 2, - WellSectionTypeName = "2", - IdCategory = 2, - CategoryName = "2", - CategoryInfo = "CategoryInfo 2", - DepthStart = 20, - DepthEnd = 30, - DateStart = GetDate(days: 1), - DurationHours = 20, - Comment = "Комментарий 2", - } - }; - } - } -} diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs index d624e89a..e91c9c65 100644 --- a/AsbCloudWebApi/Controllers/WellOperationController.cs +++ b/AsbCloudWebApi/Controllers/WellOperationController.cs @@ -1,13 +1,7 @@ using AsbCloudApp.Data; -using AsbCloudApp.Data.WellOperationImport; -using AsbCloudApp.Data.WellOperationImport.Options; -using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; -using AsbCloudApp.Services.WellOperationImport; -using AsbCloudDb.Model; -using AsbCloudInfrastructure; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -15,598 +9,340 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; +using AsbCloudApp.Requests.ExportOptions; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.WellOperations.Factories; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Буровые операции (вводимые вручную) +/// +[Route("api/well/{idWell}/wellOperations")] +[ApiController] +[Authorize] +public class WellOperationController : ControllerBase { - - /// - /// Буровые операции (вводимые вручную) - /// - [Route("api/well/{idWell}/wellOperations")] - [ApiController] - [Authorize] - public class WellOperationController : ControllerBase - { - private readonly IWellOperationRepository operationRepository; - private readonly IWellService wellService; - private readonly IWellOperationExportService wellOperationExportService; - private readonly IWellOperationImportTemplateService wellOperationImportTemplateService; - private readonly IWellOperationImportService wellOperationImportService; - private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; - private readonly IWellOperationExcelParser wellOperationDefaultExcelParser; - private readonly IWellOperationExcelParser wellOperationGazpromKhantosExcelParser; - private readonly IUserRepository userRepository; - - public WellOperationController(IWellOperationRepository operationRepository, - IWellService wellService, - IWellOperationImportTemplateService wellOperationImportTemplateService, - IWellOperationExportService wellOperationExportService, - IWellOperationImportService wellOperationImportService, - IWellOperationCategoryRepository wellOperationCategoryRepository, - IWellOperationExcelParser wellOperationDefaultExcelParser, - IWellOperationExcelParser wellOperationGazpromKhantosExcelParser, - IUserRepository userRepository) - { - this.operationRepository = operationRepository; - this.wellService = wellService; - this.wellOperationImportTemplateService = wellOperationImportTemplateService; - this.wellOperationExportService = wellOperationExportService; - this.wellOperationImportService = wellOperationImportService; - this.wellOperationCategoryRepository = wellOperationCategoryRepository; - this.wellOperationDefaultExcelParser = wellOperationDefaultExcelParser; - this.wellOperationGazpromKhantosExcelParser = wellOperationGazpromKhantosExcelParser; - this.userRepository = userRepository; - } - - /// - /// Возвращает словарь типов секций - /// - /// - [HttpGet("sectionTypes")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetSectionTypes() - { - var result = operationRepository.GetSectionTypes(); - return Ok(result); - } - - /// - /// Возвращает список имен типов операций на скважине - /// - /// флаг, нужно ли включать родителей в список - /// - [HttpGet("categories")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetCategories(bool includeParents = true) - { - var result = wellOperationCategoryRepository.Get(includeParents); - return Ok(result); - } - - /// - /// Возвращает список плановых операций для сопоставления - /// - /// id скважины - /// дата для нахождения последней сопоставленной плановой операции - /// - /// - [HttpGet("operationsPlan")] - [ProducesResponseType(typeof(WellOperationPlanDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetOperationsPlanAsync( - [FromRoute] int idWell, - [FromQuery] DateTime currentDate, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await operationRepository - .GetOperationsPlanAsync(idWell, currentDate, token) - .ConfigureAwait(false); - return Ok(result); - } - - /// - /// Отфильтрованный список фактических операций на скважине. - /// Если не применять фильтр, то вернется весь список. Сортированный по глубине затем по дате - /// - /// id скважины - /// - /// - /// Список операций на скважине - [HttpGet("fact")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetPageOperationsFactAsync( - [FromRoute] int idWell, - [FromQuery] WellOperationRequestBase request, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var requestToService = new WellOperationRequest(request, idWell); - var result = await operationRepository.GetAsync( - requestToService, - token) - .ConfigureAwait(false); - return Ok(result); - } - - /// - /// Отфильтрованный список плановых операций на скважине. - /// Если не применять фильтр, то вернется весь список. Сортированный по глубине затем по дате - /// - /// id скважины - /// - /// - /// Список операций на скважине в контейнере для постраничного просмотра - [HttpGet("plan")] - [Permission] - [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] - public async Task GetPageOperationsPlanAsync( - [FromRoute] int idWell, - [FromQuery] WellOperationRequestBase request, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var requestToService = new WellOperationRequest(request, idWell); - var result = await operationRepository.GetPageAsync( - requestToService, - token) - .ConfigureAwait(false); - return Ok(result); - } - - /// - /// Статистика операций по скважине, группированная по категориям - /// - /// id скважины - /// - /// - /// - [HttpGet("groupStat")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetGroupOperationsAsync( - [FromRoute] int idWell, - [FromQuery] WellOperationRequestBase request, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var requestToService = new WellOperationRequest(request, idWell); - var result = await operationRepository.GetGroupOperationsStatAsync( - requestToService, - token) - .ConfigureAwait(false); - return Ok(result); - } - - /// - /// Возвращает нужную операцию на скважине - /// - /// id скважины - /// id нужной операции - /// Токен отмены задачи - /// Нужную операцию на скважине - [HttpGet("{idOperation}")] - [Permission] - [ProducesResponseType(typeof(WellOperationDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetOrDefaultAsync(int idWell, int idOperation, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await operationRepository.GetOrDefaultAsync(idOperation, token).ConfigureAwait(false); - return Ok(result); - } - - /// - /// Добавляет новую операцию на скважину - /// - /// Id скважины - /// Тип добавляемой операции - /// Добавляемая операция - /// - /// Количество добавленных в БД записей - [HttpPost("{idType:int}")] - [Permission] - [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - public async Task InsertAsync( - [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] int idWell, - [Range(0, 1, ErrorMessage = "Тип операции недопустим. Допустимые: 0, 1")] int idType, - WellOperationDto wellOperation, - CancellationToken cancellationToken) - { - if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) - return Forbid(); - - if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken)) - return Forbid(); - - wellOperation.IdWell = idWell; - wellOperation.IdUser = User.GetUserId(); - wellOperation.IdType = idType; - - var result = await operationRepository.InsertRangeAsync(new[] { wellOperation }, cancellationToken); - - return Ok(result); - } - - /// - /// Добавляет новые операции на скважине - /// - /// Id скважины - /// Добавляемые операции - /// Тип добавляемых операций - /// Удалить операции перед сохранением - /// - /// Количество добавленных в БД записей - [HttpPost("{idType:int}/{deleteBeforeInsert:bool}")] - [Permission] - [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - public async Task InsertRangeAsync( - [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] int idWell, - [Range(0, 1, ErrorMessage = "Тип операции недопустим. Допустимые: 0, 1")] int idType, - bool deleteBeforeInsert, - [FromBody] IEnumerable wellOperations, - CancellationToken cancellationToken) - { - if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) - return Forbid(); - - if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken)) - return Forbid(); - - if (deleteBeforeInsert) - { - var existingOperations = await operationRepository.GetAsync(new WellOperationRequest - { - IdWell = idWell, - OperationType = idType - }, cancellationToken); - - await operationRepository.DeleteAsync(existingOperations.Select(o => o.Id), cancellationToken); - } - - foreach (var wellOperation in wellOperations) - { - wellOperation.IdWell = idWell; - wellOperation.IdUser = User.GetUserId(); - wellOperation.IdType = idType; - } - - var result = await operationRepository.InsertRangeAsync(wellOperations, cancellationToken); - - return Ok(result); - } - - /// - /// Обновляет выбранную операцию на скважине - /// - /// id скважины - /// id выбранной операции - /// Новые данные для выбранной операции - /// Токен отмены задачи - /// Количество обновленных в БД строк - [HttpPut("{idOperation}")] - [Permission] - [ProducesResponseType(typeof(WellOperationDto), (int)System.Net.HttpStatusCode.OK)] - public async Task UpdateAsync(int idWell, int idOperation, - [FromBody] WellOperationDto value, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token)) - return Forbid(); - - if (!await CanUserEditWellOperationsAsync(idWell, token)) - return Forbid(); - - value.IdWell = idWell; - value.Id = idOperation; - value.IdUser = User.GetUserId(); - - var result = await operationRepository.UpdateAsync(value, token) - .ConfigureAwait(false); - return Ok(result); - } - - /// - /// Удаляет выбранную операцию на скважине - /// - /// id скважины - /// id выбранной операции - /// Токен отмены задачи - /// Количество удаленных из БД строк - [HttpDelete("{idOperation}")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task DeleteAsync(int idWell, int idOperation, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token)) - return Forbid(); - - if (!await CanUserEditWellOperationsAsync(idWell, token)) - return Forbid(); - - var result = await operationRepository.DeleteAsync(new int[] { idOperation }, token) - .ConfigureAwait(false); - - return Ok(result); - } - - /// - /// Импорт фактических операций из excel (xlsx) файла. Стандартный заполненный шаблон - /// - /// id скважины - /// Коллекция из одного файла xlsx - /// Удалить операции перед сохранением - /// - /// - [HttpPost("import/fact/default/{deleteBeforeInsert:bool}")] - [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - [Permission] - public Task ImportFactDefaultExcelFileAsync(int idWell, - [FromForm] IFormFileCollection files, - bool deleteBeforeInsert, - CancellationToken cancellationToken) - { - var options = new WellOperationImportDefaultOptionsDto - { - IdType = WellOperation.IdOperationTypeFact - }; - - return ImportExcelFileAsync(idWell, files, options, - (stream, _) => wellOperationDefaultExcelParser.Parse(stream, options), - deleteBeforeInsert, - cancellationToken); - } - - /// - /// Импорт плановых операций из excel (xlsx) файла. Стандартный заполненный шаблон - /// - /// id скважины - /// Коллекция из одного файла xlsx - /// - /// - [HttpPost("import/plan/default")] - [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - [Permission] - public Task ImportPlanDefaultExcelFileAsync(int idWell, - [FromForm] IFormFileCollection files, - CancellationToken cancellationToken) - { - var options = new WellOperationImportDefaultOptionsDto - { - IdType = WellOperation.IdOperationTypePlan - }; - - return ImportExcelFileAsync(idWell, files, options, - (stream, _) => wellOperationDefaultExcelParser.Parse(stream, options), - null, - cancellationToken); - } - - /// - /// Импорт операций из excel (xlsx) файла. ГПНХ (Хантос) - /// - /// Id скважины - /// Параметры парсинга - /// Коллекция из одного файла xlsx - /// - /// - [HttpPost("import/plan/gazpromKhantos")] - [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - [Permission] - public Task ImportPlanGazpromKhantosExcelFileAsync(int idWell, - [FromQuery] WellOperationImportGazpromKhantosOptionsDto options, - [FromForm] IFormFileCollection files, - CancellationToken cancellationToken) - { - options.IdType = WellOperation.IdOperationTypePlan; - - return ImportExcelFileAsync(idWell, files, options, - (stream, _) => wellOperationGazpromKhantosExcelParser.Parse(stream, options), - null, - cancellationToken); - } - - /// - /// Создает excel файл с операциями по скважине - /// - /// id скважины - /// Токен отмены задачи - /// Запрашиваемый файл - [HttpGet("export")] - [Permission] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task ExportAsync([FromRoute] int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var stream = await wellOperationExportService.ExportAsync(idWell, token); - var fileName = await wellService.GetWellCaptionByIdAsync(idWell, token) + "_operations.xlsx"; - return File(stream, "application/octet-stream", fileName); - } - - /// - /// Создает excel файл с "сетевым графиком" - /// - /// id скважины - /// - /// Токен отмены задачи - /// Запрашиваемый файл - [HttpGet("scheduleReport")] - [Permission] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] - public async Task ScheduleReportAsync([FromRoute] int idWell, [FromServices] IScheduleReportService scheduleReportService, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var stream = await scheduleReportService.MakeReportAsync(idWell, token); - var fileName = await wellService.GetWellCaptionByIdAsync(idWell, token) + "_ScheduleReport.xlsx"; - return File(stream, "application/octet-stream", fileName); - } - - /// - /// Удаляет полые дубликаты операций - /// - /// - /// - [HttpPost("/api/well/wellOperations/RemoveDuplicates")] - [Permission] - [Obsolete] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task RemoveDuplicates(CancellationToken token) - { - var result = await operationRepository.RemoveDuplicates((_, _) => { }, token); - return Ok(result); - } - - /// - /// Удаляет полностью пересекающиеся операции или "подрезает" более поздние их по глубине и дате. - /// - /// - /// - /// - /// - [HttpPost("/api/well/wellOperations/TrimOverlapping")] - [Permission] - [Obsolete] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task TrimOverlapping(DateTimeOffset? geDate, DateTimeOffset leDate, CancellationToken token) - { - var result = await operationRepository.TrimOverlapping(geDate, leDate, (_, _) => { }, token); - return Ok(result); - } - - /// - /// Возвращает шаблон файла импорта - /// - /// Запрашиваемый файл - [HttpGet("template")] - [AllowAnonymous] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] - public IActionResult GetTemplate() - { - var stream = wellOperationImportTemplateService.GetExcelTemplateStream(); - var fileName = "ЕЦП_шаблон_файла_операций.xlsx"; - return File(stream, "application/octet-stream", fileName); - } - - //TODO: deleteBeforeInsert тоже быстрый костыль - private async Task ImportExcelFileAsync(int idWell, [FromForm] IFormFileCollection files, - TOptions options, - Func parseMethod, - bool? deleteBeforeInsert, - CancellationToken cancellationToken) - where TOptions : IWellOperationImportOptions - { - var idCompany = User.GetCompanyId(); - var idUser = User.GetUserId(); - - if (!idCompany.HasValue || !idUser.HasValue) - throw new ForbidException("Неизвестный пользователь"); - - if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) - throw new ForbidException("Нет доступа к скважине"); - - if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken)) - throw new ForbidException("Недостаточно прав для редактирования ГГД на завершенной скважине"); - - if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, cancellationToken)) - throw new ForbidException("Скважина недоступна для компании"); - - if (files.Count < 1) - return this.ValidationBadRequest(nameof(files), "Нет файла"); - - var file = files[0]; - if (Path.GetExtension(file.FileName).ToLower() != ".xlsx") - return this.ValidationBadRequest(nameof(files), "Требуется xlsx файл."); - - using Stream stream = file.OpenReadStream(); - - try - { - var sheet = parseMethod(stream, options); - - var wellOperations = wellOperationImportService.Import(idWell, idUser.Value, options.IdType, sheet) - .OrderBy(w => w.DateStart); - - var dateStart = wellOperations.MinOrDefault(w => w.DateStart); - - foreach (var wellOperation in wellOperations) - { - if (dateStart.HasValue) - wellOperation.Day = (wellOperation.DateStart - dateStart.Value).TotalDays; - } - - //TODO: очень быстрый костыль - if (deleteBeforeInsert is not null && options.IdType == WellOperation.IdOperationTypeFact) - { - return await InsertRangeAsync(idWell, options.IdType, - deleteBeforeInsert.Value, - wellOperations, - cancellationToken); - } - - return Ok(wellOperations); - } - catch (FileFormatException ex) - { - return this.ValidationBadRequest(nameof(files), ex.Message); - } - } - - private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - } - - private async Task CanUserEditWellOperationsAsync(int idWell, CancellationToken token) - { - var idUser = User.GetUserId(); - - if (!idUser.HasValue) - return false; - - var well = await wellService.GetOrDefaultAsync(idWell, token); - - if (well is null) - return false; - - return well.IdState != 2 || userRepository.HasPermission(idUser.Value, "WellOperation.editCompletedWell"); - } - } + private readonly IDictionary templateNames = new Dictionary + { + { WellOperation.IdOperationTypeFact, "ЕЦП_шаблон_файла_фактические_операции.xlsx" }, + { WellOperation.IdOperationTypePlan, "ЕЦП_шаблон_файла_плановые_операции.xlsx" } + }; + + private readonly IUserRepository userRepository; + private readonly IWellOperationRepository wellOperationRepository; + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; + private readonly IWellService wellService; + + private readonly WellOperationParserFactory wellOperationParserFactory; + private readonly WellOperationExportServiceFactory wellOperationExportServiceFactory; + + public WellOperationController(IWellOperationRepository wellOperationRepository, + IWellOperationCategoryRepository wellOperationCategoryRepository, + IWellService wellService, + IUserRepository userRepository, + WellOperationParserFactory wellOperationParserFactory, + WellOperationExportServiceFactory wellOperationExportServiceFactory) + { + this.wellOperationRepository = wellOperationRepository; + this.wellOperationCategoryRepository = wellOperationCategoryRepository; + this.wellService = wellService; + this.userRepository = userRepository; + this.wellOperationParserFactory = wellOperationParserFactory; + this.wellOperationExportServiceFactory = wellOperationExportServiceFactory; + } + + /// + /// Добавляет новые операции на скважине + /// + /// Id скважины + /// Добавляемые операции + /// Удалить операции перед сохранением + /// + /// Количество добавленных в БД записей + [HttpPost("{deleteBeforeInsert:bool}")] + [Permission] + [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + public async Task InsertRangeAsync( + [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] + int idWell, + bool deleteBeforeInsert, + [FromBody] IEnumerable dtos, + CancellationToken cancellationToken) + { + if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) + return Forbid(); + + if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken)) + return Forbid(); + + foreach (var dto in dtos) + { + dto.IdWell = idWell; + dto.LastUpdateDate = null; + dto.IdUser = User.GetUserId(); + } + + var result = await wellOperationRepository.InsertRangeAsync(dtos, deleteBeforeInsert, cancellationToken); + + return Ok(result); + } + + /// + /// Обновляет выбранную операцию на скважине + /// + /// id скважины + /// + /// Токен отмены задачи + /// Количество обновленных в БД строк + [HttpPut] + [Permission] + [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] + public async Task UpdateRangeAsync(int idWell, + [FromBody] IEnumerable dtos, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + if (!await CanUserEditWellOperationsAsync(idWell, token)) + return Forbid(); + + foreach (var dto in dtos) + { + dto.IdWell = idWell; + dto.IdUser = User.GetUserId(); + dto.LastUpdateDate = DateTimeOffset.UtcNow; + } + + var result = await wellOperationRepository.UpdateRangeAsync(dtos, token); + + return Ok(result); + } + + /// + /// Возвращает словарь типов секций + /// + /// + [HttpGet("sectionTypes")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public IActionResult GetSectionTypes() + { + var result = wellOperationRepository.GetSectionTypes(); + return Ok(result); + } + + /// + /// Статистика операций по скважине, группированная по категориям + /// + /// id скважины + /// + /// + /// + [HttpGet("groupStat")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetGroupOperationsAsync( + [FromRoute] int idWell, + [FromQuery] WellOperationRequest request, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + request.IdsWell = new[] { idWell }; + var result = await wellOperationRepository.GetGroupOperationsStatAsync(request, token); + return Ok(result); + } + + /// + /// Возвращает список имен типов операций на скважине + /// + /// флаг, нужно ли включать родителей в список + /// + [HttpGet("categories")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public IActionResult GetCategories(bool includeParents = true) + { + var result = wellOperationCategoryRepository.Get(includeParents); + return Ok(result); + } + + /// + /// Постраничный список операций на скважине. + /// + /// id скважины + /// + /// + /// Список операций на скважине + [HttpGet] + [Permission] + [ProducesResponseType(typeof(PaginationContainer), StatusCodes.Status200OK)] + public async Task GetPageOperationsAsync( + [FromRoute] int idWell, + [FromQuery] WellOperationRequest request, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + request.IdsWell = new[] { idWell }; + var result = await wellOperationRepository.GetPageAsync(request, token); + return Ok(result); + } + + /// + /// Создает excel файл с "сетевым графиком" + /// + /// id скважины + /// + /// + /// Запрашиваемый файл + [HttpGet("scheduleReport")] + [Permission] + [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)] + public async Task ScheduleReportAsync([FromRoute] int idWell, + [FromServices] IScheduleReportService scheduleReportService, + CancellationToken token) + { + var idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, token)) + return Forbid(); + + var stream = await scheduleReportService.MakeReportAsync(idWell, token); + var fileName = await wellService.GetWellCaptionByIdAsync(idWell, token) + "_ScheduleReport.xlsx"; + return File(stream, "application/octet-stream", fileName); + } + + /// + /// Удаляет выбранную операцию на скважине + /// + /// id скважины + /// id выбранной операции + /// Токен отмены задачи + /// Количество удаленных из БД строк + [HttpDelete("{idOperation}")] + [Permission] + [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] + public async Task DeleteAsync(int idWell, int idOperation, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + if (!await CanUserEditWellOperationsAsync(idWell, token)) + return Forbid(); + + var result = await wellOperationRepository.DeleteRangeAsync(new[] { idOperation }, token); + + return Ok(result); + } + + /// + /// Формирование excel файла с операциями на скважине + /// + /// + /// + /// + /// + [HttpGet("export")] + [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] + public async Task ExportAsync(int idWell, + int idType, + CancellationToken token) + { + var options = new WellOperationExportRequest(idWell, idType); + var exportService = wellOperationExportServiceFactory.CreateExportService(idType); + + var (fileName, file) = await exportService.ExportAsync(options, token); + + return File(file, "application/octet-stream", fileName); + } + + /// + /// Импорт ГГД из excel (xlsx) файла + /// + /// + /// + /// + /// + /// + [HttpPost("parse/{idType}")] + [Permission] + [ProducesResponseType(typeof(ParserResultDto), StatusCodes.Status200OK)] + public async Task ParseAsync(int idWell, + int idType, + [Required] IFormFile file, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + if (!await CanUserEditWellOperationsAsync(idWell, token)) + return Forbid(); + + var stream = file.GetExcelFile(); + + try + { + var timezone = wellService.GetTimezone(idWell); + var options = new WellOperationParserRequest(idWell, idType, timezone); + var parser = wellOperationParserFactory.CreateParser(idType); + var result = parser.Parse(stream, options); + + return Ok(result); + } + catch (FileFormatException ex) + { + return this.ValidationBadRequest(nameof(file), ex.Message); + } + } + + /// + /// Получение шаблона для заполнения ГГД + /// + /// + [HttpGet("template")] + [AllowAnonymous] + [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public IActionResult GetTemplate(int idType) + { + var parser = wellOperationParserFactory.CreateParser(idType); + var stream = parser.GetTemplateFile(); + + return File(stream, "application/octet-stream", templateNames[idType]); + } + + private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + } + + private async Task CanUserEditWellOperationsAsync(int idWell, CancellationToken token) + { + var idUser = User.GetUserId(); + + if (!idUser.HasValue) + return false; + + var well = await wellService.GetOrDefaultAsync(idWell, token); + + if (well is null) + return false; + + return well.IdState != 2 || userRepository.HasPermission(idUser.Value, "WellOperation.editCompletedWell"); + } } \ No newline at end of file