From f2ca89dc8dee0521fef773e1b25d483a245c3c13 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, 9 Feb 2024 09:32:31 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B0=D1=80=D1=81=D0=B8=D0=BD=D0=B3=20?= =?UTF-8?q?=D0=A0=D0=A2=D0=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProcessMapPlan/ProcessMapPlanBaseDto.cs | 7 +- .../ProcessMapPlanDrillingDto.cs | 5 + .../IProcessMapPlanImportService.cs | 4 +- .../AsbCloudInfrastructure.csproj | 1 + .../Parser/ProcessMapPlanDrillingParser.cs | 139 ++++++++++++++++++ .../Parser/ProcessMapPlanParser.cs | 48 ++++++ .../ProcessMapPlanDrillingTemplate.xlsx | Bin 0 -> 12611 bytes ...ProcessMapPlanImportWellDrillingService.cs | 2 + .../ProcessMapPlanBaseController.cs | 79 ++++++++-- .../ProcessMapPlanDrillingController.cs | 17 ++- 10 files changed, 283 insertions(+), 19 deletions(-) create mode 100644 AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanDrillingParser.cs create mode 100644 AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanParser.cs create mode 100644 AsbCloudInfrastructure/Services/ProcessMapPlan/Templates/ProcessMapPlanDrillingTemplate.xlsx diff --git a/AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanBaseDto.cs b/AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanBaseDto.cs index a6d4fd56..e8404c7f 100644 --- a/AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanBaseDto.cs +++ b/AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanBaseDto.cs @@ -19,6 +19,11 @@ public abstract class ProcessMapPlanBaseDto : ChangeLogAbstract, IId, IWellRelat [Range(1, int.MaxValue, ErrorMessage = "Id секции скважины не может быть меньше 1")] public int IdWellSectionType { get; set; } + /// + /// Название секции + /// + public string? Section { get; set; } + /// /// Глубина по стволу от, м /// @@ -41,6 +46,6 @@ public abstract class ProcessMapPlanBaseDto : ChangeLogAbstract, IId, IWellRelat public virtual IEnumerable Validate(ValidationContext validationContext) { if(DepthEnd <= DepthStart) - yield return new ("глубина окончания должна быть больше глубины начала", new string[] {nameof(DepthEnd), nameof(DepthStart) }); + yield return new ("Глубина окончания должна быть больше глубины начала", new string[] {nameof(DepthEnd), nameof(DepthStart) }); } } \ No newline at end of file diff --git a/AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanDrillingDto.cs b/AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanDrillingDto.cs index 15f30300..7ab7db5d 100644 --- a/AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanDrillingDto.cs +++ b/AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanDrillingDto.cs @@ -12,6 +12,11 @@ public class ProcessMapPlanDrillingDto : ProcessMapPlanBaseDto /// [Range(1, 2, ErrorMessage = "Id режима должен быть либо 1-ротор либо 2-слайд")] public int IdMode { get; set; } + + /// + /// Название режима бурения + /// + public string? Mode { get; set; } /// /// Осевая нагрузка, т план diff --git a/AsbCloudApp/Services/ProcessMaps/IProcessMapPlanImportService.cs b/AsbCloudApp/Services/ProcessMaps/IProcessMapPlanImportService.cs index 7b30b80d..a0c3d4ec 100644 --- a/AsbCloudApp/Services/ProcessMaps/IProcessMapPlanImportService.cs +++ b/AsbCloudApp/Services/ProcessMaps/IProcessMapPlanImportService.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using System.Threading.Tasks; using System.Threading; @@ -7,6 +8,7 @@ namespace AsbCloudApp.Services.ProcessMaps; /// /// Сервис импорта РТК /// +[Obsolete] public interface IProcessMapPlanImportService { /// diff --git a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj index cdb57ae5..ba012eb5 100644 --- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj +++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj @@ -36,6 +36,7 @@ + diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanDrillingParser.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanDrillingParser.cs new file mode 100644 index 00000000..cab930b4 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanDrillingParser.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using AsbCloudApp.Data; +using AsbCloudApp.Data.ProcessMapPlan; +using AsbCloudApp.Repositories; +using AsbCloudApp.Services; +using ClosedXML.Excel; +using Microsoft.Extensions.DependencyInjection; + +namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Parser; + +public class ProcessMapPlanDrillingParser : ProcessMapPlanParser +{ + #region Columns + + private const int columnSection = 1; + private const int columnMode = 2; + private const int columnDepthStart = 3; + private const int columnDepthEnd = 4; + private const int columnPressurePlan = 5; + private const int columnPressureLimitMax = 6; + private const int columnAxialLoadPlan = 7; + private const int columnAxialLoadLimitMax = 8; + private const int columnTopDriveTorquePlan = 9; + private const int columnTopDriveTorqueLimitMax = 10; + private const int columnTopDriveSpeedPlan = 11; + private const int columnTopDriveSpeedLimitMax = 12; + private const int columnFlowPlan = 13; + private const int columnFlowLimitMax = 14; + private const int columnRopPlan = 15; + private const int columnUsageSaub = 16; + private const int columnUsageSpin = 17; + private const int columnComment = 18; + + #endregion + + private readonly IEnumerable sections; + + public ProcessMapPlanDrillingParser(IServiceProvider serviceProvider) + : base(serviceProvider) + { + var wellOperationRepository = serviceProvider.GetRequiredService(); + + sections = wellOperationRepository.GetSectionTypes(); + } + + protected override string SheetName => "План"; + + protected override string TemplateFileName => "ProcessMapPlanDrillingTemplate.xlsx"; + + protected override ValidationResultDto ParseRow(IXLRow row) + { + var sectionCaption = row.Cell(columnSection).GetCellValue()?.Trim().ToLower(); + var modeName = row.Cell(columnMode).GetCellValue()?.Trim().ToLower(); + var depthStart = row.Cell(columnDepthStart).GetCellValue(); + var depthEnd = row.Cell(columnDepthEnd).GetCellValue(); + var deltaPressurePlan = row.Cell(columnPressurePlan).GetCellValue(); + var deltaPressureLimitMax = row.Cell(columnPressureLimitMax).GetCellValue(); + var axialLoadPlan = row.Cell(columnAxialLoadPlan).GetCellValue(); + var axialLoadLimitMax = row.Cell(columnAxialLoadLimitMax).GetCellValue(); + var topDriveTorquePlan = row.Cell(columnTopDriveTorquePlan).GetCellValue(); + var topDriveTorqueLimitMax = row.Cell(columnTopDriveTorqueLimitMax).GetCellValue(); + var topDriveSpeedPlan = row.Cell(columnTopDriveSpeedPlan).GetCellValue(); + var topDriveSpeedLimitMax = row.Cell(columnTopDriveSpeedLimitMax).GetCellValue(); + var flowPlan = row.Cell(columnFlowPlan).GetCellValue(); + var flowLimitMax = row.Cell(columnFlowLimitMax).GetCellValue(); + var ropPlan = row.Cell(columnRopPlan).GetCellValue(); + var usageSaub = row.Cell(columnUsageSaub).GetCellValue(); + var usageSpin = row.Cell(columnUsageSpin).GetCellValue(); + var comment = row.Cell(columnComment).GetCellValue() ?? string.Empty; + + var section = sections.FirstOrDefault(s => + string.Equals(s.Caption.Trim(), sectionCaption?.Trim(), StringComparison.CurrentCultureIgnoreCase)); + + if (section is null) + { + var message = string.Format(IParserService.MessageTemplate, SheetName, row.RowNumber(), columnSection, + "Указана некорректная секция"); + throw new FileFormatException(message); + } + + var idMode = GetIdMode(modeName); + + if (idMode is null) + { + var message = string.Format(IParserService.MessageTemplate, SheetName, row.RowNumber(), columnSection, + "Указан некорректный режим бурения"); + throw new FileFormatException(message); + } + + var dto = new ProcessMapPlanDrillingDto + { + IdWellSectionType = section.Id, + Section = section.Caption, + IdMode = idMode.Value, + Mode = modeName, + DepthStart = depthStart, + DepthEnd = depthEnd, + AxialLoadPlan = axialLoadPlan, + AxialLoadLimitMax = axialLoadLimitMax, + DeltaPressurePlan = deltaPressurePlan, + DeltaPressureLimitMax = deltaPressureLimitMax, + TopDriveTorquePlan = topDriveTorquePlan, + TopDriveTorqueLimitMax = topDriveTorqueLimitMax, + TopDriveSpeedPlan = topDriveSpeedPlan, + TopDriveSpeedLimitMax = topDriveSpeedLimitMax, + FlowPlan = flowPlan, + FlowLimitMax = flowLimitMax, + RopPlan = ropPlan, + UsageSaub = usageSaub, + UsageSpin = usageSpin, + Comment = comment + }; + + var columnNumbers = new Dictionary + { + { nameof(ProcessMapPlanDrillingDto.DepthStart), columnDepthStart }, + { nameof(ProcessMapPlanDrillingDto.DepthEnd), columnDepthEnd }, + { nameof(ProcessMapPlanDrillingDto.DeltaPressurePlan), columnPressurePlan }, + { nameof(ProcessMapPlanDrillingDto.DeltaPressureLimitMax), columnPressureLimitMax }, + { nameof(ProcessMapPlanDrillingDto.AxialLoadPlan), columnAxialLoadPlan }, + { nameof(ProcessMapPlanDrillingDto.AxialLoadLimitMax), columnAxialLoadLimitMax }, + { nameof(ProcessMapPlanDrillingDto.TopDriveTorquePlan), columnTopDriveTorquePlan }, + { nameof(ProcessMapPlanDrillingDto.TopDriveTorqueLimitMax), columnTopDriveTorqueLimitMax }, + { nameof(ProcessMapPlanDrillingDto.TopDriveSpeedPlan), columnTopDriveSpeedPlan }, + { nameof(ProcessMapPlanDrillingDto.TopDriveSpeedLimitMax), columnTopDriveSpeedLimitMax }, + { nameof(ProcessMapPlanDrillingDto.FlowPlan), columnFlowPlan }, + { nameof(ProcessMapPlanDrillingDto.FlowLimitMax), columnFlowLimitMax }, + { nameof(ProcessMapPlanDrillingDto.RopPlan), columnRopPlan }, + { nameof(ProcessMapPlanDrillingDto.UsageSaub), columnUsageSaub }, + { nameof(ProcessMapPlanDrillingDto.UsageSpin), columnUsageSpin }, + { nameof(ProcessMapPlanDrillingDto.Comment), columnComment } + }; + + return ValidateRow(row.RowNumber(), columnNumbers, dto); + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanParser.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanParser.cs new file mode 100644 index 00000000..5b7aab2d --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanParser.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using System.Reflection; +using AsbCloudApp.Data; +using AsbCloudApp.Data.ProcessMapPlan; +using AsbCloudApp.Requests.ParserOptions; +using ClosedXML.Excel; + +namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Parser; + +public abstract class ProcessMapPlanParser : ParserServiceBase + where TDto : ProcessMapPlanBaseDto +{ + protected ProcessMapPlanParser(IServiceProvider serviceProvider) + : base(serviceProvider) + { + } + + private const int HeaderRowsCount = 2; + private const int ColumnCount = 18; + + protected abstract string TemplateFileName { get; } + + protected abstract ValidationResultDto ParseRow(IXLRow row); + + public override ParserResultDto Parse(Stream file, IParserOptionsRequest options) + { + using var workbook = new XLWorkbook(file); + + var sheet = workbook.GetWorksheet(SheetName); + + var processMaps = ParseExcelSheet(sheet, ParseRow, ColumnCount, HeaderRowsCount); + return processMaps; + } + + public override Stream GetTemplateFile() => + Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateFileName) + ?? throw new ArgumentNullException($"Файл '{TemplateFileName}' не найден"); + + protected static int? GetIdMode(string? modeName) => + modeName?.Trim().ToLower() switch + { + "ручной" => 0, + "ротор" => 1, + "слайд" => 2, + _ => null + }; +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Templates/ProcessMapPlanDrillingTemplate.xlsx b/AsbCloudInfrastructure/Services/ProcessMapPlan/Templates/ProcessMapPlanDrillingTemplate.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..bdf13143446f1d64a808c157f915d943dcf5d610 GIT binary patch literal 12611 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 literal 0 HcmV?d00001 diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/WellDrilling/ProcessMapPlanImportWellDrillingService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/WellDrilling/ProcessMapPlanImportWellDrillingService.cs index f322c798..454daa7a 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/WellDrilling/ProcessMapPlanImportWellDrillingService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/WellDrilling/ProcessMapPlanImportWellDrillingService.cs @@ -18,6 +18,8 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.WellDrilling; /* * password for ProcessMapImportTemplate.xlsx is ASB2020! */ + +[Obsolete] public class ProcessMapPlanImportWellDrillingService : IProcessMapPlanImportService { private readonly IProcessMapPlanRepository processMapPlanWellDrillingRepository; diff --git a/AsbCloudWebApi/Controllers/ProcessMapPlan/ProcessMapPlanBaseController.cs b/AsbCloudWebApi/Controllers/ProcessMapPlan/ProcessMapPlanBaseController.cs index c3fd0c49..fb55bcf7 100644 --- a/AsbCloudWebApi/Controllers/ProcessMapPlan/ProcessMapPlanBaseController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMapPlan/ProcessMapPlanBaseController.cs @@ -9,8 +9,13 @@ using Microsoft.AspNetCore.Http; using AsbCloudApp.Exceptions; using AsbCloudApp.Requests; using System; +using System.IO; using AsbCloudApp.Services; using System.Linq; +using AsbCloudApp.Data; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudInfrastructure.Services; +using AsbCloudWebApi.Controllers.Interfaces; namespace AsbCloudWebApi.Controllers.ProcessMapPlan; @@ -20,17 +25,38 @@ namespace AsbCloudWebApi.Controllers.ProcessMapPlan; [ApiController] [Route("api/well/{idWell}/[controller]")] [Authorize] -public abstract class ProcessMapPlanBaseController : ControllerBase - where TDto : ProcessMapPlanBaseDto +public abstract class ProcessMapPlanBaseController : ControllerBase, + IControllerWithParser + where TDto : ProcessMapPlanBaseDto { - private readonly IChangeLogRepository repository; - private readonly IWellService wellService; + private readonly IChangeLogRepository repository; + private readonly IWellService wellService; + private readonly IParserService parserService; - public ProcessMapPlanBaseController(IChangeLogRepository repository, IWellService wellService) - { - this.repository = repository; - this.wellService = wellService; - } + protected ProcessMapPlanBaseController(IChangeLogRepository repository, + IWellService wellService, + ParserServiceFactory parserFactory, + int idParserService) + { + this.repository = repository; + this.wellService = wellService; + parserService = parserFactory.Create(idParserService); + } + + protected abstract string TemplateFileName { get; } + + ActionResult> IControllerWithParser.Parse(Stream file, IParserOptionsRequest options) + { + try + { + var parserResult = parserService.Parse(file, options); + return Ok(parserResult); + } + catch (FileFormatException ex) + { + return this.ValidationBadRequest("files", ex.Message); + } + } /// /// Добавление @@ -190,6 +216,39 @@ public abstract class ProcessMapPlanBaseController : ControllerBase var result = await repository.UpdateOrInsertRange(idUser, dtos, token); return Ok(result); } + + /// + /// Импорт РТК из excel (xlsx) файла + /// + /// + /// + /// + /// + [HttpPost("parse")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + public async Task>> Parse(int idWell, + [FromForm] IFormFileCollection files, + CancellationToken token) + { + await AssertUserHasAccessToWell(idWell, token); + + return this.ParseExcelFile(files, IParserOptionsRequest.Empty()); + } + + /// + /// Получение шаблона для заполнения РТК + /// + /// + [HttpGet("template")] + [AllowAnonymous] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public IActionResult GetTemplate() + { + var stream = parserService.GetTemplateFile(); + return File(stream, "application/octet-stream", TemplateFileName); + } /// /// returns user id, if he has access to well @@ -221,4 +280,4 @@ public abstract class ProcessMapPlanBaseController : ControllerBase var idUser = User.GetUserId() ?? throw new ForbidException("Неизвестный пользователь"); return idUser; } -} +} \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/ProcessMapPlan/ProcessMapPlanDrillingController.cs b/AsbCloudWebApi/Controllers/ProcessMapPlan/ProcessMapPlanDrillingController.cs index b0a20f1e..8855c54f 100644 --- a/AsbCloudWebApi/Controllers/ProcessMapPlan/ProcessMapPlanDrillingController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMapPlan/ProcessMapPlanDrillingController.cs @@ -2,15 +2,18 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; +using AsbCloudInfrastructure.Services; namespace AsbCloudWebApi.Controllers.ProcessMapPlan; public class ProcessMapPlanDrillingController : ProcessMapPlanBaseController { - public ProcessMapPlanDrillingController( - IChangeLogRepository repository, - IWellService wellService) - : base(repository, wellService) - { - } -} + public ProcessMapPlanDrillingController(IChangeLogRepository repository, + IWellService wellService, + ParserServiceFactory parserFactory) + : base(repository, wellService, parserFactory, ParserServiceFactory.IdProcessMapPlanDrillingParser) + { + } + + protected override string TemplateFileName => "ЕЦП_шаблон_файла_РТК_план_бурение.xlsx"; +} \ No newline at end of file