diff --git a/AsbCloudApp/Services/IParserService.cs b/AsbCloudApp/Services/IParserService.cs index 2cfd8eb7..252aee28 100644 --- a/AsbCloudApp/Services/IParserService.cs +++ b/AsbCloudApp/Services/IParserService.cs @@ -1,6 +1,4 @@ using System.IO; -using System.Threading; -using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; @@ -35,4 +33,5 @@ public interface IParserService : IParserService /// public interface IParserService { + const string MessageTemplate = "Лист: {0}, Строка: {1}, Столбец: {2}. {3}"; } \ No newline at end of file diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 5b131299..afab0a5a 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -45,7 +45,6 @@ using AsbCloudDb.Model.WellSections; using AsbCloudInfrastructure.Services.ProcessMaps; using AsbCloudApp.Data.ProcessMapPlan; using AsbCloudApp.Requests; -using AsbCloudInfrastructure.Services.Trajectory.Parser; namespace AsbCloudInfrastructure { @@ -205,8 +204,6 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); - services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/AsbCloudInfrastructure/ParserServiceBase.cs b/AsbCloudInfrastructure/ParserServiceBase.cs index d98404e7..bcceb80d 100644 --- a/AsbCloudInfrastructure/ParserServiceBase.cs +++ b/AsbCloudInfrastructure/ParserServiceBase.cs @@ -21,21 +21,68 @@ public abstract class ParserServiceBase : IParserService ValidationResults { get; } = new List(); + + protected abstract string SheetName { get; } + public abstract ParserResultDto Parse(Stream file, TOptions options); + public abstract Stream GetTemplateFile(); + protected virtual ValidationResultDto ValidateRow(int rowNumber, + IDictionary columnNumbers, + TDto dto) + { + var validationContext = new ValidationContext(dto, serviceProvider: null, items: null); + + if (Validator.TryValidateObject(dto, validationContext, ValidationResults, true)) + { + var validRow = new ValidationResultDto + { + Item = dto + }; + + return validRow; + } + + var invalidRow = new ValidationResultDto + { + Item = dto, + }; + + var warnings = new List(); + + foreach (var validationResult in from v in ValidationResults + let memberNames = v.MemberNames.Where(columnNumbers.ContainsKey) + select memberNames.Select(x => + { + var columnNumber = columnNumbers[x]; + var errorMessage = v.ErrorMessage; + var warningMessage = string.Format(IParserService.MessageTemplate, SheetName, rowNumber, columnNumber, errorMessage); + var warning = new ValidationResult(warningMessage, new[] { x }); + return warning; + })) + { + warnings.AddRange(validationResult); + } + + invalidRow.Warnings = warnings; + + return invalidRow; + } + protected virtual ParserResultDto ParseExcelSheet(IXLWorksheet sheet, Func> parseRow, int columnCount, int headerRowsCount = 0) { if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < columnCount) - throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов."); + throw new FileFormatException($"Лист {SheetName} содержит меньшее количество столбцов."); var count = sheet.RowsUsed().Count() - headerRowsCount; if (count > 1024) - throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество строк."); + throw new FileFormatException($"Лист {SheetName} содержит слишком большое количество строк."); if (count <= 0) return new ParserResultDto(); diff --git a/AsbCloudInfrastructure/Services/ParserServiceFactory.cs b/AsbCloudInfrastructure/Services/ParserServiceFactory.cs index 5b852a8e..91fdbebc 100644 --- a/AsbCloudInfrastructure/Services/ParserServiceFactory.cs +++ b/AsbCloudInfrastructure/Services/ParserServiceFactory.cs @@ -3,23 +3,30 @@ using System.Collections.Generic; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; using AsbCloudApp.Services; +using AsbCloudInfrastructure.Services.ProcessMapPlan.Parser; using AsbCloudInfrastructure.Services.Trajectory.Parser; +using Microsoft.Extensions.DependencyInjection; namespace AsbCloudInfrastructure.Services; -public class ParserServiceFactory +public class ParserServiceFactory : IDisposable { - public const int IdTrajectoryFactManualParserService = 1; - public const int IdTrajectoryPlanParserService = 2; + public const int IdTrajectoryFactManualParser = 1; + public const int IdTrajectoryPlanParser = 2; + public const int IdProcessMapPlanDrillingParser = 3; private readonly IDictionary> parsers; + private readonly IServiceScope serviceScope; public ParserServiceFactory(IServiceProvider serviceProvider) { + serviceScope = serviceProvider.CreateScope(); + parsers = new Dictionary> { - { IdTrajectoryPlanParserService, () => new TrajectoryPlanParserService(serviceProvider) }, - { IdTrajectoryFactManualParserService, () => new TrajectoryFactManualParserService(serviceProvider) } + { IdTrajectoryPlanParser, () => new TrajectoryPlanParser(serviceScope.ServiceProvider) }, + { IdTrajectoryFactManualParser, () => new TrajectoryFactManualParser(serviceScope.ServiceProvider) }, + { IdProcessMapPlanDrillingParser, () => new ProcessMapPlanDrillingParser(serviceScope.ServiceProvider) } }; } @@ -33,4 +40,9 @@ public class ParserServiceFactory return parserService.Invoke() as IParserService ?? throw new ArgumentNullException(nameof(idParserService), "Ошибка приведения типа"); } + + public void Dispose() + { + serviceScope.Dispose(); + } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParserService.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParser.cs similarity index 85% rename from AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParserService.cs rename to AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParser.cs index 6e4034a5..ad173db7 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParserService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParser.cs @@ -5,12 +5,12 @@ using ClosedXML.Excel; namespace AsbCloudInfrastructure.Services.Trajectory.Parser; -public class TrajectoryFactManualParserService : TrajectoryParserService +public class TrajectoryFactManualParser : TrajectoryParser { protected override string SheetName => "Фактическая траектория"; protected override string TemplateFileName => "TrajectoryFactManualTemplate.xlsx"; - public TrajectoryFactManualParserService(IServiceProvider serviceProvider) + public TrajectoryFactManualParser(IServiceProvider serviceProvider) : base(serviceProvider) { } diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs similarity index 81% rename from AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs rename to AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs index b306e602..410b1bed 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs @@ -2,26 +2,23 @@ using AsbCloudApp.Data.Trajectory; using ClosedXML.Excel; using System.IO; -using System.Linq; using System.Reflection; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; namespace AsbCloudInfrastructure.Services.Trajectory.Parser; -public abstract class TrajectoryParserService : ParserServiceBase +public abstract class TrajectoryParser : ParserServiceBase where T : TrajectoryGeoDto { private const int HeaderRowsCount = 2; private const int ColumnCount = 6; - protected TrajectoryParserService(IServiceProvider serviceProvider) + protected TrajectoryParser(IServiceProvider serviceProvider) : base(serviceProvider) { } - - protected abstract string SheetName { get; } - + protected abstract string TemplateFileName { get; } protected abstract ValidationResultDto ParseRow(IXLRow row); diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs similarity index 87% rename from AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs rename to AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs index fbf5a537..7e400024 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs @@ -5,12 +5,12 @@ using ClosedXML.Excel; namespace AsbCloudInfrastructure.Services.Trajectory.Parser; -public class TrajectoryPlanParserService : TrajectoryParserService +public class TrajectoryPlanParser : TrajectoryParser { protected override string SheetName => "Плановая траектория"; protected override string TemplateFileName => "TrajectoryPlanTemplate.xlsx"; - public TrajectoryPlanParserService(IServiceProvider serviceProvider) + public TrajectoryPlanParser(IServiceProvider serviceProvider) : base(serviceProvider) { } diff --git a/AsbCloudInfrastructure/XLExtentions.cs b/AsbCloudInfrastructure/XLExtentions.cs index 0aeeca00..8fc0220c 100644 --- a/AsbCloudInfrastructure/XLExtentions.cs +++ b/AsbCloudInfrastructure/XLExtentions.cs @@ -2,6 +2,7 @@ using System; using System.IO; using System.Linq; +using AsbCloudApp.Services; namespace AsbCloudInfrastructure; @@ -39,8 +40,9 @@ public static class XLExtentions } catch { - throw new FileFormatException( - $"Лист '{cell.Worksheet.Name}'. {cell.Address.RowNumber} строка содержит некорректное значение в {cell.Address.ColumnNumber} столбце"); + var message = string.Format(IParserService.MessageTemplate, cell.Worksheet.Name, cell.Address.RowNumber, + cell.Address.ColumnNumber, "Содержит некорректное значение"); + throw new FileFormatException(message); } } } \ No newline at end of file diff --git a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs index 1fddd56d..2a90be08 100644 --- a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs +++ b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs @@ -37,7 +37,7 @@ public class TrajectoryParserTest Assert.Fail("Файла для импорта не существует"); var parserService = parserServiceFactory.Create( - ParserServiceFactory.IdTrajectoryPlanParserService); + ParserServiceFactory.IdTrajectoryPlanParser); var trajectoryRows = parserService.Parse(stream, IParserOptionsRequest.Empty()); @@ -54,7 +54,7 @@ public class TrajectoryParserTest Assert.Fail("Файла для импорта не существует"); var parserService = parserServiceFactory.Create( - ParserServiceFactory.IdTrajectoryFactManualParserService); + ParserServiceFactory.IdTrajectoryFactManualParser); var trajectoryRows = parserService.Parse(stream, IParserOptionsRequest.Empty()); diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactManualController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactManualController.cs index 97b84b07..9113acc8 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactManualController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactManualController.cs @@ -24,7 +24,7 @@ public class TrajectoryFactManualController : TrajectoryEditableController