diff --git a/AsbCloudApp/Data/AutogeneratedDailyReport/AutoGeneratedDailyReportInfoDto.cs b/AsbCloudApp/Data/AutogeneratedDailyReport/AutoGeneratedDailyReportInfoDto.cs index 0034879a..22e34cf2 100644 --- a/AsbCloudApp/Data/AutogeneratedDailyReport/AutoGeneratedDailyReportInfoDto.cs +++ b/AsbCloudApp/Data/AutogeneratedDailyReport/AutoGeneratedDailyReportInfoDto.cs @@ -5,21 +5,10 @@ namespace AsbCloudApp.Data.AutogeneratedDailyReport; /// /// Базовая информация о суточном отчёте /// -public class AutoGeneratedDailyReportInfoDto +public class AutoGeneratedDailyReportInfoDto : ReportInfoDto { - /// - /// Дата формирования отчёта - /// - public DateOnly ReportDate { get; set; } - - /// - /// Название файла - /// - public string FileName { get; set; } = null!; - - /// - /// Размер файла - /// - public int FileSize { get; set; } - + /// + /// Дата формирования отчёта + /// + public DateOnly ReportDate { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs b/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs new file mode 100644 index 00000000..ee63bf9b --- /dev/null +++ b/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs @@ -0,0 +1,26 @@ +using AsbCloudApp.Data.SAUB; +using System; + +namespace AsbCloudApp.Data.DrillTestReport +{ + /// + /// Информация о drill test, выгружаемая в отчете + /// + public class DrillTestReportDataDto + { + /// + /// Данные для отчета + /// + public DrillTestDto Data { get; set; } = null!; + + /// + /// Заголовок отчета + /// + public string Caption { get; set; } = null!; + + /// + /// Дата отчета + /// + public DateTime Date { get; set; } = DateTime.Now; + } +} diff --git a/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs b/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs new file mode 100644 index 00000000..8d3a9244 --- /dev/null +++ b/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs @@ -0,0 +1,25 @@ +using System; + +namespace AsbCloudApp.Data.DrillTestReport +{ + /// + /// Базовая информация о drill_test отчёте + /// + public class DrillTestReportInfoDto : ReportInfoDto + { + /// + /// Идентификатор отчета + /// + public int Id { get; set; } + + /// + /// Проходка + /// + public float DrillDepth { get; set; } + + /// + /// Дата и время + /// + public DateTime DateTime { get; set; } + } +} diff --git a/AsbCloudApp/Data/ReportInfoDto.cs b/AsbCloudApp/Data/ReportInfoDto.cs new file mode 100644 index 00000000..bd55d33c --- /dev/null +++ b/AsbCloudApp/Data/ReportInfoDto.cs @@ -0,0 +1,18 @@ +namespace AsbCloudApp.Data +{ + /// + /// Справочная информация об отчете + /// + public class ReportInfoDto + { + /// + /// Название файла + /// + public string FileName { get; set; } = null!; + + /// + /// Размер файла + /// + public int FileSize { get; set; } = 0; + } +} diff --git a/AsbCloudApp/Repositories/IDrillTestRepository.cs b/AsbCloudApp/Repositories/IDrillTestRepository.cs index 45552871..18ff0e9b 100644 --- a/AsbCloudApp/Repositories/IDrillTestRepository.cs +++ b/AsbCloudApp/Repositories/IDrillTestRepository.cs @@ -1,4 +1,5 @@ using AsbCloudApp.Data.SAUB; +using AsbCloudApp.Requests; using System.Threading; using System.Threading.Tasks; @@ -9,6 +10,24 @@ namespace AsbCloudApp.Repositories /// public interface IDrillTestRepository { + /// + /// Получить данные drill_test в соответствии с параметрами запроса + /// + /// ключ телеметрии + /// запрос + /// + /// + Task GetAllAsync(int idTelemetry, FileReportRequest request, CancellationToken cancellationToken); + + /// + /// Получить запись drill_test + /// + /// ключ телеметрии + /// ключ записи drill_test + /// + /// + Task GetAsync(int idTelemetry, int id, CancellationToken cancellationToken); + /// /// Сохранить данные drill_test /// diff --git a/AsbCloudApp/Requests/AutoGeneratedDailyReportRequest.cs b/AsbCloudApp/Requests/AutoGeneratedDailyReportRequest.cs index 5e7dae7c..a9984016 100644 --- a/AsbCloudApp/Requests/AutoGeneratedDailyReportRequest.cs +++ b/AsbCloudApp/Requests/AutoGeneratedDailyReportRequest.cs @@ -3,17 +3,17 @@ using System; namespace AsbCloudApp.Requests; /// -/// Параметры запроса для получения авто-генерируемых суточных отчётов +/// Параметры запроса для получения отчетов (файлов) /// -public class AutoGeneratedDailyReportRequest : RequestBase +public class FileReportRequest : RequestBase { - /// - /// Дата начала периода - /// - public DateOnly? StartDate { get; set; } - - /// - /// Дата конца периода - /// - public DateOnly? FinishDate { get; set; } + /// + /// Дата начала периода + /// + public DateOnly? GeDate { get; set; } + + /// + /// Дата конца периода + /// + public DateOnly? LeDate { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportMakerService.cs b/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportMakerService.cs index 8571e356..8c2e9a46 100644 --- a/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportMakerService.cs +++ b/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportMakerService.cs @@ -1,20 +1,19 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -using AsbCloudApp.Data.AutogeneratedDailyReport; namespace AsbCloudApp.Services.AutoGeneratedDailyReports; /// -/// Сервис для генерации файлов авто-генерируемых суточный отчётов +/// Сервис для генерации файлов отчётов /// -public interface IAutoGeneratedDailyReportMakerService +public interface IReportMakerService { - /// - /// Генерация файла - /// - /// - /// - /// - Task MakeReportAsync(AutoGeneratedDailyReportDto report, CancellationToken cancellationToken); + /// + /// Генерация файла + /// + /// модель с данными для построения отчета + /// + /// + Task MakeReportAsync(T report, CancellationToken cancellationToken); } \ No newline at end of file diff --git a/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportService.cs b/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportService.cs index 13bdb1ea..979f948c 100644 --- a/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportService.cs +++ b/AsbCloudApp/Services/AutoGeneratedDailyReports/IAutoGeneratedDailyReportService.cs @@ -21,7 +21,7 @@ public interface IAutoGeneratedDailyReportService /// /// Task> GetListAsync(int idWell, - AutoGeneratedDailyReportRequest request, + FileReportRequest request, CancellationToken cancellationToken); /// diff --git a/AsbCloudApp/Services/IDrillTestReportService.cs b/AsbCloudApp/Services/IDrillTestReportService.cs new file mode 100644 index 00000000..6dd97b83 --- /dev/null +++ b/AsbCloudApp/Services/IDrillTestReportService.cs @@ -0,0 +1,35 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Data.DrillTestReport; +using AsbCloudApp.Requests; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Services +{ + /// + /// сервис по работе с отчетами drill test + /// + public interface IDrillTestReportService + { + /// + /// Список файлов drill test + /// + /// ключ скважины + /// параметры запроса + /// + /// + Task> GetListAsync(int idWell, + FileReportRequest request, + CancellationToken cancellationToken); + + /// + /// Генерация файла с отчётом + /// + /// ключ скважины + /// ключ drill test записи + /// + /// + Task<(string fileName, Stream stream)> GenerateAsync(int idWell, int id, CancellationToken cancellationToken); + } +} diff --git a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj index bc825b4b..2c2bd528 100644 --- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj +++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj @@ -13,6 +13,7 @@ + @@ -30,6 +31,7 @@ + diff --git a/AsbCloudInfrastructure/AssemblyExtensions.cs b/AsbCloudInfrastructure/AssemblyExtensions.cs new file mode 100644 index 00000000..9594261b --- /dev/null +++ b/AsbCloudInfrastructure/AssemblyExtensions.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure +{ + public static class AssemblyExtensions + { + public static async Task GetTemplateCopyStreamAsync(this Assembly assembly, string templateName, CancellationToken cancellationToken) + { + var resourceName = assembly + .GetManifestResourceNames() + .FirstOrDefault(n => n.EndsWith(templateName))!; + + using var stream = Assembly.GetExecutingAssembly() + .GetManifestResourceStream(resourceName)!; + + var memoryStream = new MemoryStream(); + await stream.CopyToAsync(memoryStream, cancellationToken); + memoryStream.Position = 0; + + return memoryStream; + } + } +} diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 85caf0b2..0ce35409 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -1,5 +1,6 @@ -using System; -using AsbCloudApp.Data; +using AsbCloudApp.Data; +using AsbCloudApp.Data.AutogeneratedDailyReport; +using AsbCloudApp.Data.DrillTestReport; using AsbCloudApp.Data.Manuals; using AsbCloudApp.Data.ProcessMaps; using AsbCloudApp.Data.SAUB; @@ -24,6 +25,7 @@ using AsbCloudInfrastructure.Services.AutoGeneratedDailyReports; using AsbCloudInfrastructure.Services.DailyReport; using AsbCloudInfrastructure.Services.DetectOperations; using AsbCloudInfrastructure.Services.DrillingProgram; +using AsbCloudInfrastructure.Services.DrillTestReport; using AsbCloudInfrastructure.Services.ProcessMaps.Report; using AsbCloudInfrastructure.Services.ProcessMaps.WellDrilling; using AsbCloudInfrastructure.Services.SAUB; @@ -37,273 +39,275 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using System; namespace AsbCloudInfrastructure { public static class DependencyInjection { - public static IAsbCloudDbContext MakeContext(string connectionString) - { - var options = new DbContextOptionsBuilder() - .UseNpgsql(connectionString) - .Options; - var context = new AsbCloudDbContext(options); - return context; - } + public static IAsbCloudDbContext MakeContext(string connectionString) + { + var options = new DbContextOptionsBuilder() + .UseNpgsql(connectionString) + .Options; + var context = new AsbCloudDbContext(options); + return context; + } - public static void MapsterSetup() - { - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .MapWith((source) => source.DateTime); + public static void MapsterSetup() + { + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => source.DateTime); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .MapWith((source) => source == default ? new DateTime(0, DateTimeKind.Utc) : source); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => source == default ? new DateTime(0, DateTimeKind.Utc) : source); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .MapWith((source) => source.MakeTimeOnly()); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => source.MakeTimeOnly()); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .MapWith((source) => new(source)); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => new(source)); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .MapWith((source) => new(source)); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => new(source)); #pragma warning disable CS8603 // Possible null reference return. - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(dst => dst.Cluster, - dst => dst.RelationCompaniesWells, - dst => dst.Telemetry, - dst => dst.WellComposites, - dst => dst.WellCompositeSrcs, - dst => dst.WellOperations, - dst => dst.WellType); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(dst => dst.Cluster, + dst => dst.RelationCompaniesWells, + dst => dst.Telemetry, + dst => dst.WellComposites, + dst => dst.WellCompositeSrcs, + dst => dst.WellOperations, + dst => dst.WellType); #pragma warning restore CS8603 // Possible null reference return. - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(dst => dst.Deposit, - dst => dst.Wells); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(dst => dst.Deposit, + dst => dst.Wells); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType(); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType(); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType(); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType(); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(dst => dst.NotificationCategory, - dst => dst.User); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(dst => dst.NotificationCategory, + dst => dst.User); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Map(dest => dest.AxialLoad, src => new PlanLimitDto - { - LimitMax = src.AxialLoadLimitMax, - Plan = src.AxialLoadPlan - }) - .Map(dest => dest.Flow, src => new PlanLimitDto - { - LimitMax = src.FlowLimitMax, - Plan = src.FlowPlan - }) - .Map(dest => dest.Pressure, src => new PlanLimitDto - { - LimitMax = src.PressureLimitMax, - Plan = src.PressurePlan - }) - .Map(dest => dest.TopDriveSpeed, src => new PlanLimitDto - { - LimitMax = src.TopDriveSpeedLimitMax, - Plan = src.TopDriveSpeedPlan - }) - .Map(dest => dest.TopDriveTorque, src => new PlanLimitDto - { - LimitMax = src.TopDriveTorqueLimitMax, - Plan = src.TopDriveTorquePlan - }); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Map(dest => dest.AxialLoad, src => new PlanLimitDto + { + LimitMax = src.AxialLoadLimitMax, + Plan = src.AxialLoadPlan + }) + .Map(dest => dest.Flow, src => new PlanLimitDto + { + LimitMax = src.FlowLimitMax, + Plan = src.FlowPlan + }) + .Map(dest => dest.Pressure, src => new PlanLimitDto + { + LimitMax = src.PressureLimitMax, + Plan = src.PressurePlan + }) + .Map(dest => dest.TopDriveSpeed, src => new PlanLimitDto + { + LimitMax = src.TopDriveSpeedLimitMax, + Plan = src.TopDriveSpeedPlan + }) + .Map(dest => dest.TopDriveTorque, src => new PlanLimitDto + { + LimitMax = src.TopDriveTorqueLimitMax, + Plan = src.TopDriveTorquePlan + }); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Map(dest => dest.AxialLoadPlan, src => src.AxialLoad.Plan) - .Map(dest => dest.AxialLoadLimitMax, src => src.AxialLoad.LimitMax) - .Map(dest => dest.FlowPlan, src => src.Flow.Plan) - .Map(dest => dest.FlowLimitMax, src => src.Flow.LimitMax) - .Map(dest => dest.PressurePlan, src => src.Pressure.Plan) - .Map(dest => dest.PressureLimitMax, src => src.Pressure.LimitMax) - .Map(dest => dest.TopDriveSpeedPlan, src => src.TopDriveSpeed.Plan) - .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() + .Map(dest => dest.AxialLoadPlan, src => src.AxialLoad.Plan) + .Map(dest => dest.AxialLoadLimitMax, src => src.AxialLoad.LimitMax) + .Map(dest => dest.FlowPlan, src => src.Flow.Plan) + .Map(dest => dest.FlowLimitMax, src => src.Flow.LimitMax) + .Map(dest => dest.PressurePlan, src => src.Pressure.Plan) + .Map(dest => dest.PressureLimitMax, src => src.Pressure.LimitMax) + .Map(dest => dest.TopDriveSpeedPlan, src => src.TopDriveSpeed.Plan) + .Map(dest => dest.TopDriveSpeedLimitMax, src => src.TopDriveSpeed.LimitMax) + .Map(dest => dest.TopDriveTorquePlan, src => src.TopDriveTorque.Plan) + .Map(dest => dest.TopDriveTorqueLimitMax, src => src.TopDriveTorque.LimitMax); + } - public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration) - { - MapsterSetup(); - string connectionStringName = "DefaultConnection"; + public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration) + { + MapsterSetup(); + string connectionStringName = "DefaultConnection"; #if DEBUG - connectionStringName = "DebugConnection"; + connectionStringName = "DebugConnection"; #endif - services.AddDbContext(options => - options.UseNpgsql(configuration.GetConnectionString(connectionStringName))); + services.AddDbContext(options => + options.UseNpgsql(configuration.GetConnectionString(connectionStringName))); - services.AddMemoryCache(); - services.AddScoped(provider => provider.GetRequiredService()); + services.AddMemoryCache(); + services.AddScoped(provider => provider.GetRequiredService()); - services.AddSingleton(new WitsInfoService()); - services.AddSingleton(provider => TelemetryDataCache.GetInstance(provider)); - services.AddSingleton(provider => TelemetryDataCache.GetInstance(provider)); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(provider => ReduceSamplingService.GetInstance(configuration)); + services.AddSingleton(new WitsInfoService()); + services.AddSingleton(provider => TelemetryDataCache.GetInstance(provider)); + services.AddSingleton(provider => TelemetryDataCache.GetInstance(provider)); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(provider => ReduceSamplingService.GetInstance(configuration)); - services.AddTransient(); - services.AddTransient, ProcessMapPlanRepository>(); - services.AddTransient, ProcessMapPlanRepository>(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient, CrudWellRelatedRepositoryBase>(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient, ProcessMapPlanRepository>(); + services.AddTransient, ProcessMapPlanRepository>(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient, CrudWellRelatedRepositoryBase>(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient, CrudCacheRepositoryBase, CrudCacheRepositoryBase>(); services.AddTransient(); - // admin crud services: - services.AddTransient, CrudCacheRepositoryBase>(s => - new CrudCacheRepositoryBase( - s.GetRequiredService(), - s.GetRequiredService(), - dbSet => dbSet.Include(t => t.Well))); // может быть включен в сервис TelemetryService - services.AddTransient, CrudCacheRepositoryBase>(s => - new CrudCacheRepositoryBase( - s.GetRequiredService(), - s.GetRequiredService(), - dbSet => dbSet.Include(d => d.Clusters))); - services.AddTransient, CrudCacheRepositoryBase>(s => - new CrudCacheRepositoryBase( - s.GetRequiredService(), - s.GetRequiredService(), - dbSet => dbSet.Include(c => c.CompanyType))); + // admin crud services: + services.AddTransient, CrudCacheRepositoryBase>(s => + new CrudCacheRepositoryBase( + s.GetRequiredService(), + s.GetRequiredService(), + dbSet => dbSet.Include(t => t.Well))); // может быть включен в сервис TelemetryService + services.AddTransient, CrudCacheRepositoryBase>(s => + new CrudCacheRepositoryBase( + s.GetRequiredService(), + s.GetRequiredService(), + dbSet => dbSet.Include(d => d.Clusters))); + services.AddTransient, CrudCacheRepositoryBase>(s => + new CrudCacheRepositoryBase( + s.GetRequiredService(), + s.GetRequiredService(), + dbSet => dbSet.Include(c => c.CompanyType))); - services.AddTransient, CrudCacheRepositoryBase>(); - services.AddTransient, CrudCacheRepositoryBase>(s => - new CrudCacheRepositoryBase( - s.GetRequiredService(), - s.GetRequiredService(), - dbSet => dbSet - .Include(c => c.Wells) - .Include(c => c.Deposit))); // может быть включен в сервис ClusterService + services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient, CrudCacheRepositoryBase>(s => + new CrudCacheRepositoryBase( + s.GetRequiredService(), + s.GetRequiredService(), + dbSet => dbSet + .Include(c => c.Wells) + .Include(c => c.Deposit))); // может быть включен в сервис ClusterService - services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient, CrudCacheRepositoryBase>(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient, CrudCacheRepositoryBase>(); - // Subsystem service - services.AddTransient, CrudCacheRepositoryBase>(); - services.AddTransient(); + // Subsystem service + services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient(); - services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient, CrudCacheRepositoryBase>(); - // TelemetryData services - services.AddTransient(); - services.AddTransient, TelemetryDataSpinService>(); + // TelemetryData services + services.AddTransient(); + services.AddTransient, TelemetryDataSpinService>(); - // Wits - services.AddTransient, WitsRecordRepository>(); - services.AddTransient, WitsRecordRepository>(); - services.AddTransient, WitsRecordRepository>(); - services.AddTransient, WitsRecordRepository>(); - services.AddTransient, WitsRecordRepository>(); - services.AddTransient, WitsRecordRepository>(); + // Wits + services.AddTransient, WitsRecordRepository>(); + services.AddTransient, WitsRecordRepository>(); + services.AddTransient, WitsRecordRepository>(); + services.AddTransient, WitsRecordRepository>(); + services.AddTransient, WitsRecordRepository>(); + services.AddTransient, WitsRecordRepository>(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient, AutoGeneratedDailyReportMakerService>(); + services.AddTransient(); + services.AddTransient, DrillTestReportMakerService>(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient, CrudRepositoryBase>(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient, CrudRepositoryBase>(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient, WellOperationDefaultExcelParser>(); - services.AddTransient, WellOperationGazpromKhantosExcelParser>(); + services.AddTransient, WellOperationDefaultExcelParser>(); + services.AddTransient, WellOperationGazpromKhantosExcelParser>(); - return services; - } + return services; + } - public static IServiceCollection AddTransientLazy(this IServiceCollection services) - where TService : class - where TImplementation : class, TService - => services.AddTransient() - .AddTransient(provider => new Lazy(provider.GetRequiredService)); + public static IServiceCollection AddTransientLazy(this IServiceCollection services) + where TService : class + where TImplementation : class, TService + => services.AddTransient() + .AddTransient(provider => new Lazy(provider.GetRequiredService)); - public static IServiceCollection AddTransientLazy(this IServiceCollection services, Func implementationFactory) - where TService : class - where TImplementation : class, TService - => services.AddTransient(implementationFactory) - .AddTransient(provider => new Lazy(() => implementationFactory(provider))); + public static IServiceCollection AddTransientLazy(this IServiceCollection services, Func implementationFactory) + where TService : class + where TImplementation : class, TService + => services.AddTransient(implementationFactory) + .AddTransient(provider => new Lazy(() => implementationFactory(provider))); } diff --git a/AsbCloudInfrastructure/Repository/DrillTestRepository.cs b/AsbCloudInfrastructure/Repository/DrillTestRepository.cs index a308cb0b..e349db2c 100644 --- a/AsbCloudInfrastructure/Repository/DrillTestRepository.cs +++ b/AsbCloudInfrastructure/Repository/DrillTestRepository.cs @@ -1,7 +1,12 @@ using AsbCloudApp.Data.SAUB; using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; using AsbCloudDb.Model; using Mapster; +using Microsoft.EntityFrameworkCore; +using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -16,6 +21,44 @@ namespace AsbCloudInfrastructure.Repository this.db = db; } + public async Task GetAllAsync(int idTelemetry, FileReportRequest request, CancellationToken cancellationToken) + { + var query = db.DrillTests + .Where(d => d.IdTelemetry == idTelemetry) + .AsNoTracking(); + + if (request.GeDate.HasValue) + { + var startDate = new DateTime(request.GeDate.Value.Year, request.GeDate.Value.Month, request.GeDate.Value.Day); + query = query.Where(q => q.TimeStampStart >= startDate); + } + if (request.LeDate.HasValue) + { + var finishDate = new DateTime(request.LeDate.Value.Year, request.LeDate.Value.Month, request.LeDate.Value.Day); + query = query.Where(q => q.TimeStampStart <= finishDate); + } + + var entities = await query.ToListAsync(cancellationToken); + var dtos = entities.Select(e => e.Adapt()).ToArray(); + + return dtos; + } + + + public async Task GetAsync(int idTelemetry, int id, CancellationToken cancellationToken) + { + var drillTest = await db.DrillTests + .Where(d => d.IdTelemetry == idTelemetry) + .Where(d => d.Id == id) + .FirstOrDefaultAsync(cancellationToken); + + if (drillTest is null) + throw new Exception($"Drill test with id: {id} and idTelemetry: {idTelemetry} does not exist."); + + var dto = drillTest.Adapt(); + return dto; + } + public async Task SaveDataAsync(int idTelemetry, DrillTestDto dto, CancellationToken token) { var entity = dto.Adapt(); diff --git a/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportMakerService.cs b/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportMakerService.cs index 0f1c7076..8fee9b2c 100644 --- a/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportMakerService.cs +++ b/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportMakerService.cs @@ -11,8 +11,10 @@ using ClosedXML.Excel; namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports; -public class AutoGeneratedDailyReportMakerService : IAutoGeneratedDailyReportMakerService +public class AutoGeneratedDailyReportMakerService : IReportMakerService { + private readonly string templateName = "AutogeneratedDailyReportTemplate.xlsx"; + private readonly IEnumerable blockWriters = new List() { new HeadExcelBlockWriter(), @@ -20,10 +22,12 @@ public class AutoGeneratedDailyReportMakerService : IAutoGeneratedDailyReportMak new LimitingParameterExcelBlockWriter(), new TimeBalanceExcelBlockWriter() }; - - public async Task MakeReportAsync(AutoGeneratedDailyReportDto report, CancellationToken cancellationToken) + + public async Task MakeReportAsync(AutoGeneratedDailyReportDto report, CancellationToken cancellationToken) { - using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken); + using var excelTemplateStream = await Assembly + .GetExecutingAssembly() + .GetTemplateCopyStreamAsync(templateName, cancellationToken); using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled); @@ -35,22 +39,6 @@ public class AutoGeneratedDailyReportMakerService : IAutoGeneratedDailyReportMak return memoryStream; } - - private async Task GetExcelTemplateStreamAsync(CancellationToken cancellationToken) - { - var resourceName = Assembly.GetExecutingAssembly() - .GetManifestResourceNames() - .FirstOrDefault(n => n.EndsWith("AutogeneratedDailyReportTemplate.xlsx"))!; - - using var stream = Assembly.GetExecutingAssembly() - .GetManifestResourceStream(resourceName)!; - - var memoryStream = new MemoryStream(); - await stream.CopyToAsync(memoryStream, cancellationToken); - memoryStream.Position = 0; - - return memoryStream; - } private void AddToWorkbook(XLWorkbook workbook, AutoGeneratedDailyReportDto report) { diff --git a/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs b/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs index 03ed6e07..1ada2676 100644 --- a/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs +++ b/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs @@ -26,14 +26,14 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService private readonly ISubsystemOperationTimeService subsystemOperationTimeService; private readonly ICrudRepository subsystemRepository; private readonly ILimitingParameterService limitingParameterService; - private readonly IAutoGeneratedDailyReportMakerService autoGeneratedDailyReportMakerService; + private readonly IReportMakerService autoGeneratedDailyReportMakerService; public AutoGeneratedDailyReportService(IWellService wellService, IWellOperationRepository wellOperationRepository, ISubsystemOperationTimeService subsystemOperationTimeService, ICrudRepository subsystemRepository, ILimitingParameterService limitingParameterService, - IAutoGeneratedDailyReportMakerService autoGeneratedDailyReportMakerService) + IReportMakerService autoGeneratedDailyReportMakerService) { this.wellOperationRepository = wellOperationRepository; this.wellService = wellService; @@ -44,7 +44,7 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService } public async Task> GetListAsync(int idWell, - AutoGeneratedDailyReportRequest request, + FileReportRequest request, CancellationToken cancellationToken) { var result = new PaginationContainer @@ -67,19 +67,19 @@ public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService if (datesRange is null) return result; - if (request.StartDate.HasValue) + if (request.GeDate.HasValue) { - var startDate = new DateTime(request.StartDate.Value.Year, request.StartDate.Value.Month, - request.StartDate.Value.Day); + 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.FinishDate.HasValue) + if (request.LeDate.HasValue) { - var finishDate = new DateTime(request.FinishDate.Value.Year, request.FinishDate.Value.Month, - request.FinishDate.Value.Day); + 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; diff --git a/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportMakerService.cs b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportMakerService.cs new file mode 100644 index 00000000..68ad690f --- /dev/null +++ b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportMakerService.cs @@ -0,0 +1,89 @@ +using AsbCloudApp.Data.DrillTestReport; +using AsbCloudApp.Services.AutoGeneratedDailyReports; +using ClosedXML.Excel; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Services.DrillTestReport +{ + public class DrillTestReportMakerService : IReportMakerService + { + private readonly string templateName = "DrillTestReportTemplate.xlsx"; + private readonly string sheetName = "Лист1"; + private readonly int startRowNumber = 8; + + public async Task MakeReportAsync(DrillTestReportDataDto 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, DrillTestReportDataDto report) + { + var drillTestEntities = report.Data.Params; + if (!drillTestEntities.Any()) + return; + + var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetName) + ?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}."); + + sheet.Cell(4, 2).Value = report.Caption; + sheet.Cell(5, 2)._SetValue(report.Date, setAllBorders: false); + + var rowNumber = startRowNumber; + + var stepWithMaxDepthSpeed = drillTestEntities.OrderByDescending(p => p.DepthSpeed).FirstOrDefault()!.Step; + var startDepth = report.Data.DepthStart; + var startDate = report.Data.TimeStampStart; + + foreach (var drillTestEntity in drillTestEntities) + { + var endDepth = startDepth + (drillTestEntity.DepthDrillStep ?? 0); + var endDateTime = startDate.AddSeconds(drillTestEntity.TimeDrillStep ?? 0); + + sheet.Cell(rowNumber, 2).Value = startDepth; + + sheet.Cell(rowNumber, 3).Value = endDepth; + + sheet.Cell(rowNumber, 4).Value = drillTestEntity.DepthDrillStep; + + sheet.Cell(rowNumber, 5).Value = drillTestEntity.Workload; + + sheet.Cell(rowNumber, 6).Value = drillTestEntity.Speed; + + var cell = sheet.Cell(rowNumber, 7); + cell._SetValue(startDate.DateTime); + + cell = sheet.Cell(rowNumber, 8); + cell._SetValue(endDateTime.DateTime); + + sheet.Cell(rowNumber, 9).Value = drillTestEntity.TimeDrillStep; + + sheet.Cell(rowNumber, 10).Value = drillTestEntity.DepthSpeed; + + if (drillTestEntity.Step == stepWithMaxDepthSpeed) + { + var currentCells = sheet.Row(rowNumber).Cells(1, 10); + currentCells.Style.Fill.BackgroundColor = XLColor.Yellow; + } + + startDepth = endDepth; + startDate = endDateTime; + rowNumber++; + } + } + } +} diff --git a/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs new file mode 100644 index 00000000..a3d6074e --- /dev/null +++ b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs @@ -0,0 +1,103 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Data.DrillTestReport; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using AsbCloudApp.Services.AutoGeneratedDailyReports; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Services.DrillTestReport +{ + public class DrillTestReportService : IDrillTestReportService + { + private readonly IWellService wellService; + private readonly IDrillTestRepository drillTestRepository; + private readonly ITelemetryService telemetryService; + private readonly IReportMakerService drillTestReportMakerService; + + public DrillTestReportService( + IWellService wellService, + IDrillTestRepository drillTestRepository, + ITelemetryService telemetryService, + IReportMakerService drillTestReportMakerService) + { + this.wellService = wellService; + this.drillTestRepository = drillTestRepository; + this.telemetryService = telemetryService; + this.drillTestReportMakerService = drillTestReportMakerService; + } + + public async Task<(string fileName, Stream stream)> GenerateAsync(int idWell, int id, CancellationToken cancellationToken) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + if (telemetry is null) + throw new Exception($"Telemetry with idWell: {idWell} does not exist."); + + var dto = await drillTestRepository.GetAsync(telemetry.Id, id, cancellationToken); + + var timezone = telemetryService.GetTimezone(telemetry.Id); + var remoteDateTime = dto.TimeStampStart.ToRemoteDateTime(timezone.Hours); + dto.TimeStampStart = remoteDateTime; + + var cluster = telemetry.Info?.Cluster ?? "-"; + var deposit = telemetry.Info?.Deposit ?? "-"; + var wellCaption = wellService.GetOrDefault(idWell)!.Caption ?? "-"; + + + var report = new DrillTestReportDataDto() + { + Data = dto, + Caption = string.Format("Месторождение: {0}, куст: {1}, скважина: {2}", deposit, cluster, wellCaption), + Date = DateTime.Now, + }; + + var fileName = string.Format("Drill_test_{0}.xlsx", remoteDateTime.ToString("dd.mm.yyyy_HH_MM_ss")); + var stream = await drillTestReportMakerService.MakeReportAsync(report, cancellationToken); + + return (fileName, stream); + } + + + public async Task> GetListAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + if (telemetry is null) + throw new Exception($"Telemetry with idWell: {idWell} does not exist."); + + var result = new PaginationContainer + { + Skip = request.Skip ?? 0, + Take = request.Take ?? 10, + Items = Enumerable.Empty() + }; + + var reports = new List(); + var timezone = telemetryService.GetTimezone(telemetry.Id); + + var dtos = await drillTestRepository.GetAllAsync(telemetry.Id, request, cancellationToken); + foreach (var dto in dtos) + { + var remoteDateTime = dto.TimeStampStart.ToRemoteDateTime(timezone.Hours); + + reports.Add(new DrillTestReportInfoDto + { + FileName = string.Format("Drill_test_{0}", remoteDateTime), + DrillDepth = (dto.Params + .Where(p => p.DepthDrillStep.HasValue) + .Sum(x => x.DepthDrillStep) ?? 0) + dto.DepthStart, + DateTime = remoteDateTime, + Id = dto.Id, + }); + } + + result.Items = reports; + + return result; + } + } +} diff --git a/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportTemplate.xlsx b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportTemplate.xlsx new file mode 100644 index 00000000..5b9e8ec1 Binary files /dev/null and b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportTemplate.xlsx differ diff --git a/AsbCloudInfrastructure/XLExtentions.cs b/AsbCloudInfrastructure/XLExtentions.cs index c1a463d0..f7b1654b 100644 --- a/AsbCloudInfrastructure/XLExtentions.cs +++ b/AsbCloudInfrastructure/XLExtentions.cs @@ -92,12 +92,16 @@ internal static class XLExtentions } - internal static IXLCell _SetValue(this IXLCell cell, DateTime value, string dateFormat = "DD.MM.YYYY HH:MM:SS") + internal static IXLCell _SetValue(this IXLCell cell, DateTime value, string dateFormat = "DD.MM.YYYY HH:MM:SS", bool? setAllBorders = true) { cell.Value = value; - cell.Style - .SetAllBorders() - .Alignment.WrapText = true; + if (setAllBorders == true) + { + cell.Style + .SetAllBorders() + .Alignment.WrapText = true; + } + cell.Value = value; diff --git a/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs b/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs index de26e843..a392bf51 100644 --- a/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs +++ b/AsbCloudWebApi/Controllers/AutoGeneratedDailyReportController.cs @@ -25,7 +25,8 @@ public class AutoGeneratedDailyReportController : ControllerBase private readonly IAutoGeneratedDailyReportService autoGeneratedDailyReportService; private readonly IWellService wellService; - public AutoGeneratedDailyReportController(IAutoGeneratedDailyReportService autoGeneratedDailyReportService, + public AutoGeneratedDailyReportController( + IAutoGeneratedDailyReportService autoGeneratedDailyReportService, IWellService wellService) { this.autoGeneratedDailyReportService = autoGeneratedDailyReportService; @@ -66,7 +67,7 @@ public class AutoGeneratedDailyReportController : ControllerBase [HttpGet("all")] [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] public async Task GetListAsync([FromRoute][Required] int idWell, - [FromQuery] AutoGeneratedDailyReportRequest request, + [FromQuery] FileReportRequest request, CancellationToken cancellationToken) { if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) diff --git a/AsbCloudWebApi/Controllers/DrillTestsReportController.cs b/AsbCloudWebApi/Controllers/DrillTestsReportController.cs new file mode 100644 index 00000000..5f5f6b20 --- /dev/null +++ b/AsbCloudWebApi/Controllers/DrillTestsReportController.cs @@ -0,0 +1,84 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Data.AutogeneratedDailyReport; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System.ComponentModel.DataAnnotations; +using System.Net; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudWebApi.Controllers; + +/// +/// Контроллер для drill_test отчётов +/// +[ApiController] +[Route("api/well/{idWell}/[controller]")] +[Authorize] +public class DrillTestsReportController : ControllerBase +{ + private readonly IDrillTestReportService drillTestReportService; + private readonly IWellService wellService; + + public DrillTestsReportController(IDrillTestReportService drillTestReportService, + IWellService wellService) + { + this.drillTestReportService = drillTestReportService; + this.wellService = wellService; + } + + /// + /// Формирование отчёта + /// + /// Id скважины + /// Ключ entity test записи + /// + /// + [HttpGet] + [ProducesResponseType(typeof(PhysicalFileResult), (int)HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task GenerateReportAsync([FromRoute] int idWell, + [FromQuery] int id, + CancellationToken cancellationToken) + { + if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) + return Forbid(); + + var reportFile = await drillTestReportService.GenerateAsync(idWell, id, cancellationToken); + + return File(reportFile.stream, "application/octet-stream", reportFile.fileName); + } + + /// + /// Список файлов drill test отчётов + /// + /// Id скважины + /// Параметры запроса + /// + /// + [HttpGet("all")] + [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] + public async Task GetListAsync([FromRoute][Required] int idWell, + [FromQuery] FileReportRequest request, + CancellationToken cancellationToken) + { + if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) + return Forbid(); + + var reports = await drillTestReportService.GetListAsync(idWell, + request, + cancellationToken); + + return Ok(reports); + } + + private async Task CanUserAccessToWellAsync(int idWell, CancellationToken cancellationToken) + { + int? idCompany = User.GetCompanyId(); + return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, cancellationToken).ConfigureAwait(false); + } +} \ No newline at end of file