Мердж с дев-веткой и правки по результатам этого мерджа

This commit is contained in:
Olga Nemt 2023-11-29 12:06:57 +05:00
commit 29171a6e47
128 changed files with 12562 additions and 5706 deletions

View File

@ -1,30 +0,0 @@
using System.Collections;
using System.Collections.Generic;
namespace AsbCloudApp.Data.AutogeneratedDailyReport;
/// <summary>
/// DTO авто-сгенерированного суточного отчёта
/// </summary>
public class AutoGeneratedDailyReportDto : AutoGeneratedDailyReportInfoDto
{
/// <summary>
/// Блок заголовка
/// </summary>
public HeadBlockDto Head { get; set; } = null!;
/// <summary>
/// Блок подсистем
/// </summary>
public IEnumerable<SubsystemRecordDto> Subsystems { get; set; } = null!;
/// <summary>
/// Блок ограничивающих параметров
/// </summary>
public IEnumerable<LimitingParameterRecordDto> LimitingParameters { get; set; } = null!;
/// <summary>
/// Баланс времени
/// </summary>
public IEnumerable<TimeBalanceRecordDto> TimeBalance { get; set; } = null!;
}

View File

@ -1,14 +0,0 @@
using System;
namespace AsbCloudApp.Data.AutogeneratedDailyReport;
/// <summary>
/// Базовая информация о суточном отчёте
/// </summary>
public class AutoGeneratedDailyReportInfoDto : ReportInfoDto
{
/// <summary>
/// Дата формирования отчёта
/// </summary>
public DateOnly ReportDate { get; set; }
}

View File

@ -1,37 +0,0 @@
namespace AsbCloudApp.Data.AutogeneratedDailyReport;
/// <summary>
/// Блок заголовка
/// </summary>
public class HeadBlockDto
{
/// <summary>
/// Название скважины
/// </summary>
public string Well { get; set; } = null!;
/// <summary>
/// Название куста
/// </summary>
public string Cluster { get; set; } = null!;
/// <summary>
/// Заказчик
/// </summary>
public string Customer { get; set; } = null!;
/// <summary>
/// Месторождение
/// </summary>
public string Deposit { get; set; } = null!;
/// <summary>
/// Глубина забоя на дату начала интервала
/// </summary>
public double DepthFrom { get; set; }
/// <summary>
/// Глубина забоя на дату окончания интервала
/// </summary>
public double DepthTo { get; set; }
}

View File

@ -1,27 +0,0 @@
namespace AsbCloudApp.Data.AutogeneratedDailyReport;
/// <summary>
/// Блок ограничивающих параметров
/// </summary>
public class LimitingParameterRecordDto
{
/// <summary>
/// Время использования, мин
/// </summary>
public double Hours { get; set; }
/// <summary>
/// Проходка, м
/// </summary>
public double Depth { get; set; }
/// <summary>
/// Название ограничивающего параметра
/// </summary>
public string NameFeedRegulator { get; set; } = null!;
/// <summary>
/// Процент по проходке, %
/// </summary>
public double PercentDepth { get; set; }
}

View File

@ -1,27 +0,0 @@
namespace AsbCloudApp.Data.AutogeneratedDailyReport;
/// <summary>
/// Блок подсистем
/// </summary>
public class SubsystemRecordDto
{
/// <summary>
/// Название подсистемы
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// Использование, %
/// </summary>
public double KUsage { get; set; }
/// <summary>
/// Время работы, ч
/// </summary>
public double UsedTimeHours { get; set; }
/// <summary>
/// Проходка
/// </summary>
public double Depth { get; set; }
}

View File

@ -1,17 +0,0 @@
namespace AsbCloudApp.Data.AutogeneratedDailyReport;
/// <summary>
/// Баланс времени
/// </summary>
public class TimeBalanceRecordDto
{
/// <summary>
/// Название операции
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// Продолжительность, часы
/// </summary>
public double DurationHours { get; set; }
}

View File

@ -1,64 +0,0 @@
namespace AsbCloudApp.Data.DailyReport
{
/// <summary>
/// блок КНБК
/// </summary>
public class BhaDto : ItemInfoDto
{
/// <summary>
/// КНБК описание
/// </summary>
public string BHADescription { get; set; } = string.Empty;
/// <summary>
/// Бурение с наращиваниями в инт. 2195-2763м. Время начала
/// </summary>
public string ExtensionDrillingOneBegin{ get; set; } = string.Empty;
/// <summary>
/// Бурение с наращиваниями в инт. 2195-2763м. Время окончания
/// </summary>
public string ExtensionDrillingOneFinish { get; set; } = string.Empty;
/// <summary>
/// Промывка. Время начала
/// </summary>
public string SluiceBegin { get; set; } = string.Empty;
/// <summary>
/// Промывка. Время окончания
/// </summary>
public string SluiceFinish { get; set; } = string.Empty;
/// <summary>
/// Подъем КНБК. Время начала
/// </summary>
public string ClimbBegin { get; set; } = string.Empty;
/// <summary>
/// Подъем КНБК. Время окончания
/// </summary>
public string ClimbFinish { get; set; } = string.Empty;
/// <summary>
/// Спуск КНБК. Время начала
/// </summary>
public string DescentBegin { get; set; } = string.Empty;
/// <summary>
/// Спуск КНБК. Время окончания
/// </summary>
public string DescentFinish { get; set; } = string.Empty;
/// <summary>
/// Бурение с наращиваниями в инт. 2763-2850м. Время начала
/// </summary>
public string ExtensionDrillingTwoBegin { get; set; } = string.Empty;
/// <summary>
/// Бурение с наращиваниями в инт. 2763-2850м. Время окончания
/// </summary>
public string ExtensionDrillingTwoFinish { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,27 @@
namespace AsbCloudApp.Data.DailyReport.Blocks;
/// <summary>
/// РТК
/// </summary>
public class ProcessMapWellDrillingRecordDto
{
/// <summary>
/// Режим бурения
/// </summary>
public string DrillingMode { get; set; } = null!;
/// <summary>
/// Мех. скорость
/// </summary>
public PlanFactDto<double?> Rop { get; set; } = new();
/// <summary>
/// Глубина ствола
/// </summary>
public double? WellBoreDepth { get; set; }
/// <summary>
/// Часы бурения
/// </summary>
public double MechDrillingHours { get; set; }
}

View File

@ -0,0 +1,32 @@
namespace AsbCloudApp.Data.DailyReport.Blocks;
/// <summary>
/// Блок с графиком работы
/// </summary>
public class ScheduleRecordDto
{
/// <summary>
/// Начало смены
/// </summary>
public TimeDto? ShiftStart { get; set; }
/// <summary>
/// Конец смены
/// </summary>
public TimeDto? ShiftEnd { get; set; }
/// <summary>
/// Имя бурильщика
/// </summary>
public string? Name { get; set; }
/// <summary>
/// Фамилия бурильщика
/// </summary>
public string? Surname { get; set; }
/// <summary>
/// Отчество бурильщика
/// </summary>
public string? Patronymic { get; set; }
}

View File

@ -0,0 +1,17 @@
namespace AsbCloudApp.Data.DailyReport.Blocks.Sign;
/// <summary>
/// Блок с подписями
/// </summary>
public class SignBlockDto : ItemInfoDto
{
/// <summary>
/// Подпись мастера буровой
/// </summary>
public SignRecordDto? DrillingMaster { get; set; }
/// <summary>
/// Подпись супервайзера
/// </summary>
public SignRecordDto? Supervisor { get; set; }
}

View File

@ -0,0 +1,28 @@
namespace AsbCloudApp.Data.DailyReport.Blocks.Sign;
/// <summary>
/// Подпись
/// </summary>
public class SignRecordDto
{
/// <summary>
/// Имя
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// Фамилия
/// </summary>
public string Surname { get; set; } = null!;
/// <summary>
/// Отчество
/// </summary>
public string? Patronymic { get; set; }
/// <inheritdoc />
public override string ToString()
{
return $"{Surname} {Name} {Patronymic}";
}
}

View File

@ -0,0 +1,40 @@
using System.Collections.Generic;
using System.Linq;
namespace AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
/// <summary>
/// Блок статистики работы подсистем
/// </summary>
public class SubsystemBlockDto : ItemInfoDto
{
/// <summary>
/// Длина ствола скважины
/// </summary>
public double? Wellbore { get; set; }
/// <summary>
/// Кол-во замеров за сутки
/// </summary>
public double? MeasurementsPerDay { get; set; }
/// <summary>
/// Общая плановая мех. скорость
/// </summary>
public double? TotalRopPlan { get; set; }
/// <summary>
/// Отклонение по ГГД, сут
/// </summary>
public double? TvgLagDays { get; set; }
/// <summary>
/// Рекомендации специалиста
/// </summary>
public string? Comment { get; set; }
/// <summary>
/// Подсистемы
/// </summary>
public IEnumerable<SubsystemRecordDto> Subsystems { get; set; } = Enumerable.Empty<SubsystemRecordDto>();
}

View File

@ -0,0 +1,25 @@
using System.ComponentModel.DataAnnotations;
namespace AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
/// <summary>
/// Параметры наработки подсистемы
/// </summary>
public class SubsystemParametersDto
{
/// <summary>
/// Сумма изменения глубин при включенной подсистеме
/// </summary>
public double? SumDepthInterval { get; set; }
/// <summary>
/// Наработка подсистемы
/// </summary>
public double? UsedTimeHours { get; set; }
/// <summary>
/// Коэффициент использования
/// </summary>
[Range(0, 1)]
public double? KUsage { get; set; }
}

View File

@ -0,0 +1,22 @@
namespace AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
/// <summary>
/// Модуль подсистемы
/// </summary>
public class SubsystemRecordDto
{
/// <summary>
/// Название подсистемы
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// Использование подсистемы за сутки
/// </summary>
public SubsystemParametersDto? UsagePerDay { get; set; }
/// <summary>
/// Использование подсистемы за скважину
/// </summary>
public SubsystemParametersDto? UsagePerWell { get; set; }
}

View File

@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
/// <summary>
/// Блок с балансом времени
/// </summary>
public class TimeBalanceBlockDto : ItemInfoDto
{
/// <summary>
/// Идентификатор секции
/// </summary>
[Range(1, int.MaxValue)]
public int IdSection { get; set; }
/// <summary>
/// Название секции
/// </summary>
public string? SectionName { get; set; }
/// <summary>
/// Проходка скважины
/// </summary>
public PlanFactDto<double?> WellDepth { get; set; } = new();
/// <summary>
/// Кол-во наращиваний за сутки
/// </summary>
public double? WellOperationSlipsTimeCount { get; set; }
/// <summary>
/// Операции на скважине
/// </summary>
public IEnumerable<TimeBalanceRecordDto> WellOperations { get; set; } = Enumerable.Empty<TimeBalanceRecordDto>();
}

View File

@ -0,0 +1,35 @@
namespace AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
/// <summary>
/// Операции проводимые на скважине
/// </summary>
public class TimeBalanceRecordDto
{
/// <summary>
/// Мех. бурение - 1
/// Снятие замера, ориентирование - 2
/// Наращивание, выход на режим - 3
/// Промывка, проработка - 4
/// </summary>
public int IdWellOperation { get; set; }
/// <summary>
/// Продолжительность операции, ч
/// </summary>
public PlanFactDto<double?> DurationHours { get; set; } = new();
/// <summary>
/// Отклонение за секцию
/// </summary>
public double? DrillingDeviationPerSection { get; set; }
/// <summary>
/// Отклонение за сутки
/// </summary>
public double? DrillingDeviationPerDay { get; set; }
/// <summary>
/// Причина отклонения
/// </summary>
public string? ReasonDeviation { get; set; }
}

View File

@ -0,0 +1,27 @@
namespace AsbCloudApp.Data.DailyReport.Blocks;
/// <summary>
/// Блок с траекторией скважины
/// </summary>
public class TrajectoryBlockDto
{
/// <summary>
/// Глубина по стволу
/// </summary>
public double? WellboreDepth { get; set; }
/// <summary>
/// Глубина вертикальная
/// </summary>
public double? VerticalDepth { get; set; }
/// <summary>
/// Угол зенитный
/// </summary>
public double? ZenithAngle { get; set; }
/// <summary>
/// Азимут Географ.
/// </summary>
public double? AzimuthGeo { get; set; }
}

View File

@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Linq;
namespace AsbCloudApp.Data.DailyReport.Blocks.WellOperation;
/// <summary>
/// Блок с операциями проводимыми на скважине
/// </summary>
public class WellOperationBlockDto
{
/// <summary>
/// Продолжительность бурения за секцию
/// </summary>
public double SectionDrillingHours { get; set; }
/// <summary>
/// Операции проводимые на скважине
/// </summary>
public IEnumerable<WellOperationRecordDto> WellOperations { get; set; } = Enumerable.Empty<WellOperationRecordDto>();
}

View File

@ -0,0 +1,17 @@
namespace AsbCloudApp.Data.DailyReport.Blocks.WellOperation;
/// <summary>
/// Операция на скважине
/// </summary>
public class WellOperationRecordDto
{
/// <summary>
/// Название категории
/// </summary>
public string? CategoryName { get; set; }
/// <summary>
/// Продолжительность операции
/// </summary>
public double? DurationHours { get; set; }
}

View File

@ -1,45 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
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;
namespace AsbCloudApp.Data.DailyReport
namespace AsbCloudApp.Data.DailyReport;
/// <summary>
/// Суточный отчёт
/// </summary>
public class DailyReportDto : IId,
IWellRelated
{
/// <summary>
/// Блоки для формирования суточного рапорта
/// </summary>
public class DailyReportDto
{
/// <summary>
/// дата отчёта
/// </summary>
public DateOnly StartDate { get; set; }
/// <inheritdoc/>
public int Id { get; set; }
/// <summary>
/// блок заголовка
/// </summary>
public HeadDto Head { get; set; } = new();
/// <inheritdoc/>
public int IdWell { get; set; }
/// <summary>
/// блок КНБК
/// </summary>
public BhaDto Bha { get; set; } = new();
/// <summary>
/// Название скважины
/// </summary>
public string WellCaption { get; set; } = null!;
/// <summary>
/// блок безметражные работы
/// </summary>
public NoDrillingDto NoDrilling { get; set; } = new();
/// <summary>
/// Название типа скважины
/// </summary>
public string? WellType { get; set; }
/// <summary>
/// блок баланса времени
/// </summary>
public TimeBalanceDto TimeBalance { get; set; } = new();
/// <summary>
/// Название куста
/// </summary>
public string? Cluster { get; set; }
/// <summary>
/// блок САУБ
/// </summary>
public SaubDto Saub { get; set; } = new();
/// <summary>
/// Заказчик
/// </summary>
public string? Customer { get; set; }
/// <summary>
/// блок подписи
/// </summary>
public SignDto Sign { get; set; } = new();
}
/// <summary>
/// Подрядчик
/// </summary>
public string? Contractor { get; set; }
/// <summary>
/// Месторождение
/// </summary>
public string? Deposit { get; set; }
/// <summary>
/// Глубина забоя на дату начала интервала
/// </summary>
public double? DepthStart { get; set; }
/// <summary>
/// Глубина забоя на дату окончания интервала
/// </summary>
public double? DepthEnd { get; set; }
/// <summary>
/// Дата формирования отчёта
/// </summary>
public DateTime Date { get; set; }
/// <summary>
/// Дата последнего обновления
/// </summary>
public DateTime? DateLastUpdate { get; set; }
/// <summary>
/// Блок фактической траектории
/// </summary>
public TrajectoryBlockDto TrajectoryBlock { get; set; } = null!;
/// <summary>
/// Фактические операции
/// </summary>
public WellOperationBlockDto FactWellOperationBlock { get; set; } = null!;
/// <summary>
/// Баланс времени
/// </summary>
public TimeBalanceBlockDto? TimeBalanceBlock { get; set; }
/// <summary>
/// Наработка подсистем
/// </summary>
public SubsystemBlockDto? SubsystemBlock { get; set; }
/// <summary>
/// Подпись
/// </summary>
public SignBlockDto? SignBlock { get; set; }
/// <summary>
/// Блок расписания
/// </summary>
public IEnumerable<ScheduleRecordDto> ScheduleBlock { get; set; } = Enumerable.Empty<ScheduleRecordDto>();
/// <summary>
/// РТК
/// </summary>
public IEnumerable<ProcessMapWellDrillingRecordDto> ProcessMapWellDrillingBlock { get; set; } = Enumerable.Empty<ProcessMapWellDrillingRecordDto>();
}

View File

@ -1,110 +0,0 @@
using System;
namespace AsbCloudApp.Data.DailyReport
{
/// <summary>
/// блок заголовка
/// </summary>
public class HeadDto : ItemInfoDto
{
/// <summary>
/// название скважины
/// </summary>
public string WellName { get; set; } = string.Empty;
/// <summary>
/// название куста
/// </summary>
public string ClusterName { get; set; } = string.Empty;
/// <summary>
/// заказчик
/// </summary>
public string Customer { get; set; } = string.Empty;
/// <summary>
/// подрядчик
/// </summary>
public string Contractor { get; set; } = string.Empty;
/// <summary>
/// дата рапорта
/// </summary>
public DateOnly ReportDate { get; set; }
/// <summary>
/// глубина забоя на дату начала интервала
/// </summary>
public double? WellDepthIntervalStartDate { get; set; }
/// <summary>
/// глубина забоя на дату окончания интервала
/// </summary>
public double? WellDepthIntervalFinishDate { get; set; }
/// <summary>
/// Глубина забоя по стволу на окончание отчетного периода
/// </summary>
public double? BottomholeDepth { get; set; }
/// <summary>
/// Глубина забоя по вертикали на дату окончания отчетного периода
/// </summary>
public double? VerticalDepth { get; set; }
/// <summary>
/// Зенитный угол на дату окончания отчетного периода
/// </summary>
public double? ZenithAngle { get; set; }
/// <summary>
/// Азимутальный угол на дату окончания отчетного периода
/// </summary>
public double? AzimuthAngle { get; set; }
/// <summary>
/// ФИО бурильщиков
/// </summary>
public string FirstDriller { get; set; } = string.Empty;
/// <summary>
/// ФИО бурильщиков
/// </summary>
public string SecondDriller { get; set; } = string.Empty;
/// <summary>
/// Время работы АПД
/// </summary>
public double? WorkTimeSAUB { get; set; }
/// <summary>
/// Время работы спин мастер
/// </summary>
public double? WorkTimeSpinMaster { get; set; }
/// <summary>
/// Время работы torqueMaster
/// </summary>
public double? WorkTimeTorkMaster { get; set; }
/// <summary>
/// количество метров пробуренных с включенным АПД
/// </summary>
public double? PenetrationSAUB { get; set; }
/// <summary>
/// количество метров пробуренных с включенным Спин мастер
/// </summary>
public double? PenetrationSpinMaster { get; set; }
/// <summary>
/// количество метров пробуренных с включенным torqueMaster
/// </summary>
public double? PenetrationTorkMaster { get; set; }
/// <summary>
/// Количество запусков МСЕ
/// </summary>
public int CountLaunchesMSE { get; set; }
}
}

View File

@ -1,29 +0,0 @@
namespace AsbCloudApp.Data.DailyReport
{
/// <summary>
/// блок безметражные работы
/// </summary>
public class NoDrillingDto : ItemInfoDto
{
/// <summary>
/// Нормативное время на одну операцию по подготовке ствола скважины к наращиванию
/// </summary>
public double? StandardTimeBarrelPreparation { get; set; }
/// <summary>
/// Нормативное время на одну операцию по наращиванию
/// </summary>
public double? StandardTimeExtension { get; set; }
/// <summary>
/// Фактическое время проработок при подготовке ствола скважины к наращиванию.
/// </summary>
public double? ActualTimeBarrelPreparation { get; set; }
/// <summary>
/// Фактическое время наращиваний
/// </summary>
public double? ActualTimeExtension { get; set; }
}
}

View File

@ -1,107 +0,0 @@
using System.Collections.Generic;
namespace AsbCloudApp.Data.DailyReport
{
/// <summary>
/// блок САУБ
/// </summary>
public class SaubDto : ItemInfoDto
{
/// <summary>
/// Режимы бурения в роторе
/// </summary>
public string RotorDrillingModes { get; set; } = string.Empty;
/// <summary>
/// режимы бурения в слайде
/// </summary>
public string SlideDrillingModes { get; set; } = string.Empty;
/// <summary>
/// Количество метров пробуренных в роторе за отчетный период
/// </summary>
public double? PenetrationInRotor { get; set; }
/// <summary>
/// Количество часов бурения в роторе за отчетный период
/// </summary>
public double? NumberDrillingHours { get; set; }
/// <summary>
/// средний диф перепад в роторе за отчетный период
/// </summary>
public double? AVGDiffDropRotor { get; set; }
/// <summary>
/// количество метров пробуренных в слайде за отчетный период
/// </summary>
public double? PenetrationInSlide { get; set; }
/// <summary>
/// время бурения в роторе за отчетный период
/// </summary>
public double? DrillingTimeInRotor { get; set; }
/// <summary>
/// средний диф. перепад в слайде за отчетный период
/// </summary>
public double? AVGDiffPressureSlide { get; set; }
/// <summary>
/// Плановая МСП за секцию
/// </summary>
public double? SectionROPPlan { get; set; }
/// <summary>
/// Общее время бурения за секцию
/// </summary>
public double? SectionDrillingTimeTotal { get; set; }
/// <summary>
/// Общая проходка за секцию
/// </summary>
public double? SectionPenetrationTotal { get; set; }
/// <summary>
/// Количество наращиваний за отчетный период
/// </summary>
public int ExtensionsCount { get; set; }
/// <summary>
/// Отклонение относительно ГГД
/// </summary>
public double? DeviationFromTVD { get; set; }
/// <summary>
/// указываются все причины, которые влияют на снижение МСП.
/// </summary>
public string DeclinesReasonsROP { get; set; } = string.Empty;
/// <summary>
/// Увеличение мех скорости за секцию %
/// </summary>
public string IncreaseSpeedSection { get; set; } = string.Empty;
/// <summary>
/// Увеличение мех скорости за сутки %
/// </summary>
public string IncreaseSpeedDay { get; set; } = string.Empty;
/// <summary>
/// Сокращение времени бурения за секцию, ч
/// </summary>
public string ReductionTimeDrilling { get; set; } = string.Empty;
/// <summary>
/// Ротор/Слайд %
/// </summary>
public string RotorSlidePercent { get; set; } = string.Empty;
/// <summary>
/// МСП
/// </summary>
public string MspSection { get; set; } = string.Empty;
}
}

View File

@ -1,19 +0,0 @@
namespace AsbCloudApp.Data.DailyReport
{
/// <summary>
/// блок подписи
/// </summary>
public class SignDto : ItemInfoDto
{
/// <summary>
/// ФИО Мастера буровой
/// </summary>
public string DrillingMaster { get; set; } = null!;
/// <summary>
/// ФИО супервайзера
/// </summary>
public string Supervisor { get; set; } = null!;
}
}

View File

@ -1,18 +0,0 @@
using System.Collections.Generic;
namespace AsbCloudApp.Data.DailyReport
{
/// <summary>
/// Блок баланса времени
/// </summary>
public class TimeBalanceDto : ItemInfoDto
{
/// <summary>
/// Статистика по операциям
/// </summary>
public Dictionary<int, double> OperationsStat { get; set; } = new Dictionary<int, double>();
}
}

View File

@ -7,92 +7,92 @@ namespace AsbCloudApp.Data.ProcessMaps.Report;
/// </summary>
public class ProcessMapReportWellDrillingDto
{
/// <summary>
/// Идентификатор скважины
/// </summary>
public int IdWell { get; set; }
/// <summary>
/// Идентификатор скважины
/// </summary>
public int IdWell { get; set; }
/// <summary>
/// Id секции скважины
/// </summary>
public int IdWellSectionType { get; set; }
/// <summary>
/// Id секции скважины
/// </summary>
public int IdWellSectionType { get; set; }
/// <summary>
/// Название секции скважины
/// </summary>
public string WellSectionTypeName { get; set; } = null!;
/// <summary>
/// Название секции скважины
/// </summary>
public string WellSectionTypeName { get; set; } = null!;
/// <summary>
/// Глубина по стволу от, м
/// <para>
/// на начало интервала
/// </para>
/// </summary>
public double DepthStart { get; set; }
/// <summary>
/// Глубина по стволу от, м
/// <para>
/// на начало интервала
/// </para>
/// </summary>
public double DepthStart { get; set; }
/// <summary>
/// Глубина по стволу до, м
/// <para>
/// на конец интервала
/// </para>
/// </summary>
public double DepthEnd { get; set; }
/// <summary>
/// Глубина по стволу до, м
/// <para>
/// на конец интервала
/// </para>
/// </summary>
public double DepthEnd { get; set; }
/// <summary>
/// Дата/ время
/// <para>
/// на начало интервала
/// </para>
/// </summary>
public DateTime DateStart { get; set; }
/// <summary>
/// Дата/ время
/// <para>
/// на начало интервала
/// </para>
/// </summary>
public DateTime DateStart { get; set; }
/// <summary>
/// Время мех бурения, ч
/// </summary>
public double MechDrillingHours { get; set; }
/// <summary>
/// Время мех бурения, ч
/// </summary>
public double MechDrillingHours { get; set; }
/// <summary>
/// Режим бурения (Ротор/слайд/ручной)
/// </summary>
public string DrillingMode { get; set; } = null!;
/// <summary>
/// Режим бурения (Ротор/слайд/ручной)
/// </summary>
public string DrillingMode { get; set; } = null!;
/// <summary>
/// Проходка, м
/// </summary>
public double? DeltaDepth { get; set; }
/// <summary>
/// Проходка, м
/// </summary>
public double? DeltaDepth { get; set; }
/// <summary>
/// Перепад давления, атм
/// </summary>
public ProcessMapReportWellDrillingParamsDto PressureDiff { get; set; } = new();
/// <summary>
/// Перепад давления, атм
/// </summary>
public ProcessMapReportWellDrillingParamsDto PressureDiff { get; set; } = new();
/// <summary>
/// Нагрузка, т
/// </summary>
public ProcessMapReportWellDrillingParamsDto AxialLoad { get; set; } = new();
/// <summary>
/// Нагрузка, т
/// </summary>
public ProcessMapReportWellDrillingParamsDto AxialLoad { get; set; } = new();
/// <summary>
/// Момент на ВСП, кНхМ
/// </summary>
public ProcessMapReportWellDrillingParamsDto TopDriveTorque { get; set; } = new();
/// <summary>
/// Момент на ВСП, кНхМ
/// </summary>
public ProcessMapReportWellDrillingParamsDto TopDriveTorque { get; set; } = new();
/// <summary>
/// Ограничение скорости, м/ч
/// </summary>
public ProcessMapReportWellDrillingParamsDto SpeedLimit { get; set; } = new();
/// <summary>
/// Ограничение скорости, м/ч
/// </summary>
public ProcessMapReportWellDrillingParamsDto SpeedLimit { get; set; } = new();
/// <summary>
/// Процент использования системы АПД план, %
/// </summary>
public double UsagePlan { get; set; }
/// <summary>
/// Процент использования системы АПД план, %
/// </summary>
public double UsagePlan { get; set; }
/// <summary>
/// Процент использования системы АПД факт, %
/// </summary>
public double UsageFact { get; set; }
/// <summary>
/// Процент использования системы АПД факт, %
/// </summary>
public double UsageFact { get; set; }
/// <summary>
/// Фактическая механическая скорость, м/ч
/// </summary>
public double? Rop { get; set; }
/// <summary>
/// Механическая скорость, м/ч
/// </summary>
public PlanFactDto<double?> Rop { get; set; }
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
namespace AsbCloudApp.Repositories;
/// <summary>
/// Суточные отчёты
/// </summary>
public interface IDailyReportRepository : ICrudRepository<DailyReportDto>
{
/// <summary>
/// Получить список суточный отчёт по скважине
/// </summary>
/// <param name="idWell"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<DailyReportDto>> GetAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken);
/// <summary>
/// Получить суточный отчёт
/// </summary>
/// <param name="idWell"></param>
/// <param name="date"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<DailyReportDto?> GetOrDefaultAsync(int idWell, DateTime date, CancellationToken cancellationToken);
}

View File

@ -20,15 +20,4 @@ public interface IHelpPageRepository : ICrudRepository<HelpPageDto>
Task<HelpPageDto?> GetOrDefaultByUrlPageAndIdCategoryAsync(string key,
int idCategory,
CancellationToken cancellationToken);
/// <summary>
/// Проверяет наличие справки для страницы
/// </summary>
/// <param name="key"></param>
/// <param name="idCategory"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> IsExistingAsync(string key,
int idCategory,
CancellationToken cancellationToken);
}

View File

@ -1,4 +1,5 @@
using AsbCloudApp.Data.Trajectory;
using AsbCloudApp.Requests;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -14,9 +15,9 @@ namespace AsbCloudApp.Repositories
/// <summary>
/// Получить все добавленные по скважине координаты траектории
/// </summary>
/// <param name="idWell"></param>
/// <param name="request">параметры запроса</param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<T>> GetAsync(int idWell, CancellationToken token);
Task<IEnumerable<T>> GetAsync(TrajectoryRequest request, CancellationToken token);
}
}

