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;
+ }
}
}