using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data.DailyReport; using AsbCloudApp.Data.DailyReport.Blocks; using AsbCloudApp.Data.DailyReport.Blocks.Sign; using AsbCloudApp.Data.DailyReport.Blocks.Subsystems; using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance; using AsbCloudApp.Data.DailyReport.Blocks.WellOperation; using AsbCloudApp.Services.DailyReport; using ClosedXML.Excel; namespace AsbCloudInfrastructure.Services.DailyReport; public class DailyReportExportService : IDailyReportExportService { private const int rowStartScheduleBlock = 20; private const int rowStartSubsystemBlock = 26; private const int rowStartFactWellOperationBlock = 39; private const int rowStartTimeBalanceBlock = 62; private const int rowStartProcessMapWellDrillingBlock = 68; private const int columnTimeBalanceDurationPlan = 3; private const int columnTimeBalanceDurationFact = 6; private const int columnTimeBalanceReasonDeviation = 8; private const int columnTimeBalanceDrillingDeviationPerSection = 10; private const int columnTimeBalanceDrillingDeviationPerDay = 11; private const int columnScheduleDriller = 3; private const int columnScheduleShiftStart = 7; private const int columnScheduleShiftEnd = 8; private const int columnSubsystemName = 2; private const int columnUseSubsystemPerDayUsedTimeHours = 3; private const int columnUseSubsystemPerDaySumDepthInterval = 4; private const int columnUseSubsystemPerDayKUsage = 5; private const int columnUseSubsystemPerWellUsedTimeHours = 6; private const int columnUseSubsystemPerWellSumDepthInterval = 7; private const int columnUseSubsystemPerWellKUsage = 8; private const int columnProcessMapWellDrillingBlockDrillingMode = 2; private const int columnProcessMapWellDrillingBlockWellBoreDepth = 3; private const int columnProcessMapWellDrillingBlockMechDrillingHours = 4; private const int columnProcessMapWellDrillingBlockRopPlan = 5; private const int columnProcessMapWellDrillingBlockRopFact = 6; private const int columnWellOperationCategory = 2; private const int columnWellOperationDurationHours = 4; private const string cellCustomer = "C2"; private const string cellContractor = "C3"; private const string cellDeposit = "C5"; private const string cellCluster = "C6"; private const string cellWellCaption = "C7"; private const string cellWellType = "C8"; private const string cellDate = "C12"; private const string cellDepthStart = "C13"; private const string cellDepthEnd = "D13"; private const string cellTrajectoryBlockWellboreDepth = "B17"; private const string cellTrajectoryBlockVerticalDepth = "C17"; private const string cellTrajectoryBlockZenithAngle = "D17"; private const string cellTrajectoryBlockAzimuthGeo = "E17"; private const string cellTimeBalanceBlockSection = "C60"; private const string cellTimeBalanceBlockWellDepthPlan = "C61"; private const string cellSectionDrillingHours = "F77"; private const string cellTimeBalanceBlockWellDepthFact = "F78"; private const string cellTimeBalanceBlockWellOperationSlipsTimeCount = "F79"; private const string cellSubsystemComment = "D35"; private const string cellSubsystemTvgLagDays = "F80"; private const string cellSubsystemMeasurementsPerDay = "F81"; private const string cellSubsystemWellbore = "C9"; private const string cellSubsystemTotalRopPlan = "E70"; private const string cellSignDrillingMaster = "C85"; private const string cellSignSupervisor = "C86"; private readonly IDailyReportService dailyReportService; public DailyReportExportService(IDailyReportService dailyReportService) { this.dailyReportService = dailyReportService; } public async Task<(string FileName, Stream File)> ExportAsync(int idWell, DateOnly dailyReportDate, CancellationToken cancellationToken) { var dailyReport = await dailyReportService.GetAsync(idWell, dailyReportDate, cancellationToken); var stream = GenerateFile(dailyReport); var fileName = $"Суточный_рапорт_по_скважине_{dailyReport.WellCaption}_куст_{dailyReport.Cluster}_от_{dailyReport.Date:yy-MM-dd}.xlsx"; return (fileName, stream); } private static MemoryStream GenerateFile(DailyReportDto dailyReport) { using var excelTemplateStream = Assembly .GetExecutingAssembly() .GetTemplateCopyStream("DailyReportTemplate.xlsx"); using var workbook = new XLWorkbook(excelTemplateStream); AddDailyReportToWorkBook(workbook, dailyReport); var memoryStream = new MemoryStream(); workbook.SaveAs(memoryStream, new SaveOptions { }); memoryStream.Seek(0, SeekOrigin.Begin); return memoryStream; } private static void AddDailyReportToWorkBook(IXLWorkbook workbook, DailyReportDto dailyReport) { const string sheetName = "Суточный отчёт"; var sheet = workbook.GetWorksheet(sheetName);; sheet.Cell(cellCustomer).SetCellValue(dailyReport.Customer); sheet.Cell(cellContractor).SetCellValue(dailyReport.Contractor); sheet.Cell(cellDeposit).SetCellValue(dailyReport.Deposit); sheet.Cell(cellCluster).SetCellValue(dailyReport.Cluster); sheet.Cell(cellWellCaption).SetCellValue(dailyReport.WellCaption); sheet.Cell(cellWellType).SetCellValue(dailyReport.WellType); sheet.Cell(cellDate).SetCellValue(dailyReport.Date); sheet.Cell(cellDepthStart).SetCellValue(dailyReport.DepthStart); sheet.Cell(cellDepthEnd).SetCellValue(dailyReport.DepthEnd); if (dailyReport.TimeBalanceBlock is not null) AddTimeBalanceBlockToSheet(sheet, dailyReport.TimeBalanceBlock); if (dailyReport.SubsystemBlock is not null) AddSubsystemBlockToSheet(sheet, dailyReport.SubsystemBlock); if (dailyReport.SignBlock is not null) AddSignBlockToSheet(sheet, dailyReport.SignBlock); AddTrajectoryBlockToSheet(sheet, dailyReport.TrajectoryBlock); AddScheduleBlockToSheet(sheet, dailyReport.ScheduleBlock); AddProcessMapWellDrillingBlockToSheet(sheet, dailyReport.ProcessMapWellDrillingBlock); AddFactWellOperationBlockToSheet(sheet, dailyReport.FactWellOperationBlock); } private static void AddTrajectoryBlockToSheet(IXLWorksheet sheet, TrajectoryBlockDto trajectoryBlock) { sheet.Cell(cellTrajectoryBlockWellboreDepth).SetCellValue(trajectoryBlock.WellboreDepth); sheet.Cell(cellTrajectoryBlockVerticalDepth).SetCellValue(trajectoryBlock.VerticalDepth); sheet.Cell(cellTrajectoryBlockZenithAngle).SetCellValue(trajectoryBlock.ZenithAngle); sheet.Cell(cellTrajectoryBlockAzimuthGeo).SetCellValue(trajectoryBlock.AzimuthGeo); } private static void AddTimeBalanceBlockToSheet(IXLWorksheet sheet, TimeBalanceBlockDto timeBalanceBlock) { var rowCurrent = rowStartTimeBalanceBlock; foreach (var wellOperation in timeBalanceBlock.WellOperations.OrderBy(w => w.IdWellOperation)) { sheet.Cell(rowCurrent, columnTimeBalanceDurationPlan).SetCellValue(wellOperation.DurationHours.Plan); sheet.Cell(rowCurrent, columnTimeBalanceDurationFact).SetCellValue(wellOperation.DurationHours.Fact); sheet.Cell(rowCurrent, columnTimeBalanceReasonDeviation).SetCellValue(wellOperation.ReasonDeviation); sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerSection).SetCellValue(wellOperation.DrillingDeviationPerSection); sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerDay).SetCellValue(wellOperation.DrillingDeviationPerDay); rowCurrent++; } sheet.Cell(cellTimeBalanceBlockSection).SetCellValue(timeBalanceBlock.SectionName); sheet.Cell(cellTimeBalanceBlockWellDepthPlan).SetCellValue(timeBalanceBlock.WellDepth.Plan); sheet.Cell(cellTimeBalanceBlockWellDepthFact).SetCellValue(timeBalanceBlock.WellDepth.Fact); sheet.Cell(cellTimeBalanceBlockWellOperationSlipsTimeCount).SetCellValue(timeBalanceBlock.WellOperationSlipsTimeCount); } private static void AddSubsystemBlockToSheet(IXLWorksheet sheet, SubsystemBlockDto subsystemBlock) { var rowCurrent = rowStartSubsystemBlock; foreach (var subsystem in subsystemBlock.Subsystems) { sheet.Cell(rowCurrent, columnSubsystemName).SetCellValue(subsystem.Name); sheet.Cell(rowCurrent, columnUseSubsystemPerDayUsedTimeHours).SetCellValue(subsystem.UsagePerDay?.UsedTimeHours); sheet.Cell(rowCurrent, columnUseSubsystemPerDaySumDepthInterval).SetCellValue(subsystem.UsagePerDay?.SumDepthInterval); sheet.Cell(rowCurrent, columnUseSubsystemPerDayKUsage).SetCellValue(subsystem.UsagePerDay?.KUsage * 100); sheet.Cell(rowCurrent, columnUseSubsystemPerWellUsedTimeHours).SetCellValue(subsystem.UsagePerWell?.UsedTimeHours); sheet.Cell(rowCurrent, columnUseSubsystemPerWellSumDepthInterval).SetCellValue(subsystem.UsagePerWell?.SumDepthInterval); sheet.Cell(rowCurrent, columnUseSubsystemPerWellKUsage).SetCellValue(subsystem.UsagePerWell?.KUsage * 100); rowCurrent++; } sheet.Cell(cellSubsystemComment).SetCellValue(subsystemBlock.Comment); sheet.Cell(cellSubsystemTvgLagDays).SetCellValue(subsystemBlock.TvgLagDays); sheet.Cell(cellSubsystemMeasurementsPerDay).SetCellValue(subsystemBlock.MeasurementsPerDay); sheet.Cell(cellSubsystemWellbore).SetCellValue(subsystemBlock.Wellbore); sheet.Cell(cellSubsystemTotalRopPlan).SetCellValue(subsystemBlock.TotalRopPlan); } private static void AddScheduleBlockToSheet(IXLWorksheet sheet, IEnumerable scheduleBlock) { var rowCurrent = rowStartScheduleBlock; foreach (var schedule in scheduleBlock.OrderBy(s => s.ShiftStart)) { sheet.Cell(rowCurrent, columnScheduleDriller).SetCellValue($"{schedule.Surname} {schedule.Name} {schedule.Patronymic}"); sheet.Cell(rowCurrent, columnScheduleShiftStart).SetCellValue(schedule.ShiftStart); sheet.Cell(rowCurrent, columnScheduleShiftEnd).SetCellValue(schedule.ShiftEnd); rowCurrent++; } } private static void AddProcessMapWellDrillingBlockToSheet(IXLWorksheet sheet, IEnumerable processMapWellDrillingBlock) { var rowCurrent = rowStartProcessMapWellDrillingBlock; foreach (var processMapWellDrilling in processMapWellDrillingBlock.OrderBy(p => p.DrillingMode)) { sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockDrillingMode).SetCellValue(processMapWellDrilling.DrillingMode); sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockWellBoreDepth).SetCellValue(processMapWellDrilling.WellBoreDepth); sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockMechDrillingHours).SetCellValue(processMapWellDrilling.MechDrillingHours); sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockRopPlan).SetCellValue(processMapWellDrilling.Rop.Plan); sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockRopFact).SetCellValue(processMapWellDrilling.Rop.Fact); rowCurrent++; } } private static void AddFactWellOperationBlockToSheet(IXLWorksheet sheet, WellOperationBlockDto factWellOperationBlock) { var rowCurrent = rowStartFactWellOperationBlock; sheet.Cell(cellSectionDrillingHours).SetCellValue(factWellOperationBlock.SectionDrillingHours); foreach (var factOperation in factWellOperationBlock.WellOperations.OrderBy(w => w.CategoryName)) { sheet.Cell(rowCurrent, columnWellOperationCategory).SetCellValue(factOperation.CategoryName); sheet.Cell(rowCurrent, columnWellOperationDurationHours).SetCellValue(factOperation.DurationHours); rowCurrent++; } } private static void AddSignBlockToSheet(IXLWorksheet sheet, SignBlockDto signBlock) { sheet.Cell(cellSignDrillingMaster).SetCellValue(signBlock.DrillingMaster?.ToString()); sheet.Cell(cellSignSupervisor).SetCellValue(signBlock.Supervisor?.ToString()); } }