View File

@ -0,0 +1,24 @@
using System;
namespace AsbCloudApp.Requests;
/// <summary>
/// Запрос для получения фактической траектории
/// </summary>
public class TrajectoryRequest : RequestBase
{
/// <summary>
/// Идентификатор скважины
/// </summary>
public int IdWell { get; set; }
/// <summary>
/// Больше или равно дате
/// </summary>
public DateTime? GeDate { get; set; }
/// <summary>
/// Меньше или равно дате
/// </summary>
public DateTime? LeDate { get; set; }
}

View File

@ -1,44 +0,0 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.AutogeneratedDailyReport;
using AsbCloudApp.Requests;
namespace AsbCloudApp.Services.AutoGeneratedDailyReports;
/// <summary>
/// Сервис для работы с авто-генерируемыми суточными отчётами
/// </summary>
public interface IAutoGeneratedDailyReportService
{
/// <summary>
/// Список файлов суточных отчётов
/// </summary>
/// <param name="idWell"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<PaginationContainer<AutoGeneratedDailyReportInfoDto>> GetListAsync(int idWell,
FileReportRequest request,
CancellationToken cancellationToken);
/// <summary>
/// Генерация файла с отчётом
/// </summary>
/// <param name="idWell"></param>
/// <param name="reportDate"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<(string fileName, Stream stream)> GenerateAsync(int idWell, DateOnly reportDate,
CancellationToken cancellationToken);
/// <summary>
/// Получение диапазона дат
/// </summary>
/// <param name="idWell"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken);
}

View File

@ -0,0 +1,21 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services.DailyReport;
/// <summary>
/// Сервис экспорта суточного отчёта
/// </summary>
public interface IDailyReportExportService
{
/// <summary>
/// Экспортировать
/// </summary>
/// <param name="idWell"></param>
/// <param name="dailyReportDateStart"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<(string FileName, Stream File)> ExportAsync(int idWell, DateTime dailyReportDateStart, CancellationToken cancellationToken);
}

View File

@ -0,0 +1,53 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Requests;
namespace AsbCloudApp.Services.DailyReport;
/// <summary>
/// Суточные отчёты
/// </summary>
public interface IDailyReportService
{
/// <summary>
/// Обновить или создать суточный отчёт
/// </summary>
/// <param name="dateDailyReport"></param>
/// <param name="idUser"></param>
/// <param name="editableBlock"></param>
/// <param name="cancellationToken"></param>
/// <param name="idWell"></param>
/// <returns></returns>
Task<int> UpdateOrInsertAsync<TBlock>(int idWell, DateTime dateDailyReport, int idUser, TBlock editableBlock,
CancellationToken cancellationToken)
where TBlock : ItemInfoDto;
/// <summary>
/// Получить сформированный суточный отчёт
/// </summary>
/// <param name="idWell"></param>
/// <param name="dateDailyReport"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<DailyReportDto> GetAsync(int idWell, DateTime dateDailyReport, CancellationToken cancellationToken);
/// <summary>
/// Получить список суточных отчётов по скважине
/// </summary>
/// <param name="idWell"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<PaginationContainer<DailyReportDto>> GetAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken);
/// <summary>
/// Получить диапазон дат по которым возможно сформировать суточный отчёты
/// </summary>
/// <param name="idWell"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken);
}

View File

@ -1,55 +0,0 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.DailyReport;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services
{
/// <summary>
/// Суточный рапорт (сводка)
/// </summary>
public interface IDailyReportService
{
/// <summary>
/// получить список сформированных рапортов по скважине за период времени
/// </summary>
/// <param name="idWell"></param>
/// <param name="begin"></param>
/// <param name="end"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<DailyReportDto>> GetListAsync(int idWell, DateOnly? begin, DateOnly? end, CancellationToken cancellationToken);
/// <summary>
/// Добавить новый рапорт
/// </summary>
/// <param name="idWell"></param>
/// <param name="startDate"></param>
/// <param name="idUser"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> AddAsync(int idWell, DateOnly startDate, int idUser, CancellationToken token);
/// <summary>
/// Сформировать файл рапорта
/// </summary>
/// <param name="idWell"></param>
/// <param name="date"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<Stream?> MakeReportAsync(int idWell, DateOnly date, CancellationToken token);
/// <summary>
/// изменить блок данных для суточного рапорта
/// </summary>
/// <param name="idWell"></param>
/// <param name="startDate"></param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> UpdateBlockAsync(int idWell, DateOnly startDate, ItemInfoDto dto, CancellationToken token);
}
}

View File

@ -1,5 +1,6 @@
using AsbCloudApp.Data;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -10,6 +11,15 @@ namespace AsbCloudApp.Services
/// </summary>
public interface IScheduleRepository : IRepositoryWellRelated<ScheduleDto>
{
/// <summary>
/// Получить расписание смен
/// </summary>
/// <param name="idWell"></param>
/// <param name="workTime"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<ScheduleDto>> GetAsync(int idWell, DateTime workTime, CancellationToken token);
/// <summary>
/// получить бурильщика по idWell и времени
/// </summary>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,140 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace AsbCloudDb.Migrations
{
public partial class Update_DailyReport : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("Truncate table t_daily_report");
migrationBuilder.DropPrimaryKey(
name: "t_id_well_date_start_pk",
table: "t_daily_report");
migrationBuilder.DropColumn(
name: "start_date",
table: "t_daily_report");
migrationBuilder.DropColumn(
name: "info",
table: "t_daily_report");
migrationBuilder.AddColumn<int>(
name: "Id",
table: "t_daily_report",
type: "integer",
nullable: false,
defaultValue: 0)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
migrationBuilder.AddColumn<DateTime>(
name: "date",
table: "t_daily_report",
type: "timestamp with time zone",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
comment: "Дата формирования отчёта");
migrationBuilder.AddColumn<DateTime>(
name: "date_last_update",
table: "t_daily_report",
type: "timestamp with time zone",
nullable: true,
comment: "Дата последнего обновления");
migrationBuilder.AddColumn<string>(
name: "sign_block",
table: "t_daily_report",
type: "jsonb",
nullable: true,
comment: "Подпись");
migrationBuilder.AddColumn<string>(
name: "subsystem_block",
table: "t_daily_report",
type: "jsonb",
nullable: true,
comment: "Наработкой подсистем");
migrationBuilder.AddColumn<string>(
name: "time_balance_block",
table: "t_daily_report",
type: "jsonb",
nullable: true,
comment: "Баланс времени");
migrationBuilder.AddPrimaryKey(
name: "PK_t_daily_report",
table: "t_daily_report",
column: "Id");
migrationBuilder.CreateIndex(
name: "IX_t_daily_report_id_well_date",
table: "t_daily_report",
columns: new[] { "id_well", "date" },
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("Truncate table t_daily_report");
migrationBuilder.DropPrimaryKey(
name: "PK_t_daily_report",
table: "t_daily_report");
migrationBuilder.DropIndex(
name: "IX_t_daily_report_id_well_date",
table: "t_daily_report");
migrationBuilder.DropColumn(
name: "Id",
table: "t_daily_report");
migrationBuilder.DropColumn(
name: "date",
table: "t_daily_report");
migrationBuilder.DropColumn(
name: "date_last_update",
table: "t_daily_report");
migrationBuilder.DropColumn(
name: "sign_block",
table: "t_daily_report");
migrationBuilder.DropColumn(
name: "subsystem_block",
table: "t_daily_report");
migrationBuilder.DropColumn(
name: "time_balance_block",
table: "t_daily_report");
migrationBuilder.AddColumn<DateOnly>(
name: "start_date",
table: "t_daily_report",
type: "date",
nullable: false,
defaultValue: new DateOnly(1, 1, 1),
comment: "Дата отчёта");
migrationBuilder.AddColumn<string>(
name: "info",
table: "t_daily_report",
type: "jsonb",
nullable: true,
comment: "Список параметров для отчёта");
migrationBuilder.AddPrimaryKey(
name: "t_id_well_date_start_pk",
table: "t_daily_report",
columns: new[] { "id_well", "start_date" });
}
}
}

View File

