diff --git a/AsbCloudApp/Data/WellOperationImport/RowDto.cs b/AsbCloudApp/Data/WellOperationImport/RowDto.cs
index 5b6691f4..8f15c3bf 100644
--- a/AsbCloudApp/Data/WellOperationImport/RowDto.cs
+++ b/AsbCloudApp/Data/WellOperationImport/RowDto.cs
@@ -25,7 +25,7 @@ public class RowDto
///
/// Описание категории
///
- public string CategoryInfo { get; set; } = null!;
+ public string? CategoryInfo { get; set; }
///
/// Начальная глубина операции
diff --git a/AsbCloudApp/Data/WellOperationImport/WellOperationImportOptionsDto.cs b/AsbCloudApp/Data/WellOperationImport/WellOperationImportOptionsDto.cs
index b085754f..285f9d67 100644
--- a/AsbCloudApp/Data/WellOperationImport/WellOperationImportOptionsDto.cs
+++ b/AsbCloudApp/Data/WellOperationImport/WellOperationImportOptionsDto.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace AsbCloudApp.Data.WellOperationImport;
@@ -5,28 +6,45 @@ namespace AsbCloudApp.Data.WellOperationImport;
///
/// Опции для настройки парсинга документа
///
-public class WellOperationParserOptionsDto
+public class WellOperationParserOptionsDto : IValidatableObject
{
///
/// Название листа
///
- [StringLength(250, MinimumLength =1, ErrorMessage = "Название листа должно быть задано")]
- public string SheetName { get; set; } = null!;
-
+ public string? SheetName { get; set; }
+
///
- /// Id шаблона
+ /// Тип операции
+ /// 0 - плановая операция
+ /// 1 - фактическая операция
+ ///
+ [Required]
+ [Range(0, 1, ErrorMessage = "Тип операции недопустим. Допустимые: 0, 1")]
+ public int IdType { get; set; }
+
+ ///
+ /// Тип шаблона
/// 0 - Дефолтный шаблон
/// 1 - Газпром хантос
///
+ [Required]
+ [Range(0, 1, ErrorMessage = "Тип шаблона недопустим. Допустимые: 0, 1")]
public int IdTemplate { get; set; }
///
/// Начальная строка
///
public int? StartRow { get; set; }
-
+
///
/// Конечная строка
///
public int? EndRow { get; set; }
+
+ ///
+ public IEnumerable Validate(ValidationContext validationContext)
+ {
+ if (IdTemplate != 0 && string.IsNullOrWhiteSpace(SheetName))
+ yield return new ValidationResult("Название листа должно быть задано", new[] { nameof(SheetName) });
+ }
}
\ No newline at end of file
diff --git a/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs b/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs
index 1da68cf8..7a122062 100644
--- a/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs
+++ b/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs
@@ -14,13 +14,11 @@ public interface IWellOperationImportService
/// Загрузить из excel список операций
///
///
- ///
///
///
- ///
+ ///
///
///
- Task ImportAsync(int idWell, int idUser, int idType, Stream stream, WellOperationParserOptionsDto options,
- bool deleteWellOperationsBeforeImport,
+ Task ImportAsync(int idWell, int idUser, Stream stream, WellOperationParserOptionsDto options, bool deleteBeforeImport,
CancellationToken cancellationToken);
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs
index ef9ed499..d4890934 100644
--- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using AsbCloudApp.Data.WellOperationImport;
-using AsbCloudApp.Exceptions;
using AsbCloudApp.Services.WellOperationImport;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.WellOperationImport.Constants;
@@ -25,11 +24,12 @@ public class WellOperationDefaultExcelParser : IWellOperationExcelParser
private static IEnumerable ParseWorkbook(IXLWorkbook workbook, WellOperationParserOptionsDto options)
{
- if (string.IsNullOrWhiteSpace(options.SheetName))
- throw new ArgumentInvalidException(nameof(options.SheetName), "Не указано название листа");
+ var sheetName = options.IdType == WellOperation.IdOperationTypePlan
+ ? DefaultTemplateInfo.SheetNamePlan
+ : DefaultTemplateInfo.SheetNameFact;
var sheet = workbook.Worksheets.FirstOrDefault(ws =>
- string.Equals(ws.Name, options.SheetName, StringComparison.CurrentCultureIgnoreCase))
+ string.Equals(ws.Name, sheetName, StringComparison.CurrentCultureIgnoreCase))
?? throw new FileFormatException($"Книга excel не содержит листа '{options.SheetName}'");
return ParseSheet(sheet);
@@ -81,12 +81,12 @@ public class WellOperationDefaultExcelParser : IWellOperationExcelParser
Number = xlRow.RowNumber(),
Section = xlRow.Cell(DefaultTemplateInfo.ColumnSection).GetCellValue(),
Category = xlRow.Cell(DefaultTemplateInfo.ColumnCategory).GetCellValue(),
- CategoryInfo = xlRow.Cell(DefaultTemplateInfo.ColumnCategoryInfo).GetCellValue(),
+ CategoryInfo = xlRow.Cell(DefaultTemplateInfo.ColumnCategoryInfo).GetCellValue(),
DepthStart = xlRow.Cell(DefaultTemplateInfo.ColumnDepthStart).GetCellValue(),
DepthEnd = xlRow.Cell(DefaultTemplateInfo.ColumnDepthEnd).GetCellValue(),
Date = xlRow.Cell(DefaultTemplateInfo.ColumnDate).GetCellValue(),
Duration = xlRow.Cell(DefaultTemplateInfo.ColumnDuration).GetCellValue(),
- Comment = xlRow.Cell(DefaultTemplateInfo.ColumnComment).GetCellValue()
+ Comment = xlRow.Cell(DefaultTemplateInfo.ColumnComment).GetCellValue()
};
}
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs
index d1ce47cd..a484a2da 100644
--- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -20,7 +19,7 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
{
public int RowNumber { get; set; }
- public string CategoryInfo { get; set; } = null!;
+ public string? CategoryInfo { get; set; }
public double SectionDiameter { get; set; }
@@ -31,17 +30,11 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
public DateTime Date { get; set; }
}
- private readonly CosineSimilarity cosineSimilarity;
+ private readonly CosineSimilarity cosineSimilarity = new();
private readonly Dictionary operationDict = InitDict("Operations.txt", '=');
private readonly Dictionary sectionDict = InitDict("Sections.txt", '=');
private readonly Dictionary operationAttributesDict = InitDict("OperationAttributes.txt", '=');
-
-
- public WellOperationGazpromKhantosExcelParser()
- {
- cosineSimilarity = new CosineSimilarity();
- }
public int IdTemplate => Templates.IdGazpromKhantosTemplate;
@@ -56,9 +49,6 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
private IEnumerable ParseWorkBook(IXLWorkbook workbook, WellOperationParserOptionsDto options)
{
- if (string.IsNullOrWhiteSpace(options.SheetName))
- throw new ArgumentInvalidException(nameof(options.SheetName), "Не указано название листа");
-
if (options.StartRow is null or < 1 or > 1048576)
throw new ArgumentInvalidException(nameof(options.StartRow), "Некорректное значение начальной строки");
@@ -97,7 +87,7 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
operations.Add(new Operation
{
RowNumber = xlRow.RowNumber(),
- CategoryInfo = xlRow.Cell(operationAttributes[OperationAttributes.CategoryInfo]).GetCellValue(),
+ CategoryInfo = xlRow.Cell(operationAttributes[OperationAttributes.CategoryInfo]).GetCellValue(),
SectionDiameter =xlRow.Cell(operationAttributes[OperationAttributes.SectionDiameter]).GetCellValue(),
Depth = xlRow.Cell(operationAttributes[OperationAttributes.Depth]).GetCellValue(),
Duration = xlRow.Cell(operationAttributes[OperationAttributes.Duration]).GetCellValue(),
@@ -198,8 +188,11 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
return operationAttributes is not null && operationAttributes.Count == countOperationAttributes ? operationAttributes : null;
}
- private string? GetValueDictionary(IDictionary dict, string cellValue, double? minSimilarity)
+ private string? GetValueDictionary(IDictionary dict, string? cellValue, double? minSimilarity)
{
+ if (string.IsNullOrWhiteSpace(cellValue))
+ return null;
+
var similarValues = new List<(double similarity, string value)>();
var profile1 = cosineSimilarity.GetProfile(cellValue);
diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs
index af84f3a9..b7e79b4a 100644
--- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs
@@ -10,8 +10,6 @@ using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services.WellOperationImport;
-using AsbCloudDb.Model;
-using AsbCloudInfrastructure.Services.WellOperationImport.Constants;
namespace AsbCloudInfrastructure.Services.WellOperationImport;
@@ -31,35 +29,25 @@ public class WellOperationImportService : IWellOperationImportService
this.wellOperationRepository = wellOperationRepository;
}
- public async Task ImportAsync(int idWell, int idUser, int idType, Stream stream, WellOperationParserOptionsDto options,
- bool deleteWellOperationsBeforeImport, CancellationToken cancellationToken)
+ public async Task ImportAsync(int idWell, int idUser, Stream stream, WellOperationParserOptionsDto options, bool deleteBeforeImport,
+ CancellationToken cancellationToken)
{
- var excelParser = excelParsers.FirstOrDefault(p => p.IdTemplate == options.IdTemplate && p.IdTypes.Contains(idType))
- ?? throw new ArgumentInvalidException(nameof(options.IdTemplate), "Невозможно импортировать файл");
-
- if (idType != WellOperation.IdOperationTypePlan && idType != WellOperation.IdOperationTypeFact)
- throw new ArgumentInvalidException(nameof(idType), "Операции не существует");
-
- RowDto[] rows;
+ var excelParser = excelParsers.FirstOrDefault(p =>
+ p.IdTemplate == options.IdTemplate &&
+ p.IdTypes.Contains(options.IdType))
+ ?? throw new ArgumentInvalidException(nameof(options.IdTemplate), "Невозможно импортировать файл");
+
+ IEnumerable rows;
var validationErrors = new List();
var sections = wellOperationRepository.GetSectionTypes();
var categories = wellOperationRepository.GetCategories(false);
- switch (options.IdTemplate)
+ rows = options.IdTemplate switch
{
- case 0:
- options.SheetName = idType == WellOperation.IdOperationTypePlan
- ? DefaultTemplateInfo.SheetNamePlan
- : DefaultTemplateInfo.SheetNameFact;
- rows = excelParser.Parse(stream, options).ToArray();
- break;
- default:
- if (string.IsNullOrWhiteSpace(options.SheetName))
- throw new FileFormatException("Не указано название листа");
- rows = excelParser.Parse(stream, options).ToArray();
- break;
- }
+ 0 => excelParser.Parse(stream, options),
+ _ => excelParser.Parse(stream, options)
+ };
var operations = new List();
@@ -80,16 +68,20 @@ public class WellOperationImportService : IWellOperationImportService
throw new FileFormatException($"Лист '{options.SheetName}'. В строке '{row.Number}' не удалось определить операцию");
if (row.DepthStart is not (>= 0d and <= 20_000d))
- throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная глубина на начало операции");
+ throw new FileFormatException(
+ $"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная глубина на начало операции");
if (row.DepthEnd is not (>= 0d and <= 20_000d))
- throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная глубина на конец операции");
+ throw new FileFormatException(
+ $"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная глубина на конец операции");
if (row.Date < dateLimitMin && row.Date > dateLimitMax)
- throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' неправильно получена дата начала операции");
+ throw new FileFormatException(
+ $"Лист '{options.SheetName}'. Строка '{row.Number}' неправильно получена дата начала операции");
if (operations.LastOrDefault()?.DateStart > row.Date)
- throw new FileFormatException($"Лист '{options.SheetName}' строка '{row.Number}' дата позднее даты предыдущей операции");
+ throw new FileFormatException(
+ $"Лист '{options.SheetName}' строка '{row.Number}' дата позднее даты предыдущей операции");
if (row.Duration is not (>= 0d and <= 240d))
throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная длительность операции");
@@ -98,7 +90,7 @@ public class WellOperationImportService : IWellOperationImportService
{
IdWell = idWell,
IdUser = idUser,
- IdType = idType,
+ IdType = options.IdType,
IdWellSectionType = section.Id,
IdCategory = category.Id,
CategoryInfo = row.CategoryInfo,
@@ -120,19 +112,19 @@ public class WellOperationImportService : IWellOperationImportService
if (validationErrors.Any())
throw new FileFormatException(string.Join("\r\n", validationErrors));
- if(!operations.Any())
+ if (!operations.Any())
return;
- if (deleteWellOperationsBeforeImport)
+ if (deleteBeforeImport)
{
var existingOperations = await wellOperationRepository.GetAsync(new WellOperationRequest
{
IdWell = idWell
}, cancellationToken);
-
+
await wellOperationRepository.DeleteAsync(existingOperations.Select(o => o.Id), cancellationToken);
}
- await wellOperationRepository.InsertRangeAsync(operations, cancellationToken);
+ await wellOperationRepository.InsertRangeAsync(operations, cancellationToken);
}
}
\ No newline at end of file
diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs
index 189b9747..f2c2b695 100644
--- a/AsbCloudWebApi/Controllers/WellOperationController.cs
+++ b/AsbCloudWebApi/Controllers/WellOperationController.cs
@@ -290,25 +290,17 @@ namespace AsbCloudWebApi.Controllers
/// Импорт плановых операций из excel (xlsx) файла
///
/// id скважины
- /// Тип операции
- /// Начальная строка
- /// Конечная строка
+ /// Параметры для парсинга файла
/// Коллекция из одного файла xlsx
- /// Удалить операции перед импортом = 1, если файл валидный
- /// Название листа
- /// Токен отмены задачи
- /// Шаблон файла. 0 - стандартный, 1 - Газпромнефть Хантос
+ /// Удалить операции перед импортом = 1, если файл валидный
+ ///
///
- [HttpPost("import/{options}")]
+ [HttpPost("import/{deleteBeforeImport}")]
[Permission]
public async Task ImportAsync(int idWell,
- [Required] int idType,
- string? sheetName,
- [Required] int idTemplate,
- int? startRow,
- int? endRow,
+ [FromQuery] WellOperationParserOptionsDto options,
[FromForm] IFormFileCollection files,
- int options,
+ [Range(0, 1, ErrorMessage = "Недопустимое значение. Допустимые: 0, 1")] int deleteBeforeImport,
CancellationToken token)
{
var idCompany = User.GetCompanyId();
@@ -338,13 +330,7 @@ namespace AsbCloudWebApi.Controllers
try
{
- await wellOperationImportService.ImportAsync(idWell, idUser.Value, idType, stream, new WellOperationParserOptionsDto
- {
- SheetName = sheetName,
- IdTemplate = idTemplate,
- StartRow = startRow,
- EndRow = endRow
- }, (options & 1) > 0, token);
+ await wellOperationImportService.ImportAsync(idWell, idUser.Value, stream, options, (deleteBeforeImport & 1) > 0, token);
}
catch (FileFormatException ex)
{