diff --git a/AsbCloudApp/Data/StatWellDto.cs b/AsbCloudApp/Data/StatWellDto.cs index 92df13ef..59ffd3d7 100644 --- a/AsbCloudApp/Data/StatWellDto.cs +++ b/AsbCloudApp/Data/StatWellDto.cs @@ -53,8 +53,8 @@ namespace AsbCloudApp.Data public IEnumerable Companies { get; set; } = Enumerable.Empty(); /// - /// Отставание от ГГД, дней + /// Отставание от ГГД, проценты /// - public double TvdLagDays { get; set; } = 0; + public double? TvdLagPercent { get; set; } } } diff --git a/AsbCloudApp/Data/WellMapInfoDto.cs b/AsbCloudApp/Data/WellMapInfoDto.cs index 42a48534..242ecb6c 100644 --- a/AsbCloudApp/Data/WellMapInfoDto.cs +++ b/AsbCloudApp/Data/WellMapInfoDto.cs @@ -95,9 +95,8 @@ namespace AsbCloudApp.Data public PlanFactDto WellDepth { get; set; } = null!; /// - /// Отставание от ГГД, дни + /// Отставание от ГГД, проценты /// - public double TvdLagDays { get; set; } - + public double TvdLagPercent { get; set; } } } diff --git a/AsbCloudApp/Services/IWellService.cs b/AsbCloudApp/Services/IWellService.cs index a1df94f3..edea98ae 100644 --- a/AsbCloudApp/Services/IWellService.cs +++ b/AsbCloudApp/Services/IWellService.cs @@ -97,13 +97,6 @@ namespace AsbCloudApp.Services /// DatesRangeDto GetDatesRange(int idWell); - /// - /// Проверить задан ли у скважины часовой пояс и задать его если он не задан - /// - /// - /// - Task EnshureTimezonesIsSetAsync(CancellationToken token); - /// /// ВРЕМЕННЫЙ метод /// diff --git a/AsbCloudInfrastructure/Services/LimitingParameterBackgroundService.cs b/AsbCloudInfrastructure/Services/LimitingParameterBackgroundService.cs index fdcf0ec1..7c875e70 100644 --- a/AsbCloudInfrastructure/Services/LimitingParameterBackgroundService.cs +++ b/AsbCloudInfrastructure/Services/LimitingParameterBackgroundService.cs @@ -105,7 +105,7 @@ namespace AsbCloudInfrastructure.Services }; } - if (limitingLast.IdFeedRegulator != idLimiting) + if (limitingLast.IdFeedRegulator != idLimiting || limitingLast.DepthStart < wellDepth) { limitingParameters.Add(new LimitingParameter { IdTelemetry = idTelemetry, @@ -114,7 +114,7 @@ namespace AsbCloudInfrastructure.Services DateEnd = date, DepthStart = limitingLast.DepthStart, DepthEnd = wellDepth - }); + }); limitingLast = new LimitingParameter { diff --git a/AsbCloudInfrastructure/Services/LimitingParameterService.cs b/AsbCloudInfrastructure/Services/LimitingParameterService.cs index 78587efb..695321de 100644 --- a/AsbCloudInfrastructure/Services/LimitingParameterService.cs +++ b/AsbCloudInfrastructure/Services/LimitingParameterService.cs @@ -45,13 +45,8 @@ namespace AsbCloudInfrastructure.Services { var trimData = TrimLimitingParameters(item, request).ToArray(); - //TODO: временный фикс, нужно избежать отрицательных значений в ограничивающих параметрах. - //Проблема возникает при при формировании LimitingParameter в LimitingParameterCalcWorkFactory. - //Начальная глубина ограничивающего параметра не может быть больше конечной. - var allItemDepths = trimData.Where(x => x.DepthStart < x.DepthEnd) - .Sum(x => x.DepthEnd - x.DepthStart); - var allItemDates = trimData.Where(x => x.DepthStart < x.DepthEnd) - .Sum(x => (x.DateEnd - x.DateStart).TotalMinutes); + var allItemDepths = trimData.Sum(x => x.DepthEnd - x.DepthStart); + var allItemDates = trimData.Sum(x => (x.DateEnd - x.DateStart).TotalMinutes); result.Add(new LimitingParameterDto { diff --git a/AsbCloudInfrastructure/Services/WellInfoService.cs b/AsbCloudInfrastructure/Services/WellInfoService.cs index 4f92afe9..7066ef22 100644 --- a/AsbCloudInfrastructure/Services/WellInfoService.cs +++ b/AsbCloudInfrastructure/Services/WellInfoService.cs @@ -138,8 +138,7 @@ namespace AsbCloudInfrastructure.Services wellMapInfo.FirstFactOperationDateStart = wellOperationsStat?.Total.Fact?.Start ?? wellOperationsStat?.Total.Plan?.Start; - wellMapInfo.LastPredictOperationDateEnd = wellOperationsStat?.Total.Plan?.End? - .AddDays(wellOperationsStat?.TvdLagDays ?? 0d); + wellMapInfo.LastPredictOperationDateEnd = wellOperationsStat?.Total.Plan?.End; wellMapInfo.WellDepth = new() { @@ -163,7 +162,7 @@ namespace AsbCloudInfrastructure.Services wellMapInfo.SaubUsage = wellSubsystemStat?.SubsystemAKB?.KUsage ?? 0d; wellMapInfo.SpinUsage = wellSubsystemStat?.SubsystemSpinMaster?.KUsage ?? 0d; wellMapInfo.TorqueKUsage = wellSubsystemStat?.SubsystemTorqueMaster?.KUsage ?? 0d; - wellMapInfo.TvdLagDays = wellOperationsStat?.TvdLagDays ?? 0d; + wellMapInfo.TvdLagPercent = wellOperationsStat?.TvdLagPercent ?? 0d; wellMapInfo.IdsCompanies = well.Companies.Select(c => c.Id); return wellMapInfo; diff --git a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs index 2757dbfd..e3c63e04 100644 --- a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs @@ -9,539 +9,576 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.SAUB; +using AsbCloudInfrastructure.Services.SAUB; -namespace AsbCloudInfrastructure.Services.WellOperationService +namespace AsbCloudInfrastructure.Services.WellOperationService; + +public class OperationsStatService : IOperationsStatService { + private readonly IAsbCloudDbContext db; + private readonly IMemoryCache memoryCache; + private readonly IWellService wellService; + private readonly TelemetryDataCache telemetryDataCache; - public class OperationsStatService : IOperationsStatService + public OperationsStatService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService, + TelemetryDataCache telemetryDataCache) { - private readonly IAsbCloudDbContext db; - private readonly IMemoryCache memoryCache; - private readonly IWellService wellService; + this.db = db; + this.memoryCache = memoryCache; + this.wellService = wellService; + this.telemetryDataCache = telemetryDataCache; + } - public OperationsStatService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService) + public async Task GetOrDefaultStatClusterAsync(int idCluster, int idCompany, CancellationToken token) + { + var cluster = (await memoryCache + .GetOrCreateBasicAsync(db.Set(), token)) + .FirstOrDefault(c => c.Id == idCluster); + + if (cluster is null) + return null; + + var allWellsByCompany = await wellService.GetAsync(new() { IdCompany = idCompany }, token).ConfigureAwait(false); + + var idWellsByCompany = allWellsByCompany.Select(w => w.Id).Distinct(); + + var wells = await db.Wells + .Include(w => w.WellOperations) + .Where(o => o.IdCluster == idCluster) + .Where(w => idWellsByCompany.Contains(w.Id)) + .Select(w => w.Id) + .ToListAsync(token); + + var statsWells = await GetWellsStatAsync(wells, token).ConfigureAwait(false); + + var statClusterDto = new StatClusterDto { - this.db = db; - this.memoryCache = memoryCache; - this.wellService = wellService; - } - - public async Task GetOrDefaultStatClusterAsync(int idCluster, int idCompany, CancellationToken token) - { - var cluster = (await memoryCache - .GetOrCreateBasicAsync(db.Set(), token)) - .FirstOrDefault(c => c.Id == idCluster); - - if (cluster is null) - return null; - - var allWellsByCompany = await wellService.GetAsync(new() { IdCompany = idCompany }, token).ConfigureAwait(false); - - var idWellsByCompany = allWellsByCompany.Select(w => w.Id).Distinct(); - - var wells = await db.Wells - .Include(w => w.WellOperations) - .Where(o => o.IdCluster == idCluster) - .Where(w => idWellsByCompany.Contains(w.Id)) - .Select(w => w.Id) - .ToListAsync(token); - - var statsWells = await GetWellsStatAsync(wells, token).ConfigureAwait(false); - - var statClusterDto = new StatClusterDto - { - Id = idCluster, - Caption = cluster.Caption, - StatsWells = statsWells, - }; - return statClusterDto; - } - - public async Task> GetWellsStatAsync(IEnumerable idWells, CancellationToken token) - { - var wells = await db.Wells - .Include(w => w.WellOperations) - .Where(w => idWells.Contains(w.Id)) - .AsNoTracking() - .ToListAsync(token); - - var statsWells = new List(wells.Count); - - foreach (var well in wells) - { - var statWellDto = await CalcWellStatAsync(well, token); - statsWells.Add(statWellDto); - } - return statsWells; - } - - public async Task GetOrDefaultWellStatAsync(int idWell, - CancellationToken token = default) - { - var well = await db.Wells - .Include(w => w.WellOperations) - .FirstOrDefaultAsync(w => w.Id == idWell, token) - .ConfigureAwait(false); - - if(well is null) - return null; - - var statWellDto = await CalcWellStatAsync(well, token); - return statWellDto; - } - - public async Task GetOrDefaultRopStatAsync(int idWell, CancellationToken token) - { - var clusterWellsIds = await wellService.GetClusterWellsIdsAsync(idWell, token) - .ConfigureAwait(false); - - if (clusterWellsIds is null) - return null; - - var idLastSectionType = await (from o in db.WellOperations - where o.IdWell == idWell && - o.IdType == 1 - orderby o.DepthStart - select o.IdWellSectionType) - .LastOrDefaultAsync(token) - .ConfigureAwait(false); - - if (idLastSectionType == default) - return null; - - var operations = await (from o in db.WellOperations - where clusterWellsIds.Contains(o.IdWell) && - o.IdType == 1 && - o.IdWellSectionType == idLastSectionType - select o) - .ToListAsync(token) - .ConfigureAwait(false); - - var statsList = new List(clusterWellsIds.Count()); - foreach (var clusterWellId in clusterWellsIds) - { - var currentWellOps = operations.Where(o => o.IdWell == clusterWellId); - var timezoneOffsetHours = wellService.GetTimezone(clusterWellId).Hours; - var stat = CalcStat(currentWellOps, timezoneOffsetHours); - if(stat is not null) - statsList.Add(stat); - }; - - if (!statsList.Any()) - return null; - - var clusterRops = new ClusterRopStatDto() - { - RopMax = statsList.Max(s => s.Rop), - RopAverage = statsList.Average(s => s.Rop) - }; - - return clusterRops; - } - - private async Task CalcWellStatAsync(Well well, CancellationToken token) - { - var wellType = (await memoryCache - .GetOrCreateBasicAsync(db.Set(), token)) - .FirstOrDefault(t => t.Id == well.IdWellType); - var statWellDto = new StatWellDto - { - Id = well.Id, - Caption = well.Caption, - WellType = wellType?.Caption ?? "", - IdState = well.IdState, - State = wellService.GetStateText(well.IdState), - LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id), - Companies = await wellService.GetCompaniesAsync(well.Id, token) - }; - - if (well.WellOperations is null) - return statWellDto; - - var wellOperations = well.WellOperations - .OrderBy(o => o.DateStart) - .ThenBy(o => o.DepthEnd); - - if (!wellOperations.Any()) - return statWellDto; - - var timezoneOffsetH = wellService.GetTimezone(well.Id).Hours; - statWellDto.Sections = CalcSectionsStats(wellOperations, timezoneOffsetH); - statWellDto.Total = GetStatTotal(wellOperations, well.IdState, timezoneOffsetH); - statWellDto.TvdLagDays = CalcTvdLagDays(wellOperations); - - return statWellDto; - } - - private static double CalcTvdLagDays(IOrderedEnumerable wellOperations) - { - var operationsOrdered = wellOperations - .OrderBy(o => o.DateStart); - - var factOperations = operationsOrdered - .Where(o => o.IdType == WellOperation.IdOperationTypeFact); - - var lastCorrespondingFactOperation = factOperations - .LastOrDefault(o => o.IdPlan is not null); - - if (lastCorrespondingFactOperation is null) - return 0d; - - var lastCorrespondingPlanOperation = wellOperations - .FirstOrDefault(o => o.Id == lastCorrespondingFactOperation.IdPlan); - - if (lastCorrespondingPlanOperation is null) - return 0d; - - var lastFactOperation = factOperations.Last(); - - var remainingPlanOperations = operationsOrdered - .Where(o => o.IdType == WellOperation.IdOperationTypePlan) - .Where(o => o.DateStart > lastCorrespondingPlanOperation.DateStart); - - var durationRemain = remainingPlanOperations.Sum(o => o.DurationHours); - - var factEnd = lastFactOperation.DateStart.AddHours(durationRemain + lastFactOperation.DurationHours); - var planEnd = lastCorrespondingFactOperation.DateStart.AddHours(durationRemain + lastCorrespondingFactOperation.DurationHours); - var lagDays = (planEnd - factEnd).TotalDays; - - return lagDays; - } - - private IEnumerable CalcSectionsStats(IEnumerable operations, double timezoneOffsetH) - { - var sectionTypeIds = operations - .Select(o => o.IdWellSectionType) - .Distinct(); - - var sectionTypes = memoryCache - .GetOrCreateBasic(db.Set()) - .Where(s => sectionTypeIds.Contains(s.Id)) - .ToDictionary(s => s.Id); - - var sections = new List(sectionTypes.Count); - var operationsPlan = operations.Where(o => o.IdType == WellOperation.IdOperationTypePlan); - var operationsFact = operations.Where(o => o.IdType == WellOperation.IdOperationTypeFact); - - foreach ((var id, var sectionType) in sectionTypes) - { - var section = new StatSectionDto - { - Id = id, - Caption = sectionType.Caption, - Plan = CalcSectionStat(operationsPlan, id, timezoneOffsetH), - Fact = CalcSectionStat(operationsFact, id, timezoneOffsetH), - }; - sections.Add(section); - } - return sections; - } - - private static PlanFactDto GetStatTotal(IEnumerable operations, - int idWellState, double timezoneOffsetH) - { - var operationsPlan = operations.Where(o => o.IdType == WellOperation.IdOperationTypePlan); - var operationsFact = operations.Where(o => o.IdType == WellOperation.IdOperationTypeFact); - var factEnd = CalcStat(operationsFact, timezoneOffsetH); - if (factEnd is not null && idWellState != 2) - factEnd.End = null; - var section = new PlanFactDto - { - Plan = CalcStat(operationsPlan, timezoneOffsetH), - Fact = factEnd, - }; - return section; - } - - private static StatOperationsDto? CalcSectionStat(IEnumerable operations, int idSectionType, double timezoneOffsetHours) - { - var sectionOperations = operations - .Where(o => o.IdWellSectionType == idSectionType) - .OrderBy(o => o.DateStart) - .ThenBy(o => o.DepthStart); - - return CalcStat(sectionOperations, timezoneOffsetHours); - } - - private static StatOperationsDto? CalcStat(IEnumerable operations, double timezoneOffsetHours) - { - if (!operations.Any()) - return null; - - var races = GetCompleteRaces(operations, timezoneOffsetHours); - - var section = new StatOperationsDto - { - Start = operations.FirstOrDefault()?.DateStart.ToRemoteDateTime(timezoneOffsetHours), - End = operations.Max(o => o.DateStart.ToRemoteDateTime(timezoneOffsetHours).AddHours(o.DurationHours)), - WellDepthStart = operations.Min(o => o.DepthStart), - WellDepthEnd = operations.Max(o => o.DepthStart), - Rop = CalcROP(operations), - RouteSpeed = CalcAvgRaceSpeed(races), - BhaDownSpeed = CalcBhaDownSpeed(races), - BhaUpSpeed = CalcBhaUpSpeed(races), - CasingDownSpeed = CalcCasingDownSpeed(operations), - NonProductiveHours = operations - .Where(o => WellOperationCategory.NonProductiveTimeSubIds.Contains(o.IdCategory)) - .Sum(o => o.DurationHours), - }; - return section; - } - - private static double CalcROP(IEnumerable operationsProps) - { - var drillingOperations = operationsProps.Where(o => WellOperationCategory.MechanicalDrillingSubIds.Contains(o.IdCategory)); - var dDepth = 0d; - var dHours = 0d; - foreach (var operation in drillingOperations) - { - var deltaDepth = operation.DepthEnd - operation.DepthStart; - dDepth += deltaDepth; - dHours += operation.DurationHours; - } - return dDepth / (dHours + double.Epsilon); - } - - private static double CalcCasingDownSpeed(IEnumerable operationsProps) - { - var ops = operationsProps.Where(o => o.IdCategory == WellOperationCategory.IdCasingDown); - var depth = 0d; - var dHours = 0d; - foreach (var operation in ops) - { - depth += operation.DepthStart; - dHours += operation.DurationHours; - } - return depth / (dHours + double.Epsilon); - } - - private static IEnumerable GetCompleteRaces(IEnumerable operations, double timezoneOffsetH) - { - var races = new List(); - var iterator = operations - .OrderBy(o => o.DateStart) - .GetEnumerator(); - while (iterator.MoveNext()) - { - if (iterator.Current.IdCategory == WellOperationCategory.IdBhaAssembly) - { - var race = new Race - { - StartDate = iterator.Current.DateStart.ToRemoteDateTime(timezoneOffsetH).AddHours(iterator.Current.DurationHours), - StartWellDepth = iterator.Current.DepthStart, - Operations = new List(10), - }; - while (iterator.MoveNext()) - { - if (iterator.Current.IdCategory == WellOperationCategory.IdEquipmentRepair) - race.RepairHours += iterator.Current.DurationHours; - - if (WellOperationCategory.NonProductiveTimeSubIds.Contains(iterator.Current.IdCategory)) - race.NonProductiveHours += iterator.Current.DurationHours; - - if (iterator.Current.IdCategory == WellOperationCategory.IdBhaDisassembly) - { - race.EndDate = iterator.Current.DateStart.ToRemoteDateTime(timezoneOffsetH); - race.EndWellDepth = iterator.Current.DepthStart; - races.Add(race); - break; - } - race.Operations.Add(iterator.Current); - } - } - } - return races; - } - - private static double CalcAvgRaceSpeed(IEnumerable races) - { - var dDepth = 0d; - var dHours = 0d; - foreach (var race in races) - { - dHours += race.DeltaHours - race.NonProductiveHours - race.RepairHours; - dDepth += race.DeltaDepth; - } - return dDepth / (dHours + double.Epsilon); - } - - private static double CalcBhaDownSpeed(IEnumerable races) - { - var dDepth = 0d; - var dHours = 0d; - foreach (Race race in races) - { - dDepth += race.StartWellDepth; - for (var i = 0; i < race.Operations.Count; i++) - { - if (race.Operations[i].IdCategory == WellOperationCategory.IdBhaDown) - dHours += race.Operations[i].DurationHours; - if (WellOperationCategory.MechanicalDrillingSubIds.Contains(race.Operations[i].IdCategory)) - break; - } - } - return dDepth / (dHours + double.Epsilon); - } - - private static double CalcBhaUpSpeed(IEnumerable races) - { - var dDepth = 0d; - var dHours = 0d; - foreach (var race in races) - { - dDepth += race.EndWellDepth; - for (var i = race.Operations.Count - 1; i > 0; i--) - { - if (race.Operations[i].IdCategory == WellOperationCategory.IdBhaUp) - dHours += race.Operations[i].DurationHours; - if (WellOperationCategory.MechanicalDrillingSubIds.Contains(race.Operations[i].IdCategory)) - break; - } - } - return dDepth / (dHours + double.Epsilon); - } - - public async Task>> GetTvdAsync(int idWell, CancellationToken token) - { - var wellOperations = await db.WellOperations - .Include(o => o.OperationCategory) - .Include(o => o.WellSectionType) - .Include(o => o.OperationPlan) - .Where(o => o.IdWell == idWell) - .OrderBy(o => o.DateStart) - .ThenBy(o => o.DepthEnd) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); - - var wellOperationsPlan = wellOperations - .Where(o => o.IdType == WellOperation.IdOperationTypePlan) - .OrderBy(o => o.DateStart) - .ThenBy(o => o.DepthEnd); - - var wellOperationsFact = wellOperations - .Where(o => o.IdType == WellOperation.IdOperationTypeFact) - .OrderBy(o => o.DateStart) - .ThenBy(o => o.DepthEnd); - - var sectionsIds = wellOperations - .Select(o => o.IdWellSectionType) - .Distinct(); - - var tzOffsetHours = wellService.GetTimezone(idWell).Hours; - - var merged = MergeArraysBySections(sectionsIds, wellOperationsPlan, wellOperationsFact).ToList(); - if (merged.Count ==0) - return Enumerable.Empty>(); - - var tvd = new List>(merged.Count); - var (Plan, Fact) = merged.FirstOrDefault(); - var dateStart = Plan?.DateStart ?? Fact!.DateStart; - int? iLastMatch = null; - int iLastFact = 0; - var nptHours = 0d; - for (int i = 0; i < merged.Count; i++) - { - var item = merged[i]; - var plan = item.Plan; - var fact = item.Fact; - - var planFactPredict = new PlanFactPredictBase(); - if (plan is not null) - { - planFactPredict.Plan = Convert(plan, tzOffsetHours); - planFactPredict.Plan.Day = (planFactPredict.Plan.DateStart - dateStart).TotalDays; - if (fact is not null) - iLastMatch = i; - } - - if (fact is not null) - { - if(WellOperationCategory.NonProductiveTimeSubIds.Contains(fact.IdCategory)) - nptHours += fact.DurationHours; - - planFactPredict.Fact = Convert(fact, tzOffsetHours); - planFactPredict.Fact.Day = (planFactPredict.Fact.DateStart - dateStart).TotalDays; - planFactPredict.Fact.NptHours = nptHours; - iLastFact = i; - } - - tvd.Add(planFactPredict); - } - - if (iLastMatch is null || iLastMatch == merged.Count - 1) - return tvd; - - var lastMatchPlan = merged[iLastMatch.Value].Plan!; - var lastMatchPlanOperationEnd = lastMatchPlan.DateStart.AddHours(lastMatchPlan.DurationHours); - var lastFact = merged[iLastFact].Fact!; - var lastFactDateEnd = lastFact.DateStart.AddHours(lastFact.DurationHours); - var startOffset = lastFactDateEnd - lastMatchPlanOperationEnd; - - for (int i = iLastMatch.Value + 1; i < merged.Count; i++) - { - if (merged[i].Plan is null) - continue; - var predict = Convert(merged[i].Plan!, tzOffsetHours); - predict.IdType = 2; - predict.DateStart = predict.DateStart + startOffset; - predict.Day = (predict.DateStart - dateStart).TotalDays; - tvd[i].Predict = predict; - } - - return tvd; - } - - private static IEnumerable<(WellOperation? Plan, WellOperation? Fact)> MergeArraysBySections( - IEnumerable sectionsIds, - IOrderedEnumerable wellOperationsPlan, - IOrderedEnumerable wellOperationsFact) - { - var merged = new List<(WellOperation? Plan, WellOperation? Fact)>(wellOperationsPlan.Count()); - foreach (var sectionId in sectionsIds) - { - var sectionOperationsPlan = wellOperationsPlan - .Where(o => o.IdWellSectionType == sectionId); - var sectionOperationsFact = wellOperationsFact - .Where(o => o.IdWellSectionType == sectionId); - var sectionMerged = MergeArrays(sectionOperationsPlan, sectionOperationsFact); - merged.AddRange(sectionMerged); - } - return merged; - } - - private static IEnumerable<(WellOperation? Plan, WellOperation? Fact)> MergeArrays(IEnumerable operationsPlan, IEnumerable operationsFact) - { - var operationsFactWithNoPlan = operationsFact.Where(x => x.IdPlan == null).ToArray(); - var operationsFactWithPlan = operationsFact.Where(x => x.IdPlan != null).ToArray(); - - var idsPlanWithFact = operationsFact.Where(x => x.IdPlan is not null).Select(x => x.IdPlan).Distinct(); - var operationsPlanWithNoFact = operationsPlan.Where(x => !idsPlanWithFact.Contains(x.IdPlan)).ToArray(); - - var result = new List<(WellOperation? Plan, WellOperation? Fact)>(operationsFactWithNoPlan.Length + operationsFactWithPlan.Length + operationsPlanWithNoFact.Length); - - foreach (var operation in operationsFactWithPlan) - result.Add((operation.OperationPlan, operation)); - - foreach (var operation in operationsFactWithNoPlan) - result.Add((null, operation)); - - foreach (var operation in operationsPlanWithNoFact) - result.Add((operation, null)); - - return result - .OrderBy(x => x.Plan?.DateStart) - .ThenBy(x => x.Fact?.DateStart); - } - - private static WellOperationDto Convert(WellOperation source, double tzOffsetHours) - { - var destination = source.Adapt(); - destination.CategoryName = source.OperationCategory?.Name; - destination.WellSectionTypeName = source.WellSectionType?.Caption; - destination.DateStart = source.DateStart.ToRemoteDateTime(tzOffsetHours); - return destination; - } + Id = idCluster, + Caption = cluster.Caption, + StatsWells = statsWells, + }; + return statClusterDto; } -} + public async Task> GetWellsStatAsync(IEnumerable idWells, CancellationToken token) + { + var wells = await db.Wells + .Include(w => w.WellOperations) + .Where(w => idWells.Contains(w.Id)) + .AsNoTracking() + .ToListAsync(token); + + var statsWells = new List(wells.Count); + + foreach (var well in wells) + { + var statWellDto = await CalcWellStatAsync(well, token); + statsWells.Add(statWellDto); + } + return statsWells; + } + + public async Task GetOrDefaultWellStatAsync(int idWell, + CancellationToken token = default) + { + var well = await db.Wells + .Include(w => w.WellOperations) + .FirstOrDefaultAsync(w => w.Id == idWell, token) + .ConfigureAwait(false); + + if(well is null) + return null; + + var statWellDto = await CalcWellStatAsync(well, token); + return statWellDto; + } + + public async Task GetOrDefaultRopStatAsync(int idWell, CancellationToken token) + { + var clusterWellsIds = await wellService.GetClusterWellsIdsAsync(idWell, token) + .ConfigureAwait(false); + + if (clusterWellsIds is null) + return null; + + var idLastSectionType = await (from o in db.WellOperations + where o.IdWell == idWell && + o.IdType == 1 + orderby o.DepthStart + select o.IdWellSectionType) + .LastOrDefaultAsync(token) + .ConfigureAwait(false); + + if (idLastSectionType == default) + return null; + + var operations = await (from o in db.WellOperations + where clusterWellsIds.Contains(o.IdWell) && + o.IdType == 1 && + o.IdWellSectionType == idLastSectionType + select o) + .ToListAsync(token) + .ConfigureAwait(false); + + var statsList = new List(clusterWellsIds.Count()); + foreach (var clusterWellId in clusterWellsIds) + { + var currentWellOps = operations.Where(o => o.IdWell == clusterWellId); + var timezoneOffsetHours = wellService.GetTimezone(clusterWellId).Hours; + var stat = CalcStat(currentWellOps, timezoneOffsetHours); + if(stat is not null) + statsList.Add(stat); + }; + + if (!statsList.Any()) + return null; + + var clusterRops = new ClusterRopStatDto() + { + RopMax = statsList.Max(s => s.Rop), + RopAverage = statsList.Average(s => s.Rop) + }; + + return clusterRops; + } + + private async Task CalcWellStatAsync(Well well, CancellationToken token) + { + var wellType = (await memoryCache + .GetOrCreateBasicAsync(db.Set(), token)) + .FirstOrDefault(t => t.Id == well.IdWellType); + var statWellDto = new StatWellDto + { + Id = well.Id, + Caption = well.Caption, + WellType = wellType?.Caption ?? "", + IdState = well.IdState, + State = wellService.GetStateText(well.IdState), + LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id), + Companies = await wellService.GetCompaniesAsync(well.Id, token) + }; + + if (well.WellOperations is null) + return statWellDto; + + var wellOperations = well.WellOperations + .OrderBy(o => o.DateStart) + .ThenBy(o => o.DepthEnd); + + if (!wellOperations.Any()) + return statWellDto; + + var timezoneOffsetH = wellService.GetTimezone(well.Id).Hours; + statWellDto.Sections = CalcSectionsStats(wellOperations, timezoneOffsetH); + statWellDto.Total = GetStatTotal(wellOperations, well.IdState, timezoneOffsetH); + statWellDto.TvdLagPercent = CalcTvdLagPercent(well.IdTelemetry, wellOperations); + + return statWellDto; + } + + private double? CalcTvdLagPercent(int? idTelemetry, IOrderedEnumerable wellOperations) + { + var currentDate = DateTimeOffset.UtcNow; + + var wellDepth = wellOperations + .LastOrDefault(o => o.IdType == WellOperation.IdOperationTypeFact)?.DepthEnd; + + if (idTelemetry.HasValue) + wellDepth = telemetryDataCache.GetLastOrDefault(idTelemetry.Value)?.WellDepth; + + if (wellDepth is null) + return null; + + var planOperations = wellOperations + .Where(o => o.IdType == WellOperation.IdOperationTypePlan) + .OrderBy(o => o.DateStart.AddHours(o.DurationHours)); + + if (!planOperations.Any()) + return null; + + var planDepth = CalcPlanDepth(planOperations, currentDate); + + if (planDepth is null) + return null; + + if (planDepth == 0d) + return 0d; + + return (1 - wellDepth / planDepth) * 100; + } + + private static double? CalcPlanDepth(IOrderedEnumerable planOperations, DateTimeOffset currentDate) + { + var operationIn = planOperations + .FirstOrDefault(o => o.DateStart <= currentDate && o.DateStart.AddHours(o.DurationHours) >= currentDate); + + if (operationIn is not null) + return Interpolate( + operationIn.DepthStart, + operationIn.DepthEnd, + operationIn.DateStart, + operationIn.DateStart.AddHours(operationIn.DurationHours), + currentDate); + + var operationFrom = planOperations + .LastOrDefault(o => o.DateStart.AddHours(o.DurationHours) <= currentDate); + + var operationTo = planOperations + .FirstOrDefault(o => o.DateStart >= currentDate); + + if (operationFrom is null && operationTo is not null) + return 0d; + else if (operationFrom is not null && operationTo is not null) + { + return Interpolate( + operationFrom.DepthEnd, + operationTo.DepthStart, + operationFrom.DateStart.AddHours(operationTo.DurationHours), + operationTo.DateStart, + currentDate); + } + else if (operationFrom is not null && operationTo is null) + return operationFrom.DepthEnd; + + return null; + } + + private static double Interpolate(double y0, double y1, DateTimeOffset x0, DateTimeOffset x1, DateTimeOffset x) + => y0 + (y1 - y0) * (x - x0).TotalMinutes / (x1 - x0).TotalMinutes; + + private IEnumerable CalcSectionsStats(IEnumerable operations, double timezoneOffsetH) + { + var sectionTypeIds = operations + .Select(o => o.IdWellSectionType) + .Distinct(); + + var sectionTypes = memoryCache + .GetOrCreateBasic(db.Set()) + .Where(s => sectionTypeIds.Contains(s.Id)) + .ToDictionary(s => s.Id); + + var sections = new List(sectionTypes.Count); + var operationsPlan = operations.Where(o => o.IdType == WellOperation.IdOperationTypePlan); + var operationsFact = operations.Where(o => o.IdType == WellOperation.IdOperationTypeFact); + + foreach ((var id, var sectionType) in sectionTypes) + { + var section = new StatSectionDto + { + Id = id, + Caption = sectionType.Caption, + Plan = CalcSectionStat(operationsPlan, id, timezoneOffsetH), + Fact = CalcSectionStat(operationsFact, id, timezoneOffsetH), + }; + sections.Add(section); + } + return sections; + } + + private static PlanFactDto GetStatTotal(IEnumerable operations, + int idWellState, double timezoneOffsetH) + { + var operationsPlan = operations.Where(o => o.IdType == WellOperation.IdOperationTypePlan); + var operationsFact = operations.Where(o => o.IdType == WellOperation.IdOperationTypeFact); + var factEnd = CalcStat(operationsFact, timezoneOffsetH); + if (factEnd is not null && idWellState != 2) + factEnd.End = null; + var section = new PlanFactDto + { + Plan = CalcStat(operationsPlan, timezoneOffsetH), + Fact = factEnd, + }; + return section; + } + + private static StatOperationsDto? CalcSectionStat(IEnumerable operations, int idSectionType, double timezoneOffsetHours) + { + var sectionOperations = operations + .Where(o => o.IdWellSectionType == idSectionType) + .OrderBy(o => o.DateStart) + .ThenBy(o => o.DepthStart); + + return CalcStat(sectionOperations, timezoneOffsetHours); + } + + private static StatOperationsDto? CalcStat(IEnumerable operations, double timezoneOffsetHours) + { + if (!operations.Any()) + return null; + + var races = GetCompleteRaces(operations, timezoneOffsetHours); + + var section = new StatOperationsDto + { + Start = operations.FirstOrDefault()?.DateStart.ToRemoteDateTime(timezoneOffsetHours), + End = operations.Max(o => o.DateStart.ToRemoteDateTime(timezoneOffsetHours).AddHours(o.DurationHours)), + WellDepthStart = operations.Min(o => o.DepthStart), + WellDepthEnd = operations.Max(o => o.DepthStart), + Rop = CalcROP(operations), + RouteSpeed = CalcAvgRaceSpeed(races), + BhaDownSpeed = CalcBhaDownSpeed(races), + BhaUpSpeed = CalcBhaUpSpeed(races), + CasingDownSpeed = CalcCasingDownSpeed(operations), + NonProductiveHours = operations + .Where(o => WellOperationCategory.NonProductiveTimeSubIds.Contains(o.IdCategory)) + .Sum(o => o.DurationHours), + }; + return section; + } + + private static double CalcROP(IEnumerable operationsProps) + { + var drillingOperations = operationsProps.Where(o => WellOperationCategory.MechanicalDrillingSubIds.Contains(o.IdCategory)); + var dDepth = 0d; + var dHours = 0d; + foreach (var operation in drillingOperations) + { + var deltaDepth = operation.DepthEnd - operation.DepthStart; + dDepth += deltaDepth; + dHours += operation.DurationHours; + } + return dDepth / (dHours + double.Epsilon); + } + + private static double CalcCasingDownSpeed(IEnumerable operationsProps) + { + var ops = operationsProps.Where(o => o.IdCategory == WellOperationCategory.IdCasingDown); + var depth = 0d; + var dHours = 0d; + foreach (var operation in ops) + { + depth += operation.DepthStart; + dHours += operation.DurationHours; + } + return depth / (dHours + double.Epsilon); + } + + private static IEnumerable GetCompleteRaces(IEnumerable operations, double timezoneOffsetH) + { + var races = new List(); + var iterator = operations + .OrderBy(o => o.DateStart) + .GetEnumerator(); + while (iterator.MoveNext()) + { + if (iterator.Current.IdCategory == WellOperationCategory.IdBhaAssembly) + { + var race = new Race + { + StartDate = iterator.Current.DateStart.ToRemoteDateTime(timezoneOffsetH).AddHours(iterator.Current.DurationHours), + StartWellDepth = iterator.Current.DepthStart, + Operations = new List(10), + }; + while (iterator.MoveNext()) + { + if (iterator.Current.IdCategory == WellOperationCategory.IdEquipmentRepair) + race.RepairHours += iterator.Current.DurationHours; + + if (WellOperationCategory.NonProductiveTimeSubIds.Contains(iterator.Current.IdCategory)) + race.NonProductiveHours += iterator.Current.DurationHours; + + if (iterator.Current.IdCategory == WellOperationCategory.IdBhaDisassembly) + { + race.EndDate = iterator.Current.DateStart.ToRemoteDateTime(timezoneOffsetH); + race.EndWellDepth = iterator.Current.DepthStart; + races.Add(race); + break; + } + race.Operations.Add(iterator.Current); + } + } + } + return races; + } + + private static double CalcAvgRaceSpeed(IEnumerable races) + { + var dDepth = 0d; + var dHours = 0d; + foreach (var race in races) + { + dHours += race.DeltaHours - race.NonProductiveHours - race.RepairHours; + dDepth += race.DeltaDepth; + } + return dDepth / (dHours + double.Epsilon); + } + + private static double CalcBhaDownSpeed(IEnumerable races) + { + var dDepth = 0d; + var dHours = 0d; + foreach (Race race in races) + { + dDepth += race.StartWellDepth; + for (var i = 0; i < race.Operations.Count; i++) + { + if (race.Operations[i].IdCategory == WellOperationCategory.IdBhaDown) + dHours += race.Operations[i].DurationHours; + if (WellOperationCategory.MechanicalDrillingSubIds.Contains(race.Operations[i].IdCategory)) + break; + } + } + return dDepth / (dHours + double.Epsilon); + } + + private static double CalcBhaUpSpeed(IEnumerable races) + { + var dDepth = 0d; + var dHours = 0d; + foreach (var race in races) + { + dDepth += race.EndWellDepth; + for (var i = race.Operations.Count - 1; i > 0; i--) + { + if (race.Operations[i].IdCategory == WellOperationCategory.IdBhaUp) + dHours += race.Operations[i].DurationHours; + if (WellOperationCategory.MechanicalDrillingSubIds.Contains(race.Operations[i].IdCategory)) + break; + } + } + return dDepth / (dHours + double.Epsilon); + } + + public async Task>> GetTvdAsync(int idWell, CancellationToken token) + { + var wellOperations = await db.WellOperations + .Include(o => o.OperationCategory) + .Include(o => o.WellSectionType) + .Include(o => o.OperationPlan) + .Where(o => o.IdWell == idWell) + .OrderBy(o => o.DateStart) + .ThenBy(o => o.DepthEnd) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + + var wellOperationsPlan = wellOperations + .Where(o => o.IdType == WellOperation.IdOperationTypePlan) + .OrderBy(o => o.DateStart) + .ThenBy(o => o.DepthEnd); + + var wellOperationsFact = wellOperations + .Where(o => o.IdType == WellOperation.IdOperationTypeFact) + .OrderBy(o => o.DateStart) + .ThenBy(o => o.DepthEnd); + + var sectionsIds = wellOperations + .Select(o => o.IdWellSectionType) + .Distinct(); + + var tzOffsetHours = wellService.GetTimezone(idWell).Hours; + + var merged = MergeArraysBySections(sectionsIds, wellOperationsPlan, wellOperationsFact).ToList(); + if (merged.Count ==0) + return Enumerable.Empty>(); + + var tvd = new List>(merged.Count); + var (Plan, Fact) = merged.FirstOrDefault(); + var dateStart = Plan?.DateStart ?? Fact!.DateStart; + int? iLastMatch = null; + int iLastFact = 0; + var nptHours = 0d; + for (int i = 0; i < merged.Count; i++) + { + var item = merged[i]; + var plan = item.Plan; + var fact = item.Fact; + + var planFactPredict = new PlanFactPredictBase(); + if (plan is not null) + { + planFactPredict.Plan = Convert(plan, tzOffsetHours); + planFactPredict.Plan.Day = (planFactPredict.Plan.DateStart - dateStart).TotalDays; + if (fact is not null) + iLastMatch = i; + } + + if (fact is not null) + { + if(WellOperationCategory.NonProductiveTimeSubIds.Contains(fact.IdCategory)) + nptHours += fact.DurationHours; + + planFactPredict.Fact = Convert(fact, tzOffsetHours); + planFactPredict.Fact.Day = (planFactPredict.Fact.DateStart - dateStart).TotalDays; + planFactPredict.Fact.NptHours = nptHours; + iLastFact = i; + } + + tvd.Add(planFactPredict); + } + + if (iLastMatch is null || iLastMatch == merged.Count - 1) + return tvd; + + var lastMatchPlan = merged[iLastMatch.Value].Plan!; + var lastMatchPlanOperationEnd = lastMatchPlan.DateStart.AddHours(lastMatchPlan.DurationHours); + var lastFact = merged[iLastFact].Fact!; + var lastFactDateEnd = lastFact.DateStart.AddHours(lastFact.DurationHours); + var startOffset = lastFactDateEnd - lastMatchPlanOperationEnd; + + for (int i = iLastMatch.Value + 1; i < merged.Count; i++) + { + if (merged[i].Plan is null) + continue; + var predict = Convert(merged[i].Plan!, tzOffsetHours); + predict.IdType = 2; + predict.DateStart = predict.DateStart + startOffset; + predict.Day = (predict.DateStart - dateStart).TotalDays; + tvd[i].Predict = predict; + } + + return tvd; + } + + private static IEnumerable<(WellOperation? Plan, WellOperation? Fact)> MergeArraysBySections( + IEnumerable sectionsIds, + IOrderedEnumerable wellOperationsPlan, + IOrderedEnumerable wellOperationsFact) + { + var merged = new List<(WellOperation? Plan, WellOperation? Fact)>(wellOperationsPlan.Count()); + foreach (var sectionId in sectionsIds) + { + var sectionOperationsPlan = wellOperationsPlan + .Where(o => o.IdWellSectionType == sectionId); + var sectionOperationsFact = wellOperationsFact + .Where(o => o.IdWellSectionType == sectionId); + var sectionMerged = MergeArrays(sectionOperationsPlan, sectionOperationsFact); + merged.AddRange(sectionMerged); + } + return merged; + } + + private static IEnumerable<(WellOperation? Plan, WellOperation? Fact)> MergeArrays(IEnumerable operationsPlan, IEnumerable operationsFact) + { + var operationsFactWithNoPlan = operationsFact.Where(x => x.IdPlan == null).ToArray(); + var operationsFactWithPlan = operationsFact.Where(x => x.IdPlan != null).ToArray(); + + var idsPlanWithFact = operationsFact.Where(x => x.IdPlan is not null).Select(x => x.IdPlan).Distinct(); + var operationsPlanWithNoFact = operationsPlan.Where(x => !idsPlanWithFact.Contains(x.IdPlan)).ToArray(); + + var result = new List<(WellOperation? Plan, WellOperation? Fact)>(operationsFactWithNoPlan.Length + operationsFactWithPlan.Length + operationsPlanWithNoFact.Length); + + foreach (var operation in operationsFactWithPlan) + result.Add((operation.OperationPlan, operation)); + + foreach (var operation in operationsFactWithNoPlan) + result.Add((null, operation)); + + foreach (var operation in operationsPlanWithNoFact) + result.Add((operation, null)); + + return result + .OrderBy(x => x.Plan?.DateStart) + .ThenBy(x => x.Fact?.DateStart); + } + + private static WellOperationDto Convert(WellOperation source, double tzOffsetHours) + { + var destination = source.Adapt(); + destination.CategoryName = source.OperationCategory?.Name; + destination.WellSectionTypeName = source.WellSectionType?.Caption; + destination.DateStart = source.DateStart.ToRemoteDateTime(tzOffsetHours); + return destination; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellService.cs b/AsbCloudInfrastructure/Services/WellService.cs index 4cf88d82..c47dd204 100644 --- a/AsbCloudInfrastructure/Services/WellService.cs +++ b/AsbCloudInfrastructure/Services/WellService.cs @@ -300,26 +300,6 @@ namespace AsbCloudInfrastructure.Services return dto; } - public async Task EnshureTimezonesIsSetAsync(CancellationToken token) - { - var cache = await GetCacheAsync(token); - if (!cache.Any(w => w.Timezone is null)) - return; - - var defaultTimeZone = new SimpleTimezone - { - Hours = 5, - IsOverride = false, - TimezoneId = "Assumed", - }; - - await dbSet.Where(w => w.Timezone == null) - .ForEachAsync(w => w.Timezone = defaultTimeZone, token); - - await dbContext.SaveChangesAsync(token); - DropCache(); - } - public SimpleTimezoneDto GetTimezone(int idWell) { var well = GetOrDefault(idWell); diff --git a/AsbCloudInfrastructure/Startup.cs b/AsbCloudInfrastructure/Startup.cs index 55cd361c..c1c3cc8f 100644 --- a/AsbCloudInfrastructure/Startup.cs +++ b/AsbCloudInfrastructure/Startup.cs @@ -27,9 +27,7 @@ namespace AsbCloudInfrastructure context.Database.SetCommandTimeout(TimeSpan.FromSeconds(2 * 60)); context.Database.Migrate(); - var wellService = provider.GetRequiredService(); - wellService.EnshureTimezonesIsSetAsync(CancellationToken.None).Wait();// TODO: make this background work - + // TODO: Сделать инициализацию кеша телеметрии более явной. _ = provider.GetRequiredService>(); _ = provider.GetRequiredService>(); diff --git a/AsbCloudWebApi/Controllers/AdminTelemetryController.cs b/AsbCloudWebApi/Controllers/AdminTelemetryController.cs index b9f30009..4fb1f9fb 100644 --- a/AsbCloudWebApi/Controllers/AdminTelemetryController.cs +++ b/AsbCloudWebApi/Controllers/AdminTelemetryController.cs @@ -28,8 +28,7 @@ namespace AsbCloudWebApi.Controllers /// Merge telemetries. No body required. /// /// - [HttpPost] - [Route("/merge/{idFrom}/{idTo}")] + [HttpPost("/merge/{idFrom}/{idTo}")] [Permission] public async Task MergeTelemetriesAsync(int idFrom, int idTo, CancellationToken token) { diff --git a/AsbCloudWebApi/Controllers/AdminWellController.cs b/AsbCloudWebApi/Controllers/AdminWellController.cs index 4a670652..ac08b383 100644 --- a/AsbCloudWebApi/Controllers/AdminWellController.cs +++ b/AsbCloudWebApi/Controllers/AdminWellController.cs @@ -18,13 +18,5 @@ namespace AsbCloudWebApi.Controllers public AdminWellController(IWellService service) : base(service) { } - - [HttpPost("EnshureTimezonesIsSet")] - [Permission] - public async Task EnshureTimezonesIsSet(CancellationToken token) - { - await ((IWellService)service).EnshureTimezonesIsSetAsync(token); - return Ok(); - } } } diff --git a/AsbCloudWebApi/Controllers/AuthController.cs b/AsbCloudWebApi/Controllers/AuthController.cs index ca3143ba..a041b2a5 100644 --- a/AsbCloudWebApi/Controllers/AuthController.cs +++ b/AsbCloudWebApi/Controllers/AuthController.cs @@ -2,7 +2,6 @@ using AsbCloudApp.Data.User; using AsbCloudApp.Repositories; using AsbCloudApp.Services; -using AsbCloudInfrastructure.Repository; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Swashbuckle.AspNetCore.Annotations; diff --git a/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs b/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs index 0ef6c6da..df94b605 100644 --- a/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs +++ b/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs @@ -40,10 +40,9 @@ public class AutoGeneratedDailyReportController : ControllerBase /// /// [HttpGet] - [Route("generate")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(PhysicalFileResult), (int)HttpStatusCode.OK, "application/octet-stream")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task GenerateAsync([FromRoute] int idWell, + public async Task GenerateReportAsync([FromRoute] int idWell, [Required] DateOnly reportDate, CancellationToken cancellationToken) { @@ -54,7 +53,7 @@ public class AutoGeneratedDailyReportController : ControllerBase reportDate, cancellationToken); - return File(reportFile.stream, "application/octet-stream", reportFile.fileName); + return File(reportFile.stream, reportFile.fileName); } /// @@ -64,7 +63,7 @@ public class AutoGeneratedDailyReportController : ControllerBase /// Параметры запроса /// /// - [HttpGet] + [HttpGet("all")] [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] public async Task GetListAsync([FromRoute][Required] int idWell, [FromQuery] AutoGeneratedDailyReportRequest request, diff --git a/AsbCloudWebApi/Controllers/DailyReportController.cs b/AsbCloudWebApi/Controllers/DailyReportController.cs index 5abc6659..707421dd 100644 --- a/AsbCloudWebApi/Controllers/DailyReportController.cs +++ b/AsbCloudWebApi/Controllers/DailyReportController.cs @@ -1,7 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Data.DailyReport; using AsbCloudApp.Exceptions; -using AsbCloudApp.Repositories; using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -10,6 +9,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; namespace AsbCloudWebApi.Controllers { @@ -24,16 +24,13 @@ namespace AsbCloudWebApi.Controllers { private readonly IDailyReportService dailyReportService; private readonly IWellService wellService; - private readonly IWellOperationRepository operationRepository; public DailyReportController( IDailyReportService dailyReportService, - IWellService wellService, - IWellOperationRepository operationRepository) + IWellService wellService) { this.dailyReportService = dailyReportService; this.wellService = wellService; - this.operationRepository = operationRepository; } /// @@ -165,7 +162,8 @@ namespace AsbCloudWebApi.Controllers /// /// [HttpGet("{date}/excel")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task DownloadAsync(int idWell, DateOnly date, CancellationToken token) { if (!await UserHasAccesToWellAsync(idWell, token)) @@ -175,13 +173,12 @@ namespace AsbCloudWebApi.Controllers ?? throw new ArgumentInvalidException($"Скважина c id:{idWell} не найдена", nameof(idWell)); var stream = await dailyReportService.MakeReportAsync(idWell, date, token); - if (stream is not null) - { - var fileName = $"Суточный рапорт по скважине {well.Caption} куст {well.Cluster}.xlsx"; - return File(stream, "application/octet-stream", fileName); - } - else + if (stream is null) return NoContent(); + + var fileName = $"Суточный рапорт по скважине {well.Caption} куст {well.Cluster}.xlsx"; + return File(stream, fileName); + } protected async Task UserHasAccesToWellAsync(int idWell, CancellationToken token) diff --git a/AsbCloudWebApi/Controllers/DrillingProgramController.cs b/AsbCloudWebApi/Controllers/DrillingProgramController.cs index 69944c9d..fc4ad8ea 100644 --- a/AsbCloudWebApi/Controllers/DrillingProgramController.cs +++ b/AsbCloudWebApi/Controllers/DrillingProgramController.cs @@ -83,7 +83,7 @@ namespace AsbCloudWebApi.Controllers /// /// /// - [HttpPost("ClearError")] + [HttpDelete("errors")] [Permission("DrillingProgram.get")] public IActionResult ClearError(int idWell) { diff --git a/AsbCloudWebApi/Controllers/FactTrajectoryController.cs b/AsbCloudWebApi/Controllers/FactTrajectoryController.cs index c17ce3fd..fbdb6703 100644 --- a/AsbCloudWebApi/Controllers/FactTrajectoryController.cs +++ b/AsbCloudWebApi/Controllers/FactTrajectoryController.cs @@ -30,7 +30,6 @@ public class FactTrajectoryController : ControllerBase /// Токен отмены операции /// [HttpGet] - [Route("getRows")] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetRowsAsync([FromRoute] int idWell, CancellationToken cancellationToken) diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index 2a7d6fcb..e9a7990b 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -73,8 +73,7 @@ namespace AsbCloudWebApi.Controllers /// /// Токен отмены задачи /// Список информации о файлах в этой категории - [HttpGet] - [Route("/api/files")] + [HttpGet("/api/files")] [Permission] [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] public async Task GetFilesInfoAsync( @@ -101,8 +100,7 @@ namespace AsbCloudWebApi.Controllers /// id запрашиваемого файла /// Токен отмены задачи /// Запрашиваемый файл - [HttpGet] - [Route("{idFile}")] + [HttpGet("{idFile}")] [Permission] [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] public async Task GetFileAsync( @@ -220,8 +218,7 @@ namespace AsbCloudWebApi.Controllers /// id запрашиваемого файла /// Токен отмены задачи /// Запрашиваемый файл - [HttpGet] - [Route("/api/files/{idFile}")] + [HttpGet("/api/files/{idFile}")] [Permission] [ProducesResponseType(typeof(FileInfoDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetFileInfoAsync([FromRoute] int idFile, CancellationToken token) diff --git a/AsbCloudWebApi/Controllers/HelpPageController.cs b/AsbCloudWebApi/Controllers/HelpPageController.cs index db0b5faf..a90ea46a 100644 --- a/AsbCloudWebApi/Controllers/HelpPageController.cs +++ b/AsbCloudWebApi/Controllers/HelpPageController.cs @@ -102,8 +102,7 @@ public class HelpPageController : ControllerBase /// Id категории файла. Допустимое значение параметра: 20000 /// /// - [HttpGet] - [Route("isExisting")] + [HttpGet("isExisting")] [ProducesResponseType(typeof(bool), (int)HttpStatusCode.OK)] public async Task IsExistingAsync( [Required] string key, diff --git a/AsbCloudWebApi/Controllers/MeasureController.cs b/AsbCloudWebApi/Controllers/MeasureController.cs index 510a34ca..7dc1afde 100644 --- a/AsbCloudWebApi/Controllers/MeasureController.cs +++ b/AsbCloudWebApi/Controllers/MeasureController.cs @@ -24,9 +24,8 @@ namespace AsbCloudWebApi.Controllers this.wellService = wellService; } - [HttpGet] + [HttpGet("categories")] [Permission] - [Route("categories")] public async Task GetCategoriesAsync([FromRoute] int idWell, CancellationToken token) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) @@ -36,9 +35,8 @@ namespace AsbCloudWebApi.Controllers return Ok(result); } - [HttpGet] + [HttpGet("last/{idCategory}")] [Permission] - [Route("last/{idCategory}")] public async Task GetLastAsync([FromRoute] int idWell, [FromRoute] int idCategory, CancellationToken token) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) @@ -55,9 +53,8 @@ namespace AsbCloudWebApi.Controllers /// Категория скважины. Не обязательный параметр. /// /// - [HttpGet] + [HttpGet("history")] [Permission] - [Route("history")] public async Task GetHisoryAsync([FromRoute] int idWell, CancellationToken token, int? idCategory = null) { @@ -90,9 +87,8 @@ namespace AsbCloudWebApi.Controllers return Ok(result); } - [HttpDelete] + [HttpDelete("history/{idData}")] [Permission] - [Route("history/{idData}")] public async Task MarkAsDeleteAsync([FromRoute] int idWell, [FromRoute] int idData, CancellationToken token) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) diff --git a/AsbCloudWebApi/Controllers/NotificationController.cs b/AsbCloudWebApi/Controllers/NotificationController.cs index 9e3b7b1f..e87006e6 100644 --- a/AsbCloudWebApi/Controllers/NotificationController.cs +++ b/AsbCloudWebApi/Controllers/NotificationController.cs @@ -17,7 +17,7 @@ namespace AsbCloudWebApi.Controllers; /// [ApiController] [Authorize] -[Route("api/notification")] +[Route("api/[controller]")] public class NotificationController : ControllerBase { private readonly NotificationService notificationService; @@ -79,8 +79,7 @@ public class NotificationController : ControllerBase /// Id уведомления /// /// - [HttpGet] - [Route("{idNotification}")] + [HttpGet("{idNotification}")] [ProducesResponseType(typeof(NotificationDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetAsync([Required] int idNotification, CancellationToken cancellationToken) @@ -125,8 +124,7 @@ public class NotificationController : ControllerBase /// Id уведомления /// /// - [HttpDelete] - [Route("{idNotification}")] + [HttpDelete("{idNotification}")] public async Task DeleteAsync([Required] int idNotification, CancellationToken cancellationToken) { diff --git a/AsbCloudWebApi/Controllers/OperationStatController.cs b/AsbCloudWebApi/Controllers/OperationStatController.cs index 9fa4f5bd..d4346255 100644 --- a/AsbCloudWebApi/Controllers/OperationStatController.cs +++ b/AsbCloudWebApi/Controllers/OperationStatController.cs @@ -77,8 +77,7 @@ namespace AsbCloudWebApi.Controllers /// id куста /// /// - [HttpGet] - [Route("cluster/{idCluster}/stat")] + [HttpGet("cluster/{idCluster}/stat")] [Permission] [ProducesResponseType(typeof(StatClusterDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetStatClusterAsync(int idCluster, @@ -99,8 +98,7 @@ namespace AsbCloudWebApi.Controllers /// список скважин /// /// - [HttpGet] - [Route("wellsStats")] + [HttpGet("wellsStats")] [Permission] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetWellsStatAsync([FromQuery] IEnumerable idWells, CancellationToken token) @@ -123,8 +121,7 @@ namespace AsbCloudWebApi.Controllers /// id скважины /// /// - [HttpGet] - [Route("well/{idWell}/stat")] + [HttpGet("well/{idWell}/stat")] [Permission] [ProducesResponseType(typeof(StatWellDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetStatWellAsync(int idWell, @@ -144,8 +141,7 @@ namespace AsbCloudWebApi.Controllers /// /// /// - [HttpGet] - [Route("well/{idWell}/tvd")] + [HttpGet("well/{idWell}/tvd")] [Permission] [ProducesResponseType(typeof(IEnumerable>), (int)System.Net.HttpStatusCode.OK)] public async Task GetTvdAsync(int idWell, diff --git a/AsbCloudWebApi/Controllers/OperationValueController.cs b/AsbCloudWebApi/Controllers/OperationValueController.cs index 6e9c312b..5a58953b 100644 --- a/AsbCloudWebApi/Controllers/OperationValueController.cs +++ b/AsbCloudWebApi/Controllers/OperationValueController.cs @@ -8,7 +8,7 @@ namespace AsbCloudWebApi.Controllers /// /// Целевые и нормативные значения по глубине /// - [Route("api/operationValue")] + [Route("api/[controller]")] [ApiController] [Authorize] public class OperationValueController : CrudWellRelatedController> diff --git a/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs b/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs index 5da1a2c2..322dc454 100644 --- a/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs +++ b/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs @@ -38,18 +38,18 @@ namespace AsbCloudWebApi.Controllers } /// - /// Возвращает шаблон для заполнения строк плановой траектории + /// Возвращает excel шаблон для заполнения строк плановой траектории /// /// Запрашиваемый файл - [HttpGet] - [Route("template")] + [HttpGet("template")] [AllowAnonymous] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK,"application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] public IActionResult GetTemplate() { var stream = plannedTrajectoryImportService.GetTemplateFile(); var fileName = "ЕЦП_шаблон_файла_плановая_траектория.xlsx"; - return File(stream, "application/octet-stream", fileName); + return File(stream, fileName); } /// @@ -58,9 +58,9 @@ namespace AsbCloudWebApi.Controllers /// id скважины /// Токен отмены задачи /// Запрашиваемый файл - [HttpGet] - [Route("export")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [HttpGet("export")] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ExportAsync([FromRoute] int idWell, CancellationToken token) { if (!await CanUserAccessToWellAsync(idWell, @@ -68,7 +68,7 @@ namespace AsbCloudWebApi.Controllers return Forbid(); var stream = await plannedTrajectoryImportService.ExportAsync(idWell, token); var fileName = await plannedTrajectoryImportService.GetFileNameAsync(idWell, token); - return File(stream, "application/octet-stream", fileName); + return File(stream, fileName); } /// @@ -79,8 +79,7 @@ namespace AsbCloudWebApi.Controllers /// Удалить операции перед импортом, если фал валидный /// Токен отмены задачи /// количество успешно записанных строк в БД - [HttpPost] - [Route("import/{deleteBeforeImport}")] + [HttpPost("import/{deleteBeforeImport}")] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task ImportAsync(int idWell, [FromForm] IFormFileCollection files, @@ -118,7 +117,6 @@ namespace AsbCloudWebApi.Controllers /// Токен отмены задачи /// Список добавленных координат плановой траектории [HttpGet] - [Route("getRows")] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetAsync([FromRoute] int idWell, CancellationToken token) { @@ -137,7 +135,6 @@ namespace AsbCloudWebApi.Controllers /// /// количество успешно записанных строк в БД [HttpPost] - [Route("addRow")] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task AddAsync(int idWell, [FromBody] TrajectoryGeoPlanDto row, CancellationToken token) @@ -160,8 +157,7 @@ namespace AsbCloudWebApi.Controllers /// /// /// количество успешно записанных строк в БД - [HttpPost] - [Route("addRangeRows")] + [HttpPost("range")] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task AddRangeAsync(int idWell, [FromBody] IEnumerable rows, CancellationToken token) @@ -231,7 +227,7 @@ namespace AsbCloudWebApi.Controllers /// /// /// - [HttpGet] + [HttpGet("trajectoryCartesianPlanFact")] [ProducesResponseType(typeof(PlanFactBase, IEnumerable>), (int)System.Net.HttpStatusCode.OK)] public async Task GetTrajectoryCartesianPlanFactAsync(int idWell, CancellationToken token) { diff --git a/AsbCloudWebApi/Controllers/ProcessMapController.cs b/AsbCloudWebApi/Controllers/ProcessMapController.cs index ffa88938..0199cb9a 100644 --- a/AsbCloudWebApi/Controllers/ProcessMapController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMapController.cs @@ -57,9 +57,8 @@ namespace AsbCloudWebApi.Controllers /// Дата, с которой следует искать новые параметры /// Токен отмены задачи /// Список параметров для коридоров бурения - [HttpGet] + [HttpGet("/api/telemetry/{uid}/drillFlowChart")] [Obsolete("use GetByUidAsync(..) instead")] - [Route("/api/telemetry/{uid}/drillFlowChart")] [AllowAnonymous] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public IActionResult GetByTelemetry(string uid, DateTime updateFrom, CancellationToken token) @@ -77,8 +76,7 @@ namespace AsbCloudWebApi.Controllers /// Дата, с которой следует искать новые параметры /// Токен отмены задачи /// Список параметров для коридоров бурения - [HttpGet] - [Route("/api/telemetry/{uid}/processMap")] + [HttpGet("/api/telemetry/{uid}/processMap")] [AllowAnonymous] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetByUidAsync(string uid, DateTime updateFrom, CancellationToken token) @@ -99,9 +97,9 @@ namespace AsbCloudWebApi.Controllers /// /// /// /// - [HttpGet] - [Route("getReportFile/{wellId}")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [HttpGet("report/{wellId}")] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task GetReportFileAsync(int wellId, CancellationToken token) { var stream = await processMapReportService.MakeReportAsync(wellId, token); @@ -110,14 +108,12 @@ namespace AsbCloudWebApi.Controllers var well = await wellService.GetOrDefaultAsync(wellId, token); if (well is null) return NoContent(); - else - { - var fileName = $"РТК по скважине {well.Caption} куст {well.Cluster}.xlsx"; - return File(stream, "application/octet-stream", fileName); - } + + var fileName = $"РТК по скважине {well.Caption} куст {well.Cluster}.xlsx"; + return File(stream, fileName); } - else - return NoContent(); + + return NoContent(); } /// @@ -126,8 +122,7 @@ namespace AsbCloudWebApi.Controllers /// /// /// - [HttpGet] - [Route("getDrillProcessMap/{wellId}")] + [HttpGet("report/{wellId}/data")] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetDrillProcessMap(int wellId, CancellationToken token) { @@ -169,14 +164,13 @@ namespace AsbCloudWebApi.Controllers /// Возвращает шаблон файла импорта плановой РТК /// /// Запрашиваемый файл - [HttpGet] - [Route("template")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [HttpGet("template")] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] public async Task GetTemplateAsync(CancellationToken cancellationToken) { var stream = await processMapPlanImportService.GetExcelTemplateStreamAsync(cancellationToken); var fileName = "ЕЦП_шаблон_файла_РТК.xlsx"; - return File(stream, "application/octet-stream", fileName); + return File(stream, fileName); } /// @@ -187,8 +181,7 @@ namespace AsbCloudWebApi.Controllers /// Загружаемый файл /// /// - [HttpPost] - [Route("import/{idWell}/{options}")] + [HttpPost("import/{idWell}/{options}")] public async Task ImportAsync(int idWell, int options, [Required] IFormFile file, @@ -226,9 +219,9 @@ namespace AsbCloudWebApi.Controllers /// Id скважины /// /// - [HttpGet] - [Route("export/{idWell}")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [HttpGet("export/{idWell}")] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ExportAsync(int idWell, CancellationToken cancellationToken) { int? idUser = User.GetUserId(); @@ -243,7 +236,7 @@ namespace AsbCloudWebApi.Controllers var stream = await processMapPlanImportService.ExportAsync(idWell, cancellationToken); var fileName = $"РТК-план по скважине {well.Caption} куст {well.Cluster}.xlsx"; - return File(stream, "application/octet-stream", fileName); + return File(stream, fileName); } private async Task NotifyUsersBySignalR(int idWell, CancellationToken token) diff --git a/AsbCloudWebApi/Controllers/ReportController.cs b/AsbCloudWebApi/Controllers/ReportController.cs index c20db17b..3386d505 100644 --- a/AsbCloudWebApi/Controllers/ReportController.cs +++ b/AsbCloudWebApi/Controllers/ReportController.cs @@ -104,8 +104,7 @@ namespace AsbCloudWebApi.Controllers /// Параметры запроса /// Токен для отмены задачи /// прогнозируемое кол-во страниц отчета - [HttpGet] - [Route("reportSize")] + [HttpGet("reportSize")] [Permission] [ProducesResponseType(typeof(string), (int)System.Net.HttpStatusCode.OK)] public async Task GetReportSizeAsync([Required] int idWell, @@ -133,8 +132,7 @@ namespace AsbCloudWebApi.Controllers /// id скважины /// Токен для отмены задачи /// Даты самого старого и самого свежего отчетов в БД - [HttpGet] - [Route("datesRange")] + [HttpGet("datesRange")] [Permission] [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetReportsDateRangeAsync(int idWell, CancellationToken token) diff --git a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs index 02737317..0a16bcfd 100644 --- a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; namespace AsbCloudWebApi.Controllers.SAUB { @@ -120,10 +121,10 @@ namespace AsbCloudWebApi.Controllers.SAUB /// /// Токен отмены задачи /// Запрашиваемый файл - [HttpGet] - [Route("export")] + [HttpGet("export")] [Permission] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ExportAsync(int? idWell, int? idCluster, CancellationToken token) { if (idCluster is null && idWell is null) @@ -151,7 +152,7 @@ namespace AsbCloudWebApi.Controllers.SAUB var stream = await detectedOperationService.ExportAsync(idsWells, token); var fileName = "operations.xlsx"; - return File(stream, "application/octet-stream", fileName); + return File(stream, fileName); } } } diff --git a/AsbCloudWebApi/Controllers/SAUB/MessageController.cs b/AsbCloudWebApi/Controllers/SAUB/MessageController.cs index b2bec1b8..cdac923d 100644 --- a/AsbCloudWebApi/Controllers/SAUB/MessageController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/MessageController.cs @@ -64,8 +64,7 @@ namespace AsbCloudWebApi.Controllers.SAUB /// id скважины /// Токен для отмены задачи /// список сообщений по скважине - [HttpGet] - [Route("datesRange")] + [HttpGet("datesRange")] [Permission] [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetMessagesDateRangeAsync(int idWell, CancellationToken token) diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs index f7fe0b74..a70cc72f 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs @@ -44,8 +44,7 @@ namespace AsbCloudWebApi.Controllers.SAUB /// Информация об отправителе /// Токен отмены задачи /// - [HttpPost] - [Route("{uid}/info")] + [HttpPost("{uid}/info")] public async Task PostInfoAsync(string uid, [FromBody] TelemetryInfoDto info, CancellationToken token) { @@ -60,8 +59,7 @@ namespace AsbCloudWebApi.Controllers.SAUB /// сообщения /// Токен для отмены задачи /// - [HttpPost] - [Route("{uid}/message")] + [HttpPost("{uid}/message")] public async Task PostMessagesAsync(string uid, [FromBody] IEnumerable dtos, CancellationToken token) { @@ -82,8 +80,7 @@ namespace AsbCloudWebApi.Controllers.SAUB /// справочник событий /// Токен для отмены задачи /// - [HttpPost] - [Route("{uid}/event")] + [HttpPost("{uid}/event")] public async Task PostEventsAsync(string uid, [FromBody] List events, CancellationToken token) { @@ -99,8 +96,7 @@ namespace AsbCloudWebApi.Controllers.SAUB /// справочник пользователей телеметрии /// /// - [HttpPost] - [Route("{uid}/user")] + [HttpPost("{uid}/user")] public async Task PostUsersAsync(string uid, [FromBody] List users, CancellationToken token) { diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs index 8eb26d56..05af2b9a 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs @@ -44,8 +44,7 @@ namespace AsbCloudWebApi.Controllers.SAUB /// Данные /// Токен для отмены задачи /// - [HttpPost] - [Route("{uid}")] + [HttpPost("{uid}")] [AllowAnonymous] public virtual async Task PostDataAsync(string uid, [FromBody] IEnumerable dtos, CancellationToken token) @@ -102,8 +101,7 @@ namespace AsbCloudWebApi.Controllers.SAUB /// id скважины /// Токен завершения задачи /// - [HttpGet] - [Route("{idWell}/datesRange")] + [HttpGet("{idWell}/datesRange")] [Permission] [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] public virtual async Task> GetDataDatesRangeAsync(int idWell, diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs index 8158308e..5cf3fce0 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs @@ -3,11 +3,10 @@ using AsbCloudApp.Services; using AsbCloudWebApi.SignalR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; -using System.IO; using System.Threading.Tasks; using System.Threading; -using AsbCloudInfrastructure.Services; using System; +using Microsoft.AspNetCore.Http; namespace AsbCloudWebApi.Controllers.SAUB { @@ -44,7 +43,8 @@ namespace AsbCloudWebApi.Controllers.SAUB /// /// [HttpGet("{idWell}/export/csv")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate, CancellationToken token) { int? idCompany = User.GetCompanyId(); @@ -60,7 +60,7 @@ namespace AsbCloudWebApi.Controllers.SAUB var stream = await telemetryDataSaubService.GetZippedCsv(idWell, beginDate, endDate, token).ConfigureAwait(false); var fileName = $"DataSaub idWell{idWell} {beginDate:yyyy-MM-DDTHH-mm} - {endDate:yyyy-MM-DDTHH-mm}.zip"; - return File(stream, "application/octet-stream", fileName); + return File(stream, fileName); } } } diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs index a9ee2815..b936edd5 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs @@ -45,8 +45,7 @@ namespace AsbCloudWebApi.Controllers.SAUB /// /// /// - [HttpPost] - [Route("{uid}")] + [HttpPost("{uid}")] [AllowAnonymous] public async Task PostDataAsync(string uid, [FromBody] TelemetryWirelineRunOutBaseDto dto, CancellationToken token) { diff --git a/AsbCloudWebApi/Controllers/WellCompositeController.cs b/AsbCloudWebApi/Controllers/WellCompositeController.cs index e64118fd..d977128d 100644 --- a/AsbCloudWebApi/Controllers/WellCompositeController.cs +++ b/AsbCloudWebApi/Controllers/WellCompositeController.cs @@ -71,7 +71,7 @@ namespace AsbCloudWebApi.Controllers /// /// /// - [HttpGet("getCompositeProcessMap")] + [HttpGet("compositeProcessMap")] [Permission] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetCompositeProcessMap(int idWell, CancellationToken token) diff --git a/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs b/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs index 19952231..3cd7156b 100644 --- a/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs +++ b/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs @@ -160,8 +160,7 @@ namespace AsbCloudWebApi.Controllers /// Получение справочника категорий файлов /// /// - [HttpGet] - [Route("wellCaseCategories")] + [HttpGet("wellCaseCategories")] [Permission] public async Task GetWellCaseCategoriesAsync(CancellationToken token) { diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs index 7bac5579..4bb40bdc 100644 --- a/AsbCloudWebApi/Controllers/WellOperationController.cs +++ b/AsbCloudWebApi/Controllers/WellOperationController.cs @@ -1,5 +1,4 @@ using AsbCloudApp.Data; -using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; @@ -10,7 +9,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -40,8 +38,7 @@ namespace AsbCloudWebApi.Controllers /// Возвращает словарь типов секций /// /// - [HttpGet] - [Route("sectionTypes")] + [HttpGet("sectionTypes")] [Permission] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public IActionResult GetSectionTypes() @@ -55,8 +52,7 @@ namespace AsbCloudWebApi.Controllers /// /// флаг, нужно ли включать родителей в список /// - [HttpGet] - [Route("categories")] + [HttpGet("categories")] [Permission] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public IActionResult GetCategories(bool includeParents = true) @@ -72,8 +68,7 @@ namespace AsbCloudWebApi.Controllers /// дата для нахождения последней сопоставленной плановой операции /// /// - [HttpGet] - [Route("operationsPlan")] + [HttpGet("operationsPlan")] [ProducesResponseType(typeof(WellOperationPlanDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetOperationsPlanAsync( [FromRoute] int idWell, @@ -97,8 +92,7 @@ namespace AsbCloudWebApi.Controllers /// /// /// Список операций на скважине - [HttpGet] - [Route("fact")] + [HttpGet("fact")] [Permission] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetPageOperationsFactAsync( @@ -125,8 +119,7 @@ namespace AsbCloudWebApi.Controllers /// /// /// Список операций на скважине в контейнере для постраничного просмотра - [HttpGet] - [Route("plan")] + [HttpGet("plan")] [Permission] [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] public async Task GetPageOperationsPlanAsync( @@ -152,8 +145,7 @@ namespace AsbCloudWebApi.Controllers /// /// /// - [HttpGet] - [Route("groupStat")] + [HttpGet("groupStat")] [Permission] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetGroupOperationsAsync( @@ -179,8 +171,7 @@ namespace AsbCloudWebApi.Controllers /// id нужной операции /// Токен отмены задачи /// Нужную операцию на скважине - [HttpGet] - [Route("{idOperation}")] + [HttpGet("{idOperation}")] [Permission] [ProducesResponseType(typeof(WellOperationDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetOrDefaultAsync(int idWell, int idOperation, @@ -282,9 +273,8 @@ namespace AsbCloudWebApi.Controllers /// Удалить операции перед импортом = 1, если фал валидный /// Токен отмены задачи /// - [HttpPost] + [HttpPost("import/{options}")] [Permission] - [Route("import/{options}")] public async Task ImportAsync(int idWell, [FromForm] IFormFileCollection files, int options, @@ -324,12 +314,12 @@ namespace AsbCloudWebApi.Controllers /// Создает excel файл с операциями по скважине /// /// id скважины - /// Токен отмены задачи + /// Токен отмены задачи /// Запрашиваемый файл - [HttpGet] - [Route("export")] + [HttpGet("export")] [Permission] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ExportAsync([FromRoute] int idWell, CancellationToken token) { int? idCompany = User.GetCompanyId(); @@ -343,7 +333,7 @@ namespace AsbCloudWebApi.Controllers var stream = wellOperationImportService.Export(idWell); var fileName = await wellService.GetWellCaptionByIdAsync(idWell, token) + "_operations.xlsx"; - return File(stream, "application/octet-stream", fileName); + return File(stream, fileName); } /// @@ -353,8 +343,7 @@ namespace AsbCloudWebApi.Controllers /// /// Токен отмены задачи /// Запрашиваемый файл - [HttpGet] - [Route("scheduleReport")] + [HttpGet("scheduleReport")] [Permission] [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] public async Task ScheduleReportAsync([FromRoute] int idWell, [FromServices] IScheduleReportService scheduleReportService, CancellationToken token) @@ -377,15 +366,14 @@ namespace AsbCloudWebApi.Controllers /// Возвращает шаблон файла импорта /// /// Запрашиваемый файл - [HttpGet] - [Route("template")] + [HttpGet("template")] [AllowAnonymous] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] public IActionResult GetTemplate() { var stream = wellOperationImportService.GetExcelTemplateStream(); var fileName = "ЕЦП_шаблон_файла_операций.xlsx"; - return File(stream, "application/octet-stream", fileName); + return File(stream, fileName); } private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token)