@ -3,6 +3,7 @@ using AsbCloudDb.Model.Subsystems;
using Microsoft.EntityFrameworkCore;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudDb.Model.DailyReports;
using AsbCloudDb.Model.Manuals;
using AsbCloudDb.Model.ProcessMaps;
using AsbCloudDb.Model.Trajectory;
@ -14,7 +15,7 @@ namespace AsbCloudDb.Model
public virtual DbSet<Cluster> Clusters => Set<Cluster>();
public virtual DbSet<Company> Companies => Set<Company>();
public virtual DbSet<CompanyType> CompaniesTypes => Set<CompanyType>();
public virtual DbSet<DailyReport.DailyReport> DailyReports => Set <DailyReport.DailyReport >();
public virtual DbSet<DailyReport> DailyReports => Set <DailyReport>();
public virtual DbSet<Deposit> Deposits => Set<Deposit>();
public virtual DbSet<DetectedOperation> DetectedOperations => Set<DetectedOperation>();
public virtual DbSet<TrajectoryPlanned> PlannedTrajectories => Set<TrajectoryPlanned>();
@ -333,11 +334,18 @@ namespace AsbCloudDb.Model
.IsRequired();
});
modelBuilder.Entity<DailyReport.DailyReport >(entity =>
modelBuilder.Entity<DailyReport>(entity =>
{
entity.HasKey(e => new { e.IdWell, e.StartDate })
.HasName("t_id_well_date_start_pk");
entity.Property(e => e.Info)
entity.HasIndex(e => new { e.IdWell, e.Date })
.IsUnique();
entity.Property(e => e.SubsystemBlock)
.HasJsonConversion();
entity.Property(e => e.SignBlock)
.HasJsonConversion();
entity.Property(e => e.TimeBalanceBlock)
.HasJsonConversion();
});

View File

@ -1,61 +0,0 @@
namespace AsbCloudDb.Model.DailyReport
{
public class Bha : ItemInfo
{
/// <summary>
/// КНБК описание
/// </summary>
public string BHADescription { get; set; } = string.Empty;
/// <summary>
/// Бурение с наращиваниями в инт. 2195-2763м. Время начала
/// </summary>
public string ExtensionDrillingOneBegin { get; set; } = string.Empty;
/// <summary>
/// Бурение с наращиваниями в инт. 2195-2763м. Время окончания
/// </summary>
public string ExtensionDrillingOneFinish { get; set; } = string.Empty;
/// <summary>
/// Промывка. Время начала
/// </summary>
public string SluiceBegin { get; set; } = string.Empty;
/// <summary>
/// Промывка. Время окончания
/// </summary>
public string SluiceFinish { get; set; } = string.Empty;
/// <summary>
/// Подьем КНБК. Время начала
/// </summary>
public string ClimbBegin { get; set; } = string.Empty;
/// <summary>
/// Подьем КНБК. Время окончания
/// </summary>
public string ClimbFinish { get; set; } = string.Empty;
/// <summary>
/// Спуск КНБК. Время начала
/// </summary>
public string DescentBegin { get; set; } = string.Empty;
/// <summary>
/// Спуск КНБК. Время окончания
/// </summary>
public string DescentFinish { get; set; } = string.Empty;
/// <summary>
/// Бурение с наращиваниями в инт. 2763-2850м. Время начала
/// </summary>
public string ExtensionDrillingTwoBegin { get; set; } = string.Empty;
/// <summary>
/// Бурение с наращиваниями в инт. 2763-2850м. Время окончания
/// </summary>
public string ExtensionDrillingTwoFinish { get; set; } = string.Empty;
}
}

View File

@ -1,22 +0,0 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.ComponentModel.DataAnnotations.Schema;
namespace AsbCloudDb.Model.DailyReport
{
[Table("t_daily_report"), Comment("Ежедневные отчёты")]
public class DailyReport
{
[Column("id_well"), Comment("ID скважины")]
public int IdWell { get; set; }
[Column("start_date", TypeName = "date"), Comment("Дата отчёта")]
public DateOnly StartDate { get; set; }
[Column("info", TypeName = "jsonb"), Comment("Список параметров для отчёта")]
public DailyReportInfo Info { get; set; } = null!;
[ForeignKey(nameof(IdWell))]
public virtual Well Well { get; set; } = null!;
}
}

View File

@ -1,13 +0,0 @@
using AsbCloudDb.Model.DailyReport;
namespace AsbCloudDb.Model
{
public class DailyReportInfo
{
public Head Head { get; set; } = null!;
public Bha Bha { get; set; } = new();
public NoDrilling NoDrilling { get; set; } = new();
public Saub Saub { get; set; } = new();
public Sign Sign { get; set; } = new();
}
}

View File

@ -1,110 +0,0 @@
using System;
using System.Text.Json.Serialization;
namespace AsbCloudDb.Model.DailyReport
{
public class Head : ItemInfo
{
/// <summary>
/// название скважины
/// </summary>
public string WellName { get; set; } = string.Empty;
/// <summary>
/// название куста
/// </summary>
public string ClusterName { get; set; } = string.Empty;
/// <summary>
/// заказчик
/// </summary>
public string Customer { get; set; } = string.Empty;
/// <summary>
/// подрядчик
/// </summary>
public string Contractor { get; set; } = string.Empty;
/// <summary>
/// дата рапорта
/// </summary>
[JsonConverter(typeof(DateOnlyJsonConverter))]
public DateOnly ReportDate { get; set; }
/// <summary>
/// глубина забоя на дату начала интервала
/// </summary>
public double? WellDepthIntervalStartDate { get; set; }
/// <summary>
/// глубина забоя на дату окончания интервала
/// </summary>
public double? WellDepthIntervalFinishDate { get; set; }
/// <summary>
/// Глубина забоя по стволу на окончание отчетного периода
/// </summary>
public double? BottomholeDepth { get; set; }
/// <summary>
/// Глубина забоя по вертикали на дату окончания отчетного периода
/// </summary>
public double? VerticalDepth { get; set; }
/// <summary>
/// Зенитный угол на дату окончания отчетного периода
/// </summary>
public double? ZenithAngle { get; set; }
/// <summary>
/// Азимутальный угол на дату окончания отчетного периода
/// </summary>
public double? AzimuthAngle { get; set; }
/// <summary>
/// ФИО бурильщиков
/// </summary>
public string FirstDriller { get; set; } = string.Empty;
/// <summary>
/// ФИО бурильщиков
/// </summary>
public string SecondDriller { get; set; } = string.Empty;
/// <summary>
/// Время работы АПД
/// </summary>
public double? WorkTimeSAUB { get; set; }
/// <summary>
/// Время работы спин мастер
/// </summary>
public double? WorkTimeSpinMaster { get; set; }
/// <summary>
/// Время работы torqueMaster
/// </summary>
public double? WorkTimeTorkMaster { get; set; }
/// <summary>
/// количество метров пробуренных с включенным АПД
/// </summary>
public double? PenetrationSAUB { get; set; }
/// <summary>
/// количество метров пробуренных с включенным Спин мастер
/// </summary>
public double? PenetrationSpinMaster { get; set; }
/// <summary>
/// количество метров пробуренных с включенным torqueMaster
/// </summary>
public double? PenetrationTorkMaster { get; set; }
/// <summary>
/// Количество запусков МСЕ
/// </summary>
public int CountLaunchesMSE { get; set; }
}
}

View File

@ -1,26 +0,0 @@
namespace AsbCloudDb.Model.DailyReport
{
public class NoDrilling : ItemInfo
{
/// <summary>
/// Нормативное время на одну операцию по подготовке ствола скважины к наращиванию
/// </summary>
public double? StandardTimeBarrelPreparation { get; set; }
/// <summary>
/// Нормативное время на одну операцию по наращиванию
/// </summary>
public double? StandardTimeExtension { get; set; }
/// <summary>
/// Фактическое время проработок при подготовке ствола скважины к наращиванию.
/// </summary>
public double? ActualTimeBarrelPreparation { get; set; }
/// <summary>
/// Фактическое время наращиваний
/// </summary>
public double? ActualTimeExtension { get; set; }
}
}

View File

@ -1,101 +0,0 @@
namespace AsbCloudDb.Model.DailyReport
{
public class Saub : ItemInfo
{
/// <summary>
/// Режимы бурения в роторе
/// </summary>
public string? RotorDrillingModes { get; set; }
/// <summary>
/// режимы бурения в слайде
/// </summary>
public string? SlideDrillingModes { get; set; }
/// <summary>
/// Количество метров пробуренных в роторе за отчетный период
/// </summary>
public double? PenetrationInRotor { get; set; }
/// <summary>
/// Количество часов бурения в роторе за отчетный период
/// </summary>
public double? NumberDrillingHours { get; set; }
/// <summary>
/// средний диф перепад в роторе за отчетный период
/// </summary>
public double? AVGDiffDropRotor { get; set; }
/// <summary>
/// количество метров пробуренных в слайде за отчетный период
/// </summary>
public double? PenetrationInSlide { get; set; }
/// <summary>
/// время бурения в роторе за отчетный период
/// </summary>
public double? DrillingTimeInRotor { get; set; }
/// <summary>
/// средний диф. перепад в слайде за отчетный период
/// </summary>
public double? AVGDiffPressureSlide { get; set; }
/// <summary>
/// Плановая МСП за секцию
/// </summary>
public double? SectionROPPlan { get; set; }
/// <summary>
/// Общее время бурения за секцию
/// </summary>
public double? SectionDrillingTimeTotal { get; set; }
/// <summary>
/// Общая проходка за секцию
/// </summary>
public double? SectionPenetrationTotal { get; set; }
/// <summary>
/// Количество наращиваний за отчетный период
/// </summary>
public int ExtensionsCount { get; set; }
/// <summary>
/// Отклонение относительно ГГД
/// </summary>
public double? DeviationFromTVD { get; set; }
/// <summary>
/// указываются все причины, которые влияют на снижение МСП.
/// </summary>
public string DeclinesReasonsROP { get; set; } = string.Empty;
/// <summary>
/// Увеличение мех скорости за секцию %
/// </summary>
public string IncreaseSpeedSection { get; set; } = string.Empty;
/// <summary>
/// Увеличение мех скорости за сутки %
/// </summary>
public string IncreaseSpeedDay { get; set; } = string.Empty;
/// <summary>
/// Сокращение времени бурения за секцию, ч
/// </summary>
public string ReductionTimeDrilling { get; set; } = string.Empty;
/// <summary>
/// Ротор/Слайд %
/// </summary>
public string RotorSlidePercent { get; set; } = string.Empty;
/// <summary>
/// МСП
/// </summary>
public string MspSection { get; set; } = string.Empty;
}
}

View File

@ -1,16 +0,0 @@
namespace AsbCloudDb.Model.DailyReport
{
public class Sign : ItemInfo
{
/// <summary>
/// ФИО Мастера буровой
/// </summary>
public string DrillingMaster { get; set; } = string.Empty;
/// <summary>
/// ФИО супервайзера
/// </summary>
public string Supervisor { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,8 @@
namespace AsbCloudDb.Model.DailyReports.Blocks.Sign;
public class SignBlock : ItemInfo
{
public SignRecord? DrillingMaster { get; set; }
public SignRecord? Supervisor { get; set; }
}

View File

@ -0,0 +1,10 @@
namespace AsbCloudDb.Model.DailyReports.Blocks.Sign;
public class SignRecord
{
public string Name { get; set; } = null!;
public string Surname { get; set; } = null!;
public string? Patronymic { get; set; }
}

View File

@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace AsbCloudDb.Model.DailyReports.Blocks.Subsystem;
public class SubsystemBlock : ItemInfo
{
public double? Wellbore { get; set; }
public double? MeasurementsPerDay { get; set; }
public double? TvgLagDays { get; set; }
public double? TotalRopPlan { get; set; }
public string? Comment { get; set; }
public IEnumerable<SubsystemRecord>? Subsystems { get; set; }
}

View File

@ -0,0 +1,10 @@
namespace AsbCloudDb.Model.DailyReports.Blocks.Subsystem;
public class SubsystemParameters
{
public double? SumDepthInterval { get; set; }
public double? UsedTimeHours { get; set; }
public double? KUsage { get; set; }
}

View File

@ -0,0 +1,10 @@
namespace AsbCloudDb.Model.DailyReports.Blocks.Subsystem;
public class SubsystemRecord
{
public string Name { get; set; } = null!;
public SubsystemParameters? UsagePerDay { get; set; }
public SubsystemParameters? UsagePerWell { get; set; }
}

View File

@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace AsbCloudDb.Model.DailyReports.Blocks.TimeBalance;
public class TimeBalanceBlock : ItemInfo
{
public int IdSection { get; set; }
public string? SectionName { get; set; }
public double? WellDepthPlan { get; set; }
public double WellDepthFact { get; set; }
public double? WellOperationSlipsTimeCount { get; set; }
public IEnumerable<TimeBalanceRecord>? WellOperations { get; set; }
}

View File

@ -0,0 +1,16 @@
namespace AsbCloudDb.Model.DailyReports.Blocks.TimeBalance;
public class TimeBalanceRecord
{
public int IdWellOperation { get; set; }
public double? DurationHoursPlan { get; set; }
public double? DurationHoursFact { get; set; }
public double? DrillingDeviationPerSection { get; set; }
public double? DrillingDeviationPerDay { get; set; }
public string? ReasonDeviation { get; set; }
}

View File

@ -0,0 +1,37 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using AsbCloudDb.Model.DailyReports.Blocks.Sign;
using AsbCloudDb.Model.DailyReports.Blocks.Subsystem;
using AsbCloudDb.Model.DailyReports.Blocks.TimeBalance;
using Microsoft.EntityFrameworkCore;
namespace AsbCloudDb.Model.DailyReports;
[Table("t_daily_report"), Comment("Ежедневные отчёты")]
public class DailyReport : IId
{
[Key]
public int Id { get; set; }
[Column("id_well"), Comment("ID скважины")]
public int IdWell { get; set; }
[Column("date_last_update", TypeName = "timestamp with time zone"), Comment("Дата последнего обновления")]
public DateTime? DateLastUpdate { get; set; }
[Column("date", TypeName = "timestamp with time zone"), Comment("Дата формирования отчёта")]
public DateTime Date { get; set; }
[Column("sign_block", TypeName = "jsonb"), Comment("Подпись")]
public SignBlock? SignBlock { get; set; }
[Column("time_balance_block", TypeName = "jsonb"), Comment("Баланс времени")]
public TimeBalanceBlock? TimeBalanceBlock { get; set; }
[Column("subsystem_block", TypeName = "jsonb"), Comment("Наработкой подсистем")]
public SubsystemBlock? SubsystemBlock { get; set; }
[ForeignKey(nameof(IdWell))]
public virtual Well Well { get; set; } = null!;
}

View File

@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using System;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudDb.Model.DailyReports;
using AsbCloudDb.Model.Manuals;
using AsbCloudDb.Model.ProcessMaps;
using AsbCloudDb.Model.Trajectory;
@ -18,7 +19,7 @@ namespace AsbCloudDb.Model
DbSet<Cluster> Clusters { get; }
DbSet<Company> Companies { get; }
DbSet<CompanyType> CompaniesTypes { get; }
DbSet<DailyReport.DailyReport> DailyReports { get; }
DbSet<DailyReport> DailyReports { get; }
DbSet<Deposit> Deposits { get; }
DbSet<DetectedOperation> DetectedOperations { get; }
DbSet<TrajectoryPlanned> PlannedTrajectories { get; }

View File

@ -40,7 +40,6 @@
<EmbeddedResource Include="Services\Trajectory\Templates\TrajectoryFactManualTemplate.xlsx" />
<EmbeddedResource Include="Services\Trajectory\Templates\TrajectoryPlannedTemplate.xlsx" />
<EmbeddedResource Include="Services\WellOperationService\ScheduleReportTemplate.xlsx" />
<EmbeddedResource Include="Services\AutoGeneratedDailyReports\AutogeneratedDailyReportTemplate.xlsx" />
<EmbeddedResource Include="Services\WellOperationImport\Files\WellOperationImportTemplate.xlsx" />
<EmbeddedResource Include="Services\WellOperationImport\Files\Dictionaries\Operations.txt" />
<EmbeddedResource Include="Services\WellOperationImport\Files\Dictionaries\Sections.txt" />
@ -67,10 +66,6 @@
<ProjectReference Include="..\AsbCloudDb\AsbCloudDb.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Services\DailyReport\DailyReportBlocks\" />
</ItemGroup>
<ItemGroup>
<Reference Include="AsbWitsInfo">
<HintPath>CommonLibs\AsbWitsInfo.dll</HintPath>

View File

@ -1,6 +1,5 @@
using System;
using AsbCloudApp.Data;
using AsbCloudApp.Data.AutogeneratedDailyReport;
using AsbCloudApp.Data.DrillTestReport;
using AsbCloudApp.Data.Manuals;
using AsbCloudApp.Data.ProcessMaps;
@ -10,7 +9,6 @@ using AsbCloudApp.Data.Trajectory;
using AsbCloudApp.Data.WellOperationImport.Options;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudApp.Services.AutoGeneratedDailyReports;
using AsbCloudApp.Services.Notifications;
using AsbCloudApp.Services.ProcessMaps;
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
@ -24,7 +22,6 @@ using AsbCloudDb.Model.Trajectory;
using AsbCloudInfrastructure.Background;
using AsbCloudInfrastructure.Repository;
using AsbCloudInfrastructure.Services;
using AsbCloudInfrastructure.Services.AutoGeneratedDailyReports;
using AsbCloudInfrastructure.Services.DailyReport;
using AsbCloudInfrastructure.Services.DetectOperations;
using AsbCloudInfrastructure.Services.DrillingProgram;
@ -44,6 +41,9 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
using AsbCloudApp.Services.DailyReport;
using AsbCloudDb.Model.DailyReports.Blocks.TimeBalance;
namespace AsbCloudInfrastructure
{
@ -140,6 +140,22 @@ namespace AsbCloudInfrastructure
.Map(dest => dest.TopDriveSpeedLimitMax, src => src.TopDriveSpeed.LimitMax)
.Map(dest => dest.TopDriveTorquePlan, src => src.TopDriveTorque.Plan)
.Map(dest => dest.TopDriveTorqueLimitMax, src => src.TopDriveTorque.LimitMax);
TypeAdapterConfig.GlobalSettings.Default.Config
.ForType<TimeBalanceRecord, TimeBalanceRecordDto>()
.Map(dest => dest.DurationHours, src => new PlanFactDto<double?>()
{
Plan = src.DurationHoursPlan,
Fact = src.DurationHoursFact
});
TypeAdapterConfig.GlobalSettings.Default.Config
.ForType<TimeBalanceBlock, TimeBalanceBlockDto>()
.Map(dest => dest.WellDepth, src => new PlanFactDto<double?>()
{
Plan = src.WellDepthPlan
});
}
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
@ -279,8 +295,6 @@ namespace AsbCloudInfrastructure
services.AddTransient<IWitsRecordRepository<AsbCloudApp.Data.WITS.Record60Dto>, WitsRecordRepository<AsbCloudApp.Data.WITS.Record60Dto, AsbCloudDb.Model.WITS.Record60>>();
services.AddTransient<IWitsRecordRepository<AsbCloudApp.Data.WITS.Record61Dto>, WitsRecordRepository<AsbCloudApp.Data.WITS.Record61Dto, AsbCloudDb.Model.WITS.Record61>>();
services.AddTransient<IAutoGeneratedDailyReportService, AutoGeneratedDailyReportService>();
services.AddTransient<IReportMakerService<AutoGeneratedDailyReportDto>, AutoGeneratedDailyReportMakerService>();
services.AddTransient<IDrillTestReportService, DrillTestReportService>();
services.AddTransient<IReportMakerService<DrillTestReportDataDto>, DrillTestReportMakerService>();
@ -299,6 +313,10 @@ namespace AsbCloudInfrastructure
services.AddTransient<DetectedOperationExportService>();
services.AddTransient<IDailyReportService, DailyReportService>();
services.AddTransient<IDailyReportRepository, DailyReportRepository>();
services.AddTransient<IDailyReportExportService, DailyReportExportService>();
return services;
}
}

View File

@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Data.DailyReport.Blocks.Sign;
using AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudDb;
using AsbCloudDb.Model;
using AsbCloudDb.Model.DailyReports;
using Mapster;
using Microsoft.EntityFrameworkCore;
namespace AsbCloudInfrastructure.Repository;
public class DailyReportRepository : CrudRepositoryBase<DailyReportDto, DailyReport>,
IDailyReportRepository
{
public DailyReportRepository(IAsbCloudDbContext dbContext)
: base(dbContext)
{
}
public async Task<IEnumerable<DailyReportDto>> GetAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken)
{
var skip = request.Skip ?? 0;
var take = request.Take ?? 10;
var query = GetQuery().Where(d => d.IdWell == idWell);
if (request.GeDate.HasValue)
{
var geDate = request.GeDate.Value.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
query = query.Where(d => d.Date >= geDate);
}
if (request.LeDate.HasValue)
{
var leDate = request.LeDate.Value.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
query = query.Where(d => d.Date <= leDate);
}
if (request.SortFields?.Any() == true)
{
query = query.SortBy(request.SortFields);
}
else
{
query = query.OrderBy(d => d.Date);
}
var entities = await query
.Skip(skip)
.Take(take)
.AsNoTracking()
.ToArrayAsync(cancellationToken);
var dtos = entities.Select(Convert);
return dtos;
}
public async Task<DailyReportDto?> GetOrDefaultAsync(int idWell, DateTime date, CancellationToken cancellationToken)
{
var entity = await GetQuery()
.AsNoTracking()
.SingleOrDefaultAsync(d => d.IdWell == idWell && d.Date == date, cancellationToken);
return entity is null ? null : Convert(entity);
}
protected override DailyReportDto Convert(DailyReport src)
{
var dto = new DailyReportDto
{
Id = src.Id,
IdWell = src.IdWell,
DateLastUpdate = src.DateLastUpdate,
Date = src.Date,
SignBlock = src.SignBlock?.Adapt<SignBlockDto>(),
TimeBalanceBlock = src.TimeBalanceBlock?.Adapt<TimeBalanceBlockDto>(),
SubsystemBlock = src.SubsystemBlock?.Adapt<SubsystemBlockDto>()
};
return dto;
}
}

View File

@ -31,9 +31,4 @@ public class HelpPageRepository : CrudRepositoryBase<HelpPageDto, HelpPage>,
return helpPage.Adapt<HelpPageDto>();
}
public Task<bool> IsExistingAsync(string key, int idCategory, CancellationToken cancellationToken) =>
dbContext.HelpPages.AnyAsync(h => h.UrlPage == key &&
h.IdCategory == idCategory,
cancellationToken);
}

View File

