diff --git a/AsbCloudApp/Data/WellOperationImport/Options/IWellOperationImportOptions.cs b/AsbCloudApp/Data/WellOperationImport/Options/IWellOperationImportOptions.cs
new file mode 100644
index 00000000..30b9cf8c
--- /dev/null
+++ b/AsbCloudApp/Data/WellOperationImport/Options/IWellOperationImportOptions.cs
@@ -0,0 +1,12 @@
+namespace AsbCloudApp.Data.WellOperationImport.Options;
+
+///
+/// Опции для парсинга
+///
+public interface IWellOperationImportOptions
+{
+ ///
+ /// Тип операции
+ ///
+ int IdType { get; }
+}
\ No newline at end of file
diff --git a/AsbCloudApp/Data/WellOperationImport/Options/WellOperationImportDefaultOptionsDto.cs b/AsbCloudApp/Data/WellOperationImport/Options/WellOperationImportDefaultOptionsDto.cs
new file mode 100644
index 00000000..a1db3d35
--- /dev/null
+++ b/AsbCloudApp/Data/WellOperationImport/Options/WellOperationImportDefaultOptionsDto.cs
@@ -0,0 +1,18 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace AsbCloudApp.Data.WellOperationImport.Options;
+
+///
+/// Опции для парсинга дефолтного шаблона
+///
+public class WellOperationImportDefaultOptionsDto : IWellOperationImportOptions
+{
+ ///
+ /// Тип операции
+ /// 0 - плановая операция
+ /// 1 - фактическая операция
+ ///
+ [Required]
+ [Range(0, 1, ErrorMessage = "Тип операции недопустим. Допустимые: 0, 1")]
+ public int IdType { get; set; }
+}
\ No newline at end of file
diff --git a/AsbCloudApp/Data/WellOperationImport/Options/WellOperationImportGazpromKhantosOptionsDto.cs b/AsbCloudApp/Data/WellOperationImport/Options/WellOperationImportGazpromKhantosOptionsDto.cs
new file mode 100644
index 00000000..d8b094c4
--- /dev/null
+++ b/AsbCloudApp/Data/WellOperationImport/Options/WellOperationImportGazpromKhantosOptionsDto.cs
@@ -0,0 +1,36 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace AsbCloudApp.Data.WellOperationImport.Options;
+
+///
+/// Опции для настройки парсинга документа ГПНХ(Хантос)
+///
+public class WellOperationImportGazpromKhantosOptionsDto : IWellOperationImportOptions
+{
+ ///
+ /// Название листа
+ ///
+ [Required]
+ [StringLength(250, MinimumLength = 1, ErrorMessage = "Название листа должно быть задано")]
+ public string SheetName { get; set; } = null!;
+
+ ///
+ /// Тип операции
+ /// 0 - плановая операция
+ ///
+ [Required]
+ [Range(0, 0, ErrorMessage = "Тип операции недопустим. Допустимый: 0")]
+ public int IdType { get; set; }
+
+ ///
+ /// Начальная строка
+ ///
+ [Required]
+ public int StartRow { get; set; }
+
+ ///
+ /// Конечная строка
+ ///
+ [Required]
+ public int EndRow { get; set; }
+}
\ No newline at end of file
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/SheetDto.cs b/AsbCloudApp/Data/WellOperationImport/SheetDto.cs
new file mode 100644
index 00000000..32091283
--- /dev/null
+++ b/AsbCloudApp/Data/WellOperationImport/SheetDto.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AsbCloudApp.Data.WellOperationImport;
+
+///
+/// Лист полученный из файла Excel
+///
+public class SheetDto
+{
+ ///
+ /// Название листа
+ ///
+ public string Name { get; set; } = null!;
+
+ ///
+ /// Строки
+ ///
+ public IEnumerable Rows { get; set; } = Enumerable.Empty();
+}
\ No newline at end of file
diff --git a/AsbCloudApp/Data/WellOperationImport/WellOperationImportOptionsDto.cs b/AsbCloudApp/Data/WellOperationImport/WellOperationImportOptionsDto.cs
deleted file mode 100644
index b085754f..00000000
--- a/AsbCloudApp/Data/WellOperationImport/WellOperationImportOptionsDto.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-
-namespace AsbCloudApp.Data.WellOperationImport;
-
-///
-/// Опции для настройки парсинга документа
-///
-public class WellOperationParserOptionsDto
-{
- ///
- /// Название листа
- ///
- [StringLength(250, MinimumLength =1, ErrorMessage = "Название листа должно быть задано")]
- public string SheetName { get; set; } = null!;
-
- ///
- /// Id шаблона
- /// 0 - Дефолтный шаблон
- /// 1 - Газпром хантос
- ///
- public int IdTemplate { get; set; }
-
- ///
- /// Начальная строка
- ///
- public int? StartRow { get; set; }
-
- ///
- /// Конечная строка
- ///
- public int? EndRow { get; set; }
-}
\ No newline at end of file
diff --git a/AsbCloudApp/Services/WellOperationImport/IWellOperationExcelParser.cs b/AsbCloudApp/Services/WellOperationImport/IWellOperationExcelParser.cs
index c8c8042a..7a695beb 100644
--- a/AsbCloudApp/Services/WellOperationImport/IWellOperationExcelParser.cs
+++ b/AsbCloudApp/Services/WellOperationImport/IWellOperationExcelParser.cs
@@ -1,29 +1,20 @@
-using System.Collections.Generic;
using System.IO;
using AsbCloudApp.Data.WellOperationImport;
+using AsbCloudApp.Data.WellOperationImport.Options;
namespace AsbCloudApp.Services.WellOperationImport;
///
/// Парсинг операций из excel файла
///
-public interface IWellOperationExcelParser
+public interface IWellOperationExcelParser
+ where TOptions : IWellOperationImportOptions
{
- ///
- /// Id шаблона
- ///
- int IdTemplate { get; }
-
- ///
- /// Типы операций, которые можно получить из файла
- ///
- IEnumerable IdTypes { get; }
-
- ///
- /// Метод парсинга документа
- ///
- ///
- ///
- ///
- IEnumerable Parse(Stream stream, WellOperationParserOptionsDto options);
+ ///
+ /// Метод парсинга документа
+ ///
+ ///
+ ///
+ ///
+ SheetDto Parse(Stream stream, TOptions options);
}
\ No newline at end of file
diff --git a/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs b/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs
index 1da68cf8..54e813d8 100644
--- a/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs
+++ b/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs
@@ -1,4 +1,3 @@
-using System.IO;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.WellOperationImport;
@@ -10,17 +9,14 @@ namespace AsbCloudApp.Services.WellOperationImport;
///
public interface IWellOperationImportService
{
- ///
- /// Загрузить из excel список операций
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- Task ImportAsync(int idWell, int idUser, int idType, Stream stream, WellOperationParserOptionsDto options,
- bool deleteWellOperationsBeforeImport,
- CancellationToken cancellationToken);
+ ///
+ /// Загрузить из excel список операций
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task ImportAsync(int idWell, int idUser, int idType, SheetDto sheet, bool deleteBeforeImport, CancellationToken cancellationToken);
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs
index 36a91cf3..01eea5cc 100644
--- a/AsbCloudInfrastructure/DependencyInjection.cs
+++ b/AsbCloudInfrastructure/DependencyInjection.cs
@@ -31,6 +31,7 @@ using AsbCloudInfrastructure.Services.AutoGeneratedDailyReports;
using AsbCloudApp.Services.WellOperationImport;
using AsbCloudInfrastructure.Services.WellOperationImport;
using AsbCloudInfrastructure.Services.ProcessMap.ProcessMapWellboreDevelopment;
+using AsbCloudApp.Data.WellOperationImport.Options;
using AsbCloudInfrastructure.Services.WellOperationImport.FileParser;
namespace AsbCloudInfrastructure
@@ -241,8 +242,8 @@ namespace AsbCloudInfrastructure
services.AddTransient();
services.AddTransient();
- services.AddTransient();
- services.AddTransient();
+ services.AddTransient, WellOperationDefaultExcelParser>();
+ services.AddTransient, WellOperationGazpromKhantosExcelParser>();
return services;
}
diff --git a/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs b/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs
deleted file mode 100644
index 30eee683..00000000
--- a/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-using ClosedXML.Excel;
-using System;
-
-namespace AsbCloudInfrastructure.Services.DailyReport
-{
-
- internal static class XLExtentions
- {
- public static IXLRange _SetValue(this IXLRange range, object value)
- {
- var mergedRange = range.Merge();
- mergedRange.FirstCell()._SetValue(value);
- var colWidth = mergedRange.FirstCell().WorksheetColumn().Width;
- var maxCharsToWrap = colWidth / (0.1d * mergedRange.FirstCell().Style.Font.FontSize);
- if (value is string valueString && valueString.Length > maxCharsToWrap)
- {
- var row = mergedRange.FirstCell().WorksheetRow();
- var baseHeight = row.Height;
- row.Height = 0.5d * baseHeight * Math.Ceiling(1d + valueString.Length / maxCharsToWrap);
- }
- mergedRange.Style.SetAllBorders()
- .Alignment.SetWrapText(true);
- return mergedRange;
- }
-
- public static IXLCell _SetValue(this IXLCell cell, object value)
- {
- switch (value)
- {
- case DateTime dateTime:
- cell._SetValue(dateTime);
- break;
- case IFormattable formattable:
- cell._SetValue(formattable);
- break;
- case string valueString:
- cell._SetValue(valueString);
- break;
- default:
- cell.Value = value;
- break;
- }
-
- return cell;
- }
-
- public static IXLCell _SetValue(this IXLCell cell, string value, bool adaptRowHeight = false)
- {
- cell.Value = value;
- cell.Style
- .SetAllBorders()
- .Alignment.WrapText = true;
-
- cell.Value = value;
- if (adaptRowHeight)
- {
- var colWidth = cell.WorksheetColumn().Width;
- var maxCharsToWrap = colWidth / (0.1d * cell.Style.Font.FontSize);
- if (value.Length > maxCharsToWrap)
- {
- var row = cell.WorksheetRow();
- var baseHeight = row.Height;
- row.Height = 0.5d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap);
- }
- }
-
- return cell;
- }
-
- public static IXLCell _ValueNoBorder(this IXLCell cell, string value, bool adaptRowHeight = false)
- {
- cell.Value = value;
- cell.Style.Alignment.WrapText = true;
-
- cell.Value = value;
- if (adaptRowHeight)
- {
- var colWidth = cell.WorksheetColumn().Width;
- var maxCharsToWrap = colWidth / (0.1d * cell.Style.Font.FontSize);
- if (value.Length > maxCharsToWrap)
- {
- var row = cell.WorksheetRow();
- var baseHeight = row.Height;
- row.Height = 0.5d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap);
- }
- }
-
- return cell;
- }
-
-
-
-
- public static IXLCell _SetValue(this IXLCell cell, DateTime value, string dateFormat = "DD.MM.YYYY HH:MM:SS")
- {
- cell.Value = value;
- cell.Style
- .SetAllBorders()
- .Alignment.WrapText = true;
-
- cell.Value = value;
-
- cell.DataType = XLDataType.DateTime;
- cell.Style.DateFormat.Format = "DD.MM.YYYY HH:MM:SS";
-
- return cell;
- }
-
- public static IXLCell _SetValue(this IXLCell cell, IFormattable value, string format = "0.00")
- {
- cell.Value = value;
- cell.Style
- .SetAllBorders()
- .Alignment.WrapText = true;
-
- cell.Value = value;
-
- cell.DataType = XLDataType.Number;
- cell.Style.NumberFormat.Format = "0.00";
-
- return cell;
- }
-
- public static IXLStyle SetAllBorders(this IXLStyle style, XLBorderStyleValues borderStyle = XLBorderStyleValues.Thin)
- {
- style.Border.RightBorder = borderStyle;
- style.Border.LeftBorder = borderStyle;
- style.Border.TopBorder = borderStyle;
- style.Border.BottomBorder = borderStyle;
- style.Border.InsideBorder = borderStyle;
- style.Border.OutsideBorder = borderStyle;
- return style;
- }
-
- public static IXLStyle SetBaseFont(this IXLStyle style)
- {
- style.Font.FontName = "Calibri";
- style.Font.FontSize = 10;
- return style;
- }
-
- public static IXLStyle SetH1(this IXLStyle style)
- {
- style.Font.FontName = "Calibri";
- style.Font.FontSize = 14;
- return style;
- }
-
- ///
- /// Костыль исправляющий проблему в библиотеке IXLRange Range(this IXLWorksheet, IXLAddress, IXLAddress) с кастингом IXLAddress к XLAddress.
- ///
- ///
- ///
- ///
- ///
- public static IXLRange _Range(this IXLWorksheet sheet, CellAddress begin, CellAddress end)
- => sheet.Range(begin.RowNumber, begin.ColumnNumber, end.RowNumber, end.ColumnNumber);
-
- }
-
-}
diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs
index e8185a34..7ff6ecf2 100644
--- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs
+++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapPlanImportService.cs
@@ -187,23 +187,23 @@ public class ProcessMapPlanImportService : IProcessMapPlanImportService
private ProcessMapPlanDto ParseRow(IXLRow row)
{
- var wellSectionTypeCaption = GetCellValue(row, columnWellSectionType).Trim().ToLower();
- var modeName = GetCellValue(row, columnMode).Trim().ToLower();
- var depthStart = GetCellValue(row, columnDepthStart);
- var depthEnd = GetCellValue(row, columnDepthEnd);
- var pressurePlan = GetCellValue(row, columnPressurePlan);
- var pressureLimitMax = GetCellValue(row, columnPressureLimitMax);
- var axialLoadPlan = GetCellValue(row, columnAxialLoadPlan);
- var axialLoadLimitMax = GetCellValue(row, columnAxialLoadLimitMax);
- var topDriveTorquePlan = GetCellValue(row, columnTopDriveTorquePlan);
- var topDriveTorqueLimitMax = GetCellValue(row, columnTopDriveTorqueLimitMax);
- var topDriveSpeedPlan = GetCellValue(row, columnTopDriveSpeedPlan);
- var topDriveSpeedLimitMax = GetCellValue(row, columnTopDriveSpeedLimitMax);
- var flowPlan = GetCellValue(row, columnFlowPlan);
- var flowLimitMax = GetCellValue(row, columnFlowLimitMax);
- var ropPlan = GetCellValue(row, columnRopPlan);
- var usageSaub = GetCellValue(row, columnUsageSaub);
- var usageSpin = GetCellValue(row, columnUsageSpin);
+ var wellSectionTypeCaption = row.Cell(columnWellSectionType).GetCellValue().Trim().ToLower();
+ var modeName = row.Cell(columnMode).GetCellValue().Trim().ToLower();
+ var depthStart = row.Cell(columnDepthStart).GetCellValue();
+ var depthEnd = row.Cell(columnDepthEnd).GetCellValue();
+ var pressurePlan = row.Cell(columnPressurePlan).GetCellValue();
+ var pressureLimitMax = 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 wellSection = sections.FirstOrDefault(s => s.Caption.Trim().ToLower() == wellSectionTypeCaption)
?? throw new FileFormatException(
@@ -342,19 +342,4 @@ public class ProcessMapPlanImportService : IProcessMapPlanImportService
2 => "Слайд",
_ => "Ручной",
};
-
- //TODO: вынести в метод расширения
- private static T GetCellValue(IXLRow row, int columnNumber)
- {
- try
- {
- var cell = row.Cell(columnNumber);
- return (T)Convert.ChangeType(cell.Value, typeof(T));
- }
- catch
- {
- throw new FileFormatException(
- $"Лист {row.Worksheet.Name}. Ячейка: ({row.RowNumber()},{columnNumber}) содержит некорректное значение");
- }
- }
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs b/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs
index 6ea64efb..771396dc 100644
--- a/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs
+++ b/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs
@@ -177,32 +177,17 @@ namespace AsbCloudInfrastructure.Services.Trajectory
private TrajectoryGeoPlanDto ParseRow(IXLRow row)
{
- var _wellboreDepth = row.Cell(ColumnWellboreDepth).Value;
- var _zenithAngle = row.Cell(ColumnZenithAngle).Value;
- var _azimuthGeo = row.Cell(ColumnAzimuthGeo).Value;
- var _azimuthMagnetic = row.Cell(ColumnAzimuthMagnetic).Value;
- var _verticalDepth = row.Cell(ColumnVerticalDepth).Value;
- var _radius = row.Cell(ColumnRadius).Value;
- var _comment = row.Cell(ColumnComment).Value;
-
- var trajectoryRow = new TrajectoryGeoPlanDto();
-
- static double getDoubleValue(object value, string nameParam, IXLRow row)
+ var trajectoryRow = new TrajectoryGeoPlanDto
{
- if (value is double _value)
- return _value;
- throw new FileFormatException($"Лист {row.Worksheet.Name}. Строка {row.RowNumber()} - некорректные данные - {nameParam}");
- }
-
- trajectoryRow.WellboreDepth = getDoubleValue(_wellboreDepth, "Глубина по стволу", row);
- trajectoryRow.ZenithAngle = getDoubleValue(_zenithAngle, "Зенитный угол", row);
- trajectoryRow.AzimuthGeo = getDoubleValue(_azimuthGeo, "Азимут географический", row);
- trajectoryRow.AzimuthMagnetic = getDoubleValue(_azimuthMagnetic, "Азимут магнитный", row);
- trajectoryRow.VerticalDepth = getDoubleValue(_verticalDepth, "Глубина вертикальная", row);
- trajectoryRow.Radius = getDoubleValue(_radius, "Радиус цели", row);
-
- if (_comment is not null)
- trajectoryRow.Comment = _comment.ToString();
+ WellboreDepth = row.Cell(ColumnWellboreDepth).GetCellValue(),
+ ZenithAngle = row.Cell(ColumnZenithAngle).GetCellValue(),
+ AzimuthGeo = row.Cell(ColumnAzimuthGeo).GetCellValue(),
+ AzimuthMagnetic = row.Cell(ColumnAzimuthMagnetic).GetCellValue(),
+ VerticalDepth = row.Cell(ColumnVerticalDepth).GetCellValue(),
+ Radius = row.Cell(ColumnRadius).GetCellValue(),
+ Comment = row.Cell(ColumnComment).GetCellValue()
+ };
+
return trajectoryRow;
}
}
diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs
index f5f56612..8fd86f2c 100644
--- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using AsbCloudApp.Data.WellOperationImport;
-using AsbCloudApp.Exceptions;
+using AsbCloudApp.Data.WellOperationImport.Options;
using AsbCloudApp.Services.WellOperationImport;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.WellOperationImport.Constants;
@@ -11,31 +11,29 @@ using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.WellOperationImport.FileParser;
-public class WellOperationDefaultExcelParser : IWellOperationExcelParser
+public class WellOperationDefaultExcelParser : IWellOperationExcelParser
{
- public int IdTemplate => Templates.IdDefaultTemplate;
- public IEnumerable IdTypes => new[] { WellOperation.IdOperationTypePlan, WellOperation.IdOperationTypeFact };
-
- public IEnumerable Parse(Stream stream, WellOperationParserOptionsDto options)
+ public SheetDto Parse(Stream stream, WellOperationImportDefaultOptionsDto options)
{
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
return ParseWorkbook(workbook, options);
}
- private static IEnumerable ParseWorkbook(IXLWorkbook workbook, WellOperationParserOptionsDto options)
+ private static SheetDto ParseWorkbook(IXLWorkbook workbook, WellOperationImportDefaultOptionsDto 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))
- ?? throw new FileFormatException($"Книга excel не содержит листа '{options.SheetName}'");
+ string.Equals(ws.Name, sheetName, StringComparison.CurrentCultureIgnoreCase))
+ ?? throw new FileFormatException($"Книга excel не содержит листа '{sheetName}'");
return ParseSheet(sheet);
}
- private static IEnumerable ParseSheet(IXLWorksheet sheet)
+ private static SheetDto ParseSheet(IXLWorksheet sheet)
{
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 7)
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
@@ -47,7 +45,7 @@ public class WellOperationDefaultExcelParser : IWellOperationExcelParser
case > 1024:
throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество операций.");
case <= 0:
- return Enumerable.Empty();
+ return new SheetDto { Name = sheet.Name };
}
var rows = new RowDto[count];
@@ -71,7 +69,11 @@ public class WellOperationDefaultExcelParser : IWellOperationExcelParser
if (cellValuesErrors.Any())
throw new FileFormatException(string.Join("\r\n", cellValuesErrors));
- return rows;
+ return new SheetDto
+ {
+ Name = sheet.Name,
+ Rows = rows
+ };
}
private static RowDto ParseRow(IXLRow xlRow)
@@ -79,28 +81,14 @@ public class WellOperationDefaultExcelParser : IWellOperationExcelParser
return new RowDto
{
Number = xlRow.RowNumber(),
- Section = GetCellValue(xlRow.Cell(DefaultTemplateInfo.ColumnSection)),
- Category = GetCellValue(xlRow.Cell(DefaultTemplateInfo.ColumnCategory)),
- CategoryInfo = GetCellValue(xlRow.Cell(DefaultTemplateInfo.ColumnCategoryInfo)),
- DepthStart = GetCellValue(xlRow.Cell(DefaultTemplateInfo.ColumnDepthStart)),
- DepthEnd = GetCellValue(xlRow.Cell(DefaultTemplateInfo.ColumnDepthEnd)),
- Date = GetCellValue(xlRow.Cell(DefaultTemplateInfo.ColumnDate)),
- Duration = GetCellValue(xlRow.Cell(DefaultTemplateInfo.ColumnDuration)),
- Comment = GetCellValue(xlRow.Cell(DefaultTemplateInfo.ColumnComment))
+ Section = xlRow.Cell(DefaultTemplateInfo.ColumnSection).GetCellValue(),
+ Category = xlRow.Cell(DefaultTemplateInfo.ColumnCategory).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()
};
}
-
- //TODO: вынести в метод расширения
- private static T GetCellValue(IXLCell cell)
- {
- try
- {
- return (T)Convert.ChangeType(cell.Value, typeof(T));
- }
- catch
- {
- throw new FileFormatException(
- $"Лист '{cell.Worksheet.Name}'. Ячейка: ({cell.Address.RowNumber},{cell.Address.ColumnNumber}) содержит некорректное значение");
- }
- }
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs
index 6f0b412d..1b41ebd3 100644
--- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs
@@ -1,26 +1,25 @@
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using AsbCloudApp.Data.WellOperationImport;
+using AsbCloudApp.Data.WellOperationImport.Options;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Services.WellOperationImport;
-using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.WellOperationImport.Constants;
using AsbCloudInfrastructure.Services.WellOperationImport.FileParser.StringSimilarity;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.WellOperationImport.FileParser;
-public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
+public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
{
private class Operation
{
public int RowNumber { get; set; }
- public string CategoryInfo { get; set; } = null!;
+ public string? CategoryInfo { get; set; }
public double SectionDiameter { get; set; }
@@ -31,38 +30,25 @@ 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;
-
- public IEnumerable IdTypes => new[] { WellOperation.IdOperationTypePlan };
-
- public IEnumerable Parse(Stream stream, WellOperationParserOptionsDto options)
+ public SheetDto Parse(Stream stream, WellOperationImportGazpromKhantosOptionsDto options)
{
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
return ParseWorkBook(workbook, options);
- }
+ }
- private IEnumerable ParseWorkBook(IXLWorkbook workbook, WellOperationParserOptionsDto options)
+ private SheetDto ParseWorkBook(IXLWorkbook workbook, WellOperationImportGazpromKhantosOptionsDto options)
{
- if (string.IsNullOrWhiteSpace(options.SheetName))
- throw new ArgumentInvalidException(nameof(options.SheetName), "Не указано название листа");
-
- if (options.StartRow is null or < 1 or > 1048576)
+ if (options.StartRow is < 1 or > 1048576)
throw new ArgumentInvalidException(nameof(options.StartRow), "Некорректное значение начальной строки");
- if (options.EndRow is null or < 1 or > 1048576)
+ if (options.EndRow is < 1 or > 1048576)
throw new ArgumentInvalidException(nameof(options.EndRow), "Некорректное значение конечной строки");
if (options.EndRow < options.StartRow)
@@ -72,15 +58,15 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
string.Equals(ws.Name, options.SheetName, StringComparison.CurrentCultureIgnoreCase))
?? throw new FileFormatException($"Книга excel не содержит листа '{options.SheetName}'");
- return ParseSheet(sheet, options.StartRow.Value, options.EndRow.Value);
+ return ParseSheet(sheet, options.StartRow, options.EndRow);
}
- private IEnumerable ParseSheet(IXLWorksheet sheet, int startRow, int endRow)
+ private SheetDto ParseSheet(IXLWorksheet sheet, int startRow, int endRow)
{
- var operationAttributes = GetOperationAttributes(sheet.RowsUsed());
+ var operationAttributes = GetOperationAttributes(sheet.RowsUsed());
if (operationAttributes is null)
- return Enumerable.Empty();
+ return new SheetDto { Name = sheet.Name };
var rowsCount = endRow - startRow + 1;
@@ -97,11 +83,11 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
operations.Add(new Operation
{
RowNumber = xlRow.RowNumber(),
- CategoryInfo = GetCellValue(xlRow.Cell(operationAttributes[OperationAttributes.CategoryInfo])),
- SectionDiameter = GetCellValue(xlRow.Cell(operationAttributes[OperationAttributes.SectionDiameter])),
- Depth = GetCellValue(xlRow.Cell(operationAttributes[OperationAttributes.Depth])),
- Duration = GetCellValue(xlRow.Cell(operationAttributes[OperationAttributes.Duration])),
- Date = GetCellValue(xlRow.Cell(operationAttributes[OperationAttributes.Date]))
+ 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(),
+ Date = xlRow.Cell(operationAttributes[OperationAttributes.Date]).GetCellValue()
});
}
catch (FileFormatException ex)
@@ -113,7 +99,11 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
if (cellValuesErrors.Any())
throw new FileFormatException(string.Join("\r\n", cellValuesErrors));
- return BuildRows();
+ return new SheetDto()
+ {
+ Name = sheet.Name,
+ Rows = BuildRows()
+ };
IEnumerable<(double Diameter, string Name)> BuildSections()
{
@@ -183,7 +173,7 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
foreach (var cell in cells)
{
- var operationAttribute = GetValueDictionary(operationAttributesDict, GetCellValue(cell), 0.7);
+ var operationAttribute = GetValueDictionary(operationAttributesDict, cell.GetCellValue(), 0.7);
if (operationAttribute is null || operationAttributes.Any(a => a.Key == operationAttribute))
continue;
@@ -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);
@@ -234,21 +227,4 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser
.Select(line => line.Split(separator))
.ToDictionary(parts => parts[0].Trim(), parts => parts[1].Trim());
}
-
- //TODO: вынести в метод расширения
- private static T GetCellValue(IXLCell cell)
- {
- try
- {
- if (typeof(T) != typeof(DateTime))
- return (T)Convert.ChangeType(cell.GetFormattedString(), typeof(T), CultureInfo.InvariantCulture);
-
- return (T)(object)DateTime.FromOADate((double)cell.Value);
- }
- catch
- {
- throw new FileFormatException(
- $"Лист '{cell.Worksheet.Name}'. Ячейка: ({cell.Address.RowNumber},{cell.Address.ColumnNumber}) содержит некорректное значение");
- }
- }
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs
index af84f3a9..9da293c6 100644
--- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs
@@ -6,64 +6,35 @@ using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.WellOperationImport;
-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;
public class WellOperationImportService : IWellOperationImportService
{
- private readonly IEnumerable excelParsers;
private readonly IWellOperationRepository wellOperationRepository;
private static readonly DateTime dateLimitMin = new(2001, 1, 1, 0, 0, 0);
private static readonly DateTime dateLimitMax = new(2099, 1, 1, 0, 0, 0);
private static readonly TimeSpan drillingDurationLimitMax = TimeSpan.FromDays(366);
- public WellOperationImportService(IEnumerable excelParsers,
- IWellOperationRepository wellOperationRepository)
+ public WellOperationImportService(IWellOperationRepository wellOperationRepository)
{
- this.excelParsers = excelParsers;
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, int idType, SheetDto sheet, 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 validationErrors = new List();
var sections = wellOperationRepository.GetSectionTypes();
var categories = wellOperationRepository.GetCategories(false);
- switch (options.IdTemplate)
- {
- 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;
- }
-
var operations = new List();
- foreach (var row in rows)
+ foreach (var row in sheet.Rows)
{
try
{
@@ -71,28 +42,32 @@ public class WellOperationImportService : IWellOperationImportService
string.Equals(s.Caption, row.Section, StringComparison.CurrentCultureIgnoreCase));
if (section is null)
- throw new FileFormatException($"Лист '{options.SheetName}'. В строке '{row.Number}' не удалось определить секцию");
+ throw new FileFormatException($"Лист '{sheet.Name}'. В строке '{row.Number}' не удалось определить секцию");
var category = categories.FirstOrDefault(c =>
string.Equals(c.Name, row.Category, StringComparison.CurrentCultureIgnoreCase));
if (category is null)
- throw new FileFormatException($"Лист '{options.SheetName}'. В строке '{row.Number}' не удалось определить операцию");
+ throw new FileFormatException($"Лист '{sheet.Name}'. В строке '{row.Number}' не удалось определить операцию");
if (row.DepthStart is not (>= 0d and <= 20_000d))
- throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная глубина на начало операции");
+ throw new FileFormatException(
+ $"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная глубина на начало операции");
if (row.DepthEnd is not (>= 0d and <= 20_000d))
- throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная глубина на конец операции");
+ throw new FileFormatException(
+ $"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная глубина на конец операции");
if (row.Date < dateLimitMin && row.Date > dateLimitMax)
- throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' неправильно получена дата начала операции");
+ throw new FileFormatException(
+ $"Лист '{sheet.Name}'. Строка '{row.Number}' неправильно получена дата начала операции");
if (operations.LastOrDefault()?.DateStart > row.Date)
- throw new FileFormatException($"Лист '{options.SheetName}' строка '{row.Number}' дата позднее даты предыдущей операции");
+ throw new FileFormatException(
+ $"Лист '{sheet.Name}' строка '{row.Number}' дата позднее даты предыдущей операции");
if (row.Duration is not (>= 0d and <= 240d))
- throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная длительность операции");
+ throw new FileFormatException($"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная длительность операции");
operations.Add(new WellOperationDto
{
@@ -115,24 +90,25 @@ public class WellOperationImportService : IWellOperationImportService
}
if (operations.Any() && operations.Min(o => o.DateStart) - operations.Max(o => o.DateStart) > drillingDurationLimitMax)
- validationErrors.Add($"Лист {options.SheetName} содержит диапазон дат больше {drillingDurationLimitMax}");
+ validationErrors.Add($"Лист {sheet.Name} содержит диапазон дат больше {drillingDurationLimitMax}");
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
+ IdWell = idWell,
+ OperationType = idType
}, 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/AsbCloudInfrastructure/XLExtentions.cs b/AsbCloudInfrastructure/XLExtentions.cs
new file mode 100644
index 00000000..24043605
--- /dev/null
+++ b/AsbCloudInfrastructure/XLExtentions.cs
@@ -0,0 +1,182 @@
+using ClosedXML.Excel;
+using System;
+using System.Globalization;
+using System.IO;
+using AsbCloudInfrastructure.Services.DailyReport;
+
+namespace AsbCloudInfrastructure;
+
+internal static class XLExtentions
+{
+ internal static IXLRange _SetValue(this IXLRange range, object value)
+ {
+ var mergedRange = range.Merge();
+ mergedRange.FirstCell()._SetValue(value);
+ var colWidth = mergedRange.FirstCell().WorksheetColumn().Width;
+ var maxCharsToWrap = colWidth / (0.1d * mergedRange.FirstCell().Style.Font.FontSize);
+ if (value is string valueString && valueString.Length > maxCharsToWrap)
+ {
+ var row = mergedRange.FirstCell().WorksheetRow();
+ var baseHeight = row.Height;
+ row.Height = 0.5d * baseHeight * Math.Ceiling(1d + valueString.Length / maxCharsToWrap);
+ }
+
+ mergedRange.Style.SetAllBorders()
+ .Alignment.SetWrapText(true);
+ return mergedRange;
+ }
+
+ internal static IXLCell _SetValue(this IXLCell cell, object value)
+ {
+ switch (value)
+ {
+ case DateTime dateTime:
+ cell._SetValue(dateTime);
+ break;
+ case IFormattable formattable:
+ cell._SetValue(formattable);
+ break;
+ case string valueString:
+ cell._SetValue(valueString);
+ break;
+ default:
+ cell.Value = value;
+ break;
+ }
+
+ return cell;
+ }
+
+ internal static IXLCell _SetValue(this IXLCell cell, string value, bool adaptRowHeight = false)
+ {
+ cell.Value = value;
+ cell.Style
+ .SetAllBorders()
+ .Alignment.WrapText = true;
+
+ cell.Value = value;
+ if (adaptRowHeight)
+ {
+ var colWidth = cell.WorksheetColumn().Width;
+ var maxCharsToWrap = colWidth / (0.1d * cell.Style.Font.FontSize);
+ if (value.Length > maxCharsToWrap)
+ {
+ var row = cell.WorksheetRow();
+ var baseHeight = row.Height;
+ row.Height = 0.5d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap);
+ }
+ }
+
+ return cell;
+ }
+
+ internal static IXLCell _ValueNoBorder(this IXLCell cell, string value, bool adaptRowHeight = false)
+ {
+ cell.Value = value;
+ cell.Style.Alignment.WrapText = true;
+
+ cell.Value = value;
+ if (adaptRowHeight)
+ {
+ var colWidth = cell.WorksheetColumn().Width;
+ var maxCharsToWrap = colWidth / (0.1d * cell.Style.Font.FontSize);
+ if (value.Length > maxCharsToWrap)
+ {
+ var row = cell.WorksheetRow();
+ var baseHeight = row.Height;
+ row.Height = 0.5d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap);
+ }
+ }
+
+ return cell;
+ }
+
+
+ internal static IXLCell _SetValue(this IXLCell cell, DateTime value, string dateFormat = "DD.MM.YYYY HH:MM:SS")
+ {
+ cell.Value = value;
+ cell.Style
+ .SetAllBorders()
+ .Alignment.WrapText = true;
+
+ cell.Value = value;
+
+ cell.DataType = XLDataType.DateTime;
+ cell.Style.DateFormat.Format = "DD.MM.YYYY HH:MM:SS";
+
+ return cell;
+ }
+
+ internal static IXLCell _SetValue(this IXLCell cell, IFormattable value, string format = "0.00")
+ {
+ cell.Value = value;
+ cell.Style
+ .SetAllBorders()
+ .Alignment.WrapText = true;
+
+ cell.Value = value;
+
+ cell.DataType = XLDataType.Number;
+ cell.Style.NumberFormat.Format = "0.00";
+
+ return cell;
+ }
+
+ internal static IXLStyle SetAllBorders(this IXLStyle style, XLBorderStyleValues borderStyle = XLBorderStyleValues.Thin)
+ {
+ style.Border.RightBorder = borderStyle;
+ style.Border.LeftBorder = borderStyle;
+ style.Border.TopBorder = borderStyle;
+ style.Border.BottomBorder = borderStyle;
+ style.Border.InsideBorder = borderStyle;
+ style.Border.OutsideBorder = borderStyle;
+ return style;
+ }
+
+ internal static IXLStyle SetBaseFont(this IXLStyle style)
+ {
+ style.Font.FontName = "Calibri";
+ style.Font.FontSize = 10;
+ return style;
+ }
+
+ internal static IXLStyle SetH1(this IXLStyle style)
+ {
+ style.Font.FontName = "Calibri";
+ style.Font.FontSize = 14;
+ return style;
+ }
+
+ ///
+ /// Костыль исправляющий проблему в библиотеке IXLRange Range(this IXLWorksheet, IXLAddress, IXLAddress) с кастингом IXLAddress к XLAddress.
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal static IXLRange _Range(this IXLWorksheet sheet, CellAddress begin, CellAddress end)
+ => sheet.Range(begin.RowNumber, begin.ColumnNumber, end.RowNumber, end.ColumnNumber);
+
+
+ internal static T? GetCellValue(this IXLCell cell)
+ {
+ try
+ {
+ if (cell.IsEmpty() && default(T) == null)
+ return default;
+
+ if (typeof(T) != typeof(DateTime))
+ return (T)Convert.ChangeType(cell.GetFormattedString(), typeof(T), CultureInfo.InvariantCulture);
+
+ if (cell.Value is DateTime dateTime)
+ return (T)(object)dateTime;
+
+ return (T)(object)DateTime.FromOADate((double)cell.Value);
+ }
+ catch
+ {
+ throw new FileFormatException(
+ $"Лист '{cell.Worksheet.Name}'. Ячейка: ({cell.Address.RowNumber},{cell.Address.ColumnNumber}) содержит некорректное значение");
+ }
+ }
+}
\ No newline at end of file
diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs
index 189b9747..54270f49 100644
--- a/AsbCloudWebApi/Controllers/WellOperationController.cs
+++ b/AsbCloudWebApi/Controllers/WellOperationController.cs
@@ -11,8 +11,9 @@ using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
-using AsbCloudApp.Data.WellOperationImport;
using AsbCloudApp.Services.WellOperationImport;
+using AsbCloudApp.Data.WellOperationImport.Options;
+using AsbCloudApp.Exceptions;
namespace AsbCloudWebApi.Controllers
{
@@ -30,6 +31,8 @@ namespace AsbCloudWebApi.Controllers
private readonly IWellOperationExportService wellOperationExportService;
private readonly IWellOperationImportTemplateService wellOperationImportTemplateService;
private readonly IWellOperationImportService wellOperationImportService;
+ private readonly IWellOperationExcelParser wellOperationDefaultExcelParser;
+ private readonly IWellOperationExcelParser wellOperationGazpromKhantosExcelParser;
private readonly IUserRepository userRepository;
public WellOperationController(IWellOperationRepository operationRepository,
@@ -37,6 +40,8 @@ namespace AsbCloudWebApi.Controllers
IWellOperationImportTemplateService wellOperationImportTemplateService,
IWellOperationExportService wellOperationExportService,
IWellOperationImportService wellOperationImportService,
+ IWellOperationExcelParser wellOperationDefaultExcelParser,
+ IWellOperationExcelParser wellOperationGazpromKhantosExcelParser,
IUserRepository userRepository)
{
this.operationRepository = operationRepository;
@@ -44,6 +49,8 @@ namespace AsbCloudWebApi.Controllers
this.wellOperationImportTemplateService = wellOperationImportTemplateService;
this.wellOperationExportService = wellOperationExportService;
this.wellOperationImportService = wellOperationImportService;
+ this.wellOperationDefaultExcelParser = wellOperationDefaultExcelParser;
+ this.wellOperationGazpromKhantosExcelParser = wellOperationGazpromKhantosExcelParser;
this.userRepository = userRepository;
}
@@ -287,45 +294,28 @@ namespace AsbCloudWebApi.Controllers
///
- /// Импорт плановых операций из excel (xlsx) файла
+ /// Импорт операций из excel (xlsx) файла. Стандартный заполненный шаблон
///
/// id скважины
- /// Тип операции
- /// Начальная строка
- /// Конечная строка
+ /// Параметры для парсинга файла
/// Коллекция из одного файла xlsx
- /// Удалить операции перед импортом = 1, если файл валидный
- /// Название листа
- /// Токен отмены задачи
- /// Шаблон файла. 0 - стандартный, 1 - Газпромнефть Хантос
+ /// Удалить операции перед импортом = 1, если файл валидный
+ ///
///
- [HttpPost("import/{options}")]
+ [HttpPost("import/default/{deleteBeforeImport}")]
[Permission]
- public async Task ImportAsync(int idWell,
- [Required] int idType,
- string? sheetName,
- [Required] int idTemplate,
- int? startRow,
- int? endRow,
+ public async Task ImportDefaultExcelFileAsync(int idWell,
+ [FromQuery] WellOperationImportDefaultOptionsDto options,
[FromForm] IFormFileCollection files,
- int options,
+ [Range(0, 1, ErrorMessage = "Недопустимое значение. Допустимые: 0, 1")] int deleteBeforeImport,
CancellationToken token)
{
- var idCompany = User.GetCompanyId();
var idUser = User.GetUserId();
- if (idCompany is null || idUser is null)
- return Forbid();
+ if (!idUser.HasValue)
+ throw new ForbidException("Неизвестный пользователь");
- if (!await CanUserAccessToWellAsync(idWell, token))
- return Forbid();
-
- if (!await CanUserEditWellOperationsAsync(idWell, token))
- return Forbid();
-
- if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
- idWell, token).ConfigureAwait(false))
- return Forbid();
+ await AssertUserHasAccessToImportWellOperationsAsync(idWell, token);
if (files.Count < 1)
return this.ValidationBadRequest(nameof(files), "Нет файла");
@@ -338,13 +328,56 @@ 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);
+ var sheet = wellOperationDefaultExcelParser.Parse(stream, options);
+
+ await wellOperationImportService.ImportAsync(idWell, idUser.Value, options.IdType, sheet, (deleteBeforeImport & 1) > 0, token);
+ }
+ catch (FileFormatException ex)
+ {
+ return this.ValidationBadRequest(nameof(files), ex.Message);
+ }
+
+ return Ok();
+ }
+
+ ///
+ /// Импорт операций из excel (xlsx) файла. ГПНХ (Хантос)
+ ///
+ /// id скважины
+ /// Параметры для парсинга файла
+ /// Коллекция из одного файла xlsx
+ /// Удалить операции перед импортом = 1, если файл валидный
+ ///
+ ///
+ [HttpPost("import/gazpromKhantos/{deleteBeforeImport}")]
+ [Permission]
+ public async Task ImportGazpromKhantosExcelFileAsync(int idWell,
+ [FromQuery] WellOperationImportGazpromKhantosOptionsDto options,
+ [FromForm] IFormFileCollection files,
+ [Range(0, 1, ErrorMessage = "Недопустимое значение. Допустимые: 0, 1")] int deleteBeforeImport,
+ CancellationToken token)
+ {
+ var idUser = User.GetUserId();
+
+ if (!idUser.HasValue)
+ throw new ForbidException("Неизвестный пользователь");
+
+ await AssertUserHasAccessToImportWellOperationsAsync(idWell, token);
+
+ 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 = wellOperationGazpromKhantosExcelParser.Parse(stream, options);
+
+ await wellOperationImportService.ImportAsync(idWell, idUser.Value, options.IdType, sheet, (deleteBeforeImport & 1) > 0, token);
}
catch (FileFormatException ex)
{
@@ -420,6 +453,24 @@ namespace AsbCloudWebApi.Controllers
return File(stream, "application/octet-stream", fileName);
}
+ private async Task AssertUserHasAccessToImportWellOperationsAsync(int idWell, CancellationToken token)
+ {
+ var idCompany = User.GetCompanyId();
+ var idUser = User.GetUserId();
+
+ if (!idCompany.HasValue || !idUser.HasValue)
+ throw new ForbidException("Неизвестный пользователь");
+
+ if (!await CanUserAccessToWellAsync(idWell, token))
+ throw new ForbidException("Нет доступа к скважине");
+
+ if (!await CanUserEditWellOperationsAsync(idWell, token))
+ throw new ForbidException("Недостаточно прав для редактирования ГГД на завершенной скважине");
+
+ if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, token))
+ throw new ForbidException("Скважина недоступна для компании");
+ }
+
private async Task CanUserEditWellOperationsAsync(int idWell, CancellationToken token)
{
var idUser = User.GetUserId();