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] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D1=80?= =?UTF-8?q?=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20?= =?UTF-8?q?=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81=D0=BE=D0=B2=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=B0=D1=80=D1=81=D0=B8=D0=BD=D0=B3=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);