@ -1,17 +1,19 @@
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Mapster;
namespace AsbCloudInfrastructure.Repository
{
public class ScheduleRepository : CrudWellRelatedRepositoryBase<ScheduleDto, Schedule>, IScheduleRepository
public class ScheduleRepository : CrudWellRelatedRepositoryBase<ScheduleDto, Schedule>,
IScheduleRepository
{
private readonly IWellService wellService;
@ -21,21 +23,26 @@ namespace AsbCloudInfrastructure.Repository
this.wellService = wellService;
}
public async Task<IEnumerable<ScheduleDto>> GetAsync(int idWell, DateTime workTime, CancellationToken token)
{
var entities = await BuildQuery(idWell, workTime)
.AsNoTracking()
.ToArrayAsync(token);
return entities.Select(Convert);
}
public async Task<DrillerDto?> GetOrDefaultDrillerAsync(int idWell, DateTime workTime, CancellationToken token)
{
var hoursOffset = wellService.GetTimezone(idWell).Hours;
var date = workTime.ToUtcDateTimeOffset(hoursOffset);
var entities = await GetQuery()
.Where(s => s.IdWell == idWell
&& s.DrillStart <= date
&& s.DrillEnd >= date)
.ToListAsync(token);
var entities = await BuildQuery(idWell, workTime)
.AsNoTracking()
.ToArrayAsync(token);
if (!entities.Any())
return null;
var remoteDate = date.ToRemoteDateTime(hoursOffset);
var hoursOffset = wellService.GetTimezone(idWell).Hours;
var remoteDate = workTime.ToUtcDateTimeOffset(hoursOffset).ToRemoteDateTime(hoursOffset);
var time = new TimeOnly(remoteDate.Hour, remoteDate.Minute, remoteDate.Second);
var entity = entities.FirstOrDefault(s =>
@ -46,6 +53,17 @@ namespace AsbCloudInfrastructure.Repository
return entity?.Driller.Adapt<DrillerDto>();
}
private IQueryable<Schedule> BuildQuery(int idWell, DateTime workTime)
{
var hoursOffset = wellService.GetTimezone(idWell).Hours;
var workTimeDateTime = workTime.ToUtcDateTimeOffset(hoursOffset);
return GetQuery().Where(s => s.IdWell == idWell
&& s.DrillStart <= workTimeDateTime
&& s.DrillEnd >= workTimeDateTime);
}
protected override Schedule Convert(ScheduleDto dto)
{
var hoursOffset = wellService.GetTimezone(dto.IdWell).Hours;

View File

@ -1,6 +1,7 @@
using AsbCloudApp.Data.Trajectory;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudDb.Model.Trajectory;
@ -83,15 +84,15 @@ namespace AsbCloudInfrastructure.Repository
}
/// <inheritdoc/>
public async Task<IEnumerable<Tdto>> GetAsync(int idWell, CancellationToken token)
public async Task<IEnumerable<Tdto>> GetAsync(TrajectoryRequest request, CancellationToken token)
{
var well = wellService.GetOrDefault(idWell)
?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist");
var well = wellService.GetOrDefault(request.IdWell)
?? throw new ArgumentInvalidException(nameof(request.IdWell), "idWell doesn`t exist");
var offsetHours = well.Timezone.Hours;
var query = db.Set<TEntity>()
.AsNoTracking()
.Where(x => x.IdWell == idWell);
.Where(x => x.IdWell == well.Id);
var entities = await query
.OrderBy(e => e.WellboreDepth)
.ToArrayAsync(token);

View File

@ -1,7 +1,10 @@
using AsbCloudApp.Data.Trajectory;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudDb.Model.WITS;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
@ -10,7 +13,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository
{
internal class TrajectoryNnbRepository : ITrajectoryNnbRepository
public class TrajectoryNnbRepository : ITrajectoryNnbRepository
{
private readonly IAsbCloudDbContext db;
private readonly IWellService wellService;
@ -20,25 +23,38 @@ namespace AsbCloudInfrastructure.Repository
this.wellService = wellService;
}
public async Task<IEnumerable<TrajectoryGeoFactDto>> GetAsync(int idWell, CancellationToken token)
private IQueryable<Record7> BuildQuery(TrajectoryRequest request)
{
var well = await wellService.GetOrDefaultAsync(idWell,
token);
var well = db.Wells.SingleOrDefault(w => w.Id == request.IdWell);
if (well is null)
return Enumerable.Empty<TrajectoryGeoFactDto>();
throw new ArgumentInvalidException($"Скважина с Id: {request.IdWell} не найдена", nameof(request.IdWell));
var entities = await db.Record7
.AsNoTracking()
.Where(x => x.IdTelemetry == well.IdTelemetry)
.Where(coord => coord.Deptsvym != null && coord.Svyinc != null && coord.Svyazc != null)
.OrderBy(e => e.Deptsvym)
.ToArrayAsync(token);
var query = db.Record7.Where(r => r.IdTelemetry == well.IdTelemetry)
.Where(x => x.IdTelemetry == well.IdTelemetry);
if (request.GeDate.HasValue)
query = query.Where(r => r.DateTime >= request.GeDate.Value);
if (request.LeDate.HasValue)
query = query.Where(r => r.DateTime <= request.LeDate.Value);
return query.OrderBy(e => e.Deptsvym);
}
public async Task<IEnumerable<TrajectoryGeoFactDto>> GetAsync(TrajectoryRequest request, CancellationToken token)
{
var entities = (await BuildQuery(request)
.Where(coord => coord.Deptsvym.HasValue &&
coord.Svyinc.HasValue &&
coord.Svyazc.HasValue)
.AsNoTracking()
.ToArrayAsync(token));
var result = entities
.Select(coord => new TrajectoryGeoFactDto
{
IdWell = idWell,
IdWell = request.IdWell,
AzimuthMagnetic = coord.Svymtf,
VerticalDepth = coord.Deptsvyv,
WellboreDepth = coord.Deptsvym!.Value,

View File

@ -1,55 +0,0 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.AutogeneratedDailyReport;
using AsbCloudApp.Services;
using AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports;
public class AutoGeneratedDailyReportMakerService : IReportMakerService<AutoGeneratedDailyReportDto>
{
private readonly string templateName = "AutogeneratedDailyReportTemplate.xlsx";
private readonly IEnumerable<IExcelBlockWriter> blockWriters = new List<IExcelBlockWriter>()
{
new HeadExcelBlockWriter(),
new SubsystemExcelBlockWriter(),
new LimitingParameterExcelBlockWriter(),
new TimeBalanceExcelBlockWriter()
};
public async Task<Stream> MakeReportAsync(AutoGeneratedDailyReportDto report, CancellationToken cancellationToken)
{
using var excelTemplateStream = await Assembly
.GetExecutingAssembly()
.GetTemplateCopyStreamAsync(templateName, cancellationToken);
using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled);
AddToWorkbook(workbook, report);
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
private void AddToWorkbook(XLWorkbook workbook, AutoGeneratedDailyReportDto report)
{
const string sheetName = "Рапорт";
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetName)
?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}.");
foreach (var blockBuilder in blockWriters)
{
blockBuilder.Write(sheet, report);
}
}
}

View File

@ -1,262 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.AutogeneratedDailyReport;
using AsbCloudApp.Data.Subsystems;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudApp.Services.AutoGeneratedDailyReports;
using AsbCloudApp.Services.Subsystems;
using AsbCloudDb.Model;
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports;
public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService
{
private const string fileNameTemplate = "Суточный_отчёт_по_скважине_{0}_куст_{1}_от_{2}.xlsx";
private readonly IWellService wellService;
private readonly IWellOperationRepository wellOperationRepository;
private readonly ISubsystemOperationTimeService subsystemOperationTimeService;
private readonly ICrudRepository<SubsystemDto> subsystemRepository;
private readonly ILimitingParameterService limitingParameterService;
private readonly IReportMakerService<AutoGeneratedDailyReportDto> autoGeneratedDailyReportMakerService;
public AutoGeneratedDailyReportService(IWellService wellService,
IWellOperationRepository wellOperationRepository,
ISubsystemOperationTimeService subsystemOperationTimeService,
ICrudRepository<SubsystemDto> subsystemRepository,
ILimitingParameterService limitingParameterService,
IReportMakerService<AutoGeneratedDailyReportDto> autoGeneratedDailyReportMakerService)
{
this.wellOperationRepository = wellOperationRepository;
this.wellService = wellService;
this.subsystemOperationTimeService = subsystemOperationTimeService;
this.subsystemRepository = subsystemRepository;
this.limitingParameterService = limitingParameterService;
this.autoGeneratedDailyReportMakerService = autoGeneratedDailyReportMakerService;
}
public async Task<PaginationContainer<AutoGeneratedDailyReportInfoDto>> GetListAsync(int idWell,
FileReportRequest request,
CancellationToken cancellationToken)
{
var result = new PaginationContainer<AutoGeneratedDailyReportInfoDto>
{
Skip = request.Skip ?? 0,
Take = request.Take ?? 10,
Items = Enumerable.Empty<AutoGeneratedDailyReportInfoDto>()
};
var reports = new List<AutoGeneratedDailyReportInfoDto>();
var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken)
?? throw new ArgumentInvalidException(nameof(idWell), "Скважина не найдена");
if (!well.IdTelemetry.HasValue)
throw new ArgumentInvalidException(nameof(idWell), "Телеметрия для скважины отсутствует");
var datesRange = await GetDatesRangeAsync(idWell, cancellationToken);
if (datesRange is null)
return result;
if (request.GeDate.HasValue)
{
var startDate = new DateTime(request.GeDate.Value.Year, request.GeDate.Value.Month,
request.GeDate.Value.Day);
if(startDate.Date >= datesRange.From.Date)
datesRange.From = startDate;
}
if (request.LeDate.HasValue)
{
var finishDate = new DateTime(request.LeDate.Value.Year, request.LeDate.Value.Month,
request.LeDate.Value.Day);
if (finishDate.Date <= datesRange.To.Date)
datesRange.To = finishDate;
}
if (datesRange.From.AddDays(result.Skip) <= datesRange.To)
result.Count = (int)(Math.Ceiling((datesRange.To - DateTime.UnixEpoch).TotalDays) - Math.Floor((datesRange.From - DateTime.UnixEpoch).TotalDays));
for (int day = result.Skip; (day - result.Skip) < result.Take && (datesRange.From.AddDays(day)) <= datesRange.To; day++)
{
var reportDate = DateOnly.FromDateTime(datesRange.From.AddDays(day));
reports.Add(new AutoGeneratedDailyReportInfoDto
{
FileName = string.Format(fileNameTemplate, well.Caption, well.Cluster, reportDate),
ReportDate = reportDate,
FileSize = GetFileSize(reportDate, idWell),
});
}
result.Items = reports;
return result;
}
public async Task<(string fileName, Stream stream)> GenerateAsync(int idWell, DateOnly reportDate,
CancellationToken cancellationToken)
{
var startDate = new DateTime(reportDate.Year, reportDate.Month, reportDate.Day);
var finishDate = startDate.AddDays(1);
var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken)
?? throw new ArgumentInvalidException(nameof(idWell), "Скважина не найдена");
if (!well.IdTelemetry.HasValue)
throw new ArgumentInvalidException(nameof(idWell), "Телеметрия для скважины отсутствует");
var factOperations = await GetFactOperationsAsync(well.Id, startDate, finishDate,
cancellationToken);
var report = new AutoGeneratedDailyReportDto
{
FileName = string.Format(fileNameTemplate, well.Caption, well.Cluster, reportDate),
FileSize = GetFileSize(reportDate, idWell),
ReportDate = reportDate,
Head = CreateHeadBlock(well, factOperations),
Subsystems = (await CreateSubsystemBlockAsync(idWell, startDate, finishDate, cancellationToken)).ToArray(),
LimitingParameters = (await CreateLimitingParameterBlockAsync(idWell, startDate, finishDate, cancellationToken)).ToArray(),
TimeBalance = factOperations.GroupBy(w => w.CategoryName).Select(x => new TimeBalanceRecordDto
{
Name = x.Key ?? "Название операции отсутствует",
DurationHours = x.Sum(o => o.DurationHours)
}).ToArray(),
};
var stream = await autoGeneratedDailyReportMakerService.MakeReportAsync(report, cancellationToken);
return (report.FileName, stream);
}
public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken)
{
var factOperations = await GetFactOperationsAsync(idWell, null, null,
cancellationToken);
if (!factOperations.Any())
return null;
return new DatesRangeDto
{
From = factOperations.Min(o => o.DateStart).Date,
To = factOperations.Max(o => o.DateStart).Date
};
}
private HeadBlockDto CreateHeadBlock(WellDto well, IEnumerable<WellOperationDto> factOperations)
{
var customer = well.Companies.FirstOrDefault(company => company.IdCompanyType == 1);
var sortedFactOperations = factOperations.OrderBy(o => o.DateStart);
return new HeadBlockDto
{
Customer = customer?.Caption ?? string.Empty,
Deposit = well.Deposit ?? string.Empty,
Cluster = well.Cluster ?? string.Empty,
Well = well.Caption,
DepthFrom = sortedFactOperations.FirstOrDefault()?.DepthStart ?? 0.00,
DepthTo = sortedFactOperations.LastOrDefault()?.DepthEnd ?? 0.00
};
}
private async Task<IEnumerable<SubsystemRecordDto>> CreateSubsystemBlockAsync(int idWell, DateTime startDate,
DateTime finishDate,
CancellationToken cancellationToken)
{
var subsystems = await subsystemRepository.GetAllAsync(cancellationToken);
var subsystemStats = await GetSubsystemStatsAsync(idWell, startDate, finishDate,
cancellationToken);
return subsystems.Select(subsystem =>
{
var subsytemStat = subsystemStats?.FirstOrDefault(s => s.IdSubsystem == subsystem.Id);
return new SubsystemRecordDto
{
Name = subsystem.Name,
KUsage = subsytemStat?.KUsage ?? 0.00,
UsedTimeHours = subsytemStat?.UsedTimeHours ?? 0.00,
Depth = subsytemStat?.SumDepthInterval ?? 0.00,
};
});
}
private async Task<IEnumerable<LimitingParameterRecordDto>> CreateLimitingParameterBlockAsync(int idWell,
DateTime startDate, DateTime finishDate, CancellationToken cancellationToken)
{
var limitingParameterStats = (await GetLimitingParameterStatsAsync(idWell,
startDate, finishDate, cancellationToken)).ToArray();
var sumDepths = limitingParameterStats.Sum(x => x.Depth);
return limitingParameterStats.Select(l => new LimitingParameterRecordDto
{
NameFeedRegulator = l.NameFeedRegulator,
Hours = l.TotalMinutes,
PercentDepth = sumDepths != 0 ? l.Depth / sumDepths : 0,
Depth = l.Depth,
});
}
private async Task<IOrderedEnumerable<WellOperationDto>> GetFactOperationsAsync(int idWell, DateTime? startDate,
DateTime? finishDate, CancellationToken cancellationToken)
{
var request = new WellOperationRequest
{
IdWell = idWell,
OperationType = WellOperation.IdOperationTypeFact,
GeDate = startDate,
LtDate = finishDate,
SortFields = new[] { "DateStart asc" },
};
return (await wellOperationRepository.GetAsync(request, cancellationToken))
.OrderBy(w => w.DateStart);
}
private Task<IEnumerable<SubsystemStatDto>> GetSubsystemStatsAsync(int idWell, DateTime startDate,
DateTime finishDate, CancellationToken cancellationToken)
{
var request = new SubsystemOperationTimeRequest
{
IdWell = idWell,
GtDate = startDate,
LtDate = finishDate,
};
return subsystemOperationTimeService.GetStatAsync(request, cancellationToken);
}
private Task<IEnumerable<LimitingParameterDto>> GetLimitingParameterStatsAsync(int idWell,
DateTime startDate, DateTime finishDate, CancellationToken cancellationToken)
{
var request = new LimitingParameterRequest
{
IdWell = idWell,
GtDate = startDate,
LtDate = finishDate,
};
return limitingParameterService.GetStatAsync(request, cancellationToken);
}
private int GetFileSize(DateOnly reportDate, int idWell)
{
const int fileSizeTemplate = 10240;
long ticks = 1L * reportDate.Year * reportDate.Month * reportDate.Day * idWell;
int remainder = (int)(ticks % (fileSizeTemplate / 10));
return fileSizeTemplate + remainder;
}
}

View File

@ -1,34 +0,0 @@
using AsbCloudApp.Data.AutogeneratedDailyReport;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
public class HeadExcelBlockWriter : IExcelBlockWriter
{
private static readonly (int, int) customerCell = (2, 2);
private static readonly (int, int) depositCell = (4, 2);
private static readonly (int, int) clusterCell = (5, 2);
private static readonly (int, int) wellCell = (6, 2);
private const int dateRow = 9;
private const int dateFromColumn = 2;
private const int dateFromToColumn = 3;
private const int depthRow = 10;
private const int depthFromColumn = 2;
private const int depthToColumn = 3;
public void Write(IXLWorksheet sheet, AutoGeneratedDailyReportDto report)
{
sheet.Cell(customerCell.Item1, customerCell.Item2).Value = report.Head.Customer;
sheet.Cell(depositCell.Item1, depositCell.Item2).Value = report.Head.Deposit;
sheet.Cell(clusterCell.Item1, clusterCell.Item2).Value = report.Head.Cluster;
sheet.Cell(wellCell.Item1, wellCell.Item2).Value = report.Head.Well;
sheet.Cell(dateRow, dateFromColumn).Value = report.ReportDate;
sheet.Cell(dateRow, dateFromToColumn).Value = report.ReportDate.AddDays(1);
sheet.Cell(depthRow, depthFromColumn).Value = report.Head.DepthFrom;
sheet.Cell(depthRow, depthToColumn).Value = report.Head.DepthTo;
}
}

View File

@ -1,9 +0,0 @@
using AsbCloudApp.Data.AutogeneratedDailyReport;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
public interface IExcelBlockWriter
{
void Write(IXLWorksheet sheet, AutoGeneratedDailyReportDto report);
}

View File

@ -1,28 +0,0 @@
using System.Linq;
using AsbCloudApp.Data.AutogeneratedDailyReport;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
public class LimitingParameterExcelBlockWriter : IExcelBlockWriter
{
private const int rowHeaderBlock = 20;
private const int columnNameFeedRegulator = 1;
private const int columnDepth = 2;
private const int columnTotalHours = 3;
private const int columnPercentDepth = 4;
public void Write(IXLWorksheet sheet, AutoGeneratedDailyReportDto report)
{
var i = 1;
foreach (var limitingParameter in report.LimitingParameters)
{
var row = sheet.Row( i++ + rowHeaderBlock);
row.Cell(columnNameFeedRegulator).Value = limitingParameter.NameFeedRegulator;
row.Cell(columnDepth).Value = limitingParameter.Depth;
row.Cell(columnTotalHours).Value = limitingParameter.Hours;
row.Cell(columnPercentDepth).Value = limitingParameter.PercentDepth;
}
}
}

View File

@ -1,28 +0,0 @@
using System.Linq;
using AsbCloudApp.Data.AutogeneratedDailyReport;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
public class SubsystemExcelBlockWriter : IExcelBlockWriter
{
private const int rowHeaderBlock = 13;
private const int columnName = 1;
private const int columnKUsage = 2;
private const int columnDepth = 3;
private const int columnUsedTimeHours = 4;
public void Write(IXLWorksheet sheet, AutoGeneratedDailyReportDto report)
{
var i = 1;
foreach( var subsystem in report.Subsystems )
{
var row = sheet.Row(i++ + rowHeaderBlock);
row.Cell(columnName).Value = subsystem.Name;
row.Cell(columnKUsage).Value = subsystem.KUsage;
row.Cell(columnDepth).Value = subsystem.Depth;
row.Cell(columnUsedTimeHours).Value = subsystem.UsedTimeHours;
}
}
}

View File

@ -1,34 +0,0 @@
using System.Linq;
using AsbCloudApp.Data.AutogeneratedDailyReport;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
public class TimeBalanceExcelBlockWriter : IExcelBlockWriter
{
private const int rowHeaderBlock = 27;
private const int columnName = 1;
private const int columnDurationHours = 2;
public void Write(IXLWorksheet sheet, AutoGeneratedDailyReportDto report)
{
var i = 1;
foreach(var timeBalance in report.TimeBalance)
{
var row = sheet.Row(i++ + rowHeaderBlock);
row.Cell(columnName).Value = timeBalance.Name;
row.Cell(columnDurationHours).Value = timeBalance.DurationHours;
AddBorderToCell(row.Cell(columnName));
AddBorderToCell(row.Cell(columnDurationHours));
}
}
private static void AddBorderToCell(IXLCell cell)
{
cell.Style.Border.TopBorder = XLBorderStyleValues.Thin;
cell.Style.Border.BottomBorder = XLBorderStyleValues.Thin;
cell.Style.Border.LeftBorder = XLBorderStyleValues.Thin;
cell.Style.Border.RightBorder = XLBorderStyleValues.Thin;
}
}

View File

@ -1,13 +0,0 @@
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.DailyReport
{
abstract class BlockAbstract
{
public abstract CellAddress AddressBlockBegin { get; }
public abstract CellAddress AddressBlockEnd { get; }
public abstract void Draw(IXLWorksheet sheet);
}
}

View File

@ -1,174 +0,0 @@
using ClosedXML.Excel;
using System;
using System.Diagnostics.CodeAnalysis;
using System.Text;
namespace AsbCloudInfrastructure.Services.DailyReport
{
internal class CellAddress: IXLAddress
{
const int excelLettersCount = 'Z' - 'A' + 1;
public int RowNumber { get; set; }
public int ColumnNumber { get; set; }
public string ColumnLetter
{
get { return CalcColumnLetter(); }
}
public bool FixedColumn { get; set; }
public bool FixedRow { get; set; }
public string UniqueId => ToString(XLReferenceStyle.A1, true);
public IXLWorksheet? Worksheet { get; set; }
public CellAddress(IXLWorksheet? worksheet, int row, int colunm)
{
Worksheet = worksheet;
RowNumber = row;
ColumnNumber = colunm;
}
public static CellAddress operator + (CellAddress a, CellAddress b)
=> new CellAddress(a.Worksheet, a.RowNumber + b.RowNumber, a.ColumnNumber + b.ColumnNumber);
public static CellAddress operator +(CellAddress a, (int row, int column) b)
=> new CellAddress(a.Worksheet, a.RowNumber + b.row, a.ColumnNumber + b.column);
public static CellAddress operator - (CellAddress a, CellAddress b)
=> new CellAddress(a.Worksheet, a.RowNumber - b.RowNumber, a.ColumnNumber - b.ColumnNumber);
public static bool operator == (CellAddress a, CellAddress b)
=> a.RowNumber == b.RowNumber && a.ColumnNumber == b.ColumnNumber;
public static bool operator !=(CellAddress a, CellAddress b)
=> !(a == b);
private string CalcColumnLetter()
{
string letter = "";
var columnNumber = ColumnNumber;
while (columnNumber > 0)
{
int modulo = (columnNumber - 1) % excelLettersCount;
letter = Convert.ToChar('A' + modulo) + letter;
columnNumber = (columnNumber - modulo) / excelLettersCount;
}
return letter;
}
public CellAddress Copy()
=> new CellAddress(Worksheet, RowNumber, ColumnNumber)
{
FixedColumn = this.FixedColumn,
FixedRow = this.FixedRow,
};
public override string ToString()
=> ToString(XLReferenceStyle.A1);
public string ToString(XLReferenceStyle referenceStyle)
=> ToString(referenceStyle, false);
public string ToString(XLReferenceStyle referenceStyle, bool includeSheet)
{
if (referenceStyle == XLReferenceStyle.R1C1)
throw new NotImplementedException("R1C1 - style doesn't implemented");
var sb = new StringBuilder();
if (includeSheet && Worksheet is not null)
sb.Append('$')
.Append(Worksheet.Name)
.Append('.');
if (FixedColumn)
sb.Append('$');
sb.Append(ColumnLetter);
if (FixedRow)
sb.Append('$');
sb.Append(RowNumber);
return sb.ToString();
}
public string ToStringFixed()
=> ToStringFixed(XLReferenceStyle.A1);
public string ToStringFixed(XLReferenceStyle referenceStyle)
=> ToStringFixed(referenceStyle, false);
public string ToStringFixed(XLReferenceStyle referenceStyle, bool includeSheet)
{
if (referenceStyle == XLReferenceStyle.R1C1)
throw new NotImplementedException("R1C1 - style doesn't implemented");
var sb = new StringBuilder();
if (includeSheet && Worksheet is not null)
sb.Append('$')
.Append(Worksheet.Name)
.Append('.');
sb.Append('$');
sb.Append(ColumnLetter);
sb.Append('$');
sb.Append(RowNumber);
return sb.ToString();
}
public string ToStringRelative()
=> ToStringRelative(false);
public string ToStringRelative(bool includeSheet)
{
var sb = new StringBuilder();
if (includeSheet && Worksheet is not null)
sb.Append('$')
.Append(Worksheet.Name)
.Append('.');
sb.Append(ColumnLetter);
sb.Append(RowNumber);
return sb.ToString();
}
public bool Equals(IXLAddress? x, IXLAddress? y)
=> x?.ColumnNumber == y?.ColumnNumber &&
x?.RowNumber == y?.RowNumber &&
x?.FixedColumn == y?.FixedColumn &&
x?.FixedRow == y?.FixedRow &&
x?.Worksheet == y?.Worksheet;
public override int GetHashCode()
=> base.GetHashCode();
public int GetHashCode([DisallowNull] IXLAddress obj)
=> obj.GetHashCode();
public bool Equals(IXLAddress? other)
=> Equals(this, other);
public override bool Equals(object? obj)
{
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj is null)
{
return false;
}
if (obj is CellAddress address)
return this == address;
return false;
}
}
}

View File

@ -1,118 +0,0 @@
using AsbCloudApp.Data.DailyReport;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
{
class BhaBlock : BlockAbstract
{
private readonly BhaDto blockDto;
public CellAddress AddressBhaDescription { get; }
public CellAddress AddressOperationTitle { get; }
public CellAddress AddressDurationTitle { get; }
public CellAddress AddressTotalTitle { get; }
public CellAddress[] AddressOperationData { get; }
public CellAddress[] AddressDurationDataStart { get; }
public CellAddress[] AddressDurationDataFinish { get; }
public CellAddress[] AddressTotaData { get; }
public override CellAddress AddressBlockBegin { get; }
public override CellAddress AddressBlockEnd { get; }
public BhaBlock(CellAddress addressBlockBegin, BhaDto blockDto)
{
this.blockDto = blockDto;
AddressBlockBegin = addressBlockBegin.Copy();
AddressBhaDescription = addressBlockBegin + (1,0);
AddressOperationTitle = addressBlockBegin + (3, 0);
AddressDurationTitle = addressBlockBegin + (3, 5);
AddressTotalTitle = addressBlockBegin + (3, 7);
AddressOperationData = new CellAddress[5];
AddressOperationData[0] = addressBlockBegin + (4, 0);
AddressOperationData[1] = addressBlockBegin + (5, 0);
AddressOperationData[2] = addressBlockBegin + (6, 0);
AddressOperationData[3] = addressBlockBegin + (7, 0);
AddressOperationData[4] = addressBlockBegin + (8, 0);
AddressDurationDataStart = new CellAddress[5];
AddressDurationDataStart[0] = addressBlockBegin + (4, 5);
AddressDurationDataStart[1] = addressBlockBegin + (5, 5);
AddressDurationDataStart[2] = addressBlockBegin + (6, 5);
AddressDurationDataStart[3] = addressBlockBegin + (7, 5);
AddressDurationDataStart[4] = addressBlockBegin + (8, 5);
AddressDurationDataFinish = new CellAddress[5];
AddressDurationDataFinish[0] = addressBlockBegin + (4, 6);
AddressDurationDataFinish[1] = addressBlockBegin + (5, 6);
AddressDurationDataFinish[2] = addressBlockBegin + (6, 6);
AddressDurationDataFinish[3] = addressBlockBegin + (7, 6);
AddressDurationDataFinish[4] = addressBlockBegin + (8, 6);
AddressTotaData = new CellAddress[5];
AddressTotaData[0] = addressBlockBegin + (4, 7);
AddressTotaData[1] = addressBlockBegin + (5, 7);
AddressTotaData[2] = addressBlockBegin + (6, 7);
AddressTotaData[3] = addressBlockBegin + (7, 7);
AddressTotaData[4] = addressBlockBegin + (8, 7);
AddressBlockEnd = AddressTotaData[4];
}
private string FormulaBhaBlock(CellAddress beginTime, CellAddress endTime)
{
return string.Format("IF({0}>0,({0}-{1})*24, \"\")", endTime.ToString(), beginTime.ToString());
}
public override void Draw(IXLWorksheet sheet)
{
sheet._Range(AddressBhaDescription, AddressBhaDescription + (0, 7))
._SetValue($"{blockDto.BHADescription}");
sheet._Range(AddressOperationTitle, AddressOperationTitle + (0, 4))
._SetValue("Выполняемые операции в отчетный период, комментарии:");
sheet._Range(AddressDurationTitle, AddressDurationTitle + (0, 1))
._SetValue("Продолжительность, ч. ");
sheet.Cell(AddressTotalTitle)
._SetValue("Итого");
sheet._Range(AddressOperationData[0], AddressOperationData[0] + (0, 4))
._SetValue("Бурение с наращиваниями в инт. 2195-2763м.");
sheet.Cell(AddressDurationDataStart[0])
._SetValue($"{blockDto.ExtensionDrillingOneBegin}");
sheet.Cell(AddressDurationDataFinish[0])
._SetValue($"{blockDto.ExtensionDrillingOneFinish}");
sheet.Cell(AddressTotaData[0])
.SetFormulaA1($"{FormulaBhaBlock(AddressDurationDataStart[0], AddressDurationDataFinish[0])}").Style.SetAllBorders();
sheet._Range(AddressOperationData[1], AddressOperationData[1] + (0, 4))
._SetValue("Промывка.");
sheet.Cell(AddressDurationDataStart[1])
._SetValue($"{blockDto.SluiceBegin}");
sheet.Cell(AddressDurationDataFinish[1])
._SetValue($"{blockDto.SluiceFinish}");
sheet.Cell(AddressTotaData[1])
.SetFormulaA1($"{FormulaBhaBlock(AddressDurationDataStart[1], AddressDurationDataFinish[1])}").Style.SetAllBorders();
sheet._Range(AddressOperationData[2], AddressOperationData[2] + (0, 4))
._SetValue("Подъем КНБК в инт. 2763-2442м.");
sheet.Cell(AddressDurationDataStart[2])
._SetValue($"{blockDto.ClimbBegin}");
sheet.Cell(AddressDurationDataFinish[2])
._SetValue($"{blockDto.ClimbFinish}");
sheet.Cell(AddressTotaData[2])
.SetFormulaA1($"{FormulaBhaBlock(AddressDurationDataStart[2], AddressDurationDataFinish[2])}").Style.SetAllBorders();
sheet._Range(AddressOperationData[3], AddressOperationData[3] + (0, 4))
._SetValue("Спуск КНБК в инт. 2442-2763м.");
sheet.Cell(AddressDurationDataStart[3])
._SetValue($"{blockDto.DescentBegin}");
sheet.Cell(AddressDurationDataFinish[3])
._SetValue($"{blockDto.DescentFinish}");
sheet.Cell(AddressTotaData[3])
.SetFormulaA1($"{FormulaBhaBlock(AddressDurationDataStart[3], AddressDurationDataFinish[3])}").Style.SetAllBorders();
sheet._Range(AddressOperationData[4], AddressOperationData[4] + (0, 4))
._SetValue("Бурение с наращиваниями в инт. 2763-2850м.");
sheet.Cell(AddressDurationDataStart[4])
._SetValue($"{blockDto.ExtensionDrillingTwoBegin}");
sheet.Cell(AddressDurationDataFinish[4])
._SetValue($"{blockDto.ExtensionDrillingTwoFinish}");
sheet.Cell(AddressTotaData[4])
.SetFormulaA1($"{FormulaBhaBlock(AddressDurationDataStart[4], AddressDurationDataFinish[4])}").Style.SetAllBorders();
}
}
}

View File

@ -1,119 +0,0 @@
using AsbCloudApp.Data.DailyReport;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
{
internal class DimensionlessBlock : BlockAbstract
{
private readonly NoDrillingDto blockDto;
public SaubBlock SaubBlock { get; set; } = null!;
public CellAddress AddressDimensionTitle { get; }
public CellAddress AddressPreparationTitle { get; }
public CellAddress AddressExtensionTitle { get; }
public CellAddress AddressPreparationDescription { get; }
public CellAddress AddressExtensionDescription { get; }
public CellAddress[] AddressPreparationHead { get; }
public CellAddress[] AddressPreparationValue { get; }
public CellAddress[] AddressExtensionHead { get; }
public CellAddress[] AddressExtensionValue { get; }
public CellAddress AddressBlockFormula { get; } = null!;
public override CellAddress AddressBlockBegin { get; }
public override CellAddress AddressBlockEnd { get; }
public DimensionlessBlock(CellAddress addressBlockBegin, NoDrillingDto blockDto)
{
AddressBlockBegin = addressBlockBegin.Copy();
this.blockDto = blockDto;
AddressDimensionTitle = addressBlockBegin + (2, 3);
AddressPreparationTitle = addressBlockBegin + (3, 1);
AddressExtensionTitle = addressBlockBegin + (3, 4);
AddressPreparationHead = new CellAddress[4];
AddressPreparationHead[0] = addressBlockBegin + (4, 1);
AddressPreparationHead[1] = addressBlockBegin + (5, 1);
AddressPreparationHead[2] = addressBlockBegin + (6, 1);
AddressPreparationHead[3] = addressBlockBegin + (7, 1);
AddressPreparationValue = new CellAddress[4];
AddressPreparationValue[0] = addressBlockBegin + (4, 3);
AddressPreparationValue[1] = addressBlockBegin + (5, 3);
AddressPreparationValue[2] = addressBlockBegin + (6, 3);
AddressPreparationValue[3] = addressBlockBegin + (7, 3);
AddressPreparationDescription = addressBlockBegin + (8, 1);
AddressExtensionHead = new CellAddress[4];
AddressExtensionHead[0] = addressBlockBegin + (4, 4);
AddressExtensionHead[1] = addressBlockBegin + (5, 4);
AddressExtensionHead[2] = addressBlockBegin + (6, 4);
AddressExtensionHead[3] = addressBlockBegin + (7, 4);
AddressExtensionValue = new CellAddress[4];
AddressExtensionValue[0] = addressBlockBegin + (4, 6);
AddressExtensionValue[1] = addressBlockBegin + (5, 6);
AddressExtensionValue[2] = addressBlockBegin + (6, 6);
AddressExtensionValue[3] = addressBlockBegin + (7, 6);
AddressExtensionDescription = addressBlockBegin + (8, 4);
AddressBlockEnd = addressBlockBegin + (9,0);
}
private string FormulaBlockPlan(CellAddress cellTarget)
{
return $"={cellTarget}/60*{SaubBlock.AddressExtensionsCountValue}";
}
private string FormulaBlockExcess(CellAddress cellFact, CellAddress cellPlan)
{
return string.Format("={0}-{1}", cellFact.ToString(), cellPlan.ToString());
}
public override void Draw(IXLWorksheet sheet)
{
sheet.Range(AddressDimensionTitle.RowNumber, AddressDimensionTitle.ColumnNumber,
AddressDimensionTitle.RowNumber, AddressDimensionTitle.ColumnNumber + 1)
.Merge()
.Style.Alignment.SetWrapText(true);
sheet.Cell(AddressDimensionTitle.RowNumber, AddressDimensionTitle.ColumnNumber)._ValueNoBorder("БЕЗМЕТРАЖНЫЕ РАБОТЫ",true);
sheet._Range(AddressPreparationTitle, AddressPreparationTitle + (0, 2))
._SetValue("Подготовка ствола скв. к наращиванию");
sheet._Range(AddressExtensionTitle, AddressExtensionTitle + (0, 2))
._SetValue("Наращивание");
sheet._Range(AddressPreparationHead[0], AddressPreparationHead[0] + (0, 1))
._SetValue("Норматив на одну операцию, (мин):");
sheet.Cell(AddressPreparationValue[0])
._SetValue($"{blockDto.StandardTimeBarrelPreparation}");
sheet._Range(AddressPreparationHead[1], AddressPreparationHead[1] + (0, 1))
._SetValue("Проработка при бур, план (ч):");
sheet.Cell(AddressPreparationValue[1])
.SetFormulaA1($"{FormulaBlockPlan(AddressPreparationValue[0])}").Style.SetAllBorders();
sheet._Range(AddressPreparationHead[2], AddressPreparationHead[2] + (0, 1))
._SetValue("Проработка при бур, факт (ч):");
sheet.Cell(AddressPreparationValue[2])
._SetValue($"{blockDto.ActualTimeBarrelPreparation}");
sheet._Range(AddressPreparationHead[3], AddressPreparationHead[3] + (0, 1))
._SetValue("Превышение плановых норм, (ч):");
sheet.Cell(AddressPreparationValue[3])
.SetFormulaA1($"{FormulaBlockExcess(AddressPreparationValue[2], AddressPreparationValue[1])}").Style.SetAllBorders();
sheet._Range(AddressExtensionHead[0], AddressExtensionHead[0] + (0, 1))
._SetValue("Норматив на одну операцию, (мин):");
sheet.Cell(AddressExtensionValue[0])
._SetValue($"{blockDto.StandardTimeExtension}");
sheet._Range(AddressExtensionHead[1], AddressExtensionHead[1] + (0, 1))
._SetValue("Наращивание, план (ч):");
sheet.Cell(AddressExtensionValue[1])
.SetFormulaA1($"{FormulaBlockPlan(AddressExtensionValue[0])}").Style.SetAllBorders();
sheet._Range(AddressExtensionHead[2], AddressExtensionHead[2] + (0, 1))
._SetValue("Наращивание, факт (ч):");
sheet.Cell(AddressExtensionValue[2])
._SetValue($"{blockDto.ActualTimeExtension}");
sheet._Range(AddressExtensionHead[3], AddressExtensionHead[3] + (0, 1))
._SetValue("Превышение плановых норм, (ч):");
sheet.Cell(AddressExtensionValue[3])
.SetFormulaA1($"{FormulaBlockExcess(AddressExtensionValue[2], AddressExtensionValue[1])}").Style.SetAllBorders();
sheet._Range(AddressPreparationDescription, AddressPreparationDescription + (1, 2))
._SetValue("Подготовка ствола скв. к наращиванию");
sheet._Range(AddressExtensionDescription, AddressExtensionDescription + (1, 2))
._SetValue("Наращивание");
}
}
}

View File

@ -1,181 +0,0 @@
using AsbCloudApp.Data.DailyReport;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
{
class HeadBlock : BlockAbstract
{
private readonly HeadDto blockDto;
public CellAddress AddressTitle { get; }
public CellAddress AddressCustomer { get; }
public CellAddress AddressDriller { get; }
public CellAddress AddressPeriod { get; }
public CellAddress AddressSlaughter { get; }
public CellAddress AddressTrajectoryTableTitle { get; }
public CellAddress AddressDrillerOneTitle { get; }
public CellAddress AddressDrillerOne { get; }
public CellAddress AddressDrillerTwoTitle { get; }
public CellAddress AddressDrillerTwo { get; }
public CellAddress AddressWorkSaubTitle { get; }
public CellAddress AddressWatchTitle { get; }
public CellAddress AddressMetreTitle { get; }
public CellAddress[] AddressWorkSaubData { get; }
public CellAddress[] AddressWatchData { get; }
public CellAddress[] AddressMetreData { get; }
public CellAddress[] AddressPeriodTableHeadArray { get; }
public CellAddress[] AddressPeriodTableDataArray { get; }
public CellAddress[] AddressTrajectoryTableHeadArray { get; }
public CellAddress[] AddressTrajectoryTableDataArray { get; }
public override CellAddress AddressBlockBegin { get; }
public override CellAddress AddressBlockEnd { get; }
public HeadBlock(CellAddress addressBlockBegin, HeadDto blockDto)
{
AddressBlockBegin = addressBlockBegin.Copy();
this.blockDto = blockDto;
AddressTitle = addressBlockBegin + (0, 0);
AddressCustomer = addressBlockBegin + (1, 0);
AddressDriller = addressBlockBegin + (2, 0);
AddressPeriod = addressBlockBegin + (4, 0);
AddressSlaughter = addressBlockBegin + (4, 4);
AddressPeriodTableHeadArray = new CellAddress[4];
AddressPeriodTableHeadArray[0]= addressBlockBegin + (5, 0);
AddressPeriodTableHeadArray[1] = addressBlockBegin + (5, 2);
AddressPeriodTableHeadArray[2] = addressBlockBegin + (5, 4);
AddressPeriodTableHeadArray[3] = addressBlockBegin + (5, 6);
AddressPeriodTableDataArray = new CellAddress[4];
AddressPeriodTableDataArray[0] = addressBlockBegin + (6, 0);
AddressPeriodTableDataArray[1] = addressBlockBegin + (6, 2);
AddressPeriodTableDataArray[2] = addressBlockBegin + (6, 4);
AddressPeriodTableDataArray[3] = addressBlockBegin + (6, 6);
AddressTrajectoryTableTitle = addressBlockBegin + (8,0);
AddressTrajectoryTableHeadArray = new CellAddress[4];
AddressTrajectoryTableHeadArray[0] = addressBlockBegin + (9, 0);
AddressTrajectoryTableHeadArray[1] = addressBlockBegin + (9, 2);
AddressTrajectoryTableHeadArray[2] = addressBlockBegin + (9, 4);
AddressTrajectoryTableHeadArray[3] = addressBlockBegin + (9, 6);
AddressTrajectoryTableDataArray = new CellAddress[4];
AddressTrajectoryTableDataArray[0] = addressBlockBegin + (10, 0);
AddressTrajectoryTableDataArray[1] = addressBlockBegin + (10, 2);
AddressTrajectoryTableDataArray[2] = addressBlockBegin + (10, 4);
AddressTrajectoryTableDataArray[3] = addressBlockBegin + (10, 6);
AddressDrillerOneTitle = addressBlockBegin + (12, 0);
AddressDrillerOne = addressBlockBegin + (12, 2);
AddressDrillerTwoTitle = addressBlockBegin + (13, 0);
AddressDrillerTwo = addressBlockBegin + (13, 2);
AddressWorkSaubTitle = addressBlockBegin + (15, 0);
AddressWatchTitle = addressBlockBegin + (15, 3);
AddressMetreTitle = addressBlockBegin + (15, 4);
AddressWorkSaubData = new CellAddress[4];
AddressWorkSaubData[0] = addressBlockBegin + (16, 0);
AddressWorkSaubData[1] = addressBlockBegin + (17, 0);
AddressWorkSaubData[2] = addressBlockBegin + (18, 0);
AddressWorkSaubData[3] = addressBlockBegin + (19, 0);
AddressWatchData = new CellAddress[4];
AddressWatchData[0] = addressBlockBegin + (16, 3);
AddressWatchData[1] = addressBlockBegin + (17, 3);
AddressWatchData[2] = addressBlockBegin + (18, 3);
AddressWatchData[3] = addressBlockBegin + (19, 3);
AddressMetreData = new CellAddress[4];
AddressMetreData[0] = addressBlockBegin + (16, 4);
AddressMetreData[1] = addressBlockBegin + (17, 4);
AddressMetreData[2] = addressBlockBegin + (18, 4);
AddressBlockEnd = AddressWatchData[3]+(0,1);
}
public override void Draw(IXLWorksheet sheet)
{
sheet._Range(AddressTitle, AddressTitle + (0, 7))
._SetValue($"Суточная сводка бурения скважины: {blockDto.WellName}, куст: {blockDto.ClusterName}")
.Style.SetH1();
sheet._Range(AddressCustomer, AddressCustomer + (0, 7))
._SetValue($"Заказчик: {blockDto.Customer}")
.Style.SetH1();
sheet._Range(AddressDriller, AddressDriller + (0, 7))
._SetValue($"Подрядчик: {blockDto.Contractor}")
.Style.SetH1();
sheet._Range(AddressPeriod, AddressPeriod + (0, 3))
._SetValue("Отчетный период");
sheet._Range(AddressSlaughter, AddressSlaughter + (0, 3))
._SetValue("Забой за отчетный период, м");
sheet._Range(AddressPeriodTableHeadArray[0], AddressPeriodTableHeadArray[0] + (0, 1))
._SetValue("От (дата, время)");
sheet._Range(AddressPeriodTableHeadArray[1], AddressPeriodTableHeadArray[1] + (0, 1))
._SetValue("До (дата, время)");
sheet._Range(AddressPeriodTableHeadArray[2], AddressPeriodTableHeadArray[2] + (0, 1))
._SetValue("От");
sheet._Range(AddressPeriodTableHeadArray[3], AddressPeriodTableHeadArray[3] + (0, 1))
._SetValue("До");
sheet._Range(AddressPeriodTableDataArray[0], AddressPeriodTableDataArray[0] + (0, 1))
._SetValue($"{blockDto.ReportDate}");
sheet._Range(AddressPeriodTableDataArray[1], AddressPeriodTableDataArray[1] + (0, 1))._SetValue("");
sheet.Cell(AddressPeriodTableDataArray[1])
.SetFormulaA1(string.Format("{0}-1", AddressPeriodTableDataArray[0].ToString()))
.Style.DateFormat.Format= "DD.MM.YYYY HH:MM:SS";
sheet._Range(AddressPeriodTableDataArray[2], AddressPeriodTableDataArray[2] + (0, 1))
._SetValue($"{blockDto.WellDepthIntervalStartDate}");
sheet._Range(AddressPeriodTableDataArray[3], AddressPeriodTableDataArray[3] + (0, 1))
._SetValue($"{blockDto.WellDepthIntervalFinishDate}");
sheet._Range(AddressTrajectoryTableTitle, AddressTrajectoryTableTitle + (0, 7))
._SetValue("Данные по траектории скважины на конец суток");
sheet._Range(AddressTrajectoryTableHeadArray[0], AddressTrajectoryTableHeadArray[0] + (0, 1))
._SetValue("Глубина по стволу");
sheet._Range(AddressTrajectoryTableHeadArray[1], AddressTrajectoryTableHeadArray[1] + (0, 1))
._SetValue("Глубина по вертикали");
sheet._Range(AddressTrajectoryTableHeadArray[2], AddressTrajectoryTableHeadArray[2] + (0, 1))
._SetValue("Зенитный угол");
sheet._Range(AddressTrajectoryTableHeadArray[3], AddressTrajectoryTableHeadArray[3] + (0, 1))
._SetValue("Азимут");
sheet._Range(AddressTrajectoryTableDataArray[0], AddressTrajectoryTableDataArray[0] + (0, 1))
._SetValue($"{blockDto.BottomholeDepth}");
sheet._Range(AddressTrajectoryTableDataArray[1], AddressTrajectoryTableDataArray[1] + (0, 1))
._SetValue($"{blockDto.VerticalDepth}");
sheet._Range(AddressTrajectoryTableDataArray[2], AddressTrajectoryTableDataArray[2] + (0, 1))
._SetValue($"{blockDto.ZenithAngle}");
sheet._Range(AddressTrajectoryTableDataArray[3], AddressTrajectoryTableDataArray[3] + (0, 1))
._SetValue($"{blockDto.AzimuthAngle}");
sheet._Range(AddressDrillerOneTitle, AddressDrillerOneTitle + (0, 1))
._SetValue("Бурильщик 1 смена");
sheet._Range(AddressDrillerOne, AddressDrillerOne + (0, 1))
._SetValue($"{blockDto.FirstDriller}");
sheet._Range(AddressDrillerTwoTitle, AddressDrillerTwoTitle + (0, 1))
._SetValue("Бурильщик 2 смена");
sheet._Range(AddressDrillerTwo, AddressDrillerTwo + (0, 1))
._SetValue($"{blockDto.SecondDriller}");
sheet._Range(AddressWorkSaubTitle, AddressWorkSaubTitle + (0, 2))
._SetValue("Работа модулей САУБ:");
sheet.Cell(AddressWatchTitle)
._SetValue("Часов:");
sheet.Cell(AddressMetreTitle)
._SetValue("Метров:");
sheet._Range(AddressWorkSaubData[0], AddressWorkSaubData[0] + (0, 2))
._SetValue("АПД (автоматическая подача долота), ч/м:");
sheet.Cell(AddressWatchData[0])
._SetValue($"{blockDto.WorkTimeSAUB}");
sheet.Cell(AddressMetreData[0])
._SetValue($"{blockDto.PenetrationSAUB}");
sheet._Range(AddressWorkSaubData[1], AddressWorkSaubData[1] + (0, 2))
._SetValue("Спин Мастер (осцилляция),ч/м:");
sheet.Cell(AddressWatchData[1])
._SetValue($"{blockDto.WorkTimeSpinMaster}");
sheet.Cell(AddressMetreData[1])
._SetValue($"{blockDto.PenetrationSpinMaster}");
sheet._Range(AddressWorkSaubData[2], AddressWorkSaubData[2] + (0, 2))
._SetValue("Торк Мастер (демпфирование), ч/:");
sheet.Cell(AddressWatchData[2])
._SetValue($"{blockDto.WorkTimeTorkMaster}");
sheet.Cell(AddressMetreData[2])
._SetValue($"{blockDto.PenetrationTorkMaster}");
sheet._Range(AddressWorkSaubData[3], AddressWorkSaubData[3] + (0, 2))
._SetValue("МСЕ, колличество запусков, раз:");
sheet._Range(AddressWatchData[3], AddressWatchData[3] + (0, 1))
._SetValue($"{blockDto.CountLaunchesMSE}");
}
}
}

View File

@ -1,230 +0,0 @@
using AsbCloudApp.Data.DailyReport;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
{
internal class SaubBlock : BlockAbstract
{
private readonly SaubDto blockDto;
private readonly HeadBlock headBlock;
public CellAddress AddressRotorDrilling { get; }
public CellAddress AddressSlideDrilling { get; }
public CellAddress AddressDrillingTableTitle { get; }
public CellAddress[] AddressDrillingTableHead { get; }
public CellAddress[] AddressDrillingTableData { get; }
public CellAddress AddressSlideTableTitle { get; }
public CellAddress[] AddressSlideTableHead { get; }
public CellAddress[] AddressSlideTableData { get; }
public CellAddress AddressTotalTableMechanicalSpeed { get; }
public CellAddress AddressTotalTableTitle { get; }
public CellAddress[] AddressTotalTableHead { get; }
public CellAddress[] AddressTotalTableData { get; }
public CellAddress IncreaseSpeedSection { get; }
public CellAddress IncreaseSpeedDay { get; }
public CellAddress ReductionTimeDrilling { get; }
public CellAddress RotorSlidePercent { get; }
public CellAddress MspSection { get; }
public CellAddress SectionDrillingTimeTotal { get; }
public CellAddress SectionPenetrationTotal { get; }
public CellAddress AddressExtensionsCount { get; }
public CellAddress DeviationFromTVD { get; }
public CellAddress DeclinesReasonsROP { get; }
public CellAddress IncreaseSpeedSectionValue { get; }
public CellAddress IncreaseSpeedDayValue { get; }
public CellAddress ReductionTimeDrillingValue { get; }
public CellAddress RotorSlidePercentValue { get; }
public CellAddress MspSectionValue { get; }
public CellAddress SectionDrillingTimeTotalValue { get; }
public CellAddress SectionPenetrationTotalValue { get; }
public CellAddress AddressExtensionsCountValue { get; }
public CellAddress DeviationFromTVDValue { get; }
public override CellAddress AddressBlockBegin { get; }
public override CellAddress AddressBlockEnd { get; }
public SaubBlock(CellAddress addressBlockBegin, SaubDto blockDto, HeadBlock headBlock)
{
this.headBlock = headBlock;
AddressBlockBegin = addressBlockBegin.Copy();
this.blockDto = blockDto;
AddressRotorDrilling = addressBlockBegin + (1, 0);
AddressSlideDrilling = addressBlockBegin + (2, 0);
AddressDrillingTableTitle = addressBlockBegin + (4, 0);
AddressDrillingTableHead = new CellAddress[4];
AddressDrillingTableHead[0] = addressBlockBegin + (5, 0);
AddressDrillingTableHead[1] = addressBlockBegin + (5, 2);
AddressDrillingTableHead[2] = addressBlockBegin + (5, 4);
AddressDrillingTableHead[3] = addressBlockBegin + (5, 6);
AddressDrillingTableData = new CellAddress[4];
AddressDrillingTableData[0] = addressBlockBegin + (6, 0);
AddressDrillingTableData[1] = addressBlockBegin + (6, 2);
AddressDrillingTableData[2] = addressBlockBegin + (6, 4);
AddressDrillingTableData[3] = addressBlockBegin + (6, 6);
AddressSlideTableTitle = addressBlockBegin + (8, 0);
AddressSlideTableHead = new CellAddress[4];
AddressSlideTableHead[0] = addressBlockBegin + (9, 0);
AddressSlideTableHead[1] = addressBlockBegin + (9, 2);
AddressSlideTableHead[2] = addressBlockBegin + (9, 4);
AddressSlideTableHead[3] = addressBlockBegin + (9, 6);
AddressSlideTableData = new CellAddress[4];
AddressSlideTableData[0] = addressBlockBegin + (10, 0);
AddressSlideTableData[1] = addressBlockBegin + (10, 2);
AddressSlideTableData[2] = addressBlockBegin + (10, 4);
AddressSlideTableData[3] = addressBlockBegin + (10, 6);
AddressTotalTableTitle = addressBlockBegin + (12, 0);
AddressTotalTableMechanicalSpeed = addressBlockBegin + (12, 6);
AddressTotalTableHead = new CellAddress[4];
AddressTotalTableHead[0] = addressBlockBegin + (13, 0);
AddressTotalTableHead[1] = addressBlockBegin + (13, 2);
AddressTotalTableHead[2] = addressBlockBegin + (13, 4);
AddressTotalTableData = new CellAddress[4];
AddressTotalTableData[0] = addressBlockBegin + (14, 0);
AddressTotalTableData[1] = addressBlockBegin + (14, 2);
AddressTotalTableData[2] = addressBlockBegin + (14, 4);
AddressTotalTableData[3] = addressBlockBegin + (14, 6);
IncreaseSpeedSection = addressBlockBegin + (16, 0);
IncreaseSpeedSectionValue = addressBlockBegin + (16, 4);
IncreaseSpeedDay = addressBlockBegin + (17, 0);
IncreaseSpeedDayValue = addressBlockBegin + (17, 4);
ReductionTimeDrilling = addressBlockBegin + (18, 0);
ReductionTimeDrillingValue = addressBlockBegin + (18, 4);
RotorSlidePercent = addressBlockBegin + (19, 0);
RotorSlidePercentValue = addressBlockBegin + (19, 4);
MspSection = addressBlockBegin + (20, 0);
MspSectionValue = addressBlockBegin + (20, 4);
SectionDrillingTimeTotal = addressBlockBegin + (21, 0);
SectionDrillingTimeTotalValue = addressBlockBegin + (21, 4);
SectionPenetrationTotal = addressBlockBegin + (22, 0);
SectionPenetrationTotalValue = addressBlockBegin + (22, 4);
AddressExtensionsCount = addressBlockBegin + (23, 0);
AddressExtensionsCountValue = addressBlockBegin + (23, 4);
DeviationFromTVD = addressBlockBegin + (24, 0);
DeviationFromTVDValue = addressBlockBegin + (24, 4);
DeclinesReasonsROP = addressBlockBegin + (25, 0);
AddressBlockEnd = DeclinesReasonsROP + (1,7) ;
}
private string FormulaMechanicalSpeed(CellAddress cellSinking, CellAddress cellWatch )
{
return string.Format("=IF({0}>0,{1}/{2},0)", cellWatch.ToString(), cellSinking.ToString(), cellWatch.ToString());
}
private string FormulaSinking(CellAddress sinkingDrilling, CellAddress sinkingSlide, CellAddress slaughterEnd, CellAddress slaughterBegin)
{
return string.Format("=IF(({0}+{1})<>({2}-{3}),\"ОШИБКА\",({0}+{1}))", sinkingSlide.ToString(), sinkingDrilling.ToString(),
slaughterEnd.ToString(), slaughterBegin.ToString());
}
private string FormulaWatch(CellAddress cellSinkingDrill, CellAddress cellSinkingSlide)
{
return string.Format("={0}+{1}",
cellSinkingDrill.ToString(), cellSinkingSlide.ToString());
}
public override void Draw(IXLWorksheet sheet)
{
sheet._Range(AddressRotorDrilling, AddressRotorDrilling + (0, 7))
._SetValue($"Бурение в роторе : {blockDto.RotorDrillingModes}");
sheet._Range(AddressSlideDrilling, AddressSlideDrilling + (0, 7))
._SetValue($"Бурение в слайде : {blockDto.SlideDrillingModes}");
sheet._Range(AddressDrillingTableTitle, AddressDrillingTableTitle + (0, 7))
._SetValue("Бурение в роторе(за отчетный период) с использование САУБ - 1");
sheet._Range(AddressDrillingTableHead[0], AddressDrillingTableHead[0] + (0, 1))
._SetValue("Проходка");
sheet._Range(AddressDrillingTableHead[1], AddressDrillingTableHead[1] + (0, 1))
._SetValue("Часы бурения");
sheet._Range(AddressDrillingTableHead[2], AddressDrillingTableHead[2] + (0, 1))
._SetValue("Мех. скорость");
sheet._Range(AddressDrillingTableHead[3], AddressDrillingTableHead[3] + (0, 1))
._SetValue("Среднее диф. Давление");
sheet._Range(AddressDrillingTableData[0], AddressDrillingTableData[0] + (0, 1))
._SetValue($"{blockDto.PenetrationInRotor}");
sheet._Range(AddressDrillingTableData[1], AddressDrillingTableData[1] + (0, 1))
._SetValue($"{blockDto.NumberDrillingHours}");
sheet._Range(AddressDrillingTableData[2], AddressDrillingTableData[2] + (0, 1))._SetValue("");
sheet.Cell(AddressDrillingTableData[2])
.SetFormulaA1(FormulaMechanicalSpeed(AddressDrillingTableData[0], AddressDrillingTableData[1])).Style.SetAllBorders();
sheet._Range(AddressDrillingTableData[3], AddressDrillingTableData[3] + (0, 1))
._SetValue($"{blockDto.AVGDiffDropRotor}");
sheet._Range(AddressSlideTableTitle, AddressSlideTableTitle + (0, 7))
._SetValue("Бурение в слайде (за отчетный период) с использование САУБ-1");
sheet._Range(AddressSlideTableHead[0], AddressSlideTableHead[0] + (0, 1))
._SetValue("Проходка");
sheet._Range(AddressSlideTableHead[1], AddressSlideTableHead[1] + (0, 1))
._SetValue("Часы бурения");
sheet._Range(AddressSlideTableHead[2], AddressSlideTableHead[2] + (0, 1))
._SetValue("Мех. скорость");
sheet._Range(AddressSlideTableHead[3], AddressSlideTableHead[3] + (0, 1))
._SetValue("Среднее диф. Давление");
sheet._Range(AddressSlideTableData[0], AddressSlideTableData[0] + (0, 1))
._SetValue($"{blockDto.PenetrationInSlide}");
sheet._Range(AddressSlideTableData[1], AddressSlideTableData[1] + (0, 1))
._SetValue($"{blockDto.DrillingTimeInRotor}");
sheet._Range(AddressSlideTableData[2], AddressSlideTableData[2] + (0, 1))._SetValue("");
sheet.Cell(AddressSlideTableData[2])
.SetFormulaA1(FormulaMechanicalSpeed(AddressSlideTableData[0], AddressSlideTableData[1])).Style.SetAllBorders();
sheet._Range(AddressSlideTableData[3], AddressSlideTableData[3] + (0, 1))
._SetValue($"{blockDto.AVGDiffPressureSlide}");
sheet._Range(AddressTotalTableTitle, AddressTotalTableTitle + (0, 5))
._SetValue("Итого за отчетный период, использование САУБ-1");
sheet._Range(AddressTotalTableMechanicalSpeed, AddressTotalTableMechanicalSpeed + (1, 1))
._SetValue("Плановая мех скорость");
sheet._Range(AddressTotalTableHead[0], AddressTotalTableHead[0] + (0, 1))
._SetValue("Проходка");
sheet._Range(AddressTotalTableHead[1], AddressTotalTableHead[1] + (0, 1))
._SetValue("Часы бурения");
sheet._Range(AddressTotalTableHead[2], AddressTotalTableHead[2] + (0, 1))
._SetValue("Мех. скорость");
sheet._Range(AddressTotalTableData[0], AddressTotalTableData[0] + (0, 1))._SetValue("");
sheet.Cell(AddressTotalTableData[0])
.SetFormulaA1(FormulaSinking(AddressDrillingTableData[0], AddressSlideTableData[0], headBlock.AddressPeriodTableDataArray[3], headBlock.AddressPeriodTableDataArray[2]));
sheet._Range(AddressTotalTableData[1], AddressTotalTableData[1] + (0, 1))._SetValue("");
sheet.Cell(AddressTotalTableData[1])
.SetFormulaA1(FormulaWatch(AddressDrillingTableData[1], AddressSlideTableData[1]));
sheet._Range(AddressTotalTableData[2], AddressTotalTableData[2] + (0, 1))
._SetValue("");
sheet._Range(AddressTotalTableData[3], AddressTotalTableData[3] + (0, 1))
._SetValue($"{blockDto.SectionROPPlan}");
sheet._Range(IncreaseSpeedSection, IncreaseSpeedSection + (0, 3))
._SetValue("Увеличение мех скорости за секцию %");
sheet._Range(IncreaseSpeedSectionValue, IncreaseSpeedSectionValue + (0, 3))
._SetValue($"{blockDto.IncreaseSpeedSection}");
sheet._Range(IncreaseSpeedDay, IncreaseSpeedDay + (0, 3))
._SetValue("Увеличение мех скорости за сутки %");
sheet._Range(IncreaseSpeedDayValue, IncreaseSpeedDayValue + (0, 3))
._SetValue($"{blockDto.IncreaseSpeedDay}");
sheet._Range(ReductionTimeDrilling, ReductionTimeDrilling + (0, 3))
._SetValue("Сокращение времени бурения за секцию, ч");
sheet._Range(ReductionTimeDrillingValue, ReductionTimeDrillingValue + (0, 3))
._SetValue($"{blockDto.ReductionTimeDrilling}");
sheet._Range(RotorSlidePercent, RotorSlidePercent + (0, 3))
._SetValue("Ротор / слайд, %");
sheet._Range(RotorSlidePercentValue, RotorSlidePercentValue + (0, 3))
._SetValue($"{blockDto.RotorSlidePercent}");
sheet._Range(MspSection, MspSection + (0, 3))
._SetValue("МСП за секцию м/ч.");
sheet._Range(MspSectionValue, MspSectionValue + (0, 3))
._SetValue($"{blockDto.MspSection}");
sheet._Range(SectionDrillingTimeTotal, SectionDrillingTimeTotal + (0, 3))
._SetValue("Время бурения за секцию");
sheet._Range(SectionDrillingTimeTotalValue, SectionDrillingTimeTotalValue + (0, 3))
._SetValue($"{blockDto.SectionDrillingTimeTotal}");
sheet._Range(SectionPenetrationTotal, SectionPenetrationTotal + (0, 3))
._SetValue("Проходка за секцию");
sheet._Range(SectionPenetrationTotalValue, SectionPenetrationTotalValue + (0, 3))
._SetValue($"{blockDto.SectionPenetrationTotal}");
sheet._Range(AddressExtensionsCount, AddressExtensionsCount + (0, 3))
._SetValue("Кол- во наращиваний");
sheet._Range(AddressExtensionsCountValue, AddressExtensionsCountValue + (0, 3))
._SetValue($"{blockDto.ExtensionsCount}");
sheet._Range(DeviationFromTVD, DeviationFromTVD + (0, 3))
._SetValue("Отклонение от ГГД +/-, сут");
sheet._Range(DeviationFromTVDValue, DeviationFromTVDValue + (0, 3))
._SetValue($"{blockDto.DeviationFromTVD}");
sheet._Range(DeclinesReasonsROP, DeclinesReasonsROP + (1, 7))
._SetValue($"Примечание: {blockDto.DeclinesReasonsROP}");
}
}
}

View File

@ -1,51 +0,0 @@
using AsbCloudApp.Data.DailyReport;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
{
internal class SignBlock : BlockAbstract
{
private readonly SignDto blockDto;
public CellAddress AddressDrillMasterHead { get; }
public CellAddress AddressDrillMaster { get; }
public CellAddress AddressSupervisorHead { get; }
public CellAddress AddressSupervisor { get; }
public override CellAddress AddressBlockBegin { get; }
public override CellAddress AddressBlockEnd { get; }
public SignBlock(CellAddress addressBlockBegin, SignDto blockDto)
{
AddressBlockBegin = addressBlockBegin.Copy();
this.blockDto = blockDto;
AddressDrillMasterHead = addressBlockBegin + (3, 0);
AddressDrillMaster = AddressDrillMasterHead + (0, 5);
AddressSupervisorHead = AddressDrillMasterHead + (2, 0);
AddressSupervisor = AddressSupervisorHead + (0, 5);
AddressBlockEnd = AddressSupervisor + (0,1);
}
public override void Draw(IXLWorksheet sheet)
{
sheet.Range(AddressDrillMasterHead.RowNumber, AddressDrillMasterHead.ColumnNumber
, AddressDrillMasterHead.RowNumber, AddressDrillMasterHead.ColumnNumber + 2)
.Merge()
.SetValue("Мастер буровой ");
sheet.Range(AddressDrillMaster.RowNumber, AddressDrillMaster.ColumnNumber
, AddressDrillMaster.RowNumber, AddressDrillMaster.ColumnNumber + 2)
.Merge()
.SetValue($"{blockDto.DrillingMaster}");
sheet.Range(AddressSupervisorHead.RowNumber, AddressSupervisorHead.ColumnNumber
, AddressSupervisorHead.RowNumber, AddressSupervisorHead.ColumnNumber + 2)
.Merge()
.SetValue("Супервайзер ");
sheet.Range(AddressSupervisor.RowNumber, AddressSupervisor.ColumnNumber
, AddressSupervisor.RowNumber, AddressSupervisor.ColumnNumber + 2)
.Merge()
.SetValue($"{blockDto.Supervisor}");
}
}
}

View File

@ -1,93 +0,0 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.DailyReport;
using ClosedXML.Excel;
using System;
using System.Collections.Generic;
using System.Linq;
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
{
/// <summary>
/// Построение баланса времени
/// </summary>
class TimeBalanceBlock : BlockAbstract
{
/// <summary>
/// Начальная ячейка
/// </summary>
public override CellAddress AddressBlockBegin { get; }
/// <summary>
/// Конечная ячейка
/// </summary>
public override CellAddress AddressBlockEnd { get; }
/// <summary>
/// Ячейка с заголовком
/// </summary>
private CellAddress Title { get { return AddressBlockBegin + (1, 3); } }
/// <summary>
/// Статистика по операциям
/// </summary>
private Dictionary<int, double> OperationsStatistics { get; }
/// <summary>
/// Категории операций
/// </summary>
private IEnumerable<WellOperationCategoryDto> OperationCategories { get; }
/// <summary>
/// количество столбцов в таблице
/// </summary>
private const int countColumns = 3;
/// <summary>
/// количество категорий операций
/// </summary>
private int OperationCategoriesCount { get { return OperationCategories.Count(); } }
public TimeBalanceBlock(CellAddress addressBlockBegin, TimeBalanceDto blockDto, IEnumerable<WellOperationCategoryDto> operationCategories)
{
AddressBlockBegin = addressBlockBegin.Copy();
OperationsStatistics = blockDto.OperationsStat;
OperationCategories = operationCategories;
var rowsCount = (int)Math.Ceiling( 1d * OperationCategoriesCount / countColumns);
var colsCount = (1 + 1) * countColumns;
AddressBlockEnd = Title + (rowsCount, colsCount);
}
public override void Draw(IXLWorksheet sheet)
{
sheet.Range(Title.RowNumber, Title.ColumnNumber, Title.RowNumber, Title.ColumnNumber + 1)
.Merge()
.SetValue("БАЛАНС ВРЕМЕНИ");
var i = 0;
foreach (var operationCategory in OperationCategories)
{
var row = 2 + (int)Math.Floor(1d * i / countColumns);
var col = 1 + 2 *(i % countColumns);
i++;
sheet.Cell(AddressBlockBegin + (row, col))
._SetValue(operationCategory.Name, true);
sheet.Cell(AddressBlockBegin + (row, col + 1))
._SetValue(GetValue(operationCategory.Id), true);
}
}
private string GetValue(int categoryId)
{
if (OperationsStatistics.TryGetValue(categoryId, out double duration))
return $"{duration}";
return "0";
}
}
}

View File

@ -0,0 +1,253 @@
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 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 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, 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 rowСurrent = rowStartSubsystemBlock;
foreach (var subsystem in subsystemBlock.Subsystems)
{
sheet.Cell(rowСurrent, columnSubsystemName).Value = subsystem.Name;
sheet.Cell(rowСurrent, columnUseSubsystemPerDayUsedTimeHours).Value = subsystem.UsagePerDay?.UsedTimeHours;
sheet.Cell(rowСurrent, columnUseSubsystemPerDaySumDepthInterval).Value = subsystem.UsagePerDay?.SumDepthInterval;
sheet.Cell(rowСurrent, columnUseSubsystemPerDayKUsage).Value = subsystem.UsagePerDay?.KUsage;
sheet.Cell(rowСurrent, columnUseSubsystemPerWellUsedTimeHours).Value = subsystem.UsagePerWell?.UsedTimeHours;
sheet.Cell(rowСurrent, columnUseSubsystemPerWellSumDepthInterval).Value = subsystem.UsagePerWell?.SumDepthInterval;
sheet.Cell(rowСurrent, columnUseSubsystemPerWellKUsage).Value = subsystem.UsagePerWell?.KUsage;
rowСurrent++;
}
sheet.Cell(cellSubsystemComment).Value = subsystemBlock.Comment;
sheet.Cell(cellSubsystemTvgLagDays).Value = subsystemBlock.TvgLagDays;
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();
}
}

