From 0b95361b69a08dab0b7079241c996130a73be974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Fri, 29 Sep 2023 16:48:59 +0500 Subject: [PATCH 1/8] =?UTF-8?q?=D0=92=D1=8B=D0=BD=D0=B5=D1=81=20=D0=BC?= =?UTF-8?q?=D0=B5=D1=82=D0=BE=D0=B4=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B2=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D1=88=D0=B8=D1=80=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/DailyReport/XLExtentions.cs | 161 ---------------- .../ProcessMap/ProcessMapPlanImportService.cs | 49 ++--- .../PlannedTrajectoryImportService.cs | 36 ++-- .../WellOperationDefaultExcelParser.cs | 30 +-- .../WellOperationGazpromKhantosExcelParser.cs | 29 +-- AsbCloudInfrastructure/XLExtentions.cs | 176 ++++++++++++++++++ 6 files changed, 218 insertions(+), 263 deletions(-) delete mode 100644 AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs create mode 100644 AsbCloudInfrastructure/XLExtentions.cs 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..ff1c59b6 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs @@ -177,32 +177,18 @@ 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).IsEmpty() ? null : + row.Cell(ColumnComment).GetCellValue() + }; + return trajectoryRow; } } diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs index f5f56612..ef9ed499 100644 --- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs +++ b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs @@ -79,28 +79,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..d1ce47cd 100644 --- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs +++ b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs @@ -97,11 +97,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) @@ -183,7 +183,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; @@ -234,21 +234,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/XLExtentions.cs b/AsbCloudInfrastructure/XLExtentions.cs new file mode 100644 index 00000000..ac2a40a1 --- /dev/null +++ b/AsbCloudInfrastructure/XLExtentions.cs @@ -0,0 +1,176 @@ +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 (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 From ac578bce3808185c6a05fd6b7097809f7696658e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Fri, 29 Sep 2023 18:48:17 +0500 Subject: [PATCH 2/8] =?UTF-8?q?=D0=A3=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B0=20=D1=80?= =?UTF-8?q?=D0=B0=D1=81=D1=88=D0=B8=D1=80=D0=B5=D0=BD=D0=B8=D1=8F.=20?= =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B2=D0=BE=D0=B7?= =?UTF-8?q?=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=B2=D0=BE?= =?UTF-8?q?=D0=B7=D0=B2=D1=80=D0=B0=D1=89=D0=B0=D1=82=D1=8C=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/Trajectory/PlannedTrajectoryImportService.cs | 3 +-- AsbCloudInfrastructure/XLExtentions.cs | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs b/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs index ff1c59b6..771396dc 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs @@ -185,8 +185,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory AzimuthMagnetic = row.Cell(ColumnAzimuthMagnetic).GetCellValue(), VerticalDepth = row.Cell(ColumnVerticalDepth).GetCellValue(), Radius = row.Cell(ColumnRadius).GetCellValue(), - Comment = row.Cell(ColumnComment).IsEmpty() ? null : - row.Cell(ColumnComment).GetCellValue() + Comment = row.Cell(ColumnComment).GetCellValue() }; return trajectoryRow; diff --git a/AsbCloudInfrastructure/XLExtentions.cs b/AsbCloudInfrastructure/XLExtentions.cs index ac2a40a1..a4f6f81a 100644 --- a/AsbCloudInfrastructure/XLExtentions.cs +++ b/AsbCloudInfrastructure/XLExtentions.cs @@ -158,10 +158,13 @@ internal static class XLExtentions => sheet.Range(begin.RowNumber, begin.ColumnNumber, end.RowNumber, end.ColumnNumber); - internal static T GetCellValue(this IXLCell cell) + 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); From 14615517d638a14aa3bf5750ba4fe3e7859633d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Mon, 2 Oct 2023 09:27:20 +0500 Subject: [PATCH 3/8] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82?= =?UTF-8?q?=D0=B0=20=D0=93=D0=93=D0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/WellOperationImport/RowDto.cs | 2 +- .../WellOperationImportOptionsDto.cs | 30 ++++++++-- .../IWellOperationImportService.cs | 6 +- .../WellOperationDefaultExcelParser.cs | 12 ++-- .../WellOperationGazpromKhantosExcelParser.cs | 21 +++---- .../WellOperationImportService.cs | 58 ++++++++----------- .../Controllers/WellOperationController.cs | 28 +++------ 7 files changed, 72 insertions(+), 85 deletions(-) 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) { From 7d00cfde1c61f721664c3211a1cf993a34b73958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Wed, 4 Oct 2023 15:34:42 +0500 Subject: [PATCH 4/8] =?UTF-8?q?=D0=A0=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B8?= =?UTF-8?q?=D0=BB=20Dto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Options/IWellOperationImportOptions.cs | 12 +++++ .../WellOperationImportDefaultOptionsDto.cs | 18 +++++++ ...OperationImportGazpromKhantosOptionsDto.cs | 36 +++++++++++++ .../Data/WellOperationImport/SheetDto.cs | 20 ++++++++ .../WellOperationImportOptionsDto.cs | 50 ------------------- 5 files changed, 86 insertions(+), 50 deletions(-) create mode 100644 AsbCloudApp/Data/WellOperationImport/Options/IWellOperationImportOptions.cs create mode 100644 AsbCloudApp/Data/WellOperationImport/Options/WellOperationImportDefaultOptionsDto.cs create mode 100644 AsbCloudApp/Data/WellOperationImport/Options/WellOperationImportGazpromKhantosOptionsDto.cs create mode 100644 AsbCloudApp/Data/WellOperationImport/SheetDto.cs delete mode 100644 AsbCloudApp/Data/WellOperationImport/WellOperationImportOptionsDto.cs 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/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 285f9d67..00000000 --- a/AsbCloudApp/Data/WellOperationImport/WellOperationImportOptionsDto.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; - -namespace AsbCloudApp.Data.WellOperationImport; - -/// -/// Опции для настройки парсинга документа -/// -public class WellOperationParserOptionsDto : IValidatableObject -{ - /// - /// Название листа - /// - public string? SheetName { get; set; } - - /// - /// Тип операции - /// 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 From 92a909a029d6944948788a195b62f81d71d70147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Wed, 4 Oct 2023 15:36:00 +0500 Subject: [PATCH 5/8] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20?= =?UTF-8?q?=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD?= =?UTF-8?q?=D0=B3=20=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=B0=D1=80=D1=81=D0=B8=D0=BD=D0=B3?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IWellOperationExcelParser.cs | 29 +++++------- .../IWellOperationImportService.cs | 22 +++++----- AsbCloudInfrastructure/DependencyInjection.cs | 5 ++- .../WellOperationDefaultExcelParser.cs | 22 +++++----- .../WellOperationGazpromKhantosExcelParser.cs | 32 +++++++------- .../WellOperationImportService.cs | 44 ++++++------------- 6 files changed, 65 insertions(+), 89 deletions(-) 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 7a122062..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,15 +9,14 @@ namespace AsbCloudApp.Services.WellOperationImport; /// public interface IWellOperationImportService { - /// - /// Загрузить из excel список операций - /// - /// - /// - /// - /// - /// - /// - Task ImportAsync(int idWell, int idUser, Stream stream, WellOperationParserOptionsDto options, bool deleteBeforeImport, - 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 9f845fff..e7cc796b 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -32,6 +32,7 @@ using AsbCloudInfrastructure.Services.AutoGeneratedDailyReports; using AsbCloudInfrastructure.Services.WellOperationImport; using AsbCloudInfrastructure.Services.WellOperationImport.FileParser; using AsbCloudInfrastructure.Services.ProcessMap.ProcessMapWellboreDevelopment; +using AsbCloudApp.Data.WellOperationImport.Options; namespace AsbCloudInfrastructure { @@ -239,8 +240,8 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient, WellOperationDefaultExcelParser>(); + services.AddTransient, WellOperationGazpromKhantosExcelParser>(); return services; } diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs index d4890934..8fd86f2c 100644 --- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs +++ b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using AsbCloudApp.Data.WellOperationImport; +using AsbCloudApp.Data.WellOperationImport.Options; using AsbCloudApp.Services.WellOperationImport; using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.WellOperationImport.Constants; @@ -10,19 +11,16 @@ 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) { var sheetName = options.IdType == WellOperation.IdOperationTypePlan ? DefaultTemplateInfo.SheetNamePlan @@ -30,12 +28,12 @@ public class WellOperationDefaultExcelParser : IWellOperationExcelParser var sheet = workbook.Worksheets.FirstOrDefault(ws => string.Equals(ws.Name, sheetName, StringComparison.CurrentCultureIgnoreCase)) - ?? throw new FileFormatException($"Книга excel не содержит листа '{options.SheetName}'"); + ?? 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) diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs index a484a2da..1b41ebd3 100644 --- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs +++ b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs @@ -4,16 +4,16 @@ 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 { @@ -35,24 +35,20 @@ public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser private readonly Dictionary operationDict = InitDict("Operations.txt", '='); private readonly Dictionary sectionDict = InitDict("Sections.txt", '='); private readonly Dictionary operationAttributesDict = InitDict("OperationAttributes.txt", '='); - - 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 (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) @@ -62,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; @@ -103,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() { diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs index b7e79b4a..9da293c6 100644 --- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs @@ -6,7 +6,6 @@ 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; @@ -15,43 +14,27 @@ 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, Stream stream, WellOperationParserOptionsDto options, bool deleteBeforeImport, - 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(options.IdType)) - ?? throw new ArgumentInvalidException(nameof(options.IdTemplate), "Невозможно импортировать файл"); - - IEnumerable rows; var validationErrors = new List(); var sections = wellOperationRepository.GetSectionTypes(); var categories = wellOperationRepository.GetCategories(false); - rows = options.IdTemplate switch - { - 0 => excelParser.Parse(stream, options), - _ => excelParser.Parse(stream, options) - }; - var operations = new List(); - foreach (var row in rows) + foreach (var row in sheet.Rows) { try { @@ -59,38 +42,38 @@ 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}' некорректная глубина на начало операции"); + $"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная глубина на начало операции"); if (row.DepthEnd is not (>= 0d and <= 20_000d)) throw new FileFormatException( - $"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная глубина на конец операции"); + $"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная глубина на конец операции"); if (row.Date < dateLimitMin && row.Date > dateLimitMax) throw new FileFormatException( - $"Лист '{options.SheetName}'. Строка '{row.Number}' неправильно получена дата начала операции"); + $"Лист '{sheet.Name}'. Строка '{row.Number}' неправильно получена дата начала операции"); if (operations.LastOrDefault()?.DateStart > row.Date) throw new FileFormatException( - $"Лист '{options.SheetName}' строка '{row.Number}' дата позднее даты предыдущей операции"); + $"Лист '{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 { IdWell = idWell, IdUser = idUser, - IdType = options.IdType, + IdType = idType, IdWellSectionType = section.Id, IdCategory = category.Id, CategoryInfo = row.CategoryInfo, @@ -107,7 +90,7 @@ 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)); @@ -119,7 +102,8 @@ public class WellOperationImportService : IWellOperationImportService { var existingOperations = await wellOperationRepository.GetAsync(new WellOperationRequest { - IdWell = idWell + IdWell = idWell, + OperationType = idType }, cancellationToken); await wellOperationRepository.DeleteAsync(existingOperations.Select(o => o.Id), cancellationToken); From 5d865457ec3ac56465bb4905a067f8c5e9a945b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Wed, 4 Oct 2023 15:36:14 +0500 Subject: [PATCH 6/8] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20=D1=80=D0=B0=D1=81?= =?UTF-8?q?=D1=88=D0=B8=D1=80=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudInfrastructure/XLExtentions.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/AsbCloudInfrastructure/XLExtentions.cs b/AsbCloudInfrastructure/XLExtentions.cs index a4f6f81a..24043605 100644 --- a/AsbCloudInfrastructure/XLExtentions.cs +++ b/AsbCloudInfrastructure/XLExtentions.cs @@ -168,7 +168,10 @@ internal static class XLExtentions if (typeof(T) != typeof(DateTime)) return (T)Convert.ChangeType(cell.GetFormattedString(), typeof(T), CultureInfo.InvariantCulture); - return (T)(object)DateTime.FromOADate((double)cell.Value); + if (cell.Value is DateTime dateTime) + return (T)(object)dateTime; + + return (T)(object)DateTime.FromOADate((double)cell.Value); } catch { From 5c904951b83c23df55d41a01028c281ea56e2833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Wed, 4 Oct 2023 15:36:49 +0500 Subject: [PATCH 7/8] =?UTF-8?q?=D0=A0=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=BB=D0=BB=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/WellOperationController.cs | 101 ++++++++++++++---- 1 file changed, 83 insertions(+), 18 deletions(-) diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs index f2c2b695..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,7 +294,7 @@ namespace AsbCloudWebApi.Controllers /// - /// Импорт плановых операций из excel (xlsx) файла + /// Импорт операций из excel (xlsx) файла. Стандартный заполненный шаблон /// /// id скважины /// Параметры для парсинга файла @@ -295,29 +302,20 @@ namespace AsbCloudWebApi.Controllers /// Удалить операции перед импортом = 1, если файл валидный /// /// - [HttpPost("import/{deleteBeforeImport}")] + [HttpPost("import/default/{deleteBeforeImport}")] [Permission] - public async Task ImportAsync(int idWell, - [FromQuery] WellOperationParserOptionsDto options, + public async Task ImportDefaultExcelFileAsync(int idWell, + [FromQuery] WellOperationImportDefaultOptionsDto options, [FromForm] IFormFileCollection files, [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), "Нет файла"); @@ -330,7 +328,56 @@ namespace AsbCloudWebApi.Controllers try { - await wellOperationImportService.ImportAsync(idWell, idUser.Value, stream, options, (deleteBeforeImport & 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) { @@ -406,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(); From 037aa7a0eb70da902b74a180e1b81c45d0838484 Mon Sep 17 00:00:00 2001 From: Frolov-Nikita Date: Wed, 4 Oct 2023 17:26:37 +0500 Subject: [PATCH 8/8] merge dev to well_operation_import --- AsbCloudInfrastructure/DependencyInjection.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index ada5c055..01eea5cc 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -242,8 +242,8 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient, WellOperationDefaultExcelParser>(); + services.AddTransient, WellOperationGazpromKhantosExcelParser>(); return services; }