forked from ddrilling/AsbCloudServer
Add internal DetectedOperationExportService.
Add DetectedOperation statistics
This commit is contained in:
parent
6f83e8c7cc
commit
d2b98d3a77
@ -1,12 +1,10 @@
|
|||||||
using System.Collections.Generic;
|
namespace AsbCloudApp.Data.DetectedOperation
|
||||||
|
|
||||||
namespace AsbCloudApp.Data
|
|
||||||
{
|
{
|
||||||
#nullable enable
|
#nullable enable
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Статистика по операциям бурильщика
|
/// Статистика по операциям бурильщика
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DetectedOperationStatDto
|
public class DetectedOperationDrillersStatDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Бурильщик
|
/// Бурильщик
|
||||||
@ -38,18 +36,5 @@ namespace AsbCloudApp.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double? Loss { get; set; }
|
public double? Loss { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Автоматически определяемая операция
|
|
||||||
/// </summary>
|
|
||||||
public class DetectedOperationListDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Список всех операций
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<DetectedOperationDto> Operations { get; set; }
|
|
||||||
|
|
||||||
public IEnumerable<DetectedOperationStatDto> Stats { get; set; }
|
|
||||||
}
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace AsbCloudApp.Data
|
namespace AsbCloudApp.Data.DetectedOperation
|
||||||
{
|
{
|
||||||
#nullable enable
|
#nullable enable
|
||||||
/// <summary>
|
/// <summary>
|
@ -0,0 +1,22 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Data.DetectedOperation
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Автоматически определяемая операция
|
||||||
|
/// </summary>
|
||||||
|
public class DetectedOperationListDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Список всех операций
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<DetectedOperationDto> Operations { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Статистика по бурильщикам
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<DetectedOperationDrillersStatDto> Stats { get; set; }
|
||||||
|
}
|
||||||
|
#nullable disable
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
namespace AsbCloudApp.Data.DetectedOperation
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
/// <summary>
|
||||||
|
/// Статистика по операциям например за период.
|
||||||
|
/// </summary>
|
||||||
|
public class DetectedOperationStatDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Id названия/описания операции
|
||||||
|
/// </summary>
|
||||||
|
public int IdCategory { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Название операции
|
||||||
|
/// </summary>
|
||||||
|
public string Category { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Количество операций
|
||||||
|
/// </summary>
|
||||||
|
public int Count { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Среднее по ключевому показателю
|
||||||
|
/// </summary>
|
||||||
|
public double ValueAverage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Мин по ключевому показателю
|
||||||
|
/// </summary>
|
||||||
|
public double ValueMin { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Макс по ключевому показателю
|
||||||
|
/// </summary>
|
||||||
|
public double ValueMax { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Суммарное время операций, мин
|
||||||
|
/// </summary>
|
||||||
|
public double MinutesTotal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Мин продолжительность операции, мин
|
||||||
|
/// </summary>
|
||||||
|
public double MinutesMin { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Макс продолжительность операции, мин
|
||||||
|
/// </summary>
|
||||||
|
public double MinutesMax { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Средняя продолжительность операции, мин
|
||||||
|
/// </summary>
|
||||||
|
public double MinutesAverage { get; set; }
|
||||||
|
}
|
||||||
|
#nullable disable
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace AsbCloudApp.Requests
|
namespace AsbCloudApp.Requests
|
||||||
@ -15,10 +16,9 @@ namespace AsbCloudApp.Requests
|
|||||||
public int IdWell { get; set; }
|
public int IdWell { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// категория операций
|
/// категории операций
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required]
|
public IEnumerable<int> IdsCategories { get; set; }
|
||||||
public int IdCategory { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Больше или равно дате
|
/// Больше или равно дате
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.DetectedOperation;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudApp.Services
|
namespace AsbCloudApp.Services
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public interface IDetectedOperationService
|
public interface IDetectedOperationService
|
||||||
{
|
{
|
||||||
Task<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(int? idWell, CancellationToken token);
|
Task<IEnumerable<WellOperationCategoryDto>?> GetCategoriesAsync(int? idWell, CancellationToken token);
|
||||||
Task<DetectedOperationListDto> GetAsync(DetectedOperationRequest request, CancellationToken token);
|
Task<DetectedOperationListDto?> GetAsync(DetectedOperationRequest request, CancellationToken token);
|
||||||
Task<int> DeleteAsync(DetectedOperationRequest request, CancellationToken token);
|
Task<int> DeleteAsync(DetectedOperationRequest request, CancellationToken token);
|
||||||
|
Task<IEnumerable<DetectedOperationStatDto>?> GetOperationsStatAsync(DetectedOperationRequest request, CancellationToken token);
|
||||||
|
Task<Stream> ExportAsync(IEnumerable<int> idsWells, CancellationToken token);
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using ClosedXML.Excel;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations
|
||||||
|
{
|
||||||
|
internal class DetectedOperationExportService
|
||||||
|
{
|
||||||
|
private readonly IAsbCloudDbContext db;
|
||||||
|
private readonly IWellService wellService;
|
||||||
|
|
||||||
|
public DetectedOperationExportService(IAsbCloudDbContext db, IWellService wellService)
|
||||||
|
{
|
||||||
|
this.db = db;
|
||||||
|
this.wellService = wellService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Stream> ExportAsync(IEnumerable<int> idsWells, CancellationToken token)
|
||||||
|
{
|
||||||
|
using var workbook = new XLWorkbook(XLEventTracking.Disabled);
|
||||||
|
|
||||||
|
await AddSheetsAsync(workbook, idsWells, token);
|
||||||
|
|
||||||
|
MemoryStream memoryStream = new MemoryStream();
|
||||||
|
workbook.SaveAs(memoryStream, new SaveOptions { });
|
||||||
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
return memoryStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AddSheetsAsync(XLWorkbook workbook, IEnumerable<int> idsWells, CancellationToken token)
|
||||||
|
{
|
||||||
|
if(!idsWells.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var wells = idsWells.Select(i => wellService.GetOrDefault(i))
|
||||||
|
.Where(w => w is not null && w.IdTelemetry is not null);
|
||||||
|
|
||||||
|
if (!wells.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var idsTelemetries = wells.Select(w => w.IdTelemetry);
|
||||||
|
if (!idsTelemetries.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var operations = await db.DetectedOperations
|
||||||
|
.Include(o => o.OperationCategory)
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(o => idsTelemetries.Contains(o.IdTelemetry))
|
||||||
|
.OrderBy(o => o.IdTelemetry)
|
||||||
|
.ThenBy(o => o.DateStart)
|
||||||
|
.ToListAsync(token);
|
||||||
|
|
||||||
|
var groups = operations.GroupBy(o => o.IdTelemetry);
|
||||||
|
|
||||||
|
foreach (var well in wells)
|
||||||
|
{
|
||||||
|
var ops = groups.FirstOrDefault(g => g.Key == well.IdTelemetry)
|
||||||
|
?.ToList();
|
||||||
|
|
||||||
|
if(ops?.Any() != true)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var sheetName = $"{well.Cluster}_{well.Caption}"
|
||||||
|
.Replace('.','_');
|
||||||
|
|
||||||
|
var sheet = workbook.AddWorksheet(sheetName);
|
||||||
|
AddHeader(sheet);
|
||||||
|
const int headerHeight = 1;
|
||||||
|
for(var i = 0; i< ops.Count; i++ )
|
||||||
|
AddRow(sheet, ops[i], well, i + 1 + headerHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddHeader(IXLWorksheet sheet)
|
||||||
|
{
|
||||||
|
var rowNumber = 1;
|
||||||
|
sheet.Cell(rowNumber, 1).Value = "Name";
|
||||||
|
sheet.Column(1).Width = 34;
|
||||||
|
|
||||||
|
sheet.Cell(rowNumber, 2).Value = "DateStart";
|
||||||
|
sheet.Column(2).Width = 17;
|
||||||
|
|
||||||
|
sheet.Cell(rowNumber, 3).Value = "DateEnd";
|
||||||
|
sheet.Column(3).Width = 17;
|
||||||
|
|
||||||
|
sheet.Cell(rowNumber, 4).Value = "DepthStart";
|
||||||
|
sheet.Column(4).Width = 9;
|
||||||
|
|
||||||
|
sheet.Cell(rowNumber, 5).Value = "DepthEnd";
|
||||||
|
sheet.Column(5).Width = 9;
|
||||||
|
|
||||||
|
sheet.Cell(rowNumber, 6).Value = "KeyValue";
|
||||||
|
sheet.Column(6).Width = 9;
|
||||||
|
|
||||||
|
sheet.SheetView.FreezeRows(rowNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddRow(IXLWorksheet sheet, DetectedOperation operation, WellDto well, int rowNumber)
|
||||||
|
{
|
||||||
|
var timezoneoffsetHours = well.Timezone.Hours;
|
||||||
|
sheet.Cell(rowNumber, 1).Value = operation.OperationCategory.Name;
|
||||||
|
sheet.Cell(rowNumber, 2).Value = operation.DateStart.ToRemoteDateTime(timezoneoffsetHours);
|
||||||
|
sheet.Cell(rowNumber, 3).Value = operation.DateEnd.ToRemoteDateTime(timezoneoffsetHours);
|
||||||
|
sheet.Cell(rowNumber, 4).Value = operation.DepthStart;
|
||||||
|
sheet.Cell(rowNumber, 5).Value = operation.DepthEnd;
|
||||||
|
sheet.Cell(rowNumber, 6).Value = operation.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.DetectedOperation;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb;
|
using AsbCloudDb;
|
||||||
@ -7,12 +8,14 @@ using Mapster;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations
|
namespace AsbCloudInfrastructure.Services.DetectOperations
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public class DetectedOperationService : IDetectedOperationService
|
public class DetectedOperationService : IDetectedOperationService
|
||||||
{
|
{
|
||||||
public const int IdOperationRotor = 1;
|
public const int IdOperationRotor = 1;
|
||||||
@ -33,27 +36,50 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
this.scheduleService = scheduleService;
|
this.scheduleService = scheduleService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<DetectedOperationListDto> GetAsync(DetectedOperationRequest request, CancellationToken token)
|
public async Task<DetectedOperationListDto?> GetAsync(DetectedOperationRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var dtos = await GetOperationsAsync(request, token);
|
||||||
|
if (dtos?.Any() != true)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var stats = GetOperationsDrillersStat(dtos);
|
||||||
|
var result = new DetectedOperationListDto
|
||||||
|
{
|
||||||
|
Operations = dtos,
|
||||||
|
Stats = stats
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<DetectedOperationDto>?> GetOperationsAsync(DetectedOperationRequest request, CancellationToken token)
|
||||||
{
|
{
|
||||||
var well = await wellService.GetOrDefaultAsync(request.IdWell, token);
|
var well = await wellService.GetOrDefaultAsync(request.IdWell, token);
|
||||||
if (well?.IdTelemetry is null || well.Timezone is null)
|
if (well?.IdTelemetry is null || well.Timezone is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var query = BuildQuery(well, request)
|
var query = BuildQuery(well, request)
|
||||||
.AsNoTracking();
|
?.AsNoTracking();
|
||||||
|
|
||||||
|
if (query is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
var data = await query.ToListAsync(token);
|
var data = await query.ToListAsync(token);
|
||||||
|
|
||||||
var operationValues = await operationValueService.GetByIdWellAsync(request.IdWell, token);
|
var operationValues = await operationValueService.GetByIdWellAsync(request.IdWell, token);
|
||||||
var schedules = await scheduleService.GetByIdWellAsync(request.IdWell, token);
|
var schedules = await scheduleService.GetByIdWellAsync(request.IdWell, token);
|
||||||
var dtos = data.Select(o => Convert(o, well, operationValues, schedules));
|
var dtos = data.Select(o => Convert(o, well, operationValues, schedules));
|
||||||
var groups = dtos.GroupBy(o => o.Driller);
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
var stats = new List<DetectedOperationStatDto>(groups.Count());
|
private static IEnumerable<DetectedOperationDrillersStatDto> GetOperationsDrillersStat(IEnumerable<DetectedOperationDto> operations)
|
||||||
|
{
|
||||||
|
var groups = operations.GroupBy(o => o.Driller);
|
||||||
|
|
||||||
|
var stats = new List<DetectedOperationDrillersStatDto>(groups.Count());
|
||||||
foreach (var group in groups)
|
foreach (var group in groups)
|
||||||
{
|
{
|
||||||
var itemsWithTarget = group.Where(i => i.OperationValue is not null);
|
var itemsWithTarget = group.Where(i => i.OperationValue is not null);
|
||||||
var stat = new DetectedOperationStatDto
|
var stat = new DetectedOperationDrillersStatDto
|
||||||
{
|
{
|
||||||
Driller = group.Key,
|
Driller = group.Key,
|
||||||
AverageValue = group.Sum(e => e.Value) / group.Count(),
|
AverageValue = group.Sum(e => e.Value) / group.Count(),
|
||||||
@ -62,20 +88,62 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
if (itemsWithTarget.Any())
|
if (itemsWithTarget.Any())
|
||||||
{
|
{
|
||||||
var itemsOutOfTarget = itemsWithTarget.Where(o => !IsTargetOk(o));
|
var itemsOutOfTarget = itemsWithTarget.Where(o => !IsTargetOk(o));
|
||||||
stat.AverageTargetValue = itemsWithTarget.Average(e => e.OperationValue.TargetValue);
|
stat.AverageTargetValue = itemsWithTarget.Average(e => e.OperationValue?.TargetValue);
|
||||||
stat.Efficiency = 100d * itemsOutOfTarget.Count() / itemsWithTarget.Count();
|
stat.Efficiency = 100d * itemsOutOfTarget.Count() / itemsWithTarget.Count();
|
||||||
stat.Loss = itemsOutOfTarget.Sum(DeltaToTarget);
|
stat.Loss = itemsOutOfTarget.Sum(DeltaToTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.Add(stat);
|
stats.Add(stat);
|
||||||
}
|
}
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
var result = new DetectedOperationListDto
|
public async Task<IEnumerable<DetectedOperationStatDto>?> GetOperationsStatAsync(DetectedOperationRequest request, CancellationToken token)
|
||||||
{
|
{
|
||||||
Operations = dtos,
|
var well = await wellService.GetOrDefaultAsync(request.IdWell, token);
|
||||||
Stats = stats
|
if (well?.IdTelemetry is null || well.Timezone is null)
|
||||||
};
|
return null;
|
||||||
return result;
|
|
||||||
|
var query = BuildQuery(well, request)
|
||||||
|
?.AsNoTracking();
|
||||||
|
|
||||||
|
if (query is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var entities = await query
|
||||||
|
.Select(o => new {
|
||||||
|
o.IdCategory,
|
||||||
|
DurationMinutes = (o.DateEnd - o.DateStart).TotalMinutes,
|
||||||
|
o.Value,
|
||||||
|
})
|
||||||
|
.ToListAsync(token);
|
||||||
|
|
||||||
|
if (!entities.Any())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var operationValues = await operationValueService.GetByIdWellAsync(request.IdWell, token);
|
||||||
|
var categories = await query
|
||||||
|
.Select(o => new {o.IdCategory, o.OperationCategory.Name })
|
||||||
|
.Distinct()
|
||||||
|
.ToDictionaryAsync(c=>c.IdCategory, c=>c.Name, token);
|
||||||
|
|
||||||
|
var dtos = entities
|
||||||
|
.GroupBy(o => o.IdCategory)
|
||||||
|
.OrderBy(g => g.Key)
|
||||||
|
.Select(g => new DetectedOperationStatDto{
|
||||||
|
IdCategory = g.Key,
|
||||||
|
Category = categories[g.Key],
|
||||||
|
Count = g.Count(),
|
||||||
|
MinutesAverage = g.Average(o => o.DurationMinutes),
|
||||||
|
MinutesMin = g.Min(o => o.DurationMinutes),
|
||||||
|
MinutesMax = g.Max(o => o.DurationMinutes),
|
||||||
|
MinutesTotal = g.Sum(o => o.DurationMinutes),
|
||||||
|
ValueAverage = g.Average(o => o.Value),
|
||||||
|
ValueMax = g.Max(o => o.Value),
|
||||||
|
ValueMin = g.Min(o => o.Value),
|
||||||
|
});
|
||||||
|
|
||||||
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> DeleteAsync(DetectedOperationRequest request, CancellationToken token)
|
public async Task<int> DeleteAsync(DetectedOperationRequest request, CancellationToken token)
|
||||||
@ -85,6 +153,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
var query = BuildQuery(well, request);
|
var query = BuildQuery(well, request);
|
||||||
|
|
||||||
|
if (query is null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
db.DetectedOperations.RemoveRange(query);
|
db.DetectedOperations.RemoveRange(query);
|
||||||
return await db.SaveChangesAsync(token);
|
return await db.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
@ -93,10 +165,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
{
|
{
|
||||||
return (op.IdCategory) switch
|
return (op.IdCategory) switch
|
||||||
{
|
{
|
||||||
IdOperationRotor => op.Value > op.OperationValue.TargetValue,
|
IdOperationRotor => op.Value > op.OperationValue?.TargetValue,
|
||||||
IdOperationSlide => op.Value > op.OperationValue.TargetValue,
|
IdOperationSlide => op.Value > op.OperationValue?.TargetValue,
|
||||||
IdOperationSlipsTime => op.Value > op.OperationValue.TargetValue,
|
IdOperationSlipsTime => op.Value > op.OperationValue?.TargetValue,
|
||||||
_ => op.Value > op.OperationValue.TargetValue,
|
_ => op.Value > op.OperationValue?.TargetValue,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,12 +178,12 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
{
|
{
|
||||||
IdOperationRotor => 0,
|
IdOperationRotor => 0,
|
||||||
IdOperationSlide => 0,
|
IdOperationSlide => 0,
|
||||||
IdOperationSlipsTime => op.Value - op.OperationValue.TargetValue,
|
IdOperationSlipsTime => op.Value - op.OperationValue?.TargetValue??0,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private IQueryable<DetectedOperation> BuildQuery(WellDto well, DetectedOperationRequest request)
|
private IQueryable<DetectedOperation>? BuildQuery(WellDto well, DetectedOperationRequest request)
|
||||||
{
|
{
|
||||||
if (well?.IdTelemetry is null || well.Timezone is null)
|
if (well?.IdTelemetry is null || well.Timezone is null)
|
||||||
return null;
|
return null;
|
||||||
@ -122,7 +194,8 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
|
|
||||||
if (request is not null)
|
if (request is not null)
|
||||||
{
|
{
|
||||||
query = query.Where(o => request.IdCategory == o.IdCategory);
|
if (request.IdsCategories?.Any() == true)
|
||||||
|
query = query.Where(o => request.IdsCategories.Contains(o.IdCategory));
|
||||||
|
|
||||||
if (request.GtDate is not null)
|
if (request.GtDate is not null)
|
||||||
query = query.Where(o => o.DateStart >= request.GtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours));
|
query = query.Where(o => o.DateStart >= request.GtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours));
|
||||||
@ -182,9 +255,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(int? idWell, CancellationToken token)
|
public async Task<IEnumerable<WellOperationCategoryDto>?> GetCategoriesAsync(int? idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
IQueryable<WellOperationCategory> query = null;
|
IQueryable<WellOperationCategory> query;
|
||||||
if(idWell is null)
|
if(idWell is null)
|
||||||
{
|
{
|
||||||
query = db.WellOperationCategories;
|
query = db.WellOperationCategories;
|
||||||
@ -209,5 +282,12 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
.ToArrayAsync(token);
|
.ToArrayAsync(token);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<Stream> ExportAsync(IEnumerable<int> idsWells, CancellationToken token)
|
||||||
|
{
|
||||||
|
var exportService = new DetectedOperationExportService(db, wellService);
|
||||||
|
return exportService.ExportAsync(idsWells, token);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.DetectedOperation;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -61,6 +63,25 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить статистику по фильтрованному списку операций по телеметрии САУБ
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("stat")]
|
||||||
|
[ProducesResponseType(typeof(IEnumerable<DetectedOperationStatDto>), (int)System.Net.HttpStatusCode.OK)]
|
||||||
|
public async Task<IActionResult> GetStatAsync(
|
||||||
|
[FromQuery] DetectedOperationRequest request,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
if (!await UserHasAccesToWellAsync(request.IdWell, token))
|
||||||
|
return Forbid();
|
||||||
|
|
||||||
|
var result = await detectedOperationService.GetOperationsStatAsync(request, token);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Удалить операции.
|
/// Удалить операции.
|
||||||
/// Удаленные операции будут определены повторно сервисом автоматизированного определения операций.
|
/// Удаленные операции будут определены повторно сервисом автоматизированного определения операций.
|
||||||
@ -92,5 +113,46 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Создает excel файл с операциями по скважине
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell">id скважины</param>
|
||||||
|
/// <param name="idCluster"></param>
|
||||||
|
/// <param name="token"> Токен отмены задачи </param>
|
||||||
|
/// <returns>Запрашиваемый файл</returns>
|
||||||
|
[HttpGet]
|
||||||
|
[Route("export")]
|
||||||
|
[Permission]
|
||||||
|
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
|
||||||
|
public async Task<IActionResult> ExportAsync(int? idWell, int? idCluster, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
if (idCluster is null && idWell is null)
|
||||||
|
return this.MakeBadRequest(nameof(idWell), $"One of {nameof(idWell)} or {nameof(idCluster)} mast be set.");
|
||||||
|
|
||||||
|
int? idCompany = User.GetCompanyId();
|
||||||
|
|
||||||
|
if (idCompany is null)
|
||||||
|
return Forbid();
|
||||||
|
|
||||||
|
IEnumerable<int> idsWells;
|
||||||
|
if (idCluster is not null)
|
||||||
|
{
|
||||||
|
var companyWells = await wellService.GetWellsByCompanyAsync((int)idCompany, token);
|
||||||
|
idsWells = companyWells.Where(w => w.IdCluster == idCluster)
|
||||||
|
.Select(w=>w.Id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||||
|
(int)idWell, token).ConfigureAwait(false))
|
||||||
|
return Forbid();
|
||||||
|
idsWells = new List<int> { (int)idWell };
|
||||||
|
}
|
||||||
|
|
||||||
|
var stream = await detectedOperationService.ExportAsync(idsWells, token);
|
||||||
|
var fileName = "operations.xlsx";
|
||||||
|
return File(stream, "application/octet-stream", fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,7 +268,6 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
return File(stream, "application/octet-stream", fileName);
|
return File(stream, "application/octet-stream", fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Создает excel файл с "сетевым графиком"
|
/// Создает excel файл с "сетевым графиком"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user