From f88381353e8b2880dd6011e0cfee9f66265e67b4 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Thu, 7 Mar 2024 13:38:40 +0500 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B9?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BE=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=B7?= =?UTF-8?q?=D0=B8=D1=82=D0=BD=D0=BE=D0=B9=20=D1=81=D0=BA=D0=B2=D0=B0=D0=B6?= =?UTF-8?q?=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); + } + } + +}