forked from ddrilling/AsbCloudServer
Рефакторинг после ревью
This commit is contained in:
parent
886abdcf06
commit
4fb94a443f
@ -1,11 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace AsbCloudApp.Data.Trajectory
|
namespace AsbCloudApp.Data.Trajectory
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Базовая географическая траектория
|
/// Базовая географическая траектория
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class TrajectoryGeoDto : IId
|
public abstract class TrajectoryGeoDto : IId, IValidatableObject
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ИД строки с координатами
|
/// ИД строки с координатами
|
||||||
@ -49,5 +52,11 @@ namespace AsbCloudApp.Data.Trajectory
|
|||||||
/// ИД пользователя
|
/// ИД пользователя
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int IdUser { get; set; }
|
public int IdUser { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||||
|
{
|
||||||
|
return Enumerable.Empty<ValidationResult>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,5 +33,4 @@ public interface IParserService<TDto, in TOptions> : IParserService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IParserService
|
public interface IParserService
|
||||||
{
|
{
|
||||||
const string MessageTemplate = "Лист: {0}, Строка: {1}, Столбец: {2}. {3}";
|
|
||||||
}
|
}
|
114
AsbCloudInfrastructure/Services/ParserExcelService.cs
Normal file
114
AsbCloudInfrastructure/Services/ParserExcelService.cs
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Requests.ParserOptions;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services;
|
||||||
|
|
||||||
|
public abstract class ParserExcelService<TDto, TOptions> : IParserService<TDto, TOptions>
|
||||||
|
where TDto : class, IValidatableObject, IId
|
||||||
|
where TOptions : IParserOptionsRequest
|
||||||
|
{
|
||||||
|
protected readonly IServiceProvider serviceProvider;
|
||||||
|
|
||||||
|
protected ParserExcelService(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
this.serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract string SheetName { get; }
|
||||||
|
|
||||||
|
protected abstract IDictionary<string, int> PropertyColumnNumbers { get; }
|
||||||
|
|
||||||
|
public abstract ParserResultDto<TDto> Parse(Stream file, TOptions options);
|
||||||
|
|
||||||
|
public abstract Stream GetTemplateFile();
|
||||||
|
|
||||||
|
protected abstract TDto ParseRow(IXLRow xlRow);
|
||||||
|
|
||||||
|
private ValidationResultDto<TDto> Validate(TDto dto, int rowNumber)
|
||||||
|
{
|
||||||
|
var validationResults = new List<ValidationResult>();
|
||||||
|
|
||||||
|
var isValid = dto.Validate(validationResults);
|
||||||
|
|
||||||
|
if (isValid)
|
||||||
|
{
|
||||||
|
var validDto = new ValidationResultDto<TDto>()
|
||||||
|
{
|
||||||
|
Item = dto
|
||||||
|
};
|
||||||
|
|
||||||
|
return validDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
var invalidDto = new ValidationResultDto<TDto>
|
||||||
|
{
|
||||||
|
Item = dto,
|
||||||
|
Warnings = validationResults
|
||||||
|
.SelectMany(v => v.MemberNames
|
||||||
|
.Where(PropertyColumnNumbers.ContainsKey)
|
||||||
|
.Select(m =>
|
||||||
|
{
|
||||||
|
var columnNumber = PropertyColumnNumbers[m];
|
||||||
|
var errorMessage = v.ErrorMessage;
|
||||||
|
var warningMessage = string.Format(XLMessageTemplates.ProblemDetailsTemplate, SheetName, rowNumber, columnNumber, errorMessage);
|
||||||
|
var warning = new ValidationResult(warningMessage, new[] { m });
|
||||||
|
return warning;
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
|
||||||
|
return invalidDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual ParserResultDto<TDto> ParseExcelSheet(IXLWorksheet sheet,
|
||||||
|
int columnCount,
|
||||||
|
int headerRowsCount = 0)
|
||||||
|
{
|
||||||
|
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < columnCount)
|
||||||
|
throw new FileFormatException(string.Format(XLMessageTemplates.FewerColumnsTemplate, SheetName));
|
||||||
|
|
||||||
|
var count = sheet.RowsUsed().Count() - headerRowsCount;
|
||||||
|
|
||||||
|
if (count > 1024)
|
||||||
|
throw new FileFormatException(string.Format(XLMessageTemplates.ExceedingMaxRowLimitTemplate, SheetName));
|
||||||
|
|
||||||
|
if (count <= 0)
|
||||||
|
return new ParserResultDto<TDto>();
|
||||||
|
|
||||||
|
var valiationResults = new List<ValidationResultDto<TDto>>(count);
|
||||||
|
var warnings = new List<ValidationResult>();
|
||||||
|
|
||||||
|
for (var i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var row = sheet.Row(1 + i + headerRowsCount);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var dto = ParseRow(row);
|
||||||
|
var validationResult = Validate(dto, row.RowNumber());
|
||||||
|
valiationResults.Add(validationResult);
|
||||||
|
}
|
||||||
|
catch (FileFormatException ex)
|
||||||
|
{
|
||||||
|
var warning = new ValidationResult(ex.Message);
|
||||||
|
warnings.Add(warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var parserResult = new ParserResultDto<TDto>
|
||||||
|
{
|
||||||
|
Item = valiationResults
|
||||||
|
};
|
||||||
|
|
||||||
|
if (warnings.Any())
|
||||||
|
parserResult.Warnings = warnings;
|
||||||
|
|
||||||
|
return parserResult;
|
||||||
|
}
|
||||||
|
}
|
@ -1,127 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using AsbCloudApp.Data;
|
|
||||||
using AsbCloudApp.Requests.ParserOptions;
|
|
||||||
using AsbCloudApp.Services;
|
|
||||||
using ClosedXML.Excel;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services;
|
|
||||||
|
|
||||||
public abstract class ParserServiceBase<TDto, TOptions> : IParserService<TDto, TOptions>
|
|
||||||
where TDto : class, IId
|
|
||||||
where TOptions : IParserOptionsRequest
|
|
||||||
{
|
|
||||||
protected readonly IServiceProvider serviceProvider;
|
|
||||||
|
|
||||||
protected ParserServiceBase(IServiceProvider serviceProvider)
|
|
||||||
{
|
|
||||||
this.serviceProvider = serviceProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual ICollection<ValidationResult> ValidationResults { get; } = new List<ValidationResult>();
|
|
||||||
|
|
||||||
protected abstract string SheetName { get; }
|
|
||||||
|
|
||||||
public abstract ParserResultDto<TDto> Parse(Stream file, TOptions options);
|
|
||||||
|
|
||||||
public abstract Stream GetTemplateFile();
|
|
||||||
|
|
||||||
protected virtual ValidationResultDto<TDto> ValidateRow(int rowNumber,
|
|
||||||
IDictionary<string, int> columnNumbers,
|
|
||||||
TDto dto)
|
|
||||||
{
|
|
||||||
var validationContext = new ValidationContext(dto, serviceProvider: null, items: null);
|
|
||||||
|
|
||||||
if (dto is IValidatableObject dtoWithValidateMethod)
|
|
||||||
{
|
|
||||||
var validationResults = dtoWithValidateMethod.Validate(validationContext);
|
|
||||||
|
|
||||||
foreach (var validationResult in validationResults)
|
|
||||||
ValidationResults.Add(validationResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Validator.TryValidateObject(dto, validationContext, ValidationResults, true))
|
|
||||||
{
|
|
||||||
var validRow = new ValidationResultDto<TDto>
|
|
||||||
{
|
|
||||||
Item = dto
|
|
||||||
};
|
|
||||||
|
|
||||||
return validRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
var invalidRow = new ValidationResultDto<TDto>
|
|
||||||
{
|
|
||||||
Item = dto,
|
|
||||||
};
|
|
||||||
|
|
||||||
var warnings = new List<ValidationResult>();
|
|
||||||
|
|
||||||
foreach (var validationResult in from v in ValidationResults
|
|
||||||
let memberNames = v.MemberNames.Where(columnNumbers.ContainsKey)
|
|
||||||
select memberNames.Select(x =>
|
|
||||||
{
|
|
||||||
var columnNumber = columnNumbers[x];
|
|
||||||
var errorMessage = v.ErrorMessage;
|
|
||||||
var warningMessage = string.Format(IParserService.MessageTemplate, SheetName, rowNumber, columnNumber, errorMessage);
|
|
||||||
var warning = new ValidationResult(warningMessage, new[] { x });
|
|
||||||
return warning;
|
|
||||||
}))
|
|
||||||
{
|
|
||||||
warnings.AddRange(validationResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidRow.Warnings = warnings;
|
|
||||||
|
|
||||||
return invalidRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual ParserResultDto<TDto> ParseExcelSheet(IXLWorksheet sheet,
|
|
||||||
Func<IXLRow, ValidationResultDto<TDto>> parseRow,
|
|
||||||
int columnCount,
|
|
||||||
int headerRowsCount = 0)
|
|
||||||
{
|
|
||||||
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < columnCount)
|
|
||||||
throw new FileFormatException($"Лист {SheetName} содержит меньшее количество столбцов.");
|
|
||||||
|
|
||||||
var count = sheet.RowsUsed().Count() - headerRowsCount;
|
|
||||||
|
|
||||||
if (count > 1024)
|
|
||||||
throw new FileFormatException($"Лист {SheetName} содержит слишком большое количество строк.");
|
|
||||||
|
|
||||||
if (count <= 0)
|
|
||||||
return new ParserResultDto<TDto>();
|
|
||||||
|
|
||||||
var dtos = new List<ValidationResultDto<TDto>>(count);
|
|
||||||
var warnings = new List<ValidationResult>();
|
|
||||||
|
|
||||||
for (var i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
var row = sheet.Row(1 + i + headerRowsCount);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var dto = parseRow.Invoke(row);
|
|
||||||
dtos.Add(dto);
|
|
||||||
}
|
|
||||||
catch (FileFormatException ex)
|
|
||||||
{
|
|
||||||
var warning = new ValidationResult(ex.Message);
|
|
||||||
warnings.Add(warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var parserResult = new ParserResultDto<TDto>
|
|
||||||
{
|
|
||||||
Item = dtos
|
|
||||||
};
|
|
||||||
|
|
||||||
if (warnings.Any())
|
|
||||||
parserResult.Warnings = warnings;
|
|
||||||
|
|
||||||
return parserResult;
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,6 @@ using System.Linq;
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.ProcessMapPlan;
|
using AsbCloudApp.Data.ProcessMapPlan;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Services;
|
|
||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
@ -48,73 +47,7 @@ public class ProcessMapPlanDrillingParser : ProcessMapPlanParser<ProcessMapPlanD
|
|||||||
|
|
||||||
protected override string SheetName => "План";
|
protected override string SheetName => "План";
|
||||||
|
|
||||||
protected override string TemplateFileName => "ProcessMapPlanDrillingTemplate.xlsx";
|
protected override IDictionary<string, int> PropertyColumnNumbers => new Dictionary<string, int>
|
||||||
|
|
||||||
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.DepthStart), columnDepthStart },
|
||||||
{ nameof(ProcessMapPlanDrillingDto.DepthEnd), columnDepthEnd },
|
{ nameof(ProcessMapPlanDrillingDto.DepthEnd), columnDepthEnd },
|
||||||
@ -134,6 +67,56 @@ public class ProcessMapPlanDrillingParser : ProcessMapPlanParser<ProcessMapPlanD
|
|||||||
{ nameof(ProcessMapPlanDrillingDto.Comment), columnComment }
|
{ nameof(ProcessMapPlanDrillingDto.Comment), columnComment }
|
||||||
};
|
};
|
||||||
|
|
||||||
return ValidateRow(row.RowNumber(), columnNumbers, dto);
|
protected override string TemplateFileName => "ProcessMapPlanDrillingTemplate.xlsx";
|
||||||
|
|
||||||
|
protected override ProcessMapPlanDrillingDto ParseRow(IXLRow row)
|
||||||
|
{
|
||||||
|
var sectionCaption = row.Cell(columnSection).GetCellValue<string>()?.Trim().ToLower();
|
||||||
|
var modeName = row.Cell(columnMode).GetCellValue<string>()?.Trim().ToLower();
|
||||||
|
|
||||||
|
var section = sections.FirstOrDefault(s =>
|
||||||
|
string.Equals(s.Caption.Trim(), sectionCaption?.Trim(), StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
|
||||||
|
if (section is null)
|
||||||
|
{
|
||||||
|
var message = string.Format(XLMessageTemplates.ProblemDetailsTemplate, SheetName, row.RowNumber(), columnSection,
|
||||||
|
"Указана некорректная секция");
|
||||||
|
throw new FileFormatException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
var idMode = GetIdMode(modeName);
|
||||||
|
|
||||||
|
if (idMode is null)
|
||||||
|
{
|
||||||
|
var message = string.Format(XLMessageTemplates.ProblemDetailsTemplate, SheetName, row.RowNumber(), columnSection,
|
||||||
|
"Указан некорректный режим бурения");
|
||||||
|
throw new FileFormatException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dto = new ProcessMapPlanDrillingDto
|
||||||
|
{
|
||||||
|
IdWellSectionType = section.Id,
|
||||||
|
Section = section.Caption,
|
||||||
|
IdMode = idMode.Value,
|
||||||
|
Mode = modeName,
|
||||||
|
DepthStart = row.Cell(columnDepthStart).GetCellValue<double>(),
|
||||||
|
DepthEnd = row.Cell(columnDepthEnd).GetCellValue<double>(),
|
||||||
|
AxialLoadPlan = row.Cell(columnAxialLoadPlan).GetCellValue<double>(),
|
||||||
|
AxialLoadLimitMax = row.Cell(columnAxialLoadLimitMax).GetCellValue<double>(),
|
||||||
|
DeltaPressurePlan = row.Cell(columnPressurePlan).GetCellValue<double>(),
|
||||||
|
DeltaPressureLimitMax = row.Cell(columnPressureLimitMax).GetCellValue<double>(),
|
||||||
|
TopDriveTorquePlan = row.Cell(columnTopDriveTorquePlan).GetCellValue<double>(),
|
||||||
|
TopDriveTorqueLimitMax = row.Cell(columnTopDriveTorqueLimitMax).GetCellValue<double>(),
|
||||||
|
TopDriveSpeedPlan = row.Cell(columnTopDriveSpeedPlan).GetCellValue<double>(),
|
||||||
|
TopDriveSpeedLimitMax = row.Cell(columnTopDriveSpeedLimitMax).GetCellValue<double>(),
|
||||||
|
FlowPlan = row.Cell(columnFlowPlan).GetCellValue<double>(),
|
||||||
|
FlowLimitMax = row.Cell(columnFlowLimitMax).GetCellValue<double>(),
|
||||||
|
RopPlan = row.Cell(columnRopPlan).GetCellValue<double>(),
|
||||||
|
UsageSaub = row.Cell(columnUsageSaub).GetCellValue<double>(),
|
||||||
|
UsageSpin = row.Cell(columnUsageSpin).GetCellValue<double>(),
|
||||||
|
Comment = row.Cell(columnComment).GetCellValue<string>() ?? string.Empty
|
||||||
|
};
|
||||||
|
|
||||||
|
return dto;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ using ClosedXML.Excel;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Parser;
|
namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Parser;
|
||||||
|
|
||||||
public abstract class ProcessMapPlanParser<TDto> : ParserServiceBase<TDto, IParserOptionsRequest>
|
public abstract class ProcessMapPlanParser<TDto> : ParserExcelService<TDto, IParserOptionsRequest>
|
||||||
where TDto : ProcessMapPlanBaseDto
|
where TDto : ProcessMapPlanBaseDto
|
||||||
{
|
{
|
||||||
protected ProcessMapPlanParser(IServiceProvider serviceProvider)
|
protected ProcessMapPlanParser(IServiceProvider serviceProvider)
|
||||||
@ -21,15 +21,13 @@ public abstract class ProcessMapPlanParser<TDto> : ParserServiceBase<TDto, IPars
|
|||||||
|
|
||||||
protected abstract string TemplateFileName { get; }
|
protected abstract string TemplateFileName { get; }
|
||||||
|
|
||||||
protected abstract ValidationResultDto<TDto> ParseRow(IXLRow row);
|
|
||||||
|
|
||||||
public override ParserResultDto<TDto> Parse(Stream file, IParserOptionsRequest options)
|
public override ParserResultDto<TDto> Parse(Stream file, IParserOptionsRequest options)
|
||||||
{
|
{
|
||||||
using var workbook = new XLWorkbook(file);
|
using var workbook = new XLWorkbook(file);
|
||||||
|
|
||||||
var sheet = workbook.GetWorksheet(SheetName);
|
var sheet = workbook.GetWorksheet(SheetName);
|
||||||
|
|
||||||
var processMaps = ParseExcelSheet(sheet, ParseRow, ColumnCount, HeaderRowsCount);
|
var processMaps = ParseExcelSheet(sheet, ColumnCount, HeaderRowsCount);
|
||||||
return processMaps;
|
return processMaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using AsbCloudApp.Data;
|
using System.Collections.Generic;
|
||||||
using AsbCloudApp.Data.Trajectory;
|
using AsbCloudApp.Data.Trajectory;
|
||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
@ -7,33 +7,48 @@ namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
|
|||||||
|
|
||||||
public class TrajectoryFactManualParser : TrajectoryParser<TrajectoryGeoFactDto>
|
public class TrajectoryFactManualParser : TrajectoryParser<TrajectoryGeoFactDto>
|
||||||
{
|
{
|
||||||
protected override string SheetName => "Фактическая траектория";
|
#region Columns
|
||||||
protected override string TemplateFileName => "TrajectoryFactManualTemplate.xlsx";
|
|
||||||
|
private const int columnWellboreDepth = 1;
|
||||||
|
private const int columnZenithAngle = 2;
|
||||||
|
private const int columnAzimuthGeo = 3;
|
||||||
|
private const int columnAzimuthMagnetic = 4;
|
||||||
|
private const int columnVerticalDepth = 5;
|
||||||
|
private const int columnComment = 6;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
public TrajectoryFactManualParser(IServiceProvider serviceProvider)
|
public TrajectoryFactManualParser(IServiceProvider serviceProvider)
|
||||||
: base(serviceProvider)
|
: base(serviceProvider)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ValidationResultDto<TrajectoryGeoFactDto> ParseRow(IXLRow row)
|
protected override string SheetName => "Фактическая траектория";
|
||||||
|
|
||||||
|
protected override string TemplateFileName => "TrajectoryFactManualTemplate.xlsx";
|
||||||
|
|
||||||
|
protected override IDictionary<string, int> PropertyColumnNumbers => new Dictionary<string, int>
|
||||||
{
|
{
|
||||||
var trajectoryRow = new TrajectoryGeoFactDto
|
{ nameof(TrajectoryGeoFactDto.WellboreDepth), columnWellboreDepth },
|
||||||
{
|
{ nameof(TrajectoryGeoFactDto.ZenithAngle), columnZenithAngle },
|
||||||
WellboreDepth = row.Cell(1).GetCellValue<double>(),
|
{ nameof(TrajectoryGeoFactDto.AzimuthGeo), columnAzimuthGeo },
|
||||||
ZenithAngle = row.Cell(2).GetCellValue<double>(),
|
{ nameof(TrajectoryGeoFactDto.AzimuthMagnetic), columnAzimuthMagnetic },
|
||||||
AzimuthGeo = row.Cell(3).GetCellValue<double>(),
|
{ nameof(TrajectoryGeoFactDto.VerticalDepth), columnVerticalDepth },
|
||||||
AzimuthMagnetic = row.Cell(4).GetCellValue<double>(),
|
{ nameof(TrajectoryGeoFactDto.Comment), columnComment }
|
||||||
VerticalDepth = row.Cell(5).GetCellValue<double>(),
|
|
||||||
Comment = row.Cell(6).GetCellValue<string?>()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: Добавить валидацию модели
|
protected override TrajectoryGeoFactDto ParseRow(IXLRow row)
|
||||||
|
|
||||||
var validationResult = new ValidationResultDto<TrajectoryGeoFactDto>
|
|
||||||
{
|
{
|
||||||
Item = trajectoryRow
|
var dto = new TrajectoryGeoFactDto
|
||||||
|
{
|
||||||
|
WellboreDepth = row.Cell(columnWellboreDepth).GetCellValue<double>(),
|
||||||
|
ZenithAngle = row.Cell(columnZenithAngle).GetCellValue<double>(),
|
||||||
|
AzimuthGeo = row.Cell(columnAzimuthGeo).GetCellValue<double>(),
|
||||||
|
AzimuthMagnetic = row.Cell(columnAzimuthMagnetic).GetCellValue<double>(),
|
||||||
|
VerticalDepth = row.Cell(columnVerticalDepth).GetCellValue<double>(),
|
||||||
|
Comment = row.Cell(columnComment).GetCellValue<string?>()
|
||||||
};
|
};
|
||||||
|
|
||||||
return validationResult;
|
return dto;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ using AsbCloudApp.Requests.ParserOptions;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
|
namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
|
||||||
|
|
||||||
public abstract class TrajectoryParser<T> : ParserServiceBase<T, IParserOptionsRequest>
|
public abstract class TrajectoryParser<T> : ParserExcelService<T, IParserOptionsRequest>
|
||||||
where T : TrajectoryGeoDto
|
where T : TrajectoryGeoDto
|
||||||
{
|
{
|
||||||
private const int HeaderRowsCount = 2;
|
private const int HeaderRowsCount = 2;
|
||||||
@ -21,8 +21,6 @@ public abstract class TrajectoryParser<T> : ParserServiceBase<T, IParserOptionsR
|
|||||||
|
|
||||||
protected abstract string TemplateFileName { get; }
|
protected abstract string TemplateFileName { get; }
|
||||||
|
|
||||||
protected abstract ValidationResultDto<T> ParseRow(IXLRow row);
|
|
||||||
|
|
||||||
public override Stream GetTemplateFile() =>
|
public override Stream GetTemplateFile() =>
|
||||||
Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateFileName)
|
Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateFileName)
|
||||||
?? throw new ArgumentNullException($"Файл '{TemplateFileName}' не найден");
|
?? throw new ArgumentNullException($"Файл '{TemplateFileName}' не найден");
|
||||||
@ -33,7 +31,7 @@ public abstract class TrajectoryParser<T> : ParserServiceBase<T, IParserOptionsR
|
|||||||
|
|
||||||
var sheet = workbook.GetWorksheet(SheetName);
|
var sheet = workbook.GetWorksheet(SheetName);
|
||||||
|
|
||||||
var trajectoryRows = ParseExcelSheet(sheet, ParseRow, ColumnCount, HeaderRowsCount);
|
var trajectoryRows = ParseExcelSheet(sheet, ColumnCount, HeaderRowsCount);
|
||||||
return trajectoryRows;
|
return trajectoryRows;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.Trajectory;
|
using AsbCloudApp.Data.Trajectory;
|
||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
@ -7,34 +8,51 @@ namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
|
|||||||
|
|
||||||
public class TrajectoryPlanParser : TrajectoryParser<TrajectoryGeoPlanDto>
|
public class TrajectoryPlanParser : TrajectoryParser<TrajectoryGeoPlanDto>
|
||||||
{
|
{
|
||||||
protected override string SheetName => "Плановая траектория";
|
#region Columns
|
||||||
protected override string TemplateFileName => "TrajectoryPlanTemplate.xlsx";
|
|
||||||
|
private const int columnWellboreDepth = 1;
|
||||||
|
private const int columnZenithAngle = 2;
|
||||||
|
private const int columnAzimuthGeo = 3;
|
||||||
|
private const int columnAzimuthMagnetic = 4;
|
||||||
|
private const int columnVerticalDepth = 5;
|
||||||
|
private const int columnRadius = 6;
|
||||||
|
private const int columnComment = 7;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
public TrajectoryPlanParser(IServiceProvider serviceProvider)
|
public TrajectoryPlanParser(IServiceProvider serviceProvider)
|
||||||
: base(serviceProvider)
|
: base(serviceProvider)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ValidationResultDto<TrajectoryGeoPlanDto> ParseRow(IXLRow row)
|
protected override string SheetName => "Плановая траектория";
|
||||||
|
|
||||||
|
protected override string TemplateFileName => "TrajectoryPlanTemplate.xlsx";
|
||||||
|
|
||||||
|
protected override IDictionary<string, int> PropertyColumnNumbers => new Dictionary<string, int>
|
||||||
{
|
{
|
||||||
var trajectoryRow = new TrajectoryGeoPlanDto
|
{ nameof(TrajectoryGeoPlanDto.WellboreDepth), columnWellboreDepth },
|
||||||
{
|
{ nameof(TrajectoryGeoPlanDto.ZenithAngle), columnZenithAngle },
|
||||||
WellboreDepth = row.Cell(1).GetCellValue<double>(),
|
{ nameof(TrajectoryGeoPlanDto.AzimuthGeo), columnAzimuthGeo },
|
||||||
ZenithAngle = row.Cell(2).GetCellValue<double>(),
|
{ nameof(TrajectoryGeoPlanDto.AzimuthMagnetic), columnAzimuthMagnetic },
|
||||||
AzimuthGeo = row.Cell(3).GetCellValue<double>(),
|
{ nameof(TrajectoryGeoPlanDto.VerticalDepth), columnVerticalDepth },
|
||||||
AzimuthMagnetic = row.Cell(4).GetCellValue<double>(),
|
{ nameof(TrajectoryGeoPlanDto.Radius), columnRadius },
|
||||||
VerticalDepth = row.Cell(5).GetCellValue<double>(),
|
{ nameof(TrajectoryGeoPlanDto.Comment), columnComment }
|
||||||
Radius = row.Cell(6).GetCellValue<double>(),
|
|
||||||
Comment = row.Cell(7).GetCellValue<string?>()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: Добавить валидацию модели
|
protected override TrajectoryGeoPlanDto ParseRow(IXLRow row)
|
||||||
|
|
||||||
var validationResult = new ValidationResultDto<TrajectoryGeoPlanDto>
|
|
||||||
{
|
{
|
||||||
Item = trajectoryRow
|
var dto = new TrajectoryGeoPlanDto
|
||||||
|
{
|
||||||
|
WellboreDepth = row.Cell(columnWellboreDepth).GetCellValue<double>(),
|
||||||
|
ZenithAngle = row.Cell(columnZenithAngle).GetCellValue<double>(),
|
||||||
|
AzimuthGeo = row.Cell(columnAzimuthGeo).GetCellValue<double>(),
|
||||||
|
AzimuthMagnetic = row.Cell(columnAzimuthMagnetic).GetCellValue<double>(),
|
||||||
|
VerticalDepth = row.Cell(columnVerticalDepth).GetCellValue<double>(),
|
||||||
|
Radius = row.Cell(columnRadius).GetCellValue<double>(),
|
||||||
|
Comment = row.Cell(columnComment).GetCellValue<string?>()
|
||||||
};
|
};
|
||||||
|
|
||||||
return validationResult;
|
return dto;
|
||||||
}
|
}
|
||||||
}
|
}
|
17
AsbCloudInfrastructure/ValidationExtensions.cs
Normal file
17
AsbCloudInfrastructure/ValidationExtensions.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure;
|
||||||
|
|
||||||
|
public static class ValidationExtensions
|
||||||
|
{
|
||||||
|
public static bool Validate(this IValidatableObject validatableObject, ICollection<ValidationResult> validationResults)
|
||||||
|
{
|
||||||
|
var validationContext = new ValidationContext(validatableObject, serviceProvider: null, items: null);
|
||||||
|
|
||||||
|
foreach (var validationResult in validatableObject.Validate(validationContext))
|
||||||
|
validationResults.Add(validationResult);
|
||||||
|
|
||||||
|
return Validator.TryValidateObject(validatableObject, validationContext, validationResults, true);
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AsbCloudApp.Services;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure;
|
namespace AsbCloudInfrastructure;
|
||||||
|
|
||||||
@ -10,7 +9,7 @@ public static class XLExtentions
|
|||||||
{
|
{
|
||||||
public static IXLWorksheet GetWorksheet(this IXLWorkbook workbook, string sheetName) =>
|
public static IXLWorksheet GetWorksheet(this IXLWorkbook workbook, string sheetName) =>
|
||||||
workbook.Worksheets.FirstOrDefault(ws => string.Equals(ws.Name.Trim(), sheetName.Trim(), StringComparison.CurrentCultureIgnoreCase))
|
workbook.Worksheets.FirstOrDefault(ws => string.Equals(ws.Name.Trim(), sheetName.Trim(), StringComparison.CurrentCultureIgnoreCase))
|
||||||
?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}.");
|
?? throw new FileFormatException(string.Format(XLMessageTemplates.NotFoundSheetTemplate, sheetName));
|
||||||
|
|
||||||
public static IXLCell SetCellValue<T>(this IXLCell cell, T value)
|
public static IXLCell SetCellValue<T>(this IXLCell cell, T value)
|
||||||
{
|
{
|
||||||
@ -40,7 +39,7 @@ public static class XLExtentions
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
var message = string.Format(IParserService.MessageTemplate, cell.Worksheet.Name, cell.Address.RowNumber,
|
var message = string.Format(XLMessageTemplates.ProblemDetailsTemplate, cell.Worksheet.Name, cell.Address.RowNumber,
|
||||||
cell.Address.ColumnNumber, "Содержит некорректное значение");
|
cell.Address.ColumnNumber, "Содержит некорректное значение");
|
||||||
throw new FileFormatException(message);
|
throw new FileFormatException(message);
|
||||||
}
|
}
|
||||||
|
12
AsbCloudInfrastructure/XLMessageTemplates.cs
Normal file
12
AsbCloudInfrastructure/XLMessageTemplates.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace AsbCloudInfrastructure;
|
||||||
|
|
||||||
|
public static class XLMessageTemplates
|
||||||
|
{
|
||||||
|
public const string ProblemDetailsTemplate = "Лист: {0}, Строка: {1}, Столбец: {2}. {3}";
|
||||||
|
|
||||||
|
public const string NotFoundSheetTemplate = "Книга excel не содержит листа {0}";
|
||||||
|
|
||||||
|
public const string ExceedingMaxRowLimitTemplate = "Лист {0} содержит слишком большое количество строк";
|
||||||
|
|
||||||
|
public const string FewerColumnsTemplate = "Лист {0} содержит меньшее количество столбцов";
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user