From 3828c781299d5ac3b8bbf13b4b0d279c4043dc8c Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Mon, 11 Mar 2024 14:11:13 +0500 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0=D1=82?= =?UTF-8?q?=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; + } } }