View File

@ -1,61 +0,0 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.DailyReport;
using AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks;
using ClosedXML.Excel;
using System.Collections.Generic;
using System.IO;
namespace AsbCloudInfrastructure.Services.DailyReport
{
public class DailyReportMakerExcel
{
private IEnumerable<WellOperationCategoryDto> OperationCategories = null!;
public Stream MakeReportFromBlocks(DailyReportDto dto, IEnumerable<WellOperationCategoryDto> operationCategories)
{
OperationCategories = operationCategories;
using var workbook = new XLWorkbook();
FillExampleBlocks(workbook, dto);
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
private void FillExampleBlocks(XLWorkbook workbook, DailyReportDto dto)
{
var sheet = workbook.Worksheets.Add(dto.Head.ReportDate.ToString("dd.MM.yyyy"));
var addressStart = new CellAddress(sheet, 2, 2);
var blockHeader = new HeadBlock(addressStart, dto.Head);
addressStart = blockHeader.AddressBlockEnd + (1, 0);
addressStart.ColumnNumber = 2;
var blockBha = new BhaBlock(addressStart, dto.Bha);
addressStart = blockBha.AddressBlockEnd + (1, 0);
addressStart.ColumnNumber = 2;
var timeBalance = new TimeBalanceBlock(addressStart, dto.TimeBalance, OperationCategories);
addressStart = timeBalance.AddressBlockEnd + (1, 0);
addressStart.ColumnNumber = 2;
var blockDimensionless = new DimensionlessBlock(addressStart, dto.NoDrilling);
addressStart = blockDimensionless.AddressBlockEnd + (1, 0);
addressStart.ColumnNumber = 2;
var blockSaub = new SaubBlock(addressStart, dto.Saub, blockHeader);
addressStart = blockSaub.AddressBlockEnd + (1, 0);
blockDimensionless.SaubBlock = blockSaub;
addressStart.ColumnNumber = 2;
var blockSign = new SignBlock(addressStart, dto.Sign);
addressStart = blockSign.AddressBlockEnd + (1, 0);
addressStart.ColumnNumber = 2;
blockHeader.Draw(sheet);
blockBha.Draw(sheet);
timeBalance.Draw(sheet);
blockDimensionless.Draw(sheet);
blockSaub.Draw(sheet);
blockSign.Draw(sheet);
//sheet.Columns().AdjustToContents(); // Adjust column width
sheet.Rows().AdjustToContents();
}
}
}

View File

@ -1,241 +1,378 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Data.User;
using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudDb.Model.DailyReport;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
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.Requests;
using AsbCloudApp.Services.DailyReport;
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
using AsbCloudApp.Services.Subsystems;
using AsbCloudDb.Model;
using Mapster;
using AsbCloudApp.Data.Trajectory;
namespace AsbCloudInfrastructure.Services.DailyReport
namespace AsbCloudInfrastructure.Services.DailyReport;
public class DailyReportService : IDailyReportService
{
private readonly IWellService wellService;
private readonly ITrajectoryEditableRepository<TrajectoryGeoFactDto> trajectoryFactRepository;
private readonly IDailyReportRepository dailyReportRepository;
private readonly IScheduleRepository scheduleRepository;
private readonly IWellOperationRepository wellOperationRepository;
private readonly ISubsystemOperationTimeService subsystemOperationTimeService;
private readonly IProcessMapReportWellDrillingService processMapReportWellDrillingService;
private readonly IDetectedOperationService detectedOperationService;
public class DailyReportService : IDailyReportService
{
private readonly IAsbCloudDbContext db;
private readonly IUserRepository userRepository;
private readonly IWellOperationRepository wellOperationRepository;
private readonly IWellService wellService;
private readonly DailyReportMakerExcel dailyReportMaker = new DailyReportMakerExcel();
public DailyReportService(IWellService wellService,
ITrajectoryEditableRepository<TrajectoryGeoFactDto> trajectoryFactRepository,
IDailyReportRepository dailyReportRepository,
IScheduleRepository scheduleRepository,
IWellOperationRepository wellOperationRepository,
ISubsystemOperationTimeService subsystemOperationTimeService,
IProcessMapReportWellDrillingService processMapReportWellDrillingService,
IDetectedOperationService detectedOperationService)
{
this.wellService = wellService;
this.trajectoryFactRepository = trajectoryFactRepository;
this.dailyReportRepository = dailyReportRepository;
this.scheduleRepository = scheduleRepository;
this.wellOperationRepository = wellOperationRepository;
this.subsystemOperationTimeService = subsystemOperationTimeService;
this.processMapReportWellDrillingService = processMapReportWellDrillingService;
this.detectedOperationService = detectedOperationService;
}
public DailyReportService(
IAsbCloudDbContext db,
IWellService wellService,
IUserRepository userRepository,
IWellOperationRepository wellOperationRepository)
{
this.db = db;
this.wellService = wellService;
this.userRepository = userRepository;
this.wellOperationRepository = wellOperationRepository;
public async Task<int> UpdateOrInsertAsync<TBlock>(int idWell, DateTime dateDailyReport, int idUser, TBlock editableBlock,
CancellationToken cancellationToken)
where TBlock : ItemInfoDto
{
if (!await IsDateDailyReportInRangeAsync(idWell, dateDailyReport, cancellationToken))
throw new ArgumentInvalidException(nameof(dateDailyReport), "Невозможно обновить суточный отчёт");
}
var dailyReport = await dailyReportRepository.GetOrDefaultAsync(idWell, dateDailyReport, cancellationToken) ??
new DailyReportDto
{
IdWell = idWell,
Date = dateDailyReport
};
public async Task<IEnumerable<DailyReportDto>> GetListAsync(int idWell, DateOnly? begin, DateOnly? end, CancellationToken token)
{
var well = wellService.GetOrDefault(idWell)
?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist");
switch (editableBlock)
{
case SubsystemBlockDto subsystemBlock:
dailyReport.SubsystemBlock = subsystemBlock;
break;
case TimeBalanceBlockDto timeBalanceBlock:
dailyReport.TimeBalanceBlock = timeBalanceBlock;
break;
case SignBlockDto signBlock:
dailyReport.SignBlock = signBlock;
break;
default:
throw new InvalidOperationException("Unexpected type of editableBlock");
}
var query = db.DailyReports.Where(r => r.IdWell == idWell);
editableBlock.IdUser = idUser;
editableBlock.LastUpdateDate = DateTime.UtcNow;
if (begin is not null)
{
query = query.Where(d => d.StartDate >= begin);
}
dailyReport.DateLastUpdate = DateTime.UtcNow;
if (end is not null)
{
query = query.Where(d => d.StartDate <= end);
}
if (dailyReport.Id == 0)
return await dailyReportRepository.InsertAsync(dailyReport, cancellationToken);
var entities = await query.OrderByDescending(e => e.StartDate)
.AsNoTracking()
.ToArrayAsync(token)
.ConfigureAwait(false);
return await dailyReportRepository.UpdateAsync(dailyReport, cancellationToken);
}
var factOperationsForDtos = await GetFactOperationsForDailyReportAsync(idWell, token);
var userDtos = await userRepository.GetAllAsync(token);
public async Task<DailyReportDto> GetAsync(int idWell, DateTime dateDailyReport, CancellationToken cancellationToken)
{
var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken);
var dtos = entities.Select(entity => Convert(entity, factOperationsForDtos, userDtos));
return dtos;
}
if (well is null)
throw new ArgumentNullException(nameof(idWell), $"Скважина с Id: {idWell} не найдена");
/// <summary>
/// Получение фактических операций для суточного рапорта
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>
/// <returns></returns>
private async Task<IEnumerable<WellOperationDto>> GetFactOperationsForDailyReportAsync(int idWell, CancellationToken token)
{
var request = new WellOperationRequest()
{
IdWell = idWell,
OperationType = WellOperation.IdOperationTypeFact,
};
if (!await IsDateDailyReportInRangeAsync(idWell, dateDailyReport, cancellationToken))
throw new ArgumentInvalidException(nameof(dateDailyReport), "Невозможно получить суточный отчёт");
var factOperations = await wellOperationRepository.GetAsync(request, token);
return factOperations;
}
public async Task<int> AddAsync(int idWell, DateOnly startDate, int idUser, CancellationToken token)
{
var well = wellService.GetOrDefault(idWell)
?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist");
var dailyReport = await dailyReportRepository.GetOrDefaultAsync(idWell, dateDailyReport, cancellationToken) ?? new DailyReportDto
{
Date = dateDailyReport.Date,
IdWell = well.Id
};
var hasEntity = await db.DailyReports
.AnyAsync(r => r.IdWell == idWell && r.StartDate == startDate, token);
if (hasEntity)
throw new ArgumentInvalidException(nameof(startDate), $"daily report on {startDate} already exists");
var factWellOperations = (await GetFactWellOperationsAsync(idWell, dailyReport.Date, cancellationToken))
.OrderBy(o => o.DateStart)
.ThenBy(o => o.DepthStart);
var entity = new AsbCloudDb.Model.DailyReport.DailyReport
{
IdWell = idWell,
StartDate = startDate,
Info = new DailyReportInfo()
{
Head = CreateHeadDailyReportBlock(well, startDate, idUser)
}
};
db.DailyReports.Add(entity);
var result = await db.SaveChangesAsync(token);
return result;
}
dailyReport.WellCaption = well.Caption;
dailyReport.WellType = well.WellType;
dailyReport.Cluster = well.Cluster;
dailyReport.Deposit = well.Deposit;
dailyReport.Customer = well.Companies.FirstOrDefault(c => c.IdCompanyType == 1)?.Caption;
dailyReport.Contractor = well.Companies.FirstOrDefault(c => c.IdCompanyType == 2)?.Caption;
dailyReport.DepthStart = factWellOperations.FirstOrDefault()?.DepthStart;
dailyReport.DepthEnd = factWellOperations.LastOrDefault()?.DepthEnd;
public async Task<int> UpdateBlockAsync(int idWell, DateOnly startDate, ItemInfoDto dto, CancellationToken token)
{
var well = wellService.GetOrDefault(idWell)
?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist");
await UpdateTimeBalanceBlockAsync(dailyReport, factWellOperations, cancellationToken);
await UpdateSubsystemBlockAsync(dailyReport, cancellationToken);
var entity = await db.DailyReports.FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate == startDate, token)
?? throw new ArgumentInvalidException(nameof(startDate), "Daily report doesn`t exist");
await AddTrajectoryBlockAsync(dailyReport, cancellationToken);
await AddScheduleBlockAsync(dailyReport, cancellationToken);
await AddProcessMapWellDrillingBlockAsync(dailyReport, cancellationToken);
dto.LastUpdateDate = DateTimeOffset.Now;
if (dto is HeadDto headDto)
entity.Info.Head = headDto.Adapt<Head>();
if (dto is BhaDto bhaDto)
entity.Info.Bha = bhaDto.Adapt<Bha>();
if (dto is NoDrillingDto noDrillingDto)
entity.Info.NoDrilling = noDrillingDto.Adapt<NoDrilling>();
if (dto is SaubDto saubDto)
entity.Info.Saub = saubDto.Adapt<Saub>();
if (dto is SignDto signDto)
entity.Info.Sign = signDto.Adapt<Sign>();
AddFactWellOperationBlock(dailyReport, factWellOperations);
db.DailyReports.Update(entity);
var result = await db.SaveChangesAsync(token);
return result;
}
return dailyReport;
}
public async Task<Stream?> MakeReportAsync(int idWell, DateOnly date, CancellationToken token)
{
var stageIds = WellOperationCategory.WorkStages.Select(w => w.Id).ToArray();
var wellOperationCategories = wellOperationRepository.GetCategories(true)
.Where(o => o.IdParent is not null)
.Where(o => stageIds.Contains(o.IdParent!.Value));
public async Task<PaginationContainer<DailyReportDto>> GetAsync(int idWell, FileReportRequest request,
CancellationToken cancellationToken)
{
var result = new PaginationContainer<DailyReportDto>
{
Skip = request.Skip ?? 0,
Take = request.Take ?? 10,
Items = Enumerable.Empty<DailyReportDto>()
};
var dailyReportDto = await GetOrDefaultAsync(idWell, date, token);
if (dailyReportDto is null)
return null;
var datesRange = await GetDatesRangeAsync(idWell, cancellationToken);
var memoryStream = dailyReportMaker.MakeReportFromBlocks(dailyReportDto, wellOperationCategories);
if (datesRange is null)
return result;
return memoryStream;
}
var dailyReports = new List<DailyReportDto>();
private async Task<DailyReportDto?> GetOrDefaultAsync(int idWell, DateOnly date, CancellationToken token)
{
var entity = await db.DailyReports
.FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate == date, token)
?? throw new ArgumentInvalidException(nameof(date), "Daily report doesn`t exist");
var existingDailyReports = await dailyReportRepository.GetAsync(idWell, request, cancellationToken);
var factWellOperations = await GetFactWellOperationsAsync(idWell, null, cancellationToken);
var factOperationsForDtos = await GetFactOperationsForDailyReportAsync(idWell, token);
var userDtos = await userRepository.GetAllAsync(token);
var dto = Convert(entity, factOperationsForDtos, userDtos);
return dto;
}
if (request.GeDate.HasValue)
{
var startDate = new DateTime(request.GeDate.Value.Year, request.GeDate.Value.Month,
request.GeDate.Value.Day);
/// <summary>
/// конвертация данных из модели базы данных в dto
/// </summary>
/// <param name="entity">модель базы данных</param>
/// <param name="factOperationsForDtos">список фактичских операций для формирования суточного рапорта</param>
/// <param name="users">список пользователей для нахождения последнего изменившего запись</param>
/// <returns></returns>
private DailyReportDto Convert(
AsbCloudDb.Model.DailyReport.DailyReport entity,
IEnumerable<WellOperationDto> factOperationsForDtos,
IEnumerable<UserExtendedDto> users)
{
var dto = entity.Info.Adapt<DailyReportDto>();
dto.StartDate = entity.StartDate;
if (startDate.Date >= datesRange.From.Date)
datesRange.From = startDate;
}
var dailyFactOperations = factOperationsForDtos
.Where(o => DateOnly.FromDateTime(o.DateStart) == dto.StartDate)
.Where(o => o.IdParentCategory is not null);
if (request.LeDate.HasValue)
{
var finishDate = new DateTime(request.LeDate.Value.Year, request.LeDate.Value.Month,
request.LeDate.Value.Day);
var lastDailyFactOperation = dailyFactOperations
.OrderByDescending(o => o.LastUpdateDate)
.FirstOrDefault();
dto.TimeBalance.IdUser = lastDailyFactOperation?.IdUser;
dto.TimeBalance.LastUpdateDate = lastDailyFactOperation?.LastUpdateDate;
dto.TimeBalance.OperationsStat = dailyFactOperations
.GroupBy(o => o.IdParentCategory!.Value)
.ToDictionary(g => g.Key, g => g.Sum(o => o.DurationHours));
if (finishDate.Date <= datesRange.To.Date)
datesRange.To = finishDate;
}
var blocks = new ItemInfoDto[] {
dto.Head,
dto.Bha,
dto.NoDrilling,
dto.TimeBalance,
dto.Saub,
dto.Sign
};
if (datesRange.From.AddDays(result.Skip) <= datesRange.To)
result.Count = (int)(Math.Ceiling((datesRange.To - DateTime.UnixEpoch).TotalDays) -
Math.Floor((datesRange.From - DateTime.UnixEpoch).TotalDays));
foreach (var block in blocks)
{
if (block.IdUser is not null)
{
block.UserName = users.FirstOrDefault(u => u.Id == block.IdUser.Value)?.MakeDisplayName()
?? $"userId:{block.IdUser.Value}";
}
}
return dto;
}
if (request.SortFields?.Contains("DateStart desc") == true)
{
for (var day = result.Skip; day - result.Skip < result.Take && datesRange.To.AddDays(-day) >= datesRange.From; day++)
{
var dateDailyReport = datesRange.To.AddDays(-day).Date;
/// <summary>
/// Создание блока "Заголовок" по умолчанию
/// </summary>
/// <param name="well"></param>
/// <param name="startDate"></param>
/// <param name="idUser"></param>
/// <returns></returns>
private Head CreateHeadDailyReportBlock(WellDto well, DateOnly startDate, int idUser)
{
var customer = well.Companies.FirstOrDefault(company => company.IdCompanyType == 1);
var contractor = well.Companies.FirstOrDefault(company => company.IdCompanyType == 2);
AddDailyReport(dateDailyReport);
}
}
else
{
for (var day = result.Skip; day - result.Skip < result.Take && datesRange.From.AddDays(day) <= datesRange.To; day++)
{
var dateDailyReport = datesRange.From.AddDays(day).Date;
return new Head()
{
ReportDate = startDate,
WellName = well.Caption,
ClusterName = well?.Cluster ?? string.Empty,
Customer = customer?.Caption ?? string.Empty,
Contractor = contractor?.Caption ?? string.Empty,
IdUser = idUser,
LastUpdateDate = DateTimeOffset.Now,
};
}
}
AddDailyReport(dateDailyReport);
}
}
result.Items = dailyReports;
return result;
void AddDailyReport(DateTime date)
{
var dailyReport = existingDailyReports.FirstOrDefault(d => d.IdWell == idWell && d.Date == date)
?? new DailyReportDto
{
Date = date,
IdWell = idWell
};
AddFactWellOperationBlock(dailyReport, factWellOperations.Where(o => o.DateStart >= date && o.DateStart <= date.AddDays(1)));
dailyReports.Add(dailyReport);
}
}
public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken)
{
var factOperations = await GetFactWellOperationsAsync(idWell, null, cancellationToken);
if (!factOperations.Any())
return null;
var minDateStart = factOperations.Min(o => o.DateStart).Date;
var maxDateStart = factOperations.Max(o => o.DateStart).Date;
return new DatesRangeDto
{
From = minDateStart.AddDays(1) <= DateTime.UtcNow ? minDateStart : DateTime.UtcNow.Date.AddDays(-1),
To = maxDateStart.AddDays(1) <= DateTime.UtcNow ? maxDateStart : DateTime.UtcNow.Date.AddDays(-1)
};
}
private async Task UpdateTimeBalanceBlockAsync(DailyReportDto dailyReport, IEnumerable<WellOperationDto> factWellOperations,
CancellationToken cancellationToken)
{
const int idWellOperationSlipsTime = 5011;
if (dailyReport.TimeBalanceBlock is not null)
{
dailyReport.TimeBalanceBlock.SectionName = wellOperationRepository.GetSectionTypes()
.FirstOrDefault(s => s.Id == dailyReport.TimeBalanceBlock.IdSection)?.Caption;
dailyReport.TimeBalanceBlock.WellOperationSlipsTimeCount = (await detectedOperationService.GetAsync(
new DetectedOperationRequest
{
IdsCategories = new[] { idWellOperationSlipsTime },
IdWell = dailyReport.IdWell,
GtDate = dailyReport.Date,
LtDate = dailyReport.Date.AddHours(24)
}, cancellationToken))?.Stats.Sum(s => s.Count);
dailyReport.TimeBalanceBlock.WellDepth.Fact = factWellOperations
.Where(o => o.IdWellSectionType == dailyReport.TimeBalanceBlock.IdSection)
.Sum(o => o.DepthEnd - o.DepthStart);
}
}
private async Task AddTrajectoryBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken)
{
var trajectory = (await trajectoryFactRepository.GetAsync(new TrajectoryRequest
{
IdWell = dailyReport.IdWell,
GeDate = dailyReport.Date,
LeDate = dailyReport.Date.AddHours(24)
}, cancellationToken)).MaxBy(t => t.WellboreDepth);
dailyReport.TrajectoryBlock = new TrajectoryBlockDto
{
WellboreDepth = trajectory?.WellboreDepth,
VerticalDepth = trajectory?.VerticalDepth,
ZenithAngle = trajectory?.ZenithAngle,
AzimuthGeo = trajectory?.AzimuthGeo
};
}
private async Task AddScheduleBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken) =>
dailyReport.ScheduleBlock = (await scheduleRepository.GetAsync(dailyReport.IdWell, dailyReport.Date, cancellationToken))
.Select(s => new ScheduleRecordDto
{
ShiftStart = s.ShiftStart,
ShiftEnd = s.ShiftEnd,
Name = s.Driller?.Name,
Surname = s.Driller?.Surname,
Patronymic = s.Driller?.Patronymic
});
private async Task UpdateSubsystemBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken)
{
dailyReport.SubsystemBlock ??= new SubsystemBlockDto();
dailyReport.SubsystemBlock.Subsystems = await GetSubsystemsAsync();
async Task<IEnumerable<SubsystemRecordDto>> GetSubsystemsAsync()
{
var subsystemOperationTimesPerWell = await subsystemOperationTimeService.GetStatAsync(new SubsystemOperationTimeRequest
{
IdWell = dailyReport.IdWell
}, cancellationToken);
var subsystemOperationTimesPerDay = await subsystemOperationTimeService.GetStatAsync(new SubsystemOperationTimeRequest
{
IdWell = dailyReport.IdWell,
GtDate = dailyReport.Date,
LtDate = dailyReport.Date.AddHours(24)
}, cancellationToken);
var subsystems = subsystemOperationTimesPerWell
.Select(subsystemOperationTime => new SubsystemRecordDto
{
Name = subsystemOperationTime.SubsystemName,
UsagePerDay = subsystemOperationTimesPerDay.FirstOrDefault(s => s.IdSubsystem == subsystemOperationTime.IdSubsystem)?.Adapt<SubsystemParametersDto>(),
UsagePerWell = subsystemOperationTime.Adapt<SubsystemParametersDto>()
}).ToList();
if (dailyReport.SubsystemBlock?.Subsystems != null && dailyReport.SubsystemBlock.Subsystems.Any())
subsystems.AddRange(dailyReport.SubsystemBlock.Subsystems);
return subsystems.OrderBy(s => s.Name);
}
}
private async Task AddProcessMapWellDrillingBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken)
{
dailyReport.ProcessMapWellDrillingBlock = (await processMapReportWellDrillingService.GetAsync(dailyReport.IdWell,
cancellationToken)).Where(p => p.DateStart >= dailyReport.Date &&
p.DateStart <= dailyReport.Date.AddHours(24))
.GroupBy(p => p.DrillingMode)
.Select(g => new ProcessMapWellDrillingRecordDto
{
DrillingMode = g.Key,
WellBoreDepth = g.Sum(p => p.DeltaDepth),
Rop = new PlanFactDto<double?>
{
Plan = g.Sum(p => p.Rop.Plan),
Fact = g.Sum(p => p.Rop.Fact)
},
MechDrillingHours = g.Sum(p => p.MechDrillingHours)
});
}
private static void AddFactWellOperationBlock(DailyReportDto dailyReport, IEnumerable<WellOperationDto> factWellOperations)
{
const int idWellOperationCategoryDrilling = 4001;
dailyReport.FactWellOperationBlock = new WellOperationBlockDto
{
WellOperations = factWellOperations.GroupBy(o => o.IdParentCategory)
.Select(g => new WellOperationRecordDto
{
CategoryName = g.First().CategoryName,
DurationHours = g.Sum(o => o.DurationHours)
}),
SectionDrillingHours = factWellOperations
.Where(o => o.IdParentCategory is idWellOperationCategoryDrilling)
.Sum(o => o.DurationHours)
};
}
private Task<IEnumerable<WellOperationDto>> GetFactWellOperationsAsync(int idWell, DateTime? dateDailyReport, CancellationToken cancellationToken) =>
wellOperationRepository.GetAsync(new WellOperationRequest
{
IdWell = idWell,
OperationType = WellOperation.IdOperationTypeFact,
GeDate = dateDailyReport,
LtDate = dateDailyReport?.AddHours(24)
}, cancellationToken);
private async Task<bool> IsDateDailyReportInRangeAsync(int idWell, DateTime dateDailyReport, CancellationToken cancellationToken)
{
var datesRange = await GetDatesRangeAsync(idWell, cancellationToken);
return dateDailyReport >= datesRange?.From && dateDailyReport <= datesRange.To;
}
}

