From 9ead473975ca3d775be14075beb99f47d0c69352 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Wed, 17 Apr 2024 09:44:30 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D1=81=D1=87=D0=B5=D1=82=20=D0=B4?= =?UTF-8?q?=D0=BD=D1=8F=20(=D0=B4=D0=BB=D1=8F=20=D0=B3=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D0=B7=D0=BE=D0=BD=D1=82=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=B9=20?= =?UTF-8?q?=D0=BE=D1=81=D0=B8=20=D0=B3=D1=80=D0=B0=D1=84=D0=B8=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2)=20=D0=B4=D0=BB=D1=8F=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B9=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D0=BD=D0=BE=D0=B9=20=D1=81=D0=BA=D0=B2=D0=B0=D0=B6=D0=B8?= =?UTF-8?q?=D0=BD=D1=8B=20+=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B0=D0=BD=D0=B0=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D1=8C,=20?= =?UTF-8?q?=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0=D1=89=D0=B0=D1=8E=D1=89?= =?UTF-8?q?=D0=B0=D1=8F=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5=20(=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D1=8F=20WellCompositeOperationDto)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/WellCompositeOperationDto.cs | 26 ++++++ .../IWellCompositeOperationService.cs | 6 +- .../Services/WellCompositeOperationService.cs | 56 ++++++++----- .../WellCompositeOperationServiceTest.cs | 82 +++++++------------ .../WellCompositeOperationController.cs | 2 +- 5 files changed, 94 insertions(+), 78 deletions(-) create mode 100644 AsbCloudApp/Data/WellCompositeOperationDto.cs diff --git a/AsbCloudApp/Data/WellCompositeOperationDto.cs b/AsbCloudApp/Data/WellCompositeOperationDto.cs new file mode 100644 index 00000000..f6b98b4d --- /dev/null +++ b/AsbCloudApp/Data/WellCompositeOperationDto.cs @@ -0,0 +1,26 @@ +using AsbCloudApp.Data.WellOperation; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsbCloudApp.Data +{ + /// + /// Хранение операций по композитной скважине + /// и по скважинам, на основе которых была рассчитана композитная скважина + /// + public class WellCompositeOperationDto + { + /// + /// Список операций композитной скважины + /// + public List WellOperationsComposite { get; set; } = new(); + + /// + /// Список операций, сгруппированный по скважинам + /// + public Dictionary WellOperationsGroupedByWell { get; set; } = new(); + } +} diff --git a/AsbCloudApp/Services/IWellCompositeOperationService.cs b/AsbCloudApp/Services/IWellCompositeOperationService.cs index 96dbcf2b..f1af9865 100644 --- a/AsbCloudApp/Services/IWellCompositeOperationService.cs +++ b/AsbCloudApp/Services/IWellCompositeOperationService.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; +using AsbCloudApp.Data; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using AsbCloudApp.Data.WellOperation; namespace AsbCloudApp.Services { @@ -16,6 +16,6 @@ namespace AsbCloudApp.Services /// /// /// - Task>> GetAsync(IEnumerable idsWells, CancellationToken token); + Task GetAsync(IEnumerable idsWells, CancellationToken token); } } diff --git a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs index 8beb3c3e..79fb45ee 100644 --- a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs +++ b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data.WellOperation; +using Mapster; namespace AsbCloudInfrastructure.Services { @@ -134,7 +135,7 @@ namespace AsbCloudInfrastructure.Services this.wellOperationRepository = wellOperationRepository; } - public async Task>> GetAsync(IEnumerable idsWells, CancellationToken token) + public async Task GetAsync(IEnumerable idsWells, CancellationToken token) { var sections = await wellSectionTypeRepository.GetAllAsync(token); var sectionsDict = sections.ToDictionary(s => s.Id, s => s.Caption); @@ -153,13 +154,16 @@ namespace AsbCloudInfrastructure.Services }; var operations = await wellOperationRepository.GetAsync(wellOperationRequest, token); - var renamedOperations = operations.Select(o => UpdateIdWellSectionAndIdCategory(o, sectionsDict, categoriesDict)); + var operationsForComposite = operations.Select(o => CreateCompositeOperation(o, sectionsDict, categoriesDict)); var wellOperationsWithComposite = new List>(); var compositeDepth = 0d; + var result = new WellCompositeOperationDto(); + + var prevDay = 0.0; foreach ((int IdSection, int IdCategory) in WellSectionTypesWithCategories) { - var filteredByTemplate = renamedOperations + var filteredByTemplate = operationsForComposite .Where(o => o.IdWellSectionType == IdSection) .Where(o => o.IdCategory == IdCategory); @@ -179,42 +183,50 @@ namespace AsbCloudInfrastructure.Services WellSectionTypeCaption = g.First().WellSectionTypeCaption, }); - var composite = aggreagtedByWell.OrderBy(o => o.DurationHours). - ThenByDescending(o => o.DepthStart) - .First(); + var compositeOperation = aggreagtedByWell.OrderBy(o => o.DurationHours). + ThenByDescending(o => o.DepthStart) + .First(); - composite.IdWell = 0; - if (compositeDepth > composite.DepthStart) - composite.DepthStart = compositeDepth; + compositeOperation.IdWell = 0; + compositeOperation.Day = prevDay + compositeOperation.DurationHours; + + if (compositeDepth > compositeOperation.DepthStart) + compositeOperation.DepthStart = compositeDepth; - compositeDepth = composite.DepthStart; + compositeDepth = compositeOperation.DepthStart; - var resultItem = aggreagtedByWell.ToDictionary(o => o.IdWell); - resultItem.Add(0, composite); + result.WellOperationsComposite.Add(compositeOperation); - wellOperationsWithComposite.Add(resultItem); + prevDay = compositeOperation.Day; } - return wellOperationsWithComposite; + + var groupedByWellOperations = operations + .GroupBy(o => o.IdWell) + .ToDictionary(o => o.Key, o => o.ToArray()); + result.WellOperationsGroupedByWell = groupedByWellOperations; + + return result; } - private static WellOperationDto UpdateIdWellSectionAndIdCategory( + private static WellOperationDto CreateCompositeOperation( WellOperationDto dto, IDictionary sectionTypes, IDictionary operationCategories) { - if (dto.IdWellSectionType == wellSectionTransportTable) + var newDto = dto.Adapt(); + if (newDto.IdWellSectionType == wellSectionTransportTable) { - dto.IdWellSectionType = wellSectionProductionString; - dto.WellSectionTypeCaption = sectionTypes[dto.IdWellSectionType]; + newDto.IdWellSectionType = wellSectionProductionString; + newDto.WellSectionTypeCaption = sectionTypes[newDto.IdWellSectionType]; } - if ((SettingsForSectionCategoryChange.TryGetValue((dto.IdWellSectionType, dto.IdCategory), out int newIdCategory))) + if ((SettingsForSectionCategoryChange.TryGetValue((newDto.IdWellSectionType, newDto.IdCategory), out int newIdCategory))) { - dto.IdCategory = newIdCategory; - dto.OperationCategoryName = operationCategories[dto.IdCategory] ?? string.Empty; + newDto.IdCategory = newIdCategory; + newDto.OperationCategoryName = operationCategories[newDto.IdCategory] ?? string.Empty; } - return dto; + return newDto; } } } diff --git a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs index 4018417c..cf9904d0 100644 --- a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs @@ -174,8 +174,8 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation /// /// На вход подаются 2 операции с одинаковыми секциями (id = 2), но разными категориями (ids = 5096, 5008) и ключами скважин (ids = 55, 64) - /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная - /// Операция должна иметь категорию 5013 для всех трех скважин + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин + /// Композитная операция должна иметь категорию 5013 /// /// [Fact] @@ -191,25 +191,19 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation 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 compositeWellOperations = result.WellOperationsComposite; + Assert.Single(compositeWellOperations); + Assert.Equal(5013, compositeWellOperations.FirstOrDefault()?.IdCategory); + Assert.Equal(1, compositeWellOperations.FirstOrDefault()?.DurationHours); + Assert.Equal(84, compositeWellOperations.FirstOrDefault()?.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(); + var categoryName = compositeWellOperations.Select(o => o.OperationCategoryName).First(); Assert.Equal("Подъем КНБК", categoryName); } /// /// На вход подаются 2 операции с одинаковыми секциями (id = 2) и категориями (id = 5003), но разными ключами скважин (ids = 55, 64) - /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин /// Операция композитной скважины должна содержать данные той операции, которая содержит минимальный duration_hours /// /// @@ -226,16 +220,16 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation 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); + var compositeWellOperations = result.WellOperationsComposite; + Assert.Single (compositeWellOperations); + Assert.Equal(5003, compositeWellOperations.FirstOrDefault()!.IdCategory); + Assert.Equal(1.5, compositeWellOperations.FirstOrDefault()!.DurationHours); + Assert.Equal(10, compositeWellOperations.FirstOrDefault()!.DepthStart); } /// /// На вход подаются 2 операции с одинаковыми секциями (id = 3) и категориями (id = 5036), но разными ключами скважин (ids = 55, 64) - /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин /// Операция композитной скважины должна содержать данные той операции, которая содержит минимальный duration_hours /// /// @@ -252,21 +246,19 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation 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); + var compositeWellOperations = result.WellOperationsComposite; + Assert.Single(compositeWellOperations); + Assert.Equal(5036, compositeWellOperations.FirstOrDefault()!.IdCategory); + Assert.Equal(3, compositeWellOperations.FirstOrDefault()!.DurationHours); + Assert.Equal(1372, compositeWellOperations.FirstOrDefault()!.DepthStart); } /// /// На вход подаются 3 операции с одинаковыми секциями (id = 31), но разными категориями (ids = 5012, 5083) и ключами скважин (ids = 55, 64) - /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин /// Операция композитной скважины должна содержать: /// данные той операции, которая содержит минимальный duration_hours /// категорию с ключом 5013 - /// Операции по скважине с ключом 55 должны объединиться в одну, - /// при этом их длительность складывается, а depth_start берется минимальный из двух /// /// [Fact] @@ -282,30 +274,16 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation 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 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(5, compositeWellOperation.DurationHours); - Assert.Equal(600, compositeWellOperation.DepthStart); + var compositeWellOperations = result.WellOperationsComposite; + Assert.Single(compositeWellOperations); + Assert.Equal(5013, compositeWellOperations.FirstOrDefault()!.IdCategory); + Assert.Equal(5, compositeWellOperations.FirstOrDefault()!.DurationHours); + Assert.Equal(600, compositeWellOperations.FirstOrDefault()!.DepthStart); } /// /// На вход подаются список разных операций с разными ключами скважин (ids = 55, 64) - /// Метод возвращает список из 4-х операций в разрезе 3-х скважин: 2 текущие скважины и одна композитная + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин /// Операция композитной скважины должна содержать глубину забоя = 1372 /// /// @@ -328,10 +306,10 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation var result = await service.GetAsync(idsWell, CancellationToken.None); // assert - Assert.Equal(4, result.Count()); + var wellOperationsCount = result.WellOperationsGroupedByWell.SelectMany(v => v.Value).Count(); + Assert.Equal(wellOperations.Count(), wellOperationsCount); - var lastOperation = result.Last(); - var lastOperationComposite = lastOperation[0]; + var lastOperationComposite = result.WellOperationsComposite.Last(); Assert.Equal(1372, lastOperationComposite.DepthStart); } } diff --git a/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs b/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs index ab4555c0..964addae 100644 --- a/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs +++ b/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs @@ -25,7 +25,7 @@ namespace AsbCloudWebApi.Controllers } [HttpGet] - [ProducesResponseType(typeof(IList>), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(WellCompositeOperationDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetAsync([FromQuery] IEnumerable idsWells, CancellationToken token) { foreach (var idWell in idsWells)