diff --git a/AsbCloudApp/Data/WellCompositeOperationDto.cs b/AsbCloudApp/Data/WellCompositeOperationDto.cs new file mode 100644 index 00000000..ce8e44f9 --- /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 IEnumerable WellOperationsComposite { get; set; } = null!; + + /// + /// Список операций, на основе которых были рассчитаны операции по композитной скважине + /// + public IEnumerable WellCompositeSourceOperations { get; set; } = null!; + } +} diff --git a/AsbCloudApp/Data/WellCompositeOperationSourceDto.cs b/AsbCloudApp/Data/WellCompositeOperationSourceDto.cs new file mode 100644 index 00000000..04ec7b3b --- /dev/null +++ b/AsbCloudApp/Data/WellCompositeOperationSourceDto.cs @@ -0,0 +1,21 @@ +using AsbCloudApp.Data.WellOperation; +using System.Collections.Generic; + +namespace AsbCloudApp.Data +{ + /// + /// Операции по скважине, по которой рассчитывается композитная скважина + /// + public class WellCompositeOperationSourceDto + { + /// + /// Скважина + /// + public WellDto Well { get; set; } = null!; + + /// + /// Операции по скважине + /// + public IEnumerable Operations { get; set; } = null!; + } +} 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..d1312e6e 100644 --- a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs +++ b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs @@ -1,220 +1,242 @@ using AsbCloudApp.Data; +using AsbCloudApp.Data.WellOperation; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; 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; -using AsbCloudApp.Data.WellOperation; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + +public class WellCompositeOperationService : IWellCompositeOperationService { - public class WellCompositeOperationService : IWellCompositeOperationService + private readonly ICrudRepository wellSectionTypeRepository; + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; + private readonly IWellOperationRepository wellOperationRepository; + private readonly IWellService wellService; + + /// + /// Тип секции "Транспортный стол" + /// + 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 HashSet<(int IdSectionType, int IdCategory)> WellSectionTypesWithCategories = new HashSet<(int IdSectionType, int IdCategory)>() { - private ICrudRepository wellSectionTypeRepository; - private IWellOperationCategoryRepository wellOperationCategoryRepository; - private IWellOperationRepository wellOperationRepository; + { (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) } + }; - /// - /// Тип секции "Транспортный стол" - /// - private const int wellSectionTransportTable = 5; + public WellCompositeOperationService( + ICrudRepository wellSectionTypeRepository, + IWellOperationCategoryRepository wellOperationCategoryRepository, + IWellOperationRepository wellOperationRepository, + IWellService wellService) + { + this.wellSectionTypeRepository = wellSectionTypeRepository; + this.wellOperationCategoryRepository = wellOperationCategoryRepository; + this.wellOperationRepository = wellOperationRepository; + this.wellService = wellService; + } - /// - /// Тип секции "Эксплуатационная колонна" - /// - private const int wellSectionProductionString = 4; + public async Task GetAsync(IEnumerable idsWells, CancellationToken token) + { + var sections = await wellSectionTypeRepository.GetAllAsync(token); + var sectionsDict = sections.ToDictionary(s => s.Id, s => s.Caption); + var categories = wellOperationCategoryRepository.Get(true); + var categoriesDict = categories.ToDictionary(s => s.Id, s => s.Name); - /// - /// набор настроек для замены одной категории секции на другую - /// - 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 } + var wells = await wellService.GetAsync(new WellRequest { Ids = idsWells }, token); + var wellsDict = wells.ToDictionary(w => w.Id); + + var idsWellSectionTypes = WellSectionTypesWithCategories.Select(t => t.IdSectionType).Distinct(); + var usedCategories = WellSectionTypesWithCategories.Select(c => c.IdCategory).Distinct(); + + var wellOperationRequest = new WellOperationRequest(idsWells) + { + OperationCategoryIds = usedCategories, + SectionTypeIds = idsWellSectionTypes, + OperationType = WellOperation.IdOperationTypeFact }; + var operations = await wellOperationRepository.GetAsync(wellOperationRequest, token); - private HashSet<(int IdSectionType, int IdCategory)> WellSectionTypesWithCategories = new HashSet<(int IdSectionType, int IdCategory)>() + var operationsForComposite = operations.Select(o => CreateCompositeOperation(o, sectionsDict, categoriesDict)); + + var wellOperationsWithComposite = new List>(); + var compositeDepth = 0d; + var compositeDay = 0d; + var result = new WellCompositeOperationDto(); + + var compositeOperations = new List(); + foreach ((int IdSection, int IdCategory) in WellSectionTypesWithCategories) { - { (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) } - }; + var filteredByTemplate = operationsForComposite + .Where(o => o.IdWellSectionType == IdSection) + .Where(o => o.IdCategory == IdCategory); + if (!filteredByTemplate.Any()) + continue; + var groupedByWell = filteredByTemplate.GroupBy(o => o.IdWell); - public WellCompositeOperationService( - ICrudRepository wellSectionTypeRepository, - IWellOperationCategoryRepository wellOperationCategoryRepository, - IWellOperationRepository wellOperationRepository) - { - this.wellSectionTypeRepository = wellSectionTypeRepository; - this.wellOperationCategoryRepository = wellOperationCategoryRepository; - this.wellOperationRepository = wellOperationRepository; + var aggreagtedByWell = groupedByWell.Select(g => new WellOperationDto + { + 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 compositeOperation = aggreagtedByWell.OrderBy(o => o.DurationHours). + ThenByDescending(o => o.DepthStart) + .First(); + + compositeOperation.IdWell = 0; + + if (compositeDepth > compositeOperation.DepthStart) + compositeOperation.DepthStart = compositeDepth; + compositeDepth = compositeOperation.DepthStart; + + compositeDay += compositeOperation.DurationHours; + compositeOperation.Day = compositeDay; + + compositeOperations.Add(compositeOperation); } - public async Task>> GetAsync(IEnumerable idsWells, CancellationToken token) + var groupedByWellOperations = operations + .GroupBy(o => o.IdWell) + .ToDictionary(o => o.Key, o => o.ToArray()) + .Select(o => new WellCompositeOperationSourceDto() + { + Operations = o.Value, + Well = wellsDict[o.Key], + }); + + result.WellOperationsComposite = compositeOperations; + result.WellCompositeSourceOperations = groupedByWellOperations; + + return result; + } + + private static WellOperationDto CreateCompositeOperation( + WellOperationDto dto, + IDictionary sectionTypes, + IDictionary operationCategories) + { + var newDto = dto.Adapt(); + if (newDto.IdWellSectionType == wellSectionTransportTable) { - var sections = await wellSectionTypeRepository.GetAllAsync(token); - var sectionsDict = sections.ToDictionary(s => s.Id, s => s.Caption); - - var categories = wellOperationCategoryRepository.Get(true); - var categoriesDict = categories.ToDictionary(s => s.Id, s => s.Name); - - var idsWellSectionTypes = WellSectionTypesWithCategories.Select(t => t.IdSectionType).Distinct(); - var usedCategories = WellSectionTypesWithCategories.Select(c => c.IdCategory).Distinct(); - - var wellOperationRequest = new WellOperationRequest(idsWells) - { - OperationCategoryIds = usedCategories, - SectionTypeIds = idsWellSectionTypes, - OperationType = WellOperation.IdOperationTypeFact - }; - var operations = await wellOperationRepository.GetAsync(wellOperationRequest, token); - - var renamedOperations = operations.Select(o => UpdateIdWellSectionAndIdCategory(o, sectionsDict, categoriesDict)); - - var wellOperationsWithComposite = new List>(); - var compositeDepth = 0d; - foreach ((int IdSection, int IdCategory) in WellSectionTypesWithCategories) - { - var filteredByTemplate = renamedOperations - .Where(o => o.IdWellSectionType == IdSection) - .Where(o => o.IdCategory == IdCategory); - - if (!filteredByTemplate.Any()) - continue; - - var groupedByWell = filteredByTemplate.GroupBy(o => o.IdWell); - - var aggreagtedByWell = groupedByWell.Select(g => new WellOperationDto - { - 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; + newDto.IdWellSectionType = wellSectionProductionString; + newDto.WellSectionTypeCaption = sectionTypes[newDto.IdWellSectionType]; } - private static WellOperationDto UpdateIdWellSectionAndIdCategory( - WellOperationDto dto, - IDictionary sectionTypes, - IDictionary operationCategories) + if ((SettingsForSectionCategoryChange.TryGetValue((newDto.IdWellSectionType, newDto.IdCategory), out int newIdCategory))) { - if (dto.IdWellSectionType == wellSectionTransportTable) - { - dto.IdWellSectionType = wellSectionProductionString; - dto.WellSectionTypeCaption = sectionTypes[dto.IdWellSectionType]; - } - - if ((SettingsForSectionCategoryChange.TryGetValue((dto.IdWellSectionType, dto.IdCategory), out int newIdCategory))) - { - dto.IdCategory = newIdCategory; - dto.OperationCategoryName = operationCategories[dto.IdCategory] ?? string.Empty; - } - - return dto; + newDto.IdCategory = newIdCategory; + newDto.OperationCategoryName = operationCategories[newDto.IdCategory] ?? string.Empty; } + + return newDto; } } diff --git a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs index 4018417c..14224abd 100644 --- a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs @@ -1,22 +1,16 @@ -using AsbCloudApp.Requests; -using AsbCloudDb.Model; -using AsbCloudInfrastructure.Repository; -using AsbCloudInfrastructure.Services.ProcessMaps.Report; +using AsbCloudApp.Data; +using AsbCloudApp.Data.WellOperation; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; 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.Data.WellOperation; -using AsbCloudApp.Services; namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation { @@ -30,8 +24,10 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation = Substitute.For(); private IWellOperationRepository wellOperationRepository = Substitute.For(); + private IWellService wellService + = Substitute.For(); + - private readonly static IEnumerable operationCategories = new List() { @@ -61,7 +57,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation IdWell = 55, IdWellSectionType = 2, OperationCategoryName = "Шаблонирование перед спуском", - WellSectionTypeCaption = "Направление" + WellSectionTypeCaption = "Направление" }, new() { @@ -167,15 +163,16 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation .Returns(operationCategories); service = new WellCompositeOperationService( - wellSectionTypeRepository, + wellSectionTypeRepository, wellOperationCategoryRepository, - wellOperationRepository); + wellOperationRepository, + wellService); } /// /// На вход подаются 2 операции с одинаковыми секциями (id = 2), но разными категориями (ids = 5096, 5008) и ключами скважин (ids = 55, 64) - /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная - /// Операция должна иметь категорию 5013 для всех трех скважин + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин + /// Композитная операция должна иметь категорию 5013 /// /// [Fact] @@ -185,31 +182,25 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) .Returns(wellOperations1); - var idsWell = new List() { 55, 64 }; + 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 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 +217,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 +243,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 +271,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 +303,11 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation var result = await service.GetAsync(idsWell, CancellationToken.None); // assert - Assert.Equal(4, result.Count()); + var wellOperationsCount = result.WellCompositeSourceOperations + .SelectMany(o => o.Operations).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)