forked from ddrilling/AsbCloudServer
Парсинг РТК
This commit is contained in:
parent
aff243626a
commit
f2ca89dc8d
@ -19,6 +19,11 @@ public abstract class ProcessMapPlanBaseDto : ChangeLogAbstract, IId, IWellRelat
|
||||
[Range(1, int.MaxValue, ErrorMessage = "Id секции скважины не может быть меньше 1")]
|
||||
public int IdWellSectionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Название секции
|
||||
/// </summary>
|
||||
public string? Section { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Глубина по стволу от, м
|
||||
/// <para>
|
||||
@ -41,6 +46,6 @@ public abstract class ProcessMapPlanBaseDto : ChangeLogAbstract, IId, IWellRelat
|
||||
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if(DepthEnd <= DepthStart)
|
||||
yield return new ("глубина окончания должна быть больше глубины начала", new string[] {nameof(DepthEnd), nameof(DepthStart) });
|
||||
yield return new ("Глубина окончания должна быть больше глубины начала", new string[] {nameof(DepthEnd), nameof(DepthStart) });
|
||||
}
|
||||
}
|
@ -12,6 +12,11 @@ public class ProcessMapPlanDrillingDto : ProcessMapPlanBaseDto
|
||||
/// </summary>
|
||||
[Range(1, 2, ErrorMessage = "Id режима должен быть либо 1-ротор либо 2-слайд")]
|
||||
public int IdMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Название режима бурения
|
||||
/// </summary>
|
||||
public string? Mode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Осевая нагрузка, т план
|
||||
|
@ -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;
|
||||
/// <summary>
|
||||
/// Сервис импорта РТК
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public interface IProcessMapPlanImportService
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -36,6 +36,7 @@
|
||||
<EmbeddedResource Include="Services\DetectOperations\DetectOperations.xlsx" />
|
||||
<EmbeddedResource Include="Services\DailyReport\DailyReportTemplate.xlsx" />
|
||||
<EmbeddedResource Include="Services\DrillTestReport\DrillTestReportTemplate.xlsx" />
|
||||
<EmbeddedResource Include="Services\ProcessMapPlan\Templates\ProcessMapPlanDrillingTemplate.xlsx" />
|
||||
<EmbeddedResource Include="Services\Trajectory\Templates\TrajectoryFactNnbTemplate.xlsx" />
|
||||
<EmbeddedResource Include="Services\Trajectory\Templates\TrajectoryFactManualTemplate.xlsx" />
|
||||
<EmbeddedResource Include="Services\Trajectory\Templates\TrajectoryPlanTemplate.xlsx" />
|
||||
|
@ -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<ProcessMapPlanDrillingDto>
|
||||
{
|
||||
#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<WellSectionTypeDto> sections;
|
||||
|
||||
public ProcessMapPlanDrillingParser(IServiceProvider serviceProvider)
|
||||
: base(serviceProvider)
|
||||
{
|
||||
var wellOperationRepository = serviceProvider.GetRequiredService<IWellOperationRepository>();
|
||||
|
||||
sections = wellOperationRepository.GetSectionTypes();
|
||||
}
|
||||
|
||||
protected override string SheetName => "План";
|
||||
|
||||
protected override string TemplateFileName => "ProcessMapPlanDrillingTemplate.xlsx";
|
||||
|
||||
protected override ValidationResultDto<ProcessMapPlanDrillingDto> ParseRow(IXLRow row)
|
||||
{
|
||||
var sectionCaption = row.Cell(columnSection).GetCellValue<string>()?.Trim().ToLower();
|
||||
var modeName = row.Cell(columnMode).GetCellValue<string>()?.Trim().ToLower();
|
||||
var depthStart = row.Cell(columnDepthStart).GetCellValue<double>();
|
||||
var depthEnd = row.Cell(columnDepthEnd).GetCellValue<double>();
|
||||
var deltaPressurePlan = row.Cell(columnPressurePlan).GetCellValue<double>();
|
||||
var deltaPressureLimitMax = row.Cell(columnPressureLimitMax).GetCellValue<double>();
|
||||
var axialLoadPlan = row.Cell(columnAxialLoadPlan).GetCellValue<double>();
|
||||
var axialLoadLimitMax = row.Cell(columnAxialLoadLimitMax).GetCellValue<double>();
|
||||
var topDriveTorquePlan = row.Cell(columnTopDriveTorquePlan).GetCellValue<double>();
|
||||
var topDriveTorqueLimitMax = row.Cell(columnTopDriveTorqueLimitMax).GetCellValue<double>();
|
||||
var topDriveSpeedPlan = row.Cell(columnTopDriveSpeedPlan).GetCellValue<double>();
|
||||
var topDriveSpeedLimitMax = row.Cell(columnTopDriveSpeedLimitMax).GetCellValue<double>();
|
||||
var flowPlan = row.Cell(columnFlowPlan).GetCellValue<double>();
|
||||
var flowLimitMax = row.Cell(columnFlowLimitMax).GetCellValue<double>();
|
||||
var ropPlan = row.Cell(columnRopPlan).GetCellValue<double>();
|
||||
var usageSaub = row.Cell(columnUsageSaub).GetCellValue<double>();
|
||||
var usageSpin = row.Cell(columnUsageSpin).GetCellValue<double>();
|
||||
var comment = row.Cell(columnComment).GetCellValue<string>() ?? 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<string, int>
|
||||
{
|
||||
{ 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);
|
||||
}
|
||||
}
|
@ -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<TDto> : ParserServiceBase<TDto, IParserOptionsRequest>
|
||||
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<TDto> ParseRow(IXLRow row);
|
||||
|
||||
public override ParserResultDto<TDto> 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
|
||||
};
|
||||
}
|
Binary file not shown.
@ -18,6 +18,8 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.WellDrilling;
|
||||
/*
|
||||
* password for ProcessMapImportTemplate.xlsx is ASB2020!
|
||||
*/
|
||||
|
||||
[Obsolete]
|
||||
public class ProcessMapPlanImportWellDrillingService : IProcessMapPlanImportService
|
||||
{
|
||||
private readonly IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto> processMapPlanWellDrillingRepository;
|
||||
|
@ -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<TDto> : ControllerBase
|
||||
where TDto : ProcessMapPlanBaseDto
|
||||
public abstract class ProcessMapPlanBaseController<TDto> : ControllerBase,
|
||||
IControllerWithParser<TDto, IParserOptionsRequest>
|
||||
where TDto : ProcessMapPlanBaseDto
|
||||
{
|
||||
private readonly IChangeLogRepository<TDto, ProcessMapPlanBaseRequestWithWell> repository;
|
||||
private readonly IWellService wellService;
|
||||
private readonly IChangeLogRepository<TDto, ProcessMapPlanBaseRequestWithWell> repository;
|
||||
private readonly IWellService wellService;
|
||||
private readonly IParserService<TDto, IParserOptionsRequest> parserService;
|
||||
|
||||
public ProcessMapPlanBaseController(IChangeLogRepository<TDto, ProcessMapPlanBaseRequestWithWell> repository, IWellService wellService)
|
||||
{
|
||||
this.repository = repository;
|
||||
this.wellService = wellService;
|
||||
}
|
||||
protected ProcessMapPlanBaseController(IChangeLogRepository<TDto, ProcessMapPlanBaseRequestWithWell> repository,
|
||||
IWellService wellService,
|
||||
ParserServiceFactory parserFactory,
|
||||
int idParserService)
|
||||
{
|
||||
this.repository = repository;
|
||||
this.wellService = wellService;
|
||||
parserService = parserFactory.Create<TDto, IParserOptionsRequest>(idParserService);
|
||||
}
|
||||
|
||||
protected abstract string TemplateFileName { get; }
|
||||
|
||||
ActionResult<ParserResultDto<TDto>> IControllerWithParser<TDto, IParserOptionsRequest>.Parse(Stream file, IParserOptionsRequest options)
|
||||
{
|
||||
try
|
||||
{
|
||||
var parserResult = parserService.Parse(file, options);
|
||||
return Ok(parserResult);
|
||||
}
|
||||
catch (FileFormatException ex)
|
||||
{
|
||||
return this.ValidationBadRequest("files", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавление
|
||||
@ -190,6 +216,39 @@ public abstract class ProcessMapPlanBaseController<TDto> : ControllerBase
|
||||
var result = await repository.UpdateOrInsertRange(idUser, dtos, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт РТК из excel (xlsx) файла
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="files"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("parse")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
public async Task<ActionResult<ParserResultDto<TDto>>> Parse(int idWell,
|
||||
[FromForm] IFormFileCollection files,
|
||||
CancellationToken token)
|
||||
{
|
||||
await AssertUserHasAccessToWell(idWell, token);
|
||||
|
||||
return this.ParseExcelFile(files, IParserOptionsRequest.Empty());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение шаблона для заполнения РТК
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns user id, if he has access to well
|
||||
@ -221,4 +280,4 @@ public abstract class ProcessMapPlanBaseController<TDto> : ControllerBase
|
||||
var idUser = User.GetUserId() ?? throw new ForbidException("Неизвестный пользователь");
|
||||
return idUser;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,15 +2,18 @@
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudInfrastructure.Services;
|
||||
|
||||
namespace AsbCloudWebApi.Controllers.ProcessMapPlan;
|
||||
|
||||
public class ProcessMapPlanDrillingController : ProcessMapPlanBaseController<ProcessMapPlanDrillingDto>
|
||||
{
|
||||
public ProcessMapPlanDrillingController(
|
||||
IChangeLogRepository<ProcessMapPlanDrillingDto, ProcessMapPlanBaseRequestWithWell> repository,
|
||||
IWellService wellService)
|
||||
: base(repository, wellService)
|
||||
{
|
||||
}
|
||||
}
|
||||
public ProcessMapPlanDrillingController(IChangeLogRepository<ProcessMapPlanDrillingDto, ProcessMapPlanBaseRequestWithWell> repository,
|
||||
IWellService wellService,
|
||||
ParserServiceFactory parserFactory)
|
||||
: base(repository, wellService, parserFactory, ParserServiceFactory.IdProcessMapPlanDrillingParser)
|
||||
{
|
||||
}
|
||||
|
||||
protected override string TemplateFileName => "ЕЦП_шаблон_файла_РТК_план_бурение.xlsx";
|
||||
}
|
Loading…
Reference in New Issue
Block a user