DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/DailyReport/DailyReportExportService.cs
Степанов Дмитрий 1bda2d5b77 Фикс сервисов
1. Устранение багов выявленных при тестировании
2. Изменение имён методов в сервисе суточных отчётов
3. Фикс получения фиктивных суточных отчётов
4. Фикс шаблона
5. Правки в контроллере
6. Фикс в репозитории. Приведение к utc доа выполнения запроса
7. Покрытие сервиса тестами
2023-11-14 11:01:34 +05:00

257 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 = 4;
private const int columnTimeBalanceReasonDeviation = 8;
private const int columnTimeBalanceDrillingDeviationPerSection = 10;
private const int columnTimeBalanceDrillingDeviationPerDay = 11;
private const int columnSheduleDriller = 3;
private const int columnSheduleShiftStart = 7;
private const int columnSheduleShiftEnd = 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 cellSubsystemMeasurementsPerDay = "F80";
private const string cellSubsystemWellBore = "C9";
private const string cellSubsystemTotalRopPlan = "E70";
private const string cellSignDrillingMaster = "C84";
private const string cellSignSupervisor = "C85";
private readonly IDailyReportService dailyReportService;
public DailyReportExportService(IDailyReportService dailyReportService)
{
this.dailyReportService = dailyReportService;
}
public async Task<(string FileName, Stream File)> ExportAsync(int idWell, DateTime dailyReportDateStart, CancellationToken cancellationToken)
{
var dailyReport = await dailyReportService.GetAsync(idWell, dailyReportDateStart, cancellationToken);
var stream = await GenerateFileAsync(dailyReport, cancellationToken);
var fileName = $"Суточный_рапорт_по_скважине_{dailyReport.WellCaption}_куст_{dailyReport.Cluster}_от_{dailyReport.Date:yy-MM-dd}.xlsx";
return (fileName, stream);
}
private static async Task<Stream> GenerateFileAsync(DailyReportDto dailyReport, CancellationToken cancellationToken)
{
using var excelTemplateStream = await Assembly
.GetExecutingAssembly()
.GetTemplateCopyStreamAsync("DailyReportTemplate.xlsx", cancellationToken);
using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled);
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.Worksheets.FirstOrDefault(ws => ws.Name == sheetName)
?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}.");
sheet.Cell(cellCustomer).Value = dailyReport.Customer;
sheet.Cell(cellContractor).Value = dailyReport.Contractor;
sheet.Cell(cellDeposit).Value = dailyReport.Deposit;
sheet.Cell(cellCluster).Value = dailyReport.Cluster;
sheet.Cell(cellWellCaption).Value = dailyReport.WellCaption;
sheet.Cell(cellWellType).Value = dailyReport.WellType;
sheet.Cell(cellDate).Value = dailyReport.Date;
sheet.Cell(cellDepthStart).Value = dailyReport.DepthStart;
sheet.Cell(cellDepthEnd).Value = 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).Value = trajectoryBlock.WellboreDepth;
sheet.Cell(cellTrajectoryBlockVerticalDepth).Value = trajectoryBlock.VerticalDepth;
sheet.Cell(cellTrajectoryBlockZenithAngle).Value = trajectoryBlock.ZenithAngle;
sheet.Cell(cellTrajectoryBlockAzimuthGeo).Value = 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).Value = wellOperation.DurationHours.Plan;
sheet.Cell(rowCurrent, columnTimeBalanceDurationFact).Value = wellOperation.DurationHours.Fact;
sheet.Cell(rowCurrent, columnTimeBalanceReasonDeviation).Value = wellOperation.ReasonDeviation;
sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerSection).Value = wellOperation.DrillingDeviationPerSection;
sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerDay).Value = wellOperation.DrillingDeviationPerDay;
rowCurrent++;
}
sheet.Cell(cellTimeBalanceBlockSection).Value = timeBalanceBlock.SectionName;
sheet.Cell(cellTimeBalanceBlockWellDepthPlan).Value = timeBalanceBlock.WellDepth.Plan;
sheet.Cell(cellTimeBalanceBlockWellDepthFact).Value = timeBalanceBlock.WellDepth.Fact;
sheet.Cell(cellTimeBalanceBlockWellOperationSlipsTimeCount).Value = timeBalanceBlock.WellOperationSlipsTimeCount;
}
private static void AddSubsystemBlockToSheet(IXLWorksheet sheet, SubsystemBlockDto subsystemBlock)
{
var groupedSubsystems = subsystemBlock.Subsystems.OrderBy(m => m.SubsystemName)
.GroupBy(m => m.SubsystemName);
var rowСurrent = rowStartSubsystemBlock;
foreach (var groupedModule in groupedSubsystems)
{
var useSubsystemPerDay = groupedModule.FirstOrDefault(m => m.IdTimeInterval == 1);
var useSubsystemPerWell = groupedModule.FirstOrDefault(m => m.IdTimeInterval == 2);
sheet.Cell(rowСurrent, columnSubsystemName).Value = groupedModule.Key;
sheet.Cell(rowСurrent, columnUseSubsystemPerDayUsedTimeHours).Value = useSubsystemPerDay?.UsedTimeHours;
sheet.Cell(rowСurrent, columnUseSubsystemPerDaySumDepthInterval).Value = useSubsystemPerDay?.SumDepthInterval;
sheet.Cell(rowСurrent, columnUseSubsystemPerDayKUsage).Value = useSubsystemPerDay?.KUsage;
sheet.Cell(rowСurrent, columnUseSubsystemPerWellUsedTimeHours).Value = useSubsystemPerWell?.UsedTimeHours;
sheet.Cell(rowСurrent, columnUseSubsystemPerWellSumDepthInterval).Value = useSubsystemPerWell?.SumDepthInterval;
sheet.Cell(rowСurrent, columnUseSubsystemPerWellKUsage).Value = useSubsystemPerWell?.KUsage;
rowСurrent++;
}
sheet.Cell(cellSubsystemComment).Value = subsystemBlock.Comment;
sheet.Cell(cellSubsystemMeasurementsPerDay).Value = subsystemBlock.MeasurementsPerDay;
sheet.Cell(cellSubsystemWellBore).Value = subsystemBlock.WellBore;
sheet.Cell(cellSubsystemTotalRopPlan).Value = subsystemBlock.TotalRopPlan;
}
private static void AddScheduleBlockToSheet(IXLWorksheet sheet, IEnumerable<ScheduleRecordDto> scheduleBlock)
{
var rowCurrent = rowStartScheduleBlock;
foreach (var schedule in scheduleBlock.OrderBy(s => s.ShiftStart))
{
sheet.Cell(rowCurrent, columnSheduleDriller).Value = $"{schedule.Surname} {schedule.Name} {schedule.Patronymic}";
sheet.Cell(rowCurrent, columnSheduleShiftStart).Value = schedule.ShiftStart;
sheet.Cell(rowCurrent, columnSheduleShiftEnd).Value = schedule.ShiftEnd;
rowCurrent++;
}
}
private static void AddProcessMapWellDrillingBlockToSheet(IXLWorksheet sheet,
IEnumerable<ProcessMapWellDrillingRecordDto> processMapWellDrillingBlock)
{
var rowCurrent = rowStartProcessMapWellDrillingBlock;
foreach (var processMapWellDrilling in processMapWellDrillingBlock.OrderBy(p => p.DrillingMode))
{
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockDrillingMode).Value = processMapWellDrilling.DrillingMode;
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockWellBoreDepth).Value = processMapWellDrilling.WellBoreDepth;
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockMechDrillingHours).Value = processMapWellDrilling.MechDrillingHours;
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockRopPlan).Value = processMapWellDrilling.Rop.Plan;
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockRopFact).Value = processMapWellDrilling.Rop.Fact;
rowCurrent++;
}
}
private static void AddFactWellOperationBlockToSheet(IXLWorksheet sheet, WellOperationBlockDto factWellOperationBlock)
{
sheet.Cell(cellSectionDrillingHours).Value = factWellOperationBlock.SectionDrillingHours;
foreach (var factOperation in factWellOperationBlock.WellOperations.OrderBy(w => w.CategoryName))
{
sheet.Cell(rowStartFactWellOperationBlock, columnWellOperationCategory).Value = factOperation.CategoryName;
sheet.Cell(rowStartFactWellOperationBlock, columnWellOperationDurationHours).Value = factOperation.DurationHours;
}
}
private static void AddSignBlockToSheet(IXLWorksheet sheet, SignBlockDto signBlock)
{
sheet.Cell(cellSignDrillingMaster).Value = signBlock.DrillingMaster?.ToString();
sheet.Cell(cellSignSupervisor).Value = signBlock.Supervisor?.ToString();
}
}