View File

@ -6,7 +6,6 @@ using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using AsbCloudApp.Exceptions;
namespace AsbCloudInfrastructure.Services;
@ -82,7 +81,6 @@ public class HelpPageService : IHelpPageService
/// <param name="idCategory"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <exception cref="NotFoundException"></exception>
public async Task<(Stream stream, string fileName)?> GetFileStreamAsync(string pageKey,
int idCategory,
CancellationToken cancellationToken)

View File

@ -149,7 +149,7 @@ public class ProcessMapReportWellDrillingExportService : IProcessMapReportWellDr
.SetVal(modeData.UsageFact);
sheet.Cell(row, columnRop)
.SetVal(modeData.Rop);
.SetVal(modeData.Rop.Fact);
return row + 1;
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMaps;
using AsbCloudApp.Data.ProcessMaps.Report;
using AsbCloudApp.Data.SAUB;
@ -188,7 +189,12 @@ public class ProcessMapReportWellDrillingService : IProcessMapReportWellDrilling
TopDriveTorque = telemetryStat.RotorTorque.MakeParams(processMapByMode?.TopDriveTorque.Plan),
SpeedLimit = telemetryStat.BlockSpeed.MakeParams(processMapByMode?.RopPlan),
Rop = telemetryStat.Rop,
Rop = new PlanFactDto<double?>
{
Plan = processMapByMode?.RopPlan,
Fact = telemetryStat.Rop
},
UsagePlan = processMapByMode?.UsageSaub ?? telemetryStat.UsagePredictPlan,
UsageFact = telemetryStat.UsageSaub,
};

