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