diff --git a/AsbCloudApp/Services/IWellReportService.cs b/AsbCloudApp/Services/IWellReportService.cs deleted file mode 100644 index b69c6383..00000000 --- a/AsbCloudApp/Services/IWellReportService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using AsbCloudApp.Data.WellReport; - -namespace AsbCloudApp.Services; - -public interface IWellReportService -{ - Task GetAsync(int idWell, CancellationToken token); -} \ No newline at end of file diff --git a/AsbCloudApp/Services/WellReport/IWellReportExportService.cs b/AsbCloudApp/Services/WellReport/IWellReportExportService.cs new file mode 100644 index 00000000..a697e260 --- /dev/null +++ b/AsbCloudApp/Services/WellReport/IWellReportExportService.cs @@ -0,0 +1,19 @@ +using System.IO; +using System.Threading.Tasks; +using System.Threading; + +namespace AsbCloudApp.Services.WellReport; + +/// +/// Сервис экспорта отчёта +/// +public interface IWellReportExportService +{ + /// + /// Экспортировать + /// + /// + /// + /// + Task<(string Name, Stream File)?> ExportAsync(int idWell, CancellationToken token); +} \ No newline at end of file diff --git a/AsbCloudApp/Services/WellReport/IWellReportService.cs b/AsbCloudApp/Services/WellReport/IWellReportService.cs new file mode 100644 index 00000000..9bf61049 --- /dev/null +++ b/AsbCloudApp/Services/WellReport/IWellReportService.cs @@ -0,0 +1,19 @@ +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data.WellReport; + +namespace AsbCloudApp.Services.WellReport; + +/// +/// Сервис формирования отчёта +/// +public interface IWellReportService +{ + /// + /// Сформировать + /// + /// + /// + /// + Task GetAsync(int idWell, CancellationToken token); +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj index 2942a43a..327b70b7 100644 --- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj +++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj @@ -53,6 +53,7 @@ + diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 7e8d5867..ca66ebe8 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -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,7 +471,9 @@ public static class DependencyInjection services.AddTransient, TrajectoryEditableRepository>(); services.AddTransient, TrajectoryEditableRepository>(); services.AddTransient(); - services.AddTransient(); + services.AddTransient, TrajectoryEditableRepository>(); + services.AddTransient, TrajectoryEditableRepository>(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient, CrudCacheRepositoryBase(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + return services; } } diff --git a/AsbCloudInfrastructure/Services/WellReport/WellReport.xlsx b/AsbCloudInfrastructure/Services/WellReport/WellReport.xlsx new file mode 100644 index 00000000..9e3b5ffd Binary files /dev/null and b/AsbCloudInfrastructure/Services/WellReport/WellReport.xlsx differ diff --git a/AsbCloudInfrastructure/Services/WellReport/WellReportExportService.cs b/AsbCloudInfrastructure/Services/WellReport/WellReportExportService.cs new file mode 100644 index 00000000..457a620c --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellReport/WellReportExportService.cs @@ -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 PlanOperatingModeRows = new Dictionary() + { + { 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 FactOperatingModeRows = new Dictionary + { + { 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 SubsystemRows = new Dictionary() + { + { 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 SetpointsRows = new Dictionary() + { + { 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 contacts) + { + var positionsByCompanyType = new Dictionary() + { + { 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 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 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 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 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); + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellReport/WellReportService.cs b/AsbCloudInfrastructure/Services/WellReport/WellReportService.cs new file mode 100644 index 00000000..49b7d1fa --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellReport/WellReportService.cs @@ -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 trajectoryPlanRepository; + private readonly ITrajectoryRepository trajectoryFactRepository; + + private readonly IChangeLogRepository + processMapPlanRotorRepository; + + private readonly IScheduleRepository scheduleRepository; + + private IEnumerable factWellOperations; + private IEnumerable planWellOperations; + + public WellReportService(IWellService wellService, IWellOperationService wellOperationService, + IWellContactService wellContactService, IProcessMapReportDrillingService processMapReportDrillingService, + ISubsystemService subsystemService, ITrajectoryRepository trajectoryPlanRepository, + ITrajectoryRepository trajectoryFactRepository, + IChangeLogRepository processMapPlanRotorRepository, + IScheduleRepository scheduleRepository, IEnumerable factWellOperations, + IEnumerable 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 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 + { + Plan = lastPlanOperation?.Day, + Fact = lastFactOperation?.Day + }, + WellBoreDepth = new PlanFactDto + { + Plan = planWellOperations.MaxOrDefault(x => x.DepthEnd), + Fact = factWellOperations.MaxOrDefault(x => x.DepthEnd) + }, + VerticalDepth = new PlanFactDto + { + 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> 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(); + + 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 + { + 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> GetDrillerReportsAsync(int idWell, CancellationToken token) + { + var schedules = await scheduleRepository.GetByIdWellAsync(idWell, token); + + var result = new List(); + + 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; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellReportService.cs b/AsbCloudInfrastructure/Services/WellReportService.cs deleted file mode 100644 index 0ea23674..00000000 --- a/AsbCloudInfrastructure/Services/WellReportService.cs +++ /dev/null @@ -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 trajectoryPlanRepository; - private readonly ITrajectoryRepository trajectoryFactRepository; - - private readonly IChangeLogRepository - processMapPlanRotorRepository; - - private readonly IScheduleRepository scheduleRepository; - - private IEnumerable factWellOperations; - private IEnumerable planWellOperations; - - public WellReportService(IWellService wellService, IWellOperationService wellOperationService, - IWellContactService wellContactService, IProcessMapReportDrillingService processMapReportDrillingService, - ISubsystemService subsystemService, ITrajectoryRepository trajectoryPlanRepository, - ITrajectoryRepository trajectoryFactRepository, - IChangeLogRepository processMapPlanRotorRepository, - IScheduleRepository scheduleRepository, IEnumerable factWellOperations, - IEnumerable 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 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 - { - Plan = lastPlanOperation?.Day, - Fact = lastFactOperation?.Day - }, - WellBoreDepth = new PlanFactDto - { - Plan = planWellOperations.MaxOrDefault(x => x.DepthEnd), - Fact = factWellOperations.MaxOrDefault(x => x.DepthEnd) - }, - VerticalDepth = new PlanFactDto - { - 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> 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(); - - 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 - { - 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> GetDrillerReportsAsync(int idWell, CancellationToken token) - { - var schedules = await scheduleRepository.GetByIdWellAsync(idWell, token); - - var result = new List(); - - 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; - } -} \ No newline at end of file