forked from ddrilling/AsbCloudServer
Формирование и экспорт отчёта
This commit is contained in:
parent
28788bde1f
commit
307c29fcfd
@ -1,10 +0,0 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.WellReport;
|
||||
|
||||
namespace AsbCloudApp.Services;
|
||||
|
||||
public interface IWellReportService
|
||||
{
|
||||
Task<WellReportDto> GetAsync(int idWell, CancellationToken token);
|
||||
}
|
19
AsbCloudApp/Services/WellReport/IWellReportExportService.cs
Normal file
19
AsbCloudApp/Services/WellReport/IWellReportExportService.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
|
||||
namespace AsbCloudApp.Services.WellReport;
|
||||
|
||||
/// <summary>
|
||||
/// Сервис экспорта отчёта
|
||||
/// </summary>
|
||||
public interface IWellReportExportService
|
||||
{
|
||||
/// <summary>
|
||||
/// Экспортировать
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<(string Name, Stream File)?> ExportAsync(int idWell, CancellationToken token);
|
||||
}
|
19
AsbCloudApp/Services/WellReport/IWellReportService.cs
Normal file
19
AsbCloudApp/Services/WellReport/IWellReportService.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.WellReport;
|
||||
|
||||
namespace AsbCloudApp.Services.WellReport;
|
||||
|
||||
/// <summary>
|
||||
/// Сервис формирования отчёта
|
||||
/// </summary>
|
||||
public interface IWellReportService
|
||||
{
|
||||
/// <summary>
|
||||
/// Сформировать
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<WellReportDto?> GetAsync(int idWell, CancellationToken token);
|
||||
}
|
@ -53,6 +53,7 @@
|
||||
<EmbeddedResource Include="Services\ProcessMaps\Report\ProcessMapReportTemplate.xlsx" />
|
||||
<EmbeddedResource Include="Services\WellOperations\Templates\WellOperationFactTemplate.xlsx" />
|
||||
<EmbeddedResource Include="Services\WellOperations\Templates\WellOperationPlanTemplate.xlsx" />
|
||||
<EmbeddedResource Include="Services\WellReport\WellReport.xlsx" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -47,6 +47,8 @@ using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using AsbCloudApp.Services.WellReport;
|
||||
using AsbCloudInfrastructure.Services.WellReport;
|
||||
|
||||
namespace AsbCloudInfrastructure;
|
||||
|
||||
@ -469,6 +471,8 @@ public static class DependencyInjection
|
||||
services.AddTransient<ITrajectoryEditableRepository<TrajectoryGeoPlanDto>, TrajectoryEditableRepository<TrajectoryPlan, TrajectoryGeoPlanDto>>();
|
||||
services.AddTransient<ITrajectoryEditableRepository<TrajectoryGeoFactDto>, TrajectoryEditableRepository<TrajectoryFact, TrajectoryGeoFactDto>>();
|
||||
services.AddTransient<ITrajectoryNnbRepository, TrajectoryNnbRepository>();
|
||||
services.AddTransient<ITrajectoryRepository<TrajectoryGeoPlanDto>, TrajectoryEditableRepository<TrajectoryPlan, TrajectoryGeoPlanDto>>();
|
||||
services.AddTransient<ITrajectoryRepository<TrajectoryGeoFactDto>, TrajectoryEditableRepository<TrajectoryFact, TrajectoryGeoFactDto>>();
|
||||
services.AddTransient<IFaqRepository, FaqRepository>();
|
||||
services.AddTransient<ISlipsStatService, SlipsStatService>();
|
||||
services.AddTransient<IWellContactService, WellContactService>();
|
||||
@ -563,6 +567,9 @@ public static class DependencyInjection
|
||||
services.AddTransient<WellOperationParserFactory>();
|
||||
services.AddTransient<WellOperationExportServiceFactory>();
|
||||
|
||||
services.AddTransient<IWellReportService, WellReportService>();
|
||||
services.AddTransient<IWellReportExportService, WellReportExportService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
BIN
AsbCloudInfrastructure/Services/WellReport/WellReport.xlsx
Normal file
BIN
AsbCloudInfrastructure/Services/WellReport/WellReport.xlsx
Normal file
Binary file not shown.
@ -0,0 +1,382 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.Subsystems;
|
||||
using AsbCloudApp.Data.User;
|
||||
using AsbCloudApp.Data.WellReport;
|
||||
using AsbCloudApp.Services.WellReport;
|
||||
using ClosedXML.Excel;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.WellReport;
|
||||
|
||||
public class WellReportExportService : IWellReportExportService
|
||||
{
|
||||
private static readonly IDictionary<int, int> PlanOperatingModeRows = new Dictionary<int, int>()
|
||||
{
|
||||
{ 2, 79 }, // Направление план
|
||||
{ 3, 81 }, // Кондуктор план
|
||||
{ 9, 83 }, // Кондуктор 2 план
|
||||
{ 1, 85 }, // Пилотный ствол план
|
||||
{ 7, 87 }, // Пилотный ствол 2 план
|
||||
{ 13, 89 }, // Пилотный ствол 3 план
|
||||
{ 4, 91 }, // Эксплуатационная колонна план
|
||||
{ 10, 93 }, // Эксплуатационная колонна 2 план
|
||||
{ 6, 95 }, // Хвостовик план
|
||||
{ 12, 97 }, // Хвостовик 2 план
|
||||
{ 18, 99 }, // Хвостовик 3 план
|
||||
{ 24, 101 }, // Хвостовик 4 план
|
||||
{ 30, 103 }, // Хвостовик 5 план
|
||||
{ 34, 105 }, // Хвостовик 6 план
|
||||
{ 35, 107 }, // Хвостовик 7 план
|
||||
{ 36, 109 }, // Хвостовик 8 план
|
||||
{ 37, 111 }, // Хвостовик 9 план
|
||||
{ 38, 113 } // Хвостовик 10 план
|
||||
};
|
||||
|
||||
private static readonly IDictionary<int, int> FactOperatingModeRows = new Dictionary<int, int>
|
||||
{
|
||||
{ 2, 80 }, // Направление факт
|
||||
{ 3, 82 }, // Кондуктор факт
|
||||
{ 9, 84 }, // Кондуктор 2 факт
|
||||
{ 1, 86 }, // Пилотный ствол факт
|
||||
{ 7, 88 }, // Пилотный ствол 2 факт
|
||||
{ 13, 90 }, // Пилотный ствол 3 факт
|
||||
{ 4, 92 }, // Эксплуатационная колонна факт
|
||||
{ 10, 94 }, // Эксплуатационная колонна 2 факт
|
||||
{ 6, 96 }, // Хвостовик факт
|
||||
{ 12, 98 }, // Хвостовик 2 факт
|
||||
{ 18, 100 }, // Хвостовик 3 факт
|
||||
{ 24, 102 }, // Хвостовик 4 факт
|
||||
{ 30, 104 }, // Хвостовик 5 факт
|
||||
{ 34, 106 }, // Хвостовик 6 факт
|
||||
{ 35, 108 }, // Хвостовик 7 факт
|
||||
{ 36, 110 }, // Хвостовик 8 факт
|
||||
{ 37, 112 }, // Хвостовик 9 факт
|
||||
{ 38, 114 } // Хвостовик 10 факт
|
||||
};
|
||||
|
||||
private static readonly IDictionary<int, int> SubsystemRows = new Dictionary<int, int>()
|
||||
{
|
||||
{ 2, 140 }, // Направление
|
||||
{ 3, 141 }, // Кондуктор
|
||||
{ 9, 142 }, // Кондуктор 2
|
||||
{ 1, 143 }, // Пилотный ствол
|
||||
{ 7, 144 }, // Пилотный ствол 2
|
||||
{ 13, 145 }, // Пилотный ствол 3
|
||||
{ 4, 146 }, // Эксплуатационная колонна
|
||||
{ 10, 147 }, // Эксплуатационная колонна 2
|
||||
{ 6, 148 }, // Хвостовик
|
||||
{ 12, 149 }, // Хвостовик 2
|
||||
{ 18, 150 }, // Хвостовик 3
|
||||
{ 24, 151 }, // Хвостовик 4
|
||||
{ 30, 152 }, // Хвостовик 5
|
||||
{ 34, 153 }, // Хвостовик 6
|
||||
{ 35, 154 }, // Хвостовик 7
|
||||
{ 36, 155 }, // Хвостовик 8
|
||||
{ 37, 156 }, // Хвостовик 9
|
||||
{ 38, 157 } // Хвостовик 10
|
||||
};
|
||||
|
||||
private static readonly IDictionary<int, int> SetpointsRows = new Dictionary<int, int>()
|
||||
{
|
||||
{ 2, 161 }, // Направление
|
||||
{ 3, 162 }, // Кондуктор
|
||||
{ 9, 163 }, // Кондуктор 2
|
||||
{ 1, 164 }, // Пилотный ствол
|
||||
{ 7, 165 }, // Пилотный ствол 2
|
||||
{ 13, 166 }, // Пилотный ствол 3
|
||||
{ 4, 167 }, // Эксплуатационная колонна
|
||||
{ 10, 168 }, // Эксплуатационная колонна 2
|
||||
{ 6, 169 }, // Хвостовик
|
||||
{ 12, 170 }, // Хвостовик 2
|
||||
{ 18, 171 }, // Хвостовик 3
|
||||
{ 24, 172 }, // Хвостовик 4
|
||||
{ 30, 173 }, // Хвостовик 5
|
||||
{ 34, 174 }, // Хвостовик 6
|
||||
{ 35, 175 }, // Хвостовик 7
|
||||
{ 36, 176 }, // Хвостовик 8
|
||||
{ 37, 177 }, // Хвостовик 9
|
||||
{ 38, 178 } // Хвостовик 10
|
||||
};
|
||||
|
||||
private const string TemplateName = "WellReport.xlsx";
|
||||
private const string SheetName = "Отчёт";
|
||||
|
||||
private readonly IWellReportService wellReportService;
|
||||
|
||||
private const string DateFromCell = "D5";
|
||||
private const string DateToCell = "E5";
|
||||
private const string DaysPlanCell = "D6";
|
||||
private const string DaysFactCell = "E6";
|
||||
private const string WithoutNtpDaysCell = "D8";
|
||||
private const string WellBoreDepthPlanCell = "D12";
|
||||
private const string VerticalDepthPlanCell = "E12";
|
||||
private const string WellBoreDepthFactCell = "D13";
|
||||
private const string VerticalDepthFactCell = "E13";
|
||||
private const string WellCell = "I5";
|
||||
private const string ClusterCell = "I6";
|
||||
private const string DepositCell = "I7";
|
||||
private const string CustomerCell = "N5";
|
||||
|
||||
public WellReportExportService(IWellReportService wellReportService)
|
||||
{
|
||||
this.wellReportService = wellReportService;
|
||||
}
|
||||
|
||||
public async Task<(string Name, Stream File)?> ExportAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var report = await wellReportService.GetAsync(idWell, token);
|
||||
|
||||
if (report == null)
|
||||
return null;
|
||||
|
||||
var stream = Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateName);
|
||||
using var workbook = new XLWorkbook(stream);
|
||||
|
||||
var sheet = workbook.GetWorksheet(SheetName);
|
||||
|
||||
FillSheet(sheet, report);
|
||||
|
||||
MemoryStream memoryStream = new();
|
||||
workbook.SaveAs(memoryStream, new SaveOptions { });
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var name = $"Отчёт по скважине {report.Well.Caption} куст {report.Well.Cluster}.xlsx";
|
||||
|
||||
return (name, memoryStream);
|
||||
}
|
||||
|
||||
private static void FillSheet(IXLWorksheet sheet, WellReportDto report)
|
||||
{
|
||||
sheet.Cell(DateFromCell).SetCellValue(report.DateFrom);
|
||||
sheet.Cell(DateToCell).SetCellValue(report.DateTo);
|
||||
sheet.Cell(DaysPlanCell).SetCellValue(report.Days.Plan);
|
||||
sheet.Cell(DaysFactCell).SetCellValue(report.Days.Fact);
|
||||
sheet.Cell(WithoutNtpDaysCell).SetCellValue(report.WithoutNtpDays);
|
||||
sheet.Cell(WellBoreDepthPlanCell).SetCellValue(report.WellBoreDepth.Plan);
|
||||
sheet.Cell(WellBoreDepthFactCell).SetCellValue(report.WellBoreDepth.Fact);
|
||||
sheet.Cell(VerticalDepthPlanCell).SetCellValue(report.VerticalDepth.Plan);
|
||||
sheet.Cell(VerticalDepthFactCell).SetCellValue(report.VerticalDepth.Fact);
|
||||
sheet.Cell(WellCell).SetCellValue(report.Well.Caption);
|
||||
sheet.Cell(ClusterCell).SetCellValue(report.Well.Cluster);
|
||||
sheet.Cell(DepositCell).SetCellValue(report.Well.Deposit);
|
||||
|
||||
var customer = report.Well.Companies.FirstOrDefault(x => x.IdCompanyType == 1);
|
||||
sheet.Cell(CustomerCell).SetCellValue(customer?.Caption);
|
||||
|
||||
FillContacts(sheet, report.Contacts);
|
||||
FillSectionReports(sheet, report.SectionReports);
|
||||
FillDrillerReports(sheet, report.DrillerReports);
|
||||
}
|
||||
|
||||
private static void FillContacts(IXLWorksheet sheet, IEnumerable<ContactDto> contacts)
|
||||
{
|
||||
var positionsByCompanyType = new Dictionary<int, string>()
|
||||
{
|
||||
{ 7, "Супервайзер" },
|
||||
{ 2, "Мастер" },
|
||||
{ 3, "Инженер по автоматизации" },
|
||||
{ 5, "Инженер по р-рам " },
|
||||
{ 6, "Инженер ННБ" },
|
||||
{ 14, "Инженер по долотам" },
|
||||
{ 4, "Инженер ГТИ" },
|
||||
{ 9, "Инженер по цементированию" }
|
||||
};
|
||||
|
||||
const int positionColumn = 11;
|
||||
const int fullNameColumn = 14;
|
||||
const int companyColumn = 16;
|
||||
const int phoneColumn = 18;
|
||||
|
||||
contacts = contacts.OrderByDescending(x => x.Id)
|
||||
.GroupBy(x => x.IdCompanyType)
|
||||
.Select(x => x.First());
|
||||
|
||||
var row = 6;
|
||||
|
||||
foreach (var contact in contacts)
|
||||
{
|
||||
var position = positionsByCompanyType[contact.IdCompanyType];
|
||||
|
||||
sheet.Cell(row, positionColumn).SetCellValue(position);
|
||||
sheet.Cell(row, fullNameColumn).SetCellValue(contact.FullName);
|
||||
sheet.Cell(row, companyColumn).SetCellValue(contact.Company);
|
||||
sheet.Cell(row, phoneColumn).SetCellValue(contact.Phone);
|
||||
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
private static void FillDrillerReports(IXLWorksheet sheet, IEnumerable<DrillerReportDto> drillerReports)
|
||||
{
|
||||
drillerReports = drillerReports.OrderBy(x => x.Shedule.DrillStart);
|
||||
|
||||
const int IdSubsystemAPDRotor = 11;
|
||||
const int IdSubsystemAPDSlide = 12;
|
||||
const int IdSubsystemOscillation = 65536;
|
||||
|
||||
const int fullNameColumn = 1;
|
||||
const int drillStartColumn = 5;
|
||||
const int drillEndColumn = 6;
|
||||
const int shiftStart = 7;
|
||||
const int shiftEnd = 8;
|
||||
const int kUsageApdRotorColumn = 9;
|
||||
const int kUsageApdSlideColumn = 10;
|
||||
const int kUsageOscillationColumn = 11;
|
||||
|
||||
var row = 182;
|
||||
|
||||
foreach (var drillingReport in drillerReports)
|
||||
{
|
||||
sheet.Cell(row, fullNameColumn).SetCellValue(drillingReport.Shedule.Driller?.FullName);
|
||||
sheet.Cell(row, drillStartColumn).SetCellValue(drillingReport.Shedule.DrillStart);
|
||||
sheet.Cell(row, drillEndColumn).SetCellValue(drillingReport.Shedule.DrillEnd);
|
||||
sheet.Cell(row, shiftStart).SetCellValue(drillingReport.Shedule.ShiftStart.ToString());
|
||||
sheet.Cell(row, shiftEnd).SetCellValue(drillingReport.Shedule.ShiftEnd.ToString());
|
||||
|
||||
foreach (var subsystemStat in drillingReport.SubsystemsStat)
|
||||
{
|
||||
switch (subsystemStat.IdSubsystem)
|
||||
{
|
||||
case IdSubsystemAPDRotor:
|
||||
sheet.Cell(row, kUsageApdRotorColumn).SetCellValue(subsystemStat.KUsage);
|
||||
break;
|
||||
case IdSubsystemAPDSlide:
|
||||
sheet.Cell(row, kUsageApdSlideColumn).SetCellValue(subsystemStat.KUsage);
|
||||
break;
|
||||
case IdSubsystemOscillation:
|
||||
sheet.Cell(row, kUsageOscillationColumn).SetCellValue(subsystemStat.KUsage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
private static void FillSectionReports(IXLWorksheet sheet, IEnumerable<SectionReportDto> sectionReports)
|
||||
{
|
||||
foreach (var sectionReport in sectionReports)
|
||||
{
|
||||
FillOperatingMode(sheet, sectionReport.IdSection, sectionReport.OperatingMode);
|
||||
|
||||
var drillingBySetpoints = sectionReport.DrillingBySetpoints;
|
||||
|
||||
if (drillingBySetpoints != null)
|
||||
FillDrillingBySetpoints(sheet, sectionReport.IdSection, drillingBySetpoints);
|
||||
|
||||
FillSubsystemsStat(sheet, sectionReport.IdSection, sectionReport.SubsystemsStat);
|
||||
}
|
||||
}
|
||||
|
||||
private static void FillDrillingBySetpoints(IXLWorksheet sheet, int idSection,
|
||||
DrillingBySetpointsDto drillingBySetpoints)
|
||||
{
|
||||
const int pressureColumn = 8;
|
||||
const int axialLoadColumn = 9;
|
||||
const int topDriveTorqueColumn = 10;
|
||||
const int speedLimitColumn = 11;
|
||||
|
||||
if (!SetpointsRows.TryGetValue(idSection, out var row))
|
||||
return;
|
||||
|
||||
sheet.Cell(row, pressureColumn).SetCellValue(drillingBySetpoints.Pressure);
|
||||
sheet.Cell(row, axialLoadColumn).SetCellValue(drillingBySetpoints.AxialLoad);
|
||||
sheet.Cell(row, topDriveTorqueColumn).SetCellValue(drillingBySetpoints.TopDriveTorque);
|
||||
sheet.Cell(row, speedLimitColumn).SetCellValue(drillingBySetpoints.SpeedLimit);
|
||||
}
|
||||
|
||||
private static void FillSubsystemsStat(IXLWorksheet sheet, int idSection,
|
||||
IEnumerable<SubsystemStatDto> subsystemsStat)
|
||||
{
|
||||
const int idSubsystemAPDRotor = 11;
|
||||
const int idSubsystemAPDSlide = 12;
|
||||
const int idSubsystemOscillation = 65536;
|
||||
|
||||
const int kUsageApdRotorColumn = 3;
|
||||
const int kUsageApdSlideColumn = 4;
|
||||
const int kUsageOscillationColumn = 5;
|
||||
|
||||
const int sumDepthIntervalApdRotorColumn = 14;
|
||||
const int sumDepthIntervalApdSlideColumn = 15;
|
||||
const int sumDepthIntervalApdOscillation = 17;
|
||||
|
||||
if (!SubsystemRows.TryGetValue(idSection, out var row))
|
||||
return;
|
||||
|
||||
foreach (var subsystemStat in subsystemsStat)
|
||||
{
|
||||
switch (subsystemStat.IdSubsystem)
|
||||
{
|
||||
case idSubsystemAPDRotor:
|
||||
sheet.Cell(row, kUsageApdRotorColumn).SetCellValue(subsystemStat.KUsage);
|
||||
sheet.Cell(row, sumDepthIntervalApdRotorColumn).SetCellValue(subsystemStat.SumDepthInterval);
|
||||
break;
|
||||
case idSubsystemAPDSlide:
|
||||
sheet.Cell(row, kUsageApdSlideColumn).SetCellValue(subsystemStat.KUsage);
|
||||
sheet.Cell(row, sumDepthIntervalApdSlideColumn).SetCellValue(subsystemStat.SumDepthInterval);
|
||||
break;
|
||||
case idSubsystemOscillation:
|
||||
sheet.Cell(row, kUsageOscillationColumn).SetCellValue(subsystemStat.KUsage);
|
||||
sheet.Cell(row, sumDepthIntervalApdOscillation).SetCellValue(subsystemStat.SumDepthInterval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void FillOperatingMode(IXLWorksheet sheet, int idSection,
|
||||
PlanFactDto<OperatingModeDto> operatingMode)
|
||||
{
|
||||
const int depthStartColumn = 3;
|
||||
const int depthEndColumn = 4;
|
||||
const int ropMinColumn = 6;
|
||||
const int ropMaxColumn = 7;
|
||||
const int ropAvgColumn = 8;
|
||||
const int weightOnBitMinColumn = 9;
|
||||
const int weightOnBitMaxColumn = 10;
|
||||
const int weightOnBitAvgColumn = 11;
|
||||
const int driveTorqueMinColumn = 12;
|
||||
const int driveTorqueMaxColumn = 13;
|
||||
const int driveTorqueAvgColumn = 14;
|
||||
const int differentialPressureMinColumn = 15;
|
||||
const int differentialPressureMaxColumn = 16;
|
||||
const int differentialPressureAvgColumn = 17;
|
||||
const int frowRateMinColumn = 18;
|
||||
const int frowRateMaxColumn = 19;
|
||||
|
||||
if (!PlanOperatingModeRows.TryGetValue(idSection, out var planRow))
|
||||
return;
|
||||
|
||||
if (!FactOperatingModeRows.TryGetValue(idSection, out var factRow))
|
||||
return;
|
||||
|
||||
sheet.Cell(planRow, depthStartColumn).SetCellValue(operatingMode.Plan?.DepthStart);
|
||||
sheet.Cell(planRow, depthEndColumn).SetCellValue(operatingMode.Plan?.DepthEnd);
|
||||
|
||||
sheet.Cell(planRow, ropMinColumn).SetCellValue(operatingMode.Plan?.RopMin);
|
||||
sheet.Cell(planRow, ropMaxColumn).SetCellValue(operatingMode.Plan?.RopMax);
|
||||
sheet.Cell(planRow, ropAvgColumn).SetCellValue(operatingMode.Plan?.RopAvg);
|
||||
|
||||
sheet.Cell(planRow, weightOnBitMinColumn).SetCellValue(operatingMode.Plan?.WeightOnBitMin);
|
||||
sheet.Cell(planRow, weightOnBitMaxColumn).SetCellValue(operatingMode.Plan?.WeightOnBitMax);
|
||||
sheet.Cell(planRow, weightOnBitAvgColumn).SetCellValue(operatingMode.Plan?.WeightOnBitAvg);
|
||||
|
||||
sheet.Cell(planRow, driveTorqueMinColumn).SetCellValue(operatingMode.Plan?.DriveTorqueMin);
|
||||
sheet.Cell(planRow, driveTorqueMaxColumn).SetCellValue(operatingMode.Plan?.DriveTorqueMax);
|
||||
sheet.Cell(planRow, driveTorqueAvgColumn).SetCellValue(operatingMode.Plan?.DriveTorqueAvg);
|
||||
|
||||
sheet.Cell(planRow, differentialPressureMinColumn).SetCellValue(operatingMode.Plan?.DifferentialPressureMin);
|
||||
sheet.Cell(planRow, differentialPressureMaxColumn).SetCellValue(operatingMode.Plan?.DifferentialPressureMax);
|
||||
sheet.Cell(planRow, differentialPressureAvgColumn).SetCellValue(operatingMode.Plan?.DifferentialPressureAvg);
|
||||
|
||||
sheet.Cell(planRow, frowRateMinColumn).SetCellValue(operatingMode.Plan?.FrowRateMin);
|
||||
sheet.Cell(planRow, frowRateMaxColumn).SetCellValue(operatingMode.Plan?.FrowRateMax);
|
||||
|
||||
sheet.Cell(factRow, depthStartColumn).SetCellValue(operatingMode.Fact?.DepthStart);
|
||||
sheet.Cell(factRow, depthEndColumn).SetCellValue(operatingMode.Fact?.DepthEnd);
|
||||
}
|
||||
}
|
234
AsbCloudInfrastructure/Services/WellReport/WellReportService.cs
Normal file
234
AsbCloudInfrastructure/Services/WellReport/WellReportService.cs
Normal file
@ -0,0 +1,234 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.ProcessMaps.Operations;
|
||||
using AsbCloudApp.Data.Trajectory;
|
||||
using AsbCloudApp.Data.WellOperation;
|
||||
using AsbCloudApp.Data.WellReport;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
||||
using AsbCloudApp.Services.WellReport;
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.WellReport;
|
||||
|
||||
public class WellReportService : IWellReportService
|
||||
{
|
||||
private readonly IWellService wellService;
|
||||
private readonly IWellOperationService wellOperationService;
|
||||
private readonly IWellContactService wellContactService;
|
||||
private readonly IProcessMapReportDrillingService processMapReportDrillingService;
|
||||
private readonly ISubsystemService subsystemService;
|
||||
|
||||
private readonly ITrajectoryRepository<TrajectoryGeoPlanDto> trajectoryPlanRepository;
|
||||
private readonly ITrajectoryRepository<TrajectoryGeoFactDto> trajectoryFactRepository;
|
||||
|
||||
private readonly IChangeLogRepository<ProcessMapPlanRotorDto, ProcessMapPlanBaseRequestWithWell>
|
||||
processMapPlanRotorRepository;
|
||||
|
||||
private readonly IScheduleRepository scheduleRepository;
|
||||
|
||||
private IEnumerable<WellOperationDto> factWellOperations;
|
||||
private IEnumerable<WellOperationDto> planWellOperations;
|
||||
|
||||
public WellReportService(IWellService wellService, IWellOperationService wellOperationService,
|
||||
IWellContactService wellContactService, IProcessMapReportDrillingService processMapReportDrillingService,
|
||||
ISubsystemService subsystemService, ITrajectoryRepository<TrajectoryGeoPlanDto> trajectoryPlanRepository,
|
||||
ITrajectoryRepository<TrajectoryGeoFactDto> trajectoryFactRepository,
|
||||
IChangeLogRepository<ProcessMapPlanRotorDto, ProcessMapPlanBaseRequestWithWell> processMapPlanRotorRepository,
|
||||
IScheduleRepository scheduleRepository, IEnumerable<WellOperationDto> factWellOperations,
|
||||
IEnumerable<WellOperationDto> planWellOperations)
|
||||
{
|
||||
this.wellService = wellService;
|
||||
this.wellOperationService = wellOperationService;
|
||||
this.wellContactService = wellContactService;
|
||||
this.processMapReportDrillingService = processMapReportDrillingService;
|
||||
this.subsystemService = subsystemService;
|
||||
this.trajectoryPlanRepository = trajectoryPlanRepository;
|
||||
this.trajectoryFactRepository = trajectoryFactRepository;
|
||||
this.processMapPlanRotorRepository = processMapPlanRotorRepository;
|
||||
this.scheduleRepository = scheduleRepository;
|
||||
this.factWellOperations = factWellOperations;
|
||||
this.planWellOperations = planWellOperations;
|
||||
}
|
||||
|
||||
public async Task<WellReportDto?> GetAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var well = await wellService.GetOrDefaultAsync(idWell, token);
|
||||
|
||||
if (well == null)
|
||||
return null;
|
||||
|
||||
await InitWellOperations(idWell, token);
|
||||
|
||||
var wellContactRequest = new WellContactRequest
|
||||
{
|
||||
IdsWells = new[] { idWell },
|
||||
};
|
||||
|
||||
var contacts = await wellContactService.GetAllAsync(wellContactRequest, token);
|
||||
|
||||
var sectionReports = await GetSectionReportsAsync(idWell, token);
|
||||
var drillerReports = await GetDrillerReportsAsync(idWell, token);
|
||||
|
||||
var firstFactOperation = factWellOperations.MinByOrDefault(x => x.DateStart);
|
||||
var lastFactOperation = factWellOperations.MaxByOrDefault(x => x.DateStart);
|
||||
|
||||
var lastPlanOperation = planWellOperations.MaxByOrDefault(x => x.DateStart);
|
||||
|
||||
var planTrajectories = await trajectoryPlanRepository.GetAsync(idWell, token);
|
||||
var factTrajectories = await trajectoryFactRepository.GetAsync(idWell, token);
|
||||
|
||||
var factOperationsWithoutNpt = factWellOperations
|
||||
.Where(x => x.NptHours == 0);
|
||||
|
||||
return new WellReportDto
|
||||
{
|
||||
Well = well,
|
||||
DateFrom = firstFactOperation?.DateStart,
|
||||
DateTo = lastPlanOperation?.DateStart.AddHours(lastPlanOperation.DurationHours),
|
||||
Days = new PlanFactDto<double?>
|
||||
{
|
||||
Plan = lastPlanOperation?.Day,
|
||||
Fact = lastFactOperation?.Day
|
||||
},
|
||||
WellBoreDepth = new PlanFactDto<double?>
|
||||
{
|
||||
Plan = planWellOperations.MaxOrDefault(x => x.DepthEnd),
|
||||
Fact = factWellOperations.MaxOrDefault(x => x.DepthEnd)
|
||||
},
|
||||
VerticalDepth = new PlanFactDto<double?>
|
||||
{
|
||||
Plan = planTrajectories.Max(x => x.VerticalDepth),
|
||||
Fact = factTrajectories.Max(x => x.VerticalDepth)
|
||||
},
|
||||
WithoutNtpDays = factOperationsWithoutNpt.Sum(x => x.Day),
|
||||
Contacts = contacts,
|
||||
SectionReports = sectionReports,
|
||||
DrillerReports = drillerReports,
|
||||
};
|
||||
}
|
||||
|
||||
private async Task InitWellOperations(int idWell, CancellationToken token)
|
||||
{
|
||||
var request = new WellOperationRequest(new[] { idWell })
|
||||
{
|
||||
OperationType = WellOperation.IdOperationTypeFact
|
||||
};
|
||||
|
||||
factWellOperations = await wellOperationService.GetAsync(request, token);
|
||||
|
||||
request.OperationType = WellOperation.IdOperationTypePlan;
|
||||
|
||||
planWellOperations = await wellOperationService.GetAsync(request, token);
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<SectionReportDto>> GetSectionReportsAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var factWellOperationsBySection = factWellOperations.GroupBy(x => x.IdWellSectionType);
|
||||
|
||||
var processMapPlanRequest = new ProcessMapPlanBaseRequestWithWell(idWell);
|
||||
|
||||
var processMapPlanRotorBySection =
|
||||
(await processMapPlanRotorRepository.GetCurrent(processMapPlanRequest, token))
|
||||
.GroupBy(x => x.IdWellSectionType)
|
||||
.ToDictionary(x => x.Key, x => x.AsEnumerable());
|
||||
|
||||
var dataSaubStatRequest = new DataSaubStatRequest();
|
||||
|
||||
var processMapReportBySection =
|
||||
(await processMapReportDrillingService.GetAsync(idWell, dataSaubStatRequest, token))
|
||||
.GroupBy(x => x.IdWellSectionType)
|
||||
.ToDictionary(x => x.Key, x => x.AsEnumerable());
|
||||
|
||||
var sectionReports = new List<SectionReportDto>();
|
||||
|
||||
foreach (var group in factWellOperationsBySection)
|
||||
{
|
||||
var subsystemRequest = new SubsystemRequest
|
||||
{
|
||||
IdWell = idWell,
|
||||
GeDepth = group.Min(y => y.DepthStart),
|
||||
LeDepth = group.Max(y => y.DepthEnd)
|
||||
};
|
||||
|
||||
var sectionReport = new SectionReportDto
|
||||
{
|
||||
IdSection = group.Key,
|
||||
SubsystemsStat = await subsystemService.GetStatAsync(subsystemRequest, token),
|
||||
OperatingMode = new PlanFactDto<OperatingModeDto>
|
||||
{
|
||||
Fact = new OperatingModeDto
|
||||
{
|
||||
DepthStart = factWellOperations.Min(w => w.DepthStart),
|
||||
DepthEnd = factWellOperations.Max(w => w.DepthEnd)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (processMapPlanRotorBySection.TryGetValue(group.Key, out var processMapPlanRotor))
|
||||
sectionReport.OperatingMode.Plan = new OperatingModeDto
|
||||
{
|
||||
DepthStart = processMapPlanRotor.Min(p => p.DepthStart),
|
||||
DepthEnd = processMapPlanRotor.Max(p => p.DepthEnd),
|
||||
RopMin = processMapPlanRotor.Min(p => p.RopMax),
|
||||
RopMax = processMapPlanRotor.Max(p => p.RopMax),
|
||||
RopAvg = processMapPlanRotor.Average(p => p.RopMax),
|
||||
WeightOnBitMin = processMapPlanRotor.Min(p => p.WeightOnBit),
|
||||
WeightOnBitMax = processMapPlanRotor.Max(p => p.WeightOnBitMax),
|
||||
WeightOnBitAvg = processMapPlanRotor.Average(p => p.WeightOnBit),
|
||||
DriveTorqueMin = processMapPlanRotor.Min(p => p.TopDriveTorque),
|
||||
DriveTorqueMax = processMapPlanRotor.Max(p => p.TopDriveTorqueMax),
|
||||
DriveTorqueAvg = processMapPlanRotor.Average(p => p.TopDriveTorque),
|
||||
DifferentialPressureMin = processMapPlanRotor.Min(p => p.DifferentialPressure),
|
||||
DifferentialPressureMax = processMapPlanRotor.Max(p => p.DifferentialPressureMax),
|
||||
DifferentialPressureAvg = processMapPlanRotor.Average(p => p.DifferentialPressure),
|
||||
FrowRateMin = processMapPlanRotor.Min(p => p.FlowRate),
|
||||
FrowRateMax = processMapPlanRotor.Max(p => p.FlowRateMax)
|
||||
};
|
||||
|
||||
if (processMapReportBySection.TryGetValue(group.Key, out var processMapReport))
|
||||
sectionReport.DrillingBySetpoints = new DrillingBySetpointsDto
|
||||
{
|
||||
Pressure = processMapReport.Sum(x => x.DeltaDepth * x.PressureDiff.SetpointUsage / 100),
|
||||
AxialLoad = processMapReport.Sum(x => x.DeltaDepth * x.AxialLoad.SetpointUsage / 100),
|
||||
TopDriveTorque = processMapReport.Sum(x => x.DeltaDepth * x.TopDriveTorque.SetpointUsage / 100),
|
||||
SpeedLimit = processMapReport.Sum(x => x.DeltaDepth * x.SpeedLimit.SetpointUsage / 100)
|
||||
};
|
||||
|
||||
sectionReports.Add(sectionReport);
|
||||
}
|
||||
|
||||
return sectionReports;
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<DrillerReportDto>> GetDrillerReportsAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var schedules = await scheduleRepository.GetByIdWellAsync(idWell, token);
|
||||
|
||||
var result = new List<DrillerReportDto>();
|
||||
|
||||
foreach (var schedule in schedules)
|
||||
{
|
||||
var subsystemRequest = new SubsystemRequest
|
||||
{
|
||||
IdWell = idWell,
|
||||
IdDriller = schedule.IdDriller
|
||||
};
|
||||
|
||||
var drillerReport = new DrillerReportDto
|
||||
{
|
||||
Shedule = schedule,
|
||||
SubsystemsStat = await subsystemService.GetStatAsync(subsystemRequest, token)
|
||||
};
|
||||
|
||||
result.Add(drillerReport);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.ProcessMaps.Operations;
|
||||
using AsbCloudApp.Data.Trajectory;
|
||||
using AsbCloudApp.Data.WellOperation;
|
||||
using AsbCloudApp.Data.WellReport;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services;
|
||||
|
||||
public class WellReportService : IWellReportService
|
||||
{
|
||||
private readonly IWellService wellService;
|
||||
private readonly IWellOperationService wellOperationService;
|
||||
private readonly IWellContactService wellContactService;
|
||||
private readonly IProcessMapReportDrillingService processMapReportDrillingService;
|
||||
private readonly ISubsystemService subsystemService;
|
||||
|
||||
private readonly ITrajectoryRepository<TrajectoryGeoPlanDto> trajectoryPlanRepository;
|
||||
private readonly ITrajectoryRepository<TrajectoryGeoFactDto> trajectoryFactRepository;
|
||||
|
||||
private readonly IChangeLogRepository<ProcessMapPlanRotorDto, ProcessMapPlanBaseRequestWithWell>
|
||||
processMapPlanRotorRepository;
|
||||
|
||||
private readonly IScheduleRepository scheduleRepository;
|
||||
|
||||
private IEnumerable<WellOperationDto> factWellOperations;
|
||||
private IEnumerable<WellOperationDto> planWellOperations;
|
||||
|
||||
public WellReportService(IWellService wellService, IWellOperationService wellOperationService,
|
||||
IWellContactService wellContactService, IProcessMapReportDrillingService processMapReportDrillingService,
|
||||
ISubsystemService subsystemService, ITrajectoryRepository<TrajectoryGeoPlanDto> trajectoryPlanRepository,
|
||||
ITrajectoryRepository<TrajectoryGeoFactDto> trajectoryFactRepository,
|
||||
IChangeLogRepository<ProcessMapPlanRotorDto, ProcessMapPlanBaseRequestWithWell> processMapPlanRotorRepository,
|
||||
IScheduleRepository scheduleRepository, IEnumerable<WellOperationDto> factWellOperations,
|
||||
IEnumerable<WellOperationDto> planWellOperations)
|
||||
{
|
||||
this.wellService = wellService;
|
||||
this.wellOperationService = wellOperationService;
|
||||
this.wellContactService = wellContactService;
|
||||
this.processMapReportDrillingService = processMapReportDrillingService;
|
||||
this.subsystemService = subsystemService;
|
||||
this.trajectoryPlanRepository = trajectoryPlanRepository;
|
||||
this.trajectoryFactRepository = trajectoryFactRepository;
|
||||
this.processMapPlanRotorRepository = processMapPlanRotorRepository;
|
||||
this.scheduleRepository = scheduleRepository;
|
||||
this.factWellOperations = factWellOperations;
|
||||
this.planWellOperations = planWellOperations;
|
||||
}
|
||||
|
||||
public async Task<WellReportDto> GetAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var well = await wellService.GetOrDefaultAsync(idWell, token)
|
||||
?? throw new ArgumentInvalidException(nameof(idWell), "Скважина не найдена");
|
||||
|
||||
await InitWellOperations(idWell, token);
|
||||
|
||||
var wellContactRequest = new WellContactRequest
|
||||
{
|
||||
IdsWells = new[] { idWell },
|
||||
};
|
||||
|
||||
var contacts = await wellContactService.GetAllAsync(wellContactRequest, token);
|
||||
|
||||
var sectionReports = await GetSectionReportsAsync(idWell, token);
|
||||
var drillerReports = await GetDrillerReportsAsync(idWell, token);
|
||||
|
||||
var firstFactOperation = factWellOperations.MinByOrDefault(x => x.DateStart);
|
||||
var lastFactOperation = factWellOperations.MaxByOrDefault(x => x.DateStart);
|
||||
|
||||
var lastPlanOperation = planWellOperations.MaxByOrDefault(x => x.DateStart);
|
||||
|
||||
var planTrajectories = await trajectoryPlanRepository.GetAsync(idWell, token);
|
||||
var factTrajectories = await trajectoryFactRepository.GetAsync(idWell, token);
|
||||
|
||||
var factOperationsWithoutNpt = factWellOperations
|
||||
.Where(x => x.NptHours == 0);
|
||||
|
||||
return new WellReportDto
|
||||
{
|
||||
Well = well,
|
||||
DateFrom = firstFactOperation?.DateStart,
|
||||
DateTo = lastPlanOperation?.DateStart.AddHours(lastPlanOperation.DurationHours),
|
||||
Days = new PlanFactDto<double?>
|
||||
{
|
||||
Plan = lastPlanOperation?.Day,
|
||||
Fact = lastFactOperation?.Day
|
||||
},
|
||||
WellBoreDepth = new PlanFactDto<double?>
|
||||
{
|
||||
Plan = planWellOperations.MaxOrDefault(x => x.DepthEnd),
|
||||
Fact = factWellOperations.MaxOrDefault(x => x.DepthEnd)
|
||||
},
|
||||
VerticalDepth = new PlanFactDto<double?>
|
||||
{
|
||||
Plan = planTrajectories.Max(x => x.VerticalDepth),
|
||||
Fact = factTrajectories.Max(x => x.VerticalDepth)
|
||||
},
|
||||
Constacts = contacts,
|
||||
SectionReports = sectionReports,
|
||||
DrillerReports = drillerReports,
|
||||
WithoutNtpDays = factOperationsWithoutNpt.Sum(x => x.Day)
|
||||
};
|
||||
}
|
||||
|
||||
private async Task InitWellOperations(int idWell, CancellationToken token)
|
||||
{
|
||||
var request = new WellOperationRequest(new[] { idWell })
|
||||
{
|
||||
OperationType = WellOperation.IdOperationTypeFact
|
||||
};
|
||||
|
||||
factWellOperations = await wellOperationService.GetAsync(request, token);
|
||||
|
||||
request.OperationType = WellOperation.IdOperationTypePlan;
|
||||
|
||||
planWellOperations = await wellOperationService.GetAsync(request, token);
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<SectionReportDto>> GetSectionReportsAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var factWellOperationsBySection = factWellOperations.GroupBy(x => x.IdWellSectionType);
|
||||
|
||||
var processMapPlanRequest = new ProcessMapPlanBaseRequestWithWell(idWell);
|
||||
|
||||
var processMapPlanRotorBySection =
|
||||
(await processMapPlanRotorRepository.GetCurrent(processMapPlanRequest, token))
|
||||
.GroupBy(x => x.IdWellSectionType)
|
||||
.ToDictionary(x => x.Key, x => x.AsEnumerable());
|
||||
|
||||
var dataSaubStatRequest = new DataSaubStatRequest();
|
||||
|
||||
var processMapReportBySection =
|
||||
(await processMapReportDrillingService.GetAsync(idWell, dataSaubStatRequest, token))
|
||||
.GroupBy(x => x.IdWellSectionType)
|
||||
.ToDictionary(x => x.Key, x => x.AsEnumerable());
|
||||
|
||||
var sectionReports = new List<SectionReportDto>();
|
||||
|
||||
foreach (var group in factWellOperationsBySection)
|
||||
{
|
||||
var subsystemRequest = new SubsystemRequest
|
||||
{
|
||||
IdWell = idWell,
|
||||
GeDepth = group.Min(y => y.DepthStart),
|
||||
LeDepth = group.Max(y => y.DepthEnd)
|
||||
};
|
||||
|
||||
var sectionReport = new SectionReportDto
|
||||
{
|
||||
IdSection = group.Key,
|
||||
SubsystemsStat = await subsystemService.GetStatAsync(subsystemRequest, token),
|
||||
OperatingMode = new PlanFactDto<OperatingModeDto>
|
||||
{
|
||||
Fact = new OperatingModeDto(factWellOperations),
|
||||
}
|
||||
};
|
||||
|
||||
if (processMapPlanRotorBySection.TryGetValue(group.Key, out var processMapPlanRotor))
|
||||
sectionReport.OperatingMode.Plan = new OperatingModeDto(processMapPlanRotor);
|
||||
|
||||
if (processMapReportBySection.TryGetValue(group.Key, out var processMapReport))
|
||||
sectionReport.DrillingBySetpoints = new DrillingBySetpointsDto(processMapReport);
|
||||
|
||||
sectionReports.Add(sectionReport);
|
||||
}
|
||||
|
||||
return sectionReports;
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<DrillerReportDto>> GetDrillerReportsAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var schedules = await scheduleRepository.GetByIdWellAsync(idWell, token);
|
||||
|
||||
var result = new List<DrillerReportDto>();
|
||||
|
||||
foreach (var schedule in schedules)
|
||||
{
|
||||
var subsystemRequest = new SubsystemRequest
|
||||
{
|
||||
IdWell = idWell,
|
||||
IdDriller = schedule.IdDriller
|
||||
};
|
||||
|
||||
var drillerReport = new DrillerReportDto
|
||||
{
|
||||
Shedule = schedule,
|
||||
SubsystemsStat = await subsystemService.GetStatAsync(subsystemRequest, token);
|
||||
};
|
||||
|
||||
result.Add(drillerReport);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user