View File

@ -1,5 +1,6 @@
using AsbCloudApp.Data.Trajectory;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using ClosedXML.Excel;
using System;
@ -15,7 +16,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory.Export
{
private readonly IWellService wellService;
private readonly ITrajectoryRepository<T> trajectoryService;
private readonly ITrajectoryRepository<T> trajectoryRepository;
protected abstract void AddCoordinatesToRow(IXLRow row, T trajectory);
public abstract string templateFileName { get; set; }
public abstract string usingTemplateFile { get; set; }
@ -31,12 +32,16 @@ namespace AsbCloudInfrastructure.Services.Trajectory.Export
public TrajectoryExportService(IWellService wellService, ITrajectoryRepository<T> trajectoryService)
{
this.wellService = wellService;
this.trajectoryService = trajectoryService;
this.trajectoryRepository = trajectoryService;
}
public async Task<Stream> ExportAsync(int idWell, CancellationToken token)
{
var trajectorys = await trajectoryService.GetAsync(idWell, token);
var request = new TrajectoryRequest()
{
IdWell = idWell,
};
var trajectorys = await trajectoryRepository.GetAsync(request, token);
return MakeExelFileStream(trajectorys);
}

View File

@ -1,5 +1,6 @@
using AsbCloudApp.Data.Trajectory;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using System;
using System.Collections.Generic;
using System.Linq;
@ -29,7 +30,11 @@ abstract class TrajectoryBaseService<TGeo, TCartesian>
public async Task<IEnumerable<TCartesian>?> GetAsync(int idWell, CancellationToken token)
{
var geoCoords = await repository.GetAsync(idWell, token);
var request = new TrajectoryRequest()
{
IdWell = idWell
};
var geoCoords = await repository.GetAsync(request, token);
var locs = GetTrajectoryVisualisation(geoCoords);
var dtos = locs.Select(l => Convert(l));
return dtos;

View File

@ -186,17 +186,6 @@ internal static class XLExtentions
return style;
}
/// <summary>
/// Костыль исправляющий проблему в библиотеке IXLRange Range(this IXLWorksheet, IXLAddress, IXLAddress) с кастингом IXLAddress к XLAddress.
/// </summary>
/// <param name="sheet"></param>
/// <param name="begin"></param>
/// <param name="end"></param>
/// <returns></returns>
internal static IXLRange _Range(this IXLWorksheet sheet, CellAddress begin, CellAddress end)
=> sheet.Range(begin.RowNumber, begin.ColumnNumber, end.RowNumber, end.ColumnNumber);
internal static T? GetCellValue<T>(this IXLCell cell)
{
try

View File

@ -19,12 +19,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="MockQueryable.Moq" Version="6.0.1" />
<PackageReference Include="Moq" Version="4.18.2" />
<PackageReference Include="NSubstitute" Version="5.1.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">

View File

@ -1,157 +0,0 @@
namespace AsbCloudWebApi.Tests.ControllersTests
{
//public class AnalyticsControllerTests
//{
// private readonly Mock<ITelemetryAnalyticsService> analyticsService;
// private readonly Mock<IWellService> wellService;
// private readonly TelemetryAnalyticsController controller;
// private readonly List<WellDepthToDayDto> depthToDayDtos;
// // fills class fields with data. Each test inside can change this data themselves for their needs
// public AnalyticsControllerTests()
// {
// analyticsService = new Mock<ITelemetryAnalyticsService>();
// wellService = new Mock<IWellService>();
// depthToDayDtos = new List<WellDepthToDayDto>()
// {
// new WellDepthToDayDto { WellDepth = 1000.0, BitDepth = 1000.0, Date = DateTime.Now },
// new WellDepthToDayDto { WellDepth = 2000.0, BitDepth = 2000.0, Date = DateTime.Now },
// new WellDepthToDayDto { WellDepth = 3000.0, BitDepth = 3000.0, Date = DateTime.Now }
// };
// analyticsService.Setup(s => s.GetWellDepthToDayAsync(It.IsAny<int>(), CancellationToken.None).Result)
// .Returns(depthToDayDtos);
// wellService.Setup(s => s.IsCompanyInvolvedInWell(It.IsAny<int>(), It.IsAny<int>()))
// .Returns(true);
// wellService.Setup(s => s.IsCompanyInvolvedInWellAsync(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
// .Returns(Task.FromResult(true));
// controller = new TelemetryAnalyticsController(analyticsService.Object,
// wellService.Object);
// controller.AddUser();
// }
// [Fact]
// public void It_should_return_depth_to_day_analytics()
// {
// var result = controller.GetWellDepthToDayAsync(1).Result;
// var okResult = result as OkObjectResult;
// Assert.NotNull(okResult);
// }
// [Fact]
// public void It_should_return_correct_count_depth_to_day_analytics()
// {
// var result = controller.GetWellDepthToDayAsync(1).Result;
// var okResult = result as OkObjectResult;
// var resultCount = ((List<WellDepthToDayDto>)okResult.Value).Count;
// Assert.Equal(3, resultCount);
// }
// [Fact]
// public void It_should_return_403_if_no_idCompany()
// {
// var emptyUserController = new TelemetryAnalyticsController(analyticsService.Object,
// wellService.Object);
// var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { }, "mock"));
// emptyUserController.ControllerContext = new ControllerContext()
// {
// HttpContext = new DefaultHttpContext() { User = user }
// };
// var result = emptyUserController.GetOperationsByWellAsync(1).Result;
// var forbidResult = result as ForbidResult;
// Assert.NotNull(forbidResult);
// }
// [Fact]
// public void It_should_return_403_if_user_doesnt_own_well()
// {
// var wellServiceReturnsFalse = new Mock<IWellService>();
// wellServiceReturnsFalse.Setup(s => s.IsCompanyInvolvedInWell(It.IsAny<int>(), It.IsAny<int>()))
// .Returns(false);
// var newControllerInstance = new TelemetryAnalyticsController(analyticsService.Object,
// wellServiceReturnsFalse.Object);
// var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[]
// {
// new Claim("idCompany", "1"),
// }, "mock"));
// newControllerInstance.ControllerContext = new ControllerContext()
// {
// HttpContext = new DefaultHttpContext() { User = user }
// };
// var result = newControllerInstance.GetWellDepthToDayAsync(1).Result;
// var forbidResult = result as ForbidResult;
// Assert.NotNull(forbidResult);
// }
// [Fact]
// public void It_should_return_204_if_dtos_is_empty()
// {
// var emptyAnalyticsService = new Mock<ITelemetryAnalyticsService>();
// emptyAnalyticsService.Setup(s => s.GetWellDepthToDayAsync(It.IsAny<int>(), CancellationToken.None).Result)
// .Returns(new List<WellDepthToDayDto>());
// var newControllerInstance = new TelemetryAnalyticsController(emptyAnalyticsService.Object,
// wellService.Object);
// var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[]
// {
// new Claim("idCompany", "1"),
// }, "mock"));
// newControllerInstance.ControllerContext = new ControllerContext()
// {
// HttpContext = new DefaultHttpContext() { User = user }
// };
// var result = newControllerInstance.GetWellDepthToDayAsync(1).Result;
// var notFoundResult = result as NoContentResult;
// Assert.NotNull(notFoundResult);
// }
// [Fact]
// public void It_should_return_204_if_dtos_is_null()
// {
// var emptyAnalyticsService = new Mock<ITelemetryAnalyticsService>();
// emptyAnalyticsService.Setup(s => s.GetWellDepthToDayAsync(It.IsAny<int>(), CancellationToken.None))
// .Returns(Task.FromResult<IEnumerable<WellDepthToDayDto>>(null));
// var newControllerInstance = new TelemetryAnalyticsController(emptyAnalyticsService.Object,
// wellService.Object);
// var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[]
// {
// new Claim("idCompany", "1"),
// }, "mock"));
// newControllerInstance.ControllerContext = new ControllerContext()
// {
// HttpContext = new DefaultHttpContext() { User = user }
// };
// var result = newControllerInstance.GetWellDepthToDayAsync(1).Result;
// var notFoundResult = result as NoContentResult;
// Assert.NotNull(notFoundResult);
// }
//}
}

View File

@ -1,26 +0,0 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
namespace AsbCloudWebApi.Tests.ControllersTests
{
static class ControllerExtentions
{
public static void AddUser(this ControllerBase controller)
{
var claims = new Claim[] { new Claim("idCompany", "1") };
controller.AddUser(claims);
}
public static void AddUser(this ControllerBase controller, Claim[] claims)
{
var identity = new ClaimsIdentity(claims, "mock");
var user = new ClaimsPrincipal(identity);
controller.ControllerContext = new ControllerContext()
{
HttpContext = new DefaultHttpContext() { User = user }
};
}
}
}

View File

@ -1,26 +0,0 @@
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Services;
using AsbCloudWebApi.SignalR;
using Microsoft.AspNetCore.SignalR;
using Moq;
namespace AsbCloudWebApi.Tests.ControllersTests
{
public class TelemetryDataSaubControllerTests
{
private readonly Mock<ITelemetryService> telemetryService;
private readonly Mock<ITelemetryDataService<TelemetryDataSaubDto>> telemetryDataService;
private readonly Mock<IWellService> wellService;
private readonly Mock<IHubContext<TelemetryHub>> telemetryHubContext;
public TelemetryDataSaubControllerTests()
{
telemetryService = new Mock<ITelemetryService>();
telemetryDataService = new Mock<ITelemetryDataService<TelemetryDataSaubDto>>();
wellService = new Mock<IWellService>();
telemetryHubContext = new Mock<IHubContext<TelemetryHub>>();
}
}
}

View File

@ -1,17 +0,0 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudWebApi.Tests
{
public interface IRepositoryFactory<TDto>
{
Task<int> DeleteAsync(int id, CancellationToken token);
Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token);
TDto? GetOrDefault(int id);
Task<TDto?> GetOrDefaultAsync(int id, CancellationToken token);
Task<int> InsertAsync(TDto newItem, CancellationToken token);
Task<int> InsertRangeAsync(IEnumerable<TDto> newItems, CancellationToken token);
Task<int> UpdateAsync(TDto item, CancellationToken token);
}
}

View File

@ -17,6 +17,7 @@ using Xunit;
namespace AsbCloudWebApi.Tests.Middlware
{
//TODO: переписать как интеграционный тест. Использовать WebApplicationFactory.
public class UserConnectionsLimitMiddlwareTest
{
const int iterations2Block = 8;

View File

@ -1,42 +0,0 @@
using AsbCloudApp.Services;
using Moq;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudWebApi.Tests
{
public class RepositoryFactory
{
public static Mock<TRepository> Make<TRepository, TDto>(ICollection<TDto> data)
where TDto : AsbCloudApp.Data.IId
where TRepository : class, ICrudRepository<TDto>
{
var repositoryMock = new Mock<TRepository>();
repositoryMock.Setup(x => x.InsertAsync(It.IsAny<TDto>(), It.IsAny<CancellationToken>()))
.Returns((TDto dto, CancellationToken token) => {
var id = data.Max(x => x.Id);
dto.Id = ++id;
data.Add(dto);
return Task.FromResult(dto.Id);
});
repositoryMock.Setup(x => x.DeleteAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
.Returns((int idFile, CancellationToken token) => {
var cnt = data.Count;
var dto = data.FirstOrDefault(x => x.Id == idFile);
data.Remove(dto);
return Task.FromResult(cnt - data.Count);
});
repositoryMock.Setup(x => x.GetAllAsync(It.IsAny<CancellationToken>())).ReturnsAsync(data);
repositoryMock.Setup(x => x.GetOrDefaultAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
.Returns((int idFile, CancellationToken token) => {
return Task.FromResult(data.FirstOrDefault(x => x.Id == idFile));
});
return repositoryMock;
}
}
}

View File

@ -1,113 +0,0 @@
using AsbCloudInfrastructure.Background;
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
using System;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace AsbCloudWebApi.Tests.Services;
public class BackgroundWorkerTest
{
private IServiceProvider provider;
private BackgroundWorker service;
public BackgroundWorkerTest()
{
provider = Substitute.For<IServiceProvider, ISupportRequiredService>();
var serviceScope = Substitute.For<IServiceScope>();
var serviceScopeFactory = Substitute.For<IServiceScopeFactory>();
serviceScopeFactory.CreateScope().Returns(serviceScope);
((ISupportRequiredService)provider).GetRequiredService(typeof(IServiceScopeFactory)).Returns(serviceScopeFactory);
service = new BackgroundWorker(provider);
typeof(BackgroundWorker)
.GetField("minDelay", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(service, TimeSpan.FromMilliseconds(1));
}
[Fact]
public async Task Enqueue_n_works()
{
var workCount = 10;
var result = 0;
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
{
result++;
return Task.Delay(1);
}
//act
for (int i = 0; i < workCount; i++)
{
var work = Work.CreateByDelegate(i.ToString(), workAction);
service.Enqueue(work);
}
await service.ExecuteTask;
//assert
Assert.Equal(workCount, result);
}
[Fact]
public async Task Enqueue_continues_after_exceptions()
{
var expectadResult = 42;
var result = 0;
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
{
result = expectadResult;
return Task.CompletedTask;
}
var goodWork = Work.CreateByDelegate("", workAction);
Task failAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
=> throw new Exception();
var badWork = Work.CreateByDelegate("", failAction);
badWork.OnErrorAsync = (id, exception, token) => throw new Exception();
//act
service.Enqueue(badWork);
service.Enqueue(goodWork);
await service.ExecuteTask;
//assert
Assert.Equal(expectadResult, result);
Assert.Equal(1, service.Felled.Count);
Assert.Equal(1, service.Done.Count);
}
[Fact]
public async Task TryRemove()
{
var workCount = 5;
var result = 0;
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
{
result++;
return Task.Delay(10);
}
//act
for (int i = 0; i < workCount; i++)
{
var work = Work.CreateByDelegate(i.ToString(), workAction);
service.Enqueue(work);
}
var removed = service.TryRemoveFromQueue((workCount - 1).ToString());
await service.ExecuteTask;
//assert
Assert.True(removed);
Assert.Equal(workCount - 1, result);
Assert.Equal(workCount - 1, service.Done.Count);
}
}

View File

@ -1,94 +0,0 @@
using AsbCloudApp.Services;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace AsbCloudWebApi.Tests.ServicesTests
{
public abstract class CrudServiceTestAbstract<TDto>
where TDto : AsbCloudApp.Data.IId
{
private readonly ICrudRepository<TDto> service;
public CrudServiceTestAbstract()
{
AsbCloudInfrastructure.DependencyInjection.MapsterSetup();
service = MakeService();
}
protected abstract ICrudRepository<TDto> MakeService();
protected abstract TDto MakeNewItem();
[Fact]
public async Task<int> Insert()
{
var newItem = MakeNewItem();
var id = await service.InsertAsync(newItem, CancellationToken.None);
Assert.True(id > 0);
return id;
}
[Fact]
public async Task InsertRange()
{
var items = new TDto[2];
items[0] = MakeNewItem();
items[1] = MakeNewItem();
var count = await service.InsertRangeAsync(items, CancellationToken.None);
Assert.Equal(2, count);
}
[Fact]
public async Task GetById()
{
var id = await Insert();
var gotItem = await service.GetOrDefaultAsync(id, CancellationToken.None);
Assert.True(id > 0);
Assert.Equal(id, gotItem.Id);
}
[Fact]
public async Task GetAll()
{
var items = await service.GetAllAsync(CancellationToken.None);
var count = items.Count();
await Insert();
var newItems = await service.GetAllAsync(CancellationToken.None);
var newCount = newItems.Count();
Assert.True(newCount > 0);
Assert.Equal(count + 1, newCount);
}
[Fact]
public async Task UpdateAsync_returns_notfound()
{
var item = MakeNewItem();
item.Id = int.MaxValue - 1;
var updatedId = await service.UpdateAsync(item, CancellationToken.None);
Assert.True(updatedId < 0);
}
[Fact]
public async Task UpdateAsync()
{
var newItem = MakeNewItem();
newItem.Id = await service.InsertAsync(newItem, CancellationToken.None);
var item = MakeNewItem();
item.Id = newItem.Id;
var updatedId = await service.UpdateAsync(item, CancellationToken.None);
Assert.True(newItem.Id > 0);
Assert.Equal(newItem.Id, updatedId);
}
[Fact]
public async Task DeleteAsync()
{
var newItem = MakeNewItem();
var id = await service.InsertAsync(newItem, CancellationToken.None);
var deletedId = await service.DeleteAsync(id, CancellationToken.None);
Assert.True(id > 0);
Assert.Equal(id, deletedId);
}
}
}

View File

@ -1,28 +0,0 @@
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Repository;
namespace AsbCloudWebApi.Tests.ServicesTests
{
public class DepositCrudCacheServiceTest : CrudServiceTestAbstract<DepositDto>
{
protected override DepositDto MakeNewItem()
{
var item = new DepositDto
{
Caption = "test deposit",
Latitude = 1,
Longitude = 2,
Timezone = new SimpleTimezoneDto { Hours = 5, TimezoneId = "test Never-land" }
};
return item;
}
protected override ICrudRepository<DepositDto> MakeService()
{
var dbContext = TestHelpter.MakeRealTestContext();
return new CrudCacheRepositoryBase<DepositDto, Deposit>(dbContext, TestHelpter.MemoryCache);
}
}
}

View File

@ -1,182 +0,0 @@
using AsbCloudApp.Data;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Repository;
using AsbCloudInfrastructure.Services.DetectOperations;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace AsbCloudWebApi.Tests.ServicesTests
{
public class DetectedOperationServiceTest
{
private readonly AsbCloudDbContext context;
private readonly DetectedOperationService service;
private readonly DetectedOperationRequest request;
private Deposit deposit = new Deposit { Id = 1, Caption = "Депозит 1" };
private Cluster cluster = new Cluster { Id = 1, Caption = "Кластер 1", IdDeposit = 1, Timezone = new SimpleTimezone() };
private WellDto wellDto = new WellDto
{
Id = 1,
Caption = "Test well 1",
IdTelemetry = 1,
IdCluster = 1,
Timezone = new SimpleTimezoneDto { Hours = 5 }
};
private Well well = new Well
{
Id = 1,
Caption = "Test well 1",
IdTelemetry = 1,
IdCluster = 1,
Timezone = new SimpleTimezone { Hours = 5 }
};
private Driller driller = new Driller
{
Id = 1,
Name = "Тестовый",
Patronymic = "Тест",
Surname = "Тестович"
};
private List<DetectedOperation> do1 = new List<DetectedOperation> {
new DetectedOperation
{
Id = 1,
IdCategory = 1,
IdTelemetry = 1,
DateStart = DateTimeOffset.Parse("2022-05-16T10:00:00.286Z"),
DateEnd = DateTimeOffset.Parse("2022-05-16T18:00:00.286Z"),
DepthStart = 100,
Value = 50,
DepthEnd = 1000
},
new DetectedOperation
{
Id = 2,
IdCategory = 1,
IdTelemetry = 1,
DateStart = DateTimeOffset.Parse("2022-05-16T10:00:00.286Z"),
DateEnd = DateTimeOffset.Parse("2022-05-16T18:00:00.286Z"),
DepthStart = 100,
Value = 10,
DepthEnd = 1000
}};
private Telemetry telemetry = new Telemetry
{
Id = 1,
RemoteUid = Guid.NewGuid().ToString()
};
private OperationValue ovd = new OperationValue
{
Id = 1,
StandardValue = 200,
TargetValue = 100,
DepthEnd = 300,
DepthStart = 100,
IdOperationCategory=1,
IdWell = 1
};
private List<Schedule> sch = new List<Schedule> { new Schedule
{
Id = 1,
IdDriller = 1,
IdWell = 1,
DrillStart = DateTimeOffset.Parse("2022-05-16T10:00:00.286Z"),
DrillEnd = DateTimeOffset.Parse("2022-05-16T18:00:00.286Z"),
ShiftStart = new TimeOnly(10, 00),
ShiftEnd = new TimeOnly(18, 00)
}, new Schedule
{
Id = 2,
IdDriller = 1,
IdWell = 1,
DrillStart = DateTimeOffset.Parse("2022-05-17T10:00:00.286Z"),
DrillEnd = DateTimeOffset.Parse("2022-05-17T18:00:00.286Z"),
ShiftStart = new TimeOnly(10, 00),
ShiftEnd = new TimeOnly(18, 00)
} };
public DetectedOperationServiceTest()
{
context = TestHelpter.MakeRealTestContext();
context.SaveChanges();
context.Telemetries.Add(telemetry);
context.Deposits.Add(deposit);
context.Clusters.Add(cluster);
context.Wells.Add(well);
context.Drillers.Add(driller);
context.DetectedOperations.AddRange(do1);
context.OperationValues.Add(ovd);
context.Schedule.AddRange(sch);
context.SaveChanges();
var timezone = new SimpleTimezoneDto { Hours = 5 };
var wellServiceMock = new Mock<IWellService>();
wellServiceMock.Setup(s => s.GetTimezone(It.IsAny<int>())).Returns(timezone);
wellServiceMock.Setup(s => s.GetOrDefaultAsync(It.IsAny<int>(),CancellationToken.None)).Returns(Task.Run(() => wellDto));
//var operationValueService = new OperationValueService(context);
var scheduleService = new ScheduleRepository(context, wellServiceMock.Object);
service = new DetectedOperationService(context, wellServiceMock.Object, /*operationValueService*/ null, scheduleService);
request = new DetectedOperationRequest
{
IdWell = 1,
IdsCategories = new int[] { 1 },
};
AsbCloudInfrastructure.DependencyInjection.MapsterSetup();
}
~DetectedOperationServiceTest()
{
}
[Fact]
public async Task Count_grouping_by_driller()
{
var list = await service.GetAsync(request, CancellationToken.None);
Assert.Equal(2, list.Stats.First().Count);
}
[Fact]
public async Task AvgVal_grouping_by_driller()
{
var list = await service.GetAsync(request, CancellationToken.None);
Assert.Equal(30, list.Stats.First().AverageValue);
}
[Fact]
public async Task AvgTargetVal_grouping_by_driller()
{
var list = await service.GetAsync(request, CancellationToken.None);
Assert.Equal(100, list.Stats.First().AverageTargetValue);
}
[Fact]
public async Task Loss_grouping_by_driller()
{
var list = await service.GetAsync(request, CancellationToken.None);
Assert.Equal(0, list.Stats.First().Loss);
}
[Fact]
public async Task Efficiency_grouping_by_driller()
{
var list = await service.GetAsync(request, CancellationToken.None);
Assert.Equal(100, list.Stats.First().Efficiency);
}
[Fact]
public async Task GroupCount_grouping_by_driller()
{
var list = await service.GetAsync(request, CancellationToken.None);
Assert.Equal(1, list.Stats.Count());
}
}
}

Some files were not shown because too many files have changed in this diff Show More