From f88381353e8b2880dd6011e0cfee9f66265e67b4 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Thu, 7 Mar 2024 13:38:40 +0500 Subject: [PATCH 01/27] =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D1=83=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B9=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BE=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE?= =?UTF-8?q?=D0=B7=D0=B8=D1=82=D0=BD=D0=BE=D0=B9=20=D1=81=D0=BA=D0=B2=D0=B0?= =?UTF-8?q?=D0=B6=D0=B8=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IWellCompositeOperationService.cs | 21 +++ AsbCloudInfrastructure/DependencyInjection.cs | 1 + .../Services/WellCompositeOperationService.cs | 165 ++++++++++++++++++ .../WellCompositeOperationController.cs | 35 ++++ 4 files changed, 222 insertions(+) create mode 100644 AsbCloudApp/Services/IWellCompositeOperationService.cs create mode 100644 AsbCloudInfrastructure/Services/WellCompositeOperationService.cs create mode 100644 AsbCloudWebApi/Controllers/WellCompositeOperationController.cs diff --git a/AsbCloudApp/Services/IWellCompositeOperationService.cs b/AsbCloudApp/Services/IWellCompositeOperationService.cs new file mode 100644 index 00000000..94ba1f93 --- /dev/null +++ b/AsbCloudApp/Services/IWellCompositeOperationService.cs @@ -0,0 +1,21 @@ +using AsbCloudApp.Data; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Services +{ + /// + /// Интерфейс для вычисления композитной скважины + /// + public interface IWellCompositeOperationService + { + /// + /// Получение данных для построения композитной скважины + /// + /// + /// + /// + Task>> GetAsync(IEnumerable idsWells, CancellationToken token); + } +} diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 2111356b..6250112f 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -198,6 +198,7 @@ namespace AsbCloudInfrastructure services.AddTransient, CrudCacheRepositoryBase>(); services.AddTransient(); + services.AddTransient(); // admin crud services: services.AddTransient, CrudCacheRepositoryBase>(s => diff --git a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs new file mode 100644 index 00000000..562b82c6 --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs @@ -0,0 +1,165 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Services; +using AsbCloudDb.Model; +using Mapster; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Services +{ + public class WellCompositeOperationService : IWellCompositeOperationService + { + private IAsbCloudDbContext db; + + /// + /// Тип секции "Транспортный стол" + /// + private const int wellSectionTransportTable = 5; + + /// + /// Тип секции "Эксплуатационная колонна" + /// + private const int wellSectionProductionString = 4; + + + /// + /// набор настроек для замены одной категории секции на другую + /// + private static Dictionary<(int, int), int> SettingsForSectionCategoryChange = new Dictionary<(int, int), int>() { + { (2, 5096), 5013 }, + { (2, 5008), 5013 }, + { (3, 5096), 5084 }, + { (3, 5008), 5084 }, + { (3, 5085), 5015 }, + { (3, 5014), 5015 }, + { (31, 5014), 5015 }, + { (31, 5012), 5013 }, + { (31, 5083), 5013 }, + { (4, 5085), 5015 }, + { (4, 5087), 5015 }, + { (4, 5014), 5015 }, + { (4, 5053), 5037 }, + { (4, 5084), 5096 }, + { (4, 5086), 5013 }, + { (6, 5085), 5015 }, + { (6, 5036), 5034 }, + { (6, 5035), 5097 } + }; + + private Dictionary> WellSectionTypesWithCategories = new Dictionary>() + { + { 2, new List{ 5001, 5003, 5013, 5000, 5022, 5017, 5023, 4007, 5090 } }, + { 3, new List{ 5001, 5015, 5037, 5057, 5003, 5036, 5084, 5013, 5000, 5022, 5017, 4007, 5090, 5045, 5042, 5046 } }, + { 31, new List{ 5001, 5015, 5037, 5057, 5003, 5036, 5013, 5022, 5017, 5023, 4007, 5045, 5042, 5046 } }, + { 4, new List{ 5001, 5015, 5046, 5037, 5097, 5057, 5003, 5036, 5008, 5003, 5036, 5013, 5000, 5029, 5022, 5017, 5019, 5042, 5046 } }, + { 6, new List{ 5001, 5015, 5034, 5037, 5097, 5057, 5003 } }, + }; + + + + public WellCompositeOperationService(IAsbCloudDbContext db) + { + this.db = db; + } + + public async Task>> GetAsync(IEnumerable idsWells, CancellationToken token) + { + var sections = await db.WellSectionTypes + .Select(t => t.Adapt()) + .ToArrayAsync(token); + var sectionsDict = sections.ToDictionary(s => s.Id, s => s.Caption); + + var categories = await db.WellOperationCategories + .Select(c => c.Adapt()) + .ToArrayAsync(token); + var categoriesDict = categories.ToDictionary(s => s.Id, s => s.Name); + + var idsWellSectionTypes = WellSectionTypesWithCategories.Select(t => t.Key); + + var groupedWellOperations = db.WellOperations + .Where(o => idsWells.Contains(o.IdWell)) + .Where(o => o.IdType == WellOperation.IdOperationTypeFact) + .Where(o => idsWellSectionTypes.Contains(o.IdWellSectionType)) + .AsEnumerable() + .GroupBy(o => o.IdWellSectionType, (key, group) => group.Where(x => WellSectionTypesWithCategories[key].Contains(x.IdCategory))) + .SelectMany(o => o) + .Select(x => Convert(x, sectionsDict, categoriesDict)) + .GroupBy(o => (o.IdWellSectionType, o.IdCategory, o.IdWell), (gr, o) => o.Count() == 1 ? o.FirstOrDefault()! : new WellOperationDataDto() + { + IdWellSectionType = o.FirstOrDefault()!.IdWellSectionType, + IdCategory = o.FirstOrDefault()!.IdCategory, + DepthStart = o.Max(x => x.DepthStart), + DurationHours = o.Sum(x => x.DurationHours), + IdWell = o.FirstOrDefault()!.IdWell, + WellSectionTypeCaption = o.FirstOrDefault()!.WellSectionTypeCaption, + OperationCategoryName = o.FirstOrDefault()!.OperationCategoryName + }); + + var wellOperationsWithComposite = new List>(); + var operationsGroupBySectionAndCategory = groupedWellOperations.GroupBy(o => (o.IdWellSectionType, o.IdCategory), (key, group) => group.ToList()); + foreach (var operationGroupBySectionAndCategory in operationsGroupBySectionAndCategory) + { + var dictElem = operationGroupBySectionAndCategory.ToDictionary(o => o.IdWell); + + var currentOperation = operationGroupBySectionAndCategory.FirstOrDefault()!; + var composite = new WellOperationDataDto() + { + IdWell = 0, + IdCategory = currentOperation.IdCategory, + IdWellSectionType = currentOperation.IdWellSectionType, + DurationHours = currentOperation.DurationHours, + DepthStart = currentOperation.DepthStart, + OperationCategoryName = currentOperation.OperationCategoryName, + WellSectionTypeCaption = currentOperation.WellSectionTypeCaption, + }; + dictElem.Add(0, composite); + + if (operationGroupBySectionAndCategory.Count() == 1) + { + wellOperationsWithComposite.Add(dictElem); + continue; + } + + var maxDurationHours = operationGroupBySectionAndCategory.Max(o => o.DurationHours); + var minDurationHours = operationGroupBySectionAndCategory.Min(o => o.DurationHours); + if (maxDurationHours == minDurationHours) + { + composite.DepthStart = operationGroupBySectionAndCategory.Max(o => o.DepthStart); + } + else + { + composite.DepthStart = operationGroupBySectionAndCategory.Min(o => o.DepthStart); + } + composite.DurationHours = minDurationHours; + dictElem[0] = composite; + wellOperationsWithComposite.Add(dictElem); + } + return wellOperationsWithComposite; + } + + private static WellOperationDataDto Convert(WellOperation entity, Dictionary sectionsDict, Dictionary categoriesDict) + { + var dto = new WellOperationDataDto(); + dto.IdWellSectionType = entity.IdWellSectionType == wellSectionTransportTable + ? wellSectionProductionString + : entity.IdWellSectionType; + dto.IdCategory = (SettingsForSectionCategoryChange.TryGetValue(((entity.IdWellSectionType == wellSectionTransportTable ? wellSectionProductionString : entity.IdWellSectionType), entity.IdCategory), out int newIdCategory)) + ? newIdCategory + : entity.IdCategory; + dto.DepthStart = entity.DepthStart; + dto.DurationHours = entity.DurationHours; + dto.IdWell = entity.IdWell; + dto.OperationCategoryName = categoriesDict.TryGetValue(dto.IdCategory, out string? CategoryName) + ? CategoryName + : string.Empty; + dto.WellSectionTypeCaption = sectionsDict.TryGetValue(dto.IdWellSectionType, out string? WellSectionName) + ? WellSectionName + : string.Empty; + + return dto; + } + } +} diff --git a/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs b/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs new file mode 100644 index 00000000..e2e4ee4b --- /dev/null +++ b/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs @@ -0,0 +1,35 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudWebApi.Controllers +{ + + [ApiController] + [Authorize] + [Route("api/[controller]")] + public class WellCompositeOperationController : ControllerBase + { + private readonly IWellCompositeOperationService wellCompositeOperationService; + + public WellCompositeOperationController(IWellCompositeOperationService wellCompositeOperationService, IWellService wellService) + { + this.wellCompositeOperationService = wellCompositeOperationService; + } + + [HttpGet] + [ProducesResponseType(typeof(List>), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAsync([FromQuery] IEnumerable idsWells, CancellationToken token) + { + var result = await wellCompositeOperationService.GetAsync(idsWells, token) + .ConfigureAwait(false); + + return Ok(result); + } + } + +} From dc4d9b1708d67047f82810c0bc60598ea2068277 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Thu, 7 Mar 2024 13:48:11 +0500 Subject: [PATCH 02/27] WellOperationDataDto --- AsbCloudApp/Data/WellOperationDataDto.cs | 39 ++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 AsbCloudApp/Data/WellOperationDataDto.cs diff --git a/AsbCloudApp/Data/WellOperationDataDto.cs b/AsbCloudApp/Data/WellOperationDataDto.cs new file mode 100644 index 00000000..874bd65c --- /dev/null +++ b/AsbCloudApp/Data/WellOperationDataDto.cs @@ -0,0 +1,39 @@ +namespace AsbCloudApp.Data +{ + /// Операция на скважине + public class WellOperationDataDto : IWellRelated + { + /// + public int IdWell { get; set; } + + /// + /// id секции скважины + /// + public int IdWellSectionType { get; set; } + + /// + /// id категории операции + /// + public int IdCategory { get; set; } + + /// + /// Глубина на начало операции, м + /// + public double DepthStart { get; set; } + + /// + /// Продолжительность, часы + /// + public double DurationHours { get; set; } + + /// + /// Наименование секции + /// + public string WellSectionTypeCaption { get; set; } = string.Empty; + + /// + /// Наименование категории + /// + public string OperationCategoryName { get; set; } = string.Empty; + } +} From 3828c781299d5ac3b8bbf13b4b0d279c4043dc8c Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Mon, 11 Mar 2024 14:11:13 +0500 Subject: [PATCH 03/27] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repositories/IWellOperationRepository.cs | 8 + AsbCloudApp/Requests/WellOperationRequest.cs | 18 +- .../Repository/WellOperationRepository.cs | 25 ++ .../Services/WellCompositeOperationService.cs | 224 +++++++++++------- .../WellCompositeOperationController.cs | 18 +- 5 files changed, 207 insertions(+), 86 deletions(-) diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs index cf277304..dd39ce52 100644 --- a/AsbCloudApp/Repositories/IWellOperationRepository.cs +++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs @@ -42,6 +42,14 @@ namespace AsbCloudApp.Repositories /// Task> GetAsync(WellOperationRequest request, CancellationToken token); + /// + /// Получить список операций по запросу + /// + /// + /// + /// + Task> GetAsync(WellsOperationRequest request, CancellationToken token); + /// /// Получить страницу списка операций /// diff --git a/AsbCloudApp/Requests/WellOperationRequest.cs b/AsbCloudApp/Requests/WellOperationRequest.cs index ab5b901e..89cd6858 100644 --- a/AsbCloudApp/Requests/WellOperationRequest.cs +++ b/AsbCloudApp/Requests/WellOperationRequest.cs @@ -72,7 +72,7 @@ namespace AsbCloudApp.Requests this.LeDepth = request.LeDepth; this.GeDate = request.GeDate; this.LtDate = request.LtDate; - + this.OperationCategoryIds = request.OperationCategoryIds; this.OperationType = request.OperationType; this.SectionTypeIds = request.SectionTypeIds; @@ -82,4 +82,20 @@ namespace AsbCloudApp.Requests this.SortFields = request.SortFields; } } + + /// + /// Параметры для запроса списка операций (с массивом id скважин) + /// + public class WellsOperationRequest : WellOperationRequestBase + { + /// + /// ids скважин + /// + public IEnumerable IdsWell { get; set; } = null!; + + /// + /// Тип 0 = План или 1 = Факт + /// + public int IdType { get; set; } + } } diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index 57bf3768..be039c86 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -205,6 +205,31 @@ public class WellOperationRepository : IWellOperationRepository return dtos.Select(Convert); } + public async Task> GetAsync( + WellsOperationRequest request, + CancellationToken token) + { + var query = db.WellOperations + .Where(o => request.IdsWell.Contains(o.IdWell)) + .Where(o => request.IdType == o.IdType) + .Where(o => request.SectionTypeIds != null ? request.SectionTypeIds.Contains(o.IdWellSectionType) : true) + .Where(o => request.OperationCategoryIds != null ? request.OperationCategoryIds.Contains(o.IdCategory) : true) + .Select(o => new WellOperationDataDto(){ + DepthStart = o.DepthStart, + DurationHours = o.DurationHours, + IdCategory = o.IdCategory, + IdWell = o.IdWell, + IdWellSectionType = o.IdWellSectionType, + OperationCategoryName = o.OperationCategory.Name, + WellSectionTypeCaption = o.WellSectionType.Caption, + }) + .AsNoTracking(); + + var dtos = await query.ToArrayAsync(token); + + return dtos; + } + /// public async Task> GetPageAsync( WellOperationRequest request, diff --git a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs index 562b82c6..0056b267 100644 --- a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs +++ b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs @@ -1,7 +1,8 @@ using AsbCloudApp.Data; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; -using Mapster; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; @@ -12,7 +13,9 @@ namespace AsbCloudInfrastructure.Services { public class WellCompositeOperationService : IWellCompositeOperationService { - private IAsbCloudDbContext db; + private ICrudRepository wellSectionTypeRepository; + private IWellOperationCategoryRepository wellOperationCategoryRepository; + private IWellOperationRepository wellOperationRepository; /// /// Тип секции "Транспортный стол" @@ -49,115 +52,168 @@ namespace AsbCloudInfrastructure.Services { (6, 5035), 5097 } }; - private Dictionary> WellSectionTypesWithCategories = new Dictionary>() + private HashSet<(int IdSectionType, int IdCategory)> WellSectionTypesWithCategories = new HashSet<(int IdSectionType, int IdCategory)>() { - { 2, new List{ 5001, 5003, 5013, 5000, 5022, 5017, 5023, 4007, 5090 } }, - { 3, new List{ 5001, 5015, 5037, 5057, 5003, 5036, 5084, 5013, 5000, 5022, 5017, 4007, 5090, 5045, 5042, 5046 } }, - { 31, new List{ 5001, 5015, 5037, 5057, 5003, 5036, 5013, 5022, 5017, 5023, 4007, 5045, 5042, 5046 } }, - { 4, new List{ 5001, 5015, 5046, 5037, 5097, 5057, 5003, 5036, 5008, 5003, 5036, 5013, 5000, 5029, 5022, 5017, 5019, 5042, 5046 } }, - { 6, new List{ 5001, 5015, 5034, 5037, 5097, 5057, 5003 } }, + { (2, 5001) }, + { (2, 5003) }, + { (2, 5013) }, + { (2, 5000) }, + { (2, 5022) }, + { (2, 5017) }, + { (2, 5023) }, + { (2, 4007) }, + { (2, 5090) }, + { (3, 5001) }, + { (3, 5015) }, + { (3, 5037) }, + { (3, 5057) }, + { (3, 5003) }, + { (3, 5036) }, + { (3, 5084) }, + { (3, 5013) }, + { (3, 5000) }, + { (3, 5022) }, + { (3, 5017) }, + { (3, 4007) }, + { (3, 5090) }, + { (3, 5045) }, + { (3, 5042) }, + { (3, 5046) }, + { (31, 5001) }, + { (31, 5015) }, + { (31, 5037) }, + { (31, 5057) }, + { (31, 5003) }, + { (31, 5036) }, + { (31, 5013) }, + { (31, 5022) }, + { (31, 5017) }, + { (31, 5023) }, + { (31, 4007) }, + { (31, 5045) }, + { (31, 5042) }, + { (31, 5046) }, + { (4, 5001) }, + { (4, 5015) }, + { (4, 5046) }, + { (4, 5037) }, + { (4, 5097) }, + { (4, 5057) }, + { (4, 5003) }, + { (4, 5036) }, + { (4, 5008) }, + { (4, 5003) }, + { (4, 5036) }, + { (4, 5013) }, + { (4, 5000) }, + { (4, 5029) }, + { (4, 5022) }, + { (4, 5017) }, + { (4, 5019) }, + { (4, 5042) }, + { (4, 5046) }, + { (6, 5001) }, + { (6, 5015) }, + { (6, 5034) }, + { (6, 5037) }, + { (6, 5097) }, + { (6, 5057) }, + { (6, 5003) } }; - public WellCompositeOperationService(IAsbCloudDbContext db) + public WellCompositeOperationService( + ICrudRepository wellSectionTypeRepository, + IWellOperationCategoryRepository wellOperationCategoryRepository, + IWellOperationRepository wellOperationRepository) { - this.db = db; + this.wellSectionTypeRepository = wellSectionTypeRepository; + this.wellOperationCategoryRepository = wellOperationCategoryRepository; + this.wellOperationRepository = wellOperationRepository; } public async Task>> GetAsync(IEnumerable idsWells, CancellationToken token) { - var sections = await db.WellSectionTypes - .Select(t => t.Adapt()) - .ToArrayAsync(token); + var sections = await wellSectionTypeRepository.GetAllAsync(token); var sectionsDict = sections.ToDictionary(s => s.Id, s => s.Caption); - var categories = await db.WellOperationCategories - .Select(c => c.Adapt()) - .ToArrayAsync(token); + var categories = wellOperationCategoryRepository.Get(true); var categoriesDict = categories.ToDictionary(s => s.Id, s => s.Name); - var idsWellSectionTypes = WellSectionTypesWithCategories.Select(t => t.Key); + var idsWellSectionTypes = WellSectionTypesWithCategories.Select(t => t.IdSectionType); + var usedCategories = WellSectionTypesWithCategories.Select(c => c.IdCategory).Distinct(); - var groupedWellOperations = db.WellOperations - .Where(o => idsWells.Contains(o.IdWell)) - .Where(o => o.IdType == WellOperation.IdOperationTypeFact) - .Where(o => idsWellSectionTypes.Contains(o.IdWellSectionType)) - .AsEnumerable() - .GroupBy(o => o.IdWellSectionType, (key, group) => group.Where(x => WellSectionTypesWithCategories[key].Contains(x.IdCategory))) - .SelectMany(o => o) - .Select(x => Convert(x, sectionsDict, categoriesDict)) - .GroupBy(o => (o.IdWellSectionType, o.IdCategory, o.IdWell), (gr, o) => o.Count() == 1 ? o.FirstOrDefault()! : new WellOperationDataDto() - { - IdWellSectionType = o.FirstOrDefault()!.IdWellSectionType, - IdCategory = o.FirstOrDefault()!.IdCategory, - DepthStart = o.Max(x => x.DepthStart), - DurationHours = o.Sum(x => x.DurationHours), - IdWell = o.FirstOrDefault()!.IdWell, - WellSectionTypeCaption = o.FirstOrDefault()!.WellSectionTypeCaption, - OperationCategoryName = o.FirstOrDefault()!.OperationCategoryName - }); + var wellOperationRequest = new WellsOperationRequest() + { + IdsWell = idsWells, + OperationCategoryIds = usedCategories, + SectionTypeIds = idsWellSectionTypes, + IdType = WellOperation.IdOperationTypeFact + }; + var operations = await wellOperationRepository.GetAsync(wellOperationRequest, token); + + var renamedOperations = operations.Select(o => UpdateIdWellSectionAndIdCategory(o, sectionsDict, categoriesDict)); var wellOperationsWithComposite = new List>(); - var operationsGroupBySectionAndCategory = groupedWellOperations.GroupBy(o => (o.IdWellSectionType, o.IdCategory), (key, group) => group.ToList()); - foreach (var operationGroupBySectionAndCategory in operationsGroupBySectionAndCategory) + var compositeDepth = 0d; + foreach ((int IdSection, int IdCategory) in WellSectionTypesWithCategories) { - var dictElem = operationGroupBySectionAndCategory.ToDictionary(o => o.IdWell); + var filteredByTemplate = renamedOperations + .Where(o => o.IdWellSectionType == IdSection) + .Where(o => o.IdCategory == IdCategory); - var currentOperation = operationGroupBySectionAndCategory.FirstOrDefault()!; - var composite = new WellOperationDataDto() - { - IdWell = 0, - IdCategory = currentOperation.IdCategory, - IdWellSectionType = currentOperation.IdWellSectionType, - DurationHours = currentOperation.DurationHours, - DepthStart = currentOperation.DepthStart, - OperationCategoryName = currentOperation.OperationCategoryName, - WellSectionTypeCaption = currentOperation.WellSectionTypeCaption, - }; - dictElem.Add(0, composite); - - if (operationGroupBySectionAndCategory.Count() == 1) - { - wellOperationsWithComposite.Add(dictElem); + if (!filteredByTemplate.Any()) continue; - } - var maxDurationHours = operationGroupBySectionAndCategory.Max(o => o.DurationHours); - var minDurationHours = operationGroupBySectionAndCategory.Min(o => o.DurationHours); - if (maxDurationHours == minDurationHours) + var groupedByWell = filteredByTemplate.GroupBy(o => o.IdWell); + + var aggreagtedByWell = groupedByWell.Select(g => new WellOperationDataDto { - composite.DepthStart = operationGroupBySectionAndCategory.Max(o => o.DepthStart); - } - else - { - composite.DepthStart = operationGroupBySectionAndCategory.Min(o => o.DepthStart); - } - composite.DurationHours = minDurationHours; - dictElem[0] = composite; - wellOperationsWithComposite.Add(dictElem); + IdCategory = IdCategory, + IdWell = g.Key, + IdWellSectionType = IdSection, + DepthStart = g.Min(o => o.DepthStart), + DurationHours = g.Sum(o => o.DurationHours), + OperationCategoryName = g.First().OperationCategoryName, + WellSectionTypeCaption = g.First().WellSectionTypeCaption, + }); + + var composite = aggreagtedByWell + .OrderBy(o => o.DurationHours) + .ThenByDescending(o => o.DepthStart) + .First(); + composite.IdWell = 0; + if (compositeDepth > composite.DepthStart) + composite.DepthStart = compositeDepth; + + compositeDepth = composite.DepthStart; + + + var resultItem = aggreagtedByWell.ToDictionary(o => o.IdWell); + resultItem.Add(0, composite); + + wellOperationsWithComposite.Add(resultItem); } return wellOperationsWithComposite; } - private static WellOperationDataDto Convert(WellOperation entity, Dictionary sectionsDict, Dictionary categoriesDict) + private WellOperationDataDto UpdateIdWellSectionAndIdCategory( + WellOperationDataDto dto, + Dictionary sectionTypes, + Dictionary operationCategories) { - var dto = new WellOperationDataDto(); - dto.IdWellSectionType = entity.IdWellSectionType == wellSectionTransportTable - ? wellSectionProductionString - : entity.IdWellSectionType; - dto.IdCategory = (SettingsForSectionCategoryChange.TryGetValue(((entity.IdWellSectionType == wellSectionTransportTable ? wellSectionProductionString : entity.IdWellSectionType), entity.IdCategory), out int newIdCategory)) - ? newIdCategory - : entity.IdCategory; - dto.DepthStart = entity.DepthStart; - dto.DurationHours = entity.DurationHours; - dto.IdWell = entity.IdWell; - dto.OperationCategoryName = categoriesDict.TryGetValue(dto.IdCategory, out string? CategoryName) - ? CategoryName - : string.Empty; - dto.WellSectionTypeCaption = sectionsDict.TryGetValue(dto.IdWellSectionType, out string? WellSectionName) - ? WellSectionName - : string.Empty; + if (dto.IdWellSectionType == wellSectionTransportTable) + { + dto.IdWellSectionType = wellSectionProductionString; + dto.WellSectionTypeCaption = sectionTypes[dto.IdWellSectionType] ?? string.Empty; + } + + if ((SettingsForSectionCategoryChange.TryGetValue((dto.IdWellSectionType, dto.IdCategory), out int newIdCategory))) + { + dto.IdCategory = newIdCategory; + dto.OperationCategoryName = operationCategories[dto.IdCategory] ?? string.Empty; + } return dto; } diff --git a/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs b/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs index e2e4ee4b..d662e4e8 100644 --- a/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs +++ b/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs @@ -15,21 +15,37 @@ namespace AsbCloudWebApi.Controllers public class WellCompositeOperationController : ControllerBase { private readonly IWellCompositeOperationService wellCompositeOperationService; + private readonly IWellService wellService; public WellCompositeOperationController(IWellCompositeOperationService wellCompositeOperationService, IWellService wellService) { this.wellCompositeOperationService = wellCompositeOperationService; + this.wellService = wellService; } [HttpGet] - [ProducesResponseType(typeof(List>), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(IList>), (int)System.Net.HttpStatusCode.OK)] public async Task GetAsync([FromQuery] IEnumerable idsWells, CancellationToken token) { + foreach (var idWell in idsWells) + if (!await UserHasAccessToWellAsync(idWell, token)) + return Forbid(); + var result = await wellCompositeOperationService.GetAsync(idsWells, token) .ConfigureAwait(false); return Ok(result); } + + protected async Task UserHasAccessToWellAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + if (idCompany is not null && + await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) + .ConfigureAwait(false)) + return true; + return false; + } } } From 18c6cb316fede5bda0bace4f69b1a180dc73057d 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, 11 Mar 2024 13:16:07 +0300 Subject: [PATCH 04/27] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=B8=D0=BD=D1=84=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BaseIntegrationTest.cs | 16 +- .../Data/Defaults.cs | 157 ++++++------------ .../DbConnection.cs | 15 ++ .../WebAppFactoryFixture.cs | 98 +++++------ AsbCloudWebApi/appsettings.Tests.json | 8 + 5 files changed, 131 insertions(+), 163 deletions(-) create mode 100644 AsbCloudWebApi.IntegrationTests/DbConnection.cs create mode 100644 AsbCloudWebApi/appsettings.Tests.json diff --git a/AsbCloudWebApi.IntegrationTests/BaseIntegrationTest.cs b/AsbCloudWebApi.IntegrationTests/BaseIntegrationTest.cs index add2e07b..aeaab07f 100644 --- a/AsbCloudWebApi.IntegrationTests/BaseIntegrationTest.cs +++ b/AsbCloudWebApi.IntegrationTests/BaseIntegrationTest.cs @@ -4,15 +4,23 @@ using Xunit; namespace AsbCloudWebApi.IntegrationTests; -public abstract class BaseIntegrationTest : IClassFixture +public abstract class BaseIntegrationTest : IClassFixture, + IDisposable { protected readonly IServiceScope scope; - - protected readonly IAsbCloudDbContext dbContext; + + protected readonly AsbCloudDbContext dbContext; protected BaseIntegrationTest(WebAppFactoryFixture factory) { scope = factory.Services.CreateScope(); - dbContext = scope.ServiceProvider.GetRequiredService(); + + dbContext = scope.ServiceProvider.GetRequiredService(); + } + + public void Dispose() + { + scope.Dispose(); + dbContext.Dispose(); } } \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs b/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs index 4142705c..a3667662 100644 --- a/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs +++ b/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs @@ -2,110 +2,55 @@ namespace AsbCloudWebApi.IntegrationTests.Data { - [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2211:Поля, не являющиеся константами, не должны быть видимыми", Justification = "<Ожидание>")] - public static class Defaults - { - public static Driller[] Drillers = new Driller[] - { - new() - { - Id = 1, - Name = "test1", - Surname = "test1", - Patronymic = "test1" - }, - new() - { - Id = 2, - Name = "test2", - Surname = "test2", - Patronymic = "test2" - } - }; + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2211:Поля, не являющиеся константами, не должны быть видимыми", + Justification = "<Ожидание>")] + public static class Defaults + { + public static SimpleTimezone Timezone => new() + { + Hours = 1 + }; - public static WellOperation[] WellOperations = new WellOperation[] - { - new() - { - Id = 1, - IdWell = 1, - IdType = 1, - DateStart = DateTimeOffset.UtcNow.AddDays(-1), - CategoryInfo = "1", - Comment = "1", - DepthEnd = 20, - DepthStart = 10, - DurationHours = 1, - IdCategory = 5000, - IdPlan = null, - IdUser = 1, - IdWellSectionType = 1, - LastUpdateDate = DateTimeOffset.UtcNow - } - }; - - public static Deposit[] Deposits = new Deposit[] { - new() - { - Id = 1, - Caption = "Deposit1", - Latitude = 10, - Longitude = 20, - Timezone = GetTimezone() - } - }; - - public static Cluster[] Clusters = new Cluster[] { - new() - { - Id = 1, - IdDeposit = Deposits[0].Id, - Caption = "Cluster1", - Latitude = 10, - Longitude = 20, - Timezone = GetTimezone() - } - }; - - public static Telemetry[] Telemetries = new Telemetry[] - { - new() - { - Id = 1, - RemoteUid = "555-555-555", - TimeZone = GetTimezone() - } - }; - - public static Well[] Wells = new Well[] { - new() - { - Id = 1, - IdCluster = Clusters[0].Id, - IdWellType = 1, - IdState = 1, - Caption = "Well1", - Latitude = 10, - Longitude = 20, - IdTelemetry = Telemetries[0].Id, - Timezone = GetTimezone() - } - }; - - public static RelationCompanyWell[] RelationsCompanyWell = new RelationCompanyWell[] - { - new() { IdCompany = 1, IdWell = Wells[0].Id }, - }; - - public static RelationUserUserRole[] RelationsUserUserRole = new RelationUserUserRole[] - { - new(){ IdUserRole= 1, IdUser = 1} - }; - - private static SimpleTimezone GetTimezone() => - new () - { - Hours = 1 - }; - } -} + public static Deposit[] Deposits => new Deposit[] + { + new() + { + Caption = "Deposit1", + Latitude = 10, + Longitude = 20, + Timezone = Timezone, + Clusters = new[] + { + new Cluster + { + Caption = "Cluster1", + Latitude = 10, + Longitude = 20, + Timezone = Timezone, + Wells = new[] + { + new Well + { + IdWellType = 1, + IdState = 1, + Caption = "Well1", + Latitude = 10, + Longitude = 20, + Timezone = Timezone, + Telemetry = new Telemetry + { + RemoteUid = "555-555-555", + TimeZone = Timezone + }, + RelationCompaniesWells = new RelationCompanyWell[] + { + new() { IdCompany = 1 }, + }, + } + } + } + } + } + }; + } +} \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/DbConnection.cs b/AsbCloudWebApi.IntegrationTests/DbConnection.cs new file mode 100644 index 00000000..fad06ed8 --- /dev/null +++ b/AsbCloudWebApi.IntegrationTests/DbConnection.cs @@ -0,0 +1,15 @@ +namespace AsbCloudWebApi.IntegrationTests; + +public class DbConnection +{ + public string Host { get; set; } = null!; + + public int Port { get; set; } + + public string Username { get; set; } = null!; + + public string Password { get; set; } = null!; + + public string GetConnectionString() => + $"Host={Host};Database={Guid.NewGuid()};Port={Port};Username={Username};Password={Password};Persist Security Info=True;Include Error Detail=True"; +} \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs b/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs index 44bd4b67..b990295b 100644 --- a/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs +++ b/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs @@ -1,4 +1,3 @@ -using AsbCloudDb; using AsbCloudDb.Model; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; @@ -8,87 +7,80 @@ using Microsoft.Extensions.DependencyInjection; using Refit; using System.Net.Http.Headers; using System.Text.Json; +using AsbCloudDb; using AsbCloudWebApi.IntegrationTests.Converters; -using Xunit; namespace AsbCloudWebApi.IntegrationTests; public class WebAppFactoryFixture : WebApplicationFactory, - IAsyncLifetime + IDisposable { - private static readonly JsonSerializerOptions jsonSerializerOptions = new() - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - PropertyNameCaseInsensitive = true, + private static readonly JsonSerializerOptions JsonSerializerOptions = new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + PropertyNameCaseInsensitive = true, Converters = { new ValidationResultConverter() } - }; + }; - private static readonly RefitSettings refitSettings = new RefitSettings(new SystemTextJsonContentSerializer(jsonSerializerOptions)); + private static readonly RefitSettings RefitSettings = new(new SystemTextJsonContentSerializer(JsonSerializerOptions)); - protected override void ConfigureWebHost(IWebHostBuilder builder) + protected override void ConfigureWebHost(IWebHostBuilder builder) { var configuration = new ConfigurationBuilder() - .AddJsonFile("appsettings.json") + .AddJsonFile("appsettings.Tests.json") .Build(); - var connectionString = configuration.GetConnectionString("TestConnection")!; - builder.ConfigureServices(services => + var dbConnection = configuration.GetSection("DbConnection").Get(); + var connectionString = dbConnection?.GetConnectionString(); + + builder.ConfigureServices(services => { - var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(DbContextOptions)); + var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions)); - if (descriptor is not null) + if (descriptor != null) services.Remove(descriptor); services.AddDbContext(options => options.UseNpgsql(connectionString)); + + var serviceProvider = services.BuildServiceProvider(); + + using var scope = serviceProvider.CreateScope(); + var scopedServices = scope.ServiceProvider; + var dbContext = scopedServices.GetRequiredService(); + + dbContext.Database.EnsureCreatedAndMigrated(); + dbContext.Deposits.AddRange(Data.Defaults.Deposits); + dbContext.SaveChanges(); }); } - public async Task InitializeAsync() + public new void Dispose() { using var scope = Services.CreateScope(); var scopedServices = scope.ServiceProvider; var dbContext = scopedServices.GetRequiredService(); - dbContext.Database.EnsureDeleted(); - dbContext.Database.EnsureCreatedAndMigrated(); - await FillBaseDatasets(dbContext); + + dbContext.Database.EnsureDeleted(); } - private static async Task FillBaseDatasets(AsbCloudDbContext dbContext) - { - dbContext.AddRange(Data.Defaults.Deposits); - dbContext.AddRange(Data.Defaults.Clusters); - dbContext.AddRange(Data.Defaults.Wells); - dbContext.AddRange(Data.Defaults.RelationsCompanyWell); - dbContext.AddRange(Data.Defaults.Telemetries); - dbContext.AddRange(Data.Defaults.Drillers); - dbContext.AddRange(Data.Defaults.WellOperations); - await dbContext.SaveChangesAsync(); - } - - public new async Task DisposeAsync() + public T GetAuthorizedHttpClient(string uriSuffix) { - using var scope = Services.CreateScope(); - var scopedServices = scope.ServiceProvider; - var dbContext = scopedServices.GetRequiredService(); - - await dbContext.Database.EnsureDeletedAsync(); - } + var httpClient = GetAuthorizedHttpClient(); + if (string.IsNullOrEmpty(uriSuffix)) + return RestService.For(httpClient, RefitSettings); - public HttpClient GetAuthorizedHttpClient() - { - var httpClient = CreateClient(); - var jwtToken = ApiTokenHelper.GetAdminUserToken(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken); - return httpClient; - } + if (httpClient.BaseAddress is not null) + httpClient.BaseAddress = new Uri(httpClient.BaseAddress, uriSuffix); - public T GetAuthorizedHttpClient(string uriSuffix) - { - var httpClient = GetAuthorizedHttpClient(); - if (!string.IsNullOrEmpty(uriSuffix)) - if(httpClient.BaseAddress is not null) - httpClient.BaseAddress = new Uri(httpClient.BaseAddress, uriSuffix); - return RestService.For(httpClient, refitSettings); - } + return RestService.For(httpClient, RefitSettings); + } + + private HttpClient GetAuthorizedHttpClient() + { + var httpClient = CreateClient(); + var jwtToken = ApiTokenHelper.GetAdminUserToken(); + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken); + return httpClient; + } } \ No newline at end of file diff --git a/AsbCloudWebApi/appsettings.Tests.json b/AsbCloudWebApi/appsettings.Tests.json new file mode 100644 index 00000000..d04cf2b1 --- /dev/null +++ b/AsbCloudWebApi/appsettings.Tests.json @@ -0,0 +1,8 @@ +{ + "DbConnection": { + "Host": "localhost", + "Port": 5433, + "Username": "postgres", + "Password": "root" + } +} \ No newline at end of file From 3d828a21590324547ee91a50d6cf26d1b7a13f23 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, 11 Mar 2024 13:19:50 +0300 Subject: [PATCH 05/27] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/AdminDepositControllerTest.cs | 20 +- .../ProcessMapPlanDrillingControllerTest.cs | 17 +- .../ProcessMapReportDrillingControllerTest.cs | 505 ++++++++---------- .../Controllers/ScheduleControllerTest.cs | 456 ++++++++-------- .../Controllers/SlipsStatControllerTest.cs | 111 ++-- .../WellOperationControllerTest.cs | 197 +++---- .../Repository/DataSaubStatRepositoryTest.cs | 254 ++++----- 7 files changed, 735 insertions(+), 825 deletions(-) diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/AdminDepositControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/AdminDepositControllerTest.cs index 331c7b7d..06ce5f69 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/AdminDepositControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/AdminDepositControllerTest.cs @@ -1,6 +1,5 @@ using System.Net; using AsbCloudApp.Data; -using AsbCloudDb.Model; using AsbCloudWebApi.IntegrationTests.Clients; using Mapster; using Microsoft.EntityFrameworkCore; @@ -27,8 +26,6 @@ public class AdminDepositControllerTest : BaseIntegrationTest : base(factory) { client = factory.GetAuthorizedHttpClient(string.Empty); - - dbContext.CleanupDbSet(); } [Fact] @@ -130,11 +127,8 @@ public class AdminDepositControllerTest : BaseIntegrationTest [Fact] public async Task GetOrDefault_returns_NoContent_for_IdDeposit() { - //arrange - const int idInvalid = 0; - //act - var responce = await client.GetOrDefaultAsync(idInvalid); + var responce = await client.GetOrDefaultAsync(0); //assert Assert.Equal(HttpStatusCode.NoContent, responce.StatusCode); @@ -143,9 +137,6 @@ public class AdminDepositControllerTest : BaseIntegrationTest [Fact] public async Task GetAll_returns_success() { - //arrange - await client.InsertAsync(dto); - //act var response = await client.GetAllAsync(); @@ -155,10 +146,6 @@ public class AdminDepositControllerTest : BaseIntegrationTest var expectedCount = await dbContext.Deposits.CountAsync(); Assert.Equal(expectedCount, response.Content.Count()); - - var deposit = response.Content.First(); - var excludeProps = new[] { nameof(DepositBaseDto.Id) }; - MatchHelper.Match(dto, deposit, excludeProps); } [Fact] @@ -182,11 +169,8 @@ public class AdminDepositControllerTest : BaseIntegrationTest [Fact] public async Task Delete_returns_NoContent_IdDeposit() { - //arrange - const int idInvalid = 0; - //act - var response = await client.DeleteAsync(idInvalid); + var response = await client.DeleteAsync(0); //assert Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs index 0ff8bb97..b5df18bb 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs @@ -15,6 +15,8 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers.ProcessMapPlan; public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest { + private const int IdWell = 1; + private readonly ProcessMapPlanDrillingDto dto = new (){ Id = 0, Creation = new(), @@ -22,7 +24,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest IdState = 0, IdPrevious = null, - IdWell = 1, + IdWell = IdWell, Section = "Кондуктор", IdWellSectionType = 3, DepthStart = 0.5, @@ -55,7 +57,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest IdState = AsbCloudDb.Model.ChangeLogAbstract.IdStateActual, IdPrevious = null, - IdWell = 1, + IdWell = IdWell, IdWellSectionType = 1, DepthStart = 0.5, DepthEnd = 1.5, @@ -346,7 +348,6 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest Assert.InRange(actual.Obsolete.Value, startTime, doneTime); } - [Fact] public async Task GetDatesChange_returns_success() { @@ -358,7 +359,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest dbset.Add(entity); dbset.Add(entity2); dbContext.SaveChanges(); - var timezoneHours = Data.Defaults.Wells[0].Timezone.Hours; + var timezoneHours = Defaults.Timezone.Hours; var offset = TimeSpan.FromHours(timezoneHours); var dates = new[] { entity.Creation, entity2.Creation } .Select(d => d.ToOffset(offset)) @@ -537,7 +538,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest dbContext.SaveChanges(); - var timezoneHours = Data.Defaults.Wells[0].Timezone.Hours; + var timezoneHours = Defaults.Timezone.Hours; var offset = TimeSpan.FromHours(timezoneHours); var updateFrom = entity.Creation.ToOffset(offset).AddHours(0.5); @@ -574,7 +575,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest //act var streamPart = new StreamPart(stream, fileName, "application/octet-stream"); - var response = await client.Parse(Defaults.Wells[0].Id, new[] { streamPart }); + var response = await client.Parse(IdWell, new[] { streamPart }); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -603,7 +604,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest //act var streamPart = new StreamPart(stream, fileName, "application/octet-stream"); - var response = await client.Parse(Defaults.Wells[0].Id, new[] { streamPart }); + var response = await client.Parse(IdWell, new[] { streamPart }); Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -619,4 +620,4 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest Assert.False(row.IsValid); Assert.Equal(2, row.Warnings.Count()); } -} +} \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapReportDrillingControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapReportDrillingControllerTest.cs index 3083d514..7de0acd5 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapReportDrillingControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapReportDrillingControllerTest.cs @@ -2,314 +2,255 @@ using AsbCloudDb.Model; using AsbCloudDb.Model.ProcessMaps; using AsbCloudWebApi.IntegrationTests.Clients; -using Org.BouncyCastle.Asn1.Ocsp; using System.Net; -using System.Net.Http.Headers; +using AsbCloudWebApi.IntegrationTests.Data; using Xunit; namespace AsbCloudWebApi.IntegrationTests.Controllers.ProcessMapPlan; public class ProcessMapReportDrillingControllerTest : BaseIntegrationTest { + private IProcessMapReportDrilling client; - private readonly WellSectionType wellSection = new WellSectionType() - { - Id = 1, - Caption = "Секция 1", - Order = 1 - }; + public ProcessMapReportDrillingControllerTest(WebAppFactoryFixture factory) + : base(factory) + { + dbContext.CleanupDbSet(); + dbContext.CleanupDbSet(); + client = factory.GetAuthorizedHttpClient(string.Empty); + } - private readonly WellOperationCategory wellOperationCategory = new WellOperationCategory() - { - Id = 1, - IdParent = null, - KeyValueName = "Name", - Name = "Name" - }; + [Fact] + public async Task Get_rtk_report_by_default_request_returns_success() + { + //arrange + var well = dbContext.Wells.First(); - private readonly WellOperation wellOperation = new WellOperation() - { - CategoryInfo = "CategoryInfo", - Id = 10, - Comment = "Comment", - DateStart = DateTimeOffset.UtcNow, - DepthEnd = 1, - DepthStart = 0.6, - DurationHours = 10, - IdCategory = 1, - IdPlan = null, - IdType = 1, - IdUser = 1, - IdWell = 1, - IdWellSectionType = 1, - LastUpdateDate = DateTimeOffset.UtcNow - }; + var processMapPlanDrilling = CreateProcessMapPlanDrilling(well.Id); + dbContext.ProcessMapPlanDrilling.Add(processMapPlanDrilling); - private readonly List dataSaubStats = new List() - { + var wellOperation = CreateWellOperation(well.Id); + dbContext.WellOperations.Add(wellOperation); - new DataSaubStat() - { - AxialLoad = 0, - AxialLoadLimitMax = 10, - AxialLoadSp = 8, - BlockSpeedSp = 50.0, - DateEnd = DateTimeOffset.UtcNow.AddMinutes(40), - DateStart = DateTimeOffset.UtcNow.AddMinutes(30), - DepthEnd = 85.99299621582031, - DepthStart = 85.9260025024414, - EnabledSubsystems = 0, - Flow = 10, - HasOscillation = true, - Id = 1, - IdCategory = 1, - IdFeedRegulator = 0, - IdTelemetry = 1, - Pressure = 24, - PressureIdle = 0, - PressureSp = 40, - RotorSpeed = 11.3, - RotorTorque = 1, - RotorTorqueLimitMax = 26.5, - RotorTorqueSp = 5, - Speed = 80.3924560546875 - }, - new DataSaubStat() - { - AxialLoad = 2, - AxialLoadLimitMax = 10.0, - AxialLoadSp = 8, - BlockSpeedSp = 20, - DateEnd = DateTimeOffset.UtcNow.AddMinutes(30), - DateStart = DateTimeOffset.UtcNow.AddMinutes(20), - DepthEnd = 86.28099822998047, - DepthStart = 86.21900177001953, - EnabledSubsystems = 1, - Flow = 20, - HasOscillation = true, - Id = 2, - IdCategory = 1, - IdFeedRegulator = 1, - IdTelemetry = 1, - Pressure = 30, - PressureIdle = 20, - PressureSp = 40, - RotorSpeed = 11.251153300212916, - RotorTorque = 7, - RotorTorqueLimitMax = 26.5, - RotorTorqueSp = 9, - Speed = 74.395751953125 - }, - new DataSaubStat() - { - AxialLoad = 4, - AxialLoadLimitMax = 15.0, - AxialLoadSp = 8, - BlockSpeedSp = 110.0, - DateEnd = DateTimeOffset.UtcNow.AddMinutes(20), - DateStart = DateTimeOffset.UtcNow.AddMinutes(10), - DepthEnd = 106.7490005493164, - DepthStart = 106.47899627685547, - EnabledSubsystems = 1, - Flow = 30, - HasOscillation = true, - Id = 3, - IdCategory = 1, - IdFeedRegulator = 1, - IdTelemetry = 1, - Pressure = 36, - PressureIdle = 23.0, - PressureSp = 63.0, - RotorSpeed = 11.334207942999628, - RotorTorque = 14, - RotorTorqueLimitMax = 15.0, - RotorTorqueSp = 13, - Speed = 108.001708984375 - } - }; + var dataSaubStats = CreateDataSaubStats(well.IdTelemetry!.Value, wellOperation.IdCategory); + dbContext.DataSaubStat.AddRange(dataSaubStats); + await dbContext.SaveChangesAsync(); + //act + var request = new DataSaubStatRequest(); + var response = await client.GetReportAsync(well.Id, request, CancellationToken.None); + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(response.Content); + Assert.Equal(dataSaubStats.Count() - 1, response.Content.Count()); + } - private readonly ProcessMapPlanDrilling entity = new() - { - Id = 0, - IdAuthor = 1, - IdEditor = null, - Creation = DateTimeOffset.UtcNow, - Obsolete = null, - IdState = AsbCloudDb.Model.ChangeLogAbstract.IdStateActual, - IdPrevious = null, + [Fact] + public async Task Get_rtk_report_by_parametrize_request_returns_success() + { + //arrange + var well = dbContext.Wells.First(); - IdWell = 1, - IdWellSectionType = 1, - DepthStart = 0.5, - DepthEnd = 1.5, + var processMapPlanDrilling = CreateProcessMapPlanDrilling(well.Id); + dbContext.ProcessMapPlanDrilling.Add(processMapPlanDrilling); - IdMode = 1, - AxialLoadPlan = 2.718281, - AxialLoadLimitMax = 3.1415926, - DeltaPressurePlan = 4, - DeltaPressureLimitMax = 5, - TopDriveTorquePlan = 6, - TopDriveTorqueLimitMax = 7, - TopDriveSpeedPlan = 8, - TopDriveSpeedLimitMax = 9, - FlowPlan = 10, - FlowLimitMax = 11, - RopPlan = 12, - UsageSaub = 13, - UsageSpin = 14, - Comment = "это тестовая запись", - }; + var wellOperation = CreateWellOperation(well.Id); + dbContext.WellOperations.Add(wellOperation); - private IProcessMapReportDrilling client; + var dataSaubStats = CreateDataSaubStats(well.IdTelemetry!.Value, wellOperation.IdCategory); + dbContext.DataSaubStat.AddRange(dataSaubStats); - public ProcessMapReportDrillingControllerTest(WebAppFactoryFixture factory) : base(factory) - { - client = factory.GetAuthorizedHttpClient(string.Empty); - } + await dbContext.SaveChangesAsync(); + + var request = new DataSaubStatRequest + { + DeltaAxialLoad = 5, + DeltaPressure = 15, + DeltaRotorTorque = 10 + }; + + //act + var response = await client.GetReportAsync(well.Id, request, CancellationToken.None); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(response.Content); + Assert.Equal(1, response.Content.Count()); + } + + [Fact] + public async Task Get_rtk_report_returns_BadRequest() + { + //act + var request = new DataSaubStatRequest() + { + DeltaAxialLoad = 15, + DeltaPressure = 25, + DeltaRotorTorque = 20 + }; + var response = await client.GetReportAsync(0, request, CancellationToken.None); + + //assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + + [Fact] + public async Task Export_rtk_report_returns_success() + { + //arrange + var well = dbContext.Wells.First(); + var processMapPlanDrilling = CreateProcessMapPlanDrilling(well.Id); + dbContext.ProcessMapPlanDrilling.Add(processMapPlanDrilling); - [Fact] - public async Task Get_rtk_report_by_default_request_returns_success() - { - //arrange - dbContext.CleanupDbSet(); - var dbset = dbContext.Set(); - dbset.Add(entity); - entity.Id = 1; - dbset.Add(entity); - entity.Id = 2; - dbset.Add(entity); + var wellOperation = CreateWellOperation(well.Id); + dbContext.WellOperations.Add(wellOperation); - var dbSetWellOperationCategory = dbContext.Set(); - dbSetWellOperationCategory.Add(wellOperationCategory); + var dataSaubStats = CreateDataSaubStats(well.IdTelemetry!.Value, wellOperation.IdCategory); + dbContext.DataSaubStat.AddRange(dataSaubStats); - var dbSetWellOperation = dbContext.Set(); - dbSetWellOperation.Add(wellOperation); + await dbContext.SaveChangesAsync(); + + //act + var request = new DataSaubStatRequest(); + var response = await client.ExportReportAsync(1, request, CancellationToken.None); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("application/octet-stream", response.ContentHeaders?.ContentType?.MediaType); + Assert.True(response.ContentHeaders?.ContentLength > 0); + } - var dbSetDataSaubStat = dbContext.Set(); - dbSetDataSaubStat.AddRange(dataSaubStats); + private static WellOperation CreateWellOperation(int idWell) => + new() + { + CategoryInfo = "CategoryInfo", + Comment = "Comment", + DateStart = DateTimeOffset.UtcNow, + DepthEnd = 1, + DepthStart = 0.6, + DurationHours = 10, + IdCategory = WellOperationCategory.IdSlide, + IdPlan = null, + IdType = WellOperation.IdOperationTypeFact, + IdUser = 1, + IdWell = idWell, + IdWellSectionType = 1, + LastUpdateDate = DateTimeOffset.UtcNow + }; - dbContext.SaveChanges(); + private static ProcessMapPlanDrilling CreateProcessMapPlanDrilling(int idWell) => + new() + { + IdAuthor = 1, + IdEditor = null, + Creation = DateTimeOffset.UtcNow, + Obsolete = null, + IdState = ChangeLogAbstract.IdStateActual, + IdPrevious = null, - //act - var request = new DataSaubStatRequest(); - var response = await client.GetReportAsync(1, request, CancellationToken.None); + IdWell = idWell, + IdWellSectionType = 1, + DepthStart = 0.5, + DepthEnd = 1.5, - //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Equal(dataSaubStats.Count() - 1, response.Content.Count()); - } + IdMode = 1, + AxialLoadPlan = 2.718281, + AxialLoadLimitMax = 3.1415926, + DeltaPressurePlan = 4, + DeltaPressureLimitMax = 5, + TopDriveTorquePlan = 6, + TopDriveTorqueLimitMax = 7, + TopDriveSpeedPlan = 8, + TopDriveSpeedLimitMax = 9, + FlowPlan = 10, + FlowLimitMax = 11, + RopPlan = 12, + UsageSaub = 13, + UsageSpin = 14, + Comment = "это тестовая запись", + }; - [Fact] - public async Task Get_rtk_report_by_parametrize_request_returns_success() - { - //arrange - dbContext.CleanupDbSet(); - var dbset = dbContext.Set(); - dbset.Add(entity); - entity.Id = 1; - dbset.Add(entity); - entity.Id = 2; - dbset.Add(entity); - - var dbSetWellOperationCategory = dbContext.Set(); - dbSetWellOperationCategory.Add(wellOperationCategory); - - var dbSetWellOperation = dbContext.Set(); - dbSetWellOperation.Add(wellOperation); - - var dbSetDataSaubStat = dbContext.Set(); - dbSetDataSaubStat.AddRange(dataSaubStats); - - dbContext.SaveChanges(); - - //act - var request = new DataSaubStatRequest() - { - DeltaAxialLoad = 5, - DeltaPressure = 15, - DeltaRotorTorque = 10 - }; - var response = await client.GetReportAsync(1, request, CancellationToken.None); - - //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Equal(1, response.Content.Count()); - } - - [Fact] - public async Task Get_rtk_report_returns_BadRequest() - { - //arrange - dbContext.CleanupDbSet(); - var dbset = dbContext.Set(); - dbset.Add(entity); - entity.Id = 1; - dbset.Add(entity); - entity.Id = 2; - dbset.Add(entity); - - var dbSetWellOperationCategory = dbContext.Set(); - dbSetWellOperationCategory.Add(wellOperationCategory); - - var dbSetWellOperation = dbContext.Set(); - dbSetWellOperation.Add(wellOperation); - - var dbSetDataSaubStat = dbContext.Set(); - dbSetDataSaubStat.AddRange(dataSaubStats); - - dbContext.SaveChanges(); - - //act - var request = new DataSaubStatRequest() - { - DeltaAxialLoad = 15, - DeltaPressure = 25, - DeltaRotorTorque = 20 - }; - var response = await client.GetReportAsync(1, request, CancellationToken.None); - - //assert - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - } - - [Fact] - public async Task Export_rtk_report_returns_success() - { - //clear - dbContext.CleanupDbSet(); - - //arrange - var dbset = dbContext.Set(); - dbset.Add(entity); - entity.Id = 1; - dbset.Add(entity); - entity.Id = 2; - dbset.Add(entity); - - var dbSetWellOperationCategory = dbContext.Set(); - dbSetWellOperationCategory.Add(wellOperationCategory); - - var dbSetWellOperation = dbContext.Set(); - dbSetWellOperation.Add(wellOperation); - - var dbSetDataSaubStat = dbContext.Set(); - dbSetDataSaubStat.AddRange(dataSaubStats); - - dbContext.SaveChanges(); - - //act - var request = new DataSaubStatRequest(); - var response = await client.ExportReportAsync(1, request, CancellationToken.None); - - //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("application/octet-stream", response.ContentHeaders?.ContentType?.MediaType); - Assert.True(response.ContentHeaders?.ContentLength > 0); - } -} + private static IEnumerable CreateDataSaubStats(int idTelemetry, + int idCategory) => + new[] + { + new DataSaubStat + { + AxialLoad = 0, + AxialLoadLimitMax = 10, + AxialLoadSp = 8, + BlockSpeedSp = 50.0, + DateEnd = DateTimeOffset.UtcNow.AddMinutes(40), + DateStart = DateTimeOffset.UtcNow.AddMinutes(30), + DepthEnd = 85.99299621582031, + DepthStart = 85.9260025024414, + EnabledSubsystems = 0, + Flow = 10, + IdCategory = idCategory, + HasOscillation = true, + IdFeedRegulator = 0, + IdTelemetry = idTelemetry, + Pressure = 24, + PressureIdle = 0, + PressureSp = 40, + RotorSpeed = 11.3, + RotorTorque = 1, + RotorTorqueLimitMax = 26.5, + RotorTorqueSp = 5, + Speed = 80.3924560546875 + }, + new DataSaubStat + { + AxialLoad = 2, + AxialLoadLimitMax = 10.0, + AxialLoadSp = 8, + BlockSpeedSp = 20, + DateEnd = DateTimeOffset.UtcNow.AddMinutes(30), + DateStart = DateTimeOffset.UtcNow.AddMinutes(20), + DepthEnd = 86.28099822998047, + DepthStart = 86.21900177001953, + EnabledSubsystems = 1, + Flow = 20, + HasOscillation = true, + IdCategory = idCategory, + IdFeedRegulator = 1, + IdTelemetry = idTelemetry, + Pressure = 30, + PressureIdle = 20, + PressureSp = 40, + RotorSpeed = 11.251153300212916, + RotorTorque = 7, + RotorTorqueLimitMax = 26.5, + RotorTorqueSp = 9, + Speed = 74.395751953125 + }, + new DataSaubStat + { + AxialLoad = 4, + AxialLoadLimitMax = 15.0, + AxialLoadSp = 8, + BlockSpeedSp = 110.0, + DateEnd = DateTimeOffset.UtcNow.AddMinutes(20), + DateStart = DateTimeOffset.UtcNow.AddMinutes(10), + DepthEnd = 106.7490005493164, + DepthStart = 106.47899627685547, + EnabledSubsystems = 1, + Flow = 30, + HasOscillation = true, + IdFeedRegulator = 1, + IdTelemetry = idTelemetry, + IdCategory = idCategory, + Pressure = 36, + PressureIdle = 23.0, + PressureSp = 63.0, + RotorSpeed = 11.334207942999628, + RotorTorque = 14, + RotorTorqueLimitMax = 15.0, + RotorTorqueSp = 13, + Speed = 108.001708984375 + } + }; +} \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs index a58e20f1..ad7571a2 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs @@ -1,228 +1,228 @@ -using AsbCloudApp.Data; -using AsbCloudDb.Model; -using AsbCloudInfrastructure; -using AsbCloudWebApi.IntegrationTests.Clients; -using Mapster; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using System.Net; -using Xunit; - -namespace AsbCloudWebApi.IntegrationTests.Controllers -{ - public abstract class CrudWellRelatedClient : BaseIntegrationTest - where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated - where TEntity : class, AsbCloudDb.Model.IId, AsbCloudDb.Model.IWellRelated - { - public abstract IEnumerable ValidDtos { get; } - public abstract IEnumerable InvalidDtos { get; } - public abstract IEnumerable ForbiddenDtos { get; } - protected List ExcludeProps { get; set; } = new() { "Id" }; - - protected ICrudWellRelatedClient client; - - public CrudWellRelatedClient(WebAppFactoryFixture factory, string uriSuffix) - : base(factory) - { - client = factory.GetAuthorizedHttpClient>(uriSuffix); - } - - protected async Task> GetCleanDbSet() - { - var dbset = dbContext.Set(); - dbset.RemoveRange(dbset); - await dbContext.SaveChangesAsync(CancellationToken.None); - return dbset; - } - - [Fact] - public async Task Insert_returns_success_for_validDtos() - { - foreach (var validDto in ValidDtos) - await Insert_returns_success(validDto); - } - - private async Task Insert_returns_success(TDto validDto) - { - var dbset = await GetCleanDbSet(); - - //act - var response = await client.InsertAsync(validDto); - - //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.True(response.Content > 0); - - var entity = dbset.First(); - var fromDbDto = Convert(entity); - MatchHelper.Match(validDto, fromDbDto, ExcludeProps); - } - - [Fact] - public async Task Insert_returns_badRequest_for_invalidDtos() - { - foreach (var inValidDto in InvalidDtos) - await Insert_returns_badRequest(inValidDto); - } - - private async Task Insert_returns_badRequest(TDto invalidDto) - { - await GetCleanDbSet(); - - //act - var response = await client.InsertAsync(invalidDto); - - //assert - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - } - - [Fact] - public async Task Insert_returns_forbidden_for_forbiddenDtos() - { - foreach (var forbiddenDto in ForbiddenDtos) - await Insert_returns_forbidden(forbiddenDto); - } - - private async Task Insert_returns_forbidden(TDto forbiddenDto) - { - await GetCleanDbSet(); - - //act - var response = await client.InsertAsync(forbiddenDto); - - //assert - Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); - } - - [Fact] - public async Task GetAllAsync_returns_data() - { - //arrange - var dbset = await GetCleanDbSet(); - var entries = new List<(EntityEntry, TDto)>(); - - foreach (var dto in ValidDtos) - { - var entity = Convert(dto); - entity.Id = 0; - var entry = dbset.Add(entity); - entries.Add((entry, dto)); - } - dbContext.SaveChanges(); - - //act - var response = await client.GetAllAsync(); - - //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Equal(entries.Count, response.Content.Count()); - - foreach (var item in response.Content) - { - var entry = entries.First(e => e.Item1.Entity.Id == item.Id); - MatchHelper.Match(entry.Item2, item, ExcludeProps); - } - } - - protected virtual TDto Convert(TEntity entity) - { - var dto = entity.Adapt(); - return dto; - } - - protected virtual TEntity Convert(TDto dto) - { - var entity = dto.Adapt(); - return entity; - } - } - - public class ScheduleControllerTest : CrudWellRelatedClient - { - static Driller driller = Data.Defaults.Drillers.First(); - static DrillerDto drillerDto = driller.Adapt(); - - static Well well = Data.Defaults.Wells.First(); - - public override IEnumerable ValidDtos { get; } = new ScheduleDto[] - { - new() { - Id = 1, - IdWell = well.Id, - Driller = drillerDto, - IdDriller = driller.Id, - DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), - DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), - ShiftStart = new TimeDto(8, 0, 0), - ShiftEnd = new TimeDto(20, 0, 0), - }, - new() { - Id = 1, - IdWell = well.Id, - Driller = drillerDto, - IdDriller = driller.Id, - DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), - DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), - ShiftStart = new TimeDto(20, 0, 0), - ShiftEnd = new TimeDto(8, 0, 0), - } - }; - - public override IEnumerable InvalidDtos { get; } = new ScheduleDto[] - { - new() { - IdWell = well.Id, - Driller = drillerDto, - IdDriller = driller.Id, - DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), - DrillEnd = new DateTime(2022, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), - ShiftStart = new TimeDto(8, 0, 0), - ShiftEnd = new TimeDto(20, 0, 0), - }, - new() { - IdWell = well.Id, - Driller = drillerDto, - IdDriller = int.MaxValue - 1, - DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), - DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), - ShiftStart = new TimeDto(8, 0, 0), - ShiftEnd = new TimeDto(20, 0, 0), - } - }; - - public override IEnumerable ForbiddenDtos { get; } = new ScheduleDto[] { - new() { - IdWell = int.MaxValue - 1, - Driller = drillerDto, - IdDriller = driller.Id, - DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), - DrillEnd = new DateTime(2022, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), - ShiftStart = new TimeDto(8, 0, 0), - ShiftEnd = new TimeDto(20, 0, 0), - } - }; - - public ScheduleControllerTest(WebAppFactoryFixture factory) - : base(factory, "api/schedule") - { - ExcludeProps.Add(nameof(ScheduleDto.Driller)); - } - - protected override ScheduleDto Convert(Schedule entity) - { - var dto = base.Convert(entity); - dto.DrillStart = entity.DrillStart.ToRemoteDateTime(well.Timezone.Hours); - dto.DrillEnd = entity.DrillEnd.ToRemoteDateTime(well.Timezone.Hours); - return dto; - } - - protected override Schedule Convert(ScheduleDto dto) - { - var entity = base.Convert(dto); - entity.DrillStart = dto.DrillStart.FromTimeZoneOffsetHours(well.Timezone.Hours); - entity.DrillEnd = dto.DrillEnd.FromTimeZoneOffsetHours(well.Timezone.Hours); - return entity; - } - } -} +// using AsbCloudApp.Data; +// using AsbCloudDb.Model; +// using AsbCloudInfrastructure; +// using AsbCloudWebApi.IntegrationTests.Clients; +// using Mapster; +// using Microsoft.EntityFrameworkCore; +// using Microsoft.EntityFrameworkCore.ChangeTracking; +// using System.Net; +// using Xunit; +// +// namespace AsbCloudWebApi.IntegrationTests.Controllers +// { +// public abstract class CrudWellRelatedClient : BaseIntegrationTest +// where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated +// where TEntity : class, AsbCloudDb.Model.IId, AsbCloudDb.Model.IWellRelated +// { +// public abstract IEnumerable ValidDtos { get; } +// public abstract IEnumerable InvalidDtos { get; } +// public abstract IEnumerable ForbiddenDtos { get; } +// protected List ExcludeProps { get; set; } = new() { "Id" }; +// +// protected ICrudWellRelatedClient client; +// +// public CrudWellRelatedClient(WebAppFactoryFixture factory, string uriSuffix) +// : base(factory) +// { +// client = factory.GetAuthorizedHttpClient>(uriSuffix); +// } +// +// protected async Task> GetCleanDbSet() +// { +// var dbset = dbContext.Set(); +// dbset.RemoveRange(dbset); +// await dbContext.SaveChangesAsync(CancellationToken.None); +// return dbset; +// } +// +// [Fact] +// public async Task Insert_returns_success_for_validDtos() +// { +// foreach (var validDto in ValidDtos) +// await Insert_returns_success(validDto); +// } +// +// private async Task Insert_returns_success(TDto validDto) +// { +// var dbset = await GetCleanDbSet(); +// +// //act +// var response = await client.InsertAsync(validDto); +// +// //assert +// Assert.Equal(HttpStatusCode.OK, response.StatusCode); +// Assert.True(response.Content > 0); +// +// var entity = dbset.First(); +// var fromDbDto = Convert(entity); +// MatchHelper.Match(validDto, fromDbDto, ExcludeProps); +// } +// +// [Fact] +// public async Task Insert_returns_badRequest_for_invalidDtos() +// { +// foreach (var inValidDto in InvalidDtos) +// await Insert_returns_badRequest(inValidDto); +// } +// +// private async Task Insert_returns_badRequest(TDto invalidDto) +// { +// await GetCleanDbSet(); +// +// //act +// var response = await client.InsertAsync(invalidDto); +// +// //assert +// Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); +// } +// +// [Fact] +// public async Task Insert_returns_forbidden_for_forbiddenDtos() +// { +// foreach (var forbiddenDto in ForbiddenDtos) +// await Insert_returns_forbidden(forbiddenDto); +// } +// +// private async Task Insert_returns_forbidden(TDto forbiddenDto) +// { +// await GetCleanDbSet(); +// +// //act +// var response = await client.InsertAsync(forbiddenDto); +// +// //assert +// Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); +// } +// +// [Fact] +// public async Task GetAllAsync_returns_data() +// { +// //arrange +// var dbset = await GetCleanDbSet(); +// var entries = new List<(EntityEntry, TDto)>(); +// +// foreach (var dto in ValidDtos) +// { +// var entity = Convert(dto); +// entity.Id = 0; +// var entry = dbset.Add(entity); +// entries.Add((entry, dto)); +// } +// dbContext.SaveChanges(); +// +// //act +// var response = await client.GetAllAsync(); +// +// //assert +// Assert.Equal(HttpStatusCode.OK, response.StatusCode); +// Assert.NotNull(response.Content); +// Assert.Equal(entries.Count, response.Content.Count()); +// +// foreach (var item in response.Content) +// { +// var entry = entries.First(e => e.Item1.Entity.Id == item.Id); +// MatchHelper.Match(entry.Item2, item, ExcludeProps); +// } +// } +// +// protected virtual TDto Convert(TEntity entity) +// { +// var dto = entity.Adapt(); +// return dto; +// } +// +// protected virtual TEntity Convert(TDto dto) +// { +// var entity = dto.Adapt(); +// return entity; +// } +// } +// +// public class ScheduleControllerTest : CrudWellRelatedClient +// { +// static Driller driller = Data.Defaults.Drillers.First(); +// static DrillerDto drillerDto = driller.Adapt(); +// +// static Well well = Data.Defaults.Wells.First(); +// +// public override IEnumerable ValidDtos { get; } = new ScheduleDto[] +// { +// new() { +// Id = 1, +// IdWell = well.Id, +// Driller = drillerDto, +// IdDriller = driller.Id, +// DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), +// DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), +// ShiftStart = new TimeDto(8, 0, 0), +// ShiftEnd = new TimeDto(20, 0, 0), +// }, +// new() { +// Id = 1, +// IdWell = well.Id, +// Driller = drillerDto, +// IdDriller = driller.Id, +// DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), +// DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), +// ShiftStart = new TimeDto(20, 0, 0), +// ShiftEnd = new TimeDto(8, 0, 0), +// } +// }; +// +// public override IEnumerable InvalidDtos { get; } = new ScheduleDto[] +// { +// new() { +// IdWell = well.Id, +// Driller = drillerDto, +// IdDriller = driller.Id, +// DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), +// DrillEnd = new DateTime(2022, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), +// ShiftStart = new TimeDto(8, 0, 0), +// ShiftEnd = new TimeDto(20, 0, 0), +// }, +// new() { +// IdWell = well.Id, +// Driller = drillerDto, +// IdDriller = int.MaxValue - 1, +// DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), +// DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), +// ShiftStart = new TimeDto(8, 0, 0), +// ShiftEnd = new TimeDto(20, 0, 0), +// } +// }; +// +// public override IEnumerable ForbiddenDtos { get; } = new ScheduleDto[] { +// new() { +// IdWell = int.MaxValue - 1, +// Driller = drillerDto, +// IdDriller = driller.Id, +// DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), +// DrillEnd = new DateTime(2022, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), +// ShiftStart = new TimeDto(8, 0, 0), +// ShiftEnd = new TimeDto(20, 0, 0), +// } +// }; +// +// public ScheduleControllerTest(WebAppFactoryFixture factory) +// : base(factory, "api/schedule") +// { +// ExcludeProps.Add(nameof(ScheduleDto.Driller)); +// } +// +// protected override ScheduleDto Convert(Schedule entity) +// { +// var dto = base.Convert(entity); +// dto.DrillStart = entity.DrillStart.ToRemoteDateTime(well.Timezone.Hours); +// dto.DrillEnd = entity.DrillEnd.ToRemoteDateTime(well.Timezone.Hours); +// return dto; +// } +// +// protected override Schedule Convert(ScheduleDto dto) +// { +// var entity = base.Convert(dto); +// entity.DrillStart = dto.DrillStart.FromTimeZoneOffsetHours(well.Timezone.Hours); +// entity.DrillEnd = dto.DrillEnd.FromTimeZoneOffsetHours(well.Timezone.Hours); +// return entity; +// } +// } +// } \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/SlipsStatControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/SlipsStatControllerTest.cs index 57eacadf..70f72369 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/SlipsStatControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/SlipsStatControllerTest.cs @@ -2,77 +2,38 @@ using AsbCloudApp.Data; using AsbCloudApp.Requests; using AsbCloudDb.Model; using AsbCloudWebApi.IntegrationTests.Clients; -using Microsoft.EntityFrameworkCore; using Xunit; namespace AsbCloudWebApi.IntegrationTests.Controllers; public class SlipsStatControllerTest : BaseIntegrationTest { - private static readonly Schedule schedule = new() - { - Id = 0, - IdDriller = Data.Defaults.Drillers[0].Id, - IdWell = Data.Defaults.Wells[0].Id, - ShiftStart = new TimeOnly(8, 0, 0), - ShiftEnd = new TimeOnly(20, 0, 0), - DrillStart = new DateTimeOffset(new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc)), - DrillEnd = new DateTimeOffset(new DateTime(2024, 2, 1, 0, 0, 0, DateTimeKind.Utc)) - }; - - private static readonly DetectedOperation detectedOperation = new() - { - Id = 0, - IdTelemetry = Data.Defaults.Telemetries[0].Id, - IdCategory = WellOperationCategory.IdSlipsTime, - DateStart = new DateTimeOffset(new DateTime(2024, 1, 23, 15, 0, 0, 0, DateTimeKind.Utc)), - DateEnd = new DateTimeOffset(new DateTime(2024, 1, 23, 15, 2, 0, 0, DateTimeKind.Utc)), - ExtraData = new Dictionary - { - { "test", 5 } - } - }; - - private static readonly WellOperation factWellOperation = new() - { - Id = 0, - IdWell = Data.Defaults.Wells[0].Id, - IdWellSectionType = 1, - IdCategory = WellOperationCategory.IdRotor, - IdType = WellOperation.IdOperationTypeFact, - DepthStart = 0, - DepthEnd = 100, - LastUpdateDate = DateTimeOffset.UtcNow, - DateStart = new DateTimeOffset(new DateTime(2024, 1, 15, 15, 0, 0, DateTimeKind.Utc)), - DurationHours = 1 - }; - private readonly ISlipsTimeClient client; public SlipsStatControllerTest(WebAppFactoryFixture factory) : base(factory) { - var schedules = dbContext.Set(); - var detectedOperations = dbContext.Set(); - var wellOperations = dbContext.Set(); - - schedules.RemoveRange(schedules); - detectedOperations.RemoveRange(detectedOperations); - wellOperations.RemoveRange(wellOperations); - dbContext.SaveChanges(); - - schedules.Add(schedule); - detectedOperations.Add(detectedOperation); - wellOperations.Add(factWellOperation); - dbContext.SaveChanges(); - client = factory.GetAuthorizedHttpClient(string.Empty); + + dbContext.CleanupDbSet(); + dbContext.CleanupDbSet(); + dbContext.CleanupDbSet(); } [Fact] public async Task GetAll_returns_success() { //arrange + var well = dbContext.Wells.First(); + var schedule = CreateScheduleAsync(well.Id); + var factWellOperation = CreateFactWellOperation(well.Id); + var detectedOperation = CreateDetectedOperation(well.IdTelemetry!.Value); + + dbContext.Schedule.Add(schedule); + dbContext.WellOperations.Add(factWellOperation); + dbContext.DetectedOperations.Add(detectedOperation); + await dbContext.SaveChangesAsync(); + var request = new OperationStatRequest { DateStartUTC = schedule.DrillStart.DateTime, @@ -83,7 +44,7 @@ public class SlipsStatControllerTest : BaseIntegrationTest var dtoExpected = new SlipsStatDto { - DrillerName = $"{Data.Defaults.Drillers[0].Surname} {Data.Defaults.Drillers[0].Name} {Data.Defaults.Drillers[0].Patronymic}", + DrillerName = $"{schedule.Driller.Surname} {schedule.Driller.Name} {schedule.Driller.Patronymic}", WellCount = 1, SectionCaption = "Пилотный ствол", SlipsCount = 1, @@ -101,4 +62,46 @@ public class SlipsStatControllerTest : BaseIntegrationTest var slipsStat = response.Content.First(); MatchHelper.Match(dtoExpected, slipsStat); } + + private static Schedule CreateScheduleAsync(int idWell) => new() + { + IdWell = idWell, + ShiftStart = new TimeOnly(8, 0, 0), + ShiftEnd = new TimeOnly(20, 0, 0), + DrillStart = new DateTimeOffset(new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc)), + DrillEnd = new DateTimeOffset(new DateTime(2024, 2, 1, 0, 0, 0, DateTimeKind.Utc)), + Driller = new Driller + { + Name = "TestName", + Surname = "TestSurname", + Patronymic = "TestPatronymic" + } + }; + + private static WellOperation CreateFactWellOperation(int idWell) => + new() + { + IdWell = idWell, + IdWellSectionType = 1, + IdCategory = WellOperationCategory.IdRotor, + IdType = WellOperation.IdOperationTypeFact, + DepthStart = 0, + DepthEnd = 100, + LastUpdateDate = DateTimeOffset.UtcNow, + DateStart = new DateTimeOffset(new DateTime(2024, 1, 15, 15, 0, 0, DateTimeKind.Utc)), + DurationHours = 1 + }; + + private static DetectedOperation CreateDetectedOperation(int idTelemetry) => + new() + { + IdTelemetry = idTelemetry, + IdCategory = WellOperationCategory.IdSlipsTime, + DateStart = new DateTimeOffset(new DateTime(2024, 1, 23, 15, 0, 0, 0, DateTimeKind.Utc)), + DateEnd = new DateTimeOffset(new DateTime(2024, 1, 23, 15, 2, 0, 0, DateTimeKind.Utc)), + ExtraData = new Dictionary + { + { "test", 5 } + } + }; } \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs index 459e6b52..830f2e14 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs @@ -5,6 +5,8 @@ using System.Net; using System.Reflection; using AsbCloudApp.Requests; using AsbCloudWebApi.IntegrationTests.Data; +using Mapster; +using Microsoft.EntityFrameworkCore; using Refit; using Xunit; @@ -12,85 +14,76 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers; public class WellOperationControllerTest : BaseIntegrationTest { - private static int idWell = 1; - - private readonly WellOperationDto[] dtos = new WellOperationDto[] - { - new() - { - IdWell = 1, - IdWellSectionType = 1, - WellSectionTypeName = "Пилотный ствол", - IdCategory = 5000, - IdPlan = null, - CategoryName = "Разборка КНБК", - IdParentCategory = 4000, - CategoryInfo = "1", - IdType = 0, - DepthStart = 10.0, - DepthEnd = 20.0, - Day = 0.0, - NptHours = 0.0, - DateStart = new DateTimeOffset(new DateTime(2023, 1, 10), TimeSpan.FromHours(Defaults.Wells[0].Timezone.Hours)), - DurationHours = 1.0, - Comment = "1", - IdUser = 1, - UserName = null, - } - }; - private IWellOperationClient client; - public WellOperationControllerTest(WebAppFactoryFixture factory) - : base(factory) - { - client = factory.GetAuthorizedHttpClient(string.Empty); - } + public WellOperationControllerTest(WebAppFactoryFixture factory) + : base(factory) + { + client = factory.GetAuthorizedHttpClient(string.Empty); - /// - /// Успешное добавление операций (без предварительной очистки данных) - /// - /// - [Fact] - public async Task InsertRange_returns_success() - { - dbContext.CleanupDbSet(); - //act - var response = await client.InsertRangeAsync(idWell, 1, false, dtos); + dbContext.CleanupDbSet(); + } - //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } + /// + /// Успешное добавление операций (без предварительной очистки данных) + /// + /// + [Fact] + public async Task InsertRange_returns_success() + { + //arrange + var well = await dbContext.Wells.FirstAsync(); + var entity = CreateWellOperation(well.Id); + var dtos = new[] { entity.Adapt() }; - /// - /// Успешное добавление операций (с предварительной очисткой данных) - /// - /// - [Fact] - public async Task InsertRangeWithDeleteBefore_returns_success() - { - //act - var response = await client.InsertRangeAsync(idWell, 1, true, dtos); + //act + var response = await client.InsertRangeAsync(well.Id, 1, false, dtos); - //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } - /// - /// Успешное обновление операции - /// - /// - [Fact] - public async Task UpdateAsync_returns_success() - { - //act - var dto = dtos.FirstOrDefault()!; - var response = await client.UpdateAsync(idWell, 1, dto, CancellationToken.None); + /// + /// Успешное добавление операций (с предварительной очисткой данных) + /// + /// + [Fact] + public async Task InsertRangeWithDeleteBefore_returns_success() + { + //arrange + var well = await dbContext.Wells.FirstAsync(); + var entity = CreateWellOperation(well.Id); + var dtos = new[] { entity.Adapt() }; + + //act + var response = await client.InsertRangeAsync(well.Id, 1, true, dtos); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + /// + /// Успешное обновление операции + /// + /// + [Fact] + public async Task UpdateAsync_returns_success() + { + //arrange + var well = await dbContext.Wells.FirstAsync(); + var entity = CreateWellOperation(well.Id); + dbContext.WellOperations.Add(entity); + await dbContext.SaveChangesAsync(); + + var dto = entity.Adapt(); + + //act + var response = await client.UpdateAsync(well.Id, entity.Id, dto, CancellationToken.None); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } - //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - /// /// Получение плановых операций /// @@ -99,8 +92,14 @@ public class WellOperationControllerTest : BaseIntegrationTest public async Task GetPageOperationsPlanAsync_returns_success() { //arrange - dbContext.CleanupDbSet(); - await client.InsertRangeAsync(idWell, WellOperation.IdOperationTypePlan, false, dtos); + var well = await dbContext.Wells.FirstAsync(); + var entity = CreateWellOperation(well.Id); + dbContext.WellOperations.Add(entity); + await dbContext.SaveChangesAsync(); + + var dto = entity.Adapt(); + var timezoneOffset = TimeSpan.FromHours(well.Timezone.Hours); + dto.DateStart = dto.DateStart.ToOffset(timezoneOffset); var request = new WellOperationRequestBase { @@ -108,49 +107,59 @@ public class WellOperationControllerTest : BaseIntegrationTest }; //act - var response = await client.GetPageOperationsPlanAsync(idWell, request, CancellationToken.None); + var response = await client.GetPageOperationsPlanAsync(well.Id, request, CancellationToken.None); //assert Assert.NotNull(response.Content); Assert.Single(response.Content.Items); - var dto = dtos[0]; - var wellOperation = response.Content.Items.First(); + var actualDto = response.Content.Items.First(); - var excludeProps = new[] { nameof(WellOperationDto.Id) }; - MatchHelper.Match(dto, wellOperation, excludeProps); + var excludeProps = new[] + { + nameof(WellOperationDto.LastUpdateDate) + }; + MatchHelper.Match(dto, actualDto, excludeProps); } [Fact] public async Task ImportPlanDefaultExcelFileAsync_returns_success() { //arrange - //TODO: вынести в метод расширения. Сделать когда доберёмся до рефакторинга операций по скважине - var resourceName = Assembly.GetExecutingAssembly() - .GetManifestResourceNames() - .FirstOrDefault(n => n.EndsWith("WellOperationsPlan.xlsx")); - - if (string.IsNullOrWhiteSpace(resourceName)) - throw new ArgumentNullException(nameof(resourceName)); - - var stream = Assembly.GetExecutingAssembly() - .GetManifestResourceStream(resourceName); - - if (stream is null) - throw new ArgumentNullException(nameof(stream)); + var stream = Assembly.GetExecutingAssembly().GetFileCopyStream("WellOperationsPlan.xlsx"); var memoryStream = new MemoryStream(); - stream.CopyTo(memoryStream); + await stream.CopyToAsync(memoryStream); memoryStream.Position = 0; + var well = await dbContext.Wells.FirstAsync(); + //act var streamPart = new StreamPart(memoryStream, "WellOperations.xlsx", "application/octet-stream"); - var response = await client.ImportPlanDefaultExcelFileAsync(idWell, new[] { streamPart }, CancellationToken.None); + var response = await client.ImportPlanDefaultExcelFileAsync(well.Id, new[] { streamPart }, CancellationToken.None); //assert Assert.NotNull(response.Content); Assert.Equal(4, response.Content.Count()); - Assert.True(response.Content.All(w => Math.Abs(w.DateStart.Offset.Hours - Defaults.Wells[0].Timezone.Hours) < 0.1)); + Assert.True(response.Content.All(w => Math.Abs(w.DateStart.Offset.Hours - Defaults.Timezone.Hours) < 0.1)); } + + private static WellOperation CreateWellOperation(int idWell) => + new() + { + IdWell = idWell, + IdWellSectionType = 2, + LastUpdateDate = DateTimeOffset.UtcNow, + IdCategory = 5000, + IdPlan = null, + CategoryInfo = "1", + IdType = 0, + DepthStart = 10.0, + DepthEnd = 20.0, + DateStart = new DateTimeOffset(new DateTime(2023, 1, 10), TimeSpan.FromHours(Defaults.Timezone.Hours)).ToUniversalTime(), + DurationHours = 1.0, + Comment = "1", + IdUser = 1 + }; } \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Repository/DataSaubStatRepositoryTest.cs b/AsbCloudWebApi.IntegrationTests/Repository/DataSaubStatRepositoryTest.cs index f44d32ed..9641dc3c 100644 --- a/AsbCloudWebApi.IntegrationTests/Repository/DataSaubStatRepositoryTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Repository/DataSaubStatRepositoryTest.cs @@ -2,6 +2,7 @@ using AsbCloudApp.Repositories; using AsbCloudDb.Model; using Mapster; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Xunit; @@ -9,157 +10,128 @@ namespace AsbCloudWebApi.IntegrationTests.Repository; public class DataSaubStatRepositoryTest : BaseIntegrationTest { - private static readonly TimeSpan timeSpan = TimeSpan.FromHours(1); + private readonly IDataSaubStatRepository dataSaubStatRepository; + + public DataSaubStatRepositoryTest(WebAppFactoryFixture factory) + : base(factory) + { + dataSaubStatRepository = scope.ServiceProvider.GetRequiredService(); + dbContext.CleanupDbSet(); + } - private static readonly DataSaubStatDto[] statDtos = new DataSaubStatDto[2] - { - new() - { - IdTelemetry = 1, - DateEnd = new DateTimeOffset(2024, 1, 1, 20, 25, 0, timeSpan), - DateStart = new DateTimeOffset(2024, 1, 1, 20, 15, 0, timeSpan), - AxialLoad = 10.0, - AxialLoadLimitMax = 10.0, - AxialLoadSp = 10.0, - BlockSpeedSp = 1000, - DepthEnd = 10.0, - DepthStart = 5.0, - EnabledSubsystems = 1, - Flow = 10.0, - HasOscillation = true, - Id = default, - IdCategory = 2, - IdFeedRegulator = 1, - Pressure = 10.0, - PressureIdle = 10.0, - PressureSp = 10.0, - RotorSpeed = 9.0, - RotorTorque = 9.0, - RotorTorqueSp = 9.0, - RotorTorqueLimitMax = 9.0, - Speed = 10.0 - }, - new() - { - IdTelemetry = 1, - DateEnd = new DateTimeOffset(2024, 2, 2, 20, 25, 0, timeSpan), - DateStart = new DateTimeOffset(2024, 2, 2, 20, 15, 0, timeSpan), - AxialLoad = 10.0, - AxialLoadLimitMax = 10.0, - AxialLoadSp = 10.0, - BlockSpeedSp = 1000, - DepthEnd = 10.0, - DepthStart = 5.0, - EnabledSubsystems = 1, - Flow = 10.0, - HasOscillation = true, - Id = default, - IdCategory = 2, - IdFeedRegulator = 1, - Pressure = 10.0, - PressureIdle = 10.0, - PressureSp = 10.0, - RotorSpeed = 10.0, - RotorTorque = 10.0, - RotorTorqueSp = 10.0, - RotorTorqueLimitMax = 10.0, - Speed = 10.0 - } - }; - private static readonly WellOperationCategory category = new() - { - Id = 2, - IdParent = null, - Name = "Категория 2" - }; + [Fact] + public async Task GetLastDatesAsync_returns_success() + { + //arrange + var telemetry = await dbContext.Telemetries.FirstAsync(); + var timeZoneOffset = TimeSpan.FromHours(telemetry.TimeZone.Hours); + var dataSaubStat = CreateDataSaubStat(telemetry.Id, timeZoneOffset); + dbContext.AddRange(dataSaubStat); + await dbContext.SaveChangesAsync(); - private readonly IDataSaubStatRepository dataSaubStatRepository; + var telemetryIds = dataSaubStat.Select(stat => stat.IdTelemetry).ToArray(); - public DataSaubStatRepositoryTest(WebAppFactoryFixture factory) : base(factory) - { - dataSaubStatRepository = scope.ServiceProvider.GetRequiredService(); - } + //act + var result = await dataSaubStatRepository.GetLastsAsync(telemetryIds, CancellationToken.None); - [Fact] - public async Task GetLastDatesAsync_returns_success() - { - //prepare - dbContext.CleanupDbSet(); - dbContext.CleanupDbSet(); + //assert + var expected = dataSaubStat.Max(stat => stat.DateEnd).ToOffset(timeZoneOffset); + var actual = result.First().DateEnd; + Assert.True((expected - actual).Ticks == 0.0); + } - var dbSetSaubStat = dbContext.Set(); - var dbSetCategories = dbContext.Set(); + [Fact] + public async Task InsertRangeAsync_returns_success() + { + //arrange + var telemetry = await dbContext.Telemetries.FirstAsync(); + var timeZoneOffset = TimeSpan.FromHours(telemetry.TimeZone.Hours); + var dataSaubStat = CreateDataSaubStat(telemetry.Id, timeZoneOffset); + var expectedDtos = dataSaubStat.Select(entity => ConvertToDto(entity, timeZoneOffset)); - var entities = statDtos.Select(stat => ConvertToEntity(stat)); + //act + await dataSaubStatRepository.InsertRangeAsync(expectedDtos, CancellationToken.None); - dbSetCategories.Add(category); - dbContext.SaveChanges(); + //assert + var entities = await dbContext.DataSaubStat.ToArrayAsync(); + var actualDtos = entities.Select(entity => ConvertToDto(entity, timeZoneOffset)); - dbSetSaubStat.AddRange(entities); - dbContext.SaveChanges(); + var excludedProps = new[] + { + nameof(DataSaubStat.Telemetry), + nameof(DataSaubStat.Id), + nameof(DataSaubStat.OperationCategory) + }; - //act - var telemetryIds = statDtos.Select(stat => stat.IdTelemetry).ToArray(); - var result = await dataSaubStatRepository.GetLastsAsync(telemetryIds, CancellationToken.None); + foreach (var actualDto in actualDtos) + { + var statDto = expectedDtos.FirstOrDefault(stat => stat.DateEnd == actualDto.DateEnd && + stat.DateStart == actualDto.DateStart); - var expected = statDtos.Max(stat => stat.DateEnd); - var actual = result.First().DateEnd; + MatchHelper.Match(actualDto, statDto, excludedProps); + } + } - //assert - Assert.True((expected - actual).Ticks == 0.0); - } + private static IEnumerable CreateDataSaubStat(int idTelemetry, TimeSpan timeZoneOffset) => new DataSaubStat[] + { + new() + { + IdTelemetry = idTelemetry, + DateEnd = new DateTimeOffset(2024, 1, 1, 20, 25, 0, timeZoneOffset).ToUniversalTime(), + DateStart = new DateTimeOffset(2024, 1, 1, 20, 15, 0, timeZoneOffset).ToUniversalTime(), + AxialLoad = 10.0, + AxialLoadLimitMax = 10.0, + AxialLoadSp = 10.0, + BlockSpeedSp = 1000, + DepthEnd = 10.0, + DepthStart = 5.0, + EnabledSubsystems = 1, + Flow = 10.0, + HasOscillation = true, + IdCategory = WellOperationCategory.IdSlide, + IdFeedRegulator = 1, + Pressure = 10.0, + PressureIdle = 10.0, + PressureSp = 10.0, + RotorSpeed = 9.0, + RotorTorque = 9.0, + RotorTorqueSp = 9.0, + RotorTorqueLimitMax = 9.0, + Speed = 10.0 + }, + new() + { + IdTelemetry = idTelemetry, + DateEnd = new DateTimeOffset(2024, 2, 2, 20, 25, 0, timeZoneOffset).ToUniversalTime(), + DateStart = new DateTimeOffset(2024, 2, 2, 20, 15, 0, timeZoneOffset).ToUniversalTime(), + AxialLoad = 10.0, + AxialLoadLimitMax = 10.0, + AxialLoadSp = 10.0, + BlockSpeedSp = 1000, + DepthEnd = 10.0, + DepthStart = 5.0, + EnabledSubsystems = 1, + Flow = 10.0, + HasOscillation = true, + IdCategory = WellOperationCategory.IdSlide, + IdFeedRegulator = 1, + Pressure = 10.0, + PressureIdle = 10.0, + PressureSp = 10.0, + RotorSpeed = 10.0, + RotorTorque = 10.0, + RotorTorqueSp = 10.0, + RotorTorqueLimitMax = 10.0, + Speed = 10.0 + } + }; - [Fact] - public async Task InsertRangeAsync_returns_success() - { - //prepare - dbContext.CleanupDbSet(); - var dbSet = dbContext.Set(); - - var dbSetCategories = dbContext.Set(); - dbSetCategories.Add(category); + private static DataSaubStatDto ConvertToDto(DataSaubStat entity, TimeSpan timeZoneOffset) + { + var dto = entity.Adapt(); + dto.DateStart = dto.DateStart.ToOffset(timeZoneOffset); + dto.DateEnd = dto.DateEnd.ToOffset(timeZoneOffset); - dbContext.SaveChanges(); - - //act - var result = await dataSaubStatRepository.InsertRangeAsync(statDtos, CancellationToken.None); - - //assert - Assert.Equal(statDtos.Length, result); - - var statDtosFromDb = dbSet.Select(stat => ConvertToDto(stat, timeSpan)).ToArray(); - - var excludedProps = new[] { - nameof(DataSaubStat.Telemetry), - nameof(DataSaubStat.Id), - nameof(DataSaubStat.OperationCategory) - }; - foreach (var statDtoFromDb in statDtosFromDb) - { - var statDto = statDtos - .Where(stat => stat.DateStart == statDtoFromDb.DateStart) - .Where(stat => stat.DateEnd == statDtoFromDb.DateEnd) - .FirstOrDefault(); - - MatchHelper.Match(statDtoFromDb, statDto, excludedProps); - } - } - - private static DataSaubStat ConvertToEntity(DataSaubStatDto stat) - { - var entity = stat.Adapt(); - entity.DateStart = entity.DateStart.ToUniversalTime(); - entity.DateEnd = entity.DateEnd.ToUniversalTime(); - - return entity; - } - - private static DataSaubStatDto ConvertToDto(DataSaubStat stat, TimeSpan timeSpan) - { - var dto = stat.Adapt(); - dto.DateStart = dto.DateStart.ToOffset(timeSpan); - dto.DateEnd = dto.DateEnd.ToOffset(timeSpan); - - return dto; - } -} + return dto; + } +} \ No newline at end of file From caf2392f45941822c5318eaeee36efe41b1845b9 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: Tue, 12 Mar 2024 07:24:24 +0300 Subject: [PATCH 06/27] fix protobuf registered --- AsbCloudWebApi/ProtobufModel.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/AsbCloudWebApi/ProtobufModel.cs b/AsbCloudWebApi/ProtobufModel.cs index fb3479e2..fc8b9995 100644 --- a/AsbCloudWebApi/ProtobufModel.cs +++ b/AsbCloudWebApi/ProtobufModel.cs @@ -5,13 +5,18 @@ namespace AsbCloudWebApi { public static class ProtobufModel { + private static readonly object SyncRoot = new(); + public static void EnshureRegistered() { - EnshureRegisteredDataSpin(); - EnshureRegisteredDataSaub(); - EnshureRegisteredWITS(); - EnshureRegisteredWirelineRunOutBaseDto(); - EnshureRegisteredWirelineRunOutDto(); + lock (SyncRoot) + { + EnshureRegisteredDataSpin(); + EnshureRegisteredDataSaub(); + EnshureRegisteredWITS(); + EnshureRegisteredWirelineRunOutBaseDto(); + EnshureRegisteredWirelineRunOutDto(); + } } private static void EnshureRegisteredWirelineRunOutBaseDto() From 17454f762c53912696d9bc6279a9fa9300de072f 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: Tue, 12 Mar 2024 10:01:33 +0300 Subject: [PATCH 07/27] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BF=D0=B0=D1=80=D1=81=D0=B5?= =?UTF-8?q?=D1=80=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ParserOptions/WellRelatedParserRequest.cs | 21 +++++++++++++++++ AsbCloudApp/Services/IParserService.cs | 7 +++--- .../Services/Parser/ParserExcelService.cs | 8 +++---- .../Parser/ProcessMapPlanDrillingParser.cs | 1 - .../Parser/ProcessMapPlanParser.cs | 16 +++++++++++-- .../Parser/ProcessMapPlanReamParser.cs | 4 +--- .../Parser/TrajectoryFactManualParser.cs | 6 ++--- .../Trajectory/Parser/TrajectoryParser.cs | 23 +++++++++++++++++++ .../Trajectory/Parser/TrajectoryPlanParser.cs | 6 ++--- 9 files changed, 71 insertions(+), 21 deletions(-) create mode 100644 AsbCloudApp/Requests/ParserOptions/WellRelatedParserRequest.cs create mode 100644 AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs diff --git a/AsbCloudApp/Requests/ParserOptions/WellRelatedParserRequest.cs b/AsbCloudApp/Requests/ParserOptions/WellRelatedParserRequest.cs new file mode 100644 index 00000000..3ffbf4d5 --- /dev/null +++ b/AsbCloudApp/Requests/ParserOptions/WellRelatedParserRequest.cs @@ -0,0 +1,21 @@ +namespace AsbCloudApp.Requests.ParserOptions; + +/// +/// Параметры парсинга +/// +public class WellRelatedParserRequest : IParserOptionsRequest +{ + /// + /// Конструктор + /// + /// Id скважины + public WellRelatedParserRequest(int idWell) + { + IdWell = idWell; + } + + /// + /// Id скважины + /// + public int IdWell { get; } +} \ No newline at end of file diff --git a/AsbCloudApp/Services/IParserService.cs b/AsbCloudApp/Services/IParserService.cs index 8c01af5a..6fa095cd 100644 --- a/AsbCloudApp/Services/IParserService.cs +++ b/AsbCloudApp/Services/IParserService.cs @@ -8,8 +8,10 @@ namespace AsbCloudApp.Services; /// Сервис парсинга /// /// -public interface IParserService : IParserService +/// +public interface IParserService : IParserService where TDto : class, IId + where TOptions : IParserOptionsRequest { /// /// Распарсить файл @@ -17,8 +19,7 @@ public interface IParserService : IParserService /// /// /// - ParserResultDto Parse(Stream file, TOptions options) - where TOptions : IParserOptionsRequest; + ParserResultDto Parse(Stream file, TOptions options); /// /// Получение шаблона для заполнения diff --git a/AsbCloudInfrastructure/Services/Parser/ParserExcelService.cs b/AsbCloudInfrastructure/Services/Parser/ParserExcelService.cs index 661c729f..13c621af 100644 --- a/AsbCloudInfrastructure/Services/Parser/ParserExcelService.cs +++ b/AsbCloudInfrastructure/Services/Parser/ParserExcelService.cs @@ -12,8 +12,9 @@ using Mapster; namespace AsbCloudInfrastructure.Services.Parser; -public abstract class ParserExcelService : IParserService +public abstract class ParserExcelService : IParserService where TDto : class, IValidatableObject, IId + where TOptions : IParserOptionsRequest { protected abstract string SheetName { get; } @@ -22,9 +23,8 @@ public abstract class ParserExcelService : IParserService protected abstract string TemplateFileName { get; } protected abstract IDictionary Cells { get; } - - public virtual ParserResultDto Parse(Stream file, TOptions options) - where TOptions : IParserOptionsRequest + + public virtual ParserResultDto Parse(Stream file, TOptions options) { using var workbook = new XLWorkbook(file); var sheet = workbook.GetWorksheet(SheetName); diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanDrillingParser.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanDrillingParser.cs index c1717db1..f4e829fc 100644 --- a/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanDrillingParser.cs +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanDrillingParser.cs @@ -6,7 +6,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Data.ProcessMaps; using AsbCloudApp.Repositories; using AsbCloudInfrastructure.Services.Parser; -using Microsoft.Extensions.DependencyInjection; namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Parser; diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanParser.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanParser.cs index 1686779b..effe7ef6 100644 --- a/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanParser.cs +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanParser.cs @@ -1,14 +1,26 @@ -using System; +using System.IO; +using AsbCloudApp.Data; using AsbCloudApp.Data.ProcessMaps; +using AsbCloudApp.Requests.ParserOptions; using AsbCloudInfrastructure.Services.Parser; namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Parser; -public abstract class ProcessMapPlanParser : ParserExcelService +public abstract class ProcessMapPlanParser : ParserExcelService where TDto : ProcessMapPlanBaseDto { protected override int HeaderRowsCount => 2; + public override ParserResultDto Parse(Stream file, WellRelatedParserRequest options) + { + var result = base.Parse(file, options); + + foreach (var item in result.Item) + item.Item.IdWell = options.IdWell; + + return result; + } + protected static int? GetIdMode(string? modeName) => modeName?.Trim().ToLower() switch { diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanReamParser.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanReamParser.cs index 20aca5ed..6ca31714 100644 --- a/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanReamParser.cs +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanReamParser.cs @@ -22,14 +22,12 @@ public class ProcessMapPlanReamParser : ProcessMapPlanParser "ProcessMapPlanReamTemplate.xlsx"; private const int ColumnSection = 1; - private const int ColumnMode = 2; - + protected override IDictionary Cells => new Dictionary { { nameof(ProcessMapPlanReamDto.Section), new Cell(ColumnSection, typeof(string)) }, { nameof(ProcessMapPlanReamDto.DepthStart), new Cell(2, typeof(double)) }, { nameof(ProcessMapPlanReamDto.DepthEnd), new Cell(3, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.Repeats), new Cell(4, typeof(double)) }, { nameof(ProcessMapPlanReamDto.SpinUpward), new Cell(5, typeof(double)) }, { nameof(ProcessMapPlanReamDto.SpinUpward), new Cell(6, typeof(double)) }, diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParser.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParser.cs index 5de4e2c5..cf4b7118 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParser.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParser.cs @@ -4,12 +4,10 @@ using AsbCloudInfrastructure.Services.Parser; namespace AsbCloudInfrastructure.Services.Trajectory.Parser; -public class TrajectoryFactManualParser : ParserExcelService +public class TrajectoryFactManualParser : TrajectoryParser { protected override string SheetName => "Фактическая траектория"; - - protected override int HeaderRowsCount => 2; - + protected override string TemplateFileName => "TrajectoryFactManualTemplate.xlsx"; protected override IDictionary Cells => new Dictionary diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs new file mode 100644 index 00000000..ce579fa6 --- /dev/null +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs @@ -0,0 +1,23 @@ +using System.IO; +using AsbCloudApp.Data; +using AsbCloudApp.Data.Trajectory; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudInfrastructure.Services.Parser; + +namespace AsbCloudInfrastructure.Services.Trajectory.Parser; + +public abstract class TrajectoryParser : ParserExcelService + where TDto : TrajectoryGeoDto +{ + protected override int HeaderRowsCount => 2; + + public override ParserResultDto Parse(Stream file, WellRelatedParserRequest options) + { + var result = base.Parse(file, options); + + foreach (var item in result.Item) + item.Item.IdWell = options.IdWell; + + return result; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs index 4c100766..568bfa35 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs @@ -4,12 +4,10 @@ using AsbCloudInfrastructure.Services.Parser; namespace AsbCloudInfrastructure.Services.Trajectory.Parser; -public class TrajectoryPlanParser : ParserExcelService +public class TrajectoryPlanParser : TrajectoryParser { protected override string SheetName => "Плановая траектория"; - - protected override int HeaderRowsCount => 2; - + protected override string TemplateFileName => "TrajectoryPlanTemplate.xlsx"; protected override IDictionary Cells => new Dictionary From 84564c2a38f5e8a52c311e02fb012877223f8490 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: Tue, 12 Mar 2024 10:02:03 +0300 Subject: [PATCH 08/27] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=BB=D0=BB=D0=B5=D1=80=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProcessMapPlanDrillingControllerTest.cs | 16 ++++++++-------- .../ProcessMaps/ProcessMapPlanBaseController.cs | 11 +++++------ .../Trajectory/TrajectoryEditableController.cs | 9 ++++++--- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs index 0ff8bb97..3a5815e9 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs @@ -571,10 +571,10 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest //arrange const string fileName = "ProcessMapPlanDrillingValid.xlsx"; var stream = Assembly.GetExecutingAssembly().GetFileCopyStream(fileName); - - //act var streamPart = new StreamPart(stream, fileName, "application/octet-stream"); - var response = await client.Parse(Defaults.Wells[0].Id, new[] { streamPart }); + + //act + var response = await client.Parse(Defaults.Wells[0].Id, streamPart); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -589,9 +589,8 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest var dtoActual = row.Item; Assert.True(row.IsValid); - - var excludeProps = new[] { nameof(ProcessMapPlanDrillingDto.IdWell) }; - MatchHelper.Match(dto, dtoActual, excludeProps); + + MatchHelper.Match(dto, dtoActual); } [Fact] @@ -600,11 +599,12 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest //arrange const string fileName = "ProcessMapPlanDrillingInvalid.xlsx"; var stream = Assembly.GetExecutingAssembly().GetFileCopyStream(fileName); + var streamPart = new StreamPart(stream, fileName, "application/octet-stream"); //act - var streamPart = new StreamPart(stream, fileName, "application/octet-stream"); - var response = await client.Parse(Defaults.Wells[0].Id, new[] { streamPart }); + var response = await client.Parse(Defaults.Wells[0].Id, streamPart); + //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); var parserResult = response.Content; diff --git a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs index 45da7f11..49513f2c 100644 --- a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs @@ -30,11 +30,11 @@ public abstract class ProcessMapPlanBaseController : ControllerBase { private readonly IChangeLogRepository repository; private readonly IWellService wellService; - private readonly ParserExcelService parserService; + private readonly ParserExcelService parserService; protected ProcessMapPlanBaseController(IChangeLogRepository repository, IWellService wellService, - ParserExcelService parserService) + ParserExcelService parserService) { this.repository = repository; this.wellService = wellService; @@ -213,7 +213,7 @@ public abstract class ProcessMapPlanBaseController : ControllerBase [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task>> Parse(int idWell, - [Required] IFormFile file, + [Required] IFormFile file, CancellationToken token) { await AssertUserHasAccessToWell(idWell, token); @@ -222,9 +222,8 @@ public abstract class ProcessMapPlanBaseController : ControllerBase try { - var dto = parserService.Parse(stream, IParserOptionsRequest.Empty()); - foreach (var item in dto.Item) - item.Item.IdWell = idWell; + var options = new WellRelatedParserRequest(idWell); + var dto = parserService.Parse(stream, options); return Ok(dto); } diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs index 344ed707..814bcdcf 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; using AsbCloudInfrastructure.Services.Parser; +using AsbCloudInfrastructure.Services.Trajectory.Parser; namespace AsbCloudWebApi.Controllers.Trajectory { @@ -25,11 +26,11 @@ namespace AsbCloudWebApi.Controllers.Trajectory public abstract class TrajectoryEditableController : TrajectoryController where TDto : TrajectoryGeoDto { - private readonly ParserExcelService parserService; + private readonly TrajectoryParser parserService; private readonly ITrajectoryEditableRepository trajectoryRepository; protected TrajectoryEditableController(IWellService wellService, - ParserExcelService parserService, + TrajectoryParser parserService, TrajectoryExportService trajectoryExportService, ITrajectoryEditableRepository trajectoryRepository) : base(wellService, trajectoryExportService, trajectoryRepository) @@ -78,7 +79,9 @@ namespace AsbCloudWebApi.Controllers.Trajectory try { - var dto = parserService.Parse(stream, IParserOptionsRequest.Empty()); + var options = new WellRelatedParserRequest(idWell); + var dto = parserService.Parse(stream, options); + return Ok(dto); } catch (FileFormatException ex) From a53f5c3ac343a501f8f79066bf691b84d99a0915 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: Tue, 12 Mar 2024 10:02:16 +0300 Subject: [PATCH 09/27] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D1=82=D0=BA?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Clients/IProcessMapPlanDrillingClient.cs | 2 +- .../Services/Trajectory/TrajectoryParserTest.cs | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/AsbCloudWebApi.IntegrationTests/Clients/IProcessMapPlanDrillingClient.cs b/AsbCloudWebApi.IntegrationTests/Clients/IProcessMapPlanDrillingClient.cs index 2a151573..93ce768b 100644 --- a/AsbCloudWebApi.IntegrationTests/Clients/IProcessMapPlanDrillingClient.cs +++ b/AsbCloudWebApi.IntegrationTests/Clients/IProcessMapPlanDrillingClient.cs @@ -35,5 +35,5 @@ public interface IProcessMapPlanDrillingClient [Multipart] [Post(BaseRoute + "/parse")] - Task>> Parse(int idWell, [AliasAs("files")] IEnumerable streams); + Task>> Parse(int idWell, [AliasAs("file")] StreamPart stream); } diff --git a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs index 8921d982..8b9bd3e9 100644 --- a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs +++ b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs @@ -11,9 +11,11 @@ public class TrajectoryParserTest { private const string UsingTemplateFile = "AsbCloudWebApi.Tests.Services.Trajectory.Templates"; + private readonly WellRelatedParserRequest options = new(1); + private readonly TrajectoryPlanParser trajectoryPlanParser = new(); private readonly TrajectoryFactManualParser trajectoryFactManualParser = new(); - + [Fact] public void Parse_trajectory_plan() { @@ -22,8 +24,8 @@ public class TrajectoryParserTest if (stream is null) Assert.Fail("Файла для импорта не существует"); - - var trajectoryRows = trajectoryPlanParser.Parse(stream, IParserOptionsRequest.Empty()); + + var trajectoryRows = trajectoryPlanParser.Parse(stream, options); Assert.Equal(3, trajectoryRows.Item.Count()); } @@ -37,7 +39,7 @@ public class TrajectoryParserTest if (stream is null) Assert.Fail("Файла для импорта не существует"); - var trajectoryRows = trajectoryFactManualParser.Parse(stream, IParserOptionsRequest.Empty()); + var trajectoryRows = trajectoryFactManualParser.Parse(stream, options); Assert.Equal(4, trajectoryRows.Item.Count()); } From 45f0f50a347b63cab4572a98a706c9aeacc97d79 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Tue, 12 Mar 2024 15:00:14 +0500 Subject: [PATCH 10/27] =?UTF-8?q?Bug=20fix=20+=20=D0=B0=D0=B2=D1=82=D0=BE?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D1=8B=20(=D1=8E=D0=BD=D0=B8=D1=82-?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/WellCompositeOperationService.cs | 10 +- .../WellCompositeOperationServiceTest.cs | 299 ++++++++++++++++++ 2 files changed, 304 insertions(+), 5 deletions(-) create mode 100644 AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs diff --git a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs index 0056b267..3a02b6b2 100644 --- a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs +++ b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs @@ -141,7 +141,7 @@ namespace AsbCloudInfrastructure.Services var categories = wellOperationCategoryRepository.Get(true); var categoriesDict = categories.ToDictionary(s => s.Id, s => s.Name); - var idsWellSectionTypes = WellSectionTypesWithCategories.Select(t => t.IdSectionType); + var idsWellSectionTypes = WellSectionTypesWithCategories.Select(t => t.IdSectionType).Distinct(); var usedCategories = WellSectionTypesWithCategories.Select(c => c.IdCategory).Distinct(); var wellOperationRequest = new WellsOperationRequest() @@ -179,10 +179,10 @@ namespace AsbCloudInfrastructure.Services WellSectionTypeCaption = g.First().WellSectionTypeCaption, }); - var composite = aggreagtedByWell - .OrderBy(o => o.DurationHours) - .ThenByDescending(o => o.DepthStart) - .First(); + var composite = aggreagtedByWell.GroupBy(g => g.DurationHours).Count() == 1 + ? aggreagtedByWell.OrderByDescending(o => o.DepthStart).First() + : aggreagtedByWell.OrderBy(o => o.DepthStart).First(); + composite.IdWell = 0; if (compositeDepth > composite.DepthStart) composite.DepthStart = compositeDepth; diff --git a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs new file mode 100644 index 00000000..eece10e8 --- /dev/null +++ b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs @@ -0,0 +1,299 @@ +using AsbCloudApp.Requests; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; +using AsbCloudInfrastructure.Services.ProcessMaps.Report; +using AsbCloudInfrastructure.Services; +using NSubstitute; +using ProtoBuf.Meta; +using SignalRSwaggerGen.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Xunit; +using AsbCloudApp.Repositories; +using AsbCloudApp.Data; +using AsbCloudApp.Services; + +namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation +{ + public class WellCompositeOperationServiceTest + { + private WellCompositeOperationService service; + + private ICrudRepository wellSectionTypeRepository + = Substitute.For>(); + private IWellOperationCategoryRepository wellOperationCategoryRepository + = Substitute.For(); + private IWellOperationRepository wellOperationRepository + = Substitute.For(); + + + + private readonly static IEnumerable operationCategories = new List() + { + new(){Id = 5096, Name = "Шаблонирование перед спуском"}, + new(){Id = 5008, Name = "Шаблонировка во время бурения"}, + new(){Id = 5013, Name = "Подъем КНБК"}, + new(){Id = 5003, Name = "Бурение ротором"}, + new(){Id = 5036, Name = "Промывка"}, + new(){Id = 5012, Name = "Подъем инструмента"}, + new(){Id = 5083, Name = "Проработка принудительная"}, + }; + + private readonly static IEnumerable sectionTypes = new List() + { + new() {Id = 2, Caption = "Направление", Order = 0}, + new() {Id = 3, Caption = "Кондуктор", Order = 1}, + new() {Id = 31, Caption = "Техническая колонна", Order = 2} + }; + + private readonly static IEnumerable wellOperations1 = new List() + { + new WellOperationDataDto() + { + DepthStart = 50, + DurationHours = 1, + IdCategory = 5096, + IdWell = 55, + IdWellSectionType = 2, + OperationCategoryName = "Шаблонирование перед спуском", + WellSectionTypeCaption = "Направление" + }, + new WellOperationDataDto() + { + DepthStart = 84, + DurationHours = 1, + IdCategory = 5008, + IdWell = 64, + IdWellSectionType = 2, + OperationCategoryName = "Шаблонировка во время бурения", + WellSectionTypeCaption = "Направление" + } + }; + + private readonly static IEnumerable wellOperations2 = new List() + { + new WellOperationDataDto() + { + DepthStart = 10, + DurationHours = 1.5, + IdCategory = 5003, + IdWell = 55, + IdWellSectionType = 2, + OperationCategoryName = "Бурение ротором", + WellSectionTypeCaption = "Направление" + }, + new WellOperationDataDto() + { + DepthStart = 20, + DurationHours = 3.5, + IdCategory = 5003, + IdWell = 64, + IdWellSectionType = 2, + OperationCategoryName = "Бурение ротором", + WellSectionTypeCaption = "Направление" + } + }; + + private readonly static IEnumerable wellOperations3 = new List() + { + new WellOperationDataDto() + { + DepthStart = 1372, + DurationHours = 3, + IdCategory = 5036, + IdWell = 55, + IdWellSectionType = 3, + OperationCategoryName = "Промывка", + WellSectionTypeCaption = "Кондуктор" + }, + new WellOperationDataDto() + { + DepthStart = 1435, + DurationHours = 4, + IdCategory = 5036, + IdWell = 64, + IdWellSectionType = 3, + OperationCategoryName = "Промывка", + WellSectionTypeCaption = "Кондуктор" + } + }; + + private readonly static IEnumerable wellOperations4 = new List() + { + new WellOperationDataDto() + { + DepthStart = 1000, + DurationHours = 10, + IdCategory = 5012, + IdWell = 55, + IdWellSectionType = 31, + OperationCategoryName = "Подъем инструмента", + WellSectionTypeCaption = "Техническая колонна" + }, + new WellOperationDataDto() + { + DepthStart = 500, + DurationHours = 5, + IdCategory = 5083, + IdWell = 55, + IdWellSectionType = 31, + OperationCategoryName = "Проработка принудительная", + WellSectionTypeCaption = "Техническая колонна" + }, + new WellOperationDataDto() + { + DepthStart = 600, + DurationHours = 5, + IdCategory = 5083, + IdWell = 64, + IdWellSectionType = 31, + OperationCategoryName = "Проработка принудительная", + WellSectionTypeCaption = "Техническая колонна" + } + }; + + public WellCompositeOperationServiceTest() + { + + wellSectionTypeRepository.GetAllAsync(Arg.Any()) + .Returns(sectionTypes); + + wellOperationCategoryRepository.Get(Arg.Any()) + .Returns(operationCategories); + + service = new WellCompositeOperationService( + wellSectionTypeRepository, + wellOperationCategoryRepository, + wellOperationRepository); + } + + [Fact] + public async Task GetAsync_return_data() + { + // arrange + wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wellOperations1); + + var idsWell = new List() { 55, 64 }; + + // act + var result = await service.GetAsync(idsWell, CancellationToken.None); + + // assert + var compositeWellOperation = result.SelectMany(o => o.Values.Where(o => o.IdWell == 0)).FirstOrDefault(); + Assert.NotNull(compositeWellOperation); + Assert.Equal(5013, compositeWellOperation.IdCategory); + Assert.Equal(1, compositeWellOperation.DurationHours); + Assert.Equal(84, compositeWellOperation.DepthStart); + + var currentWellOperations = result.SelectMany(o => o.Values.Where(o => o.IdWell != 0)); + var categories = currentWellOperations.Select(o => o.IdCategory).Distinct(); + Assert.NotNull(categories); + Assert.Single(categories); + Assert.Equal(5013, categories.First()); + + var categoryName = currentWellOperations.Select(o => o.OperationCategoryName).First(); + Assert.Equal("Подъем КНБК", categoryName); + } + + + [Fact] + public async Task GetAsync_return_data2() + { + // arrange + wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wellOperations2); + + var idsWell = new List() { 55, 64 }; + + // act + var result = await service.GetAsync(idsWell, CancellationToken.None); + + // assert + var compositeWellOperation = result.SelectMany(o => o.Values.Where(o => o.IdWell == 0)).FirstOrDefault(); + Assert.NotNull(compositeWellOperation); + Assert.Equal(5003, compositeWellOperation.IdCategory); + Assert.Equal(1.5, compositeWellOperation.DurationHours); + Assert.Equal(10, compositeWellOperation.DepthStart); + } + + [Fact] + public async Task GetAsync_return_data3() + { + // arrange + wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wellOperations3); + + var idsWell = new List() { 55, 64 }; + + // act + var result = await service.GetAsync(idsWell, CancellationToken.None); + + // assert + var compositeWellOperation = result.SelectMany(o => o.Values.Where(o => o.IdWell == 0)).FirstOrDefault(); + Assert.NotNull(compositeWellOperation); + Assert.Equal(5036, compositeWellOperation.IdCategory); + Assert.Equal(3, compositeWellOperation.DurationHours); + Assert.Equal(1372, compositeWellOperation.DepthStart); + } + + [Fact] + public async Task GetAsync_return_data4() + { + // arrange + wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wellOperations4); + + var idsWell = new List() { 55, 64 }; + + // act + var result = await service.GetAsync(idsWell, CancellationToken.None); + + // assert + var currentWellOperations = result.SelectMany(o => o.Values.Where(o => o.IdWell != 0)); + var categories = currentWellOperations.Select(o => o.IdCategory).Distinct(); + Assert.NotNull(categories); + Assert.Single(categories); + Assert.Equal(5013, categories.First()); + + var categoryName = currentWellOperations.Select(o => o.OperationCategoryName).First(); + Assert.Equal("Подъем КНБК", categoryName); + + var compositeWellOperation = result.SelectMany(o => o.Values.Where(o => o.IdWell == 0)).FirstOrDefault(); + Assert.NotNull(compositeWellOperation); + Assert.Equal(5013, compositeWellOperation.IdCategory); + Assert.Equal(15, compositeWellOperation.DurationHours); + Assert.Equal(500, compositeWellOperation.DepthStart); + } + + [Fact] + public async Task GetAsync_return_data5() + { + // arrange + var wellOperations = new List(); + wellOperations.AddRange(wellOperations1); + wellOperations.AddRange(wellOperations2); + wellOperations.AddRange(wellOperations3); + wellOperations.AddRange(wellOperations4); + + wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wellOperations); + + var idsWell = new List() { 55, 64 }; + + // act + var result = await service.GetAsync(idsWell, CancellationToken.None); + + // assert + Assert.Equal(4, result.Count()); + + var lastOperation = result.Last(); + var lastOperationComposite = lastOperation[0]; + Assert.Equal(1372, lastOperationComposite.DepthStart); + } + } +} From a03e9bb7f2a5b223a12d580a6e760cc6f8610323 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 12 Mar 2024 17:21:05 +0500 Subject: [PATCH 11/27] WellOperationRequest move copeCtor to WellOperationRequestBase --- AsbCloudApp/Requests/WellOperationRequest.cs | 50 +++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/AsbCloudApp/Requests/WellOperationRequest.cs b/AsbCloudApp/Requests/WellOperationRequest.cs index 89cd6858..3296c4ad 100644 --- a/AsbCloudApp/Requests/WellOperationRequest.cs +++ b/AsbCloudApp/Requests/WellOperationRequest.cs @@ -6,7 +6,7 @@ namespace AsbCloudApp.Requests /// /// параметры для запроса списка операций /// - public class WellOperationRequestBase: RequestBase + public class WellOperationRequestBase : RequestBase { /// /// фильтр по дате начала операции @@ -42,12 +42,40 @@ namespace AsbCloudApp.Requests /// фильтр по списку id конструкций секции /// public IEnumerable? SectionTypeIds { get; set; } + + /// + /// Параметры для запроса списка операций. + /// Базовый конструктор + /// + public WellOperationRequestBase() + { } + + /// + /// Параметры для запроса списка операций. + /// Копирующий конструктор + /// + /// + public WellOperationRequestBase(WellOperationRequestBase request) + { + GeDepth = request.GeDepth; + LeDepth = request.LeDepth; + GeDate = request.GeDate; + LtDate = request.LtDate; + + OperationCategoryIds = request.OperationCategoryIds; + OperationType = request.OperationType; + SectionTypeIds = request.SectionTypeIds; + + Skip = request.Skip; + Take = request.Take; + SortFields = request.SortFields; + } } /// /// Параметры для запроса списка операций (с id скважины) /// - public class WellOperationRequest: WellOperationRequestBase + public class WellOperationRequest : WellOperationRequestBase { /// /// id скважины @@ -57,7 +85,7 @@ namespace AsbCloudApp.Requests /// /// ctor /// - public WellOperationRequest(){} + public WellOperationRequest() { } /// /// копирующий конструктор @@ -65,21 +93,9 @@ namespace AsbCloudApp.Requests /// /// public WellOperationRequest(WellOperationRequestBase request, int idWell) + :base(request) { - this.IdWell = idWell; - - this.GeDepth = request.GeDepth; - this.LeDepth = request.LeDepth; - this.GeDate = request.GeDate; - this.LtDate = request.LtDate; - - this.OperationCategoryIds = request.OperationCategoryIds; - this.OperationType = request.OperationType; - this.SectionTypeIds = request.SectionTypeIds; - - this.Skip= request.Skip; - this.Take= request.Take; - this.SortFields = request.SortFields; + IdWell = idWell; } } From fc2589b5a25205f8537a2072c06964e17f043aa7 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Wed, 13 Mar 2024 09:52:21 +0500 Subject: [PATCH 12/27] =?UTF-8?q?fix=20=D0=BE=D0=BF=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8,=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B0=D1=8F=20=D0=B4=D0=BE=D0=BB=D0=B6=D0=BD=D0=B0=20=D0=B2?= =?UTF-8?q?=D0=BE=D0=B9=D1=82=D0=B8=20=D0=B2=20=D0=BA=D0=BE=D0=BC=D0=BF?= =?UTF-8?q?=D0=BE=D0=B7=D0=B8=D1=82=D0=BD=D1=83=D1=8E=20=D0=BE=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B0=D1=86=D0=B8=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/WellCompositeOperationService.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs index 3a02b6b2..4730352d 100644 --- a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs +++ b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs @@ -179,9 +179,9 @@ namespace AsbCloudInfrastructure.Services WellSectionTypeCaption = g.First().WellSectionTypeCaption, }); - var composite = aggreagtedByWell.GroupBy(g => g.DurationHours).Count() == 1 - ? aggreagtedByWell.OrderByDescending(o => o.DepthStart).First() - : aggreagtedByWell.OrderBy(o => o.DepthStart).First(); + var composite = aggreagtedByWell.OrderBy(o => o.DurationHours). + ThenByDescending(o => o.DepthStart) + .First(); composite.IdWell = 0; if (compositeDepth > composite.DepthStart) From cc69ff832cff229d7a7846591258f5447c86bd42 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 13 Mar 2024 14:21:40 +0500 Subject: [PATCH 13/27] fix appsettings.Tests.json --- AsbCloudWebApi/appsettings.Tests.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AsbCloudWebApi/appsettings.Tests.json b/AsbCloudWebApi/appsettings.Tests.json index d04cf2b1..e8132302 100644 --- a/AsbCloudWebApi/appsettings.Tests.json +++ b/AsbCloudWebApi/appsettings.Tests.json @@ -1,8 +1,8 @@ { "DbConnection": { "Host": "localhost", - "Port": 5433, + "Port": 5432, "Username": "postgres", - "Password": "root" + "Password": "q" } } \ No newline at end of file From fa9095b2f0e9a4e21e83be9a4560dc7923789109 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Wed, 13 Mar 2024 14:30:54 +0500 Subject: [PATCH 14/27] =?UTF-8?q?=D0=9A=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=80=D0=B8=D0=B8=20=D0=BA=20=D0=B0=D0=B2=D1=82?= =?UTF-8?q?=D0=BE=D1=82=D0=B5=D1=81=D1=82=D0=B0=D0=BC=20+=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B0=20=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D0=BE=D0=B4=D0=B0=20BuildQuery?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repository/WellOperationRepository.cs | 61 ++++++++++++++----- .../WellCompositeOperationServiceTest.cs | 48 +++++++++++++-- 2 files changed, 88 insertions(+), 21 deletions(-) diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index be039c86..aa0d28ce 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -209,24 +209,10 @@ public class WellOperationRepository : IWellOperationRepository WellsOperationRequest request, CancellationToken token) { - var query = db.WellOperations - .Where(o => request.IdsWell.Contains(o.IdWell)) - .Where(o => request.IdType == o.IdType) - .Where(o => request.SectionTypeIds != null ? request.SectionTypeIds.Contains(o.IdWellSectionType) : true) - .Where(o => request.OperationCategoryIds != null ? request.OperationCategoryIds.Contains(o.IdCategory) : true) - .Select(o => new WellOperationDataDto(){ - DepthStart = o.DepthStart, - DurationHours = o.DurationHours, - IdCategory = o.IdCategory, - IdWell = o.IdWell, - IdWellSectionType = o.IdWellSectionType, - OperationCategoryName = o.OperationCategory.Name, - WellSectionTypeCaption = o.WellSectionType.Caption, - }) - .AsNoTracking(); + var query = BuildQuery(request) + .AsNoTracking(); var dtos = await query.ToArrayAsync(token); - return dtos; } @@ -497,6 +483,49 @@ public class WellOperationRepository : IWellOperationRepository return dtos.AsNoTracking(); } + /// + /// Получение данных по запросу + /// + /// + /// + /// + private IQueryable BuildQuery(WellsOperationRequest request) + { + var query = db.WellOperations + .Where(o => request.IdsWell.Contains(o.IdWell)) + .Where(o => request.IdType == o.IdType); + + if (request.SectionTypeIds?.Any() == true) + query = query.Where(o => request.SectionTypeIds.Contains(o.IdWellSectionType)); + + if (request.OperationCategoryIds?.Any() == true) + query = query.Where(o => request.OperationCategoryIds.Contains(o.IdCategory)); + + var dtos = query.Select(o => new WellOperationDataDto + { + DepthStart = o.DepthStart, + DurationHours = o.DurationHours, + IdCategory = o.IdCategory, + IdWell = o.IdWell, + IdWellSectionType = o.IdWellSectionType, + OperationCategoryName = o.OperationCategory.Name, + WellSectionTypeCaption = o.WellSectionType.Caption, + }); + + if (request.SortFields?.Any() == true) + { + dtos = dtos.SortBy(request.SortFields); + } + + if (request.Skip.HasValue) + dtos = dtos.Skip(request.Skip.Value); + + if (request.Take.HasValue) + dtos = dtos.Take(request.Take.Value); + + return dtos.AsNoTracking(); + } + private WellOperationDto Convert(WellOperationDto dto) { var timezone = wellService.GetTimezone(dto.IdWell); diff --git a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs index eece10e8..d4659d8a 100644 --- a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs @@ -171,8 +171,14 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation wellOperationRepository); } + /// + /// На вход подаются 2 операции с одинаковыми секциями (id = 2), но разными категориями (ids = 5096, 5008) и ключами скважин (ids = 55, 64) + /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная + /// Операция должна иметь категорию 5013 для всех трех скважин + /// + /// [Fact] - public async Task GetAsync_return_data() + public async Task GetAsync_return_composite_and_others_with_category_5013() { // arrange wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) @@ -200,9 +206,14 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation Assert.Equal("Подъем КНБК", categoryName); } - + /// + /// На вход подаются 2 операции с одинаковыми секциями (id = 2) и категориями (id = 5003), но разными ключами скважин (ids = 55, 64) + /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная + /// Операция композитной скважины должна содержать данные той операции, которая содержит минимальный duration_hours + /// + /// [Fact] - public async Task GetAsync_return_data2() + public async Task GetAsync_return_composite_with_minimum_depth_start() { // arrange wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) @@ -221,6 +232,12 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation Assert.Equal(10, compositeWellOperation.DepthStart); } + /// + /// На вход подаются 2 операции с одинаковыми секциями (id = 3) и категориями (id = 5036), но разными ключами скважин (ids = 55, 64) + /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная + /// Операция композитной скважины должна содержать данные той операции, которая содержит минимальный duration_hours + /// + /// [Fact] public async Task GetAsync_return_data3() { @@ -241,6 +258,16 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation Assert.Equal(1372, compositeWellOperation.DepthStart); } + /// + /// На вход подаются 3 операции с одинаковыми секциями (id = 31), но разными категориями (ids = 5012, 5083) и ключами скважин (ids = 55, 64) + /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная + /// Операция композитной скважины должна содержать: + /// данные той операции, которая содержит минимальный duration_hours + /// категорию с ключом 5013 + /// Операции по скважине с ключом 55 должны объединиться в одну, + /// при этом их длительность складывается, а depth_start берется минимальный из двух + /// + /// [Fact] public async Task GetAsync_return_data4() { @@ -260,16 +287,27 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation Assert.Single(categories); Assert.Equal(5013, categories.First()); + var currentOperationByWell55 = currentWellOperations.Where(o => o.IdWell == 55).FirstOrDefault(); + Assert.NotNull(currentOperationByWell55); + Assert.Equal(15, currentOperationByWell55.DurationHours); + Assert.Equal(500, currentOperationByWell55.DepthStart); + var categoryName = currentWellOperations.Select(o => o.OperationCategoryName).First(); Assert.Equal("Подъем КНБК", categoryName); var compositeWellOperation = result.SelectMany(o => o.Values.Where(o => o.IdWell == 0)).FirstOrDefault(); Assert.NotNull(compositeWellOperation); Assert.Equal(5013, compositeWellOperation.IdCategory); - Assert.Equal(15, compositeWellOperation.DurationHours); - Assert.Equal(500, compositeWellOperation.DepthStart); + Assert.Equal(5, compositeWellOperation.DurationHours); + Assert.Equal(600, compositeWellOperation.DepthStart); } + /// + /// На вход подаются список разных операций с разными ключами скважин (ids = 55, 64) + /// Метод возвращает список из 4-х операций в разрезе 3-х скважин: 2 текущие скважины и одна композитная + /// Операция композитной скважины должна содержать глубину забоя = 1372 + /// + /// [Fact] public async Task GetAsync_return_data5() { From a91fc4f213f904e75ef36efc342db0289af17e7a Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 13 Mar 2024 16:04:49 +0500 Subject: [PATCH 15/27] =?UTF-8?q?WellsOperationRequest.IdType=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=20=D0=BD=D0=B0=20WellOpera?= =?UTF-8?q?tionRequestBase.OperationType.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=82=D1=83=D0=B4=D1=83=D1=88=D0=BA?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Requests/WellOperationRequest.cs | 5 ----- AsbCloudInfrastructure/Repository/WellOperationRepository.cs | 5 +++-- .../Services/WellCompositeOperationService.cs | 5 ++--- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/AsbCloudApp/Requests/WellOperationRequest.cs b/AsbCloudApp/Requests/WellOperationRequest.cs index 3296c4ad..1d190018 100644 --- a/AsbCloudApp/Requests/WellOperationRequest.cs +++ b/AsbCloudApp/Requests/WellOperationRequest.cs @@ -108,10 +108,5 @@ namespace AsbCloudApp.Requests /// ids скважин /// public IEnumerable IdsWell { get; set; } = null!; - - /// - /// Тип 0 = План или 1 = Факт - /// - public int IdType { get; set; } } } diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index aa0d28ce..329d2502 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -396,7 +396,6 @@ public class WellOperationRepository : IWellOperationRepository .Include(s => s.OperationCategory) .Where(o => o.IdWell == request.IdWell); - if (request.OperationType.HasValue) query = query.Where(e => e.IdType == request.OperationType.Value); @@ -431,6 +430,7 @@ public class WellOperationRepository : IWellOperationRepository .Where(subOp => subOp.IdType == 1) .Where(subOp => WellOperationCategory.NonProductiveTimeSubIds.Contains(subOp.IdCategory)); + // TODO: Вынести query.Select из метода BuildQuery var dtos = query.Select(o => new WellOperationDto { Id = o.Id, @@ -493,7 +493,7 @@ public class WellOperationRepository : IWellOperationRepository { var query = db.WellOperations .Where(o => request.IdsWell.Contains(o.IdWell)) - .Where(o => request.IdType == o.IdType); + .Where(o => request.OperationType == o.IdType); if (request.SectionTypeIds?.Any() == true) query = query.Where(o => request.SectionTypeIds.Contains(o.IdWellSectionType)); @@ -501,6 +501,7 @@ public class WellOperationRepository : IWellOperationRepository if (request.OperationCategoryIds?.Any() == true) query = query.Where(o => request.OperationCategoryIds.Contains(o.IdCategory)); + // TODO: Вынести query.Select из метода BuildQuery var dtos = query.Select(o => new WellOperationDataDto { DepthStart = o.DepthStart, diff --git a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs index 4730352d..6ba97ea0 100644 --- a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs +++ b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs @@ -149,7 +149,7 @@ namespace AsbCloudInfrastructure.Services IdsWell = idsWells, OperationCategoryIds = usedCategories, SectionTypeIds = idsWellSectionTypes, - IdType = WellOperation.IdOperationTypeFact + OperationType = WellOperation.IdOperationTypeFact }; var operations = await wellOperationRepository.GetAsync(wellOperationRequest, token); @@ -189,7 +189,6 @@ namespace AsbCloudInfrastructure.Services compositeDepth = composite.DepthStart; - var resultItem = aggreagtedByWell.ToDictionary(o => o.IdWell); resultItem.Add(0, composite); @@ -198,7 +197,7 @@ namespace AsbCloudInfrastructure.Services return wellOperationsWithComposite; } - private WellOperationDataDto UpdateIdWellSectionAndIdCategory( + private static WellOperationDataDto UpdateIdWellSectionAndIdCategory( WellOperationDataDto dto, Dictionary sectionTypes, Dictionary operationCategories) From 5b3664d3e02089fdeb8c7ad11dc8b79084b521cb 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, 13 Mar 2024 14:34:51 +0300 Subject: [PATCH 16/27] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D1=83=D0=B4?= =?UTF-8?q?=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=91=D0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WebAppFactoryFixture.cs | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs b/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs index b990295b..b3edf988 100644 --- a/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs +++ b/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs @@ -12,8 +12,7 @@ using AsbCloudWebApi.IntegrationTests.Converters; namespace AsbCloudWebApi.IntegrationTests; -public class WebAppFactoryFixture : WebApplicationFactory, - IDisposable +public class WebAppFactoryFixture : WebApplicationFactory { private static readonly JsonSerializerOptions JsonSerializerOptions = new() { @@ -24,15 +23,20 @@ public class WebAppFactoryFixture : WebApplicationFactory, private static readonly RefitSettings RefitSettings = new(new SystemTextJsonContentSerializer(JsonSerializerOptions)); - protected override void ConfigureWebHost(IWebHostBuilder builder) + private readonly string connectionString; + + public WebAppFactoryFixture() { var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.Tests.json") .Build(); - - var dbConnection = configuration.GetSection("DbConnection").Get(); - var connectionString = dbConnection?.GetConnectionString(); - + + var dbConnection = configuration.GetSection("DbConnection").Get()!; + connectionString = dbConnection.GetConnectionString(); + } + + protected override void ConfigureWebHost(IWebHostBuilder builder) + { builder.ConfigureServices(services => { var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions)); @@ -55,13 +59,14 @@ public class WebAppFactoryFixture : WebApplicationFactory, }); } - public new void Dispose() + public override async ValueTask DisposeAsync() { - using var scope = Services.CreateScope(); - var scopedServices = scope.ServiceProvider; - var dbContext = scopedServices.GetRequiredService(); + var dbContext = new AsbCloudDbContext( + new DbContextOptionsBuilder() + .UseNpgsql(connectionString) + .Options); - dbContext.Database.EnsureDeleted(); + await dbContext.Database.EnsureDeletedAsync(); } public T GetAuthorizedHttpClient(string uriSuffix) From 8f29a9178b91727e3585fc021c5fb0fb15df6008 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, 13 Mar 2024 14:40:56 +0300 Subject: [PATCH 17/27] fix after merge --- .../ProcessMapPlanDrillingControllerTest.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs index b5df18bb..c5335ae0 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs @@ -573,9 +573,10 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest const string fileName = "ProcessMapPlanDrillingValid.xlsx"; var stream = Assembly.GetExecutingAssembly().GetFileCopyStream(fileName); - //act var streamPart = new StreamPart(stream, fileName, "application/octet-stream"); - var response = await client.Parse(IdWell, new[] { streamPart }); + + //act + var response = await client.Parse(IdWell, streamPart); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -602,9 +603,10 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest const string fileName = "ProcessMapPlanDrillingInvalid.xlsx"; var stream = Assembly.GetExecutingAssembly().GetFileCopyStream(fileName); - //act var streamPart = new StreamPart(stream, fileName, "application/octet-stream"); - var response = await client.Parse(IdWell, new[] { streamPart }); + + //act + var response = await client.Parse(IdWell, streamPart); Assert.Equal(HttpStatusCode.OK, response.StatusCode); From 0b9fd490395ccd772d732a60e839c4936e741d9c 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, 13 Mar 2024 14:49:28 +0300 Subject: [PATCH 18/27] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Удалён лишний тест. В данном тесте никогда не возникнет BadRequest. Если идентификатор скважины не валиден у нас возникнет Forbidden. 2. Сделал коллекцию прав потокобезопасной, чтобы не возникало состояние RaiseCondition --- .../ProcessMapPlanDrillingControllerTest.cs | 16 +--------------- AsbCloudWebApi/PermissionAttribute.cs | 5 ++--- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs index c5335ae0..6f21bd0b 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs @@ -150,21 +150,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest //assert Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } - - [Fact] - public async Task InsertRange_returns_BadRequest_for_IdWell() - { - //arrange - var badDto = dto.Adapt(); - badDto.IdWell = int.MaxValue; - - //act - var response = await client.InsertRange(dto.IdWell, new[] { badDto }); - - //assert - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - } - + [Fact] public async Task ClearAndInsertRange_returns_success() { diff --git a/AsbCloudWebApi/PermissionAttribute.cs b/AsbCloudWebApi/PermissionAttribute.cs index 1249b531..775617a1 100644 --- a/AsbCloudWebApi/PermissionAttribute.cs +++ b/AsbCloudWebApi/PermissionAttribute.cs @@ -1,13 +1,12 @@ using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; +using System.Collections.Concurrent; namespace AsbCloudWebApi { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class PermissionAttribute : Attribute { - public static SortedSet Registered { get; } = new SortedSet(); + public static ConcurrentBag Registered { get; } = new(); public string Name { get; set; } = null!; From af2d180d992d1823c40625f86fc0f458e8e7361d 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: Thu, 14 Mar 2024 08:00:14 +0300 Subject: [PATCH 19/27] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D1=80=D1=8B=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Templates/ITemplateParameters.cs | 14 ++++++++ .../ProcessMapPlanDrillingTemplate.cs | 35 +++++++++++++++++++ .../ProcessMapPlanReamTemplate.cs | 29 +++++++++++++++ .../TrajectoryFactManualTemplate.cs | 23 ++++++++++++ .../TrajectoryFactNnbTemplate.cs | 23 ++++++++++++ .../TrajectoryPlanTemplate.cs | 21 +++++++++++ 6 files changed, 145 insertions(+) create mode 100644 AsbCloudInfrastructure/Services/ExcelServices/Templates/ITemplateParameters.cs create mode 100644 AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanDrillingTemplate.cs create mode 100644 AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanReamTemplate.cs create mode 100644 AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryFactManualTemplate.cs create mode 100644 AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryFactNnbTemplate.cs create mode 100644 AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryPlanTemplate.cs diff --git a/AsbCloudInfrastructure/Services/ExcelServices/Templates/ITemplateParameters.cs b/AsbCloudInfrastructure/Services/ExcelServices/Templates/ITemplateParameters.cs new file mode 100644 index 00000000..eeb1076c --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/Templates/ITemplateParameters.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace AsbCloudInfrastructure.Services.ExcelServices.Templates; + +public interface ITemplateParameters +{ + string SheetName { get; } + + int HeaderRowsCount { get; } + + string FileName { get; } + + IDictionary Cells { get; } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanDrillingTemplate.cs b/AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanDrillingTemplate.cs new file mode 100644 index 00000000..dff24dcf --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanDrillingTemplate.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using AsbCloudApp.Data.ProcessMaps; + +namespace AsbCloudInfrastructure.Services.ExcelServices.Templates.ProcessMapPlanTemplates; + +public class ProcessMapPlanDrillingTemplate : ITemplateParameters +{ + public string SheetName => "План"; + + public int HeaderRowsCount => 2; + + public string FileName => "ProcessMapPlanDrillingTemplate.xlsx"; + + public IDictionary Cells => new Dictionary + { + { nameof(ProcessMapPlanDrillingDto.Section), new Cell(1, typeof(string)) }, + { nameof(ProcessMapPlanDrillingDto.Mode), new Cell(2, typeof(string)) }, + { nameof(ProcessMapPlanDrillingDto.DepthStart), new Cell(3, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.DepthEnd), new Cell(4, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.DeltaPressurePlan), new Cell(5, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.DeltaPressureLimitMax), new Cell(6, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.AxialLoadPlan), new Cell(7, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.AxialLoadLimitMax), new Cell(8, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.TopDriveTorquePlan), new Cell(9, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.TopDriveTorqueLimitMax), new Cell(10, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.TopDriveSpeedPlan), new Cell(11, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.TopDriveSpeedLimitMax), new Cell(12, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.FlowPlan), new Cell(13, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.FlowLimitMax), new Cell(14, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.RopPlan), new Cell(15, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.UsageSaub), new Cell(16, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.UsageSpin), new Cell(17, typeof(double)) }, + { nameof(ProcessMapPlanDrillingDto.Comment), new Cell(18, typeof(string)) } + }; +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanReamTemplate.cs b/AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanReamTemplate.cs new file mode 100644 index 00000000..4df80a7e --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanReamTemplate.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using AsbCloudApp.Data.ProcessMaps; + +namespace AsbCloudInfrastructure.Services.ExcelServices.Templates.ProcessMapPlanTemplates; + +public class ProcessMapPlanReamTemplate : ITemplateParameters +{ + public string SheetName => "План"; + + public int HeaderRowsCount => 2; + + public string FileName => "ProcessMapPlanReamTemplate.xlsx"; + + public IDictionary Cells => new Dictionary + { + { nameof(ProcessMapPlanReamDto.Section), new Cell(1, typeof(string)) }, + { nameof(ProcessMapPlanReamDto.DepthStart), new Cell(2, typeof(double)) }, + { nameof(ProcessMapPlanReamDto.DepthEnd), new Cell(3, typeof(double)) }, + { nameof(ProcessMapPlanReamDto.Repeats), new Cell(4, typeof(double)) }, + { nameof(ProcessMapPlanReamDto.SpinUpward), new Cell(5, typeof(double)) }, + { nameof(ProcessMapPlanReamDto.SpinDownward), new Cell(6, typeof(double)) }, + { nameof(ProcessMapPlanReamDto.SpeedUpward), new Cell(7, typeof(double)) }, + { nameof(ProcessMapPlanReamDto.SpeedDownward), new Cell(8, typeof(double)) }, + { nameof(ProcessMapPlanReamDto.SetpointDrag), new Cell(9, typeof(double)) }, + { nameof(ProcessMapPlanReamDto.SetpointTight), new Cell(10, typeof(double)) }, + { nameof(ProcessMapPlanReamDto.Pressure), new Cell(11, typeof(double)) }, + { nameof(ProcessMapPlanReamDto.Torque), new Cell(12, typeof(double)) }, + }; +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryFactManualTemplate.cs b/AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryFactManualTemplate.cs new file mode 100644 index 00000000..8e604e1e --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryFactManualTemplate.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using AsbCloudApp.Data.Trajectory; + +namespace AsbCloudInfrastructure.Services.ExcelServices.Templates.TrajectoryTemplates; + +public class TrajectoryFactManualTemplate : ITemplateParameters +{ + public string SheetName => "Фактическая траектория"; + + public int HeaderRowsCount => 2; + + public string FileName => "TrajectoryFactManualTemplate.xlsx"; + + public IDictionary Cells => new Dictionary + { + { nameof(TrajectoryGeoFactDto.WellboreDepth), new Cell(1, typeof(double)) }, + { nameof(TrajectoryGeoFactDto.ZenithAngle), new Cell(2, typeof(double)) }, + { nameof(TrajectoryGeoFactDto.AzimuthGeo), new Cell(3, typeof(double)) }, + { nameof(TrajectoryGeoFactDto.AzimuthMagnetic), new Cell(4, typeof(double)) }, + { nameof(TrajectoryGeoFactDto.VerticalDepth), new Cell(5, typeof(double)) }, + { nameof(TrajectoryGeoFactDto.Comment), new Cell(6, typeof(string)) } + }; +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryFactNnbTemplate.cs b/AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryFactNnbTemplate.cs new file mode 100644 index 00000000..87489d7c --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryFactNnbTemplate.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using AsbCloudApp.Data.Trajectory; + +namespace AsbCloudInfrastructure.Services.ExcelServices.Templates.TrajectoryTemplates; + +public class TrajectoryFactNnbTemplate : ITemplateParameters +{ + public string SheetName => "Фактическая ннб-траектория"; + + public int HeaderRowsCount => 2; + + public string FileName => "TrajectoryFactNnbTemplate.xlsx"; + + public IDictionary Cells => new Dictionary + { + { nameof(TrajectoryGeoFactDto.WellboreDepth), new Cell(1, typeof(double)) }, + { nameof(TrajectoryGeoFactDto.ZenithAngle), new Cell(2, typeof(double)) }, + { nameof(TrajectoryGeoFactDto.AzimuthGeo), new Cell(3, typeof(double)) }, + { nameof(TrajectoryGeoFactDto.AzimuthMagnetic), new Cell(4, typeof(double)) }, + { nameof(TrajectoryGeoFactDto.VerticalDepth), new Cell(5, typeof(double)) }, + { nameof(TrajectoryGeoFactDto.Comment), new Cell(6, typeof(string)) } + }; +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryPlanTemplate.cs b/AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryPlanTemplate.cs new file mode 100644 index 00000000..d98c1d89 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/Templates/TrajectoryTemplates/TrajectoryPlanTemplate.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using AsbCloudApp.Data.Trajectory; + +namespace AsbCloudInfrastructure.Services.ExcelServices.Templates.TrajectoryTemplates; + +public class TrajectoryPlanTemplate : ITemplateParameters +{ + public string SheetName => "Плановая траектория"; + public int HeaderRowsCount => 2; + public string FileName => "TrajectoryPlanTemplate.xlsx"; + public IDictionary Cells => new Dictionary + { + { nameof(TrajectoryGeoPlanDto.WellboreDepth), new Cell(1, typeof(double)) }, + { nameof(TrajectoryGeoPlanDto.ZenithAngle), new Cell(2, typeof(double)) }, + { nameof(TrajectoryGeoPlanDto.AzimuthGeo), new Cell(3, typeof(double)) }, + { nameof(TrajectoryGeoPlanDto.AzimuthMagnetic), new Cell(4, typeof(double)) }, + { nameof(TrajectoryGeoPlanDto.VerticalDepth), new Cell(5, typeof(double)) }, + { nameof(TrajectoryGeoPlanDto.Radius), new Cell(6, typeof(double)) }, + { nameof(TrajectoryGeoPlanDto.Comment), new Cell(7, typeof(string)) } + }; +} \ No newline at end of file From a08c9c0d8b10b01ee901109c5190fd0f2c1b5629 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: Thu, 14 Mar 2024 08:03:57 +0300 Subject: [PATCH 20/27] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BF=D0=B0=D1=80=D1=81=D0=B5?= =?UTF-8?q?=D1=80=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Services/IParserService.cs | 9 +--- .../{Parser => ExcelServices}/Cell.cs | 2 +- .../ParserExcelService.cs | 30 ++++++------ .../Parser/ProcessMapPlanDrillingParser.cs | 46 +++++-------------- .../Parser/ProcessMapPlanParser.cs | 13 ++++-- .../Parser/ProcessMapPlanReamParser.cs | 33 +++---------- .../Parser/TrajectoryFactManualParser.cs | 20 ++------ .../Trajectory/Parser/TrajectoryParser.cs | 4 +- .../Trajectory/Parser/TrajectoryPlanParser.cs | 21 ++------- .../Trajectory/TrajectoryParserTest.cs | 1 - 10 files changed, 54 insertions(+), 125 deletions(-) rename AsbCloudInfrastructure/Services/{Parser => ExcelServices}/Cell.cs (97%) rename AsbCloudInfrastructure/Services/{Parser => ExcelServices}/ParserExcelService.cs (77%) diff --git a/AsbCloudApp/Services/IParserService.cs b/AsbCloudApp/Services/IParserService.cs index 6fa095cd..89212ba7 100644 --- a/AsbCloudApp/Services/IParserService.cs +++ b/AsbCloudApp/Services/IParserService.cs @@ -9,7 +9,7 @@ namespace AsbCloudApp.Services; /// /// /// -public interface IParserService : IParserService +public interface IParserService where TDto : class, IId where TOptions : IParserOptionsRequest { @@ -26,11 +26,4 @@ public interface IParserService : IParserService /// /// Stream GetTemplateFile(); -} - -/// -/// Сервис парсинга(интерфейс маркер) -/// -public interface IParserService -{ } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Parser/Cell.cs b/AsbCloudInfrastructure/Services/ExcelServices/Cell.cs similarity index 97% rename from AsbCloudInfrastructure/Services/Parser/Cell.cs rename to AsbCloudInfrastructure/Services/ExcelServices/Cell.cs index 381ca57b..a18fb167 100644 --- a/AsbCloudInfrastructure/Services/Parser/Cell.cs +++ b/AsbCloudInfrastructure/Services/ExcelServices/Cell.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; using ClosedXML.Excel; -namespace AsbCloudInfrastructure.Services.Parser; +namespace AsbCloudInfrastructure.Services.ExcelServices; public class Cell { diff --git a/AsbCloudInfrastructure/Services/Parser/ParserExcelService.cs b/AsbCloudInfrastructure/Services/ExcelServices/ParserExcelService.cs similarity index 77% rename from AsbCloudInfrastructure/Services/Parser/ParserExcelService.cs rename to AsbCloudInfrastructure/Services/ExcelServices/ParserExcelService.cs index 13c621af..64e0259c 100644 --- a/AsbCloudInfrastructure/Services/Parser/ParserExcelService.cs +++ b/AsbCloudInfrastructure/Services/ExcelServices/ParserExcelService.cs @@ -7,39 +7,34 @@ using System.Reflection; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; using AsbCloudApp.Services; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; using ClosedXML.Excel; using Mapster; -namespace AsbCloudInfrastructure.Services.Parser; +namespace AsbCloudInfrastructure.Services.ExcelServices; public abstract class ParserExcelService : IParserService where TDto : class, IValidatableObject, IId where TOptions : IParserOptionsRequest { - protected abstract string SheetName { get; } + protected abstract ITemplateParameters TemplateParameters { get; } - protected virtual int HeaderRowsCount => 0; - - protected abstract string TemplateFileName { get; } - - protected abstract IDictionary Cells { get; } - public virtual ParserResultDto Parse(Stream file, TOptions options) { using var workbook = new XLWorkbook(file); - var sheet = workbook.GetWorksheet(SheetName); + var sheet = workbook.GetWorksheet(TemplateParameters.SheetName); var dtos = ParseExcelSheet(sheet); return dtos; } public virtual Stream GetTemplateFile() => - Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateFileName) - ?? throw new ArgumentNullException($"Файл '{TemplateFileName}' не найден"); + Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateParameters.FileName) + ?? throw new ArgumentNullException($"Файл '{TemplateParameters.FileName}' не найден"); protected virtual IDictionary ParseRow(IXLRow xlRow) { - var cells = Cells.ToDictionary(x => x.Key, x => + var cells = TemplateParameters.Cells.ToDictionary(x => x.Key, x => { var columnNumber = x.Value.ColumnNumber; var xlCell = xlRow.Cell(columnNumber); @@ -72,7 +67,7 @@ public abstract class ParserExcelService : IParserService x.Key, x => x.Value.ColumnNumber); + var columnsDict = TemplateParameters.Cells.ToDictionary(x => x.Key, x => x.Value.ColumnNumber); var invalidDto = new ValidationResultDto { @@ -84,7 +79,10 @@ public abstract class ParserExcelService : IParserService : IParserService ParseExcelSheet(IXLWorksheet sheet) { - var count = sheet.RowsUsed().Count() - HeaderRowsCount; + var count = sheet.RowsUsed().Count() - TemplateParameters.HeaderRowsCount; if (count <= 0) return new ParserResultDto(); @@ -105,7 +103,7 @@ public abstract class ParserExcelService : IParserService { - private readonly IEnumerable sections; - public ProcessMapPlanDrillingParser(IWellOperationRepository wellOperationRepository) + : base(wellOperationRepository) { - sections = wellOperationRepository.GetSectionTypes(); } - - protected override string SheetName => "План"; - protected override string TemplateFileName => "ProcessMapPlanDrillingTemplate.xlsx"; - private const int ColumnSection = 1; - private const int ColumnMode = 2; - - protected override IDictionary Cells => new Dictionary - { - { nameof(ProcessMapPlanDrillingDto.Section), new Cell(ColumnSection, typeof(string)) }, - { nameof(ProcessMapPlanDrillingDto.Mode), new Cell(ColumnMode, typeof(string)) }, - { nameof(ProcessMapPlanDrillingDto.DepthStart), new Cell(3, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.DepthEnd), new Cell(4, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.DeltaPressurePlan), new Cell(5, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.DeltaPressureLimitMax), new Cell(6, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.AxialLoadPlan), new Cell(7, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.AxialLoadLimitMax), new Cell(8, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.TopDriveTorquePlan), new Cell(9, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.TopDriveTorqueLimitMax), new Cell(10, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.TopDriveSpeedPlan), new Cell(11, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.TopDriveSpeedLimitMax), new Cell(12, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.FlowPlan), new Cell(13, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.FlowLimitMax), new Cell(14, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.RopPlan), new Cell(15, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.UsageSaub), new Cell(16, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.UsageSpin), new Cell(17, typeof(double)) }, - { nameof(ProcessMapPlanDrillingDto.Comment), new Cell(18, typeof(string)) } - }; + protected override ITemplateParameters TemplateParameters => new ProcessMapPlanDrillingTemplate(); protected override ProcessMapPlanDrillingDto BuildDto(IDictionary row, int rowNumber) { @@ -55,7 +27,10 @@ public class ProcessMapPlanDrillingParser : ProcessMapPlanParser : ParserExcelService where TDto : ProcessMapPlanBaseDto { - protected override int HeaderRowsCount => 2; - + protected readonly IEnumerable sections; + + protected ProcessMapPlanParser(IWellOperationRepository wellOperationRepository) + { + sections = wellOperationRepository.GetSectionTypes(); + } + public override ParserResultDto Parse(Stream file, WellRelatedParserRequest options) { var result = base.Parse(file, options); diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanReamParser.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanReamParser.cs index 6ca31714..7bfaa880 100644 --- a/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanReamParser.cs +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Parser/ProcessMapPlanReamParser.cs @@ -2,42 +2,21 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using AsbCloudApp.Data; using AsbCloudApp.Data.ProcessMaps; using AsbCloudApp.Repositories; -using AsbCloudInfrastructure.Services.Parser; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.ProcessMapPlanTemplates; namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Parser; public class ProcessMapPlanReamParser : ProcessMapPlanParser { - private readonly IEnumerable sections; - public ProcessMapPlanReamParser(IWellOperationRepository wellOperationRepository) + : base(wellOperationRepository) { - sections = wellOperationRepository.GetSectionTypes(); } - - protected override string SheetName => "План"; - protected override string TemplateFileName => "ProcessMapPlanReamTemplate.xlsx"; - private const int ColumnSection = 1; - - protected override IDictionary Cells => new Dictionary - { - { nameof(ProcessMapPlanReamDto.Section), new Cell(ColumnSection, typeof(string)) }, - { nameof(ProcessMapPlanReamDto.DepthStart), new Cell(2, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.DepthEnd), new Cell(3, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.Repeats), new Cell(4, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.SpinUpward), new Cell(5, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.SpinUpward), new Cell(6, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.SpeedDownward), new Cell(7, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.SpeedUpward), new Cell(8, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.SetpointDrag), new Cell(9, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.SetpointTight), new Cell(10, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.Pressure), new Cell(11, typeof(double)) }, - { nameof(ProcessMapPlanReamDto.Torque), new Cell(12, typeof(double)) }, - }; + protected override ITemplateParameters TemplateParameters => new ProcessMapPlanReamTemplate(); protected override ProcessMapPlanReamDto BuildDto(IDictionary row, int rowNumber) { @@ -48,7 +27,9 @@ public class ProcessMapPlanReamParser : ProcessMapPlanParser { - protected override string SheetName => "Фактическая траектория"; - - protected override string TemplateFileName => "TrajectoryFactManualTemplate.xlsx"; - - protected override IDictionary Cells => new Dictionary - { - { nameof(TrajectoryGeoFactDto.WellboreDepth), new Cell(1, typeof(double)) }, - { nameof(TrajectoryGeoFactDto.ZenithAngle), new Cell(2, typeof(double)) }, - { nameof(TrajectoryGeoFactDto.AzimuthGeo), new Cell(3, typeof(double)) }, - { nameof(TrajectoryGeoFactDto.AzimuthMagnetic), new Cell(4, typeof(double)) }, - { nameof(TrajectoryGeoFactDto.VerticalDepth), new Cell(5, typeof(double)) }, - { nameof(TrajectoryGeoFactDto.Comment), new Cell(6, typeof(string)) } - }; + protected override ITemplateParameters TemplateParameters => new TrajectoryFactManualTemplate(); } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs index ce579fa6..f2aca93d 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParser.cs @@ -2,15 +2,13 @@ using System.IO; using AsbCloudApp.Data; using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Requests.ParserOptions; -using AsbCloudInfrastructure.Services.Parser; +using AsbCloudInfrastructure.Services.ExcelServices; namespace AsbCloudInfrastructure.Services.Trajectory.Parser; public abstract class TrajectoryParser : ParserExcelService where TDto : TrajectoryGeoDto { - protected override int HeaderRowsCount => 2; - public override ParserResultDto Parse(Stream file, WellRelatedParserRequest options) { var result = base.Parse(file, options); diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs index 568bfa35..d99f0b9f 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParser.cs @@ -1,23 +1,10 @@ -using System.Collections.Generic; -using AsbCloudApp.Data.Trajectory; -using AsbCloudInfrastructure.Services.Parser; +using AsbCloudApp.Data.Trajectory; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.TrajectoryTemplates; namespace AsbCloudInfrastructure.Services.Trajectory.Parser; public class TrajectoryPlanParser : TrajectoryParser { - protected override string SheetName => "Плановая траектория"; - - protected override string TemplateFileName => "TrajectoryPlanTemplate.xlsx"; - - protected override IDictionary Cells => new Dictionary - { - { nameof(TrajectoryGeoPlanDto.WellboreDepth), new Cell(1, typeof(double)) }, - { nameof(TrajectoryGeoPlanDto.ZenithAngle), new Cell(2, typeof(double)) }, - { nameof(TrajectoryGeoPlanDto.AzimuthGeo), new Cell(3, typeof(double)) }, - { nameof(TrajectoryGeoPlanDto.AzimuthMagnetic), new Cell(4, typeof(double)) }, - { nameof(TrajectoryGeoPlanDto.VerticalDepth), new Cell(5, typeof(double)) }, - { nameof(TrajectoryGeoPlanDto.Radius), new Cell(6, typeof(double)) }, - { nameof(TrajectoryGeoPlanDto.Comment), new Cell(7, typeof(string)) } - }; + protected override ITemplateParameters TemplateParameters => new TrajectoryPlanTemplate(); } \ No newline at end of file diff --git a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs index 8b9bd3e9..1acd0ad7 100644 --- a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs +++ b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs @@ -1,7 +1,6 @@ using System.Linq; using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Requests.ParserOptions; -using AsbCloudInfrastructure.Services.Parser; using AsbCloudInfrastructure.Services.Trajectory.Parser; using Xunit; From 95ddd97ace0d551756e6f0d056f8f595cb3cfead 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: Thu, 14 Mar 2024 08:30:25 +0300 Subject: [PATCH 21/27] =?UTF-8?q?=D0=AD=D0=BA=D1=81=D0=BF=D0=BE=D1=80?= =?UTF-8?q?=D1=82=20=D0=A0=D0=A2=D0=9A=20=D0=B8=20=D1=82=D1=80=D0=B0=D0=B5?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProcessMaps/ProcessMapPlanDrillingDto.cs | 10 +- .../Services/IProcessMapPlanExportService.cs | 19 ++++ .../Services/ITrajectoryExportService.cs | 19 ++++ AsbCloudInfrastructure/DependencyInjection.cs | 11 ++- .../ProcessMapPlanBaseRepository.cs | 8 ++ .../ExcelServices/ExportExcelService.cs | 57 ++++++++++++ .../ProcessMapPlanReamTemplate.cs | 2 +- .../ProcessMapPlanDrillingExportService.cs | 29 ++++++ .../Export/ProcessMapPlanExportService.cs | 38 ++++++++ .../Export/ProcessMapPlanReamExportService.cs | 29 ++++++ .../Export/TrajectoryExportService.cs | 92 +++++-------------- .../TrajectoryFactManualExportService.cs | 48 ++++------ .../Export/TrajectoryFactNnbExportService.cs | 48 ++++------ .../Export/TrajectoryPlanExportService.cs | 53 +++++------ .../ProcessMapPlanDrillingControllerTest.cs | 2 - .../Trajectory/TrajectoryExportTest.cs | 6 +- .../ProcessMapPlanBaseController.cs | 23 ++++- .../ProcessMapPlanDrillingController.cs | 6 +- .../ProcessMapPlanReamController.cs | 6 +- .../Trajectory/TrajectoryController.cs | 16 ++-- .../TrajectoryEditableController.cs | 14 +-- .../TrajectoryFactManualController.cs | 2 +- .../Trajectory/TrajectoryFactNnbController.cs | 2 +- .../Trajectory/TrajectoryPlanController.cs | 2 +- AsbCloudWebApi/Extensions.cs | 3 - 25 files changed, 345 insertions(+), 200 deletions(-) create mode 100644 AsbCloudApp/Services/IProcessMapPlanExportService.cs create mode 100644 AsbCloudApp/Services/ITrajectoryExportService.cs create mode 100644 AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs create mode 100644 AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs create mode 100644 AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs create mode 100644 AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanReamExportService.cs diff --git a/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanDrillingDto.cs b/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanDrillingDto.cs index 67d6c74b..78567c2d 100644 --- a/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanDrillingDto.cs +++ b/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanDrillingDto.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using System; +using System.ComponentModel.DataAnnotations; namespace AsbCloudApp.Data.ProcessMaps; @@ -16,7 +17,12 @@ public class ProcessMapPlanDrillingDto : ProcessMapPlanBaseDto /// /// Название режима бурения /// - public string? Mode { get; set; } + public string Mode => IdMode switch + { + 1 => "Ротор", + 2 => "Слайд", + _ => throw new ArgumentOutOfRangeException() + }; /// /// Осевая нагрузка, т план diff --git a/AsbCloudApp/Services/IProcessMapPlanExportService.cs b/AsbCloudApp/Services/IProcessMapPlanExportService.cs new file mode 100644 index 00000000..6c226a55 --- /dev/null +++ b/AsbCloudApp/Services/IProcessMapPlanExportService.cs @@ -0,0 +1,19 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Services; + +/// +/// Экспорт РТК +/// +public interface IProcessMapPlanExportService +{ + /// + /// Экспортировать РТК по скважине + /// + /// + /// + /// + Task<(string FileName, Stream File)> ExportAsync(int idWell, CancellationToken token); +} \ No newline at end of file diff --git a/AsbCloudApp/Services/ITrajectoryExportService.cs b/AsbCloudApp/Services/ITrajectoryExportService.cs new file mode 100644 index 00000000..610ccf9f --- /dev/null +++ b/AsbCloudApp/Services/ITrajectoryExportService.cs @@ -0,0 +1,19 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Services; + +/// +/// Экспорт траекторий +/// +public interface ITrajectoryExportService +{ + /// + /// Экспортировать траектории по скважине + /// + /// + /// + /// + Task<(string FileName, Stream File)> ExportAsync(int idWell, CancellationToken token); +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 2111356b..b1e9f17e 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -45,6 +45,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System; +using AsbCloudInfrastructure.Services.ProcessMapPlan.Export; namespace AsbCloudInfrastructure { @@ -161,9 +162,6 @@ namespace AsbCloudInfrastructure services.AddScoped(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -294,7 +292,14 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); + + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + return services; } } diff --git a/AsbCloudInfrastructure/Repository/ProcessMapPlanBaseRepository.cs b/AsbCloudInfrastructure/Repository/ProcessMapPlanBaseRepository.cs index bfea0fe6..789da211 100644 --- a/AsbCloudInfrastructure/Repository/ProcessMapPlanBaseRepository.cs +++ b/AsbCloudInfrastructure/Repository/ProcessMapPlanBaseRepository.cs @@ -28,6 +28,7 @@ public class ProcessMapPlanBaseRepository : ChangeLogRepositoryAb .Include(e => e.Author) .Include(e => e.Editor) .Include(e => e.Well) + .Include(e => e.WellSectionType) .Where(e => e.IdWell == request.IdWell); if (request.IdWellSectionType.HasValue) @@ -56,4 +57,11 @@ public class ProcessMapPlanBaseRepository : ChangeLogRepositoryAb var offset = TimeSpan.FromHours(timezone.Hours); return offset; } + + protected override TDto Convert(TEntity entity, TimeSpan offset) + { + var dto = base.Convert(entity, offset); + dto.Section = entity.WellSectionType.Caption; + return dto; + } } diff --git a/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs b/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs new file mode 100644 index 00000000..9e189411 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; +using ClosedXML.Excel; +using Mapster; + +namespace AsbCloudInfrastructure.Services.ExcelServices; + +public abstract class ExportExcelService +{ + protected abstract ITemplateParameters TemplateParameters { get; } + + protected Stream Export(IEnumerable dtos) + { + using var template = GetTemplateFile(); + using var workbook = new XLWorkbook(template); + AddDtosToWorkbook(workbook, dtos); + + var memoryStream = new MemoryStream(); + workbook.SaveAs(memoryStream, new SaveOptions { }); + memoryStream.Seek(0, SeekOrigin.Begin); + return memoryStream; + } + + private void AddDtosToWorkbook(XLWorkbook workbook, IEnumerable dtos) + { + var dtosToArray = dtos.ToArray(); + + if (!dtosToArray.Any()) + return; + + var sheet = workbook.GetWorksheet(TemplateParameters.SheetName); + for (var i = 0; i < dtosToArray.Length; i++) + { + var row = sheet.Row(1 + i + TemplateParameters.HeaderRowsCount); + AddRow(row, dtosToArray[i]); + } + } + + private void AddRow(IXLRow xlRow, TDto dto) + { + var properties = dto.Adapt>(); + + foreach (var (name, cellValue) in properties) + { + if (TemplateParameters.Cells.TryGetValue(name, out var cell)) + xlRow.Cell(cell.ColumnNumber).SetCellValue(cellValue); + } + } + + private Stream GetTemplateFile() => + Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateParameters.FileName) + ?? throw new ArgumentNullException($"Файл '{TemplateParameters.FileName}' не найден"); +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanReamTemplate.cs b/AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanReamTemplate.cs index 4df80a7e..5c454d7b 100644 --- a/AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanReamTemplate.cs +++ b/AsbCloudInfrastructure/Services/ExcelServices/Templates/ProcessMapPlanTemplates/ProcessMapPlanReamTemplate.cs @@ -7,7 +7,7 @@ public class ProcessMapPlanReamTemplate : ITemplateParameters { public string SheetName => "План"; - public int HeaderRowsCount => 2; + public int HeaderRowsCount => 1; public string FileName => "ProcessMapPlanReamTemplate.xlsx"; diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs new file mode 100644 index 00000000..671a34ee --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs @@ -0,0 +1,29 @@ +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data.ProcessMaps; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.ProcessMapPlanTemplates; + +namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Export; + +public class ProcessMapPlanDrillingExportService : ProcessMapPlanExportService +{ + public ProcessMapPlanDrillingExportService( + IChangeLogRepository processMapPlanRepository, + IWellService wellService) + : base(processMapPlanRepository, wellService) + { + } + + protected override ITemplateParameters TemplateParameters => new ProcessMapPlanDrillingTemplate(); + + protected override async Task BuildFileNameAsync(int idWell, CancellationToken token) + { + var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); + + return $"{caption}_РТК_План_бурение.xlsx"; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs new file mode 100644 index 00000000..60491ca8 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs @@ -0,0 +1,38 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using AsbCloudInfrastructure.Services.ExcelServices; + +namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Export; + +public abstract class ProcessMapPlanExportService : ExportExcelService, + IProcessMapPlanExportService + where TDto : ChangeLogAbstract +{ + protected readonly IWellService wellService; + + private readonly IChangeLogRepository processMapPlanRepository; + + protected ProcessMapPlanExportService(IChangeLogRepository processMapPlanRepository, + IWellService wellService) + { + this.processMapPlanRepository = processMapPlanRepository; + this.wellService = wellService; + } + + public async Task<(string FileName, Stream File)> ExportAsync(int idWell, CancellationToken token) + { + var request = new ProcessMapPlanBaseRequestWithWell(idWell); + var dtos = await processMapPlanRepository.Get(request, token); + + var fileName = await BuildFileNameAsync(idWell, token); + var file = Export(dtos); + return (fileName, file); + } + + protected abstract Task BuildFileNameAsync(int idWell, CancellationToken token); +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanReamExportService.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanReamExportService.cs new file mode 100644 index 00000000..b2452172 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanReamExportService.cs @@ -0,0 +1,29 @@ +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data.ProcessMaps; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.ProcessMapPlanTemplates; + +namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Export; + +public class ProcessMapPlanReamExportService : ProcessMapPlanExportService +{ + protected override ITemplateParameters TemplateParameters => new ProcessMapPlanReamTemplate(); + + public ProcessMapPlanReamExportService( + IChangeLogRepository processMapPlanRepository, + IWellService wellService) + : base(processMapPlanRepository, wellService) + { + } + + protected override async Task BuildFileNameAsync(int idWell, CancellationToken token) + { + var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); + + return $"{caption}_РТК_План_проработка.xlsx"; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryExportService.cs b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryExportService.cs index 6ac2bf15..489b15f4 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryExportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryExportService.cs @@ -1,83 +1,35 @@ using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Repositories; using AsbCloudApp.Services; -using ClosedXML.Excel; -using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudInfrastructure.Services.ExcelServices; -namespace AsbCloudInfrastructure.Services.Trajectory.Export +namespace AsbCloudInfrastructure.Services.Trajectory.Export; + +public abstract class TrajectoryExportService : ExportExcelService, + ITrajectoryExportService + where TDto : TrajectoryGeoDto { - public abstract class TrajectoryExportService where T : TrajectoryGeoDto - { - private readonly IWellService wellService; + protected readonly IWellService wellService; - private readonly ITrajectoryRepository trajectoryRepository; - public abstract string templateFileName { get; } - public abstract string usingTemplateFile { get; } - public abstract string sheetName { get; } - public abstract int headerRowsCount { get; } + private readonly ITrajectoryRepository trajectoryRepository; - public TrajectoryExportService(IWellService wellService, ITrajectoryRepository trajectoryRepository) - { - this.wellService = wellService; - this.trajectoryRepository = trajectoryRepository; - } + protected TrajectoryExportService(IWellService wellService, ITrajectoryRepository trajectoryRepository) + { + this.wellService = wellService; + this.trajectoryRepository = trajectoryRepository; + } - protected abstract void AddCoordinatesToRow(IXLRow row, T trajectory); + public async Task<(string FileName, Stream File)> ExportAsync(int idWell, CancellationToken token) + { + var dtos = await trajectoryRepository.GetAsync(idWell, token); - public async Task ExportAsync(int idWell, CancellationToken token) - { - var trajectorys = await trajectoryRepository.GetAsync(idWell, token); - return MakeExelFileStream(trajectorys); - } + var fileName = await BuildFileNameAsync(idWell, token); + var file = Export(dtos); + return (fileName, file); + } - public async Task GetFileNameAsync(int idWell, CancellationToken token) - { - var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); - return string.Format("{0}_{1}", caption, templateFileName); - } - - public Stream GetTemplateFile() - { - var stream = System.Reflection.Assembly.GetExecutingAssembly() - .GetManifestResourceStream($"{usingTemplateFile}.{templateFileName}"); - if (stream is null) - throw new Exception($"Область {usingTemplateFile} не содержит файла с названием {templateFileName}"); - return stream; - } - - private Stream MakeExelFileStream(IEnumerable trajectories) - { - using Stream ecxelTemplateStream = GetTemplateFile(); - using var workbook = new XLWorkbook(ecxelTemplateStream); - AddTrajecoryToWorkbook(workbook, trajectories); - MemoryStream memoryStream = new MemoryStream(); - workbook.SaveAs(memoryStream, new SaveOptions { }); - memoryStream.Seek(0, SeekOrigin.Begin); - return memoryStream; - } - - private void AddTrajecoryToWorkbook(XLWorkbook workbook, IEnumerable trajectories) - { - if (trajectories.Any()) - { - var sheet = workbook.GetWorksheet(sheetName); - AddTrajecoryToSheet(sheet, trajectories); - } - } - - private void AddTrajecoryToSheet(IXLWorksheet sheet, IEnumerable trajectories) - { - var rowList = trajectories.ToList(); - for (int i = 0; i < rowList.Count; i++) - { - var row = sheet.Row(1 + i + headerRowsCount); - AddCoordinatesToRow(row, rowList[i]); - } - } - } -} + protected abstract Task BuildFileNameAsync(int idWell, CancellationToken token); +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactManualExportService.cs b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactManualExportService.cs index 2662d62a..f1ccbc89 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactManualExportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactManualExportService.cs @@ -1,35 +1,27 @@ -using AsbCloudApp.Data.Trajectory; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Repositories; using AsbCloudApp.Services; -using ClosedXML.Excel; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.TrajectoryTemplates; -namespace AsbCloudInfrastructure.Services.Trajectory.Export +namespace AsbCloudInfrastructure.Services.Trajectory.Export; + +public class TrajectoryFactManualExportService : TrajectoryExportService { + public TrajectoryFactManualExportService(IWellService wellService, + ITrajectoryEditableRepository trajectoryRepository) + : base(wellService, trajectoryRepository) + { + } - public class TrajectoryFactManualExportService : TrajectoryExportService - { - public override string templateFileName { get; } = "TrajectoryFactManualTemplate.xlsx"; - public override string usingTemplateFile { get; } = "AsbCloudInfrastructure.Services.Trajectory.Templates"; - public override string sheetName { get; } = "Фактическая траектория"; - public override int headerRowsCount { get; } = 2; + protected override ITemplateParameters TemplateParameters => new TrajectoryFactManualTemplate(); - public TrajectoryFactManualExportService( - IWellService wellService, - ITrajectoryEditableRepository factTrajectoryService) - : base(wellService, factTrajectoryService) - { - - } - - protected override void AddCoordinatesToRow(IXLRow row, TrajectoryGeoFactDto trajectory) - { - row.Cell(1).SetCellValue(trajectory.WellboreDepth); - row.Cell(2).SetCellValue(trajectory.ZenithAngle); - row.Cell(3).SetCellValue(trajectory.AzimuthGeo); - row.Cell(4).SetCellValue(trajectory.AzimuthMagnetic); - row.Cell(5).SetCellValue(trajectory.VerticalDepth); - row.Cell(6).SetCellValue(trajectory.Comment); - } - } -} + protected override async Task BuildFileNameAsync(int idWell, CancellationToken token) + { + var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); + return $"{caption}_Фактическая_траектория.xlsx"; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactNnbExportService.cs b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactNnbExportService.cs index c32e6cff..2bab0783 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactNnbExportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactNnbExportService.cs @@ -1,35 +1,27 @@ -using AsbCloudApp.Data.Trajectory; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Repositories; using AsbCloudApp.Services; -using ClosedXML.Excel; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.TrajectoryTemplates; -namespace AsbCloudInfrastructure.Services.Trajectory.Export +namespace AsbCloudInfrastructure.Services.Trajectory.Export; + +public class TrajectoryFactNnbExportService : TrajectoryExportService { + public TrajectoryFactNnbExportService(IWellService wellService, + ITrajectoryNnbRepository trajectoryRepository) + : base(wellService, trajectoryRepository) + { + } - public class TrajectoryFactNnbExportService : TrajectoryExportService - { - public override string templateFileName { get; } = "TrajectoryFactNnbTemplate.xlsx"; - public override string usingTemplateFile { get; } = "AsbCloudInfrastructure.Services.Trajectory.Templates"; - public override string sheetName { get; } = "Фактическая ннб-траектория"; - public override int headerRowsCount { get; } = 2; + protected override ITemplateParameters TemplateParameters => new TrajectoryFactNnbTemplate(); - public TrajectoryFactNnbExportService( - IWellService wellService, - ITrajectoryNnbRepository nnbTrajectoryService) - : base(wellService, nnbTrajectoryService) - { - - } - - protected override void AddCoordinatesToRow(IXLRow row, TrajectoryGeoFactDto trajectory) - { - row.Cell(1).SetCellValue(trajectory.WellboreDepth); - row.Cell(2).SetCellValue(trajectory.ZenithAngle); - row.Cell(3).SetCellValue(trajectory.AzimuthGeo); - row.Cell(4).SetCellValue(trajectory.AzimuthMagnetic); - row.Cell(5).SetCellValue(trajectory.VerticalDepth); - row.Cell(6).SetCellValue(trajectory.Comment); - } - } -} + protected override async Task BuildFileNameAsync(int idWell, CancellationToken token) + { + var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); + return $"{caption}_Траектория_ННБ.xlsx"; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryPlanExportService.cs b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryPlanExportService.cs index 403ceccc..5a931939 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryPlanExportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryPlanExportService.cs @@ -1,38 +1,27 @@ -using AsbCloudApp.Data.Trajectory; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Repositories; using AsbCloudApp.Services; -using ClosedXML.Excel; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.TrajectoryTemplates; -namespace AsbCloudInfrastructure.Services.Trajectory.Export +namespace AsbCloudInfrastructure.Services.Trajectory.Export; + +public class TrajectoryPlanExportService : TrajectoryExportService { - public class TrajectoryPlanExportService : TrajectoryExportService - { - /* - * password for PlannedTrajectoryTemplate.xlsx is Drill2022 - */ - public override string templateFileName { get; } = "TrajectoryPlanTemplate.xlsx"; - public override string usingTemplateFile { get; } = "AsbCloudInfrastructure.Services.Trajectory.Templates"; - public override string sheetName { get; } = "Плановая траектория"; - public override int headerRowsCount { get; } = 2; + public TrajectoryPlanExportService(IWellService wellService, + ITrajectoryEditableRepository trajectoryRepository) + : base(wellService, trajectoryRepository) + { + } - public TrajectoryPlanExportService( - IWellService wellService, - ITrajectoryEditableRepository trajectoryPlanService) - : base(wellService, trajectoryPlanService) - { - } - - protected override void AddCoordinatesToRow(IXLRow row, TrajectoryGeoPlanDto trajectory) - { - row.Cell(1).SetCellValue(trajectory.WellboreDepth); - row.Cell(2).SetCellValue(trajectory.ZenithAngle); - row.Cell(3).SetCellValue(trajectory.AzimuthGeo); - row.Cell(4).SetCellValue(trajectory.AzimuthMagnetic); - row.Cell(5).SetCellValue(trajectory.VerticalDepth); - row.Cell(6).SetCellValue(trajectory.Radius); - row.Cell(7).SetCellValue(trajectory.Comment); - } - } - -} + protected override ITemplateParameters TemplateParameters => new TrajectoryPlanTemplate(); + + protected override async Task BuildFileNameAsync(int idWell, CancellationToken token) + { + var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); + return $"{caption}_Плановая_Траектория.xlsx"; + } +} \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs index 3a5815e9..40a0c3c1 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs @@ -29,7 +29,6 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest DepthEnd = 1.5, IdMode = 1, - Mode = "Ротор", AxialLoadPlan = 2.718281, AxialLoadLimitMax = 3.1415926, DeltaPressurePlan = 4, @@ -115,7 +114,6 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest nameof(ProcessMapPlanDrillingDto.IdState), nameof(ProcessMapPlanDrillingDto.Author), nameof(ProcessMapPlanDrillingDto.Creation), - nameof(ProcessMapPlanDrillingDto.Mode), nameof(ProcessMapPlanDrillingDto.Section) }; MatchHelper.Match(expected, actual, excludeProps); diff --git a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs index 79b63ac6..1c026185 100644 --- a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs +++ b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs @@ -100,7 +100,7 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory .Returns(trajectoryPlanRows); var stream = await trajectoryPlanExportService.ExportAsync(idWell, CancellationToken.None); - Assert.True(stream.Length > 0); + Assert.True(stream.File.Length > 0); } @@ -111,7 +111,7 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory .Returns(trajectoryFactRows); var stream = await trajectoryFactManualExportService.ExportAsync(idWell, CancellationToken.None); - Assert.True(stream.Length > 0); + Assert.True(stream.File.Length > 0); } [Fact] @@ -121,7 +121,7 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory .Returns(trajectoryFactRows); var stream = await trajectoryFactNnbExportService.ExportAsync(idWell, CancellationToken.None); - Assert.True(stream.Length > 0); + Assert.True(stream.File.Length > 0); } } } diff --git a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs index 49513f2c..c3afebb3 100644 --- a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs @@ -13,7 +13,6 @@ using AsbCloudApp.Services; using System.Linq; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; -using AsbCloudInfrastructure.Services.Parser; using AsbCloudApp.Data.ProcessMaps; using System.ComponentModel.DataAnnotations; @@ -30,15 +29,18 @@ public abstract class ProcessMapPlanBaseController : ControllerBase { private readonly IChangeLogRepository repository; private readonly IWellService wellService; - private readonly ParserExcelService parserService; + private readonly IParserService parserService; + private readonly IProcessMapPlanExportService processMapPlanExportService; protected ProcessMapPlanBaseController(IChangeLogRepository repository, IWellService wellService, - ParserExcelService parserService) + IParserService parserService, + IProcessMapPlanExportService processMapPlanExportService) { this.repository = repository; this.wellService = wellService; this.parserService = parserService; + this.processMapPlanExportService = processMapPlanExportService; } protected abstract string TemplateFileName { get; } @@ -266,6 +268,21 @@ public abstract class ProcessMapPlanBaseController : ControllerBase throw new ForbidException("Нет доступа к скважине"); return idUser; } + + /// + /// Формируем excel файл с текущими строками РТК + /// + /// id скважины + /// + /// Запрашиваемый файл + [HttpGet("export")] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task ExportAsync([FromRoute] int idWell, CancellationToken token) + { + var (fileName, file) = await processMapPlanExportService.ExportAsync(idWell, token); + return File(file, "application/octet-stream", fileName); + } /// /// returns user id or throw diff --git a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanDrillingController.cs b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanDrillingController.cs index 5c038496..241be301 100644 --- a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanDrillingController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanDrillingController.cs @@ -2,6 +2,7 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; +using AsbCloudInfrastructure.Services.ProcessMapPlan.Export; using AsbCloudInfrastructure.Services.ProcessMapPlan.Parser; namespace AsbCloudWebApi.Controllers.ProcessMaps; @@ -13,8 +14,9 @@ public class ProcessMapPlanDrillingController : ProcessMapPlanBaseController repository, IWellService wellService, - ProcessMapPlanDrillingParser parserService) - : base(repository, wellService, parserService) + ProcessMapPlanDrillingParser parserService, + ProcessMapPlanDrillingExportService processMapPlanExportService) + : base(repository, wellService, parserService, processMapPlanExportService) { } diff --git a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanReamController.cs b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanReamController.cs index b785d480..9c103f06 100644 --- a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanReamController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanReamController.cs @@ -2,6 +2,7 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; +using AsbCloudInfrastructure.Services.ProcessMapPlan.Export; using AsbCloudInfrastructure.Services.ProcessMapPlan.Parser; namespace AsbCloudWebApi.Controllers.ProcessMaps; @@ -13,8 +14,9 @@ public class ProcessMapPlanReamController : ProcessMapPlanBaseController repository, IWellService wellService, - ProcessMapPlanReamParser parserService) - : base(repository, wellService, parserService) + ProcessMapPlanReamParser parserService, + ProcessMapPlanReamExportService processMapPlanExportService) + : base(repository, wellService, parserService, processMapPlanExportService) { } diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs index 789b9252..6311d34a 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs @@ -1,8 +1,6 @@ using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Repositories; -using AsbCloudApp.Requests; using AsbCloudApp.Services; -using AsbCloudInfrastructure.Services.Trajectory.Export; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -21,14 +19,14 @@ namespace AsbCloudWebApi.Controllers.Trajectory public abstract class TrajectoryController : ControllerBase where TDto : TrajectoryGeoDto { - protected abstract string fileName { get; } + protected abstract string TemplateFileName { get; } private readonly IWellService wellService; - private readonly TrajectoryExportService trajectoryExportService; + private readonly ITrajectoryExportService trajectoryExportService; private readonly ITrajectoryRepository trajectoryRepository; - public TrajectoryController(IWellService wellService, - TrajectoryExportService trajectoryExportService, + protected TrajectoryController(IWellService wellService, + ITrajectoryExportService trajectoryExportService, ITrajectoryRepository trajectoryRepository) { this.trajectoryExportService = trajectoryExportService; @@ -50,9 +48,9 @@ namespace AsbCloudWebApi.Controllers.Trajectory if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); - var stream = await trajectoryExportService.ExportAsync(idWell, token); - var fileName = await trajectoryExportService.GetFileNameAsync(idWell, token); - return File(stream, "application/octet-stream", fileName); + + var (fileName, file) = await trajectoryExportService.ExportAsync(idWell, token); + return File(file, "application/octet-stream", fileName); } /// diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs index 814bcdcf..a014e1bc 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs @@ -1,8 +1,6 @@ -using System; -using AsbCloudApp.Data.Trajectory; +using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Repositories; using AsbCloudApp.Services; -using AsbCloudInfrastructure.Services.Trajectory.Export; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -12,8 +10,6 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; -using AsbCloudInfrastructure.Services.Parser; -using AsbCloudInfrastructure.Services.Trajectory.Parser; namespace AsbCloudWebApi.Controllers.Trajectory { @@ -26,12 +22,12 @@ namespace AsbCloudWebApi.Controllers.Trajectory public abstract class TrajectoryEditableController : TrajectoryController where TDto : TrajectoryGeoDto { - private readonly TrajectoryParser parserService; + private readonly IParserService parserService; private readonly ITrajectoryEditableRepository trajectoryRepository; protected TrajectoryEditableController(IWellService wellService, - TrajectoryParser parserService, - TrajectoryExportService trajectoryExportService, + IParserService parserService, + ITrajectoryExportService trajectoryExportService, ITrajectoryEditableRepository trajectoryRepository) : base(wellService, trajectoryExportService, trajectoryRepository) { @@ -50,7 +46,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory public IActionResult GetTemplate() { var stream = parserService.GetTemplateFile(); - return File(stream, "application/octet-stream", fileName); + return File(stream, "application/octet-stream", TemplateFileName); } /// diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactManualController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactManualController.cs index aa1a60dc..d0bd33b5 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactManualController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactManualController.cs @@ -14,7 +14,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory; [Route("api/well/{idWell}/[controller]")] public class TrajectoryFactManualController : TrajectoryEditableController { - protected override string fileName => "ЕЦП_шаблон_файла_фактическая_траектория.xlsx"; + protected override string TemplateFileName => "ЕЦП_шаблон_файла_фактическая_траектория.xlsx"; public TrajectoryFactManualController(IWellService wellService, TrajectoryFactManualExportService trajectoryExportService, diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactNnbController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactNnbController.cs index 4e2b4661..6dd84898 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactNnbController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryFactNnbController.cs @@ -15,7 +15,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory; [Route("api/well/{idWell}/[controller]")] public class TrajectoryFactNnbController : TrajectoryController { - protected override string fileName => "ЕЦП_шаблон_файла_фактическая_ннб_траектория.xlsx"; + protected override string TemplateFileName => "ЕЦП_шаблон_файла_фактическая_ннб_траектория.xlsx"; public TrajectoryFactNnbController( ITrajectoryNnbRepository trajectoryNnbRepository, TrajectoryFactNnbExportService trajectoryExportService, diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryPlanController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryPlanController.cs index bffd7d15..67a54007 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryPlanController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryPlanController.cs @@ -20,7 +20,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory { private readonly TrajectoryService trajectoryVisualizationService; - protected override string fileName => "ЕЦП_шаблон_файла_плановая_траектория.xlsx"; + protected override string TemplateFileName => "ЕЦП_шаблон_файла_плановая_траектория.xlsx"; public TrajectoryPlanController(IWellService wellService, TrajectoryPlanParser parserService, diff --git a/AsbCloudWebApi/Extensions.cs b/AsbCloudWebApi/Extensions.cs index 26cea7ba..a19dcc6e 100644 --- a/AsbCloudWebApi/Extensions.cs +++ b/AsbCloudWebApi/Extensions.cs @@ -7,10 +7,7 @@ using System.IO; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Security.Claims; -using AsbCloudApp.Data; using AsbCloudApp.Exceptions; -using AsbCloudApp.Requests.ParserOptions; -using AsbCloudInfrastructure.Services.Parser; using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Mvc; From b662f138197699cea8ffec79b7c3000c7b978b17 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: Thu, 14 Mar 2024 09:05:58 +0300 Subject: [PATCH 22/27] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=D1=8B=20=D1=8D?= =?UTF-8?q?=D0=BA=D1=81=D0=BF=D0=BE=D1=80=D1=82=D0=B0=20=D0=B8=20=D0=B8?= =?UTF-8?q?=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D0=B0=20=D0=A0=D0=A2=D0=9A-?= =?UTF-8?q?=D0=9F=D0=BB=D0=B0=D0=BD=20=D0=B1=D1=83=D1=80=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProcessMaps/ProcessMapPlanDrillingDto.cs | 12 +++-------- .../ProcessMapPlanDrillingExportService.cs | 21 +++++++++++++++++++ .../Export/ProcessMapPlanExportService.cs | 11 ++++++++-- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanDrillingDto.cs b/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanDrillingDto.cs index 78567c2d..ea2555a8 100644 --- a/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanDrillingDto.cs +++ b/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanDrillingDto.cs @@ -1,5 +1,4 @@ -using System; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace AsbCloudApp.Data.ProcessMaps; @@ -17,13 +16,8 @@ public class ProcessMapPlanDrillingDto : ProcessMapPlanBaseDto /// /// Название режима бурения /// - public string Mode => IdMode switch - { - 1 => "Ротор", - 2 => "Слайд", - _ => throw new ArgumentOutOfRangeException() - }; - + public string? Mode { get; set; } + /// /// Осевая нагрузка, т план /// diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs index 671a34ee..18778ca1 100644 --- a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs @@ -1,3 +1,6 @@ +using System; +using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data.ProcessMaps; @@ -26,4 +29,22 @@ public class ProcessMapPlanDrillingExportService : ProcessMapPlanExportService

> GetProcessMapPlanAsync(int idWell, CancellationToken token) + { + var dtos = await base.GetProcessMapPlanAsync(idWell, token); + var dtosWithMode = dtos.Select(dto => + { + dto.Mode = dto.IdMode switch + { + 1 => "Ротор", + 2 => "Слайд", + _ => throw new ArgumentOutOfRangeException() + }; + + return dto; + }); + + return dtosWithMode; + } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs index 60491ca8..6d684946 100644 --- a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -26,8 +27,7 @@ public abstract class ProcessMapPlanExportService : ExportExcelService ExportAsync(int idWell, CancellationToken token) { - var request = new ProcessMapPlanBaseRequestWithWell(idWell); - var dtos = await processMapPlanRepository.Get(request, token); + var dtos = await GetProcessMapPlanAsync(idWell, token); var fileName = await BuildFileNameAsync(idWell, token); var file = Export(dtos); @@ -35,4 +35,11 @@ public abstract class ProcessMapPlanExportService : ExportExcelService BuildFileNameAsync(int idWell, CancellationToken token); + + protected virtual async Task> GetProcessMapPlanAsync(int idWell, CancellationToken token) + { + var request = new ProcessMapPlanBaseRequestWithWell(idWell); + var dtos = await processMapPlanRepository.Get(request, token); + return dtos; + } } \ No newline at end of file From 8b761779fd847c71fa9dcba39b6921fe8125f62d Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Thu, 14 Mar 2024 14:57:00 +0500 Subject: [PATCH 23/27] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=B0=D0=BB=D0=B3=D0=BE=D1=80=D0=B8=D1=82=D0=BC=D0=B0=20=D1=84?= =?UTF-8?q?=D0=BE=D1=80=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D0=B5=D0=B9=20=D0=B2=20?= =?UTF-8?q?=D0=BA=D0=B5=D1=88-=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D1=83?= =?UTF-8?q?=20Data=5FSaub=5FStat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PeriodicWorks/WorkDataSaubStat.cs | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs b/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs index d7daf9ad..ccb8472e 100644 --- a/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs +++ b/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs @@ -34,7 +34,7 @@ namespace AsbCloudInfrastructure.Background.PeriodicWorks var cacheRequest = new TelemetryDataRequest() { - GeDate = DateTime.UtcNow.AddDays(-Gap) + GeDate = DateTime.UtcNow.AddDays(-100) }; var idTelemetries = telemetryDataCache.GetIds(cacheRequest).ToArray(); @@ -49,6 +49,10 @@ namespace AsbCloudInfrastructure.Background.PeriodicWorks for( var i =0; i < idTelemetries.Length; i++) { var idTelemetry = idTelemetries[i]; + if(idTelemetry == 783) + { + ; + } var lastDate = stats.FirstOrDefault(s => s.IdTelemetry == idTelemetry)?.DateEnd.ToUniversalTime() ?? DateTimeOffset.UnixEpoch; var statsCount = await CreateStatForTelemetryFromDate(idTelemetry, lastDate, dataSaubService, dataSaubStatRepo, detectedOperationRepository, token); onProgressCallback($"Calculate stat for telemetry: {idTelemetry}; from {lastDate}; results count: {statsCount};", 100*i / idTelemetries.Length); @@ -154,13 +158,19 @@ namespace AsbCloudInfrastructure.Background.PeriodicWorks var hasOscillation = EnabledSubsystemsFlags.AutoOscillation.HasEnabledSubsystems(operation.EnabledSubsystems); var aggregatedValues = CalcAggregate(span); + var dateStart = span[0].DateTime; + var dateEnd = span[^1].DateTime; + var depthStart = span[0].WellDepth; + var depthEnd = span[^1].WellDepth; + var speed = ((depthEnd - depthStart) / (dateEnd - dateStart).TotalHours); + var processMapDrillingCacheItem = new DataSaubStatDto { - DateStart = operation.DateStart, - DateEnd = operation.DateEnd, - DepthStart = operation.DepthStart, - DepthEnd = operation.DepthEnd, - Speed = (operation.DepthEnd - operation.DepthStart) / ((operation.DateEnd - operation.DateStart).TotalHours), + DateStart = dateStart, + DateEnd = dateEnd, + DepthStart = depthStart, + DepthEnd = depthEnd, + Speed = speed, BlockSpeedSp = span[0].BlockSpeedSp, Pressure = aggregatedValues.Pressure, PressureIdle = span[0].PressureIdle, From 6cd42a546c840c14fa1e0f675e6d0a066941866f Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Thu, 14 Mar 2024 14:58:09 +0500 Subject: [PATCH 24/27] =?UTF-8?q?=D0=9E=D1=82=D0=BA=D0=B0=D1=82=20=D0=BB?= =?UTF-8?q?=D0=B8=D1=88=D0=BD=D0=B5=D0=B3=D0=BE=20=D0=BA=D0=BE=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Background/PeriodicWorks/WorkDataSaubStat.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs b/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs index ccb8472e..074c26ca 100644 --- a/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs +++ b/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs @@ -34,7 +34,7 @@ namespace AsbCloudInfrastructure.Background.PeriodicWorks var cacheRequest = new TelemetryDataRequest() { - GeDate = DateTime.UtcNow.AddDays(-100) + GeDate = DateTime.UtcNow.AddDays(-Gap) }; var idTelemetries = telemetryDataCache.GetIds(cacheRequest).ToArray(); @@ -49,10 +49,6 @@ namespace AsbCloudInfrastructure.Background.PeriodicWorks for( var i =0; i < idTelemetries.Length; i++) { var idTelemetry = idTelemetries[i]; - if(idTelemetry == 783) - { - ; - } var lastDate = stats.FirstOrDefault(s => s.IdTelemetry == idTelemetry)?.DateEnd.ToUniversalTime() ?? DateTimeOffset.UnixEpoch; var statsCount = await CreateStatForTelemetryFromDate(idTelemetry, lastDate, dataSaubService, dataSaubStatRepo, detectedOperationRepository, token); onProgressCallback($"Calculate stat for telemetry: {idTelemetry}; from {lastDate}; results count: {statsCount};", 100*i / idTelemetries.Length); From e3a7767a41917f4676b8bda45391ff8b2557177a 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: Thu, 14 Mar 2024 13:16:56 +0300 Subject: [PATCH 25/27] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80?= =?UTF-8?q?=D1=84=D0=B5=D0=B9=D1=81=D0=BE=D0=B2=20=D1=8D=D0=BA=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D1=80=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExportOptions/IExportOptionsRequest.cs | 8 +++++++ .../ExportOptions/WellRelatedExportRequest.cs | 21 +++++++++++++++++++ AsbCloudApp/Services/IExportService.cs | 21 +++++++++++++++++++ .../Services/IProcessMapPlanExportService.cs | 19 ----------------- .../Services/ITrajectoryExportService.cs | 19 ----------------- 5 files changed, 50 insertions(+), 38 deletions(-) create mode 100644 AsbCloudApp/Requests/ExportOptions/IExportOptionsRequest.cs create mode 100644 AsbCloudApp/Requests/ExportOptions/WellRelatedExportRequest.cs create mode 100644 AsbCloudApp/Services/IExportService.cs delete mode 100644 AsbCloudApp/Services/IProcessMapPlanExportService.cs delete mode 100644 AsbCloudApp/Services/ITrajectoryExportService.cs diff --git a/AsbCloudApp/Requests/ExportOptions/IExportOptionsRequest.cs b/AsbCloudApp/Requests/ExportOptions/IExportOptionsRequest.cs new file mode 100644 index 00000000..8d65572b --- /dev/null +++ b/AsbCloudApp/Requests/ExportOptions/IExportOptionsRequest.cs @@ -0,0 +1,8 @@ +namespace AsbCloudApp.Requests.ExportOptions; + +///

+/// Параметры экспорта +/// +public interface IExportOptionsRequest +{ +} \ No newline at end of file diff --git a/AsbCloudApp/Requests/ExportOptions/WellRelatedExportRequest.cs b/AsbCloudApp/Requests/ExportOptions/WellRelatedExportRequest.cs new file mode 100644 index 00000000..63b185cd --- /dev/null +++ b/AsbCloudApp/Requests/ExportOptions/WellRelatedExportRequest.cs @@ -0,0 +1,21 @@ +namespace AsbCloudApp.Requests.ExportOptions; + +/// +/// Параметры экспорта +/// +public class WellRelatedExportRequest : IExportOptionsRequest +{ + /// + /// Конструктор + /// + /// Id скважины + public WellRelatedExportRequest(int idWell) + { + IdWell = idWell; + } + + /// + /// Id скважины + /// + public int IdWell { get; } +} \ No newline at end of file diff --git a/AsbCloudApp/Services/IExportService.cs b/AsbCloudApp/Services/IExportService.cs new file mode 100644 index 00000000..b921fec5 --- /dev/null +++ b/AsbCloudApp/Services/IExportService.cs @@ -0,0 +1,21 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Requests.ExportOptions; + +namespace AsbCloudApp.Services; + +/// +/// Экспорт данных +/// +public interface IExportService + where TOptions : IExportOptionsRequest +{ + /// + /// Экспортировать данные + /// + /// + /// + /// + Task<(string FileName, Stream File)> ExportAsync(TOptions options, CancellationToken token); +} \ No newline at end of file diff --git a/AsbCloudApp/Services/IProcessMapPlanExportService.cs b/AsbCloudApp/Services/IProcessMapPlanExportService.cs deleted file mode 100644 index 6c226a55..00000000 --- a/AsbCloudApp/Services/IProcessMapPlanExportService.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudApp.Services; - -/// -/// Экспорт РТК -/// -public interface IProcessMapPlanExportService -{ - /// - /// Экспортировать РТК по скважине - /// - /// - /// - /// - Task<(string FileName, Stream File)> ExportAsync(int idWell, CancellationToken token); -} \ No newline at end of file diff --git a/AsbCloudApp/Services/ITrajectoryExportService.cs b/AsbCloudApp/Services/ITrajectoryExportService.cs deleted file mode 100644 index 610ccf9f..00000000 --- a/AsbCloudApp/Services/ITrajectoryExportService.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudApp.Services; - -/// -/// Экспорт траекторий -/// -public interface ITrajectoryExportService -{ - /// - /// Экспортировать траектории по скважине - /// - /// - /// - /// - Task<(string FileName, Stream File)> ExportAsync(int idWell, CancellationToken token); -} \ No newline at end of file From bc4d52200d065e0575ea166dc91190a81d18eaf9 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: Thu, 14 Mar 2024 13:18:02 +0300 Subject: [PATCH 26/27] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D1=81=D0=B5=D1=80=D0=B2=D0=B8?= =?UTF-8?q?=D1=81=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExcelServices/ExportExcelService.cs | 24 ++++++++++++++++--- .../ProcessMapPlanDrillingExportService.cs | 12 ++++++---- .../Export/ProcessMapPlanExportService.cs | 22 ++++------------- .../Export/ProcessMapPlanReamExportService.cs | 7 +++--- .../Export/TrajectoryExportService.cs | 20 +++++----------- .../TrajectoryFactManualExportService.cs | 7 +++--- .../Export/TrajectoryFactNnbExportService.cs | 5 ++-- .../Export/TrajectoryPlanExportService.cs | 9 +++---- .../Trajectory/TrajectoryExportTest.cs | 20 +++++++++------- .../ProcessMapPlanBaseController.cs | 8 ++++--- .../Trajectory/TrajectoryController.cs | 11 +++++---- .../TrajectoryEditableController.cs | 3 ++- 12 files changed, 80 insertions(+), 68 deletions(-) diff --git a/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs b/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs index 9e189411..086eba97 100644 --- a/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs +++ b/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs @@ -3,17 +3,35 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Requests.ExportOptions; +using AsbCloudApp.Services; using AsbCloudInfrastructure.Services.ExcelServices.Templates; using ClosedXML.Excel; using Mapster; namespace AsbCloudInfrastructure.Services.ExcelServices; -public abstract class ExportExcelService +public abstract class ExportExcelService : IExportService + where TOptions : IExportOptionsRequest { protected abstract ITemplateParameters TemplateParameters { get; } - - protected Stream Export(IEnumerable dtos) + + protected abstract Task BuildFileNameAsync(TOptions options, CancellationToken token); + + protected abstract Task> GetDtosAsync(TOptions options, CancellationToken token); + + public async Task<(string FileName, Stream File)> ExportAsync(TOptions options, CancellationToken token) + { + var dtos = await GetDtosAsync(options, token); + + var fileName = await BuildFileNameAsync(options, token); + var file = BuildFile(dtos); + return (fileName, file); + } + + private Stream BuildFile(IEnumerable dtos) { using var template = GetTemplateFile(); using var workbook = new XLWorkbook(template); diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs index 18778ca1..5b0935d2 100644 --- a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanDrillingExportService.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using AsbCloudApp.Data.ProcessMaps; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; +using AsbCloudApp.Requests.ExportOptions; using AsbCloudApp.Services; using AsbCloudInfrastructure.Services.ExcelServices.Templates; using AsbCloudInfrastructure.Services.ExcelServices.Templates.ProcessMapPlanTemplates; @@ -23,16 +24,17 @@ public class ProcessMapPlanDrillingExportService : ProcessMapPlanExportService

new ProcessMapPlanDrillingTemplate(); - protected override async Task BuildFileNameAsync(int idWell, CancellationToken token) + protected override async Task BuildFileNameAsync(WellRelatedExportRequest options, CancellationToken token) { - var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); + var caption = await wellService.GetWellCaptionByIdAsync(options.IdWell, token); return $"{caption}_РТК_План_бурение.xlsx"; } - protected override async Task> GetProcessMapPlanAsync(int idWell, CancellationToken token) + protected override async Task> GetDtosAsync(WellRelatedExportRequest options, + CancellationToken token) { - var dtos = await base.GetProcessMapPlanAsync(idWell, token); + var dtos = await base.GetDtosAsync(options, token); var dtosWithMode = dtos.Select(dto => { dto.Mode = dto.IdMode switch @@ -41,7 +43,7 @@ public class ProcessMapPlanDrillingExportService : ProcessMapPlanExportService

"Слайд", _ => throw new ArgumentOutOfRangeException() }; - + return dto; }); diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs index 6d684946..458877d1 100644 --- a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanExportService.cs @@ -1,17 +1,16 @@ using System.Collections.Generic; -using System.IO; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; +using AsbCloudApp.Requests.ExportOptions; using AsbCloudApp.Services; using AsbCloudInfrastructure.Services.ExcelServices; namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Export; -public abstract class ProcessMapPlanExportService : ExportExcelService, - IProcessMapPlanExportService +public abstract class ProcessMapPlanExportService : ExportExcelService where TDto : ChangeLogAbstract { protected readonly IWellService wellService; @@ -24,21 +23,10 @@ public abstract class ProcessMapPlanExportService : ExportExcelService ExportAsync(int idWell, CancellationToken token) + + protected override async Task> GetDtosAsync(WellRelatedExportRequest options, CancellationToken token) { - var dtos = await GetProcessMapPlanAsync(idWell, token); - - var fileName = await BuildFileNameAsync(idWell, token); - var file = Export(dtos); - return (fileName, file); - } - - protected abstract Task BuildFileNameAsync(int idWell, CancellationToken token); - - protected virtual async Task> GetProcessMapPlanAsync(int idWell, CancellationToken token) - { - var request = new ProcessMapPlanBaseRequestWithWell(idWell); + var request = new ProcessMapPlanBaseRequestWithWell(options.IdWell); var dtos = await processMapPlanRepository.Get(request, token); return dtos; } diff --git a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanReamExportService.cs b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanReamExportService.cs index b2452172..c3dc5d69 100644 --- a/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanReamExportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMapPlan/Export/ProcessMapPlanReamExportService.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using AsbCloudApp.Data.ProcessMaps; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; +using AsbCloudApp.Requests.ExportOptions; using AsbCloudApp.Services; using AsbCloudInfrastructure.Services.ExcelServices.Templates; using AsbCloudInfrastructure.Services.ExcelServices.Templates.ProcessMapPlanTemplates; @@ -19,10 +20,10 @@ public class ProcessMapPlanReamExportService : ProcessMapPlanExportService BuildFileNameAsync(int idWell, CancellationToken token) + + protected override async Task BuildFileNameAsync(WellRelatedExportRequest options, CancellationToken token) { - var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); + var caption = await wellService.GetWellCaptionByIdAsync(options.IdWell, token); return $"{caption}_РТК_План_проработка.xlsx"; } diff --git a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryExportService.cs b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryExportService.cs index 489b15f4..fe78b6b5 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryExportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryExportService.cs @@ -1,15 +1,15 @@ -using AsbCloudApp.Data.Trajectory; +using System.Collections.Generic; +using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Repositories; using AsbCloudApp.Services; -using System.IO; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Requests.ExportOptions; using AsbCloudInfrastructure.Services.ExcelServices; namespace AsbCloudInfrastructure.Services.Trajectory.Export; -public abstract class TrajectoryExportService : ExportExcelService, - ITrajectoryExportService +public abstract class TrajectoryExportService : ExportExcelService where TDto : TrajectoryGeoDto { protected readonly IWellService wellService; @@ -22,14 +22,6 @@ public abstract class TrajectoryExportService : ExportExcelService, this.trajectoryRepository = trajectoryRepository; } - public async Task<(string FileName, Stream File)> ExportAsync(int idWell, CancellationToken token) - { - var dtos = await trajectoryRepository.GetAsync(idWell, token); - - var fileName = await BuildFileNameAsync(idWell, token); - var file = Export(dtos); - return (fileName, file); - } - - protected abstract Task BuildFileNameAsync(int idWell, CancellationToken token); + protected override Task> GetDtosAsync(WellRelatedExportRequest options, CancellationToken token) => + trajectoryRepository.GetAsync(options.IdWell, token); } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactManualExportService.cs b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactManualExportService.cs index f1ccbc89..40b7d1c8 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactManualExportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactManualExportService.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Repositories; +using AsbCloudApp.Requests.ExportOptions; using AsbCloudApp.Services; using AsbCloudInfrastructure.Services.ExcelServices.Templates; using AsbCloudInfrastructure.Services.ExcelServices.Templates.TrajectoryTemplates; @@ -17,10 +18,10 @@ public class TrajectoryFactManualExportService : TrajectoryExportService new TrajectoryFactManualTemplate(); - - protected override async Task BuildFileNameAsync(int idWell, CancellationToken token) + + protected override async Task BuildFileNameAsync(WellRelatedExportRequest options, CancellationToken token) { - var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); + var caption = await wellService.GetWellCaptionByIdAsync(options.IdWell, token); return $"{caption}_Фактическая_траектория.xlsx"; } diff --git a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactNnbExportService.cs b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactNnbExportService.cs index 2bab0783..3b3206f5 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactNnbExportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryFactNnbExportService.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Repositories; +using AsbCloudApp.Requests.ExportOptions; using AsbCloudApp.Services; using AsbCloudInfrastructure.Services.ExcelServices.Templates; using AsbCloudInfrastructure.Services.ExcelServices.Templates.TrajectoryTemplates; @@ -18,9 +19,9 @@ public class TrajectoryFactNnbExportService : TrajectoryExportService new TrajectoryFactNnbTemplate(); - protected override async Task BuildFileNameAsync(int idWell, CancellationToken token) + protected override async Task BuildFileNameAsync(WellRelatedExportRequest options, CancellationToken token) { - var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); + var caption = await wellService.GetWellCaptionByIdAsync(options.IdWell, token); return $"{caption}_Траектория_ННБ.xlsx"; } diff --git a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryPlanExportService.cs b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryPlanExportService.cs index 5a931939..37bce068 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryPlanExportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Export/TrajectoryPlanExportService.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using AsbCloudApp.Data.Trajectory; using AsbCloudApp.Repositories; +using AsbCloudApp.Requests.ExportOptions; using AsbCloudApp.Services; using AsbCloudInfrastructure.Services.ExcelServices.Templates; using AsbCloudInfrastructure.Services.ExcelServices.Templates.TrajectoryTemplates; @@ -10,17 +11,17 @@ namespace AsbCloudInfrastructure.Services.Trajectory.Export; public class TrajectoryPlanExportService : TrajectoryExportService { - public TrajectoryPlanExportService(IWellService wellService, + public TrajectoryPlanExportService(IWellService wellService, ITrajectoryEditableRepository trajectoryRepository) : base(wellService, trajectoryRepository) { } protected override ITemplateParameters TemplateParameters => new TrajectoryPlanTemplate(); - - protected override async Task BuildFileNameAsync(int idWell, CancellationToken token) + + protected override async Task BuildFileNameAsync(WellRelatedExportRequest options, CancellationToken token) { - var caption = await wellService.GetWellCaptionByIdAsync(idWell, token); + var caption = await wellService.GetWellCaptionByIdAsync(options.IdWell, token); return $"{caption}_Плановая_Траектория.xlsx"; } diff --git a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs index 1c026185..34d2077c 100644 --- a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs +++ b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs @@ -6,12 +6,15 @@ using NSubstitute; using System; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Requests.ExportOptions; using Xunit; namespace AsbCloudWebApi.Tests.Services.Trajectory { public class TrajectoryExportTest { + private const int idWell = 4; + private IWellService wellService; private readonly ITrajectoryEditableRepository trajectoryPlanRepository; private readonly TrajectoryPlanExportService trajectoryPlanExportService; @@ -22,8 +25,6 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory private readonly ITrajectoryNnbRepository trajectoryFactNnbRepository; private readonly TrajectoryFactNnbExportService trajectoryFactNnbExportService; - private readonly int idWell = 4; - private readonly TrajectoryGeoPlanDto[] trajectoryPlanRows = new TrajectoryGeoPlanDto[2] { new TrajectoryGeoPlanDto() { Id = 1, @@ -80,6 +81,8 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory }, }; + private readonly WellRelatedExportRequest exportOptions = new(idWell); + public TrajectoryExportTest() { wellService = Substitute.For(); @@ -98,10 +101,9 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory { trajectoryPlanRepository.GetAsync(idWell, CancellationToken.None) .Returns(trajectoryPlanRows); - - var stream = await trajectoryPlanExportService.ExportAsync(idWell, CancellationToken.None); + + var stream = await trajectoryPlanExportService.ExportAsync(exportOptions, CancellationToken.None); Assert.True(stream.File.Length > 0); - } [Fact] @@ -109,8 +111,8 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory { trajectoryFactManualReposirory.GetAsync(idWell, CancellationToken.None) .Returns(trajectoryFactRows); - - var stream = await trajectoryFactManualExportService.ExportAsync(idWell, CancellationToken.None); + + var stream = await trajectoryFactManualExportService.ExportAsync(exportOptions, CancellationToken.None); Assert.True(stream.File.Length > 0); } @@ -119,8 +121,8 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory { trajectoryFactNnbRepository.GetAsync(idWell, CancellationToken.None) .Returns(trajectoryFactRows); - - var stream = await trajectoryFactNnbExportService.ExportAsync(idWell, CancellationToken.None); + + var stream = await trajectoryFactNnbExportService.ExportAsync(exportOptions, CancellationToken.None); Assert.True(stream.File.Length > 0); } } diff --git a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs index c3afebb3..a7d1763e 100644 --- a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs @@ -15,6 +15,7 @@ using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; using AsbCloudApp.Data.ProcessMaps; using System.ComponentModel.DataAnnotations; +using AsbCloudApp.Requests.ExportOptions; namespace AsbCloudWebApi.Controllers.ProcessMaps; @@ -30,12 +31,12 @@ public abstract class ProcessMapPlanBaseController : ControllerBase private readonly IChangeLogRepository repository; private readonly IWellService wellService; private readonly IParserService parserService; - private readonly IProcessMapPlanExportService processMapPlanExportService; + private readonly IExportService processMapPlanExportService; protected ProcessMapPlanBaseController(IChangeLogRepository repository, IWellService wellService, IParserService parserService, - IProcessMapPlanExportService processMapPlanExportService) + IExportService processMapPlanExportService) { this.repository = repository; this.wellService = wellService; @@ -280,7 +281,8 @@ public abstract class ProcessMapPlanBaseController : ControllerBase [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ExportAsync([FromRoute] int idWell, CancellationToken token) { - var (fileName, file) = await processMapPlanExportService.ExportAsync(idWell, token); + var exportOptions = new WellRelatedExportRequest(idWell); + var (fileName, file) = await processMapPlanExportService.ExportAsync(exportOptions, token); return File(file, "application/octet-stream", fileName); } diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs index 6311d34a..a4521ef8 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs @@ -7,6 +7,8 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Requests.ExportOptions; +using AsbCloudInfrastructure.Services.Trajectory.Export; namespace AsbCloudWebApi.Controllers.Trajectory { @@ -22,11 +24,11 @@ namespace AsbCloudWebApi.Controllers.Trajectory protected abstract string TemplateFileName { get; } private readonly IWellService wellService; - private readonly ITrajectoryExportService trajectoryExportService; + private readonly TrajectoryExportService trajectoryExportService; private readonly ITrajectoryRepository trajectoryRepository; protected TrajectoryController(IWellService wellService, - ITrajectoryExportService trajectoryExportService, + TrajectoryExportService trajectoryExportService, ITrajectoryRepository trajectoryRepository) { this.trajectoryExportService = trajectoryExportService; @@ -48,8 +50,9 @@ namespace AsbCloudWebApi.Controllers.Trajectory if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); - - var (fileName, file) = await trajectoryExportService.ExportAsync(idWell, token); + + var exportOptions = new WellRelatedExportRequest(idWell); + var (fileName, file) = await trajectoryExportService.ExportAsync(exportOptions, token); return File(file, "application/octet-stream", fileName); } diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs index a014e1bc..56a08c1e 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; +using AsbCloudInfrastructure.Services.Trajectory.Export; namespace AsbCloudWebApi.Controllers.Trajectory { @@ -27,7 +28,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory protected TrajectoryEditableController(IWellService wellService, IParserService parserService, - ITrajectoryExportService trajectoryExportService, + TrajectoryExportService trajectoryExportService, ITrajectoryEditableRepository trajectoryRepository) : base(wellService, trajectoryExportService, trajectoryRepository) { From 26bb23f7da07fd36c052e8dbca6f0912e749fc83 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Fri, 15 Mar 2024 14:33:14 +0500 Subject: [PATCH 27/27] ProcessMapPlanBaseDto remove validation of IdWell --- AsbCloudApp/Data/ProcessMaps/ProcessMapPlanBaseDto.cs | 1 - .../ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanBaseDto.cs b/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanBaseDto.cs index 0abc05b3..9ae3c6ff 100644 --- a/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanBaseDto.cs +++ b/AsbCloudApp/Data/ProcessMaps/ProcessMapPlanBaseDto.cs @@ -10,7 +10,6 @@ public abstract class ProcessMapPlanBaseDto : ChangeLogAbstract, IId, IWellRelat ///

/// Id скважины /// - [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] public int IdWell { get; set; } /// diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs index 6f21bd0b..b742ad02 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs @@ -202,6 +202,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest entry.State = EntityState.Detached; var dtoUpdate = dto.Adapt(); + dtoUpdate.IdWell = 0; dtoUpdate.Id = entry.Entity.Id; dtoUpdate.Comment = "nebuchadnezzar"; dtoUpdate.DeltaPressureLimitMax++; @@ -263,6 +264,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest var expected = dtoUpdate.Adapt(); var excludeProps = new[] { nameof(ProcessMapPlanDrilling.Id), + nameof(ProcessMapPlanDrilling.IdWell), nameof(ProcessMapPlanDrilling.Author), nameof(ProcessMapPlanDrilling.IdAuthor), nameof(ProcessMapPlanDrilling.Editor),