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.Data.WellOperation; 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() { DepthStart = 50, DurationHours = 1, IdCategory = 5096, IdWell = 55, IdWellSectionType = 2, OperationCategoryName = "Шаблонирование перед спуском", WellSectionTypeCaption = "Направление" }, new() { DepthStart = 84, DurationHours = 1, IdCategory = 5008, IdWell = 64, IdWellSectionType = 2, OperationCategoryName = "Шаблонировка во время бурения", WellSectionTypeCaption = "Направление" } }; private readonly static IEnumerable wellOperations2 = new List() { new() { DepthStart = 10, DurationHours = 1.5, IdCategory = 5003, IdWell = 55, IdWellSectionType = 2, OperationCategoryName = "Бурение ротором", WellSectionTypeCaption = "Направление" }, new() { DepthStart = 20, DurationHours = 3.5, IdCategory = 5003, IdWell = 64, IdWellSectionType = 2, OperationCategoryName = "Бурение ротором", WellSectionTypeCaption = "Направление" } }; private readonly static IEnumerable wellOperations3 = new List() { new() { DepthStart = 1372, DurationHours = 3, IdCategory = 5036, IdWell = 55, IdWellSectionType = 3, OperationCategoryName = "Промывка", WellSectionTypeCaption = "Кондуктор" }, new() { DepthStart = 1435, DurationHours = 4, IdCategory = 5036, IdWell = 64, IdWellSectionType = 3, OperationCategoryName = "Промывка", WellSectionTypeCaption = "Кондуктор" } }; private readonly static IEnumerable wellOperations4 = new List() { new() { DepthStart = 1000, DurationHours = 10, IdCategory = 5012, IdWell = 55, IdWellSectionType = 31, OperationCategoryName = "Подъем инструмента", WellSectionTypeCaption = "Техническая колонна" }, new() { DepthStart = 500, DurationHours = 5, IdCategory = 5083, IdWell = 55, IdWellSectionType = 31, OperationCategoryName = "Проработка принудительная", WellSectionTypeCaption = "Техническая колонна" }, new() { 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); } /// /// На вход подаются 2 операции с одинаковыми секциями (id = 2), но разными категориями (ids = 5096, 5008) и ключами скважин (ids = 55, 64) /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная /// Операция должна иметь категорию 5013 для всех трех скважин /// /// [Fact] public async Task GetAsync_return_composite_and_others_with_category_5013() { // 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); } /// /// На вход подаются 2 операции с одинаковыми секциями (id = 2) и категориями (id = 5003), но разными ключами скважин (ids = 55, 64) /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная /// Операция композитной скважины должна содержать данные той операции, которая содержит минимальный duration_hours /// /// [Fact] public async Task GetAsync_return_composite_with_minimum_depth_start() { // 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); } /// /// На вход подаются 2 операции с одинаковыми секциями (id = 3) и категориями (id = 5036), но разными ключами скважин (ids = 55, 64) /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная /// Операция композитной скважины должна содержать данные той операции, которая содержит минимальный duration_hours /// /// [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); } /// /// На вход подаются 3 операции с одинаковыми секциями (id = 31), но разными категориями (ids = 5012, 5083) и ключами скважин (ids = 55, 64) /// Метод возвращает список из одной операции в разрезе 3-х скважин: 2 текущие скважины и одна композитная /// Операция композитной скважины должна содержать: /// данные той операции, которая содержит минимальный duration_hours /// категорию с ключом 5013 /// Операции по скважине с ключом 55 должны объединиться в одну, /// при этом их длительность складывается, а depth_start берется минимальный из двух /// /// [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 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); } /// /// На вход подаются список разных операций с разными ключами скважин (ids = 55, 64) /// Метод возвращает список из 4-х операций в разрезе 3-х скважин: 2 текущие скважины и одна композитная /// Операция композитной скважины должна содержать глубину забоя = 1372 /// /// [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); } } }