From 2334beb9714f42167b2b9d7993f80272c5e78bca Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Mon, 19 Sep 2022 15:55:53 +0500 Subject: [PATCH 01/37] =?UTF-8?q?#5996638=20=D0=9F=D0=BE=D0=B4=D1=81=D0=B2?= =?UTF-8?q?=D0=B5=D1=87=D0=B8=D0=B2=D0=B0=D1=82=D1=8C=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D0=BE=D0=BF=D1=82=D0=B8=D0=BC=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/DrillParamsDto.cs | 25 ++++++++ AsbCloudApp/Data/MinMaxDto.cs | 26 +++++++++ AsbCloudApp/Data/MinMaxExtendedViewDto.cs | 31 ++++++++++ .../Services/DrillParamsService.cs | 58 ++++++++++++++++++- 4 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 AsbCloudApp/Data/MinMaxDto.cs create mode 100644 AsbCloudApp/Data/MinMaxExtendedViewDto.cs diff --git a/AsbCloudApp/Data/DrillParamsDto.cs b/AsbCloudApp/Data/DrillParamsDto.cs index 0d667a58..76a39b71 100644 --- a/AsbCloudApp/Data/DrillParamsDto.cs +++ b/AsbCloudApp/Data/DrillParamsDto.cs @@ -42,6 +42,11 @@ namespace AsbCloudApp.Data /// public double AxialLoadMax { get; set; } + /// + /// axial load + /// + public MinMaxExtendedViewDto AxialLoad { get; set; } + /// /// pressure min. /// @@ -57,6 +62,11 @@ namespace AsbCloudApp.Data /// public double PressureMax { get; set; } + /// + /// pressure + /// + public MinMaxExtendedViewDto Pressure { get; set; } + /// /// rotor torque min. /// @@ -72,6 +82,11 @@ namespace AsbCloudApp.Data /// public double RotorTorqueMax { get; set; } + /// + /// rotor torque + /// + public MinMaxExtendedViewDto RotorTorque { get; set; } + /// /// rotor speed min. /// @@ -87,6 +102,11 @@ namespace AsbCloudApp.Data /// public double RotorSpeedMax { get; set; } + /// + /// rotor speed + /// + public MinMaxExtendedViewDto RotorSpeed { get; set; } + /// /// flow min. /// @@ -101,5 +121,10 @@ namespace AsbCloudApp.Data /// flow max. /// public double FlowMax { get; set; } + + /// + /// flow + /// + public MinMaxExtendedViewDto Flow { get; set; } } } \ No newline at end of file diff --git a/AsbCloudApp/Data/MinMaxDto.cs b/AsbCloudApp/Data/MinMaxDto.cs new file mode 100644 index 00000000..59ba90b0 --- /dev/null +++ b/AsbCloudApp/Data/MinMaxDto.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsbCloudApp.Data +{ +#nullable enable + /// + /// Минимальное и максимальное значение + /// + public class MinMaxDto + { + /// + /// Минимальное значение + /// + public double Min { get; set; } + + /// + /// максимальное значение + /// + public double Max { get; set; } + } +#nullable disable +} diff --git a/AsbCloudApp/Data/MinMaxExtendedViewDto.cs b/AsbCloudApp/Data/MinMaxExtendedViewDto.cs new file mode 100644 index 00000000..f3e91b88 --- /dev/null +++ b/AsbCloudApp/Data/MinMaxExtendedViewDto.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsbCloudApp.Data +{ +#nullable enable + /// + /// Расширение для класса MinMaxDto + /// + public class MinMaxExtendedViewDto : MinMaxDto + { + /// + /// Среднее значение + /// + public double Avg { get; set; } + + /// + /// Является максимальным + /// + public bool IsMax { get; set; } + + /// + /// Является минимальным + /// + public bool IsMin { get; set; } + } +#nullable disable +} diff --git a/AsbCloudInfrastructure/Services/DrillParamsService.cs b/AsbCloudInfrastructure/Services/DrillParamsService.cs index 1af54956..5eb813c8 100644 --- a/AsbCloudInfrastructure/Services/DrillParamsService.cs +++ b/AsbCloudInfrastructure/Services/DrillParamsService.cs @@ -4,6 +4,7 @@ using AsbCloudDb.Model; using AsbCloudInfrastructure.Repository; using Mapster; using Microsoft.EntityFrameworkCore; +using Org.BouncyCastle.Crypto; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -85,6 +86,16 @@ namespace AsbCloudInfrastructure.Services public async Task> GetCompositeAllAsync(int idWell, CancellationToken token = default) { + var allDrillParams = + await (from p in db.DrillParams + from c in db.WellComposites + where p.IdWell == c.IdWellSrc && + p.IdWellSectionType == c.IdWellSectionType + select p) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + var compositeWellDrillParams = await (from p in db.DrillParams from c in db.WellComposites @@ -98,7 +109,8 @@ namespace AsbCloudInfrastructure.Services var compositeDrillParamsDtos = compositeWellDrillParams.Adapt>(); - return compositeDrillParamsDtos; + var result = compositeDrillParamsDtos.Select(x => Convert(x, allDrillParams)); + return result; } public async Task InsertAsync(int idWell, DrillParamsDto dto, @@ -143,5 +155,49 @@ namespace AsbCloudInfrastructure.Services var result = await base.UpdateAsync(dto, token).ConfigureAwait(false); return result; } + + private static DrillParamsDto Convert(DrillParamsDto dto, IEnumerable drillParams) + { + return new DrillParamsDto + { + Id = dto.Id, + IdWellSectionType = dto.IdWellSectionType, + AxialLoad = GetMinMaxExtended(dto, drillParams.Select(x => (x.AxialLoadMin, x.AxialLoadMax))), + AxialLoadAvg = dto.AxialLoadAvg, + AxialLoadMax = dto.AxialLoadMax, + AxialLoadMin = dto.AxialLoadMin, + DepthEnd = dto.DepthEnd, + DepthStart = dto.DepthStart, + Flow = GetMinMaxExtended(dto, drillParams.Select(x => (x.FlowMin, x.FlowMax))), + FlowAvg = dto.FlowAvg, + FlowMax = dto.FlowMax, + FlowMin = dto.FlowMin, + IdWell = dto.IdWell, + Pressure = GetMinMaxExtended(dto, drillParams.Select(x => (x.PressureMin, x.PressureMax))), + PressureAvg = dto.PressureAvg, + PressureMax = dto.PressureMax, + PressureMin = dto.PressureMin, + RotorSpeed = GetMinMaxExtended(dto, drillParams.Select(x => (x.RotorSpeedMin, x.RotorSpeedMax))), + RotorSpeedAvg = dto.RotorSpeedAvg, + RotorSpeedMax = dto.RotorSpeedMax, + RotorSpeedMin = dto.RotorSpeedMin, + RotorTorque = GetMinMaxExtended(dto, drillParams.Select(x => (x.RotorTorqueMin, x.RotorTorqueMax))), + RotorTorqueAvg = dto.RotorTorqueAvg, + RotorTorqueMax = dto.RotorTorqueMax, + RotorTorqueMin = dto.RotorTorqueMin + }; + } + + private static MinMaxExtendedViewDto GetMinMaxExtended(DrillParamsDto x, IEnumerable<(double min, double max)> allDrillParams) + { + return new MinMaxExtendedViewDto + { + Avg = x.AxialLoadAvg, + Max = x.AxialLoadMax, + Min = x.AxialLoadMin, + IsMax = allDrillParams.Max(mx => mx.max) < x.AxialLoadMax, + IsMin = allDrillParams.Min(mn => mn.min) > x.AxialLoadMin + }; + } } } From c87acfdd59ab162392f2eb7a9a3800000f79948e Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Tue, 20 Sep 2022 09:47:54 +0500 Subject: [PATCH 02/37] =?UTF-8?q?#5996638=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D1=87=D0=B0=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/DrillParamsDto.cs | 84 +---------- AsbCloudApp/Data/MinMaxDto.cs | 8 +- AsbCloudApp/Data/MinMaxExtendedViewDto.cs | 2 +- .../Services/DrillParamsService.cs | 133 +++++++++--------- 4 files changed, 72 insertions(+), 155 deletions(-) diff --git a/AsbCloudApp/Data/DrillParamsDto.cs b/AsbCloudApp/Data/DrillParamsDto.cs index 76a39b71..d79f2451 100644 --- a/AsbCloudApp/Data/DrillParamsDto.cs +++ b/AsbCloudApp/Data/DrillParamsDto.cs @@ -13,115 +13,35 @@ namespace AsbCloudApp.Data public int IdWell { get; set; } /// - /// + /// /// - public double DepthStart { get; set; } - - /// - /// - /// - public double DepthEnd { get; set; } + public MinMaxDto Depth { get; set; } /// /// id well section type. /// public int IdWellSectionType { get; set; } - /// - /// axial load min. - /// - public double AxialLoadMin { get; set; } - - /// - /// axial load avg. - /// - public double AxialLoadAvg { get; set; } - - /// - /// axial load max. - /// - public double AxialLoadMax { get; set; } - /// /// axial load /// public MinMaxExtendedViewDto AxialLoad { get; set; } - /// - /// pressure min. - /// - public double PressureMin { get; set; } - - /// - /// pressure avg. - /// - public double PressureAvg { get; set; } - - /// - /// pressure max. - /// - public double PressureMax { get; set; } - /// /// pressure /// public MinMaxExtendedViewDto Pressure { get; set; } - /// - /// rotor torque min. - /// - public double RotorTorqueMin { get; set; } - - /// - /// rotor torque avg. - /// - public double RotorTorqueAvg { get; set; } - - /// - /// rotor torque max. - /// - public double RotorTorqueMax { get; set; } - /// /// rotor torque /// public MinMaxExtendedViewDto RotorTorque { get; set; } - /// - /// rotor speed min. - /// - public double RotorSpeedMin { get; set; } - - /// - /// rotor speed avg. - /// - public double RotorSpeedAvg { get; set; } - - /// - /// rotor speed max. - /// - public double RotorSpeedMax { get; set; } - /// /// rotor speed /// public MinMaxExtendedViewDto RotorSpeed { get; set; } - /// - /// flow min. - /// - public double FlowMin { get; set; } - - /// - /// flow avg. - /// - public double FlowAvg { get; set; } - - /// - /// flow max. - /// - public double FlowMax { get; set; } - /// /// flow /// diff --git a/AsbCloudApp/Data/MinMaxDto.cs b/AsbCloudApp/Data/MinMaxDto.cs index 59ba90b0..291574bc 100644 --- a/AsbCloudApp/Data/MinMaxDto.cs +++ b/AsbCloudApp/Data/MinMaxDto.cs @@ -10,17 +10,17 @@ namespace AsbCloudApp.Data /// /// Минимальное и максимальное значение /// - public class MinMaxDto + public class MinMaxDto { /// /// Минимальное значение /// - public double Min { get; set; } + public T? Min { get; set; } /// - /// максимальное значение + /// Максимальное значение /// - public double Max { get; set; } + public T? Max { get; set; } } #nullable disable } diff --git a/AsbCloudApp/Data/MinMaxExtendedViewDto.cs b/AsbCloudApp/Data/MinMaxExtendedViewDto.cs index f3e91b88..cb66e60d 100644 --- a/AsbCloudApp/Data/MinMaxExtendedViewDto.cs +++ b/AsbCloudApp/Data/MinMaxExtendedViewDto.cs @@ -10,7 +10,7 @@ namespace AsbCloudApp.Data /// /// Расширение для класса MinMaxDto /// - public class MinMaxExtendedViewDto : MinMaxDto + public class MinMaxExtendedViewDto : MinMaxDto { /// /// Среднее значение diff --git a/AsbCloudInfrastructure/Services/DrillParamsService.cs b/AsbCloudInfrastructure/Services/DrillParamsService.cs index 5eb813c8..d0f914d1 100644 --- a/AsbCloudInfrastructure/Services/DrillParamsService.cs +++ b/AsbCloudInfrastructure/Services/DrillParamsService.cs @@ -4,7 +4,6 @@ using AsbCloudDb.Model; using AsbCloudInfrastructure.Repository; using Mapster; using Microsoft.EntityFrameworkCore; -using Org.BouncyCastle.Crypto; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -12,6 +11,7 @@ using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services { +#nullable enable public class DrillParamsService : CrudServiceBase, IDrillParamsService { private readonly IAsbCloudDbContext db; @@ -40,28 +40,40 @@ namespace AsbCloudInfrastructure.Services select new DrillParamsDto() { IdWell = idWell, - DepthStart = startDepth, - DepthEnd = endDepth, + Depth = new MinMaxDto { + Min = endDepth, + Max = startDepth + }, IdWellSectionType = 0, - AxialLoadMin = g.Min(t => t.AxialLoad) ?? double.NaN, - AxialLoadAvg = g.Average(t => t.AxialLoad) ?? double.NaN, - AxialLoadMax = g.Max(t => t.AxialLoad) ?? double.NaN, - PressureMin = g.Min(t => t.Pressure) ?? double.NaN, - PressureAvg = g.Average(t => t.Pressure) ?? double.NaN, - PressureMax = g.Max(t => t.Pressure) ?? double.NaN, - RotorTorqueMin = g.Min(t => t.RotorTorque) ?? double.NaN, - RotorTorqueAvg = g.Average(t => t.RotorTorque) ?? double.NaN, - RotorTorqueMax = g.Max(t => t.RotorTorque) ?? double.NaN, - RotorSpeedMin = g.Min(t => t.RotorSpeed) ?? double.NaN, - RotorSpeedAvg = g.Average(t => t.RotorSpeed) ?? double.NaN, - RotorSpeedMax = g.Max(t => t.RotorSpeed) ?? double.NaN, - FlowMin = g.Min(t => t.Flow) ?? double.NaN, - FlowAvg = g.Min(t => t.Flow) ?? double.NaN, - FlowMax = g.Min(t => t.Flow) ?? double.NaN + AxialLoad = new MinMaxExtendedViewDto { + Min = g.Min(t => t.AxialLoad) ?? double.NaN, + Avg = g.Average(t => t.AxialLoad) ?? double.NaN, + Max = g.Max(t => t.AxialLoad) ?? double.NaN + }, + Pressure = new MinMaxExtendedViewDto { + Min = g.Min(t => t.Pressure) ?? double.NaN, + Avg = g.Average(t => t.Pressure) ?? double.NaN, + Max = g.Max(t => t.Pressure) ?? double.NaN + }, + RotorTorque = new MinMaxExtendedViewDto { + Min = g.Min(t => t.RotorTorque) ?? double.NaN, + Avg = g.Average(t => t.RotorTorque) ?? double.NaN, + Max = g.Max(t => t.RotorTorque) ?? double.NaN + }, + RotorSpeed = new MinMaxExtendedViewDto { + Min = g.Min(t => t.RotorSpeed) ?? double.NaN, + Avg = g.Average(t => t.RotorSpeed) ?? double.NaN, + Max = g.Max(t => t.RotorSpeed) ?? double.NaN + }, + Flow = new MinMaxExtendedViewDto { + Min = g.Min(t => t.Flow) ?? double.NaN, + Avg = g.Min(t => t.Flow) ?? double.NaN, + Max = g.Min(t => t.Flow) ?? double.NaN + } }) .AsNoTracking() .DefaultIfEmpty() - .OrderBy(t => t.AxialLoadMin) + .OrderBy(t => t.AxialLoad.Min) .FirstOrDefaultAsync(token) .ConfigureAwait(false); @@ -86,30 +98,26 @@ namespace AsbCloudInfrastructure.Services public async Task> GetCompositeAllAsync(int idWell, CancellationToken token = default) { - var allDrillParams = - await (from p in db.DrillParams - from c in db.WellComposites - where p.IdWell == c.IdWellSrc && - p.IdWellSectionType == c.IdWellSectionType - select p) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); + var allDrillParams = await db.WellComposites + .Join(db.DrillParams, + c => new { IdWell = c.IdWellSrc, IdSection = c.IdWellSectionType }, + p => new { IdWell = p.IdWell, IdSection = p.IdWellSectionType }, + (c, p) => p) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); - var compositeWellDrillParams = - await (from p in db.DrillParams - from c in db.WellComposites - where c.IdWell == idWell && - p.IdWell == c.IdWellSrc && - p.IdWellSectionType == c.IdWellSectionType - select p) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); + var compositeWellDrillParams = await db.WellComposites + .Where(c => c.IdWell == idWell) + .Join(db.DrillParams, + c => new { IdWell = c.IdWellSrc, IdSection = c.IdWellSectionType }, + p => new { IdWell = p.IdWell, IdSection = p.IdWellSectionType }, + (c, p) => p) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); - var compositeDrillParamsDtos = compositeWellDrillParams.Adapt>(); - - var result = compositeDrillParamsDtos.Select(x => Convert(x, allDrillParams)); + var result = compositeWellDrillParams.Select(x => Convert(x, allDrillParams)); return result; } @@ -156,39 +164,27 @@ namespace AsbCloudInfrastructure.Services return result; } - private static DrillParamsDto Convert(DrillParamsDto dto, IEnumerable drillParams) + private static DrillParamsDto Convert(DrillParams entity, IEnumerable drillParams) { return new DrillParamsDto { - Id = dto.Id, - IdWellSectionType = dto.IdWellSectionType, - AxialLoad = GetMinMaxExtended(dto, drillParams.Select(x => (x.AxialLoadMin, x.AxialLoadMax))), - AxialLoadAvg = dto.AxialLoadAvg, - AxialLoadMax = dto.AxialLoadMax, - AxialLoadMin = dto.AxialLoadMin, - DepthEnd = dto.DepthEnd, - DepthStart = dto.DepthStart, - Flow = GetMinMaxExtended(dto, drillParams.Select(x => (x.FlowMin, x.FlowMax))), - FlowAvg = dto.FlowAvg, - FlowMax = dto.FlowMax, - FlowMin = dto.FlowMin, - IdWell = dto.IdWell, - Pressure = GetMinMaxExtended(dto, drillParams.Select(x => (x.PressureMin, x.PressureMax))), - PressureAvg = dto.PressureAvg, - PressureMax = dto.PressureMax, - PressureMin = dto.PressureMin, - RotorSpeed = GetMinMaxExtended(dto, drillParams.Select(x => (x.RotorSpeedMin, x.RotorSpeedMax))), - RotorSpeedAvg = dto.RotorSpeedAvg, - RotorSpeedMax = dto.RotorSpeedMax, - RotorSpeedMin = dto.RotorSpeedMin, - RotorTorque = GetMinMaxExtended(dto, drillParams.Select(x => (x.RotorTorqueMin, x.RotorTorqueMax))), - RotorTorqueAvg = dto.RotorTorqueAvg, - RotorTorqueMax = dto.RotorTorqueMax, - RotorTorqueMin = dto.RotorTorqueMin + Id = entity.Id, + IdWellSectionType = entity.IdWellSectionType, + AxialLoad = GetMinMaxExtended(entity, drillParams.Select(x => (x.AxialLoadMin, x.AxialLoadMax))), + Depth = new MinMaxDto + { + Min = entity.DepthEnd, + Max = entity.DepthStart + }, + Flow = GetMinMaxExtended(entity, drillParams.Select(x => (x.FlowMin, x.FlowMax))), + IdWell = entity.IdWell, + Pressure = GetMinMaxExtended(entity, drillParams.Select(x => (x.PressureMin, x.PressureMax))), + RotorSpeed = GetMinMaxExtended(entity, drillParams.Select(x => (x.RotorSpeedMin, x.RotorSpeedMax))), + RotorTorque = GetMinMaxExtended(entity, drillParams.Select(x => (x.RotorTorqueMin, x.RotorTorqueMax))) }; } - private static MinMaxExtendedViewDto GetMinMaxExtended(DrillParamsDto x, IEnumerable<(double min, double max)> allDrillParams) + private static MinMaxExtendedViewDto GetMinMaxExtended(DrillParams x, IEnumerable<(double min, double max)> allDrillParams) { return new MinMaxExtendedViewDto { @@ -200,4 +196,5 @@ namespace AsbCloudInfrastructure.Services }; } } +#nullable disable } From 07eb1bd8784b46ceb1500eea0da46b6884619f3d Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Tue, 20 Sep 2022 10:52:57 +0500 Subject: [PATCH 03/37] =?UTF-8?q?#5996638=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D1=87=D0=B0=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/DrillParamsService.cs | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DrillParamsService.cs b/AsbCloudInfrastructure/Services/DrillParamsService.cs index d0f914d1..6dfc40f2 100644 --- a/AsbCloudInfrastructure/Services/DrillParamsService.cs +++ b/AsbCloudInfrastructure/Services/DrillParamsService.cs @@ -24,7 +24,7 @@ namespace AsbCloudInfrastructure.Services this.telemetryService = telemetryService; } - public async Task GetDefaultDrillParamsAsync(int idWell, + public async Task GetDefaultDrillParamsAsync(int idWell, double startDepth, double endDepth, CancellationToken token = default) { var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell); @@ -40,32 +40,38 @@ namespace AsbCloudInfrastructure.Services select new DrillParamsDto() { IdWell = idWell, - Depth = new MinMaxDto { + Depth = new MinMaxDto + { Min = endDepth, Max = startDepth }, IdWellSectionType = 0, - AxialLoad = new MinMaxExtendedViewDto { + AxialLoad = new MinMaxExtendedViewDto + { Min = g.Min(t => t.AxialLoad) ?? double.NaN, Avg = g.Average(t => t.AxialLoad) ?? double.NaN, Max = g.Max(t => t.AxialLoad) ?? double.NaN }, - Pressure = new MinMaxExtendedViewDto { + Pressure = new MinMaxExtendedViewDto + { Min = g.Min(t => t.Pressure) ?? double.NaN, Avg = g.Average(t => t.Pressure) ?? double.NaN, Max = g.Max(t => t.Pressure) ?? double.NaN }, - RotorTorque = new MinMaxExtendedViewDto { + RotorTorque = new MinMaxExtendedViewDto + { Min = g.Min(t => t.RotorTorque) ?? double.NaN, Avg = g.Average(t => t.RotorTorque) ?? double.NaN, Max = g.Max(t => t.RotorTorque) ?? double.NaN }, - RotorSpeed = new MinMaxExtendedViewDto { + RotorSpeed = new MinMaxExtendedViewDto + { Min = g.Min(t => t.RotorSpeed) ?? double.NaN, Avg = g.Average(t => t.RotorSpeed) ?? double.NaN, Max = g.Max(t => t.RotorSpeed) ?? double.NaN }, - Flow = new MinMaxExtendedViewDto { + Flow = new MinMaxExtendedViewDto + { Min = g.Min(t => t.Flow) ?? double.NaN, Avg = g.Min(t => t.Flow) ?? double.NaN, Max = g.Min(t => t.Flow) ?? double.NaN @@ -170,31 +176,27 @@ namespace AsbCloudInfrastructure.Services { Id = entity.Id, IdWellSectionType = entity.IdWellSectionType, - AxialLoad = GetMinMaxExtended(entity, drillParams.Select(x => (x.AxialLoadMin, x.AxialLoadMax))), - Depth = new MinMaxDto - { + AxialLoad = GetMinMaxExtended(entity.AxialLoadAvg, entity.AxialLoadMax, entity.AxialLoadMin, drillParams.Select(x => (x.AxialLoadMin, x.AxialLoadMax))), + Depth = new MinMaxDto { Min = entity.DepthEnd, Max = entity.DepthStart }, - Flow = GetMinMaxExtended(entity, drillParams.Select(x => (x.FlowMin, x.FlowMax))), + Flow = GetMinMaxExtended(entity.FlowAvg, entity.FlowMax, entity.FlowMin, drillParams.Select(x => (x.FlowMin, x.FlowMax))), IdWell = entity.IdWell, - Pressure = GetMinMaxExtended(entity, drillParams.Select(x => (x.PressureMin, x.PressureMax))), - RotorSpeed = GetMinMaxExtended(entity, drillParams.Select(x => (x.RotorSpeedMin, x.RotorSpeedMax))), - RotorTorque = GetMinMaxExtended(entity, drillParams.Select(x => (x.RotorTorqueMin, x.RotorTorqueMax))) + Pressure = GetMinMaxExtended(entity.PressureAvg, entity.PressureMax, entity.PressureMin, drillParams.Select(x => (x.PressureMin, x.PressureMax))), + RotorSpeed = GetMinMaxExtended(entity.RotorSpeedAvg, entity.RotorSpeedMax, entity.RotorSpeedMin, drillParams.Select(x => (x.RotorSpeedMin, x.RotorSpeedMax))), + RotorTorque = GetMinMaxExtended(entity.RotorTorqueAvg, entity.RotorTorqueMax, entity.RotorTorqueMin, drillParams.Select(x => (x.RotorTorqueMin, x.RotorTorqueMax))) }; } - private static MinMaxExtendedViewDto GetMinMaxExtended(DrillParams x, IEnumerable<(double min, double max)> allDrillParams) - { - return new MinMaxExtendedViewDto - { - Avg = x.AxialLoadAvg, - Max = x.AxialLoadMax, - Min = x.AxialLoadMin, - IsMax = allDrillParams.Max(mx => mx.max) < x.AxialLoadMax, - IsMin = allDrillParams.Min(mn => mn.min) > x.AxialLoadMin - }; - } + private static MinMaxExtendedViewDto GetMinMaxExtended(double avg, double max, double min, IEnumerable<(double min, double max)> allDrillParams) + => new MinMaxExtendedViewDto { + Avg = avg, + Max = max, + Min = min, + IsMax = allDrillParams.Any(mx => mx.max > max), + IsMin = allDrillParams.Any(mn => mn.min < min) + }; } #nullable disable } From ed5f181754d1c9dc87fd529a6bdccac0e8c23c80 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 20 Sep 2022 12:29:55 +0500 Subject: [PATCH 04/37] =?UTF-8?q?#5996638=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D1=81=D0=B0=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=20=D0=B1=D1=83=D1=80=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=B2=D1=81=D0=B5=D1=85=20=D1=81=D0=B5?= =?UTF-8?q?=D0=BA=D1=86=D0=B8=D0=B9=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=B7?= =?UTF-8?q?=D0=B8=D1=82=D0=BD=D0=BE=D0=B9=20=D1=81=D0=BA=D0=B2=D0=B0=D0=B6?= =?UTF-8?q?=D0=B8=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/DrillParamsService.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DrillParamsService.cs b/AsbCloudInfrastructure/Services/DrillParamsService.cs index 6dfc40f2..bc488e6e 100644 --- a/AsbCloudInfrastructure/Services/DrillParamsService.cs +++ b/AsbCloudInfrastructure/Services/DrillParamsService.cs @@ -104,21 +104,26 @@ namespace AsbCloudInfrastructure.Services public async Task> GetCompositeAllAsync(int idWell, CancellationToken token = default) { - var allDrillParams = await db.WellComposites + var allDrillParamsQuery = db.WellComposites + .Where(c => c.IdWell == idWell) .Join(db.DrillParams, - c => new { IdWell = c.IdWellSrc, IdSection = c.IdWellSectionType }, - p => new { IdWell = p.IdWell, IdSection = p.IdWellSectionType }, - (c, p) => p) + c => c.IdWellSrc, + p => p.IdWell, + (c, p) => p); + + var allDrillParams = await allDrillParamsQuery .AsNoTracking() .ToListAsync(token) .ConfigureAwait(false); - var compositeWellDrillParams = await db.WellComposites + var compositeWellDrillParamsQuery = db.WellComposites .Where(c => c.IdWell == idWell) .Join(db.DrillParams, c => new { IdWell = c.IdWellSrc, IdSection = c.IdWellSectionType }, p => new { IdWell = p.IdWell, IdSection = p.IdWellSectionType }, - (c, p) => p) + (c, p) => p); + + var compositeWellDrillParams = await compositeWellDrillParamsQuery .AsNoTracking() .ToListAsync(token) .ConfigureAwait(false); From df5c98838d80247eb170662a86d98140880585b2 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 20 Sep 2022 15:09:01 +0500 Subject: [PATCH 05/37] Fix DrillParamsService.GetAllAsync(..) --- .../Services/DrillParamsService.cs | 51 ++++++++++++------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DrillParamsService.cs b/AsbCloudInfrastructure/Services/DrillParamsService.cs index bc488e6e..a081bdd9 100644 --- a/AsbCloudInfrastructure/Services/DrillParamsService.cs +++ b/AsbCloudInfrastructure/Services/DrillParamsService.cs @@ -89,16 +89,31 @@ namespace AsbCloudInfrastructure.Services public async Task> GetAllAsync(int idWell, CancellationToken token = default) { - var entities = await (from p in db.DrillParams - where p.IdWell == idWell - orderby p.Id - select p) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); + var entities = await db.DrillParams + .Where(p => p.IdWell == idWell) + .OrderBy(p=> p.Id) + .AsNoTracking() + .ToArrayAsync(token) + .ConfigureAwait(false); - var dto = entities.Adapt>(); - return dto; + var dtos = entities.Select(p => + { + var dto = new DrillParamsDto + { + IdWell = p.IdWell, + Id = p.Id, + IdWellSectionType = p.IdWellSectionType, + Depth = new MinMaxDto { Max = p.PressureMax, Min = p.PressureMin }, + Pressure = MakeMinMaxExtended(p.PressureAvg, p.PressureMax, p.PressureMin), + AxialLoad = MakeMinMaxExtended(p.AxialLoadAvg, p.AxialLoadMax, p.AxialLoadMin), + Flow = MakeMinMaxExtended(p.FlowAvg, p.FlowMax, p.FlowMin), + RotorSpeed = MakeMinMaxExtended(p.RotorSpeedAvg, p.RotorSpeedMax, p.RotorSpeedMin), + RotorTorque = MakeMinMaxExtended(p.RotorTorqueAvg, p.RotorTorqueMax, p.RotorTorqueMin) + }; + return dto; + }); + + return dtos; } public async Task> GetCompositeAllAsync(int idWell, @@ -181,27 +196,27 @@ namespace AsbCloudInfrastructure.Services { Id = entity.Id, IdWellSectionType = entity.IdWellSectionType, - AxialLoad = GetMinMaxExtended(entity.AxialLoadAvg, entity.AxialLoadMax, entity.AxialLoadMin, drillParams.Select(x => (x.AxialLoadMin, x.AxialLoadMax))), + AxialLoad = MakeMinMaxExtended(entity.AxialLoadAvg, entity.AxialLoadMax, entity.AxialLoadMin, drillParams.Select(x => (x.AxialLoadMin, x.AxialLoadMax))), Depth = new MinMaxDto { Min = entity.DepthEnd, Max = entity.DepthStart }, - Flow = GetMinMaxExtended(entity.FlowAvg, entity.FlowMax, entity.FlowMin, drillParams.Select(x => (x.FlowMin, x.FlowMax))), + Flow = MakeMinMaxExtended(entity.FlowAvg, entity.FlowMax, entity.FlowMin, drillParams.Select(x => (x.FlowMin, x.FlowMax))), IdWell = entity.IdWell, - Pressure = GetMinMaxExtended(entity.PressureAvg, entity.PressureMax, entity.PressureMin, drillParams.Select(x => (x.PressureMin, x.PressureMax))), - RotorSpeed = GetMinMaxExtended(entity.RotorSpeedAvg, entity.RotorSpeedMax, entity.RotorSpeedMin, drillParams.Select(x => (x.RotorSpeedMin, x.RotorSpeedMax))), - RotorTorque = GetMinMaxExtended(entity.RotorTorqueAvg, entity.RotorTorqueMax, entity.RotorTorqueMin, drillParams.Select(x => (x.RotorTorqueMin, x.RotorTorqueMax))) + Pressure = MakeMinMaxExtended(entity.PressureAvg, entity.PressureMax, entity.PressureMin, drillParams.Select(x => (x.PressureMin, x.PressureMax))), + RotorSpeed = MakeMinMaxExtended(entity.RotorSpeedAvg, entity.RotorSpeedMax, entity.RotorSpeedMin, drillParams.Select(x => (x.RotorSpeedMin, x.RotorSpeedMax))), + RotorTorque = MakeMinMaxExtended(entity.RotorTorqueAvg, entity.RotorTorqueMax, entity.RotorTorqueMin, drillParams.Select(x => (x.RotorTorqueMin, x.RotorTorqueMax))) }; } - private static MinMaxExtendedViewDto GetMinMaxExtended(double avg, double max, double min, IEnumerable<(double min, double max)> allDrillParams) + private static MinMaxExtendedViewDto MakeMinMaxExtended(double avg, double max, double min, IEnumerable<(double min, double max)>? allDrillParams = null) => new MinMaxExtendedViewDto { Avg = avg, Max = max, Min = min, - IsMax = allDrillParams.Any(mx => mx.max > max), - IsMin = allDrillParams.Any(mn => mn.min < min) - }; + IsMax = allDrillParams?.Any(mx => mx.max > max) ?? false, + IsMin = allDrillParams?.Any(mn => mn.min < min) ?? false + }; } #nullable disable } From 67e4913c846237c47f7a707df4ce9d682e152055 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Wed, 21 Sep 2022 09:41:01 +0500 Subject: [PATCH 06/37] =?UTF-8?q?#5908066=20=D0=A1=D1=83=D1=82=D0=BE=D1=87?= =?UTF-8?q?=D0=BD=D1=8B=D0=B9=20=D1=80=D0=B0=D0=BF=D0=BE=D1=80=D1=82.=20?= =?UTF-8?q?=D0=91=D0=BB=D0=BE=D0=BA=20=D0=9A=D0=9D=D0=91=D0=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/DailyReport/DailyReportDto.cs | 4 +++- .../Services/DailyReport/DailyReportService.cs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/AsbCloudApp/Data/DailyReport/DailyReportDto.cs b/AsbCloudApp/Data/DailyReport/DailyReportDto.cs index c47b8934..781a6717 100644 --- a/AsbCloudApp/Data/DailyReport/DailyReportDto.cs +++ b/AsbCloudApp/Data/DailyReport/DailyReportDto.cs @@ -1,5 +1,6 @@ namespace AsbCloudApp.Data.DailyReport { +#nullable enable /// /// Блоки для формирования суточного рапорта /// @@ -13,7 +14,7 @@ /// /// блок КНБК /// - public BhaDto Bha { get; set; } = new(); + public BhaDto? Bha { get; set; } = new(); /// /// блок безметражные работы @@ -35,4 +36,5 @@ /// public SignDto Sign { get; set; } = new(); } +#nullable disable } diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs index 1c30ba0b..ecdd7d15 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs @@ -124,10 +124,26 @@ namespace AsbCloudInfrastructure.Services.DailyReport ClusterName = well?.Cluster ?? "", }, TimeBalance = await MakeTimeBalanceAsync(idWell, date, token), + Bha = await GetPrevBhaAsync(idWell, date, token) }; return dto; } + private async Task GetPrevBhaAsync(int idWell, DateTime date, CancellationToken token) + { + var dateOffset = date.Date; + var entity = await db.DailyReports + .OrderByDescending(x => x.StartDate) + .FirstOrDefaultAsync(r => r.IdWell == idWell && + r.StartDate.Year <= dateOffset.Year && + r.StartDate.DayOfYear <= dateOffset.DayOfYear, token); + + if (entity is null) + return null; + var dto = Convert(entity); + return dto?.Bha; + } + private async Task MakeTimeBalanceAsync(int idWell, DateTime date, CancellationToken token) { var stat = await detectedOperationService.GetOperationsStatAsync(new DetectedOperationRequest From 6cac72259c39fca0c81c3855f91e2c353cd33ca3 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Wed, 21 Sep 2022 12:56:18 +0500 Subject: [PATCH 07/37] =?UTF-8?q?#5908066=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/DailyReport/DailyReportDto.cs | 2 +- .../Services/DailyReport/DailyReportService.cs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AsbCloudApp/Data/DailyReport/DailyReportDto.cs b/AsbCloudApp/Data/DailyReport/DailyReportDto.cs index 781a6717..920aeb54 100644 --- a/AsbCloudApp/Data/DailyReport/DailyReportDto.cs +++ b/AsbCloudApp/Data/DailyReport/DailyReportDto.cs @@ -14,7 +14,7 @@ /// /// блок КНБК /// - public BhaDto? Bha { get; set; } = new(); + public BhaDto Bha { get; set; } = new(); /// /// блок безметражные работы diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs index ecdd7d15..807b10ca 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs @@ -124,24 +124,24 @@ namespace AsbCloudInfrastructure.Services.DailyReport ClusterName = well?.Cluster ?? "", }, TimeBalance = await MakeTimeBalanceAsync(idWell, date, token), - Bha = await GetPrevBhaAsync(idWell, date, token) + Bha = await GetPrevOrNewBhaAsync(idWell, date, token) }; return dto; } - private async Task GetPrevBhaAsync(int idWell, DateTime date, CancellationToken token) + private async Task GetPrevOrNewBhaAsync(int idWell, DateTime date, CancellationToken token) { var dateOffset = date.Date; var entity = await db.DailyReports + .Where(x => x.IdWell == idWell) .OrderByDescending(x => x.StartDate) - .FirstOrDefaultAsync(r => r.IdWell == idWell && - r.StartDate.Year <= dateOffset.Year && - r.StartDate.DayOfYear <= dateOffset.DayOfYear, token); + .FirstOrDefaultAsync(r => r.StartDate <= dateOffset, token); if (entity is null) - return null; + return new BhaDto(); + var dto = Convert(entity); - return dto?.Bha; + return dto.Bha; } private async Task MakeTimeBalanceAsync(int idWell, DateTime date, CancellationToken token) From c924b957acd65b3275c98f02d14e4427d031bdfa Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Fri, 23 Sep 2022 11:03:50 +0500 Subject: [PATCH 08/37] =?UTF-8?q?#6008377=20=D0=9E=D1=88=D0=B8=D0=B1=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=B2=20=D0=B2=D1=8B=D0=B4=D0=B0=D1=87=D0=B5=20=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BF=D0=BE=20=D0=A1=D0=90?= =?UTF-8?q?=D0=A3=D0=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/SAUB/TelemetryDataBaseService.cs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs index c8983361..ebfe6822 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs @@ -134,25 +134,6 @@ namespace AsbCloudInfrastructure.Services.SAUB if (fullDataCount > 1.75 * approxPointsCount) { var m = (int)Math.Round(1d * fullDataCount / approxPointsCount); - - switch (m) - { - //case var i when i <= 1: // тут для полноты, но никогда не сработает из-за условия выше - // break; - case var i when i < 10: - query = query.Where((d) => d.DateTime.Second % m == 0); - break; - case var i when i < 30: - query = query.Where((d) => (d.DateTime.Minute * 60 + d.DateTime.Second) % m == 0); - break; - case var i when i < 600: - query = query.Where((d) => ((d.DateTime.Hour * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0); - break; - default: - query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0); - break; - } - if (m > 1) query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0); } From 863749cfe1daf70496afdb3da69c1e2dfbdae0d2 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Wed, 28 Sep 2022 10:46:12 +0500 Subject: [PATCH 09/37] =?UTF-8?q?##6539681=20=D0=A4=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=D1=8B=D0=B9=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Services/IFileService.cs | 72 +---- AsbCloudInfrastructure/DependencyInjection.cs | 1 + .../Repository/FileRepository.cs | 275 +++++++++++++++++ .../Repository/IFileRepository.cs | 120 ++++++++ .../DrillingProgram/DrillingProgramService.cs | 12 +- .../Services/FileService.cs | 276 ++---------------- .../Services/ReportService.cs | 7 +- .../Services/WellFinalDocumentsService.cs | 10 +- AsbCloudWebApi/Controllers/FileController.cs | 39 ++- 9 files changed, 476 insertions(+), 336 deletions(-) create mode 100644 AsbCloudInfrastructure/Repository/FileRepository.cs create mode 100644 AsbCloudInfrastructure/Repository/IFileRepository.cs diff --git a/AsbCloudApp/Services/IFileService.cs b/AsbCloudApp/Services/IFileService.cs index 18d0829d..6b1a171f 100644 --- a/AsbCloudApp/Services/IFileService.cs +++ b/AsbCloudApp/Services/IFileService.cs @@ -31,23 +31,6 @@ namespace AsbCloudApp.Services /// Task SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token = default); - /// - /// Получить список файлов в контейнере - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - Task> GetInfosAsync(int idWell, - int idCategory, string companyName = default, string fileName = default, DateTime begin = default, DateTime end = default, - int skip = 0, int take = 32, CancellationToken token = default); - /// /// Инфо о файле /// @@ -57,24 +40,6 @@ namespace AsbCloudApp.Services Task GetInfoAsync(int idFile, CancellationToken token); - /// - /// Пометить файл как удаленный - /// - /// - /// - /// - Task MarkAsDeletedAsync(int idFile, - CancellationToken token = default); - - /// - /// Получить файлы определенной категории - /// - /// - /// - /// - /// - Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token = default); - /// /// удалить файл /// @@ -103,7 +68,7 @@ namespace AsbCloudApp.Services /// /// /// - string GetUrl(int idFile); + Task GetUrl(int idFile); /// /// получить путь для скачивания @@ -115,15 +80,6 @@ namespace AsbCloudApp.Services /// string GetUrl(int idWell, int idCategory, int idFile, string dotExtention); - /// - /// добавить метку на файл - /// - /// - /// - /// - /// - Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token); - /// /// пометить метку файла как удаленную /// @@ -143,22 +99,6 @@ namespace AsbCloudApp.Services /// /// Task MoveAsync(int idWell, int? idUser, int idCategory, string destinationFileName, string srcFileFullName, CancellationToken token = default); - - /// - /// получить инфо о файле по метке - /// - /// - /// - /// - Task GetByMarkId(int idMark, CancellationToken token); - - /// - /// пометить метки файлов как удаленные - /// - /// - /// - /// - Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token); /// /// Инфо о файле @@ -166,14 +106,6 @@ namespace AsbCloudApp.Services /// /// /// - Task> GetInfoByIdsAsync(List idsFile, CancellationToken token); - - /// - /// Получение файлов по скважине - /// - /// - /// - /// - Task> GetInfosByWellIdAsync(int idWell, CancellationToken token); + Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token); } } diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 04e707f6..e86a314b 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -106,6 +106,7 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/AsbCloudInfrastructure/Repository/FileRepository.cs b/AsbCloudInfrastructure/Repository/FileRepository.cs new file mode 100644 index 00000000..efa6296a --- /dev/null +++ b/AsbCloudInfrastructure/Repository/FileRepository.cs @@ -0,0 +1,275 @@ +using AsbCloudApp.Data; +using AsbCloudDb.Model; +using Mapster; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Repository +{ + public class FileRepository : IFileRepository + { + private readonly IQueryable dbSetConfigured; + private readonly IAsbCloudDbContext db; + + public FileRepository(IAsbCloudDbContext db) + { + this.db = db; + this.dbSetConfigured = db.Files + .Include(f => f.Author) + .ThenInclude(u => u.Company) + .ThenInclude(c => c.CompanyType) + .Include(f => f.FileMarks) + .ThenInclude(m => m.User) + .Include(f => f.Well); + } + + public async Task AddAsync(int idWell, int? idUser, int idCategory, + string destinationFileName, long fileSize, CancellationToken token = default) + { + var fileInfo = new AsbCloudDb.Model.FileInfo() + { + IdWell = idWell, + IdAuthor = idUser, + IdCategory = idCategory, + Name = destinationFileName, + UploadDate = DateTime.UtcNow, + IsDeleted = false, + Size = fileSize, + }; + + var entry = db.Files.Add(fileInfo); + await db.SaveChangesAsync(token).ConfigureAwait(false); + return entry.Entity.Id; + } + + public async Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token) + { + var entities = await dbSetConfigured + .Where(e => e.IdWell == idWell && e.IdCategory == idCategory && e.IsDeleted == false) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + + var dtos = entities.Select(e => Convert(e)); + return dtos; + } + + public async Task> GetInfosAsync(int idWell, + int idCategory, string companyName = default, string fileName = default, DateTime begin = default, + DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default) + { + var query = dbSetConfigured + .Where(e => e.IdWell == idWell && + e.IdCategory == idCategory && + !e.IsDeleted); + + if (!string.IsNullOrEmpty(companyName)) + query = query.Where(e => (e.Author == null) || + (e.Author.Company == null) || + e.Author.Company.Caption.Contains(companyName)); + + if (!string.IsNullOrEmpty(fileName)) + query = query.Where(e => e.Name.ToLower().Contains(fileName.ToLower())); + + var firstFile = await query.FirstOrDefaultAsync(token); + if (firstFile is null) + return new PaginationContainer() + { + Skip = skip, + Take = take, + Count = 0, + }; + + var timezoneOffset = firstFile.Well.Timezone?.Hours ?? 5; + + if (begin != default) + { + var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); + query = query.Where(e => e.UploadDate >= beginUtc); + } + + if (end != default) + { + var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); + query = query.Where(e => e.UploadDate <= endUtc); + } + + var count = await query.CountAsync(token).ConfigureAwait(false); + + var result = new PaginationContainer(count) + { + Skip = skip, + Take = take, + Count = count, + }; + + if (count <= skip) + return result; + + query = query.OrderBy(e => e.UploadDate); + + if (skip > 0) + query = query.Skip(skip); + query = query.Take(take); + + var entities = await query + .Take(take).AsNoTracking().ToListAsync(token) + .ConfigureAwait(false); + + var dtos = entities.Select(e => Convert(e, timezoneOffset)); + result.Items.AddRange(dtos); + return result; + } + + public async Task GetInfoAsync(int idFile, CancellationToken token) + { + var entity = await dbSetConfigured + .AsNoTracking() + .FirstOrDefaultAsync(f => f.Id == idFile, token) + .ConfigureAwait(false); + + if (entity is null) + { + throw new FileNotFoundException($"fileId:{idFile} not found"); + } + + var dto = Convert(entity); + return dto; + } + + public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) + { + var result = new List(); + + var entities = await dbSetConfigured + .AsNoTracking() + .Where(f => idsFile.Contains(f.Id)) + .ToListAsync(token) + .ConfigureAwait(false); + + foreach (var entity in entities) + { + if (entity is null) + { + throw new FileNotFoundException($"fileId:{entity.Id} not found"); + } + result.Add(Convert(entity)); + } + + return result; + } + + public async Task MarkAsDeletedAsync(int idFile, CancellationToken token = default) + { + var fileInfo = await db.Files.FirstOrDefaultAsync(f => f.Id == idFile, token).ConfigureAwait(false); + + if (fileInfo is null) + return 0; + + fileInfo.IsDeleted = true; + + return await db.SaveChangesAsync(token).ConfigureAwait(false); + } + + public async Task> DeleteAsync(IEnumerable ids, CancellationToken token) + { + var filesQuery = db.Files + .Where(f => ids.Contains(f.Id)); + + var files = await filesQuery.ToListAsync(token); + + var filesDtos = files.Select(x => new FileInfoDto { + Id = x.Id, + IdWell = x.Id, + IdCategory = x.IdCategory, + Name = x.Name + }); + + db.Files.RemoveRange(filesQuery); + await db.SaveChangesAsync(token).ConfigureAwait(false); + + return filesDtos; + } + + public async Task GetByMarkId(int idMark, + CancellationToken token) + { + var entity = await dbSetConfigured + .FirstOrDefaultAsync(f => f.FileMarks.Any(m => m.Id == idMark), token) + .ConfigureAwait(false); + + FileInfoDto dto = Convert(entity); + return dto; + } + + public async Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) + { + var fileMark = await db.FileMarks + .FirstOrDefaultAsync(m => m.IdFile == fileMarkDto.IdFile && + m.IdMarkType == fileMarkDto.IdMarkType && + m.IdUser == idUser && + m.IsDeleted == false, + token) + .ConfigureAwait(false); + + if (fileMark is not null) + return 0; + + var newFileMark = fileMarkDto.Adapt(); + newFileMark.Id = default; + newFileMark.DateCreated = DateTime.UtcNow; + newFileMark.IdUser = idUser; + newFileMark.User = null; + + db.FileMarks.Add(newFileMark); + return await db.SaveChangesAsync(token); + } + + public async Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) + { + var fileMarkQuery = db.FileMarks + .Where(m => idsMarks.Contains(m.Id)); + + foreach (var fileMark in fileMarkQuery) + fileMark.IsDeleted = true; + + return await db.SaveChangesAsync(token); + } + + public async Task> GetInfosByWellIdAsync(int idWell, CancellationToken token) + { + var entities = await dbSetConfigured + .Where(e => e.IdWell == idWell && e.IsDeleted == false) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + + var dtos = entities.Select(e => Convert(e)); + return dtos; + } + + private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity) + { + var timezoneOffset = entity.Well.Timezone?.Hours ?? 5; + return Convert(entity, timezoneOffset); + } + + private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity, double timezoneOffset) + { + var dto = entity.Adapt(); + dto.UploadDate = entity.UploadDate.ToRemoteDateTime(timezoneOffset); + dto.FileMarks = entity.FileMarks.Select(m => + { + var mark = m.Adapt(); + mark.DateCreated = m.DateCreated.ToRemoteDateTime(timezoneOffset); + return mark; + }); + return dto; + } + } +} diff --git a/AsbCloudInfrastructure/Repository/IFileRepository.cs b/AsbCloudInfrastructure/Repository/IFileRepository.cs new file mode 100644 index 00000000..73ae9b86 --- /dev/null +++ b/AsbCloudInfrastructure/Repository/IFileRepository.cs @@ -0,0 +1,120 @@ +using AsbCloudApp.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Repository +{ + /// + /// Сервис доступа к файлам + /// + public interface IFileRepository + { + /// + /// Добавление, в БД, информации о файле + /// + /// + /// + /// + /// + /// + /// + /// + Task AddAsync(int idWell, int? idUser, int idCategory, + string destinationFileName, long fileSize, CancellationToken token = default); + + /// + /// Получить файлы определенной категории + /// + /// + /// + /// + /// + Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token); + + /// + /// Получить список файлов в контейнере + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + Task> GetInfosAsync(int idWell, + int idCategory, string companyName = default, string fileName = default, DateTime begin = default, + DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default); + + /// + /// Инфо о файле + /// + /// + /// + /// + Task GetInfoAsync(int idFile, CancellationToken token); + + /// + /// Пометить файл как удаленный + /// + /// + /// + /// + Task MarkAsDeletedAsync(int idFile, CancellationToken token = default); + + /// + /// удалить файлы + /// + /// + /// + /// + Task> DeleteAsync(IEnumerable ids, CancellationToken token); + + /// + /// получить инфо о файле по метке + /// + /// + /// + /// + Task GetByMarkId(int idMark, CancellationToken token); + + /// + /// добавить метку на файл + /// + /// + /// + /// + /// + Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token); + + /// + /// Инфо о файлах + /// + /// + /// + /// + Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token); + + /// + /// пометить метки файлов как удаленные + /// + /// + /// + /// + Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token); + + /// + /// Получение файлов по скважине + /// + /// + /// + /// + Task> GetInfosByWellIdAsync(int idWell, CancellationToken token); + } +} diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index 5fbc7301..c1973c11 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -2,6 +2,7 @@ using AsbCloudApp.Exceptions; using AsbCloudApp.Services; using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; using Mapster; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -22,6 +23,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram private readonly IFileService fileService; private readonly IUserService userService; private readonly IWellService wellService; + private readonly IFileRepository fileRepository; private readonly IConfiguration configuration; private readonly IBackgroundWorkerService backgroundWorker; private readonly IEmailService emailService; @@ -52,6 +54,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram IFileService fileService, IUserService userService, IWellService wellService, + IFileRepository fileRepository, IConfiguration configuration, IBackgroundWorkerService backgroundWorker, IEmailService emailService) @@ -60,6 +63,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram this.fileService = fileService; this.userService = userService; this.wellService = wellService; + this.fileRepository = fileRepository; this.configuration = configuration; this.backgroundWorker = backgroundWorker; this.connectionString = configuration.GetConnectionString("DefaultConnection"); @@ -308,9 +312,9 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram .Select(m => m.Id); if (oldMarksIds?.Any() == true) - await fileService.MarkFileMarkAsDeletedAsync(oldMarksIds, token); + await fileRepository.MarkFileMarkAsDeletedAsync(oldMarksIds, token); - var result = await fileService.CreateFileMarkAsync(fileMarkDto, idUser, token) + var result = await fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token) .ConfigureAwait(false); if (fileMarkDto.IdMarkType == idMarkTypeReject) @@ -340,7 +344,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram public async Task MarkAsDeletedFileMarkAsync(int idMark, CancellationToken token) { - var fileInfo = await fileService.GetByMarkId(idMark, token) + var fileInfo = await fileRepository.GetByMarkId(idMark, token) .ConfigureAwait(false); if (fileInfo.IdCategory < idFileCategoryDrillingProgramPartsStart || @@ -479,7 +483,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram .UseNpgsql(connectionString) .Options; using var context = new AsbCloudDbContext(contextOptions); - var fileService = new FileService(context); + var fileService = new FileService(fileRepository); var files = state.Parts.Select(p => fileService.GetUrl(p.File)); DrillingProgramMaker.UniteExcelFiles(files, tempResultFilePath, state.Parts, well); await fileService.MoveAsync(idWell, null, idFileCategoryDrillingProgram, resultFileName, tempResultFilePath, token); diff --git a/AsbCloudInfrastructure/Services/FileService.cs b/AsbCloudInfrastructure/Services/FileService.cs index 947fd853..c30fd23b 100644 --- a/AsbCloudInfrastructure/Services/FileService.cs +++ b/AsbCloudInfrastructure/Services/FileService.cs @@ -2,6 +2,7 @@ using AsbCloudApp.Exceptions; using AsbCloudApp.Services; using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; using Mapster; using Microsoft.EntityFrameworkCore; using System; @@ -16,21 +17,12 @@ namespace AsbCloudInfrastructure.Services public class FileService : IFileService { public string RootPath { get; private set; } + private readonly IFileRepository fileRepository; - private readonly IQueryable dbSetConfigured; - private readonly IAsbCloudDbContext db; - - public FileService(IAsbCloudDbContext db) + public FileService(IFileRepository fileRepository) { RootPath = "files"; - this.db = db; - dbSetConfigured = db.Files - .Include(f => f.Author) - .ThenInclude(u => u.Company) - .ThenInclude(c => c.CompanyType) - .Include(f => f.FileMarks) - .ThenInclude(m => m.User) - .Include(f => f.Well); + this.fileRepository = fileRepository; } public async Task MoveAsync(int idWell, int? idUser, int idCategory, @@ -44,45 +36,23 @@ namespace AsbCloudInfrastructure.Services var sysFileInfo = new System.IO.FileInfo(srcFilePath); //save info to db - var fileInfo = new AsbCloudDb.Model.FileInfo() - { - IdWell = idWell, - IdAuthor = idUser, - IdCategory = idCategory, - Name = destinationFileName, - UploadDate = DateTime.UtcNow, - IsDeleted = false, - Size = sysFileInfo.Length, - }; - - var entry = db.Files.Add(fileInfo); - await db.SaveChangesAsync(token).ConfigureAwait(false); - var fileId = entry.Entity.Id; + var fileId = await fileRepository.AddAsync(idWell, idUser, idCategory, destinationFileName, sysFileInfo.Length, token) + .ConfigureAwait(false); + string filePath = MakeFilePath(idWell, idCategory, destinationFileName, fileId); Directory.CreateDirectory(Path.GetDirectoryName(filePath)); File.Move(srcFilePath, filePath); - return await GetInfoAsync(entry.Entity.Id, token); + return await GetInfoAsync(fileId, token); } public async Task SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token) { //save info to db - var fileInfo = new AsbCloudDb.Model.FileInfo() - { - IdWell = idWell, - IdAuthor = idUser, - IdCategory = idCategory, - Name = Path.GetFileName(fileFullName), - UploadDate = DateTime.UtcNow, - IsDeleted = false, - Size = fileStream?.Length ?? 0 - }; + var fileId = await fileRepository.AddAsync(idWell, idUser, idCategory, Path.GetFileName(fileFullName), fileStream?.Length ?? 0, token) + .ConfigureAwait(false); - var entry = db.Files.Add(fileInfo); - await db.SaveChangesAsync(token).ConfigureAwait(false); - var fileId = entry.Entity.Id; //save stream to disk string filePath = MakeFilePath(idWell, idCategory, fileFullName, fileId); @@ -91,7 +61,7 @@ namespace AsbCloudInfrastructure.Services using var newfileStream = new FileStream(filePath, FileMode.Create); await fileStream.CopyToAsync(newfileStream, token).ConfigureAwait(false); - return await GetInfoAsync(entry.Entity.Id, token); + return await GetInfoAsync(fileId, token); } private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) @@ -100,125 +70,23 @@ namespace AsbCloudInfrastructure.Services $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); } - public async Task> GetInfosByCategoryAsync(int idWell, - int idCategory, CancellationToken token) - { - var entities = await dbSetConfigured - .Where(e => e.IdWell == idWell && e.IdCategory == idCategory && e.IsDeleted == false) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); - - var dtos = entities.Select(e => Convert(e)); - return dtos; - } - - public async Task> GetInfosAsync(int idWell, - int idCategory, string companyName = default, string fileName = default, DateTime begin = default, - DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default) - { - var query = dbSetConfigured - .Where(e => e.IdWell == idWell && - e.IdCategory == idCategory && - !e.IsDeleted); - - if (!string.IsNullOrEmpty(companyName)) - query = query.Where(e => (e.Author == null) || - (e.Author.Company == null) || - e.Author.Company.Caption.Contains(companyName)); - - if (!string.IsNullOrEmpty(fileName)) - query = query.Where(e => e.Name.ToLower().Contains(fileName.ToLower())); - - var firstFile = await query.FirstOrDefaultAsync(token); - if (firstFile is null) - return new PaginationContainer() - { - Skip = skip, - Take = take, - Count = 0, - }; - - var timezoneOffset = firstFile.Well.Timezone?.Hours ?? 5; - - if (begin != default) - { - var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); - query = query.Where(e => e.UploadDate >= beginUtc); - } - - if (end != default) - { - var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); - query = query.Where(e => e.UploadDate <= endUtc); - } - - var count = await query.CountAsync(token).ConfigureAwait(false); - - var result = new PaginationContainer(count) - { - Skip = skip, - Take = take, - Count = count, - }; - - if (count <= skip) - return result; - - query = query.OrderBy(e => e.UploadDate); - - if (skip > 0) - query = query.Skip(skip); - query = query.Take(take); - - var entities = await query - .Take(take).AsNoTracking().ToListAsync(token) - .ConfigureAwait(false); - - var dtos = entities.Select(e => Convert(e, timezoneOffset)); - result.Items.AddRange(dtos); - return result; - } - public async Task GetInfoAsync(int idFile, CancellationToken token) { - var entity = await dbSetConfigured - .AsNoTracking() - .FirstOrDefaultAsync(f => f.Id == idFile, token) - .ConfigureAwait(false); + var dto = await fileRepository.GetInfoAsync(idFile, token).ConfigureAwait(false); - if (entity is null) - { - throw new FileNotFoundException($"fileId:{idFile} not found"); - } + var ext = Path.GetExtension(dto.Name); - var ext = Path.GetExtension(entity.Name); - - var relativePath = GetUrl(entity.IdWell, entity.IdCategory, entity.Id, ext); + var relativePath = GetUrl(dto.IdWell, dto.IdCategory, dto.Id, ext); var fullPath = Path.GetFullPath(relativePath); if (!File.Exists(fullPath)) { throw new FileNotFoundException("not found", relativePath); } - var dto = Convert(entity); return dto; } - public async Task MarkAsDeletedAsync(int idFile, - CancellationToken token = default) - { - var fileInfo = await db.Files.FirstOrDefaultAsync(f => f.Id == idFile, token).ConfigureAwait(false); - - if (fileInfo is null) - return 0; - - fileInfo.IsDeleted = true; - - return await db.SaveChangesAsync(token).ConfigureAwait(false); - } - public Task DeleteAsync(int idFile, CancellationToken token) => DeleteAsync(new int[] { idFile }, token); @@ -227,10 +95,7 @@ namespace AsbCloudInfrastructure.Services if (ids is null || !ids.Any()) return 0; - var filesQuery = db.Files - .Where(f => ids.Contains(f.Id)); - - var files = await filesQuery.ToListAsync(token); + var files = await fileRepository.DeleteAsync(ids, token).ConfigureAwait(false); if (files is null || !files.Any()) return 0; @@ -242,18 +107,12 @@ namespace AsbCloudInfrastructure.Services File.Delete(fileName); } - db.Files.RemoveRange(filesQuery); - - return await db.SaveChangesAsync(token).ConfigureAwait(false); + return files.Any() ? 1 : 0; } - public string GetUrl(int idFile) + public async Task GetUrl(int idFile) { - var fileInfo = db.Files - .FirstOrDefault(f => f.Id == idFile); - - if (fileInfo is null) - return null; + var fileInfo = await fileRepository.GetInfoAsync(idFile, CancellationToken.None).ConfigureAwait(false); return GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); } @@ -264,116 +123,27 @@ namespace AsbCloudInfrastructure.Services public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) => Path.Combine(RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); - public async Task GetByMarkId(int idMark, - CancellationToken token) - { - var entity = await dbSetConfigured - .FirstOrDefaultAsync(f => f.FileMarks.Any(m => m.Id == idMark), token) - .ConfigureAwait(false); - - FileInfoDto dto = Convert(entity); - return dto; - } - - private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity) - { - var timezoneOffset = entity.Well.Timezone?.Hours ?? 5; - return Convert(entity, timezoneOffset); - } - - private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity, double timezoneOffset) - { - var dto = entity.Adapt(); - dto.UploadDate = entity.UploadDate.ToRemoteDateTime(timezoneOffset); - dto.FileMarks = entity.FileMarks.Select(m => - { - var mark = m.Adapt(); - mark.DateCreated = m.DateCreated.ToRemoteDateTime(timezoneOffset); - return mark; - }); - return dto; - } - public async Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) - { - var fileMark = await db.FileMarks - .FirstOrDefaultAsync(m => m.IdFile == fileMarkDto.IdFile && - m.IdMarkType == fileMarkDto.IdMarkType && - m.IdUser == idUser && - m.IsDeleted == false, - token) - .ConfigureAwait(false); - - if (fileMark is not null) - return 0; - - var newFileMark = fileMarkDto.Adapt(); - newFileMark.Id = default; - newFileMark.DateCreated = DateTime.UtcNow; - newFileMark.IdUser = idUser; - newFileMark.User = null; - - db.FileMarks.Add(newFileMark); - return await db.SaveChangesAsync(token); - } - public Task MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token) - => MarkFileMarkAsDeletedAsync(new int[] { idMark }, token); + => fileRepository.MarkFileMarkAsDeletedAsync(new int[] { idMark }, token); - public async Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, - CancellationToken token) + public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) { - var fileMarkQuery = db.FileMarks - .Where(m => idsMarks.Contains(m.Id)); + var result = await fileRepository.GetInfoByIdsAsync(idsFile, token).ConfigureAwait(false); - foreach (var fileMark in fileMarkQuery) - fileMark.IsDeleted = true; - - return await db.SaveChangesAsync(token); - } - - public async Task> GetInfoByIdsAsync(List idsFile, CancellationToken token) - { - var result = new List(); - - var entities = await dbSetConfigured - .AsNoTracking() - .Where(f => idsFile.Contains(f.Id)) - .ToListAsync(token) - .ConfigureAwait(false); - - foreach (var entity in entities) + foreach (var entity in result) { - if (entity is null) - { - throw new FileNotFoundException($"fileId:{entity.Id} not found"); - } - + var ext = Path.GetExtension(entity.Name); - var relativePath = GetUrl(entity.IdWell, entity.IdCategory, entity.Id, ext); var fullPath = Path.GetFullPath(relativePath); if (!File.Exists(fullPath)) { throw new FileNotFoundException("not found", relativePath); } - - result.Add(Convert(entity)); } return result; } - - public async Task> GetInfosByWellIdAsync(int idWell, CancellationToken token) - { - var entities = await dbSetConfigured - .Where(e => e.IdWell == idWell && e.IsDeleted == false) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); - - var dtos = entities.Select(e => Convert(e)); - return dtos; - } } } diff --git a/AsbCloudInfrastructure/Services/ReportService.cs b/AsbCloudInfrastructure/Services/ReportService.cs index 3c70915b..6265f6c6 100644 --- a/AsbCloudInfrastructure/Services/ReportService.cs +++ b/AsbCloudInfrastructure/Services/ReportService.cs @@ -1,6 +1,7 @@ using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; using AsbSaubReport; using Mapster; using Microsoft.EntityFrameworkCore; @@ -21,15 +22,17 @@ namespace AsbCloudInfrastructure.Services private readonly ITelemetryService telemetryService; private readonly IWellService wellService; private readonly IBackgroundWorkerService backgroundWorkerService; + private readonly IFileRepository fileRepository; public ReportService(IAsbCloudDbContext db, IConfiguration configuration, - ITelemetryService telemetryService, IWellService wellService, IBackgroundWorkerService backgroundWorkerService) + ITelemetryService telemetryService, IWellService wellService, IBackgroundWorkerService backgroundWorkerService, IFileRepository fileRepository) { this.db = db; this.connectionString = configuration.GetConnectionString("DefaultConnection"); this.wellService = wellService; this.backgroundWorkerService = backgroundWorkerService; this.telemetryService = telemetryService; + this.fileRepository = fileRepository; ReportCategoryId = db.FileCategories.AsNoTracking() .FirstOrDefault(c => c.Name.Equals("Рапорт")).Id; @@ -65,7 +68,7 @@ namespace AsbCloudInfrastructure.Services }; generator.Make(reportFileName); - var fileService = new FileService(context); + var fileService = new FileService(fileRepository); var fileInfo = await fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName, token); progressHandler.Invoke(new diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs index 3885d0e3..dc90128c 100644 --- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs +++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs @@ -2,6 +2,7 @@ using AsbCloudApp.Exceptions; using AsbCloudApp.Services; using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; using Mapster; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -27,6 +28,7 @@ namespace AsbCloudInfrastructure.Services private readonly IConfiguration configuration; private readonly IEmailService emailService; private readonly IFileCategoryService fileCategoryService; + private readonly IFileRepository fileRepository; private const int FileServiceThrewException = -1; @@ -36,7 +38,8 @@ namespace AsbCloudInfrastructure.Services IWellService wellService, IConfiguration configuration, IEmailService emailService, - IFileCategoryService fileCategoryService) + IFileCategoryService fileCategoryService, + IFileRepository fileRepository) { this.context = context; this.fileService = fileService; @@ -45,6 +48,7 @@ namespace AsbCloudInfrastructure.Services this.configuration = configuration; this.emailService = emailService; this.fileCategoryService = fileCategoryService; + this.fileRepository = fileRepository; } public async Task UpdateRangeAsync(int idWell, IEnumerable? dtos, CancellationToken token) @@ -94,7 +98,7 @@ namespace AsbCloudInfrastructure.Services var categoriesIds = entitiesGroups .Select(g => g.Key); - var files = (await fileService + var files = (await fileRepository .GetInfosByWellIdAsync(idWell, token) .ConfigureAwait(false)) .Where(f => categoriesIds.Contains(f.IdCategory)) @@ -161,7 +165,7 @@ namespace AsbCloudInfrastructure.Services public async Task GetFilesHistoryByIdCategory(int idWell, int idCategory, CancellationToken token) { - var files = await fileService.GetInfosByCategoryAsync(idWell, idCategory, token).ConfigureAwait(false); + var files = await fileRepository.GetInfosByCategoryAsync(idWell, idCategory, token).ConfigureAwait(false); return new WellFinalDocumentsHistoryDto { IdWell = idWell, diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index 46f9d589..52b314f3 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -1,5 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Services; +using AsbCloudInfrastructure.Repository; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -20,11 +21,13 @@ namespace AsbCloudWebApi.Controllers { private readonly IFileService fileService; private readonly IWellService wellService; + private readonly IFileRepository fileRepository; - public FileController(IFileService fileService, IWellService wellService) + public FileController(IFileService fileService, IWellService wellService, IFileRepository fileRepository) { this.fileService = fileService; this.wellService = wellService; + this.fileRepository = fileRepository; } /// @@ -98,7 +101,7 @@ namespace AsbCloudWebApi.Controllers idWell, token).ConfigureAwait(false)) return Forbid(); - var filesInfo = await fileService.GetInfosAsync(idWell, idCategory, + var filesInfo = await fileRepository.GetInfosAsync(idWell, idCategory, companyName, fileName, begin, end, skip, take, token).ConfigureAwait(false); return Ok(filesInfo); @@ -168,7 +171,7 @@ namespace AsbCloudWebApi.Controllers if (!userService.HasPermission((int)idUser, $"File.edit{file.IdCategory}")) return Forbid(); - var result = await fileService.MarkAsDeletedAsync(idFile, token); + var result = await fileRepository.MarkAsDeletedAsync(idFile, token); return Ok(result); } @@ -193,7 +196,7 @@ namespace AsbCloudWebApi.Controllers idWell, token).ConfigureAwait(false)) return Forbid(); - var result = await fileService.CreateFileMarkAsync(markDto, (int)idUser, token) + var result = await fileRepository.CreateFileMarkAsync(markDto, (int)idUser, token) .ConfigureAwait(false); return Ok(result); @@ -223,5 +226,33 @@ namespace AsbCloudWebApi.Controllers return Ok(result); } + + /// + /// Возвращает информацию о файле + /// + /// id запрашиваемого файла + /// Токен отмены задачи + /// Запрашиваемый файл + [HttpGet] + [Route("/api/files/{idFile}")] + [Permission] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + public async Task GetFileInfoByIdAsync([FromRoute] int idFile, CancellationToken token = default) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + try + { + var fileInfo = await fileRepository.GetInfoAsync(idFile, token).ConfigureAwait(false); + return Ok(fileInfo); + } + catch (FileNotFoundException ex) + { + return NotFound(ex.FileName); + } + } } } From ead3e860bae92386d5bb8d3eeb058093f2d350ba Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Wed, 28 Sep 2022 11:17:33 +0500 Subject: [PATCH 10/37] =?UTF-8?q?#6539681=20=D0=A4=D0=B0=D0=B9=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2=D1=8B=D0=B9=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudWebApi/Controllers/FileController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index 52b314f3..b75f71f4 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -236,7 +236,7 @@ namespace AsbCloudWebApi.Controllers [HttpGet] [Route("/api/files/{idFile}")] [Permission] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(FileInfoDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetFileInfoByIdAsync([FromRoute] int idFile, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); From 90026f95d3b29e8bb6de5bb7299df9febb1b0301 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 28 Sep 2022 14:51:47 +0500 Subject: [PATCH 11/37] =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=84=D0=B8=D0=B3=D1=83=D1=80=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8=20=D0=B8=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=B7=D1=83=D0=B5=D1=82=D1=81=D1=8F=20=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=BA=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=20pg=20=D1=81=20=D0=B1?= =?UTF-8?q?=D0=BE=D0=BB=D0=B5=D0=B5=20=D0=BF=D0=BE=D0=B4=D1=80=D0=BE=D0=B1?= =?UTF-8?q?=D0=BD=D1=8B=D0=BC=D0=B8=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudInfrastructure/DependencyInjection.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 04e707f6..35f5f3e2 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -82,8 +82,12 @@ namespace AsbCloudInfrastructure public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration) { MapsterSetup(); + var connectionStringName = "DefaultConnection"; +#if DEBUG + connectionStringName = "DebugConnection"; +#endif services.AddDbContext(options => - options.UseNpgsql(configuration.GetConnectionString("DefaultConnection"))); + options.UseNpgsql(configuration.GetConnectionString(connectionStringName))); services.AddFluentValidation(); From 6e31d29784a76384ec2931af7739d55a821289b3 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 28 Sep 2022 14:52:45 +0500 Subject: [PATCH 12/37] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE=D0=B2=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=BD=D0=BE=D0=BC=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B8=20WITS=20=D1=82=D0=B5=D0=BB=D0=B5=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D1=80=D0=B8=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repository/WitsRecordRepository.cs | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/AsbCloudInfrastructure/Repository/WitsRecordRepository.cs b/AsbCloudInfrastructure/Repository/WitsRecordRepository.cs index 1be9a7de..0c750c6b 100644 --- a/AsbCloudInfrastructure/Repository/WitsRecordRepository.cs +++ b/AsbCloudInfrastructure/Repository/WitsRecordRepository.cs @@ -66,17 +66,33 @@ namespace AsbCloudInfrastructure.Repository return new TDto[] { Convert(data, timezoneHours) }; } - public Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token) + public async Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token) { if (dtos?.Any() != true) - return Task.CompletedTask; + return; var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; var entities = dtos .DistinctBy(d => d.DateTime) .Select(dto => Convert(dto, idTelemetry, timezoneHours)); - dbset.AddRange(entities); - return db.SaveChangesAsync(token); + + var dateMin = entities.Min(e => e.DateTime); + var dateMax = entities.Max(e => e.DateTime); + var existingEntities = await dbset + .Where(e => e.IdTelemetry == idTelemetry) + .Where(e => e.DateTime >= dateMin && e.DateTime <= dateMax) + .Select(e => new { e.DateTime, e.IdTelemetry}) + .ToArrayAsync(token); + + foreach (var entity in entities) + { + if (existingEntities.Any(e=>e.IdTelemetry == entity.IdTelemetry && e.DateTime == entity.DateTime)) + dbset.Update(entity); + else + dbset.Add(entity); + } + + await db.SaveChangesAsync(token); } private static TEntity Convert(TDto dto, int idTelemetry, double timezoneHours) From b3004dead7289ec7795cef4b7c9ca277186be6bb Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 28 Sep 2022 14:54:47 +0500 Subject: [PATCH 13/37] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BF=D1=80=D0=BE=D1=84=D0=B8=D0=BB=D0=B8?= =?UTF-8?q?=20=D0=BF=D1=83=D0=B1=D0=BB=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 +++--- .../PublishProfiles/PubLinux.pubxml | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml diff --git a/.gitignore b/.gitignore index d65f82ed..fc614d65 100644 --- a/.gitignore +++ b/.gitignore @@ -174,13 +174,13 @@ publish/ *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj +# *.pubxml +# *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted -PublishScripts/ +# PublishScripts/ # NuGet Packages *.nupkg diff --git a/AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml b/AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml new file mode 100644 index 00000000..9ca6d0f0 --- /dev/null +++ b/AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml @@ -0,0 +1,21 @@ + + + + + true + false + true + Release + Any CPU + FileSystem + bin\publishLinux\ + FileSystem + + net6.0 + a2768702-47cb-4127-941c-e339d5efcffe + true + linux-x64 + + \ No newline at end of file From 88f229359785d64eb8b7725774b61fbeeec74204 Mon Sep 17 00:00:00 2001 From: eugeniy_ivanov Date: Thu, 29 Sep 2022 12:29:10 +0500 Subject: [PATCH 14/37] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=D1=8B=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BD=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=8F=D1=87=D0=B5?= =?UTF-8?q?=D0=B5=D0=BA=20=D0=BE=D1=82=D0=BD=D0=BE=D1=81=D0=B8=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D0=BE=20=D1=81=D0=BE=D0=B4=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=B8=D0=BC=D0=BE=D0=B3=D0=BE=20=D0=B2=20=D1=81=D1=83=D1=82?= =?UTF-8?q?=D0=BE=D1=87=D0=BD=D0=BE=D0=BC=20=D1=80=D0=B0=D0=BF=D0=BE=D1=80?= =?UTF-8?q?=D1=82=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/DailyReport/DailyReportMakerExcel.cs | 4 +++- .../Services/DailyReport/XLExtentions.cs | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportMakerExcel.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportMakerExcel.cs index d5e9728a..a54a8e90 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportMakerExcel.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportMakerExcel.cs @@ -44,7 +44,9 @@ namespace AsbCloudInfrastructure.Services.DailyReport timeBalance.Draw(sheet); blockDimensionless.Draw(sheet); blockSaub.Draw(sheet); - blockSign.Draw(sheet); + blockSign.Draw(sheet); + //sheet.Columns().AdjustToContents(); // Adjust column width + sheet.Rows().AdjustToContents(); } } } diff --git a/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs b/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs index ff079b14..5297b0e1 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs @@ -10,12 +10,12 @@ namespace AsbCloudInfrastructure.Services.DailyReport var mergedRange = range.Merge(); mergedRange.FirstCell()._SetValue(value); var colWidth = mergedRange.FirstCell().WorksheetColumn().Width; - var maxCharsToWrap = colWidth / (0.05d * mergedRange.FirstCell().Style.Font.FontSize); + var maxCharsToWrap = colWidth / (0.1d * mergedRange.FirstCell().Style.Font.FontSize); if (value is string valueString && valueString.Length > maxCharsToWrap) { var row = mergedRange.FirstCell().WorksheetRow(); var baseHeight = row.Height; - row.Height = 0.45d * baseHeight * Math.Ceiling(1d + valueString.Length / maxCharsToWrap); + row.Height = 0.5d * baseHeight * Math.Ceiling(1d + valueString.Length / maxCharsToWrap); } mergedRange.Style.SetAllBorders() .Alignment.SetWrapText(true); @@ -59,7 +59,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport { var row = cell.WorksheetRow(); var baseHeight = row.Height; - row.Height = 0.52d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap); + row.Height = 0.5d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap); } } @@ -80,7 +80,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport { var row = cell.WorksheetRow(); var baseHeight = row.Height; - row.Height = 0.52d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap); + row.Height = 0.5d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap); } } From 219f409aa69d210f82d75cd5bde70590c7187862 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 29 Sep 2022 17:56:59 +0500 Subject: [PATCH 15/37] SubsystemOperationTimeService.CalcStat() limit kUsage. --- .../Services/Subsystems/SubsystemOperationTimeService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs b/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs index 8fbc75df..18566010 100644 --- a/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs +++ b/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs @@ -145,8 +145,8 @@ namespace AsbCloudInfrastructure.Services.Subsystems SumDepthInterval = periodGroupDepth, OperationCount = g.Count() }; - if(subsystemStat.KUsage > 100) - subsystemStat.KUsage = 100; + if(subsystemStat.KUsage > 1) + subsystemStat.KUsage = 1; return subsystemStat; }); From f9e566cfef77f772813448f6c41427df9f5ccaa5 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Fri, 30 Sep 2022 10:49:40 +0500 Subject: [PATCH 16/37] =?UTF-8?q?#6539681=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services}/IFileRepository.cs | 27 +--- AsbCloudApp/Services/IFileService.cs | 42 ++++++ .../Repository/FileRepository.cs | 124 +++++++++++------- .../Services/FileService.cs | 44 ++++++- AsbCloudWebApi/Controllers/FileController.cs | 15 +-- 5 files changed, 167 insertions(+), 85 deletions(-) rename {AsbCloudInfrastructure/Repository => AsbCloudApp/Services}/IFileRepository.cs (79%) diff --git a/AsbCloudInfrastructure/Repository/IFileRepository.cs b/AsbCloudApp/Services/IFileRepository.cs similarity index 79% rename from AsbCloudInfrastructure/Repository/IFileRepository.cs rename to AsbCloudApp/Services/IFileRepository.cs index 73ae9b86..e01891cc 100644 --- a/AsbCloudInfrastructure/Repository/IFileRepository.cs +++ b/AsbCloudApp/Services/IFileRepository.cs @@ -1,31 +1,16 @@ using AsbCloudApp.Data; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudApp.Services { /// /// Сервис доступа к файлам /// - public interface IFileRepository + public interface IFileRepository : ICrudService { - /// - /// Добавление, в БД, информации о файле - /// - /// - /// - /// - /// - /// - /// - /// - Task AddAsync(int idWell, int? idUser, int idCategory, - string destinationFileName, long fileSize, CancellationToken token = default); - /// /// Получить файлы определенной категории /// @@ -52,14 +37,6 @@ namespace AsbCloudInfrastructure.Repository int idCategory, string companyName = default, string fileName = default, DateTime begin = default, DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default); - /// - /// Инфо о файле - /// - /// - /// - /// - Task GetInfoAsync(int idFile, CancellationToken token); - /// /// Пометить файл как удаленный /// diff --git a/AsbCloudApp/Services/IFileService.cs b/AsbCloudApp/Services/IFileService.cs index 6b1a171f..89b89f00 100644 --- a/AsbCloudApp/Services/IFileService.cs +++ b/AsbCloudApp/Services/IFileService.cs @@ -107,5 +107,47 @@ namespace AsbCloudApp.Services /// /// Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token); + + /// + /// Получить список файлов в контейнере + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + Task> GetInfosAsync(int idWell, + int idCategory, string companyName = default, string fileName = default, DateTime begin = default, + DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default); + + /// + /// Пометить файл как удаленный + /// + /// + /// + /// + Task MarkAsDeletedAsync(int idFile, CancellationToken token = default); + + /// + /// добавить метку на файл + /// + /// + /// + /// + /// + Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token); + + /// + /// Получить запись по id + /// + /// + /// + /// + Task GetOrDefaultAsync(int id, CancellationToken token); } } diff --git a/AsbCloudInfrastructure/Repository/FileRepository.cs b/AsbCloudInfrastructure/Repository/FileRepository.cs index efa6296a..2726c2b7 100644 --- a/AsbCloudInfrastructure/Repository/FileRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileRepository.cs @@ -1,4 +1,5 @@ using AsbCloudApp.Data; +using AsbCloudApp.Services; using AsbCloudDb.Model; using Mapster; using Microsoft.EntityFrameworkCore; @@ -28,25 +29,6 @@ namespace AsbCloudInfrastructure.Repository .Include(f => f.Well); } - public async Task AddAsync(int idWell, int? idUser, int idCategory, - string destinationFileName, long fileSize, CancellationToken token = default) - { - var fileInfo = new AsbCloudDb.Model.FileInfo() - { - IdWell = idWell, - IdAuthor = idUser, - IdCategory = idCategory, - Name = destinationFileName, - UploadDate = DateTime.UtcNow, - IsDeleted = false, - Size = fileSize, - }; - - var entry = db.Files.Add(fileInfo); - await db.SaveChangesAsync(token).ConfigureAwait(false); - return entry.Entity.Id; - } - public async Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token) { var entities = await dbSetConfigured @@ -126,22 +108,6 @@ namespace AsbCloudInfrastructure.Repository return result; } - public async Task GetInfoAsync(int idFile, CancellationToken token) - { - var entity = await dbSetConfigured - .AsNoTracking() - .FirstOrDefaultAsync(f => f.Id == idFile, token) - .ConfigureAwait(false); - - if (entity is null) - { - throw new FileNotFoundException($"fileId:{idFile} not found"); - } - - var dto = Convert(entity); - return dto; - } - public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) { var result = new List(); @@ -178,26 +144,20 @@ namespace AsbCloudInfrastructure.Repository public async Task> DeleteAsync(IEnumerable ids, CancellationToken token) { - var filesQuery = db.Files - .Where(f => ids.Contains(f.Id)); + var query = dbSetConfigured + .Where(f => ids.Contains(f.Id) && f.IsDeleted); - var files = await filesQuery.ToListAsync(token); + var files = await query.ToListAsync(token); - var filesDtos = files.Select(x => new FileInfoDto { - Id = x.Id, - IdWell = x.Id, - IdCategory = x.IdCategory, - Name = x.Name - }); + var filesDtos = files.Select(x => Convert(x)); - db.Files.RemoveRange(filesQuery); + db.Files.RemoveRange(query); await db.SaveChangesAsync(token).ConfigureAwait(false); return filesDtos; } - public async Task GetByMarkId(int idMark, - CancellationToken token) + public async Task GetByMarkId(int idMark, CancellationToken token) { var entity = await dbSetConfigured .FirstOrDefaultAsync(f => f.FileMarks.Any(m => m.Id == idMark), token) @@ -271,5 +231,75 @@ namespace AsbCloudInfrastructure.Repository }); return dto; } + + public async Task> GetAllAsync(CancellationToken token) + => await dbSetConfigured.AsNoTracking() + .Select(x => Convert(x)) + .ToListAsync(token) + .ConfigureAwait(false); + + public async Task GetOrDefaultAsync(int id, CancellationToken token) + { + var entity = await dbSetConfigured + .AsNoTracking() + .FirstOrDefaultAsync(f => f.Id == id, token) + .ConfigureAwait(false); + + if (entity is null) + { + throw new FileNotFoundException($"fileId:{id} not found"); + } + + var dto = Convert(entity); + return dto; + } + + public FileInfoDto GetOrDefault(int id) + { + var entity = dbSetConfigured + .AsNoTracking() + .FirstOrDefault(f => f.Id == id); + + if (entity is null) + { + throw new FileNotFoundException($"fileId:{id} not found"); + } + + var dto = Convert(entity); + return dto; + } + + public async Task InsertAsync(FileInfoDto newItem, CancellationToken token) + { + var fileInfo = new AsbCloudDb.Model.FileInfo() + { + IdWell = newItem.IdWell, + IdAuthor = newItem.IdAuthor, + IdCategory = newItem.IdCategory, + Name = newItem.Name, + UploadDate = DateTime.UtcNow, + IsDeleted = false, + Size = newItem.Size, + }; + + var entry = db.Files.Add(fileInfo); + await db.SaveChangesAsync(token).ConfigureAwait(false); + return entry.Entity.Id; + } + + public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task UpdateAsync(FileInfoDto item, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task DeleteAsync(int id, CancellationToken token) + { + throw new NotImplementedException(); + } } } diff --git a/AsbCloudInfrastructure/Services/FileService.cs b/AsbCloudInfrastructure/Services/FileService.cs index c30fd23b..6970d9b9 100644 --- a/AsbCloudInfrastructure/Services/FileService.cs +++ b/AsbCloudInfrastructure/Services/FileService.cs @@ -36,7 +36,14 @@ namespace AsbCloudInfrastructure.Services var sysFileInfo = new System.IO.FileInfo(srcFilePath); //save info to db - var fileId = await fileRepository.AddAsync(idWell, idUser, idCategory, destinationFileName, sysFileInfo.Length, token) + var dto = new FileInfoDto { + IdWell = idWell, + IdAuthor = idUser, + IdCategory = idCategory, + Name = destinationFileName, + Size = sysFileInfo.Length + }; + var fileId = await fileRepository.InsertAsync(dto, token) .ConfigureAwait(false); string filePath = MakeFilePath(idWell, idCategory, destinationFileName, fileId); @@ -50,7 +57,16 @@ namespace AsbCloudInfrastructure.Services string fileFullName, Stream fileStream, CancellationToken token) { //save info to db - var fileId = await fileRepository.AddAsync(idWell, idUser, idCategory, Path.GetFileName(fileFullName), fileStream?.Length ?? 0, token) + var dto = new FileInfoDto + { + IdWell = idWell, + IdAuthor = idUser, + IdCategory = idCategory, + Name = Path.GetFileName(fileFullName), + Size = fileStream?.Length ?? 0 + }; + + var fileId = await fileRepository.InsertAsync(dto, token) .ConfigureAwait(false); //save stream to disk @@ -73,7 +89,7 @@ namespace AsbCloudInfrastructure.Services public async Task GetInfoAsync(int idFile, CancellationToken token) { - var dto = await fileRepository.GetInfoAsync(idFile, token).ConfigureAwait(false); + var dto = await fileRepository.GetOrDefaultAsync(idFile, token).ConfigureAwait(false); var ext = Path.GetExtension(dto.Name); @@ -88,7 +104,7 @@ namespace AsbCloudInfrastructure.Services } public Task DeleteAsync(int idFile, CancellationToken token) - => DeleteAsync(new int[] { idFile }, token); + => DeleteAsync(new int[] { idFile }, token); public async Task DeleteAsync(IEnumerable ids, CancellationToken token) { @@ -112,7 +128,7 @@ namespace AsbCloudInfrastructure.Services public async Task GetUrl(int idFile) { - var fileInfo = await fileRepository.GetInfoAsync(idFile, CancellationToken.None).ConfigureAwait(false); + var fileInfo = await fileRepository.GetOrDefaultAsync(idFile, CancellationToken.None).ConfigureAwait(false); return GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); } @@ -145,5 +161,23 @@ namespace AsbCloudInfrastructure.Services return result; } + + public async Task> GetInfosAsync(int idWell, + int idCategory, string companyName = default, string fileName = default, DateTime begin = default, + DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default) + => await fileRepository.GetInfosAsync(idWell, idCategory, companyName, fileName, begin, end, skip, take, token) + .ConfigureAwait(false); + + public async Task MarkAsDeletedAsync(int idFile, CancellationToken token = default) + => await fileRepository.MarkAsDeletedAsync(idFile, token) + .ConfigureAwait(false); + + public async Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) + => await fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token) + .ConfigureAwait(false); + + public async Task GetOrDefaultAsync(int id, CancellationToken token) + => await fileRepository.GetOrDefaultAsync(id, token) + .ConfigureAwait(false); } } diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index b75f71f4..f598bc34 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -1,10 +1,11 @@ using AsbCloudApp.Data; using AsbCloudApp.Services; -using AsbCloudInfrastructure.Repository; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; +using System.Collections; +using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -21,13 +22,11 @@ namespace AsbCloudWebApi.Controllers { private readonly IFileService fileService; private readonly IWellService wellService; - private readonly IFileRepository fileRepository; - public FileController(IFileService fileService, IWellService wellService, IFileRepository fileRepository) + public FileController(IFileService fileService, IWellService wellService) { this.fileService = fileService; this.wellService = wellService; - this.fileRepository = fileRepository; } /// @@ -101,7 +100,7 @@ namespace AsbCloudWebApi.Controllers idWell, token).ConfigureAwait(false)) return Forbid(); - var filesInfo = await fileRepository.GetInfosAsync(idWell, idCategory, + var filesInfo = await fileService.GetInfosAsync(idWell, idCategory, companyName, fileName, begin, end, skip, take, token).ConfigureAwait(false); return Ok(filesInfo); @@ -171,7 +170,7 @@ namespace AsbCloudWebApi.Controllers if (!userService.HasPermission((int)idUser, $"File.edit{file.IdCategory}")) return Forbid(); - var result = await fileRepository.MarkAsDeletedAsync(idFile, token); + var result = await fileService.MarkAsDeletedAsync(idFile, token); return Ok(result); } @@ -196,7 +195,7 @@ namespace AsbCloudWebApi.Controllers idWell, token).ConfigureAwait(false)) return Forbid(); - var result = await fileRepository.CreateFileMarkAsync(markDto, (int)idUser, token) + var result = await fileService.CreateFileMarkAsync(markDto, (int)idUser, token) .ConfigureAwait(false); return Ok(result); @@ -246,7 +245,7 @@ namespace AsbCloudWebApi.Controllers try { - var fileInfo = await fileRepository.GetInfoAsync(idFile, token).ConfigureAwait(false); + var fileInfo = await fileService.GetOrDefaultAsync(idFile, token).ConfigureAwait(false); return Ok(fileInfo); } catch (FileNotFoundException ex) From 6ab6da961aff74d84c09105df2788fb799474678 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Fri, 30 Sep 2022 11:05:09 +0500 Subject: [PATCH 17/37] #6539681 --- AsbCloudApp/Services/IFileService.cs | 8 ++++++++ AsbCloudInfrastructure/Services/FileService.cs | 4 ++++ .../ServicesTests/DrillingProgramServiceTest.cs | 14 ++++++++++++++ .../ServicesTests/WellFinalDocumentsServiceTest.cs | 5 ++++- 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/AsbCloudApp/Services/IFileService.cs b/AsbCloudApp/Services/IFileService.cs index 89b89f00..c6f299c3 100644 --- a/AsbCloudApp/Services/IFileService.cs +++ b/AsbCloudApp/Services/IFileService.cs @@ -149,5 +149,13 @@ namespace AsbCloudApp.Services /// /// Task GetOrDefaultAsync(int id, CancellationToken token); + + /// + /// получить инфо о файле по метке + /// + /// + /// + /// + Task GetByMarkId(int idMark, CancellationToken token); } } diff --git a/AsbCloudInfrastructure/Services/FileService.cs b/AsbCloudInfrastructure/Services/FileService.cs index 6970d9b9..5f01fc22 100644 --- a/AsbCloudInfrastructure/Services/FileService.cs +++ b/AsbCloudInfrastructure/Services/FileService.cs @@ -179,5 +179,9 @@ namespace AsbCloudInfrastructure.Services public async Task GetOrDefaultAsync(int id, CancellationToken token) => await fileRepository.GetOrDefaultAsync(id, token) .ConfigureAwait(false); + + public async Task GetByMarkId(int idMark, CancellationToken token) + => await fileRepository.GetByMarkId(idMark, token) + .ConfigureAwait(false); } } diff --git a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs index 7cea8d32..dfe19eaa 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs @@ -1,6 +1,7 @@ using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; using AsbCloudInfrastructure.Services.DrillingProgram; using Mapster; using Microsoft.Extensions.Configuration; @@ -80,6 +81,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests private readonly Mock fileServiceMock; private readonly Mock userServiceMock; private readonly Mock wellServiceMock; + private readonly Mock fileRepository; private readonly Mock configurationMock; private readonly Mock backgroundWorkerMock; private readonly Mock emailService; @@ -99,6 +101,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock = new Mock(); userServiceMock = new Mock(); wellServiceMock = new Mock(); + fileRepository = new Mock(); configurationMock = new Mock(); backgroundWorkerMock = new Mock(); } @@ -111,6 +114,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -128,6 +132,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -147,6 +152,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -170,6 +176,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -205,6 +212,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -231,6 +239,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -262,6 +271,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -300,6 +310,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -327,6 +338,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -354,6 +366,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -384,6 +397,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, + fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); diff --git a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs index ac53a5b9..1957091d 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs @@ -23,6 +23,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests private readonly Mock configurationMock; private readonly Mock emailServiceMock; private readonly Mock fileCategoryService; + private readonly Mock fileRepository; private readonly IEnumerable users = new List { new UserDto { @@ -52,6 +53,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests configurationMock = new Mock(); emailServiceMock = new Mock(); fileCategoryService = new Mock(); + fileRepository = new Mock(); service = new WellFinalDocumentsService( context: context, @@ -60,7 +62,8 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellService: wellServiceMock.Object, configuration: configurationMock.Object, emailService: emailServiceMock.Object, - fileCategoryService: fileCategoryService.Object); + fileCategoryService: fileCategoryService.Object, + fileRepository.Object); } ~WellFinalDocumentsServiceTest() From 9644f730906746e67a0904b660edefeac1f5a50c Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Fri, 30 Sep 2022 13:34:50 +0500 Subject: [PATCH 18/37] =?UTF-8?q?#6539681=20=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B5=20=D1=80=D0=B5?= =?UTF-8?q?=D1=84=D0=B5=D1=80=D0=B5=D0=BD=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Services/IFileService.cs | 25 +++++++++++++++++++ AsbCloudInfrastructure/DependencyInjection.cs | 2 +- .../DrillingProgram/DrillingProgramService.cs | 10 +++----- .../Services/FileService.cs | 12 +++++++++ .../Services/ReportService.cs | 5 ++-- .../Services/WellFinalDocumentsService.cs | 9 +++---- .../DrillingProgramServiceTest.cs | 13 ---------- .../WellFinalDocumentsServiceTest.cs | 5 +--- 8 files changed, 48 insertions(+), 33 deletions(-) diff --git a/AsbCloudApp/Services/IFileService.cs b/AsbCloudApp/Services/IFileService.cs index c6f299c3..a83d6d5c 100644 --- a/AsbCloudApp/Services/IFileService.cs +++ b/AsbCloudApp/Services/IFileService.cs @@ -157,5 +157,30 @@ namespace AsbCloudApp.Services /// /// Task GetByMarkId(int idMark, CancellationToken token); + + /// + /// пометить метки файлов как удаленные + /// + /// + /// + /// + Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token); + + /// + /// Получение файлов по скважине + /// + /// + /// + /// + Task> GetInfosByWellIdAsync(int idWell, CancellationToken token); + + /// + /// Получить файлы определенной категории + /// + /// + /// + /// + /// + Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token); } } diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index e86a314b..f178b648 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -106,7 +106,6 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -155,6 +154,7 @@ namespace AsbCloudInfrastructure dbSet => dbSet .Include(c => c.Wells) .Include(c => c.Deposit))); // может быть включен в сервис ClusterService + services.AddTransient(); // Subsystem service services.AddTransient, CrudCacheServiceBase>(); services.AddTransient(); diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index c1973c11..0e840524 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -23,7 +23,6 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram private readonly IFileService fileService; private readonly IUserService userService; private readonly IWellService wellService; - private readonly IFileRepository fileRepository; private readonly IConfiguration configuration; private readonly IBackgroundWorkerService backgroundWorker; private readonly IEmailService emailService; @@ -54,7 +53,6 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram IFileService fileService, IUserService userService, IWellService wellService, - IFileRepository fileRepository, IConfiguration configuration, IBackgroundWorkerService backgroundWorker, IEmailService emailService) @@ -63,7 +61,6 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram this.fileService = fileService; this.userService = userService; this.wellService = wellService; - this.fileRepository = fileRepository; this.configuration = configuration; this.backgroundWorker = backgroundWorker; this.connectionString = configuration.GetConnectionString("DefaultConnection"); @@ -312,9 +309,9 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram .Select(m => m.Id); if (oldMarksIds?.Any() == true) - await fileRepository.MarkFileMarkAsDeletedAsync(oldMarksIds, token); + await fileService.MarkFileMarkAsDeletedAsync(oldMarksIds, token); - var result = await fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token) + var result = await fileService.CreateFileMarkAsync(fileMarkDto, idUser, token) .ConfigureAwait(false); if (fileMarkDto.IdMarkType == idMarkTypeReject) @@ -344,7 +341,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram public async Task MarkAsDeletedFileMarkAsync(int idMark, CancellationToken token) { - var fileInfo = await fileRepository.GetByMarkId(idMark, token) + var fileInfo = await fileService.GetByMarkId(idMark, token) .ConfigureAwait(false); if (fileInfo.IdCategory < idFileCategoryDrillingProgramPartsStart || @@ -483,6 +480,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram .UseNpgsql(connectionString) .Options; using var context = new AsbCloudDbContext(contextOptions); + var fileRepository = new FileRepository(context); var fileService = new FileService(fileRepository); var files = state.Parts.Select(p => fileService.GetUrl(p.File)); DrillingProgramMaker.UniteExcelFiles(files, tempResultFilePath, state.Parts, well); diff --git a/AsbCloudInfrastructure/Services/FileService.cs b/AsbCloudInfrastructure/Services/FileService.cs index 5f01fc22..cdfed260 100644 --- a/AsbCloudInfrastructure/Services/FileService.cs +++ b/AsbCloudInfrastructure/Services/FileService.cs @@ -183,5 +183,17 @@ namespace AsbCloudInfrastructure.Services public async Task GetByMarkId(int idMark, CancellationToken token) => await fileRepository.GetByMarkId(idMark, token) .ConfigureAwait(false); + + public async Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) + => await fileRepository.MarkFileMarkAsDeletedAsync(idsMarks, token) + .ConfigureAwait(false); + + public async Task> GetInfosByWellIdAsync(int idWell, CancellationToken token) + => await fileRepository.GetInfosByWellIdAsync(idWell, token) + .ConfigureAwait(false); + + public async Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token) + => await fileRepository.GetInfosByCategoryAsync(idWell, idCategory, token) + .ConfigureAwait(false); } } diff --git a/AsbCloudInfrastructure/Services/ReportService.cs b/AsbCloudInfrastructure/Services/ReportService.cs index 6265f6c6..53d8653a 100644 --- a/AsbCloudInfrastructure/Services/ReportService.cs +++ b/AsbCloudInfrastructure/Services/ReportService.cs @@ -22,17 +22,15 @@ namespace AsbCloudInfrastructure.Services private readonly ITelemetryService telemetryService; private readonly IWellService wellService; private readonly IBackgroundWorkerService backgroundWorkerService; - private readonly IFileRepository fileRepository; public ReportService(IAsbCloudDbContext db, IConfiguration configuration, - ITelemetryService telemetryService, IWellService wellService, IBackgroundWorkerService backgroundWorkerService, IFileRepository fileRepository) + ITelemetryService telemetryService, IWellService wellService, IBackgroundWorkerService backgroundWorkerService) { this.db = db; this.connectionString = configuration.GetConnectionString("DefaultConnection"); this.wellService = wellService; this.backgroundWorkerService = backgroundWorkerService; this.telemetryService = telemetryService; - this.fileRepository = fileRepository; ReportCategoryId = db.FileCategories.AsNoTracking() .FirstOrDefault(c => c.Name.Equals("Рапорт")).Id; @@ -68,6 +66,7 @@ namespace AsbCloudInfrastructure.Services }; generator.Make(reportFileName); + var fileRepository = new FileRepository(context); var fileService = new FileService(fileRepository); var fileInfo = await fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName, token); diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs index dc90128c..4d5f6427 100644 --- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs +++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs @@ -28,7 +28,6 @@ namespace AsbCloudInfrastructure.Services private readonly IConfiguration configuration; private readonly IEmailService emailService; private readonly IFileCategoryService fileCategoryService; - private readonly IFileRepository fileRepository; private const int FileServiceThrewException = -1; @@ -38,8 +37,7 @@ namespace AsbCloudInfrastructure.Services IWellService wellService, IConfiguration configuration, IEmailService emailService, - IFileCategoryService fileCategoryService, - IFileRepository fileRepository) + IFileCategoryService fileCategoryService) { this.context = context; this.fileService = fileService; @@ -48,7 +46,6 @@ namespace AsbCloudInfrastructure.Services this.configuration = configuration; this.emailService = emailService; this.fileCategoryService = fileCategoryService; - this.fileRepository = fileRepository; } public async Task UpdateRangeAsync(int idWell, IEnumerable? dtos, CancellationToken token) @@ -98,7 +95,7 @@ namespace AsbCloudInfrastructure.Services var categoriesIds = entitiesGroups .Select(g => g.Key); - var files = (await fileRepository + var files = (await fileService .GetInfosByWellIdAsync(idWell, token) .ConfigureAwait(false)) .Where(f => categoriesIds.Contains(f.IdCategory)) @@ -165,7 +162,7 @@ namespace AsbCloudInfrastructure.Services public async Task GetFilesHistoryByIdCategory(int idWell, int idCategory, CancellationToken token) { - var files = await fileRepository.GetInfosByCategoryAsync(idWell, idCategory, token).ConfigureAwait(false); + var files = await fileService.GetInfosByCategoryAsync(idWell, idCategory, token).ConfigureAwait(false); return new WellFinalDocumentsHistoryDto { IdWell = idWell, diff --git a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs index dfe19eaa..949c8c46 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs @@ -81,7 +81,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests private readonly Mock fileServiceMock; private readonly Mock userServiceMock; private readonly Mock wellServiceMock; - private readonly Mock fileRepository; private readonly Mock configurationMock; private readonly Mock backgroundWorkerMock; private readonly Mock emailService; @@ -101,7 +100,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock = new Mock(); userServiceMock = new Mock(); wellServiceMock = new Mock(); - fileRepository = new Mock(); configurationMock = new Mock(); backgroundWorkerMock = new Mock(); } @@ -114,7 +112,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -132,7 +129,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -152,7 +148,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -176,7 +171,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -212,7 +206,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -239,7 +232,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -271,7 +263,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -310,7 +301,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -338,7 +328,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -366,7 +355,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); @@ -397,7 +385,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests fileServiceMock.Object, userServiceMock.Object, wellServiceMock.Object, - fileRepository.Object, configurationMock.Object, backgroundWorkerMock.Object, emailService.Object); diff --git a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs index 1957091d..ac53a5b9 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs @@ -23,7 +23,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests private readonly Mock configurationMock; private readonly Mock emailServiceMock; private readonly Mock fileCategoryService; - private readonly Mock fileRepository; private readonly IEnumerable users = new List { new UserDto { @@ -53,7 +52,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests configurationMock = new Mock(); emailServiceMock = new Mock(); fileCategoryService = new Mock(); - fileRepository = new Mock(); service = new WellFinalDocumentsService( context: context, @@ -62,8 +60,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellService: wellServiceMock.Object, configuration: configurationMock.Object, emailService: emailServiceMock.Object, - fileCategoryService: fileCategoryService.Object, - fileRepository.Object); + fileCategoryService: fileCategoryService.Object); } ~WellFinalDocumentsServiceTest() From 06b7a0da227dadfde0483c3e7366b561b1a674b2 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Mon, 3 Oct 2022 15:46:24 +0500 Subject: [PATCH 19/37] DrillParamsService.GetCompositeAllAsync invert isMin/isMax flags. --- .../Services/DrillParamsService.cs | 4 +- AsbCloudWebApi/wwwroot/asset-manifest.json | 50 ------------------ AsbCloudWebApi/wwwroot/favicon.ico | Bin 362870 -> 0 bytes AsbCloudWebApi/wwwroot/index.html | 2 +- AsbCloudWebApi/wwwroot/manifest.json | 15 ------ AsbCloudWebApi/wwwroot/robots.txt | 3 -- 6 files changed, 3 insertions(+), 71 deletions(-) delete mode 100644 AsbCloudWebApi/wwwroot/asset-manifest.json delete mode 100644 AsbCloudWebApi/wwwroot/favicon.ico delete mode 100644 AsbCloudWebApi/wwwroot/manifest.json delete mode 100644 AsbCloudWebApi/wwwroot/robots.txt diff --git a/AsbCloudInfrastructure/Services/DrillParamsService.cs b/AsbCloudInfrastructure/Services/DrillParamsService.cs index a081bdd9..95528330 100644 --- a/AsbCloudInfrastructure/Services/DrillParamsService.cs +++ b/AsbCloudInfrastructure/Services/DrillParamsService.cs @@ -214,8 +214,8 @@ namespace AsbCloudInfrastructure.Services Avg = avg, Max = max, Min = min, - IsMax = allDrillParams?.Any(mx => mx.max > max) ?? false, - IsMin = allDrillParams?.Any(mn => mn.min < min) ?? false + IsMax = (! allDrillParams?.Any (mx => mx.max > max)) ?? false, + IsMin = (! allDrillParams?.Any (mn => mn.min < min)) ?? false }; } #nullable disable diff --git a/AsbCloudWebApi/wwwroot/asset-manifest.json b/AsbCloudWebApi/wwwroot/asset-manifest.json deleted file mode 100644 index cdaee685..00000000 --- a/AsbCloudWebApi/wwwroot/asset-manifest.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "files": { - "main.css": "/static/css/main.c2a82e71.chunk.css", - "main.js": "/static/js/main.01e9ada9.chunk.js", - "main.js.map": "/static/js/main.01e9ada9.chunk.js.map", - "runtime-main.js": "/static/js/runtime-main.8da12c69.js", - "runtime-main.js.map": "/static/js/runtime-main.8da12c69.js.map", - "static/js/2.f196b75b.chunk.js": "/static/js/2.f196b75b.chunk.js", - "static/js/2.f196b75b.chunk.js.map": "/static/js/2.f196b75b.chunk.js.map", - "static/css/3.f8ac3883.chunk.css": "/static/css/3.f8ac3883.chunk.css", - "static/js/3.31b66021.chunk.js": "/static/js/3.31b66021.chunk.js", - "static/js/3.31b66021.chunk.js.map": "/static/js/3.31b66021.chunk.js.map", - "static/css/4.f8ac3883.chunk.css": "/static/css/4.f8ac3883.chunk.css", - "static/js/4.1f09e89e.chunk.js": "/static/js/4.1f09e89e.chunk.js", - "static/js/4.1f09e89e.chunk.js.map": "/static/js/4.1f09e89e.chunk.js.map", - "static/js/5.ef929bfe.chunk.js": "/static/js/5.ef929bfe.chunk.js", - "static/js/5.ef929bfe.chunk.js.map": "/static/js/5.ef929bfe.chunk.js.map", - "static/js/6.88051835.chunk.js": "/static/js/6.88051835.chunk.js", - "static/js/6.88051835.chunk.js.map": "/static/js/6.88051835.chunk.js.map", - "static/js/7.4f3c315a.chunk.js": "/static/js/7.4f3c315a.chunk.js", - "static/js/7.4f3c315a.chunk.js.map": "/static/js/7.4f3c315a.chunk.js.map", - "static/js/8.8e9a1dc7.chunk.js": "/static/js/8.8e9a1dc7.chunk.js", - "static/js/8.8e9a1dc7.chunk.js.map": "/static/js/8.8e9a1dc7.chunk.js.map", - "static/js/9.71667cac.chunk.js": "/static/js/9.71667cac.chunk.js", - "static/js/9.71667cac.chunk.js.map": "/static/js/9.71667cac.chunk.js.map", - "static/js/10.e5247b1b.chunk.js": "/static/js/10.e5247b1b.chunk.js", - "static/js/10.e5247b1b.chunk.js.map": "/static/js/10.e5247b1b.chunk.js.map", - "static/js/11.70112c8f.chunk.js": "/static/js/11.70112c8f.chunk.js", - "static/js/11.70112c8f.chunk.js.map": "/static/js/11.70112c8f.chunk.js.map", - "static/js/12.2265b74f.chunk.js": "/static/js/12.2265b74f.chunk.js", - "static/js/12.2265b74f.chunk.js.map": "/static/js/12.2265b74f.chunk.js.map", - "static/js/13.063a16c9.chunk.js": "/static/js/13.063a16c9.chunk.js", - "static/js/13.063a16c9.chunk.js.map": "/static/js/13.063a16c9.chunk.js.map", - "static/js/14.50a284b1.chunk.js": "/static/js/14.50a284b1.chunk.js", - "static/js/14.50a284b1.chunk.js.map": "/static/js/14.50a284b1.chunk.js.map", - "index.html": "/index.html", - "static/css/3.f8ac3883.chunk.css.map": "/static/css/3.f8ac3883.chunk.css.map", - "static/css/4.f8ac3883.chunk.css.map": "/static/css/4.f8ac3883.chunk.css.map", - "static/css/main.c2a82e71.chunk.css.map": "/static/css/main.c2a82e71.chunk.css.map", - "static/js/2.f196b75b.chunk.js.LICENSE.txt": "/static/js/2.f196b75b.chunk.js.LICENSE.txt", - "static/media/ClusterIcon.f85713df.svg": "/static/media/ClusterIcon.f85713df.svg", - "static/media/DepositIcon.9688e406.svg": "/static/media/DepositIcon.9688e406.svg" - }, - "entrypoints": [ - "static/js/runtime-main.8da12c69.js", - "static/js/2.f196b75b.chunk.js", - "static/css/main.c2a82e71.chunk.css", - "static/js/main.01e9ada9.chunk.js" - ] -} \ No newline at end of file diff --git a/AsbCloudWebApi/wwwroot/favicon.ico b/AsbCloudWebApi/wwwroot/favicon.ico deleted file mode 100644 index 0427b291466049cd352f9064e64671e66f3f41a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 362870 zcmeHQ2b>f|)?d`S^X|U8)AKw%+?m-4yNmA50ImrY-2{jTm=+ZTF=5UD)Kk}lm<3G0 zCV~mGo}L-?45*m1h{DV)K?Ed8Sa$pSzn-p{nx3B7?%D1Q@RnauJ>6CBz4}+Z3a?U5 zPPd%j=j^moPEH>Fow-9!&X}B>oZWYi{hsj0oScvGE-x?k`w@g2_Sc-8($d)P9_2YX zE$*D0>T2!xj@@z!P6h$|<>6nCyd83eoYgI-2Yw?e-sI$TQ~w7I&~5FnEYP#4+!wqP z?u&9?@v~+Ay-O?b z8%YlOU7A<4d$~U}gW}^|UwYTi)w}zBH{Pm@zi6Ct(eP81XC8c18C7}2^YpF0zV_P7 z&N%yoGJh~!5h&WL!XG>X@;pGYSLIY~PhseK^4B>HNg0F#J{85Up$Szi@%fmANlS@C!DOD)NhD#{dt!vWxnD;;#*x^ z?YD664Bl@)FZiyh04|_$xcE*!=-z$91(z!|w@p+=lpd~7n#A|Ix|;EbuhiAmO+fs$ z6~3N#l;-8_D87>qnx|fK=7q{h6-OwSpEPEb{H>;@rgtoU?Ha`Y3T~|Yot`W6ic68E z8LIOI@6vxq{P}QSP(C33PZfb+A2|$_wF+A17f z7YrgyGh7q$v=F}0MiiV>2UGAzP{#c#Mub5eD4Up6$<4w*jvo?Yayc05ysK;ZU*6ZOn!)L~ZsN&}%>ajuV>GHnc-9B4GlpYqDOJp6Q9xok^jME+Ivy&$^PmJU-1!{c$E2z&qsVJ)0N=+EIj_;{)@>SvtQ{i;(0)ilJ5}q1Gv|;ct}g}c}6@?4-G^Zs-qRE zpG6p?{q|E2J4(6k+)I?zD_1Esw@*}lS@yH??=j~oqx%nq{Gkge?2z6EpMtoAXLGqX zG+4yf{BC$JFi|S}MP=eU>g1DV-7{60JLfIstf9v%7ou)E?eJriPu}}LxozCFN?Bg; zPzsB3d-=e<_8y_}Sgp?wypQFVH~0&+8-jj$Ahh@O=Ut{OU%E`W^u*JYBTM=!H=_Pq zw`PrU){!T)9PAG6Oktt_BjE0>@E0FPJb>#1^q$HfJd%F}9OYL%y%&E21A#vrRdPtv zsEWbLod3M2;zR!FgN{`W+iTySL^#m?3v_M+{8LdTjs?cQ5pAktO7nWALaCtb3;_C-m)4*gqk{kPrIL5D)13zR2gJN~sO<2LDUtifDlT z`oY~x{v^ktXYhRFm8YIlhzG(cV~(g&o@kh*P`xRKMSV3A^r_AXBR_U6%M0xfnpDQd zp+5Z(d>)s>i)WOFt19z*DUa99RPIIlS$D@|l!1_8~HmbLBEz{pAWaO(jPqCD7^NrTfh8X ztNIo6qW*}2XDVke8-+*S?gaXqG#=kl{vs@}EZWy7JiVhfp4xqsv3nA(=$3ThLHmUm z{hH^sI)~(WAzfXomSbP28s+hB$TJB%&`%6igMK$XkLlB=7J&ALL?2k4)8Ak00_|A6 z;|ne+%j-EnA4mK~xYd+axDUiT;Zr*adUqgyFO11v+ca(3G}7H1l$%;D9>r~;I+^rV z#1%gEHSn!3`UTW%#sAQ+@qp%Blo#qBeW1xcRRmD`im`G^^o9GB+9wevoew=43bzun ze}}w1Qj>iRe#iS|6qocCx_LU>Z1DJ19#2t)q zpCkOsa1X#;e(Uu&op$?=4GlveQ;_mlN2b-Ekkf^^ zd2pq0q90aG1Hdf*N{fpAkJ?D+IE`&Eo>TiY8{t1xSrGIIvIi9w{)PH!;&)s9n2r_S z2R`fIgpQ$K9(<)T(6cwur}`V^7Gu89+gg})=s!-8<+3UVjeo%7Iz3;s+wWEeic6^; z!Pwwv=;bpAvsso+dfo&*9dA_UWRi#asi5(uM2FJ-C3shneo{S#-|{#*j*Bi%>^)?b z^*9r6jPpXE5lPSqEiA=&4(Ygp`r(Q9iM%lL4p@e1Y?g^P$w=W6^ok#r$MtysSw*0y za?kY>l+BwqDJ?B6YJZgc=H_PQ*@tE;gNpa3G&fQHQGF)H@+wV?^NsojBol>28~Y)4sQjs4eC289DyI%STB*Hb67m0Bq;q=hlrsFT zkJCk77?lU~HG0Lv#LD@vdOgDTvD6IMWAAPQSCHgmu@0#DO(${N{^qur;mM%;V%KE@j82=OAKQCFToO{fP zYJYC{Ap?{jzWz3zABcOAh}+OGtps)W;>nXIcgK6GI|!dmvThzieF1-{Jehy!7(qk$ zly{W>l+QzY9jJ~?E+2h{@_7ABWl-<{t$#c~A^j9_$VXlM18{ho`U=pYNh%+IP;JN6 zdMyuqe{awIB>o$y9+PQ^XT<-7`miK}T>ch(^BwY`FQqL$wh(c^pX>{0d+P4SyKb8P zu8Y;Fq2sBJ(Clm!pZem@h`4&6`olw!--j3Pr|Q9FqfS>|dg2-7q{_hxy+{1`*h9oc z+V_d^SNmS0@t(#tcTs%;UQ?mh&ytNp+_F3 zq4x9f`$?mS;J-kVVFQ&33Pbi7g#Q5L;>Xg0l7DFYx6rc@4SEOur&k?Nt_YmDLo``ZKt@E1ZSR31qCa`0{G8wgOHi}ZwEH;OObX=5K{ zWZ58P)rys>{!?8v7UfWlpE?FsqoSX&pTwW~z^`iK9CiGv(S^;b_+7e%UY67kB)bgRNz}Nc5BfMpzo~vh*afLBbd^zf@h&wF>fXb6eH!tH zTS9G?2%E_#ouxY7$RS?Jm_Vk5y68>`gDEKQCuscDaldRYmE+0J2tO0+nvk<8|Xi%8OOh*A?-Nd}?D5j>fMs=MRoH3P<$}_+Xq+HyL~%(s-+5ClMa@_5#o$ z8=9(5aUWwo^b4}?wbR%S{G#B!2+zInyhY=`7Qa;+xR8PDeR00Ya?Gc;QG_$&6W$oJ zT>xI2i67EG1P*p~p?fvg>FHGGLC)v&NUrS`&TERS^7`~bQy!!43{it+twymvkPaGeWzax>Cns$Pw8PW~V93qcEMsQt}= zkKm{Cr;Q;hGiJ=NJV%ktJ@G4sa~jjx5kS zzdJfAJq*fr0eAQ#eH^?SpFU3POJ3ejI|f|gp?-JdmVhhr0%&{)_Z5D>h2N9?o+zwz z%65Kt<3V_@Wa)lGyzk*&1h2CKyD!-_om?d)^L~eLUmEaPRp<&Qt(lW)K-LEh;`}Iw zk)QqD8(sPC$RxyBZ4ghN&an4ii#-Up(nMH&T%+G>1Fq<)n*#_o5QLL)iCI!h0hBrNnFaq<&8>1M35x$akReF)EO#=!RqjFRSMjVmEu{JE8i7)GFHMe z{jY3~y01Uv_*9OYc#aybNq}sxCc>E4S2+&K*ni~T@n=tDt}i!|ukK&+2Oq`!=W3dJ ztnl^P7i;(`vHs~+%)4Jp>vRYQzbkruz9)KPJbnV_l~k`}O1=1&n;ZF~QC^T9h%mBG z@_}E9UK_|@l(%W$`CXAG`s7ys9qFB=&HKjoE~n2=s<*MWR_McDt__TEsEm(VTc4>~X1LzvHgX4^3Pxmh06S>Sl zzOhE(i;BMbJ@oEtgYc^hawAE5KmvKu0}R5+7@r?ty4J?^R4>~EZUdW2se?gpq_g~&x7>TNcME^0?2DU4Zk~lf76iB-RiAy)uMgc{qwcSvb*8k3l=jBZ96d023VW@t zMVxv0uAfep=m~5$P+u}xmh`_0@)q|VV?|M&an4 z&l5Qu>oQM8Iv#{e+AoFQuhHJI7iK@HJonIJwC0uezpCvL=G`B|`qt~Q7W|6+JjV|L zt(3g*xuX@CphX5X)P}0JKDFqfWruxAJ*BOdQ!i^ z$}_VbQL4|mnAQs3A--$tRA~Rl8rpx7rX74=gwN!Ab0Zj51X$;-%@UFGL!5L;A7yxcF}UemL4=M(f@O_w1ukU5It@BLzM3QT`uC z`W5*1q-h7Y81-dk8d`f!#A zH(@W>#j;%VOnb1X|1+|D&|Bp9^YzM?!(g4&@ml)t&(ID|1>doT&K0S_d!unzO91t| z%&WC$>WdkqPXPv}QC!LgeBY!GQ|MXfrFNh8gzEPvl=?%(Sa<#m(*7Uh{j>VLdUbVE z52f^DZPH2FSjv|1Ao`YS8{Ar&f$JIWc>9)>Pd zb-)|^xYAR+r%adDm*U$pU~rvyPwUE%=IfCERQ}h~+C!?VHCv6Izt!LGP+9~pD}HP| zl9GPnKZEFCym7WZ{WQKS-Sup$10yO1s0&dZ&Pc}>^?f1SXVCfckoGNjzDa9eHh55$ zKtH7&OyQZDM*^eAX>68`x0(0gHOqis3)!s#dqi`MhTlzkWnY0>(A^QpB zN$HP+$G2KLNcKFvT$_MT8P*W)h5ZUA-8EstpsIr_$Ef|gK(U|JrXuZFV@SGAdo}A0 z#Pd6M-8J)Hpfxj2&lA1ZxE+i>Lv5LngG})?uSV&~<{i>{dR(UDv|fug@v1c6)}aq_ z6k&k0y%0;Qy6^gXl=UCA-<19nX%A^t)w_SkxK(ds{86*j>G6$blaB1;sP^Bt4br&* zW&LP__d;IM-5HcmC9HP@`aY0hvtADBSK!?b`uDou&G`LVz9)P&+KiEKRr#*ynKT|l+w_wztiX=^&uJ`g z)Yqc+S+>vR=S6$z^?~Xq>nTki1M=K#BrEhI)z*-#CvuuhJ)>NGwx?&Iy4Jf5?ci#& zcBAyEPJE#;5YnI0w=}|}jqhetz6;K1zjp_{tlB{;BZ7_{KI*iA7SfiYFRjF#58XJ{ zNKV8{9S@o*W3K2$M)cb9&PX4P(xugn+#ro^;>QvAmXcbS=glV-HZBBeNX)Z8Y>{ps{KQR zOXtV>S_#^MzwA@LQOF|vfG64~9Zi1E2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9B z^&!v$Nvft~!Ri!0CjxgJ@E;?<2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS z03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R z2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftoB90J%-x`rvI7dh5Hlq@w53&@`5MbPw_6Cl{;{^&>ev&6Bo!hw{jPd zSsd*O*9`eyMR`7f%62yR#O}FBy?ZD_KD}=CJ`24((5*`{&`rW5(><U)XFk;l+2jq%`KcyxP-TK1r@iY=pBM6P z+==41z-OTx*UU5B0f@U=&cz*Li!AUljWgZRL~?-s94F}8K@)oOO6<-VGl+>WxDVAG zdEEm4)&A~{E)m;`4<28b0U*%*iks#=e-xwlycW;+H|@iFIb^3!h+s)X=&>7&cwY|)K5fz=swWQ>h3VpvczOt zCHjySE|>qma$Cttlh;*cXno?*IwU#5OQkc$7NZ{wH)KN z$#gd-wR3`|kxzX*YG3I7Vem@5_ZYSXif3gUNOxQt@v{0Zc0X_QSk$3!Wr4#uv;64p z<}BztQYPpg?2?jszk{y8er&l+{s^p2*O&d$yk0w%dwcFz<_!%g_Xevf{J|sp`S#4O z&dJ#>86))dT;U-yZ_(!Aot1GQNZb1tyB9XH+yW+R3%W1PVhikXZrF z=Oet~z1$h-kj?HIvI&XwmidDv<-XvZa9_bGnrkWd2WR*5^~x9Fs2r5#1&3C6Lw&1q zsEaP5bkEP{I&FT23sf9!F0cT z5~dk`FOcs9ukaT4Lteil<++;oWxn7m<$=)NgvWr~qQ9ejj4Ahp-cAlz{C$N#bW*ie zFKA=VH|cI?iU%3O8RU@VZE|8xi)7H+YqR6g6@kF~KTtd~f2cceHJLs+tsVBP*3-DV zo6^=d(0kVkU-9F~`3b%E2H&j=6qlCfIfNL+dpfE8(w7&$5oz1W*^r19qeY~|IzskJ9IVB|}zZ2<2KmT&H=gJ9v2PmJs_rB87(xQC% z(Wgq?9h24PwX4@CcV2m&LSd+Wh{yAV#tWM8o6%1=L43ow{0)<7XrcLb5zh(V?3lF2 z9?@N_@ZZz3@Lx!yX`2AG!?2U<#!{&qX`bICc1HQGzN0=0QKt4BdGnK$Pn3se%3P7J zhaJ0rnex&T&nQO(4^Zy8euDDp`}5TNpZC9amE#WTr;HtahH}@xZ=g0HKL1c#TiYLb zUMH7E`Mt`y> z&CN>nITus>2_kM?UENi11MqGv#aEp-_%V$St&9U9|5QQK2_H6rV+}A$(H*Pv!!cQ5 z6L3Y|Gechsv%1g~PQqWGX0q!btm%41&zs7-ph>zO&l}1k^z+3x*{6E_!?)g1>-+cL zcw6aLu(z6@H(qeLvT?%(_5G-dBd85HUc`g`7uMC)u9!A$nz!5=x+=kk>K9A%feQpp zCw#Iq>M=6@9Zl-Tnw3SHzctgxh}F%QOK6R@W_M31qsDS4*#Lg?`4;?*=vP%$ZI5yO ziHUp(DrNpqylluapdNpH=Hw~L)LZUS`WNo4+;Z8!mD|T%tDH6Tcx80|p~|OoKU6C7 zdn&LE7RvFU|6kVC)qFB#%9KA5ZH?EWs-mLbo9=s~ZnVBWN0uVLQ?kkguIkj<^JNMb|{5aqis zzKZw%nwpvvDi{3T%XU~jU(#Vnh!>IlSWAORTWPG^3VH1GfupH$S~lx8WI3U;N1870$S=&L-5|%;KZDkbR_Li= z_lV{a9pvSkYTw*nd?4j3xe9OadOZ*En`}cE|0^H7`L^2Er}lqn?}L=81IpF@-}sBK zP+&K_SA>^+~KsUHknR-3?ai5>jF=V=qX zL|wEg-?LD)pBnMTIN)pxw20;^qEn4J8u*i~<}v7hi1MCXWuRwoBR=$QaQBiwAx!iA z<8N2<{K&ogD#H&sOl|Y2J~(yY(davd)Hz-~4b=VDi8=uO(&^KutLvW*b_aKcOs2UGScGS~v%Wt&H=a|HBc3b#}xU>cs{4%YT5P2W-v2HqDxz}u0R@QKSNODyAiriYB ze^VYP_Q#$>3-KwVeqjvoJ%z2gZ6fSIAFAX3Z$A4%sp?a%mY-5z@jgUf|5smMAC&SR zeSy07CQX{8&Zk%!2bx&hs^^{QH`yUEK3{Aq|4~jd(X#RldV8@co?4qtbExU)t8+Jr zwmrG*q`Z&5OmsARALZGWa&K>sRu=9`$3wiQd7&dheboGZ?%~IkX}8|3+&1*==TcfLE^V1_TkY{_=*zL9*TSStgXADiS& zdAdBE?Gfv+t~5_4{4B{+<}W%(%X8&WPq2^r>q~Y+KC1J5w2mWPzb#qX__*O_#6_7&cBOg2 z9{TY5-x&YjBN_v6=oTWpm9Ke!+4ZeQ-cNbRKl6JOJdywEd0UuEd7R>wd-tSqAJ$~V%fKqE_c68S32|PM;wjXh z(90u!W9+{p@_Y*HepT?-i~JXDKjyJ+jO|x4KMu5@D+c*$O3!}r=SBh|4ejA0O{VQ& zvGga;MWT;7#3U}8g&i9<_-EvNq-WTGr;x2LQ<~8Z+>fxI3)kNt`lnHN=y)OAXK+)| z*S}5VJ^Tfz`_=IVWd0sySKY52dO%HmCo&$vmXK;9@b4OLA%Z zP}iA^Urli;d`0^r59K;Qv8=z;A|IqzYh$i;T z4J3JKtt|bvG7dDEPBZx}hglxTiylC-bi^O6$3wcz_fvKI{QR!S6Q*#%xkz*_3#Acl z`83jd1GkadcLd336V~IT)%O!cUZWfw1>K(@e#4&|>-QLf+@o zS`R6&AH!VFF8IAhdx!d|lqM^GZucV0 ziA9$tVUxMP`!U&*iHCaDk~?B{ZEy?i372I4Udw<3QWH#M9zFNQwU91C%mi+=9x*|UGID2e&?YS;v{d7`oEo-bc; z6P1hpyM_KNr<>;SP{-dZ{U{9nVxInotf@TQ99?!QS_e3}oCy`%q|( z*Wg=ndPTYMgik4OH&$A4eoy0pG~Sfc&>5eB!Aqubz=M{YLZ!pszGf z`v%-Aa8uAv8w*#}&@ip!?Bh>%k^R5I7rKD<{Sju!Uk}2~h12pp?!QiD31xuhd{)6f zg2I#S5_RoU>ExsJF=U^_cXKvToWVwPx5huxOWi$T6FMP9xK_aMIA4)?1;n02(?H%6!KS$d}Yq4jUzpK-ks^?fL;*>ND9 zxk2H#)<5XORT=UuwN8W$fUrQEPb|fY)u+qkxwVFdnu9QQd&wYw^}4S6U8l|ip^WS$ z@`Y@C=+n$IAyb&*SQrO7vL;N(-O)bnnFVHFnZPYp7O!X3R+H z6H*@!G)_l9?`zX#SCb9>m&=J4;=O4mF7LY#DE;Wt_% zg)(?TYkQJtt_0({p~#O(;A?6w%0RviRNg5s@y+CXU~Em()|~&e_6z;ypAGOb&Ntd` zW^HYWF&$lfL3Ucm@DAGYXJD(WqrN;p7wn$VV?{n%7zeJVHYUlb zdt;(ipqJJejTt+0TY~givF%ZQ&em`>mA4%nmd=fb4Nm^EFb*^>PnOe-y6Xd3g3k4< z;_L+KWas z(_AaH2ko9#ht_&p&FggGfk$<_V`5YNnj|;+4(Zmki?mxA2PV;Oi@cujO@e=C^fenQ z^|#tfNA2c=GuNUc&0>pmni>b%g$MO#&C1qM;pna(JGTo`=Mx0Y= zRo3xw>0U zUQCcY_4>7r6N))A0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R z2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q` zi~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7 zzz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS z0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGK zBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N% zFanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS z03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R z2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q` zi~u9R2rvSS03*N%FanGKBftnS0*nA7zz8q`i~u9R2rvSS03*N%FanGKBftnS0*nA7 zzz8q`i~u9R2rvSS03*N%v>GUK?b)3-&SrVZdojy;g8_Ii8A;++@yTyg5MJ@^ZS?nvn^QK9XCHWvOnZ( zhEp7HTZq2hGMk~-z5C)nAw9o2kR~PIS-iIy89F|U(kEWYB^{k5>;h_=sLlnBJDJ7Nsc->L z^j?eQ!3vIF1p@Q`;FRo{=ps!|JCQEGD|}TZz8(1uZF+vd6}}i{>lvhdxfAKvXs(4n z8~udgX38+i`v(rnVx>HGwy>Lk3+m-)RcVg0Lr0VypKrn6{O-tNr}D?|ir&x>=|Vqt zv=eE{cSrx%5$Q?CGe0ld3;A~o()x`P=`}%<%J7RQ!^fs8!}wlpf=*}C&Gwcj0*tP8 zyBF=8F0Y+>kGvb^VE$~TGU}A<>FD;@Bf1OH)Z{?An#{C$>EyEGz1pXCMK418`cNxR@?ga!K4Va+a(NhddA95Nswzp@=4_&9G-o+lIr^SIZHMYk*AlgtrWS<4smGoZd zQB=kVX*kh=d=R|0c7Josj^=D%fb2J@r$2QppFEMd?bV+V^#RiIu@mX>=0-w-huwZ| zZsd=UnQUeooRGb}Xcl;*Jq0#A4`^x5HC=u7ChP*c3rwBx{qDwtP(GY%Z!kaQgxu+9 z=6k|dJ5=7srsLU`_x{|-VUTx$Lo%l;R}Q_8ULj+FG`+udq{|jv&KC11t-+9Swfh-) zG}Xa;T8}awuv_MI^r)S7BrUKlrsJ8-dusDBk2evrIx$|!wyd=^-kUNONZWOeLJ~^&RXx`$E3& z9gtC9Zrb~I(p+gEFM7aMn8x5(z@u_I`9r1OJg+bY|3J5aU8Utt7VJU>9;0>9p6#zra7Z;i;AqsNAow3!;v{jXVTa9I@9l7R3b16 z?7n1I$m!htlKr}6M;+K6G*)AcU9rH~E}!;)2i)PW9V}Zb3ti#vcFCKLj?WW0+=(>! zJ>g5!@zlTfcW-n-hOK07&wRZ=ZHSBo`hC0~(3yJb`@+KIf041aW=)6qdc=1~V^-$dj2bUf)j_4zTk|E&YOJ6f;J^4~)HF$G3E z4`^>2q%T((Q=crbw#(P{(>ghKvx?>$oOHlxz8))Ee!Id$(%~H1ZRwxE<3n5cw7tz} z#JY}`VS}F>JIg0Bkmg2ce>R=<~sGO^3@fhV%d%RmkeIA@yat56ZBukdfGo2L!T1Vu&BDWzwzp|L8vt*u5 z%>$wzd7R9rGd$C|f6$#VNb`FZG0VP;V85mPX;-=-4RhKp4Q+4lvd7N?Z{+PyMp!$w z?x+>~>AXHVQ)(F60MqC68Oh(;JMHYDTfr~VicFLb%P|kQouG-|PR#>my(UA*=A^Hk zg@XKXb__uDeeP(5-D#ozA!u)G5Ba+i55h&pn$~AS{`Tzmt)=>APtU@C$#S&EGo9^% z`er23`$eWalh1>7a31i-_DFMEdC+_mwHul6vfno?Q22~Bmbbn!oQUIiuWn=1&5dWLe+5hm-~V<;hutfq1+#w4gbyx zf6p=;a%A!B8T1d`je|4H7hfmK1biIX4@kBQnNMeZ*4Ba1`3`3CIjb;E>=UAXC1lc~0hOoHot`BAZ>N@;xvR_ycr$V7WhZJM{V^xMnydja!HJ z6DoZrf6G9#8_~@0JxA*gTnIT~e@K*Vn)jFE;hQ7v2CO%>kY zlnQTg(z%^7{fa=*UQ{>0Mc}9oc@6c-XzEYM;pAtsdqG}#tlKQ#f#KXdVDu4Lj;`=b z^WVUVY&Z6oRabbZ6Bt0&nU2Wo1P1Lxa~$xX^RVsDLyab_H_9-#)2-Ya8Vuc>3n%M$ zy60x<@AvnFyhi2YV0UomGJkLk>XElI&|8CV69(iK{oRNLy~8+n6fjvwxX^PV9QI{+ zB0oETSCXwU!LM^a(cC4lu)j^k*}hJsT&v$#IFNsi>5s#*+Mjocx&-}0I#0*={xP)O z{h)_mWYE*3IsoJUR}d%V3^R4SKy^sW4zS5AJ%mF&5UTEz+vkr)WlcT9)E!xfG$ggn zPR#?#XO9`l(^=m+)PLMkkQ>>#a&JmEuie+P=f5zvpJ7%{N$<)2 zr!NcT{^A2Ij2DvXk|f^V;DRz=@gO~Y`c3^7l$DprMk2mz^9FWe6{FS8=gf)pwB08g zYWP_PbZT7NWiz6Hd**N_jsx=AUnUZ5X;-4Xn(mG?LcYQuJQBKRW_%BQEq=eu7fPBB z?(Z*lA^upn?~-)b+}I&~9YFC>C-vVg^k==?WFwK+OFK0Wh;h>Mdfr{-x3*VgrOi6^ zrBmt0x!y&P)zNXU%~*65{a=fI+kX0dqdt0tH#E_d&iaF2mwSVBUr9HjgSdY!^M^)J zKLGJtOwq``KKQ267Yyp<*Z-z@0SEGTZAaWWqfcA5zj5~a*>+>n+FVh#vQj+sS;pHf z?>0_vGo1yj&y&);UOPc&-!!4Oi^z6Yl~c7nIdu-uSNt&I{bnL==C<8heXzDHucveu zkUm9JcAS|9q`eKP+`7seWqaHAjCmrbI+c3u%=!h}xX#+uuV^M)us*L!^NMz_@P$6f ztiQ#}@qKJ*Ufzynfu2Qpra8MMnd6w6D`-odu&KfyO1r<)xp~0IwR#M@(r<0v#I7<0 zI^jp1Oh4WE#`i)G&F|QqkJ}VI+>xXox6&FL=oPKq zOQ%~eq?>=QDk}Ot;>G9j`sMdhrrvUwvU$@crKP1M$vs{-Q>Ab8ZQa_n%AHqUr=T5A z$lwkBqAN|^!0XNoa&AWalras_aA+QIvutbB$=W4;VhlicLfF;^z#Pm@P9|KN<4Icg zX{Y?4MSIX`oMF{b`$9HVy>sk*Q}D8yZ!74GFgbrpOG|fvKE0Yjr${FabxP1dTyAs+I+Tq72KYabIDgFOq-p9(wvO)20JMC@GUE|E^I zX>C0|!aPKJc&f$ppE@P592kAb$93~QV$*O_U{x=PCv zy+bc!SNg4;TW8}n8=OAq z*hCoA9m^UQE2~$oioY`&&qM#m)z#GVO$^>Q2i#$8U0z4d8;?qss3#q=;Xx372|Zl#^K!Kg*t~hO(s1{^irlu}bkR7K=B#_BDE$lfR-g5KgiqdkKd%3kp5i@| z7~uzW-&a>xy9WMV^bLGzeNjA){9NG+j*#Oc51iN!*g|WJWIkQ(8McvHyUHi*33s6Oo7N(THY|=*OW7&moR&>&w)dXExBWge#vJX)Fm)i+7uMIQm-exr2-f`{za)zy50I^f$WQ>Li&AJkO^*G$B&)CXw$d|=lHf)%4w}9^x?;>bRyB$PhVHqbdRXE-qQZD zrBigOCieqjii4I?l`kqWpF0GrMKq7l4ku_h9T#lMeAv*mSv{)yeu!Y zzj%i=wzOX-p>s*kp$kPgGk!%N*hkP3Hh=nk#VKd2bAQw)koBK_uU)-HUGrxUZ_D8B zC4b7q7y4hA(0>{S)P6o=#*FxWV68rq>wx(FbeapbyR0~MFIFZD?D_^QUb71il<`~a zlFJ$$)wbir{H~}|zR<6mwI-js4{d^7IGdqE=LE|#s(oW`DBezC{(PFyJ-wgq%r2Rp z{9Ia8^naic*SCs5PvwQ#PbQ7+_4+StfA739M>)KBKe-+!*t@ScgP+AP%k+IM!LKv>bXE$|Y2Uq-p71#xm0oXdB!sj$xh5dq zhGdgQS{rGxOo_TD8~=N~jIq6a#qs%BwEuVO^hIsyuUB4r;u&Rh|Dh>iDL&>Ml5{wo46yt4 z(Ca^bZ^4{E(s=-w8$1Pc(GLh!$7ne;4=CNykWS{#_8w!Q%k3?Xi;6ljjdVXb(qrbn zsJO0JO1~%a-?pR=yrx>>*ZLUWFdh2y{OBxgO*fYc`P0prm-<7+B8(Ludv&iT9z*v& zSoz@1x0SJ@&rI6SH>B4=s=gn8aKE_T)BM2ri?2}T&Uq{TPJfPACK;gbUm4T^E2d4G zmSm5I?w^3Zz#D>=6Z3#*d;TNncNO1eTgZmCj*;!a4S9Q%vpN=~^RBY`qjUA0l})pO z?h(zE1w@-VUDJQ1Z=kojUKM+P&KK__f4&^g$}{wHGQW`hW3W_HV!9 zT4ni?WokIt_Fr01@(;6o(ciB&(0^JR^a<7nCfN}C1%g#%ry$x6%>%CK4CUV}cC;qk z=Cb&%S>8^EL%N=}Ic;(~yCmCv&f0z}`|K^o{ev}nTNLyzegS!2ME#91#M4%IQdsE!*Xim2^bgY7qiyc{iuR#PoC&6_nXzx*FZ7@K z-B$C?$?&$WYff!vn`u8uHu6J9ow}PkRt9zZeM<9!J%p~2Pj_*V+-U#f`}VZ&ORIBo zlJ*E&O&{hMKa_d(FX*k%n&9w)pOWVP7k>YP`d(fu5Q`^lbmlo@9^m?P`j7XU(MLGM zh?+z5fNvV{>TK^&2JOBVbhFR5K;4hkS<Y9{C&ezgE`&`n&FpuL01{|B-#*&a1AM_y?7; zKyau`&&)GyeW48cPiupgPMq{_MR=$`zTT$G0>5_PN6Q zBCT|$m*}6_>Z1>NK{n|`yjLBQ$rJv!EEC4`C(1gB=hgV$jpoCX-g}Gt%ki>#Mjdit z5>50s$Ob@ber5gNv~i;{;nJ&;bYG3<-P4l|U+DNZnd^YM_a;r6^oL~H&ddX%A3QLb zPv`kX_9xug{h8fm59Rs%&XdYyNnq!=$L{n>^wtD)w)SN1#=p=;pC{39v`&Ifo~75x zN?(zi&exFM|4L_h8cS>bE$-zh7c|c~dU#yF&#xM#%$WRu`g=*FF}~)9&ijEAdp4@moI5|VYUC-iylbD-Qc(H{5CmC}SXG%i7!8y!fu zs<+wfd8E5iAdkI$Fww`+-NS(UcrFtjAO}KKIaL%9IIrihANTW2&vc#af_Vt?55~hdpqZOwFNrz)xfzo#h#I z-MP-_K=hf;lE!p$IDZaj)4fMteC$Mipl@-y%rnit__1`Rx6nr_G^xz~;_& zCK&E}8I7{$%o#MU@DLf(&iah>Kj(zLsWe@YMON)ThAOY z?0(X{4Q9^yl4)jo2ECVv*CiuPRrUYZl`E6Z`lN4Hoqn!DHUQH9ssqYZ{U-t}pG&f2#otX#hEN6nz{kiHIUq||yXluTO4ZKZrMy=(mUEjUl#UAL}Iwy3F zXzK0mt;wyOVQTBxUzNiZy+P)UzWs30xg@9U@xi;zSQ~6>{|$A^ZN%%SlD_Ksej^SY zsPd-%KG^|;9A^w3rhN0+7xCY8pO`GS)n}~x-`j-#r`V~TmvYIQM>zN73~eM zB6DkD>Hc5AN2~!N|M^FsP#PD7mAX47$JYdk?+CwvHZy=kGbdK_l;;-eTP24gjV!_LMlyX<^kLHOfaPz zt>;JH--z{`!Edo9v90`J-`}Sd{Xf}=ha>ZV?#L(Dhy9Av4)^Z9jWV>_ z?sAloo-6XHm3Gbu^NxH++7HzN52Jp(p*>ZOT*7@9;M*la=o;~}IMzTA0 zE@*b`hg^<2-E(KKZ5rjF)puA2Ioy7|ORO{YxuX?kWWre;N7^k1rA_9Iw*G_^{r3hJ zw05_rOvB8xG^ZH1>!Jm~yVf9K3~;8A{^R|tnbLqfaPs`fPN&CNmbu1k_r7Ps zzN5aO-}iEsIJBOhp2&A*?4#N}M!(rA2kvx}F@;TTcj#FBd`?Lxzr?(INDkYUXKha5 zEzq~_{K2Gs3s&W5XlU?L`wrdz)=2;5yF!Sze$A>A^MJPIX~*{^wwP_xtma)ug{L!e zkw^CGUUEKFn@Jn$p=WF^D-k_koX_*Fr1x_Byn)WlM|fMu0>q!r-6tDEIw#KK(aUP} zcYS@$Na*+ZF<(6ooc8@CIXWvurVG5s(!C7gokR10t+x}&<)t%+Z`1j=0_V===VQN| z&AKP&p{aXBF%Ni({W2`tOU4?u{xj3)zgidIJdhWupCHF+>$7_1c$)q`$x@mZ%IXXS zAs5#D?+87gh`#-2+H;zHfT`>L$Zk$&L!%$J-TpPE-!->X zS66R`XWe}u@&5lB^!=0WaKs+nD>bY)(V5YroB^{@cILrWKIdV4L$%$lA{Sm*&^82n4&X-(!#H zF1W|>X9qFPc#kOb-)}$f@U!|H!CHVvP3k|@0lztA8`R6y+HbVs9?b2(FX?v+^uChr z{L;n&N%lT1+yJo&jX^*Py2^tT(*U0^#4w>UkBs%pB6fMEfbF5 z{iV(PTYR~Zq&8gZ1JL>$(cd@YKV|nmflN5)zhV4-B=mWer2C}n>K;4P0mtgz$Lj&q z3)OmB+Im^JO~zbF!alRD&jZqVHo3VG!*x=6EVsVj*hk@xyl%4&%4IF%J)+wF4LQ6G z&*4Y)`2-u^br$tsLBF99;4l-{~FZ19kHl zG`|=AC=I?+o@|5jfLN=gV85;VC?nNr%89I3**>pNzc*Cve?%PM{l30lFNf_7 z_W5O5)B&n(Fxz_q&6F+Z^$_U(N@Lxwn=NSI`-eth&_B3Ggb_a4{WRD|!jZoX z%>&Zfw`w{wKu-U*{!Ht3VGH~&ZFy=soS>Z!ywqyra84)w5<}bwqrQPagAsrr+nI+4Wau zz%}Xqifv#Xa1+gU^~n1vFT0%D`eOxhBZs2AIJqX^SR)kCPW8`FPP6TEP`vdR=jI#n z6z|mYdvT8^?Z-zw5HVR7JXz7B$1Z|Kwm#YSq2F`U=)LIoj~4V1?gN9cKhr({5hmtS zpQ`os)z~u?KLd3uo(Ei^o;j1nnf1w-ZX3U#Gcz30MbgJ8`dxq3BNO&!H~JG-t4s=KAHhR-V!39|2unVW7|Pb{*edBYPjwMO`t- zAnbbd3Hs>yVxPCUyB2hNrhxy}G7m^=nrC24GssHb>v7x`e{1c4W9O*p&*~ExJ9Hk6 z+IPTtG!F=v^5 z>m|dQwBsz&vBVo?Bjt=TT0=W$&K%QcaME5O^{h{Sa5n0Km7+d?P4UADU(W)4n)JUh zj?YDV{kB0nE_6QbBiw}|KGp&pri-)INcXk#o-Lh)C!gO+b0)Uuf$nY=ktX&#GXhFC z^daA}y)49Sh;(0f@;#z7E&x9#=OCNV$57|cWaMeS9lACh{qcElv*BQis~ZDX3Fj02 zZ#fP<(;0)pj)=7dub?hit*sl>2UUNARylNdsZNjM`YykxwjTDp?FAux`=9iE3Hk*o zXD(}ZtXe&N%)Q#&u>pGcxs!4ZL=ewe3I>=9q7dBwNVW<)E(9?sVYhj^pCVbLq3jYQi zn)sT3gT@HBJ~U?szq|G=lfEZ?L!4?^HpHj4e+!7;AomGG7}{e6%(Bvb4eKVVKLkA| z<^eIbi`Qp@5Br@T0a_D{GV+6iI{CPaLZK_%9lRWze~j--Xu?_UC(FFWGqvfYgV4E6 za7nu9{O`Iiq2uv$j2jwiD!}t2=>GmfKG~ zQ3{!4Ut6nT%UGSxV@{&&j?S|e`_w&|GCzLq+z2=@CKP>f+#wkKiOvHR2w>gH750|B zc$**RDbpuAC*4gh`0IW21@?h^3iW{5@q3nihPu0D-s$X)nvIUuYTI~rQgkWk#_Ji( z1KuEGWW)2CboH#9W`6FR2w-jS?kEGRY$ylmbnq6Dayp;VDLxtK{z~T&3K@)in!6+0 zAL@ed9Ox5#3!DCqMttRWzCEG^cAuFfFp=kE9hnEri?-?9Lm3BtZhr(Ew#{u$-j5n_ zY#)Ls??yh|TP4ep4rSBf3IxcphTG<$a9{d%MRKojE8eB*7PGtkJcC-YX%OOM%N zHyX)p$2*(}dv$`R1M`5c@Kp)={M7XjP|uKh*N(E5hQ>Rh4~jndt!cs-_8)8xy9M^D zDVfFu`n*Hiy*qUIP`EMFM}SXj2qvSSFa>i0x8V62%-vlKe<<|55PS3uZ4P?6>bhuG z_$;I^Y;zh@adbuAlleO^=6hYH&(B>C0dH<3gmOq{CZv`h8{UaEdUR%xQ#>rt-5k58 zEcsrs_Q*Awk0YBoWOZKe6Zy79KL5&rdBBa^?ioAnQEJ+Uhr@02O4@%w{Q%ejms-$O zN9vqeseNLQ|`zMn~{0{v+Y@~|qC2#>J=omq}K3fQyS)}ATdV&^VJM`B<4 zgGg(pz50T`Gd|9MEpRXL=}QyRY4bc_gV@#UpeTnagc{ybwF39vzh90qx_|J4$K2$%>wl)5{}ki(7a0~ zrP>$$`&A#5dfB%zK8@m4Ni`Y3)AnTn*<``KL85PS!C_$=y}x!j2m? zJdY`n>-NtBI#^!Xg8R5cn)%5r0;q4#cQ8LO*Bu`3ApN$Km#!WcceEzX{>qf!s3RWP z+VcSAIPKY#nXut+%J#tS0|(2;C!mdX%CSC1SJ&fgr(3F1nsQ>XIJ#1){)>4MhLXSnt-jVthK+s z%%D6n$~!af?4AegjBQ1}EApfnEI5oY0(7TzXUx}aT&DGOmaB1&nSblRJYZ+6&sT{3 zC+3mikTL?$wWqgned|2s8f%vAo7dh}<^kJ(uZOHZUHzHHm(c&UTnBXMSb44A6TZZ5 zd-k?44@i4Fy1EW_wEV#EV%Gl-)Boq_4ge?0z_u_CNb3llz;0WjN&DEK{~vQ5(0+9Q z?MW(dh5I^L&bH$F0pnvfnjdu%!)=AOb_bP{YXahVmTf&l>&_9kBlg+0S@w9EF~;|K zB8RtEx!M-y0qIQT_QG>(=7T+PljG&I{pY({*D;)@MQs}Td^bYQUplp{$@n!x51(vJ(`4YfA@z~RFfp*R=+S>LT$EWa8bv}Go zY=3^@d~UtW?e}||mAnHRA>n7K{-OI9Gs)Ib-+;$fzaOw8`&b>7uTJspk@r&`^k#i$tOKmxO-pBz#Lgy) zT#ocigN7y(9r5nu!u0Y-okU<4Qe zMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-ok zU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u z0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r z5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE> z7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EE zfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u z1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4Qe zMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-ok zU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u Jf%Zq>{{f^u2toh= diff --git a/AsbCloudWebApi/wwwroot/index.html b/AsbCloudWebApi/wwwroot/index.html index d2c883f8..80927d26 100644 --- a/AsbCloudWebApi/wwwroot/index.html +++ b/AsbCloudWebApi/wwwroot/index.html @@ -1 +1 @@ -АСБ Vision
\ No newline at end of file +DDrilling
\ No newline at end of file diff --git a/AsbCloudWebApi/wwwroot/manifest.json b/AsbCloudWebApi/wwwroot/manifest.json deleted file mode 100644 index 1f2f141f..00000000 --- a/AsbCloudWebApi/wwwroot/manifest.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} diff --git a/AsbCloudWebApi/wwwroot/robots.txt b/AsbCloudWebApi/wwwroot/robots.txt deleted file mode 100644 index e9e57dc4..00000000 --- a/AsbCloudWebApi/wwwroot/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: From 1e34f137cf2adb6d34ab1a71385e54692ae67dd4 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Mon, 3 Oct 2022 16:04:25 +0500 Subject: [PATCH 20/37] rename method --- AsbCloudWebApi/Controllers/FileController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index f598bc34..a7711247 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -236,7 +236,7 @@ namespace AsbCloudWebApi.Controllers [Route("/api/files/{idFile}")] [Permission] [ProducesResponseType(typeof(FileInfoDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetFileInfoByIdAsync([FromRoute] int idFile, CancellationToken token = default) + public async Task GetFileInfoAsync([FromRoute] int idFile, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); From 44e96e1ad17b942eb82bfa6863f986bb92eaabca Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 4 Oct 2022 09:09:35 +0500 Subject: [PATCH 21/37] DailyReportService.GetOrGenerateAsync() truncate time of DateTime --- .../Services/DailyReport/DailyReportService.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs index 807b10ca..afa6c0df 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs @@ -48,9 +48,10 @@ namespace AsbCloudInfrastructure.Services.DailyReport public async Task GetOrGenerateAsync(int idWell, DateTime date, CancellationToken token) { - var dailyReportDto = await GetAsync(idWell, date, token); + var dateOnly = DateTime.SpecifyKind(date.Date, DateTimeKind.Unspecified); + var dailyReportDto = await GetAsync(idWell, dateOnly, token); if (dailyReportDto is null) - dailyReportDto = await MakeDefaultDailyReportAsync(idWell, date, token); + dailyReportDto = await MakeDefaultDailyReportAsync(idWell, dateOnly, token); return dailyReportDto; } From 03e50a429711c26aa1e4a3d657264ca346c7a170 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Wed, 5 Oct 2022 15:47:02 +0500 Subject: [PATCH 22/37] #6539681 test file service --- AsbCloudWebApi.Tests/IRepositoryFactory.cs | 17 ++ AsbCloudWebApi.Tests/RepositoryFactory.cs | 44 ++++ .../ServicesTests/FileServiceTest.cs | 222 ++++++++++++++++++ AsbCloudWebApi.Tests/TestHelpter.cs | 3 +- 4 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 AsbCloudWebApi.Tests/IRepositoryFactory.cs create mode 100644 AsbCloudWebApi.Tests/RepositoryFactory.cs create mode 100644 AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs diff --git a/AsbCloudWebApi.Tests/IRepositoryFactory.cs b/AsbCloudWebApi.Tests/IRepositoryFactory.cs new file mode 100644 index 00000000..e7028689 --- /dev/null +++ b/AsbCloudWebApi.Tests/IRepositoryFactory.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudWebApi.Tests +{ + public interface IRepositoryFactory + { + Task DeleteAsync(int id, CancellationToken token); + Task> GetAllAsync(CancellationToken token); + TDto? GetOrDefault(int id); + Task GetOrDefaultAsync(int id, CancellationToken token); + Task InsertAsync(TDto newItem, CancellationToken token); + Task InsertRangeAsync(IEnumerable newItems, CancellationToken token); + Task UpdateAsync(TDto item, CancellationToken token); + } +} \ No newline at end of file diff --git a/AsbCloudWebApi.Tests/RepositoryFactory.cs b/AsbCloudWebApi.Tests/RepositoryFactory.cs new file mode 100644 index 00000000..8495751c --- /dev/null +++ b/AsbCloudWebApi.Tests/RepositoryFactory.cs @@ -0,0 +1,44 @@ +using AsbCloudApp.Services; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudWebApi.Tests +{ + public class RepositoryFactory + { + public static Mock Make(IList data) + where TDto : AsbCloudApp.Data.IId + where TRepository : class, ICrudService + { + var repositoryMock = new Mock(); + + repositoryMock.Setup(x => x.InsertAsync(It.IsAny(), It.IsAny())) + .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(), It.IsAny())) + .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())).ReturnsAsync(data); + repositoryMock.Setup(x => x.GetOrDefaultAsync(It.IsAny(), It.IsAny())) + .Returns((int idFile, CancellationToken token) => { + return Task.FromResult(data.FirstOrDefault(x => x.Id == idFile)); + }); + + return repositoryMock; + } + } +} diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs new file mode 100644 index 00000000..bf3c6442 --- /dev/null +++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs @@ -0,0 +1,222 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Services; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services; +using DocumentFormat.OpenXml.Spreadsheet; +using DocumentFormat.OpenXml.Wordprocessing; +using Moq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Xunit; +using static AsbCloudWebApi.Tests.TestHelpter; + +namespace AsbCloudWebApi.Tests.ServicesTests +{ + public class FileServiceTest + { + private IFileService fileService; + + private static UserDto Author = new UserDto { + Id = 1, + IdCompany = 1 + }; + + private static List FileMarks = new List { + new FileMarkDto + { + Id = 132, + IdFile = 1742, + User = Author, + Comment = "qqq", + IdMarkType = 1, + DateCreated = DateTime.Now, + IsDeleted = false + }, + new FileMarkDto + { + Id = 133, + IdFile = 1742, + User = Author, + Comment = "qqq3", + IdMarkType = 1, + DateCreated = DateTime.Now, + IsDeleted = false + } + }; + + private static List Files = new List { + new FileInfoDto { + Id = 1742, + IdAuthor = 1, + Author = Author, + IdWell = 90, + IdCategory = 10040, + Name = "test.txt", + Size = 0, + UploadDate = DateTime.Now, + FileMarks = FileMarks + }, + new FileInfoDto + { + Id = 1743, + IdAuthor = 1, + Author = Author, + IdWell = 90, + IdCategory = 10021, + Name = "test1.txt", + Size = 0, + UploadDate = DateTime.Now + } + }; + + public FileServiceTest() + { + var repositoryMock = RepositoryFactory.Make(Files); + + repositoryMock.Setup(x => x.GetByMarkId(It.IsAny(), It.IsAny())) + .Returns((int idMark, CancellationToken token) => { + var data = Files.FirstOrDefault(x => x.FileMarks.Any(m => m.Id == idMark)); + return Task.FromResult(data); + }); + repositoryMock.Setup(x => x.GetInfoByIdsAsync(It.IsAny>(), It.IsAny())) + .Returns((int[] idsFile, CancellationToken token) => { + var data = Files.Where(x => idsFile.Contains(x.Id)); + return Task.FromResult(data); + }); + + repositoryMock.Setup(x => x.DeleteAsync(It.IsAny>(), It.IsAny())) + .Returns((int[] idsFile, CancellationToken token) => { + var dtos = Files.Where(x => idsFile.Contains(x.Id)).ToArray(); + Files.RemoveAll(x => dtos.Select(d => d.Id).Contains(x.Id)); + return Task.FromResult(dtos.AsEnumerable()); + }); + + repositoryMock.Setup(x => x.MarkFileMarkAsDeletedAsync(It.IsAny>(), It.IsAny())) + .Returns((int[] idsMarks, CancellationToken token) => { + var data = FileMarks.Where(m => idsMarks.Contains(m.Id)); + + foreach (var fileMark in data) + fileMark.IsDeleted = true; + + var result = data.All(x => x.IsDeleted) ? 1 : 0; + return Task.FromResult(result); + }); + + repositoryMock.Setup(x => x.MarkAsDeletedAsync(It.IsAny(), It.IsAny())) + .Returns((int idFile, CancellationToken token) => { + var result = Files.Where(x => x.Id == idFile).Any() ? 1 : 0; + return Task.FromResult(result); + }); + + repositoryMock.Setup(x => x.GetInfosByWellIdAsync(It.IsAny(), It.IsAny())) + .Returns((int idWell, CancellationToken token) => { + var data = Files.Where(x => x.IdWell == idWell); + return Task.FromResult(data); + }); + + repositoryMock.Setup(x => x.GetInfosByCategoryAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((int idWell, int idCategory, CancellationToken token) => { + var data = Files.Where(x => x.IdWell == idWell && x.IdCategory == idCategory); + return Task.FromResult(data); + }); + + repositoryMock.Setup(x => x.CreateFileMarkAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((FileMarkDto dto, int idUser, CancellationToken token) => { + dto.Id = FileMarks.Max(x => x.Id) + 1; + dto.DateCreated = DateTime.UtcNow; + dto.User = null; + FileMarks.Add(dto); + + var result = FileMarks.Any(x => x.Id == dto.Id) ? 1 : 0; + return Task.FromResult(result); + }); + + fileService = new FileService(repositoryMock.Object); + } + + [Fact] + public async Task GetByMarkId_returns_FileInfo_by_idMark() + { + var data = await fileService.GetByMarkId(133, CancellationToken.None); + Assert.NotNull(data); + } + + [Fact] + public async Task GetInfoAsync_throws_FileNotFoundException() + { + await Assert.ThrowsAsync(async () => + { + await fileService.GetInfoAsync(1743, CancellationToken.None); + }); + } + + [Fact] + public async Task GetInfoByIdsAsync_throws_FileNotFoundException() + { + await Assert.ThrowsAsync(async () => + { + await fileService.GetInfoByIdsAsync(new int[] { 1742, 1743 }, CancellationToken.None); + }); + } + + [Fact] + public async Task SaveAsync_returns_FileInfoa() + { + var stream = new FileStream("D:\\test\\test.txt", FileMode.Open); + var data = await fileService.SaveAsync(90, 1, 10040, "test.txt", stream, CancellationToken.None); + Assert.NotNull(data); + } + + [Fact] + public async Task DeleteAsync() + { + var result = await fileService.DeleteAsync(new int[] { 1743 }, CancellationToken.None); + Assert.True(result > 0); + } + + [Fact] + public async Task MarkFileMarkAsDeletedAsync() + { + var result = await fileService.MarkFileMarkAsDeletedAsync(new int[] { 132, 133 }, CancellationToken.None); + Assert.True(result > 0); + } + + [Fact] + public async Task MarkAsDeletedAsync() + { + var result = await fileService.MarkAsDeletedAsync(1742, CancellationToken.None); + Assert.True(result > 0); + } + + [Fact] + public async Task GetInfosByWellIdAsync_returns_FileInfo() + { + var data = await fileService.GetInfosByWellIdAsync(90, CancellationToken.None); + Assert.NotNull(data); + } + + [Fact] + public async Task GetInfosByCategoryAsync_returns_FileInfo() + { + var data = await fileService.GetInfosByCategoryAsync(90, 10040, CancellationToken.None); + Assert.NotNull(data); + } + + [Fact] + public async Task CreateFileMarkAsync() + { + var dto = new FileMarkDto { + Comment = "test", + IdFile = 1742, + IdMarkType = 1 + }; + var result = await fileService.CreateFileMarkAsync(dto, 1, CancellationToken.None); + Assert.True(result > 0); + } + } +} diff --git a/AsbCloudWebApi.Tests/TestHelpter.cs b/AsbCloudWebApi.Tests/TestHelpter.cs index 9322503b..f7c8e8a9 100644 --- a/AsbCloudWebApi.Tests/TestHelpter.cs +++ b/AsbCloudWebApi.Tests/TestHelpter.cs @@ -1,4 +1,5 @@ -using AsbCloudDb.Model; +using AsbCloudApp.Services; +using AsbCloudDb.Model; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; From b6ce4cad7712bd4091f1829692c0d6d83629840f Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Thu, 6 Oct 2022 13:41:46 +0500 Subject: [PATCH 23/37] #6539681 file storage repository + tests --- AsbCloudApp/AsbCloudApp.csproj | 8 +++ AsbCloudApp/Services/IFileService.cs | 5 -- .../Services/IFileStorageRepository.cs | 51 ++++++++++++++++ AsbCloudInfrastructure/DependencyInjection.cs | 1 + .../Repository/FileStorageRepository.cs | 59 +++++++++++++++++++ .../DrillingProgram/DrillingProgramService.cs | 3 +- .../Services/FileService.cs | 41 ++++--------- .../Services/ReportService.cs | 3 +- AsbCloudWebApi.Tests/RepositoryFactory.cs | 4 +- .../ServicesTests/FileServiceTest.cs | 25 ++++---- 10 files changed, 150 insertions(+), 50 deletions(-) create mode 100644 AsbCloudApp/Services/IFileStorageRepository.cs create mode 100644 AsbCloudInfrastructure/Repository/FileStorageRepository.cs diff --git a/AsbCloudApp/AsbCloudApp.csproj b/AsbCloudApp/AsbCloudApp.csproj index 64a7b66a..5c826cb1 100644 --- a/AsbCloudApp/AsbCloudApp.csproj +++ b/AsbCloudApp/AsbCloudApp.csproj @@ -13,4 +13,12 @@ + + + + + + + + diff --git a/AsbCloudApp/Services/IFileService.cs b/AsbCloudApp/Services/IFileService.cs index a83d6d5c..a87397f7 100644 --- a/AsbCloudApp/Services/IFileService.cs +++ b/AsbCloudApp/Services/IFileService.cs @@ -14,11 +14,6 @@ namespace AsbCloudApp.Services ///
public interface IFileService { - /// - /// Директория хранения файлов - /// - string RootPath { get; } - /// /// Сохранить файл /// diff --git a/AsbCloudApp/Services/IFileStorageRepository.cs b/AsbCloudApp/Services/IFileStorageRepository.cs new file mode 100644 index 00000000..6659e976 --- /dev/null +++ b/AsbCloudApp/Services/IFileStorageRepository.cs @@ -0,0 +1,51 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Services +{ + /// + /// Репозиторий хранения фалов + /// + public interface IFileStorageRepository + { + /// + /// Директория хранения файлов + /// + string RootPath { get; } + + /// + /// Получение длинны фала и проверка его наличия, если отсутствует падает исключение + /// + /// + /// + long GetLengthFile(string srcFilePath); + + /// + /// Перемещение файла + /// + /// + /// + void MoveFile (string srcFilePath, string filePath); + + /// + /// Копирование файла + /// + /// + Task CopyFileAsync(string filePath, Stream fileStream, CancellationToken token); + + /// + /// Удаление файла + /// + /// + void DeleteFile(string fileName); + + /// + /// Проверка наличия файла + /// + /// + /// + /// + bool FileExists(string fullPath, string fileName); + } +} diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index f178b648..5c1bf56f 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -155,6 +155,7 @@ namespace AsbCloudInfrastructure .Include(c => c.Wells) .Include(c => c.Deposit))); // может быть включен в сервис ClusterService services.AddTransient(); + services.AddTransient(); // Subsystem service services.AddTransient, CrudCacheServiceBase>(); services.AddTransient(); diff --git a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs new file mode 100644 index 00000000..6cb38cfb --- /dev/null +++ b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs @@ -0,0 +1,59 @@ +using AsbCloudApp.Exceptions; +using AsbCloudApp.Services; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Repository +{ + public class FileStorageRepository : IFileStorageRepository + { + public string RootPath { get; private set; } + + public FileStorageRepository() + { + RootPath = "files"; + } + + public async Task CopyFileAsync(string filePath, Stream fileStream, CancellationToken token) + { + CreateDirectory(filePath); + using var newfileStream = new FileStream(filePath, FileMode.Create); + await fileStream.CopyToAsync(newfileStream, token).ConfigureAwait(false); + } + + public void DeleteFile(string fileName) + { + if (File.Exists(fileName)) + File.Delete(fileName); + } + + public long GetLengthFile(string srcFilePath) + { + if (!File.Exists(srcFilePath)) + throw new ArgumentInvalidException($"file {srcFilePath} doesn't exist", nameof(srcFilePath)); + + var sysFileInfo = new FileInfo(srcFilePath); + return sysFileInfo.Length; + } + + public void MoveFile(string srcFilePath, string filePath) + { + CreateDirectory(filePath); + File.Move(srcFilePath, filePath); + } + + public bool FileExists(string fullPath, string fileName) + { + if (!File.Exists(fullPath)) + throw new FileNotFoundException("not found", fileName); + + return true; + } + + private void CreateDirectory(string filePath) + { + Directory.CreateDirectory(Path.GetDirectoryName(filePath)); + } + } +} diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index 0e840524..2780e7b1 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -481,7 +481,8 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram .Options; using var context = new AsbCloudDbContext(contextOptions); var fileRepository = new FileRepository(context); - var fileService = new FileService(fileRepository); + var fileStorageRepository = new FileStorageRepository(); + var fileService = new FileService(fileRepository, fileStorageRepository); var files = state.Parts.Select(p => fileService.GetUrl(p.File)); DrillingProgramMaker.UniteExcelFiles(files, tempResultFilePath, state.Parts, well); await fileService.MoveAsync(idWell, null, idFileCategoryDrillingProgram, resultFileName, tempResultFilePath, token); diff --git a/AsbCloudInfrastructure/Services/FileService.cs b/AsbCloudInfrastructure/Services/FileService.cs index cdfed260..5cb60fcd 100644 --- a/AsbCloudInfrastructure/Services/FileService.cs +++ b/AsbCloudInfrastructure/Services/FileService.cs @@ -16,13 +16,13 @@ namespace AsbCloudInfrastructure.Services { public class FileService : IFileService { - public string RootPath { get; private set; } private readonly IFileRepository fileRepository; + private readonly IFileStorageRepository fileStorageRepository; - public FileService(IFileRepository fileRepository) + public FileService(IFileRepository fileRepository, IFileStorageRepository fileStorageRepository) { - RootPath = "files"; this.fileRepository = fileRepository; + this.fileStorageRepository = fileStorageRepository; } public async Task MoveAsync(int idWell, int? idUser, int idCategory, @@ -30,10 +30,7 @@ namespace AsbCloudInfrastructure.Services { destinationFileName = Path.GetFileName(destinationFileName); srcFilePath = Path.GetFullPath(srcFilePath); - if (!File.Exists(srcFilePath)) - throw new ArgumentInvalidException($"file {srcFilePath} doesn't exist", nameof(srcFilePath)); - - var sysFileInfo = new System.IO.FileInfo(srcFilePath); + var fileSize = fileStorageRepository.GetLengthFile(srcFilePath); //save info to db var dto = new FileInfoDto { @@ -41,14 +38,13 @@ namespace AsbCloudInfrastructure.Services IdAuthor = idUser, IdCategory = idCategory, Name = destinationFileName, - Size = sysFileInfo.Length + Size = fileSize }; var fileId = await fileRepository.InsertAsync(dto, token) .ConfigureAwait(false); string filePath = MakeFilePath(idWell, idCategory, destinationFileName, fileId); - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); - File.Move(srcFilePath, filePath); + fileStorageRepository.MoveFile(srcFilePath, filePath); return await GetInfoAsync(fileId, token); } @@ -71,18 +67,14 @@ namespace AsbCloudInfrastructure.Services //save stream to disk string filePath = MakeFilePath(idWell, idCategory, fileFullName, fileId); - - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); - - using var newfileStream = new FileStream(filePath, FileMode.Create); - await fileStream.CopyToAsync(newfileStream, token).ConfigureAwait(false); + await fileStorageRepository.CopyFileAsync(filePath, fileStream, token); return await GetInfoAsync(fileId, token); } private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) { - return Path.Combine(RootPath, $"{idWell}", + return Path.Combine(fileStorageRepository.RootPath, $"{idWell}", $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); } @@ -95,10 +87,7 @@ namespace AsbCloudInfrastructure.Services var relativePath = GetUrl(dto.IdWell, dto.IdCategory, dto.Id, ext); var fullPath = Path.GetFullPath(relativePath); - if (!File.Exists(fullPath)) - { - throw new FileNotFoundException("not found", relativePath); - } + fileStorageRepository.FileExists(fullPath, relativePath); return dto; } @@ -119,8 +108,7 @@ namespace AsbCloudInfrastructure.Services foreach (var file in files) { var fileName = GetUrl(file.IdWell, file.IdCategory, file.Id, Path.GetExtension(file.Name)); - if (File.Exists(fileName)) - File.Delete(fileName); + fileStorageRepository.DeleteFile(fileName); } return files.Any() ? 1 : 0; @@ -137,7 +125,7 @@ namespace AsbCloudInfrastructure.Services GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) => - Path.Combine(RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); + Path.Combine(fileStorageRepository.RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); public Task MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token) @@ -153,12 +141,9 @@ namespace AsbCloudInfrastructure.Services var ext = Path.GetExtension(entity.Name); var relativePath = GetUrl(entity.IdWell, entity.IdCategory, entity.Id, ext); var fullPath = Path.GetFullPath(relativePath); - if (!File.Exists(fullPath)) - { - throw new FileNotFoundException("not found", relativePath); - } + fileStorageRepository.FileExists(fullPath, relativePath); } - + return result; } diff --git a/AsbCloudInfrastructure/Services/ReportService.cs b/AsbCloudInfrastructure/Services/ReportService.cs index 53d8653a..7d60f852 100644 --- a/AsbCloudInfrastructure/Services/ReportService.cs +++ b/AsbCloudInfrastructure/Services/ReportService.cs @@ -67,7 +67,8 @@ namespace AsbCloudInfrastructure.Services generator.Make(reportFileName); var fileRepository = new FileRepository(context); - var fileService = new FileService(fileRepository); + var fileStorageRepository = new FileStorageRepository(); + var fileService = new FileService(fileRepository, fileStorageRepository); var fileInfo = await fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName, token); progressHandler.Invoke(new diff --git a/AsbCloudWebApi.Tests/RepositoryFactory.cs b/AsbCloudWebApi.Tests/RepositoryFactory.cs index 8495751c..a8588dda 100644 --- a/AsbCloudWebApi.Tests/RepositoryFactory.cs +++ b/AsbCloudWebApi.Tests/RepositoryFactory.cs @@ -1,9 +1,7 @@ using AsbCloudApp.Services; using Moq; -using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; @@ -11,7 +9,7 @@ namespace AsbCloudWebApi.Tests { public class RepositoryFactory { - public static Mock Make(IList data) + public static Mock Make(ICollection data) where TDto : AsbCloudApp.Data.IId where TRepository : class, ICrudService { diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs index bf3c6442..828f19ae 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs @@ -1,6 +1,7 @@ using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; using AsbCloudInfrastructure.Services; using DocumentFormat.OpenXml.Spreadsheet; using DocumentFormat.OpenXml.Wordprocessing; @@ -136,7 +137,11 @@ namespace AsbCloudWebApi.Tests.ServicesTests return Task.FromResult(result); }); - fileService = new FileService(repositoryMock.Object); + var storageRepositoryMock = new Mock(); + + storageRepositoryMock.Setup(x => x.RootPath).Returns("files"); + + fileService = new FileService(repositoryMock.Object, storageRepositoryMock.Object); } [Fact] @@ -147,27 +152,23 @@ namespace AsbCloudWebApi.Tests.ServicesTests } [Fact] - public async Task GetInfoAsync_throws_FileNotFoundException() + public async Task GetInfoAsync_returns_FileInfo() { - await Assert.ThrowsAsync(async () => - { - await fileService.GetInfoAsync(1743, CancellationToken.None); - }); + var data = await fileService.GetInfoAsync(1742, CancellationToken.None); + Assert.NotNull(data); } [Fact] - public async Task GetInfoByIdsAsync_throws_FileNotFoundException() + public async Task GetInfoByIdsAsync_returns_FileInfo() { - await Assert.ThrowsAsync(async () => - { - await fileService.GetInfoByIdsAsync(new int[] { 1742, 1743 }, CancellationToken.None); - }); + var data = await fileService.GetInfoByIdsAsync(new int[] { 1742, 1743 }, CancellationToken.None); + Assert.NotNull(data); } [Fact] public async Task SaveAsync_returns_FileInfoa() { - var stream = new FileStream("D:\\test\\test.txt", FileMode.Open); + using var stream = new MemoryStream(); var data = await fileService.SaveAsync(90, 1, 10040, "test.txt", stream, CancellationToken.None); Assert.NotNull(data); } From ea1eb20f821782cb583a17b864f56e999ad550d7 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 6 Oct 2022 13:49:20 +0500 Subject: [PATCH 24/37] 1-st try --- .../Services/SAUB/TelemetryDataBaseService.cs | 13 +- .../Services/SAUB/TelemetryDataSaubService.cs | 44 ++++++ .../Services/SAUB/TelemetryDataSpinService.cs | 7 + AsbCloudInfrastructure/Startup.cs | 1 + .../AsbCloudWebApi.Tests.csproj | 2 + ConsoleApp1/ConsoleApp1.csproj | 1 + ConsoleApp1/Program.cs | 140 +++++++++++------- 7 files changed, 153 insertions(+), 55 deletions(-) diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs index ebfe6822..5231e573 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs @@ -16,7 +16,7 @@ namespace AsbCloudInfrastructure.Services.SAUB where TDto : AsbCloudApp.Data.ITelemetryData where TModel : class, AsbCloudDb.Model.ITelemetryData { - private readonly IAsbCloudDbContext db; + protected readonly IAsbCloudDbContext db; private readonly ITelemetryService telemetryService; protected readonly CacheTable cacheTelemetry; protected readonly CacheTable cacheTelemetryUsers; @@ -170,5 +170,16 @@ namespace AsbCloudInfrastructure.Services.SAUB return offset; } + + /// + /// Прореживание данных телеметрии. + /// Каждая ratio запись будет сохранена, остальные удаляются. Остаются (Row_number % ratio) = 0. + /// Из-за возможности запуска повторного прореживания можно ограничить величину разрыва по времени параметром maxDateGapSec. + /// + /// Id телеметрии + /// желаемое отношение оставшихся записей к исходным + /// ограничение разрыва по времени + /// + public abstract Task<(int oldCount, int newCount)> RediceSamplingAsync(int idTelemetry, int ratio, int maxDateGapSec, CancellationToken token); } } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs index 2941b1ca..a6330757 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs @@ -2,7 +2,12 @@ using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.Cache; +using DocumentFormat.OpenXml.Drawing.Charts; using Mapster; +using Microsoft.EntityFrameworkCore; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.SAUB { @@ -34,5 +39,44 @@ namespace AsbCloudInfrastructure.Services.SAUB dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset); return dto; } + + public override async Task<(int oldCount, int newCount)> RediceSamplingAsync(int idTelemetry, int ratio, int maxDateGapSec, CancellationToken token) + { + const int ramLimit = 50 * 1024 * 1024; + const int dataItemSize = 345; // by profiler + const int itemsCountLimit = ramLimit / dataItemSize; // ~ 150_000, iterations count ~ 46 + const int maxWellDepthGap = 1; + + var dbset = db.Set(); + + var sql = + "select" + + " *" + + "from" + + " (select" + + " *," + + " rank() over win1 as row_num," + + " lag(\"date\", 1) over win1 as lag_date," + + " lag(\"mode\", 1) over win1 as lag_mode," + + " lag(mse_state, 1) over win1 as lag_mse_state," + + " lag(well_depth, 1) over win1 as lag_well_depth," + + " lag(id_feed_regulator, 1) over win1 as lag_id_feed_regulator" + + " from t_telemetry_data_saub" + + $" where id_telemetry = {idTelemetry}" + + " window win1 as (order by \"date\")" + + " ) as ttt" + + "where" + + $" (row_num % {ratio}) = 0" + + " or \"mode\" != lag_mode" + + $" or(\"date\" - lag_date) > interval '{maxDateGapSec} second'" + + $" or well_depth - lag_well_depth > {maxWellDepthGap}" + + " or mse_state != lag_mse_state" + + " or id_feed_regulator != lag_id_feed_regulator;"; + + var query = dbset.FromSqlRaw(sql); + + await Task.Delay(0); + return (0, 0); + } } } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs index c33b7cab..b555286b 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs @@ -3,6 +3,8 @@ using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.Cache; using Mapster; +using System.Threading; +using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.SAUB { @@ -28,5 +30,10 @@ namespace AsbCloudInfrastructure.Services.SAUB dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset); return dto; } + + public override Task<(int oldCount, int newCount)> RediceSamplingAsync(int idTelemetry, int ratio, int maxDateGapSec, CancellationToken token) + { + throw new System.NotImplementedException(); + } } } diff --git a/AsbCloudInfrastructure/Startup.cs b/AsbCloudInfrastructure/Startup.cs index 884a3383..5ccb0df7 100644 --- a/AsbCloudInfrastructure/Startup.cs +++ b/AsbCloudInfrastructure/Startup.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System; +using System.Linq; namespace AsbCloudInfrastructure { diff --git a/AsbCloudWebApi.Tests/AsbCloudWebApi.Tests.csproj b/AsbCloudWebApi.Tests/AsbCloudWebApi.Tests.csproj index f8b181c5..0f182ff4 100644 --- a/AsbCloudWebApi.Tests/AsbCloudWebApi.Tests.csproj +++ b/AsbCloudWebApi.Tests/AsbCloudWebApi.Tests.csproj @@ -4,6 +4,8 @@ net6.0 false + + enable diff --git a/ConsoleApp1/ConsoleApp1.csproj b/ConsoleApp1/ConsoleApp1.csproj index da0e1e97..c0c5ae85 100644 --- a/ConsoleApp1/ConsoleApp1.csproj +++ b/ConsoleApp1/ConsoleApp1.csproj @@ -4,6 +4,7 @@ Exe net6.0 ConsoleApp1.Program + enable diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 5b345220..c1fe0dc8 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -1,72 +1,104 @@ using AsbCloudApp.Data; using AsbCloudApp.Data.DailyReport; +using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.DailyReport; using ClosedXML.Excel; +using DocumentFormat.OpenXml.Wordprocessing; +using Microsoft.EntityFrameworkCore; using System; using System.IO; - +using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace ConsoleApp1 { class Program { + private static AsbCloudDbContext db = ServiceFactory.Context; + + public static async Task<(int oldCount, int newCount)> RediceSamplingAsync(int idTelemetry, int ratio, int maxDateGapSec, CancellationToken token) + { + const int ramLimit = 30 * 1024 * 1024; + const int dataItemSize = 345; // by profiler + const int itemsCountLimit = ramLimit / dataItemSize; // ~ 90_000 + const int maxWellDepthGap = 1; + + ratio = ratio > 0 ? ratio : 5; + maxDateGapSec = maxDateGapSec > 0 ? maxDateGapSec : 9; + + var dbset = db.Set(); + + var sqlSelect = + "select " + + " * " + + "from " + + " (select " + + " *, " + + " rank() over win1 as row_num, " + + " lag(\"date\", 1) over win1 as lag_date, " + + " lag(\"mode\", 1) over win1 as lag_mode, " + + " lag(mse_state, 1) over win1 as lag_mse_state, " + + " lag(well_depth, 1) over win1 as lag_well_depth, " + + " lag(id_feed_regulator, 1) over win1 as lag_id_feed_regulator " + + " from t_telemetry_data_saub " + + $" where id_telemetry = {idTelemetry} and \"date\" > {{0}}" + + " window win1 as (order by \"date\") " + + " ) as ttt " + + "where " + + $" (row_num % {ratio}) = 0 " + + " or \"mode\" != lag_mode " + + $" or(\"date\" - lag_date) > interval '{maxDateGapSec} second' " + + $" or well_depth - lag_well_depth > {maxWellDepthGap} " + + " or mse_state != lag_mse_state " + + " or id_feed_regulator != lag_id_feed_regulator " + + "order by \"date\" "; + + var sqlDelete = "delete " + + "from t_telemetry_data_saub " + + $"where id_telemetry = {idTelemetry} and \"date\" between {{0}} and {{1}};"; + + var startDate = DateTimeOffset.MinValue; + var iteration = 0; + var deleted = 0; + var saved = 0; + do + { + var query = dbset + .FromSqlRaw(sqlSelect, startDate) + .AsNoTracking(); + + var data = await query + .Take(itemsCountLimit) + .ToArrayAsync(token); + + var currentDataCount = data.Length; + if (currentDataCount == 0) + break; + + var lastDate = data.Last().DateTime; + + var currentDeleted = await db.Database.ExecuteSqlRawAsync(sqlDelete, new object[]{ startDate, lastDate}.AsEnumerable(), token); + if (currentDeleted == 0) + break; + + dbset.AddRange(data); + await db.SaveChangesAsync(token); + + startDate = lastDate; + deleted += currentDeleted; + saved += currentDataCount; + iteration++; + } while (true); + + return (deleted, saved); + } + // use ServiceFactory to make services static void Main(/*string[] args*/) { - - - var block = new HeadDto() - { - AzimuthAngle = 12, - WellName = "WellName", - ClusterName = "clusterName", - Customer = "customer", - Contractor = "Contractor", - ReportDate = DateTime.Now, - WellDepthIntervalFinishDate = 27.5, - WellDepthIntervalStartDate = 26.5, - BottomholeDepth = 66.6 - }; - var block2 = new BhaDto() - { - BHADescription = "sadasdasdasdasdasdjlaskjdaksjdlasdlalskdklj" - }; - var block3 = new SaubDto(); - var bloks = new DailyReportDto() - { - Head = block, - Saub = block3 - }; - - - - var service = new DailyReportMakerExcel(); - var stream = service.MakeReportFromBlocks(bloks); - var filename = "____.xlsx"; - if (File.Exists(filename)) - File.Delete(filename); - using var fileStream = File.OpenWrite(filename); - stream.CopyTo(fileStream); - - return; - - - - - - - //var ms = MakeReportFromBlocks(block,block3); - ////File.Create("", MakeReportFromBlocks(block)); - //using var file = new FileStream("file.xlsx", FileMode.Create, System.IO.FileAccess.Write); - //byte[] bytes = new byte[ms.Length]; - //ms.Read(bytes, 0, (int)ms.Length); - //file.Write(bytes, 0, bytes.Length); - //ms.Close(); + RediceSamplingAsync(183, 5, 10, CancellationToken.None).Wait(); } - - - - } } From fe49c90e58d064e06a53aafdd206b40fbba4fc68 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Thu, 6 Oct 2022 14:37:03 +0500 Subject: [PATCH 25/37] #6539681 file service refactor --- AsbCloudApp/AsbCloudApp.csproj | 4 + .../IFileRepository.cs | 3 +- .../IFileStorageRepository.cs | 4 +- .../Services/FileService.cs | 156 +++++++++++++-- AsbCloudApp/Services/IFileService.cs | 181 ------------------ AsbCloudInfrastructure/DependencyInjection.cs | 3 +- .../Repository/FileRepository.cs | 2 +- .../Repository/FileStorageRepository.cs | 2 +- .../DrillingProgram/DrillingProgramService.cs | 4 +- .../Services/WellFinalDocumentsService.cs | 4 +- .../DrillingProgramServiceTest.cs | 4 +- .../ServicesTests/FileServiceTest.cs | 7 +- .../WellFinalDocumentsServiceTest.cs | 4 +- AsbCloudWebApi/Controllers/FileController.cs | 4 +- .../Controllers/ReportController.cs | 4 +- 15 files changed, 170 insertions(+), 216 deletions(-) rename AsbCloudApp/{Services => Repositories}/IFileRepository.cs (98%) rename AsbCloudApp/{Services => Repositories}/IFileStorageRepository.cs (94%) rename {AsbCloudInfrastructure => AsbCloudApp}/Services/FileService.cs (59%) delete mode 100644 AsbCloudApp/Services/IFileService.cs diff --git a/AsbCloudApp/AsbCloudApp.csproj b/AsbCloudApp/AsbCloudApp.csproj index 5c826cb1..7a10181c 100644 --- a/AsbCloudApp/AsbCloudApp.csproj +++ b/AsbCloudApp/AsbCloudApp.csproj @@ -21,4 +21,8 @@ + + + + diff --git a/AsbCloudApp/Services/IFileRepository.cs b/AsbCloudApp/Repositories/IFileRepository.cs similarity index 98% rename from AsbCloudApp/Services/IFileRepository.cs rename to AsbCloudApp/Repositories/IFileRepository.cs index e01891cc..e36d1001 100644 --- a/AsbCloudApp/Services/IFileRepository.cs +++ b/AsbCloudApp/Repositories/IFileRepository.cs @@ -1,10 +1,11 @@ using AsbCloudApp.Data; +using AsbCloudApp.Services; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Repositories { /// /// Сервис доступа к файлам diff --git a/AsbCloudApp/Services/IFileStorageRepository.cs b/AsbCloudApp/Repositories/IFileStorageRepository.cs similarity index 94% rename from AsbCloudApp/Services/IFileStorageRepository.cs rename to AsbCloudApp/Repositories/IFileStorageRepository.cs index 6659e976..9d821861 100644 --- a/AsbCloudApp/Services/IFileStorageRepository.cs +++ b/AsbCloudApp/Repositories/IFileStorageRepository.cs @@ -2,7 +2,7 @@ using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Repositories { /// /// Репозиторий хранения фалов @@ -26,7 +26,7 @@ namespace AsbCloudApp.Services /// /// /// - void MoveFile (string srcFilePath, string filePath); + void MoveFile(string srcFilePath, string filePath); /// /// Копирование файла diff --git a/AsbCloudInfrastructure/Services/FileService.cs b/AsbCloudApp/Services/FileService.cs similarity index 59% rename from AsbCloudInfrastructure/Services/FileService.cs rename to AsbCloudApp/Services/FileService.cs index 5cb60fcd..b27c4383 100644 --- a/AsbCloudInfrastructure/Services/FileService.cs +++ b/AsbCloudApp/Services/FileService.cs @@ -1,10 +1,5 @@ using AsbCloudApp.Data; -using AsbCloudApp.Exceptions; -using AsbCloudApp.Services; -using AsbCloudDb.Model; -using AsbCloudInfrastructure.Repository; -using Mapster; -using Microsoft.EntityFrameworkCore; +using AsbCloudApp.Repositories; using System; using System.Collections.Generic; using System.IO; @@ -12,19 +7,37 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudApp.Services { - public class FileService : IFileService + /// + /// Сервис доступа к файлам + /// + public class FileService { private readonly IFileRepository fileRepository; private readonly IFileStorageRepository fileStorageRepository; + /// + /// Сервис доступа к файлам + /// + /// + /// public FileService(IFileRepository fileRepository, IFileStorageRepository fileStorageRepository) { this.fileRepository = fileRepository; this.fileStorageRepository = fileStorageRepository; } + /// + /// переместить файл + /// + /// + /// + /// + /// + /// + /// + /// public async Task MoveAsync(int idWell, int? idUser, int idCategory, string destinationFileName, string srcFilePath, CancellationToken token = default) { @@ -49,6 +62,16 @@ namespace AsbCloudInfrastructure.Services return await GetInfoAsync(fileId, token); } + /// + /// Сохранить файл + /// + /// + /// + /// + /// + /// + /// + /// public async Task SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token) { @@ -72,12 +95,12 @@ namespace AsbCloudInfrastructure.Services return await GetInfoAsync(fileId, token); } - private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) - { - return Path.Combine(fileStorageRepository.RootPath, $"{idWell}", - $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); - } - + /// + /// Инфо о файле + /// + /// + /// + /// public async Task GetInfoAsync(int idFile, CancellationToken token) { @@ -92,9 +115,21 @@ namespace AsbCloudInfrastructure.Services return dto; } + /// + /// удалить файл + /// + /// + /// + /// public Task DeleteAsync(int idFile, CancellationToken token) => DeleteAsync(new int[] { idFile }, token); + /// + /// удалить файлы + /// + /// + /// + /// public async Task DeleteAsync(IEnumerable ids, CancellationToken token) { if (ids is null || !ids.Any()) @@ -114,6 +149,11 @@ namespace AsbCloudInfrastructure.Services return files.Any() ? 1 : 0; } + /// + /// получить путь для скачивания + /// + /// + /// public async Task GetUrl(int idFile) { var fileInfo = await fileRepository.GetOrDefaultAsync(idFile, CancellationToken.None).ConfigureAwait(false); @@ -121,16 +161,41 @@ namespace AsbCloudInfrastructure.Services return GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); } + /// + /// получить путь для скачивания + /// + /// + /// public string GetUrl(FileInfoDto fileInfo) => GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); + /// + /// получить путь для скачивания + /// + /// + /// + /// + /// + /// public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) => Path.Combine(fileStorageRepository.RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); + /// + /// пометить метку файла как удаленную + /// + /// + /// + /// public Task MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token) => fileRepository.MarkFileMarkAsDeletedAsync(new int[] { idMark }, token); + /// + /// Инфо о файле + /// + /// + /// + /// public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) { var result = await fileRepository.GetInfoByIdsAsync(idsFile, token).ConfigureAwait(false); @@ -147,38 +212,101 @@ namespace AsbCloudInfrastructure.Services return result; } + /// + /// Получить список файлов в контейнере + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public async Task> GetInfosAsync(int idWell, int idCategory, string companyName = default, string fileName = default, DateTime begin = default, DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default) => await fileRepository.GetInfosAsync(idWell, idCategory, companyName, fileName, begin, end, skip, take, token) .ConfigureAwait(false); + /// + /// Пометить файл как удаленный + /// + /// + /// + /// public async Task MarkAsDeletedAsync(int idFile, CancellationToken token = default) => await fileRepository.MarkAsDeletedAsync(idFile, token) .ConfigureAwait(false); + /// + /// добавить метку на файл + /// + /// + /// + /// + /// public async Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) => await fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token) .ConfigureAwait(false); + /// + /// Получить запись по id + /// + /// + /// + /// public async Task GetOrDefaultAsync(int id, CancellationToken token) => await fileRepository.GetOrDefaultAsync(id, token) .ConfigureAwait(false); + /// + /// получить инфо о файле по метке + /// + /// + /// + /// public async Task GetByMarkId(int idMark, CancellationToken token) => await fileRepository.GetByMarkId(idMark, token) .ConfigureAwait(false); + /// + /// получить инфо о файле по метке + /// + /// + /// + /// public async Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) => await fileRepository.MarkFileMarkAsDeletedAsync(idsMarks, token) .ConfigureAwait(false); + /// + /// Получение файлов по скважине + /// + /// + /// + /// public async Task> GetInfosByWellIdAsync(int idWell, CancellationToken token) => await fileRepository.GetInfosByWellIdAsync(idWell, token) .ConfigureAwait(false); + /// + /// Получить файлы определенной категории + /// + /// + /// + /// + /// public async Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token) => await fileRepository.GetInfosByCategoryAsync(idWell, idCategory, token) .ConfigureAwait(false); + + private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) + { + return Path.Combine(fileStorageRepository.RootPath, $"{idWell}", + $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); + } } } diff --git a/AsbCloudApp/Services/IFileService.cs b/AsbCloudApp/Services/IFileService.cs deleted file mode 100644 index a87397f7..00000000 --- a/AsbCloudApp/Services/IFileService.cs +++ /dev/null @@ -1,181 +0,0 @@ -using AsbCloudApp.Data; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudApp.Services -{ - //TODO: refactor IFileService - - /// - /// Сервис доступа к файлам - /// - public interface IFileService - { - /// - /// Сохранить файл - /// - /// - /// - /// - /// - /// - /// - /// - Task SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token = default); - - /// - /// Инфо о файле - /// - /// - /// - /// - Task GetInfoAsync(int idFile, - CancellationToken token); - - /// - /// удалить файл - /// - /// - /// - /// - Task DeleteAsync(int id, CancellationToken token); - - /// - /// удалить файлы - /// - /// - /// - /// - Task DeleteAsync(IEnumerable ids, CancellationToken token); - - /// - /// получить путь для скачивания - /// - /// - /// - string GetUrl(FileInfoDto fileInfo); - - /// - /// получить путь для скачивания - /// - /// - /// - Task GetUrl(int idFile); - - /// - /// получить путь для скачивания - /// - /// - /// - /// - /// - /// - string GetUrl(int idWell, int idCategory, int idFile, string dotExtention); - - /// - /// пометить метку файла как удаленную - /// - /// - /// - /// - Task MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token); - - /// - /// переместить файл - /// - /// - /// - /// - /// - /// - /// - /// - Task MoveAsync(int idWell, int? idUser, int idCategory, string destinationFileName, string srcFileFullName, CancellationToken token = default); - - /// - /// Инфо о файле - /// - /// - /// - /// - Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token); - - /// - /// Получить список файлов в контейнере - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - Task> GetInfosAsync(int idWell, - int idCategory, string companyName = default, string fileName = default, DateTime begin = default, - DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default); - - /// - /// Пометить файл как удаленный - /// - /// - /// - /// - Task MarkAsDeletedAsync(int idFile, CancellationToken token = default); - - /// - /// добавить метку на файл - /// - /// - /// - /// - /// - Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token); - - /// - /// Получить запись по id - /// - /// - /// - /// - Task GetOrDefaultAsync(int id, CancellationToken token); - - /// - /// получить инфо о файле по метке - /// - /// - /// - /// - Task GetByMarkId(int idMark, CancellationToken token); - - /// - /// пометить метки файлов как удаленные - /// - /// - /// - /// - Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token); - - /// - /// Получение файлов по скважине - /// - /// - /// - /// - Task> GetInfosByWellIdAsync(int idWell, CancellationToken token); - - /// - /// Получить файлы определенной категории - /// - /// - /// - /// - /// - Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token); - } -} diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 5c1bf56f..ab3ba9e2 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -1,6 +1,7 @@ using AsbCloudApp.Data; using AsbCloudApp.Data.SAUB; using AsbCloudApp.Data.Subsystems; +using AsbCloudApp.Repositories; using AsbCloudApp.Services; using AsbCloudApp.Services.Subsystems; using AsbCloudDb.Model; @@ -105,7 +106,7 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/AsbCloudInfrastructure/Repository/FileRepository.cs b/AsbCloudInfrastructure/Repository/FileRepository.cs index 2726c2b7..0cca5b8b 100644 --- a/AsbCloudInfrastructure/Repository/FileRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileRepository.cs @@ -1,5 +1,5 @@ using AsbCloudApp.Data; -using AsbCloudApp.Services; +using AsbCloudApp.Repositories; using AsbCloudDb.Model; using Mapster; using Microsoft.EntityFrameworkCore; diff --git a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs index 6cb38cfb..7466f3a3 100644 --- a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs @@ -1,5 +1,5 @@ using AsbCloudApp.Exceptions; -using AsbCloudApp.Services; +using AsbCloudApp.Repositories; using System.IO; using System.Threading; using System.Threading.Tasks; diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index 2780e7b1..ca0827b0 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -20,7 +20,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram private static readonly Dictionary drillingProgramCreateErrors = new Dictionary(); private readonly IAsbCloudDbContext context; - private readonly IFileService fileService; + private readonly FileService fileService; private readonly IUserService userService; private readonly IWellService wellService; private readonly IConfiguration configuration; @@ -50,7 +50,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram public DrillingProgramService( IAsbCloudDbContext context, - IFileService fileService, + FileService fileService, IUserService userService, IWellService wellService, IConfiguration configuration, diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs index 4d5f6427..62d82522 100644 --- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs +++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs @@ -22,7 +22,7 @@ namespace AsbCloudInfrastructure.Services public class WellFinalDocumentsService : IWellFinalDocumentsService { private readonly IAsbCloudDbContext context; - private readonly IFileService fileService; + private readonly FileService fileService; private readonly IUserService userService; private readonly IWellService wellService; private readonly IConfiguration configuration; @@ -32,7 +32,7 @@ namespace AsbCloudInfrastructure.Services private const int FileServiceThrewException = -1; public WellFinalDocumentsService(IAsbCloudDbContext context, - IFileService fileService, + FileService fileService, IUserService userService, IWellService wellService, IConfiguration configuration, diff --git a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs index 949c8c46..fa72df35 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs @@ -78,7 +78,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests new RelationCompanyWell { IdCompany = 3003, IdWell = 3002, }, }; - private readonly Mock fileServiceMock; + private readonly Mock fileServiceMock; private readonly Mock userServiceMock; private readonly Mock wellServiceMock; private readonly Mock configurationMock; @@ -97,7 +97,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests db.RelationCompaniesWells.AddRange(relationsCompanyWell); db.SaveChanges(); - fileServiceMock = new Mock(); + fileServiceMock = new Mock(); userServiceMock = new Mock(); wellServiceMock = new Mock(); configurationMock = new Mock(); diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs index 828f19ae..025cc7bb 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs @@ -1,4 +1,5 @@ using AsbCloudApp.Data; +using AsbCloudApp.Repositories; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Repository; @@ -20,7 +21,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests { public class FileServiceTest { - private IFileService fileService; + private FileService fileService; private static UserDto Author = new UserDto { Id = 1, @@ -166,9 +167,9 @@ namespace AsbCloudWebApi.Tests.ServicesTests } [Fact] - public async Task SaveAsync_returns_FileInfoa() + public async Task SaveAsync_returns_FileInfo() { - using var stream = new MemoryStream(); + using var stream = new MemoryStream(Array.Empty()); var data = await fileService.SaveAsync(90, 1, 10040, "test.txt", stream, CancellationToken.None); Assert.NotNull(data); } diff --git a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs index ac53a5b9..1718b92d 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs @@ -17,7 +17,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests { private readonly AsbCloudDbContext context; private WellFinalDocumentsService service; - private readonly Mock fileServiceMock; + private readonly Mock fileServiceMock; private readonly Mock userServiceMock; private readonly Mock wellServiceMock; private readonly Mock configurationMock; @@ -44,7 +44,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests context = TestHelpter.MakeTestContext(); context.SaveChanges(); - fileServiceMock = new Mock(); + fileServiceMock = new Mock(); userServiceMock = new Mock(); userServiceMock.Setup(x => x.GetAllAsync(CancellationToken.None)).Returns(Task.Run(() => users.Select(x => (UserExtendedDto)x))); diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index a7711247..378b5a50 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -20,10 +20,10 @@ namespace AsbCloudWebApi.Controllers [Authorize] public class FileController : ControllerBase { - private readonly IFileService fileService; + private readonly FileService fileService; private readonly IWellService wellService; - public FileController(IFileService fileService, IWellService wellService) + public FileController(FileService fileService, IWellService wellService) { this.fileService = fileService; this.wellService = wellService; diff --git a/AsbCloudWebApi/Controllers/ReportController.cs b/AsbCloudWebApi/Controllers/ReportController.cs index 03897582..d3df1092 100644 --- a/AsbCloudWebApi/Controllers/ReportController.cs +++ b/AsbCloudWebApi/Controllers/ReportController.cs @@ -18,12 +18,12 @@ namespace AsbCloudWebApi.Controllers public class ReportController : ControllerBase { private readonly IReportService reportService; - private readonly IFileService fileService; + private readonly FileService fileService; private readonly IWellService wellService; private readonly IHubContext reportsHubContext; public ReportController(IReportService reportService, IWellService wellService, - IFileService fileService, IHubContext reportsHubContext) + FileService fileService, IHubContext reportsHubContext) { this.reportService = reportService; this.fileService = fileService; From 01e07a56ac0de348db4d6c2a8ea93b68e1bfa228 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Fri, 7 Oct 2022 12:50:16 +0500 Subject: [PATCH 26/37] nit DailyReport fixes --- .../Services/DailyReport/DailyReportBlocks/HeadBlock.cs | 2 +- .../Services/DailyReport/DailyReportService.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportBlocks/HeadBlock.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportBlocks/HeadBlock.cs index 2eab984d..2acc1160 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportBlocks/HeadBlock.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportBlocks/HeadBlock.cs @@ -162,7 +162,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks sheet.Cell(AddressWatchData[1]) ._SetValue($"{blockDto.WorkTimeSpinMaster}"); sheet.Cell(AddressMetreData[1]) - ._SetValue($"{blockDto.PenetrationTorkMaster}"); + ._SetValue($"{blockDto.PenetrationSpinMaster}"); sheet._Range(AddressWorkSaubData[2], AddressWorkSaubData[2] + (0, 2)) ._SetValue("Торк Мастер (демпфирование), ч/:"); sheet.Cell(AddressWatchData[2]) diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs index afa6c0df..df762093 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs @@ -48,7 +48,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport public async Task GetOrGenerateAsync(int idWell, DateTime date, CancellationToken token) { - var dateOnly = DateTime.SpecifyKind(date.Date, DateTimeKind.Unspecified); + var dateOnly = DateTime.SpecifyKind(date.Date, DateTimeKind.Utc); var dailyReportDto = await GetAsync(idWell, dateOnly, token); if (dailyReportDto is null) dailyReportDto = await MakeDefaultDailyReportAsync(idWell, dateOnly, token); @@ -136,7 +136,8 @@ namespace AsbCloudInfrastructure.Services.DailyReport var entity = await db.DailyReports .Where(x => x.IdWell == idWell) .OrderByDescending(x => x.StartDate) - .FirstOrDefaultAsync(r => r.StartDate <= dateOffset, token); + .FirstOrDefaultAsync(r => r.StartDate.Year <= dateOffset.Year && + r.StartDate.DayOfYear <= dateOffset.DayOfYear, token); if (entity is null) return new BhaDto(); From 4d42c9e5add73a257c7af59895cef1d189573711 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Mon, 10 Oct 2022 12:39:54 +0500 Subject: [PATCH 27/37] poc debagged. --- AsbCloudDb/EFExtentions.cs | 17 +++++++++++++++++ ConsoleApp1/Program.cs | 31 ++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/AsbCloudDb/EFExtentions.cs b/AsbCloudDb/EFExtentions.cs index db66be04..f0523294 100644 --- a/AsbCloudDb/EFExtentions.cs +++ b/AsbCloudDb/EFExtentions.cs @@ -69,6 +69,15 @@ namespace AsbCloudDb return database.ExecuteSqlRawAsync(query, token); } + public static Task ExecInsertAsync(this Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade database, DbSet dbSet, IEnumerable items, CancellationToken token) + where T : class + { + var factory = GetQueryStringFactory(dbSet); + var query = factory.MakeInsertSql(items); + + return database.ExecuteSqlRawAsync(query, token); + } + public static string GetTableName(this DbSet dbSet) where T : class { @@ -154,6 +163,14 @@ namespace AsbCloudDb return builder.ToString(); } + public string MakeInsertSql(IEnumerable items) + { + var builder = new StringBuilder(insertHeader, 7); + BuildRows(builder, items); + builder.Append(';'); + return builder.ToString(); + } + private StringBuilder BuildRows(StringBuilder builder, IEnumerable items) { var list = items.ToList(); diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index c1fe0dc8..3bb591fc 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -1,5 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Data.DailyReport; +using AsbCloudDb; using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.DailyReport; using ClosedXML.Excel; @@ -18,17 +19,21 @@ namespace ConsoleApp1 { private static AsbCloudDbContext db = ServiceFactory.Context; - public static async Task<(int oldCount, int newCount)> RediceSamplingAsync(int idTelemetry, int ratio, int maxDateGapSec, CancellationToken token) + public delegate void OnProgress(int handled, int total); + + public static async Task<(int oldCount, int newCount)> RediceSamplingAsync(int idTelemetry, int ratio, int maxDateGapSec, OnProgress onProgress, CancellationToken token) { - const int ramLimit = 30 * 1024 * 1024; + const int ramLimit = 10 * 1024 * 1024; const int dataItemSize = 345; // by profiler const int itemsCountLimit = ramLimit / dataItemSize; // ~ 90_000 - const int maxWellDepthGap = 1; + const double maxWellDepthGap = 0.1; ratio = ratio > 0 ? ratio : 5; maxDateGapSec = maxDateGapSec > 0 ? maxDateGapSec : 9; var dbset = db.Set(); + var oldCount = await dbset.Where(t => t.IdTelemetry == idTelemetry).CountAsync(token); + onProgress?.Invoke(0, oldCount); var sqlSelect = "select " + @@ -49,8 +54,8 @@ namespace ConsoleApp1 "where " + $" (row_num % {ratio}) = 0 " + " or \"mode\" != lag_mode " + - $" or(\"date\" - lag_date) > interval '{maxDateGapSec} second' " + - $" or well_depth - lag_well_depth > {maxWellDepthGap} " + + $" or(\"date\" - lag_date) >= interval '{maxDateGapSec} second' " + + $" or well_depth - lag_well_depth > {maxWellDepthGap:#0,0#} " + " or mse_state != lag_mse_state " + " or id_feed_regulator != lag_id_feed_regulator " + "order by \"date\" "; @@ -60,7 +65,6 @@ namespace ConsoleApp1 $"where id_telemetry = {idTelemetry} and \"date\" between {{0}} and {{1}};"; var startDate = DateTimeOffset.MinValue; - var iteration = 0; var deleted = 0; var saved = 0; do @@ -83,22 +87,27 @@ namespace ConsoleApp1 if (currentDeleted == 0) break; - dbset.AddRange(data); - await db.SaveChangesAsync(token); + await db.Database.ExecInsertAsync(dbset, data, token); startDate = lastDate; deleted += currentDeleted; saved += currentDataCount; - iteration++; + onProgress?.Invoke(deleted, oldCount); } while (true); - return (deleted, saved); + return (oldCount, saved); } // use ServiceFactory to make services static void Main(/*string[] args*/) { - RediceSamplingAsync(183, 5, 10, CancellationToken.None).Wait(); + var i = 0; + var sw = new System.Diagnostics.Stopwatch(); + sw.Start(); + var result = RediceSamplingAsync(94, 5, 5, (p, t) => { Console.WriteLine($"{i++:0000}\t{p:00_000_000}\t{t:00_000_000}\t{1d*p/t:00.00}"); }, CancellationToken.None).Result; + sw.Stop(); + Console.WriteLine($"result: saved {result.newCount} old = {result.oldCount} ratio = {1d*result.oldCount/result.newCount}"); + Console.WriteLine($"total time: {sw.ElapsedMilliseconds} ms"); } } } From dbe5618a567b8f9205a229b4d5380eda18b221e1 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Tue, 11 Oct 2022 08:28:37 +0500 Subject: [PATCH 28/37] =?UTF-8?q?#6385536=20=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B5=D0=BD=D1=83=D0=B6=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Repositories/IFileRepository.cs | 20 ++--- .../Repositories/IFileStorageRepository.cs | 31 +++++++- AsbCloudApp/Requests/FileServiceRequest.cs | 60 ++++++++++++++ AsbCloudApp/Services/FileService.cs | 79 ++++++++++++++----- .../Repository/FileRepository.cs | 39 +++++---- .../Repository/FileStorageRepository.cs | 69 +++++++++++++++- .../ServicesTests/FileServiceTest.cs | 7 +- AsbCloudWebApi/Controllers/FileController.cs | 32 +++----- 8 files changed, 263 insertions(+), 74 deletions(-) create mode 100644 AsbCloudApp/Requests/FileServiceRequest.cs diff --git a/AsbCloudApp/Repositories/IFileRepository.cs b/AsbCloudApp/Repositories/IFileRepository.cs index e36d1001..488630ae 100644 --- a/AsbCloudApp/Repositories/IFileRepository.cs +++ b/AsbCloudApp/Repositories/IFileRepository.cs @@ -1,4 +1,5 @@ using AsbCloudApp.Data; +using AsbCloudApp.Requests; using AsbCloudApp.Services; using System; using System.Collections.Generic; @@ -7,6 +8,7 @@ using System.Threading.Tasks; namespace AsbCloudApp.Repositories { +#nullable enable /// /// Сервис доступа к файлам /// @@ -24,19 +26,10 @@ namespace AsbCloudApp.Repositories /// /// Получить список файлов в контейнере /// - /// - /// - /// - /// - /// - /// - /// - /// + /// /// /// - Task> GetInfosAsync(int idWell, - int idCategory, string companyName = default, string fileName = default, DateTime begin = default, - DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default); + Task> GetInfosAsync(FileServiceRequest request, CancellationToken token = default); /// /// Пометить файл как удаленный @@ -90,9 +83,10 @@ namespace AsbCloudApp.Repositories /// /// Получение файлов по скважине /// - /// + /// /// /// - Task> GetInfosByWellIdAsync(int idWell, CancellationToken token); + Task> GetInfosByWellIdAsync(FileServiceRequest request, CancellationToken token); } +#nullable disable } diff --git a/AsbCloudApp/Repositories/IFileStorageRepository.cs b/AsbCloudApp/Repositories/IFileStorageRepository.cs index 9d821861..72c11d21 100644 --- a/AsbCloudApp/Repositories/IFileStorageRepository.cs +++ b/AsbCloudApp/Repositories/IFileStorageRepository.cs @@ -1,9 +1,12 @@ -using System.IO; +using AsbCloudApp.Data; +using System.Collections.Generic; +using System.IO; using System.Threading; using System.Threading.Tasks; namespace AsbCloudApp.Repositories { +#nullable enable /// /// Репозиторий хранения фалов /// @@ -47,5 +50,31 @@ namespace AsbCloudApp.Repositories /// /// bool FileExists(string fullPath, string fileName); + + /// + /// Удаление всех файлов с диска о которых нет информации в базе + /// + /// + /// + int DeleteFilesNotExistStorage(int idWell, IEnumerable idsFiles); + + /// + /// Вывод списка всех файлов из базы, для которых нет файла на диске + /// + /// + /// + /// + IEnumerable GetListFilesNotDisc(int idWell, IEnumerable files); + + /// + /// Получение пути к файлу + /// + /// + /// + /// + /// + /// + string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId); } +#nullable disable } diff --git a/AsbCloudApp/Requests/FileServiceRequest.cs b/AsbCloudApp/Requests/FileServiceRequest.cs new file mode 100644 index 00000000..bc561bdd --- /dev/null +++ b/AsbCloudApp/Requests/FileServiceRequest.cs @@ -0,0 +1,60 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace AsbCloudApp.Requests +{ +#nullable enable + /// + /// Параметры запроса для файлового сервиса + /// + public class FileServiceRequest : RequestBase + { + /// + /// Идентификатор скважины + /// + [Required] + public int? IdWell { get; set; } + + /// + /// Идентификатор категории файла + /// + [Required] + public int? IdCategory { get; set; } + + /// + /// Наименование компании + /// + public string? CompanyName { get; set; } + + /// + /// Имя файла + /// + public string? FileName { get; set; } + + /// + /// Дата начала периода + /// + public DateTime? Begin { get; set; } + + /// + /// Дата окончания периода + /// + public DateTime? End { get; set; } + + /// + /// Идентификатор файла + /// + public int? IdFile { get; set; } + + /// + /// Идентификатор отметки + /// + public int? IdMark { get; set; } + + /// + /// Признак удаления + /// + public bool? IsDeleted { get; set; } + } +#nullable disable +} diff --git a/AsbCloudApp/Services/FileService.cs b/AsbCloudApp/Services/FileService.cs index b27c4383..934e5dc3 100644 --- a/AsbCloudApp/Services/FileService.cs +++ b/AsbCloudApp/Services/FileService.cs @@ -1,5 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; using System; using System.Collections.Generic; using System.IO; @@ -9,6 +10,7 @@ using System.Threading.Tasks; namespace AsbCloudApp.Services { +#nullable enable /// /// Сервис доступа к файлам /// @@ -56,7 +58,7 @@ namespace AsbCloudApp.Services var fileId = await fileRepository.InsertAsync(dto, token) .ConfigureAwait(false); - string filePath = MakeFilePath(idWell, idCategory, destinationFileName, fileId); + string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, destinationFileName, fileId); fileStorageRepository.MoveFile(srcFilePath, filePath); return await GetInfoAsync(fileId, token); @@ -89,7 +91,7 @@ namespace AsbCloudApp.Services .ConfigureAwait(false); //save stream to disk - string filePath = MakeFilePath(idWell, idCategory, fileFullName, fileId); + string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, fileFullName, fileId); await fileStorageRepository.CopyFileAsync(filePath, fileStream, token); return await GetInfoAsync(fileId, token); @@ -215,20 +217,11 @@ namespace AsbCloudApp.Services /// /// Получить список файлов в контейнере /// - /// - /// - /// - /// - /// - /// - /// - /// + /// /// /// - public async Task> GetInfosAsync(int idWell, - int idCategory, string companyName = default, string fileName = default, DateTime begin = default, - DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default) - => await fileRepository.GetInfosAsync(idWell, idCategory, companyName, fileName, begin, end, skip, take, token) + public async Task> GetInfosAsync(FileServiceRequest request, CancellationToken token) + => await fileRepository.GetInfosAsync(request, token) .ConfigureAwait(false); /// @@ -275,7 +268,7 @@ namespace AsbCloudApp.Services /// /// получить инфо о файле по метке /// - /// + /// /// /// public async Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) @@ -289,7 +282,7 @@ namespace AsbCloudApp.Services /// /// public async Task> GetInfosByWellIdAsync(int idWell, CancellationToken token) - => await fileRepository.GetInfosByWellIdAsync(idWell, token) + => await fileRepository.GetInfosByWellIdAsync(new FileServiceRequest { IdWell = idWell, IsDeleted = false }, token) .ConfigureAwait(false); /// @@ -303,10 +296,58 @@ namespace AsbCloudApp.Services => await fileRepository.GetInfosByCategoryAsync(idWell, idCategory, token) .ConfigureAwait(false); - private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) + /// + /// Удаление всех файлов по скважине помеченных как удаленные + /// + /// + /// + /// + public async Task DeleteFilesFromDbMarkedDeletionByIdWell(int idWell, CancellationToken token) { - return Path.Combine(fileStorageRepository.RootPath, $"{idWell}", - $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); + var files = await fileRepository.GetInfosByWellIdAsync( + new FileServiceRequest + { + IdWell = idWell, + IsDeleted = true + }, + token); + var result = await DeleteAsync(files.Select(x => x.Id), token); + return result; + } + + /// + /// Удаление всех файлов с диска о которых нет информации в базе + /// + /// + /// + public async Task DeleteFilesNotExistStorage(int idWell, CancellationToken token) + { + var files = await fileRepository.GetInfosByWellIdAsync( + new FileServiceRequest + { + IdWell = idWell + }, + token); + var result = await Task.FromResult(fileStorageRepository.DeleteFilesNotExistStorage(idWell, files.Select(x => x.Id))); + return result; + } + + /// + /// Вывод списка всех файлов из базы, для которых нет файла на диске + /// + /// + /// + public async Task> GetListFilesNotDisc(int idWell, CancellationToken token) + { + var files = await fileRepository.GetInfosByWellIdAsync( + new FileServiceRequest + { + IdWell = idWell + }, + token); + var result = fileStorageRepository.GetListFilesNotDisc(idWell, files); + return result; } } +#nullable disable } diff --git a/AsbCloudInfrastructure/Repository/FileRepository.cs b/AsbCloudInfrastructure/Repository/FileRepository.cs index 0cca5b8b..16367b09 100644 --- a/AsbCloudInfrastructure/Repository/FileRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileRepository.cs @@ -1,5 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; using AsbCloudDb.Model; using Mapster; using Microsoft.EntityFrameworkCore; @@ -12,6 +13,7 @@ using System.Threading.Tasks; namespace AsbCloudInfrastructure.Repository { +#nullable enable public class FileRepository : IFileRepository { private readonly IQueryable dbSetConfigured; @@ -41,22 +43,23 @@ namespace AsbCloudInfrastructure.Repository return dtos; } - public async Task> GetInfosAsync(int idWell, - int idCategory, string companyName = default, string fileName = default, DateTime begin = default, - DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default) + public async Task> GetInfosAsync(FileServiceRequest request, CancellationToken token = default) { var query = dbSetConfigured - .Where(e => e.IdWell == idWell && - e.IdCategory == idCategory && + .Where(e => e.IdWell == request.IdWell && + e.IdCategory == request.IdCategory && !e.IsDeleted); - if (!string.IsNullOrEmpty(companyName)) + if (request.CompanyName is not null) query = query.Where(e => (e.Author == null) || (e.Author.Company == null) || - e.Author.Company.Caption.Contains(companyName)); + e.Author.Company.Caption.Contains(request.CompanyName)); - if (!string.IsNullOrEmpty(fileName)) - query = query.Where(e => e.Name.ToLower().Contains(fileName.ToLower())); + if (request.FileName is not null) + query = query.Where(e => e.Name.ToLower().Contains(request.FileName.ToLower())); + + var skip = request.Skip ?? 0; + var take = request.Take ?? 32; var firstFile = await query.FirstOrDefaultAsync(token); if (firstFile is null) @@ -69,15 +72,15 @@ namespace AsbCloudInfrastructure.Repository var timezoneOffset = firstFile.Well.Timezone?.Hours ?? 5; - if (begin != default) + if (request.Begin is not null) { - var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); + var beginUtc = request.Begin.Value.ToUtcDateTimeOffset(timezoneOffset); query = query.Where(e => e.UploadDate >= beginUtc); } - if (end != default) + if (request.End is not null) { - var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); + var endUtc = request.End.Value.ToUtcDateTimeOffset(timezoneOffset); query = query.Where(e => e.UploadDate <= endUtc); } @@ -201,10 +204,13 @@ namespace AsbCloudInfrastructure.Repository return await db.SaveChangesAsync(token); } - public async Task> GetInfosByWellIdAsync(int idWell, CancellationToken token) + public async Task> GetInfosByWellIdAsync(FileServiceRequest request, CancellationToken token) { - var entities = await dbSetConfigured - .Where(e => e.IdWell == idWell && e.IsDeleted == false) + var query = dbSetConfigured.Where(e => e.IdWell == request.IdWell); + if (request.IsDeleted is not null) + query = query.Where(x => x.IsDeleted == request.IsDeleted); + + var entities = await query .AsNoTracking() .ToListAsync(token) .ConfigureAwait(false); @@ -302,4 +308,5 @@ namespace AsbCloudInfrastructure.Repository throw new NotImplementedException(); } } +#nullable disable } diff --git a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs index 7466f3a3..2b1f84f1 100644 --- a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs @@ -1,11 +1,17 @@ -using AsbCloudApp.Exceptions; +using AsbCloudApp.Data; +using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; +using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using FileInfo = System.IO.FileInfo; namespace AsbCloudInfrastructure.Repository { +#nullable enable public class FileStorageRepository : IFileStorageRepository { public string RootPath { get; private set; } @@ -51,9 +57,68 @@ namespace AsbCloudInfrastructure.Repository return true; } - private void CreateDirectory(string filePath) + public string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) + { + return Path.Combine(RootPath, $"{idWell}", + $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); + } + + public int DeleteFilesNotExistStorage(int idWell, IEnumerable idsFiles) + { + var allFilesPath = GetFilesPath(idWell); + var resutl = 0; + + foreach (var filePath in allFilesPath) + { + var idFile = Path.GetFileNameWithoutExtension(filePath); + if (!idsFiles.Any(x => x.ToString() == idFile)) + { + File.Delete(filePath); + resutl++; + } + } + + return resutl; + } + + public IEnumerable GetListFilesNotDisc(int idWell, IEnumerable files) + { + var resutl = new List(); + var idsFilesStorage = GetIdsFiles(idWell); + + foreach (var file in files) + { + if (!idsFilesStorage.Any(x => x == file.Id)) + resutl.Add(file); + } + + return resutl; + } + + private IEnumerable GetIdsFiles(int idWell) + { + var result = new List(); + var allFilesPath = GetFilesPath(idWell); + + foreach (var filePath in allFilesPath) + { + var idFileStr = Path.GetFileNameWithoutExtension(filePath); + result.Add(Convert.ToInt32(idFileStr)); + } + + return result; + } + + private IEnumerable GetFilesPath(int idWell) + { + var path = Path.Combine(RootPath, $"{idWell}"); + return Directory.GetFiles(path, "*.*", SearchOption.AllDirectories); + } + + private static void CreateDirectory(string filePath) { Directory.CreateDirectory(Path.GetDirectoryName(filePath)); } } +#nullable disable } diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs index 025cc7bb..91b2af74 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs @@ -1,5 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Repository; @@ -115,9 +116,9 @@ namespace AsbCloudWebApi.Tests.ServicesTests return Task.FromResult(result); }); - repositoryMock.Setup(x => x.GetInfosByWellIdAsync(It.IsAny(), It.IsAny())) - .Returns((int idWell, CancellationToken token) => { - var data = Files.Where(x => x.IdWell == idWell); + repositoryMock.Setup(x => x.GetInfosByWellIdAsync(It.IsAny(), It.IsAny())) + .Returns((FileServiceRequest request, CancellationToken token) => { + var data = Files.Where(x => x.IdWell == request.IdWell); return Task.FromResult(data); }); diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index 378b5a50..499129f2 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -1,4 +1,5 @@ using AsbCloudApp.Data; +using AsbCloudApp.Requests; using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -12,6 +13,7 @@ using System.Threading.Tasks; namespace AsbCloudWebApi.Controllers { +#nullable enable /// /// Хранение файлов /// @@ -70,38 +72,27 @@ namespace AsbCloudWebApi.Controllers /// /// Возвращает информацию о файлах для скважины в выбраной категории /// - /// id скважины - /// id категории файла - /// id компаний для фильтрации возвращаемых файлов - /// часть имени файла для поиска - /// дата начала - /// дата окончания - /// для пагинации кол-во записей пропустить - /// для пагинации кол-во записей взять + /// /// Токен отмены задачи /// Список информации о файлах в этой категории [HttpGet] + [Route("/api/files")] [Permission] [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] public async Task GetFilesInfoAsync( - [FromRoute] int idWell, - int idCategory = default, - string companyName = default, - string fileName = default, - DateTime begin = default, - DateTime end = default, - int skip = 0, - int take = 32, + [FromQuery] FileServiceRequest request, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); - if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) + if (request.IdWell is null || request.IdCategory is null || idCompany is null) return Forbid(); - var filesInfo = await fileService.GetInfosAsync(idWell, idCategory, - companyName, fileName, begin, end, skip, take, token).ConfigureAwait(false); + if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, + request.IdWell.Value, token).ConfigureAwait(false)) + return Forbid(); + + var filesInfo = await fileService.GetInfosAsync(request, token).ConfigureAwait(false); return Ok(filesInfo); } @@ -254,4 +245,5 @@ namespace AsbCloudWebApi.Controllers } } } +#nullable disable } From 8cbcd9a115eeba1f7f13be54d9288ff7ab67e585 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 11 Oct 2022 09:02:53 +0500 Subject: [PATCH 29/37] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B2=D0=B0=D1=8F=20?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F=20Reduce=20service?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/ReduceSamplingService.cs | 317 ++++++++++++++++++ .../Services/SAUB/TelemetryDataBaseService.cs | 11 +- .../Services/SAUB/TelemetryDataSaubService.cs | 39 --- .../Services/SAUB/TelemetryDataSpinService.cs | 5 - ConsoleApp1/Program.cs | 94 +----- 5 files changed, 325 insertions(+), 141 deletions(-) create mode 100644 AsbCloudInfrastructure/Services/ReduceSamplingService.cs diff --git a/AsbCloudInfrastructure/Services/ReduceSamplingService.cs b/AsbCloudInfrastructure/Services/ReduceSamplingService.cs new file mode 100644 index 00000000..46489fec --- /dev/null +++ b/AsbCloudInfrastructure/Services/ReduceSamplingService.cs @@ -0,0 +1,317 @@ +using AsbCloudDb; +using AsbCloudDb.Model; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Services +{ +#nullable enable + public class JobDto + { + public enum JobState { Waiting, Working, Done, Fail }; + public int Id { get; internal set; } + public JobState State { get; internal set; } + public object? Result { get; internal set; } + public Exception? Error { get; internal set; } + } + + class JobWithProgress: JobDto + { + public ReduceSamplingService.OnProgressDelagate OnProgress { get; set; } = null!; + } + + public class ReduceSamplingService + { + public delegate void OnProgressDelagate(JobDto job); + private static ReduceSamplingService? instance; + private readonly string connectionString; + private const int ratio = 5; + private readonly List jobs = new(5); + private bool isHandling; + private CancellationTokenSource? cancellationTokenSource; + private Task? task; + + private ReduceSamplingService(IConfiguration configuration) + { + connectionString = configuration.GetConnectionString("DefaultConnection"); + } + + ~ReduceSamplingService() + { + Stop(); + } + + public static ReduceSamplingService GetInstance(IConfiguration configuration) + { + if (instance is null) + instance = new(configuration); + return instance; + } + + public int TryEnqueueRediceSamplingJob(int idTelemetry, OnProgressDelagate onProgress) + { + var result = 0; + lock (jobs) + { + if (jobs.Any(j => j.Id == idTelemetry)) + result = - 1; + + var job = new JobWithProgress + { + Id = idTelemetry, + State = JobDto.JobState.Waiting, + OnProgress = onProgress, + }; + + jobs.Add(job); + result = jobs.Count; + } + EnsureHandleQueueStarted(); + return result; + } + + public JobDto? GetState(int idTelemetry) + { + JobWithProgress? job; + lock (jobs) + { + job = jobs.FirstOrDefault(j=>j.Id == idTelemetry); + } + return job; + } + + public IEnumerable GetJobs() + { + return jobs; + } + + private bool TryTakeWaitingJob(out JobWithProgress? job) + { + lock (jobs) + { + job = jobs.FirstOrDefault(j => j.State == JobDto.JobState.Waiting); + } + return job is not null; + } + + private void EnsureHandleQueueStarted() + { + if(isHandling) + return; + isHandling = true; + cancellationTokenSource = new CancellationTokenSource(); + var token = cancellationTokenSource.Token; + task = Task.Run(async () => await HandleJobs(token)) + .ContinueWith(_ => isHandling = false); + } + + private async Task HandleJobs(CancellationToken token) + { + while (TryTakeWaitingJob(out JobWithProgress? job)) + { + job!.State = JobDto.JobState.Working; + try + { + await RediceSamplingSaubAsync(job, token); + await RediceSamplingSpinAsync(job, token); + job.State = JobDto.JobState.Done; + } + catch (Exception exception) + { + job.State = JobDto.JobState.Fail; + job.Error = exception; + job.OnProgress.Invoke(job); + } + await Task.Delay(100, token); + } + await VacuumAsync(token); + await Task.Delay(1_000, token); + CleanJobs(); + } + + private void CleanJobs() + { + lock (jobs) + { + jobs.RemoveAll(j => j.State == JobDto.JobState.Done || j.State == JobDto.JobState.Fail); + } + } + + private async Task VacuumAsync(CancellationToken token) + { + using var db = MakeContext(); + var sqlVacuum = "vacuum (SKIP_LOCKED);"; + await db.Database.ExecuteSqlRawAsync(sqlVacuum, token); + } + + private void Stop() + { + cancellationTokenSource?.Cancel(); + task?.Wait(1_000); + task = null; + cancellationTokenSource = null; + } + + /// + /// Прореживание данных телеметрии САУБ. + /// Каждая ratio запись будет сохранена, остальные удаляются. Остаются (Row_number % ratio) = 0. + /// + /// Id телеметрии + /// желаемое отношение оставшихся записей к исходным + /// + private Task RediceSamplingSaubAsync(JobWithProgress job, CancellationToken token) + { + const int ramLimit = 10 * 1024 * 1024; + const int dataItemSize = 345; // by profiler + const int chankSize = ramLimit / dataItemSize; // ~ 90_000 + const double maxWellDepthGap = 0.1; + + var maxDateGapSec = ratio; + + var sqlSelectTemplate = + "select " + + " * " + + "from " + + " (select " + + " *, " + + " rank() over win1 as row_num, " + + " lag(\"date\", 1) over win1 as lag_date, " + + " lag(\"mode\", 1) over win1 as lag_mode, " + + " lag(mse_state, 1) over win1 as lag_mse_state, " + + " lag(well_depth, 1) over win1 as lag_well_depth, " + + " lag(id_feed_regulator, 1) over win1 as lag_id_feed_regulator " + + " from t_telemetry_data_saub " + + $" where id_telemetry = {job.Id} and \"date\" > {{0}}" + + " window win1 as (order by \"date\") " + + " ) as t_1 " + + "where " + + $" (row_num % {ratio}) = 0 " + + " or \"mode\" != lag_mode " + + $" or(\"date\" - lag_date) >= interval '{maxDateGapSec} second' " + + $" or well_depth - lag_well_depth > {maxWellDepthGap:#0,0#} " + + " or mse_state != lag_mse_state " + + " or id_feed_regulator != lag_id_feed_regulator " + + "order by \"date\" "; + + var sqlDeleteTemplate = "delete " + + "from t_telemetry_data_saub " + + $"where id_telemetry = {job.Id} and \"date\" between {{0}} and {{1}};"; + + return RediceSamplingAsync( + job, + chankSize, + sqlSelectTemplate, + sqlDeleteTemplate, + token); + } + + private Task RediceSamplingSpinAsync(JobWithProgress job, CancellationToken token) + { + const int ramLimit = 10 * 1024 * 1024; + const int dataItemSize = 345; // by profiler + const int chankSize = ramLimit / dataItemSize; // ~ 90_000 + var maxDateGapSec = ratio; + + var sqlSelectTemplate = + "select " + + " * " + + "from " + + " (select " + + " *, " + + " rank() over win1 as row_num, " + + " lag(\"date\", 1) over win1 as lag_date, " + + " lag(\"mode\", 1) over win1 as lag_mode, " + + " lag(state, 1) over win1 as lag_state " + + " from t_telemetry_data_spin " + + $" where id_telemetry = {job.Id} and \"date\" > {{0}}" + + " window win1 as (order by \"date\") " + + " ) as t_1 " + + "where " + + $" (row_num % {ratio}) = 0 " + + " or \"mode\" != lag_mode " + + $" or(\"date\" - lag_date) >= interval '{maxDateGapSec} second' " + + " or state != lag_state " + + "order by \"date\" "; + + var sqlDeleteTemplate = "delete " + + "from t_telemetry_data_spin " + + $"where id_telemetry = {job.Id} and \"date\" between {{0}} and {{1}};"; + + return RediceSamplingAsync( + job, + chankSize, + sqlSelectTemplate, + sqlDeleteTemplate, + token); + } + + private async Task RediceSamplingAsync( + JobWithProgress job, + int chankSize, + string sqlSelectTemplate, + string sqlDeleteTemplate, + CancellationToken token) + where TEntity: class, ITelemetryData + { + using var db = MakeContext(); + var dbset = db.Set(); + + var deleted = 0; + var oldCount = await dbset.Where(t => t.IdTelemetry == job.Id).CountAsync(token); + + if (job.Result is Tuple tupleResult) + { + deleted += tupleResult.Item1; + oldCount += tupleResult.Item2; + } + job.Result = (deleted, oldCount); + job.OnProgress?.Invoke(job); + var startDate = DateTimeOffset.MinValue; + + do + { + var query = dbset + .FromSqlRaw(sqlSelectTemplate, startDate) + .AsNoTracking(); + + var data = await query + .Take(chankSize) + .ToArrayAsync(token); + + var currentDataCount = data.Length; + if (currentDataCount == 0) + break; + + var lastDate = data.Last().DateTime; + + var currentDeleted = await db.Database.ExecuteSqlRawAsync(sqlDeleteTemplate, new object[] { startDate, lastDate }.AsEnumerable(), token); + if (currentDeleted == 0) + break; + + await db.Database.ExecInsertAsync(dbset, data, token); + + startDate = lastDate; + deleted += currentDeleted; + job.Result = (deleted, oldCount); + job.OnProgress?.Invoke(job); + } while (true); + + return; + } + + private AsbCloudDbContext MakeContext() + { + var options = new DbContextOptionsBuilder() + .UseNpgsql(connectionString) + .Options; + + return new AsbCloudDbContext(options); + } + } +#nullable disable +} diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs index 5231e573..285ac3d8 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs @@ -171,15 +171,6 @@ namespace AsbCloudInfrastructure.Services.SAUB return offset; } - /// - /// Прореживание данных телеметрии. - /// Каждая ratio запись будет сохранена, остальные удаляются. Остаются (Row_number % ratio) = 0. - /// Из-за возможности запуска повторного прореживания можно ограничить величину разрыва по времени параметром maxDateGapSec. - /// - /// Id телеметрии - /// желаемое отношение оставшихся записей к исходным - /// ограничение разрыва по времени - /// - public abstract Task<(int oldCount, int newCount)> RediceSamplingAsync(int idTelemetry, int ratio, int maxDateGapSec, CancellationToken token); + } } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs index a6330757..419c5831 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs @@ -39,44 +39,5 @@ namespace AsbCloudInfrastructure.Services.SAUB dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset); return dto; } - - public override async Task<(int oldCount, int newCount)> RediceSamplingAsync(int idTelemetry, int ratio, int maxDateGapSec, CancellationToken token) - { - const int ramLimit = 50 * 1024 * 1024; - const int dataItemSize = 345; // by profiler - const int itemsCountLimit = ramLimit / dataItemSize; // ~ 150_000, iterations count ~ 46 - const int maxWellDepthGap = 1; - - var dbset = db.Set(); - - var sql = - "select" + - " *" + - "from" + - " (select" + - " *," + - " rank() over win1 as row_num," + - " lag(\"date\", 1) over win1 as lag_date," + - " lag(\"mode\", 1) over win1 as lag_mode," + - " lag(mse_state, 1) over win1 as lag_mse_state," + - " lag(well_depth, 1) over win1 as lag_well_depth," + - " lag(id_feed_regulator, 1) over win1 as lag_id_feed_regulator" + - " from t_telemetry_data_saub" + - $" where id_telemetry = {idTelemetry}" + - " window win1 as (order by \"date\")" + - " ) as ttt" + - "where" + - $" (row_num % {ratio}) = 0" + - " or \"mode\" != lag_mode" + - $" or(\"date\" - lag_date) > interval '{maxDateGapSec} second'" + - $" or well_depth - lag_well_depth > {maxWellDepthGap}" + - " or mse_state != lag_mse_state" + - " or id_feed_regulator != lag_id_feed_regulator;"; - - var query = dbset.FromSqlRaw(sql); - - await Task.Delay(0); - return (0, 0); - } } } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs index b555286b..5cd51161 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs @@ -30,10 +30,5 @@ namespace AsbCloudInfrastructure.Services.SAUB dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset); return dto; } - - public override Task<(int oldCount, int newCount)> RediceSamplingAsync(int idTelemetry, int ratio, int maxDateGapSec, CancellationToken token) - { - throw new System.NotImplementedException(); - } } } diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 3bb591fc..11c0ca13 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -6,7 +6,9 @@ using AsbCloudInfrastructure.Services.DailyReport; using ClosedXML.Excel; using DocumentFormat.OpenXml.Wordprocessing; using Microsoft.EntityFrameworkCore; +using Org.BouncyCastle.Utilities.Collections; using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; @@ -18,96 +20,14 @@ namespace ConsoleApp1 class Program { private static AsbCloudDbContext db = ServiceFactory.Context; - - public delegate void OnProgress(int handled, int total); - - public static async Task<(int oldCount, int newCount)> RediceSamplingAsync(int idTelemetry, int ratio, int maxDateGapSec, OnProgress onProgress, CancellationToken token) - { - const int ramLimit = 10 * 1024 * 1024; - const int dataItemSize = 345; // by profiler - const int itemsCountLimit = ramLimit / dataItemSize; // ~ 90_000 - const double maxWellDepthGap = 0.1; - - ratio = ratio > 0 ? ratio : 5; - maxDateGapSec = maxDateGapSec > 0 ? maxDateGapSec : 9; - - var dbset = db.Set(); - var oldCount = await dbset.Where(t => t.IdTelemetry == idTelemetry).CountAsync(token); - onProgress?.Invoke(0, oldCount); - - var sqlSelect = - "select " + - " * " + - "from " + - " (select " + - " *, " + - " rank() over win1 as row_num, " + - " lag(\"date\", 1) over win1 as lag_date, " + - " lag(\"mode\", 1) over win1 as lag_mode, " + - " lag(mse_state, 1) over win1 as lag_mse_state, " + - " lag(well_depth, 1) over win1 as lag_well_depth, " + - " lag(id_feed_regulator, 1) over win1 as lag_id_feed_regulator " + - " from t_telemetry_data_saub " + - $" where id_telemetry = {idTelemetry} and \"date\" > {{0}}" + - " window win1 as (order by \"date\") " + - " ) as ttt " + - "where " + - $" (row_num % {ratio}) = 0 " + - " or \"mode\" != lag_mode " + - $" or(\"date\" - lag_date) >= interval '{maxDateGapSec} second' " + - $" or well_depth - lag_well_depth > {maxWellDepthGap:#0,0#} " + - " or mse_state != lag_mse_state " + - " or id_feed_regulator != lag_id_feed_regulator " + - "order by \"date\" "; - - var sqlDelete = "delete " + - "from t_telemetry_data_saub " + - $"where id_telemetry = {idTelemetry} and \"date\" between {{0}} and {{1}};"; - - var startDate = DateTimeOffset.MinValue; - var deleted = 0; - var saved = 0; - do - { - var query = dbset - .FromSqlRaw(sqlSelect, startDate) - .AsNoTracking(); - - var data = await query - .Take(itemsCountLimit) - .ToArrayAsync(token); - - var currentDataCount = data.Length; - if (currentDataCount == 0) - break; - - var lastDate = data.Last().DateTime; - - var currentDeleted = await db.Database.ExecuteSqlRawAsync(sqlDelete, new object[]{ startDate, lastDate}.AsEnumerable(), token); - if (currentDeleted == 0) - break; - - await db.Database.ExecInsertAsync(dbset, data, token); - - startDate = lastDate; - deleted += currentDeleted; - saved += currentDataCount; - onProgress?.Invoke(deleted, oldCount); - } while (true); - - return (oldCount, saved); - } - + // use ServiceFactory to make services static void Main(/*string[] args*/) { - var i = 0; - var sw = new System.Diagnostics.Stopwatch(); - sw.Start(); - var result = RediceSamplingAsync(94, 5, 5, (p, t) => { Console.WriteLine($"{i++:0000}\t{p:00_000_000}\t{t:00_000_000}\t{1d*p/t:00.00}"); }, CancellationToken.None).Result; - sw.Stop(); - Console.WriteLine($"result: saved {result.newCount} old = {result.oldCount} ratio = {1d*result.oldCount/result.newCount}"); - Console.WriteLine($"total time: {sw.ElapsedMilliseconds} ms"); + Task.Run(() => { throw new Exception(); }) + .ContinueWith(t => { Console.WriteLine("Dooom"); }); + Console.WriteLine($"total time: ms"); + Console.ReadLine(); } } } From 9de5f04fbc6e81674616309ef5e6bf484873f9c6 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Tue, 11 Oct 2022 09:08:25 +0500 Subject: [PATCH 30/37] =?UTF-8?q?#6385536=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Repositories/IFileRepository.cs | 1 - AsbCloudApp/Services/FileService.cs | 1 - AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs | 7 ------- AsbCloudWebApi/Controllers/FileController.cs | 3 --- 4 files changed, 12 deletions(-) diff --git a/AsbCloudApp/Repositories/IFileRepository.cs b/AsbCloudApp/Repositories/IFileRepository.cs index 488630ae..9e3e41c9 100644 --- a/AsbCloudApp/Repositories/IFileRepository.cs +++ b/AsbCloudApp/Repositories/IFileRepository.cs @@ -1,7 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Requests; using AsbCloudApp.Services; -using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/AsbCloudApp/Services/FileService.cs b/AsbCloudApp/Services/FileService.cs index 934e5dc3..34cb1fe5 100644 --- a/AsbCloudApp/Services/FileService.cs +++ b/AsbCloudApp/Services/FileService.cs @@ -1,7 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs index 91b2af74..5710f40b 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs @@ -2,21 +2,14 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; -using AsbCloudDb.Model; -using AsbCloudInfrastructure.Repository; -using AsbCloudInfrastructure.Services; -using DocumentFormat.OpenXml.Spreadsheet; -using DocumentFormat.OpenXml.Wordprocessing; using Moq; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit; -using static AsbCloudWebApi.Tests.TestHelpter; namespace AsbCloudWebApi.Tests.ServicesTests { diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index 499129f2..1c29b902 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -4,9 +4,6 @@ using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections; -using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; From 0b2ae0b361d7caa9a5be36cf2780a29e9cefc56c Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Tue, 11 Oct 2022 09:38:19 +0500 Subject: [PATCH 31/37] + --- AsbCloudApp/Repositories/IFileRepository.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AsbCloudApp/Repositories/IFileRepository.cs b/AsbCloudApp/Repositories/IFileRepository.cs index 9e3e41c9..4363c204 100644 --- a/AsbCloudApp/Repositories/IFileRepository.cs +++ b/AsbCloudApp/Repositories/IFileRepository.cs @@ -1,5 +1,5 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Requests; +using AsbCloudApp.Requests; +using AsbCloudApp.Data; using AsbCloudApp.Services; using System.Collections.Generic; using System.Threading; From b54de8fe0624364a975d45e9caa32e8b902d4bb3 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Tue, 11 Oct 2022 14:42:04 +0500 Subject: [PATCH 32/37] =?UTF-8?q?#6385536=20=D0=97=D0=B0=D0=BC=D0=B5=D1=87?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repositories/IFileStorageRepository.cs | 38 ++++----- AsbCloudApp/Services/FileService.cs | 34 +++----- .../Repository/FileStorageRepository.cs | 83 ++++++++++--------- .../ServicesTests/FileServiceTest.cs | 2 - AsbCloudWebApi/Controllers/FileController.cs | 7 +- 5 files changed, 76 insertions(+), 88 deletions(-) diff --git a/AsbCloudApp/Repositories/IFileStorageRepository.cs b/AsbCloudApp/Repositories/IFileStorageRepository.cs index 72c11d21..68ce51e9 100644 --- a/AsbCloudApp/Repositories/IFileStorageRepository.cs +++ b/AsbCloudApp/Repositories/IFileStorageRepository.cs @@ -12,17 +12,12 @@ namespace AsbCloudApp.Repositories /// public interface IFileStorageRepository { - /// - /// Директория хранения файлов - /// - string RootPath { get; } - /// /// Получение длинны фала и проверка его наличия, если отсутствует падает исключение /// /// /// - long GetLengthFile(string srcFilePath); + long GetFileLength(string srcFilePath); /// /// Перемещение файла @@ -34,29 +29,24 @@ namespace AsbCloudApp.Repositories /// /// Копирование файла /// + /// + /// + /// /// - Task CopyFileAsync(string filePath, Stream fileStream, CancellationToken token); + Task SaveFileAsync(string filePathRec, Stream fileStreamSrc, CancellationToken token); /// /// Удаление файла /// - /// - void DeleteFile(string fileName); - - /// - /// Проверка наличия файла - /// - /// - /// - /// - bool FileExists(string fullPath, string fileName); + /// + void DeleteFile(IEnumerable filesName); /// /// Удаление всех файлов с диска о которых нет информации в базе /// /// /// - int DeleteFilesNotExistStorage(int idWell, IEnumerable idsFiles); + int DeleteFilesNotList(int idWell, IEnumerable idsFiles); /// /// Вывод списка всех файлов из базы, для которых нет файла на диске @@ -64,7 +54,7 @@ namespace AsbCloudApp.Repositories /// /// /// - IEnumerable GetListFilesNotDisc(int idWell, IEnumerable files); + IEnumerable GetListFilesNotDisc(IEnumerable files); /// /// Получение пути к файлу @@ -75,6 +65,16 @@ namespace AsbCloudApp.Repositories /// /// string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId); + + /// + /// Получить путь для скачивания + /// + /// + /// + /// + /// + /// + string GetUrl(int idWell, int idCategory, int idFile, string dotExtention); } #nullable disable } diff --git a/AsbCloudApp/Services/FileService.cs b/AsbCloudApp/Services/FileService.cs index 34cb1fe5..d16006e1 100644 --- a/AsbCloudApp/Services/FileService.cs +++ b/AsbCloudApp/Services/FileService.cs @@ -6,6 +6,8 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using static Npgsql.PostgresTypes.PostgresCompositeType; +using static System.Net.WebRequestMethods; namespace AsbCloudApp.Services { @@ -44,7 +46,7 @@ namespace AsbCloudApp.Services { destinationFileName = Path.GetFileName(destinationFileName); srcFilePath = Path.GetFullPath(srcFilePath); - var fileSize = fileStorageRepository.GetLengthFile(srcFilePath); + var fileSize = fileStorageRepository.GetFileLength(srcFilePath); //save info to db var dto = new FileInfoDto { @@ -91,7 +93,7 @@ namespace AsbCloudApp.Services //save stream to disk string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, fileFullName, fileId); - await fileStorageRepository.CopyFileAsync(filePath, fileStream, token); + await fileStorageRepository.SaveFileAsync(filePath, fileStream, token); return await GetInfoAsync(fileId, token); } @@ -111,7 +113,6 @@ namespace AsbCloudApp.Services var relativePath = GetUrl(dto.IdWell, dto.IdCategory, dto.Id, ext); var fullPath = Path.GetFullPath(relativePath); - fileStorageRepository.FileExists(fullPath, relativePath); return dto; } @@ -141,27 +142,12 @@ namespace AsbCloudApp.Services if (files is null || !files.Any()) return 0; - foreach (var file in files) - { - var fileName = GetUrl(file.IdWell, file.IdCategory, file.Id, Path.GetExtension(file.Name)); - fileStorageRepository.DeleteFile(fileName); - } + var filesName = files.Select(x => GetUrl(x.IdWell, x.IdCategory, x.Id, Path.GetExtension(x.Name))); + fileStorageRepository.DeleteFile(filesName); return files.Any() ? 1 : 0; } - /// - /// получить путь для скачивания - /// - /// - /// - public async Task GetUrl(int idFile) - { - var fileInfo = await fileRepository.GetOrDefaultAsync(idFile, CancellationToken.None).ConfigureAwait(false); - - return GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); - } - /// /// получить путь для скачивания /// @@ -179,7 +165,7 @@ namespace AsbCloudApp.Services /// /// public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) => - Path.Combine(fileStorageRepository.RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); + fileStorageRepository.GetUrl(idWell, idCategory, idFile, dotExtention); /// /// пометить метку файла как удаленную @@ -207,7 +193,6 @@ namespace AsbCloudApp.Services var ext = Path.GetExtension(entity.Name); var relativePath = GetUrl(entity.IdWell, entity.IdCategory, entity.Id, ext); var fullPath = Path.GetFullPath(relativePath); - fileStorageRepository.FileExists(fullPath, relativePath); } return result; @@ -327,7 +312,7 @@ namespace AsbCloudApp.Services IdWell = idWell }, token); - var result = await Task.FromResult(fileStorageRepository.DeleteFilesNotExistStorage(idWell, files.Select(x => x.Id))); + var result = await Task.FromResult(fileStorageRepository.DeleteFilesNotList(idWell, files.Select(x => x.Id))); return result; } @@ -335,6 +320,7 @@ namespace AsbCloudApp.Services /// Вывод списка всех файлов из базы, для которых нет файла на диске /// /// + /// /// public async Task> GetListFilesNotDisc(int idWell, CancellationToken token) { @@ -344,7 +330,7 @@ namespace AsbCloudApp.Services IdWell = idWell }, token); - var result = fileStorageRepository.GetListFilesNotDisc(idWell, files); + var result = fileStorageRepository.GetListFilesNotDisc(files); return result; } } diff --git a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs index 2b1f84f1..37a041b7 100644 --- a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs @@ -14,31 +14,33 @@ namespace AsbCloudInfrastructure.Repository #nullable enable public class FileStorageRepository : IFileStorageRepository { - public string RootPath { get; private set; } + /// + /// Директория хранения файлов + /// + private readonly string RootPath = "files"; public FileStorageRepository() { - RootPath = "files"; } - public async Task CopyFileAsync(string filePath, Stream fileStream, CancellationToken token) + public async Task SaveFileAsync(string filePathRec, Stream fileStreamSrc, CancellationToken token) { - CreateDirectory(filePath); - using var newfileStream = new FileStream(filePath, FileMode.Create); - await fileStream.CopyToAsync(newfileStream, token).ConfigureAwait(false); + CreateDirectory(filePathRec); + using var newfileStream = new FileStream(filePathRec, FileMode.Create); + await fileStreamSrc.CopyToAsync(newfileStream, token).ConfigureAwait(false); } - public void DeleteFile(string fileName) + public void DeleteFile(IEnumerable filesName) { - if (File.Exists(fileName)) - File.Delete(fileName); + foreach (var fileName in filesName) + { + if (File.Exists(fileName)) + File.Delete(fileName); + } } - public long GetLengthFile(string srcFilePath) + public long GetFileLength(string srcFilePath) { - if (!File.Exists(srcFilePath)) - throw new ArgumentInvalidException($"file {srcFilePath} doesn't exist", nameof(srcFilePath)); - var sysFileInfo = new FileInfo(srcFilePath); return sysFileInfo.Length; } @@ -49,51 +51,50 @@ namespace AsbCloudInfrastructure.Repository File.Move(srcFilePath, filePath); } - public bool FileExists(string fullPath, string fileName) - { - if (!File.Exists(fullPath)) - throw new FileNotFoundException("not found", fileName); - - return true; - } - public string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) { return Path.Combine(RootPath, $"{idWell}", $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); } - public int DeleteFilesNotExistStorage(int idWell, IEnumerable idsFiles) + public int DeleteFilesNotList(int idWell, IEnumerable idsFilesList) { var allFilesPath = GetFilesPath(idWell); - var resutl = 0; + var result = 0; foreach (var filePath in allFilesPath) { - var idFile = Path.GetFileNameWithoutExtension(filePath); - if (!idsFiles.Any(x => x.ToString() == idFile)) + if (int.TryParse(Path.GetFileNameWithoutExtension(filePath), out int idFile) + || !idsFilesList.Any(x => x == idFile)) { File.Delete(filePath); - resutl++; + result++; + } + } + + return result; + } + + public IEnumerable GetListFilesNotDisc(IEnumerable files) + { + var resutl = new List(); + var groupFiles = files.GroupBy(x => x.IdWell); + + foreach (var itemGroupFiles in groupFiles) + { + var idsFilesStorage = GetIdsFiles(itemGroupFiles.Key); + foreach (var file in files) + { + if (!idsFilesStorage.Any(x => x == file.Id)) + resutl.Add(file); } } return resutl; } - public IEnumerable GetListFilesNotDisc(int idWell, IEnumerable files) - { - var resutl = new List(); - var idsFilesStorage = GetIdsFiles(idWell); - - foreach (var file in files) - { - if (!idsFilesStorage.Any(x => x == file.Id)) - resutl.Add(file); - } - - return resutl; - } + public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) => + Path.Combine(RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); private IEnumerable GetIdsFiles(int idWell) { @@ -102,8 +103,8 @@ namespace AsbCloudInfrastructure.Repository foreach (var filePath in allFilesPath) { - var idFileStr = Path.GetFileNameWithoutExtension(filePath); - result.Add(Convert.ToInt32(idFileStr)); + int.TryParse(Path.GetFileNameWithoutExtension(filePath), out int idFile); + result.Add(idFile); } return result; diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs index 5710f40b..cf35bcab 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs @@ -134,8 +134,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests var storageRepositoryMock = new Mock(); - storageRepositoryMock.Setup(x => x.RootPath).Returns("files"); - fileService = new FileService(repositoryMock.Object, storageRepositoryMock.Object); } diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index 1c29b902..85c095a3 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -7,6 +7,8 @@ using Microsoft.AspNetCore.Mvc; using System.IO; using System.Threading; using System.Threading.Tasks; +using System.Text; +using static System.Net.WebRequestMethods; namespace AsbCloudWebApi.Controllers { @@ -120,9 +122,10 @@ namespace AsbCloudWebApi.Controllers try { var fileInfo = await fileService.GetInfoAsync(fileId, token); - var relativePath = fileService.GetUrl(fileInfo); - return PhysicalFile(Path.GetFullPath(relativePath), "application/octet-stream", fileInfo.Name); + + var fileStream = new FileStream(Path.GetFullPath(relativePath), FileMode.Open); + return File(fileStream, "application/octet-stream", fileInfo.Name); } catch (FileNotFoundException ex) { From 707f2a638a21ed2f9d8900398228212d0d23caf9 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 11 Oct 2022 17:04:26 +0500 Subject: [PATCH 33/37] Add ReduceSamplingController. --- AsbCloudApp/Data/JobDto.cs | 56 ++++++ .../Services/IReduceSamplingService.cs | 43 +++++ AsbCloudInfrastructure/DependencyInjection.cs | 1 + .../Services/ReduceSamplingService.cs | 174 ++++++++++-------- .../Controllers/ReduceSamplingController.cs | 78 ++++++++ ConsoleApp1/Program.cs | 10 +- 6 files changed, 282 insertions(+), 80 deletions(-) create mode 100644 AsbCloudApp/Data/JobDto.cs create mode 100644 AsbCloudApp/Services/IReduceSamplingService.cs create mode 100644 AsbCloudWebApi/Controllers/ReduceSamplingController.cs diff --git a/AsbCloudApp/Data/JobDto.cs b/AsbCloudApp/Data/JobDto.cs new file mode 100644 index 00000000..2e9b336a --- /dev/null +++ b/AsbCloudApp/Data/JobDto.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections; + +namespace AsbCloudApp.Data +{ +#nullable enable + /// + /// Состояние фоновой задачи + /// + public enum JobState + { + /// + /// Ожидает в очереди на выполнение + /// + Waiting, + /// + /// выполняется + /// + Working, + /// + /// успешно выполнена + /// + Done, + /// + /// завершена с ошибкой + /// + Fail + }; + + /// + /// работа фоновой задачи + /// + public class JobDto + { + /// + /// идентификатор + /// + public int Id { get; set; } + + /// + /// Состояние + /// + public JobState State { get; set; } + + /// + /// результат выполнения + /// + public Hashtable? Results { get; set; } + + /// + /// Исключение, если возникла ошибка + /// + public string? Error { get; set; } + } +#nullable disable +} diff --git a/AsbCloudApp/Services/IReduceSamplingService.cs b/AsbCloudApp/Services/IReduceSamplingService.cs new file mode 100644 index 00000000..a0220c58 --- /dev/null +++ b/AsbCloudApp/Services/IReduceSamplingService.cs @@ -0,0 +1,43 @@ +using AsbCloudApp.Data; +using System.Collections.Generic; + +namespace AsbCloudApp.Services +{ +#nullable enable + /// + /// Делегат обновления состояния задачи + /// + /// + public delegate void OnJobProgressDelagate(JobDto job); + + /// + /// Сервис прореживания архива БД. + /// Удаляет часть телеметрии. + /// Понижает частоту записей в БД с 1 запись за 1 сек до 1 запись за N сек. + /// + public interface IReduceSamplingService + { + /// + /// Получить все задания. Задания удаляются минимум через 10 сек после выполнения, возможно позднее. + /// + /// Enumerable of JobDto or empty + IEnumerable GetJobs(); + + /// + /// Получить состояние определенной задачи + /// + /// + /// + JobDto? GetOrDefaultState(int idTelemetry); + + /// + /// Создать задачу прореживанию архива и добавить её в очередь на выполнение + /// + /// телеметрия для прореживания + /// колбек процесса выполнения + /// созданная задача или задача из очереди + /// задача добавлена == true + bool TryEnqueueRediceSamplingJob(int idTelemetry, OnJobProgressDelagate onProgress, out JobDto jobDto); + } +#nullable disable +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 1c69736d..421e550c 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -102,6 +102,7 @@ namespace AsbCloudInfrastructure services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(provider => ReduceSamplingService.GetInstance(configuration)); services.AddTransient(); services.AddTransient(); diff --git a/AsbCloudInfrastructure/Services/ReduceSamplingService.cs b/AsbCloudInfrastructure/Services/ReduceSamplingService.cs index 46489fec..d9c11e0d 100644 --- a/AsbCloudInfrastructure/Services/ReduceSamplingService.cs +++ b/AsbCloudInfrastructure/Services/ReduceSamplingService.cs @@ -1,9 +1,12 @@ -using AsbCloudDb; +using AsbCloudApp.Data; +using AsbCloudApp.Services; +using AsbCloudDb; using AsbCloudDb.Model; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -11,27 +14,22 @@ using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services { #nullable enable - public class JobDto + class JobHandle { - public enum JobState { Waiting, Working, Done, Fail }; - public int Id { get; internal set; } - public JobState State { get; internal set; } - public object? Result { get; internal set; } - public Exception? Error { get; internal set; } + public int Id => Job.Id; + public JobDto Job { get; set; } = null!; + public DateTime DateCreate { get; set; } = DateTime.Now; + public OnJobProgressDelagate? OnProgress { get; set; } } - class JobWithProgress: JobDto + public class ReduceSamplingService : IReduceSamplingService { - public ReduceSamplingService.OnProgressDelagate OnProgress { get; set; } = null!; - } - - public class ReduceSamplingService - { - public delegate void OnProgressDelagate(JobDto job); + private const string jobResultKeyDeleted = "deleted"; + private const string jobResultKeyTotal = "total"; private static ReduceSamplingService? instance; private readonly string connectionString; private const int ratio = 5; - private readonly List jobs = new(5); + private readonly List jobHandlers = new(5); private bool isHandling; private CancellationTokenSource? cancellationTokenSource; private Task? task; @@ -46,62 +44,73 @@ namespace AsbCloudInfrastructure.Services Stop(); } + /// + /// Get singleton Instance + /// + /// + /// public static ReduceSamplingService GetInstance(IConfiguration configuration) { - if (instance is null) - instance = new(configuration); + instance ??= new(configuration); return instance; } - public int TryEnqueueRediceSamplingJob(int idTelemetry, OnProgressDelagate onProgress) + /// + public bool TryEnqueueRediceSamplingJob(int idTelemetry, OnJobProgressDelagate? onProgress, out JobDto jobDto) { - var result = 0; - lock (jobs) + lock (jobHandlers) { - if (jobs.Any(j => j.Id == idTelemetry)) - result = - 1; + var oldJob = jobHandlers.FirstOrDefault(j => j.Id == idTelemetry); + if (oldJob is not null) + { + jobDto = oldJob.Job; + return false; + } - var job = new JobWithProgress + jobDto = new JobDto { Id = idTelemetry, - State = JobDto.JobState.Waiting, + State = JobState.Waiting, + Results = new(), + }; + var jobHandler = new JobHandle + { + Job = jobDto, OnProgress = onProgress, }; - jobs.Add(job); - result = jobs.Count; + jobHandlers.Add(jobHandler); } EnsureHandleQueueStarted(); - return result; + return true; } - public JobDto? GetState(int idTelemetry) + /// + public JobDto? GetOrDefaultState(int idTelemetry) { - JobWithProgress? job; - lock (jobs) + JobHandle? jobHandler; + lock (jobHandlers) { - job = jobs.FirstOrDefault(j=>j.Id == idTelemetry); + jobHandler = jobHandlers.FirstOrDefault(j => j.Id == idTelemetry); } - return job; + return jobHandler?.Job; } - public IEnumerable GetJobs() - { - return jobs; - } + /// + public IEnumerable GetJobs() => jobHandlers.Select(j=>j.Job); - private bool TryTakeWaitingJob(out JobWithProgress? job) + private bool TryTakeWaitingJob(out JobHandle? job) { - lock (jobs) + lock (jobHandlers) { - job = jobs.FirstOrDefault(j => j.State == JobDto.JobState.Waiting); + job = jobHandlers.FirstOrDefault(j => j.Job.State == JobState.Waiting); } return job is not null; } private void EnsureHandleQueueStarted() { - if(isHandling) + if (isHandling) return; isHandling = true; cancellationTokenSource = new CancellationTokenSource(); @@ -112,33 +121,43 @@ namespace AsbCloudInfrastructure.Services private async Task HandleJobs(CancellationToken token) { - while (TryTakeWaitingJob(out JobWithProgress? job)) + while (TryTakeWaitingJob(out JobHandle? jobHandler)) { - job!.State = JobDto.JobState.Working; + jobHandler!.Job.State = JobState.Working; try { - await RediceSamplingSaubAsync(job, token); - await RediceSamplingSpinAsync(job, token); - job.State = JobDto.JobState.Done; + await RediceSamplingSaubAsync(jobHandler, token); + await RediceSamplingSpinAsync(jobHandler, token); + jobHandler.Job.State = JobState.Done; } catch (Exception exception) { - job.State = JobDto.JobState.Fail; - job.Error = exception; - job.OnProgress.Invoke(job); + jobHandler.Job.State = JobState.Fail; + jobHandler.Job.Results = null; + jobHandler.Job.Error = exception.Message; + jobHandler.OnProgress?.Invoke(jobHandler.Job); + } + + if (!jobHandlers.Any(j => j.Job.State == JobState.Waiting)) + { + var sw = Stopwatch.StartNew(); + await VacuumAsync(token); + sw.Stop(); + if (sw.ElapsedMilliseconds < 10_000) + { + var delayMs = 10_000 - (int)sw.ElapsedMilliseconds; + await Task.Delay(delayMs, token); + } + CleanJobs(); } - await Task.Delay(100, token); } - await VacuumAsync(token); - await Task.Delay(1_000, token); - CleanJobs(); } private void CleanJobs() { - lock (jobs) + lock (jobHandlers) { - jobs.RemoveAll(j => j.State == JobDto.JobState.Done || j.State == JobDto.JobState.Fail); + jobHandlers.RemoveAll(j => j.Job.State == JobState.Done || j.Job.State == JobState.Fail); } } @@ -154,17 +173,11 @@ namespace AsbCloudInfrastructure.Services cancellationTokenSource?.Cancel(); task?.Wait(1_000); task = null; + cancellationTokenSource?.Dispose(); cancellationTokenSource = null; } - /// - /// Прореживание данных телеметрии САУБ. - /// Каждая ratio запись будет сохранена, остальные удаляются. Остаются (Row_number % ratio) = 0. - /// - /// Id телеметрии - /// желаемое отношение оставшихся записей к исходным - /// - private Task RediceSamplingSaubAsync(JobWithProgress job, CancellationToken token) + private Task RediceSamplingSaubAsync(JobHandle job, CancellationToken token) { const int ramLimit = 10 * 1024 * 1024; const int dataItemSize = 345; // by profiler @@ -204,13 +217,13 @@ namespace AsbCloudInfrastructure.Services return RediceSamplingAsync( job, - chankSize, - sqlSelectTemplate, + chankSize, + sqlSelectTemplate, sqlDeleteTemplate, token); } - private Task RediceSamplingSpinAsync(JobWithProgress job, CancellationToken token) + private Task RediceSamplingSpinAsync(JobHandle job, CancellationToken token) { const int ramLimit = 10 * 1024 * 1024; const int dataItemSize = 345; // by profiler @@ -251,26 +264,30 @@ namespace AsbCloudInfrastructure.Services } private async Task RediceSamplingAsync( - JobWithProgress job, - int chankSize, + JobHandle jobHandle, + int chankSize, string sqlSelectTemplate, string sqlDeleteTemplate, CancellationToken token) - where TEntity: class, ITelemetryData + where TEntity : class, AsbCloudDb.Model.ITelemetryData { using var db = MakeContext(); var dbset = db.Set(); var deleted = 0; - var oldCount = await dbset.Where(t => t.IdTelemetry == job.Id).CountAsync(token); + var totalCount = await dbset.Where(t => t.IdTelemetry == jobHandle.Id).CountAsync(token); - if (job.Result is Tuple tupleResult) - { - deleted += tupleResult.Item1; - oldCount += tupleResult.Item2; - } - job.Result = (deleted, oldCount); - job.OnProgress?.Invoke(job); + var result = jobHandle.Job.Results!; + if (result[jobResultKeyDeleted] is int previousDeleted) + deleted += previousDeleted; + + if (result[jobResultKeyTotal] is int previousCount) + totalCount += previousCount; + + result[jobResultKeyDeleted] = deleted; + result[jobResultKeyTotal] = totalCount; + + jobHandle.OnProgress?.Invoke(jobHandle.Job); var startDate = DateTimeOffset.MinValue; do @@ -297,8 +314,9 @@ namespace AsbCloudInfrastructure.Services startDate = lastDate; deleted += currentDeleted; - job.Result = (deleted, oldCount); - job.OnProgress?.Invoke(job); + result[jobResultKeyDeleted] = deleted; + result[jobResultKeyTotal] = totalCount; + jobHandle.OnProgress?.Invoke(jobHandle.Job); } while (true); return; diff --git a/AsbCloudWebApi/Controllers/ReduceSamplingController.cs b/AsbCloudWebApi/Controllers/ReduceSamplingController.cs new file mode 100644 index 00000000..ddb99b2d --- /dev/null +++ b/AsbCloudWebApi/Controllers/ReduceSamplingController.cs @@ -0,0 +1,78 @@ +using AsbCloudApp.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; +using AsbCloudApp.Data; +using System.Linq; +using AsbCloudWebApi.SignalR; +using Microsoft.AspNetCore.SignalR; + +namespace AsbCloudWebApi.Controllers +{ + /// + /// Редактор кустов для админки + /// + [Route("api/admin/[controller]")] + [ApiController] + [Authorize] + public class ReduceSamplingController: ControllerBase + { + private readonly IReduceSamplingService service; + private readonly IHubContext telemetryHubContext; + private const string sirnalRGroupName = "ReduceSampling"; + private const string sirnalRMethodOnProgress = "OnProgress"; + + public ReduceSamplingController( + IReduceSamplingService service, + IHubContext telemetryHubContext ) + { + this.service = service; + this.telemetryHubContext = telemetryHubContext; + } + + /// + /// Получить все задания. Задания удаляются минимум через 10 сек после выполнения, возможно позднее. + /// + /// + /// + [HttpGet] + public virtual ActionResult> GetAll(int idTelemetry) + { + var result = service.GetJobs(); + if (result.Any()) + return Ok(result); + else + return NoContent(); + } + + /// + /// Получить состояние определенной задачи + /// + /// + /// + [HttpGet("{idTelemetry}")] + public virtual ActionResult GetOrDefault(int idTelemetry) + { + var result = service.GetOrDefaultState(idTelemetry); + return Ok(result); + } + + /// + /// Создать задачу прореживанию архива и добавить её в очередь на выполнение. + /// Если задача есть в очереди, она же и возвращается, но подписка не происходит. + /// + [HttpPost] + [Permission] + public virtual ActionResult Enqueue(int idTelemetry) + { + void onProgress(JobDto job) => + Task.Run(async () => + await telemetryHubContext.Clients.Group(sirnalRGroupName) + .SendAsync(sirnalRMethodOnProgress, job)); + + service.TryEnqueueRediceSamplingJob(idTelemetry, onProgress, out JobDto job); + return Ok(job); + } + } +} diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 11c0ca13..b3d1d6fb 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -8,6 +8,7 @@ using DocumentFormat.OpenXml.Wordprocessing; using Microsoft.EntityFrameworkCore; using Org.BouncyCastle.Utilities.Collections; using System; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; @@ -24,8 +25,13 @@ namespace ConsoleApp1 // use ServiceFactory to make services static void Main(/*string[] args*/) { - Task.Run(() => { throw new Exception(); }) - .ContinueWith(t => { Console.WriteLine("Dooom"); }); + var h = new Hashtable(); + h.Add("name", 1); + h.Add("name2", "66"); + var v = h["v"]; + + var s = System.Text.Json.JsonSerializer.Serialize(h); + Console.WriteLine($"total time: ms"); Console.ReadLine(); } From ceb088519abe5b8ae794c5ec66adb64b80cb3795 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Wed, 12 Oct 2022 09:47:25 +0500 Subject: [PATCH 34/37] =?UTF-8?q?#6385536=20=D0=98=D0=BD=D1=81=D1=82=D1=80?= =?UTF-8?q?=D1=83=D0=BA=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=20=D0=B2=D1=8B?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D1=8E=20=D1=80=D0=B5=D0=BF?= =?UTF-8?q?=D0=BE=D0=B7=D0=B8=D1=82=D0=BE=D1=80=D0=B8=D1=8F=20=D0=B2=20?= =?UTF-8?q?=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudInfrastructure/Services/_Readme.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 AsbCloudInfrastructure/Services/_Readme.md diff --git a/AsbCloudInfrastructure/Services/_Readme.md b/AsbCloudInfrastructure/Services/_Readme.md new file mode 100644 index 00000000..d05ae29e --- /dev/null +++ b/AsbCloudInfrastructure/Services/_Readme.md @@ -0,0 +1,9 @@ +# Создание репозитория для сервися + +1. Создать интерфейс репозитория в AsbCloudApp.Services +2. Создать репозиторий в AsbCloudInfrastructure.Repository, наследоваться от созданного интерфейса, в нем добавить работу с БД +3. Добавить репозиторий в AsbCloudInfrastructure.DependencyInjection +4. Добавить в конструктор сервиса новый репозиторий и использовать его методы +5. Перенести сервис из AsbCloudInfrastructure.Services в AsbCloudApp.Services +6. Добавить или поправить тесты на изменяемый сервис используя AsbCloudWebApi.Tests.RepositoryFactory +7. В тестах сделать мок данных для репозитория \ No newline at end of file From b4372dde500324519c9b2e9247242047679a4523 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Thu, 13 Oct 2022 14:22:20 +0500 Subject: [PATCH 35/37] =?UTF-8?q?#6838390=20=D0=A3=D0=BC=D0=B5=D0=BD=D1=8C?= =?UTF-8?q?=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=85=D1=80=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=BC=D0=BE=D0=B9=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20SPIN=20master?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/SAUB/TelemetryDataSpinDto.cs | 113 +- ...ms_table_t_telemetry_data_spin.Designer.cs | 6543 +++++++++++++++++ ...lete_colums_table_t_telemetry_data_spin.cs | 577 ++ .../AsbCloudDbContextModelSnapshot.cs | 244 - AsbCloudDb/Model/TelemetryDataSpin.cs | 116 +- AsbCloudWebApi/Program.cs | 6 +- AsbCloudWebApi/ProtobufModel.cs | 55 +- 7 files changed, 7190 insertions(+), 464 deletions(-) create mode 100644 AsbCloudDb/Migrations/20221013040242_Delete_colums_table_t_telemetry_data_spin.Designer.cs create mode 100644 AsbCloudDb/Migrations/20221013040242_Delete_colums_table_t_telemetry_data_spin.cs diff --git a/AsbCloudApp/Data/SAUB/TelemetryDataSpinDto.cs b/AsbCloudApp/Data/SAUB/TelemetryDataSpinDto.cs index 1011f214..008bfeda 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryDataSpinDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryDataSpinDto.cs @@ -2,80 +2,77 @@ namespace AsbCloudApp.Data.SAUB { -#pragma warning disable CS1591 // Отсутствует комментарий XML для открытого видимого типа или члена +#nullable enable public class TelemetryDataSpinDto : ITelemetryData { - /// + /// + /// Идентификатор телеметрии + /// public int IdTelemetry { get; set; } + + /// + /// Дата + /// public DateTime DateTime { get; set; } - public DateTime Date // TODO: remove this legacy after all panels updated + + /// + /// Дата + /// + public DateTime Date { get { return DateTime; } set { DateTime = value; } } - public float? TopDriveSpeed { get; set; } - public float? TopDriveSpeedMin { get; set; } - public float? TopDriveSpeedMax { get; set; } - public float? TopDriveSpeedOffset { get; set; } - public short? TopDriveSpeedErr { get; set; } - public float? TopDriveTorque { get; set; } - public float? TopDriveTorqueMin { get; set; } - public float? TopDriveTorqueMax { get; set; } - public float? TopDriveTorqueOffset { get; set; } - public short? TopDriveTorqueErr { get; set; } - public float? TopDriveSpeedSpFrom { get; set; } - public float? TopDriveSpeedSpFromMin { get; set; } - public float? TopDriveSpeedSpFromMax { get; set; } - public float? TopDriveSpeedSpFromOffset { get; set; } - public short? TopDriveSpeedSpFromErr { get; set; } - public float? TopDriveTorqueSpFrom { get; set; } - public float? TopDriveTorqueSpFromMin { get; set; } - public float? TopDriveTorqueSpFromMax { get; set; } - public float? TopDriveTorqueSpFromOffset { get; set; } - public short? TopDriveTorqueSpFromErr { get; set; } - public float? TopDriveSpeedSpTo { get; set; } - public float? TopDriveSpeedSpToMin { get; set; } - public float? TopDriveSpeedSpToMax { get; set; } - public float? TopDriveSpeedSpToOffset { get; set; } - public short? TopDriveSpeedSpToErr { get; set; } - public float? TopDriveTorqueSpTo { get; set; } - public float? TopDriveTorqueSpToMin { get; set; } - public float? TopDriveTorqueSpToMax { get; set; } - public float? TopDriveTorqueSpToOffset { get; set; } - public short? TopDriveTorqueSpToErr { get; set; } - public short? W2800 { get; set; } - public short? W2810 { get; set; } - public short? Mode { get; set; } - public short? W2808 { get; set; } - public float? TorqueStarting { get; set; } - public float? RotorTorqueAvg { get; set; } - public float? EncoderResolution { get; set; } - public float? Ratio { get; set; } - public float? TorqueRightLimit { get; set; } - public float? TorqueLeftLimit { get; set; } + + /// + /// Ограничение числа оборотов вправо + /// public float? RevolsRightLimit { get; set; } + + /// + /// Ограничение числа оборотов влево + /// public float? RevolsLeftLimit { get; set; } + + /// + /// Заданная скорость вращения вправо + /// public float? SpeedRightSp { get; set; } + + /// + /// Заданная скорость вращения влево + /// public float? SpeedLeftSp { get; set; } + + /// + /// Суммарное количество оборотов вправо + /// public float? RevolsRightTotal { get; set; } + + /// + /// Суммарное количество оборотов влево + /// public float? RevolsLeftTotal { get; set; } - public float? TurnRightOnceByTorque { get; set; } - public float? TurnLeftOnceByTorque { get; set; } - public float? TurnRightOnceByAngle { get; set; } - public float? TurnLeftOnceByAngle { get; set; } - public float? TurnRightOnceByRevols { get; set; } - public float? TurnLeftOnceByRevols { get; set; } - public float? BreakAngleK { get; set; } - public float? ReverseKTorque { get; set; } + + /// + /// Нулевая позиция осцилляции + /// public float? PositionZero { get; set; } + + /// + /// Крайний правый угол осцилляции + /// public float? PositionRight { get; set; } - public float? TorqueRampTime { get; set; } - public float? Ver { get; set; } - public short? ReverseSpeedSpZeroTime { get; set; } - public float? UnlockBySectorOut { get; set; } - public float? PidMuxTorqueLeftLimit { get; set; } + + /// + /// Выбранный режим управления + /// + public short? Mode { get; set; } + + /// + /// Переменная этапа + /// public short? State { get; set; } - public float? BreakAngleLeft { get; set; } } -#pragma warning restore CS1591 // Отсутствует комментарий XML для открытого видимого типа или члена +#nullable disable } diff --git a/AsbCloudDb/Migrations/20221013040242_Delete_colums_table_t_telemetry_data_spin.Designer.cs b/AsbCloudDb/Migrations/20221013040242_Delete_colums_table_t_telemetry_data_spin.Designer.cs new file mode 100644 index 00000000..d42e6b13 --- /dev/null +++ b/AsbCloudDb/Migrations/20221013040242_Delete_colums_table_t_telemetry_data_spin.Designer.cs @@ -0,0 +1,6543 @@ +// +using System; +using System.Text.Json; +using AsbCloudDb.Model; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace AsbCloudDb.Migrations +{ + [DbContext(typeof(AsbCloudDbContext))] + [Migration("20221013040242_Delete_colums_table_t_telemetry_data_spin")] + partial class Delete_colums_table_t_telemetry_data_spin + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseCollation("Russian_Russia.1251") + .HasAnnotation("ProductVersion", "6.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack"); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AsbCloudDb.Model.Cluster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.Property("IdDeposit") + .HasColumnType("integer") + .HasColumnName("id_deposit"); + + b.Property("Latitude") + .HasColumnType("double precision") + .HasColumnName("latitude"); + + b.Property("Longitude") + .HasColumnType("double precision") + .HasColumnName("longitude"); + + b.Property("Timezone") + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.HasIndex("IdDeposit"); + + b.ToTable("t_cluster"); + + b.HasComment("Кусты"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property("IdCompanyType") + .HasMaxLength(255) + .HasColumnType("integer") + .HasColumnName("id_company_type") + .HasComment("вид деятельности"); + + b.HasKey("Id"); + + b.HasIndex("IdCompanyType"); + + b.ToTable("t_company"); + + b.HasData( + new + { + Id = 1, + Caption = "ООО \"АСБ\"", + IdCompanyType = 3 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.CompanyType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.HasKey("Id"); + + b.ToTable("t_company_type"); + + b.HasData( + new + { + Id = 1, + Caption = "Недрапользователь" + }, + new + { + Id = 2, + Caption = "Буровой подрядчик" + }, + new + { + Id = 3, + Caption = "Сервис автоматизации бурения" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DailyReport.DailyReport", b => + { + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("ID скважины"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("start_date") + .HasComment("Дата отчёта"); + + b.Property("Info") + .HasColumnType("jsonb") + .HasColumnName("info") + .HasComment("Список параметров для отчёта"); + + b.HasKey("IdWell", "StartDate") + .HasName("t_id_well_date_start_pk"); + + b.ToTable("t_daily_report"); + + b.HasComment("Ежедневные отчёты"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Deposit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property("Latitude") + .HasColumnType("double precision") + .HasColumnName("latitude"); + + b.Property("Longitude") + .HasColumnType("double precision") + .HasColumnName("longitude"); + + b.Property("Timezone") + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.ToTable("t_deposit"); + + b.HasComment("Месторождение"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DetectedOperation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_end") + .HasComment("Дата начала операции"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start") + .HasComment("Дата начала операции"); + + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина после завершения операции, м"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина на начало операции, м"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Id категории операции"); + + b.Property("IdReasonOfEnd") + .HasColumnType("integer") + .HasColumnName("id_reason_of_end") + .HasComment("Код признака окончания операции"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdUsersAtStart") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Id пользователя по телеметрии на момент начала операции"); + + b.Property("Value") + .HasColumnType("double precision") + .HasColumnName("value") + .HasComment("Ключевой показатель операции"); + + b.HasKey("Id"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_detected_operation"); + + b.HasComment("автоматически определенные операции по телеметрии"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Driller", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name") + .HasComment("Имя"); + + b.Property("Patronymic") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("patronymic") + .HasComment("Отчество"); + + b.Property("Surname") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("surname") + .HasComment("Фамилия"); + + b.HasKey("Id"); + + b.ToTable("t_driller"); + + b.HasComment("Бурильщик"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillFlowChart", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AxialLoadMax") + .HasColumnType("double precision") + .HasColumnName("axial_load_max") + .HasComment("Максимальная нагрузка"); + + b.Property("AxialLoadMin") + .HasColumnType("double precision") + .HasColumnName("axial_load_min") + .HasComment("Минимальная нагрузка"); + + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина окончания интервала"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Стартовая глубина"); + + b.Property("FlowMax") + .HasColumnType("double precision") + .HasColumnName("flow_max") + .HasComment("Максимальный расход"); + + b.Property("FlowMin") + .HasColumnType("double precision") + .HasColumnName("flow_min") + .HasComment("Минимальный расход"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("well_id") + .HasComment("Id скважины"); + + b.Property("IdWellOperationCategory") + .HasColumnType("integer") + .HasColumnName("id_operation_category") + .HasComment("Id типа операции"); + + b.Property("LastUpdate") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_update") + .HasComment("Дата последнего изменения"); + + b.Property("PressureMax") + .HasColumnType("double precision") + .HasColumnName("pressure_max") + .HasComment("Максимальное давление"); + + b.Property("PressureMin") + .HasColumnType("double precision") + .HasColumnName("pressure_min") + .HasComment("Минимальное давление"); + + b.Property("RotorSpeedMax") + .HasColumnType("double precision") + .HasColumnName("rotor_speed_max") + .HasComment("Максимальные обороты на ВСП"); + + b.Property("RotorSpeedMin") + .HasColumnType("double precision") + .HasColumnName("rotor_speed_min") + .HasComment("Минимальные обороты на ВСП"); + + b.Property("RotorTorqueMax") + .HasColumnType("double precision") + .HasColumnName("rotor_torque_max") + .HasComment("Максимальный момент на ВСП"); + + b.Property("RotorTorqueMin") + .HasColumnType("double precision") + .HasColumnName("rotor_torque_min") + .HasComment("Минимальный момент на ВСП"); + + b.HasKey("Id"); + + b.HasIndex("IdWell"); + + b.HasIndex("IdWellOperationCategory"); + + b.ToTable("t_drill_flow_chart"); + + b.HasComment("Параметры коридоров бурения (диапазоны параметров бурения)"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IdFileCategory") + .HasColumnType("integer") + .HasColumnName("id_file_category"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.HasKey("Id"); + + b.HasIndex("IdFileCategory"); + + b.HasIndex("IdWell", "IdFileCategory") + .IsUnique(); + + b.ToTable("t_drilling_program_part"); + + b.HasComment("части программ бурения"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillParams", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AxialLoadAvg") + .HasColumnType("double precision") + .HasColumnName("axial_load_avg") + .HasComment("Средняя нагрузка"); + + b.Property("AxialLoadMax") + .HasColumnType("double precision") + .HasColumnName("axial_load_max") + .HasComment("Максимальная нагрузка"); + + b.Property("AxialLoadMin") + .HasColumnType("double precision") + .HasColumnName("axial_load_min") + .HasComment("Минимальная нагрузка"); + + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина окончания интервала"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Стартовая глубина"); + + b.Property("FlowAvg") + .HasColumnType("double precision") + .HasColumnName("flow_avg") + .HasComment("Средний расход"); + + b.Property("FlowMax") + .HasColumnType("double precision") + .HasColumnName("flow_max") + .HasComment("Максимальный расход"); + + b.Property("FlowMin") + .HasColumnType("double precision") + .HasColumnName("flow_min") + .HasComment("Минимальный расход"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("well_id") + .HasComment("Id скважины"); + + b.Property("IdWellSectionType") + .HasColumnType("integer") + .HasColumnName("id_wellsection_type") + .HasComment("Id с типом секции скважины"); + + b.Property("PressureAvg") + .HasColumnType("double precision") + .HasColumnName("pressure_avg") + .HasComment("Среднее давление"); + + b.Property("PressureMax") + .HasColumnType("double precision") + .HasColumnName("pressure_max") + .HasComment("Максимальное давление"); + + b.Property("PressureMin") + .HasColumnType("double precision") + .HasColumnName("pressure_min") + .HasComment("Минимальное давление"); + + b.Property("RotorSpeedAvg") + .HasColumnType("double precision") + .HasColumnName("rotor_speed_avg") + .HasComment("Средние обороты на ВСП"); + + b.Property("RotorSpeedMax") + .HasColumnType("double precision") + .HasColumnName("rotor_speed_max") + .HasComment("Максимальные обороты на ВСП"); + + b.Property("RotorSpeedMin") + .HasColumnType("double precision") + .HasColumnName("rotor_speed_min") + .HasComment("Минимальные обороты на ВСП"); + + b.Property("RotorTorqueAvg") + .HasColumnType("double precision") + .HasColumnName("rotor_torque_avg") + .HasComment("Средний момент на ВСП"); + + b.Property("RotorTorqueMax") + .HasColumnType("double precision") + .HasColumnName("rotor_torque_max") + .HasComment("Максимальный момент на ВСП"); + + b.Property("RotorTorqueMin") + .HasColumnType("double precision") + .HasColumnName("rotor_torque_min") + .HasComment("Минимальный момент на ВСП"); + + b.HasKey("Id"); + + b.HasIndex("IdWell"); + + b.HasIndex("IdWellSectionType"); + + b.ToTable("t_drill_params"); + + b.HasComment("Режим бурения в секции (диапазоны параметров бурения)"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название категории"); + + b.Property("ShortName") + .HasColumnType("text") + .HasColumnName("short_name") + .HasComment("Короткое название категории"); + + b.HasKey("Id"); + + b.ToTable("t_file_category"); + + b.HasComment("Категории файлов"); + + b.HasData( + new + { + Id = 1, + Name = "Растворный сервис", + ShortName = "fluidService" + }, + new + { + Id = 2, + Name = "Цементирование", + ShortName = "cement" + }, + new + { + Id = 3, + Name = "ННБ", + ShortName = "nnb" + }, + new + { + Id = 4, + Name = "ГТИ", + ShortName = "gti" + }, + new + { + Id = 5, + Name = "Документы по скважине", + ShortName = "wellDocuments" + }, + new + { + Id = 6, + Name = "Супервайзер", + ShortName = "supervisor" + }, + new + { + Id = 7, + Name = "Мастер", + ShortName = "master" + }, + new + { + Id = 8, + Name = "Долотный сервис", + ShortName = "toolService" + }, + new + { + Id = 9, + Name = "Буровой подрядчик", + ShortName = "drillService" + }, + new + { + Id = 10, + Name = "Сервис по заканчиванию скважины", + ShortName = "closingService" + }, + new + { + Id = 12, + Name = "Рапорт", + ShortName = "report" + }, + new + { + Id = 1000, + Name = "Программа бурения" + }, + new + { + Id = 1001, + Name = "Задание от геологов" + }, + new + { + Id = 1002, + Name = "Профиль ствола скважины (ННБ)" + }, + new + { + Id = 1003, + Name = "Технологические расчеты (ННБ)" + }, + new + { + Id = 1004, + Name = "Долотная программа" + }, + new + { + Id = 1005, + Name = "Программа по растворам" + }, + new + { + Id = 1006, + Name = "Программа геофизических исследований" + }, + new + { + Id = 1007, + Name = "Планы спусков обсадных колонн" + }, + new + { + Id = 1008, + Name = "Программы цементирования обсадных колонн" + }, + new + { + Id = 10000, + Name = "Проект на бурение транспортного и горизонтального участков скважины" + }, + new + { + Id = 10001, + Name = "Программа на бурение транспортного и горизонтального участков скважины" + }, + new + { + Id = 10002, + Name = "Акт о начале бурения" + }, + new + { + Id = 10003, + Name = "План работ спуска и цементирования направления" + }, + new + { + Id = 10004, + Name = "Программа цементирования направления" + }, + new + { + Id = 10005, + Name = "Мера обсадных труб (направление)" + }, + new + { + Id = 10006, + Name = "Акт на выполненные работы по цементированию направления" + }, + new + { + Id = 10007, + Name = "Отчет по цементированию направления (график)" + }, + new + { + Id = 10008, + Name = "План работ спуска и цементирования кондуктора" + }, + new + { + Id = 10009, + Name = "Программа цементирования (кондуктор)" + }, + new + { + Id = 10010, + Name = "Мера обсадных труб (кондуктор)" + }, + new + { + Id = 10011, + Name = "Карта крепления кондуктора" + }, + new + { + Id = 10012, + Name = "Акт на выполненные работы по цементированию кондуктора" + }, + new + { + Id = 10013, + Name = "Отчет по цементированию кондуктора (график)" + }, + new + { + Id = 10014, + Name = "Акт о замере расстояния от стола ротора до муфты кондуктора" + }, + new + { + Id = 10015, + Name = "Акт опресовки цементного кольца за кондуктором" + }, + new + { + Id = 10016, + Name = "Акт опресовки ППГ с глухими плашками совместно с кондуктором" + }, + new + { + Id = 10017, + Name = "Акт опресовки ПУГ, ППГ с трубными плашками совместно с кондуктором" + }, + new + { + Id = 10018, + Name = "План работ на крепление обсадной колонны (эк. колонна)" + }, + new + { + Id = 10019, + Name = "Программа цементирования (эк. колонна)" + }, + new + { + Id = 10020, + Name = "Мера труб эксплуатационной колонны" + }, + new + { + Id = 10021, + Name = "Карта по креплению скважины (эк. колонна)" + }, + new + { + Id = 10022, + Name = "Акт на установку пружинных центраторов" + }, + new + { + Id = 10023, + Name = "Отчет по цементированию эксплуатационной колонны (график)" + }, + new + { + Id = 10024, + Name = "Акт на выполненные работы по цементированию эксплуатационной колонны" + }, + new + { + Id = 10025, + Name = "Акт об испытании эк. колонны на герметичность (СТОП)" + }, + new + { + Id = 10026, + Name = "Акт опресовки ППГ с глухими плашками совместно с э/колонной" + }, + new + { + Id = 10027, + Name = "Акт опресовки ПУГ, ППГ с трубными плашками совместно с э/колонной" + }, + new + { + Id = 10028, + Name = "Акт на вскрытие продуктивного пласта" + }, + new + { + Id = 10029, + Name = "Акт замера параметров раствора при бурении горизонтального участка" + }, + new + { + Id = 10030, + Name = "Разрешение на спуск «хвостовика» (телефонограмма)" + }, + new + { + Id = 10031, + Name = "План работ на спуск «хвостовика»" + }, + new + { + Id = 10032, + Name = "Акт готовности бурового и энергетического оборудования к спуску «хвостовика»" + }, + new + { + Id = 10033, + Name = "Акт шаблонировки ствола скважины перед спуском «хвостовика»" + }, + new + { + Id = 10034, + Name = "Мера обсадных труб (хвостовик)" + }, + new + { + Id = 10035, + Name = "Акт выполненных работ по спуску хвостовика с закачкой (нефти, солевого раствора" + }, + new + { + Id = 10036, + Name = "Акт о переводе скважины на тех. воду" + }, + new + { + Id = 10037, + Name = "Акт об окончании бурения" + }, + new + { + Id = 10038, + Name = "Акт на передачу скважины в освоение (КРС)" + }, + new + { + Id = 10039, + Name = "Акт на опресовку межколонного пространства с КРС" + }, + new + { + Id = 10040, + Name = "Акт на сдачу скважины в ЦДНГ" + }, + new + { + Id = 10041, + Name = "Паспорт ОУС (заполняется геологами)" + }, + new + { + Id = 10042, + Name = "Паспорт скважины (заполняется геологами)" + }, + new + { + Id = 10043, + Name = "Фактические данные бурения (вставляются в паспорт скважины)" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IdAuthor") + .HasColumnType("integer") + .HasColumnName("id_author") + .HasComment("Id пользователя, загрузившего файл"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("id категории файла"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property("IsDeleted") + .HasColumnType("boolean") + .HasColumnName("is_deleted") + .HasComment("Удален ли файл"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название файла"); + + b.Property("Size") + .HasColumnType("bigint") + .HasColumnName("file_size") + .HasComment("Размер файла"); + + b.Property("UploadDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthor"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdWell"); + + b.ToTable("t_file_info"); + + b.HasComment("Файлы всех категорий"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileMark", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Comment") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("comment") + .HasComment("Комментарий"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created") + .HasComment("Дата совершенного действия"); + + b.Property("IdFile") + .HasColumnType("integer") + .HasColumnName("id_file") + .HasComment("id файла"); + + b.Property("IdMarkType") + .HasColumnType("integer") + .HasColumnName("id_mark_type") + .HasComment("0 - отклонен, 1 - согласован"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("id пользователя"); + + b.Property("IsDeleted") + .HasColumnType("boolean") + .HasColumnName("is_deleted") + .HasComment("Помечен ли файл как удаленный"); + + b.HasKey("Id"); + + b.HasIndex("IdFile"); + + b.HasIndex("IdUser"); + + b.ToTable("t_file_mark"); + + b.HasComment("Действия с файлами."); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Measure", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .HasColumnType("jsonb") + .HasColumnName("data") + .HasComment("Данные таблицы последних данных"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("id категории"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property("IsDeleted") + .HasColumnType("boolean") + .HasColumnName("is_deleted") + .HasComment("Пометка удаленным"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp") + .HasComment("время добавления"); + + b.HasKey("Id"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdWell"); + + b.ToTable("t_measure"); + + b.HasComment("Таблица c данными для вкладки 'Последние данные'"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.MeasureCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название категории"); + + b.Property("ShortName") + .HasColumnType("text") + .HasColumnName("short_name") + .HasComment("Короткое название категории"); + + b.HasKey("Id"); + + b.ToTable("t_measure_category"); + + b.HasComment("Категория последних данных"); + + b.HasData( + new + { + Id = 1, + Name = "Показатели бурового раствора", + ShortName = "Раствор" + }, + new + { + Id = 2, + Name = "Шламограмма", + ShortName = "Шламограмма" + }, + new + { + Id = 3, + Name = "ННБ", + ShortName = "ННБ" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.OperationValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Конечная глубина"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Старотовая глубина"); + + b.Property("IdOperationCategory") + .HasColumnType("integer") + .HasColumnName("id_operation_category") + .HasComment("Ид категории операции"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Ид скважины"); + + b.Property("StandardValue") + .HasColumnType("double precision") + .HasColumnName("standard_value") + .HasComment("Нормативный показатель"); + + b.Property("TargetValue") + .HasColumnType("double precision") + .HasColumnName("target_value") + .HasComment("Целевой показатель"); + + b.HasKey("Id"); + + b.HasIndex("IdOperationCategory"); + + b.HasIndex("IdWell"); + + b.ToTable("t_operationvalue"); + + b.HasComment("Целевые/нормативные показатели операции"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("description") + .HasComment("Краткое описание"); + + b.Property("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name") + .HasComment("Название"); + + b.HasKey("Id"); + + b.ToTable("t_permission"); + + b.HasComment("Разрешения на доступ к данным"); + + b.HasData( + new + { + Id = 100, + Description = "Разрешение удалять админ. Кусты", + Name = "AdminCluster.delete" + }, + new + { + Id = 101, + Description = "Разрешение редактировать админ. Кусты", + Name = "AdminCluster.edit" + }, + new + { + Id = 102, + Description = "Разрешение просматривать админ. Кусты", + Name = "AdminCluster.get" + }, + new + { + Id = 103, + Description = "Разрешение удалять админ. Компании", + Name = "AdminCompany.delete" + }, + new + { + Id = 104, + Description = "Разрешение редактировать админ. Компании", + Name = "AdminCompany.edit" + }, + new + { + Id = 105, + Description = "Разрешение просматривать админ. Компании", + Name = "AdminCompany.get" + }, + new + { + Id = 106, + Description = "Разрешение удалять админ. Типы компаний", + Name = "AdminCompanyType.delete" + }, + new + { + Id = 107, + Description = "Разрешение редактировать админ. Типы компаний", + Name = "AdminCompanyType.edit" + }, + new + { + Id = 108, + Description = "Разрешение просматривать админ. Типы компаний", + Name = "AdminCompanyType.get" + }, + new + { + Id = 109, + Description = "Разрешение удалять админ. Месторождения", + Name = "AdminDeposit.delete" + }, + new + { + Id = 110, + Description = "Разрешение редактировать админ. Месторождения", + Name = "AdminDeposit.edit" + }, + new + { + Id = 111, + Description = "Разрешение просматривать админ. Месторождения", + Name = "AdminDeposit.get" + }, + new + { + Id = 112, + Description = "Разрешение удалять админ. Разрешения", + Name = "AdminPermission.delete" + }, + new + { + Id = 113, + Description = "Разрешение редактировать админ. Разрешения", + Name = "AdminPermission.edit" + }, + new + { + Id = 114, + Description = "Разрешение просматривать админ. Разрешения", + Name = "AdminPermission.get" + }, + new + { + Id = 115, + Description = "Разрешение удалять админ. Телеметрию", + Name = "AdminTelemetry.delete" + }, + new + { + Id = 116, + Description = "Разрешение редактировать админ. Телеметрию", + Name = "AdminTelemetry.edit" + }, + new + { + Id = 117, + Description = "Разрешение просматривать админ. Телеметрию", + Name = "AdminTelemetry.get" + }, + new + { + Id = 118, + Description = "Разрешение удалять админ. Пользователей", + Name = "AdminUser.delete" + }, + new + { + Id = 119, + Description = "Разрешение редактировать админ. Пользователей", + Name = "AdminUser.edit" + }, + new + { + Id = 120, + Description = "Разрешение просматривать админ. Пользователей", + Name = "AdminUser.get" + }, + new + { + Id = 121, + Description = "Разрешение удалять админ. Роли пользователей", + Name = "AdminUserRole.delete" + }, + new + { + Id = 122, + Description = "Разрешение редактировать админ. Роли пользователей", + Name = "AdminUserRole.edit" + }, + new + { + Id = 123, + Description = "Разрешение просматривать админ. Роли пользователей", + Name = "AdminUserRole.get" + }, + new + { + Id = 124, + Description = "Разрешение удалять админ. Скважины", + Name = "AdminWell.delete" + }, + new + { + Id = 125, + Description = "Разрешение редактировать админ. Скважины", + Name = "AdminWell.edit" + }, + new + { + Id = 126, + Description = "Разрешение просматривать админ. Скважины", + Name = "AdminWell.get" + }, + new + { + Id = 127, + Description = "Разрешение удалять админ. Подсистемы", + Name = "AdminSubsytem.delete" + }, + new + { + Id = 128, + Description = "Разрешение редактировать админ. Подсистемы", + Name = "AdminSubsytem.edit" + }, + new + { + Id = 129, + Description = "Разрешение просматривать админ. Подсистемы", + Name = "AdminSubsytem.get" + }, + new + { + Id = 200, + Description = "Разрешение редактировать 0", + Name = "Auth.edit" + }, + new + { + Id = 201, + Description = "Разрешение просматривать 0", + Name = "Auth.get" + }, + new + { + Id = 202, + Description = "Разрешение просматривать Кусты", + Name = "Cluster.get" + }, + new + { + Id = 203, + Description = "Разрешение просматривать Месторождения", + Name = "Deposit.get" + }, + new + { + Id = 204, + Description = "Разрешение удалять РТК", + Name = "DrillFlowChart.delete" + }, + new + { + Id = 205, + Description = "Разрешение редактировать РТК", + Name = "DrillFlowChart.edit" + }, + new + { + Id = 206, + Description = "Разрешение просматривать РТК", + Name = "DrillFlowChart.get" + }, + new + { + Id = 207, + Description = "Разрешение удалять Программу бурения", + Name = "DrillingProgram.delete" + }, + new + { + Id = 208, + Description = "Разрешение редактировать Программу бурения", + Name = "DrillingProgram.edit" + }, + new + { + Id = 209, + Description = "Разрешение просматривать Программу бурения", + Name = "DrillingProgram.get" + }, + new + { + Id = 210, + Description = "Разрешение удалять Режимы бурения", + Name = "DrillParams.delete" + }, + new + { + Id = 211, + Description = "Разрешение редактировать Режимы бурения", + Name = "DrillParams.edit" + }, + new + { + Id = 212, + Description = "Разрешение просматривать Режимы бурения", + Name = "DrillParams.get" + }, + new + { + Id = 213, + Description = "Разрешение удалять Файлы", + Name = "File.delete" + }, + new + { + Id = 214, + Description = "Разрешение редактировать Файлы", + Name = "File.edit" + }, + new + { + Id = 215, + Description = "Разрешение просматривать Файлы", + Name = "File.get" + }, + new + { + Id = 216, + Description = "Разрешение удалять Измерения", + Name = "Measure.delete" + }, + new + { + Id = 217, + Description = "Разрешение редактировать Измерения", + Name = "Measure.edit" + }, + new + { + Id = 218, + Description = "Разрешение просматривать Измерения", + Name = "Measure.get" + }, + new + { + Id = 219, + Description = "Разрешение просматривать Сообщения телеметрии", + Name = "Message.get" + }, + new + { + Id = 220, + Description = "Разрешение просматривать Статистику по операциям", + Name = "OperationStat.get" + }, + new + { + Id = 221, + Description = "Разрешение редактировать Рапорта", + Name = "Report.edit" + }, + new + { + Id = 222, + Description = "Разрешение просматривать Рапорта", + Name = "Report.get" + }, + new + { + Id = 223, + Description = "Разрешение просматривать админ. Системная статистика", + Name = "RequestTracker.get" + }, + new + { + Id = 224, + Description = "Разрешение удалять Рекомендации уставок", + Name = "Setpoints.delete" + }, + new + { + Id = 225, + Description = "Разрешение редактировать Рекомендации уставок", + Name = "Setpoints.edit" + }, + new + { + Id = 226, + Description = "Разрешение просматривать Рекомендации уставок", + Name = "Setpoints.get" + }, + new + { + Id = 227, + Description = "Разрешение редактировать Телеметрии", + Name = "Telemetry.edit" + }, + new + { + Id = 228, + Description = "Разрешение просматривать Анализ телеметрии", + Name = "TelemetryAnalytics.get" + }, + new + { + Id = 229, + Description = "Разрешение редактировать Данные телеметрии по САУБ", + Name = "TelemetryDataSaub.edit" + }, + new + { + Id = 230, + Description = "Разрешение просматривать Данные телеметрии по САУБ", + Name = "TelemetryDataSaub.get" + }, + new + { + Id = 231, + Description = "Разрешение редактировать Данные телеметрии по SpinMaster", + Name = "TelemetryDataSpin.edit" + }, + new + { + Id = 232, + Description = "Разрешение просматривать Данные телеметрии по SpinMaster", + Name = "TelemetryDataSpin.get" + }, + new + { + Id = 233, + Description = "Разрешение редактировать Скважины", + Name = "Well.edit" + }, + new + { + Id = 234, + Description = "Разрешение просматривать Скважины", + Name = "Well.get" + }, + new + { + Id = 235, + Description = "Разрешение редактировать Композитные скважины", + Name = "WellComposite.edit" + }, + new + { + Id = 236, + Description = "Разрешение просматривать Композитные скважины", + Name = "WellComposite.get" + }, + new + { + Id = 237, + Description = "Разрешение удалять Операции по скважинам", + Name = "WellOperation.delete" + }, + new + { + Id = 238, + Description = "Разрешение редактировать Операции по скважинам", + Name = "WellOperation.edit" + }, + new + { + Id = 239, + Description = "Разрешение просматривать Операции по скважинам", + Name = "WellOperation.get" + }, + new + { + Id = 240, + Description = "Разрешение редактировать Файлы категории 1 (Растворный сервис)", + Name = "File.edit1" + }, + new + { + Id = 241, + Description = "Разрешение редактировать Файлы категории 2 (Цементирование)", + Name = "File.edit2" + }, + new + { + Id = 242, + Description = "Разрешение редактировать Файлы категории 3 (ННБ)", + Name = "File.edit3" + }, + new + { + Id = 243, + Description = "Разрешение редактировать Файлы категории 4 (ГТИ)", + Name = "File.edit4" + }, + new + { + Id = 244, + Description = "Разрешение редактировать Файлы категории 5 (Документы по скважине)", + Name = "File.edit5" + }, + new + { + Id = 245, + Description = "Разрешение редактировать Файлы категории 6 (Супервайзер)", + Name = "File.edit6" + }, + new + { + Id = 246, + Description = "Разрешение редактировать Файлы категории 7 (Мастер)", + Name = "File.edit7" + }, + new + { + Id = 247, + Description = "Разрешение редактировать Файлы категории 8 (Долотный сервис)", + Name = "File.edit8" + }, + new + { + Id = 248, + Description = "Разрешение редактировать Файлы категории 9 (Буровой подрядчик)", + Name = "File.edit9" + }, + new + { + Id = 249, + Description = "Разрешение редактировать Файлы категории 10 (Сервис по заканчиванию скважины)", + Name = "File.edit10" + }, + new + { + Id = 250, + Description = "Разрешение редактировать Файлы категории 11 (Рапорт)", + Name = "File.edit11" + }, + new + { + Id = 251, + Description = "Разрешение редактировать Файлы категории 12", + Name = "File.edit12" + }, + new + { + Id = 252, + Description = "Разрешение редактировать Файлы категории 12", + Name = "File.edit13" + }, + new + { + Id = 253, + Description = "Разрешение редактировать Файлы категории 13", + Name = "File.edit14" + }, + new + { + Id = 254, + Description = "Разрешение редактировать Файлы категории 14", + Name = "File.edit15" + }, + new + { + Id = 255, + Description = "Разрешение редактировать Файлы категории 15", + Name = "File.edit16" + }, + new + { + Id = 256, + Description = "Разрешение редактировать Файлы категории 16", + Name = "File.edit17" + }, + new + { + Id = 257, + Description = "Разрешение редактировать Файлы категории 17", + Name = "File.edit18" + }, + new + { + Id = 258, + Description = "Разрешение редактировать Файлы категории 18", + Name = "File.edit19" + }, + new + { + Id = 259, + Description = "Разрешение редактировать Файлы категории 19", + Name = "File.edit20" + }, + new + { + Id = 260, + Description = "Разрешение редактировать Файлы категории 20", + Name = "File.edit21" + }, + new + { + Id = 261, + Description = "Разрешение редактировать Файлы категории 21", + Name = "File.edit22" + }, + new + { + Id = 262, + Description = "Разрешение редактировать Файлы категории 22", + Name = "File.edit23" + }, + new + { + Id = 263, + Description = "Разрешение редактировать Файлы категории 23", + Name = "File.edit24" + }, + new + { + Id = 264, + Description = "Разрешение редактировать Файлы категории 24", + Name = "File.edit25" + }, + new + { + Id = 265, + Description = "Разрешение редактировать Файлы категории 25", + Name = "File.edit26" + }, + new + { + Id = 266, + Description = "Разрешение редактировать Файлы категории 26", + Name = "File.edit27" + }, + new + { + Id = 267, + Description = "Разрешение редактировать Файлы категории 27", + Name = "File.edit28" + }, + new + { + Id = 268, + Description = "Разрешение редактировать Файлы категории 28", + Name = "File.edit29" + }, + new + { + Id = 269, + Description = "Разрешение редактировать Файлы категории 29", + Name = "File.edit30" + }, + new + { + Id = 380, + Description = "Разрешение просматривать список бурильщиков", + Name = "Driller.get" + }, + new + { + Id = 381, + Description = "Разрешение редактировать бурильщика", + Name = "Driller.edit" + }, + new + { + Id = 382, + Description = "Разрешение удалять бурильщик", + Name = "Driller.delete" + }, + new + { + Id = 383, + Description = "Разрешение просматривать графики бурильщиков", + Name = "Schedule.get" + }, + new + { + Id = 384, + Description = "Разрешение редактировать график бурильщика", + Name = "Schedule.edit" + }, + new + { + Id = 385, + Description = "Разрешение удалять график бурильщика", + Name = "Schedule.delete" + }, + new + { + Id = 386, + Description = "Разрешение просматривать суточный рапорт", + Name = "DailyReport.get" + }, + new + { + Id = 387, + Description = "Разрешение редактировать суточный рапорт", + Name = "DailyReport.edit" + }, + new + { + Id = 388, + Description = "Разрешение просматривать авто. определенные операции", + Name = "DetectedOperation.get" + }, + new + { + Id = 389, + Description = "Разрешение просматривать целевые значения", + Name = "OperationValue.get" + }, + new + { + Id = 390, + Description = "Разрешение редактировать целевые значения", + Name = "OperationValue.edit" + }, + new + { + Id = 391, + Description = "Разрешение удалять целевые значения", + Name = "OperationValue.delete" + }, + new + { + Id = 400, + Description = "Разрешение просматривать инфо по wits параметрам", + Name = "WitsInfo.get" + }, + new + { + Id = 401, + Description = "Разрешение просматривать WITS record 1", + Name = "WitsRecord1.get" + }, + new + { + Id = 407, + Description = "Разрешение просматривать WITS record 7", + Name = "WitsRecord7.get" + }, + new + { + Id = 408, + Description = "Разрешение просматривать WITS record 8", + Name = "WitsRecord8.get" + }, + new + { + Id = 450, + Description = "Разрешение просматривать WITS record 50", + Name = "WitsRecord50.get" + }, + new + { + Id = 460, + Description = "Разрешение просматривать WITS record 60", + Name = "WitsRecord60.get" + }, + new + { + Id = 461, + Description = "Разрешение просматривать WITS record 61", + Name = "WitsRecord61.get" + }, + new + { + Id = 500, + Description = "Разрешение удалять Категорий документов файлов", + Name = "FileCategory.delete" + }, + new + { + Id = 501, + Description = "Разрешение редактировать Категорий документов файлов", + Name = "FileCategory.edit" + }, + new + { + Id = 502, + Description = "Разрешение просматривать Категорий документов файлов", + Name = "FileCategory.get" + }, + new + { + Id = 503, + Description = "Разрешение удалять Дело скважины", + Name = "WellFinalDocuments.delete" + }, + new + { + Id = 504, + Description = "Разрешение редактировать Дело скважины", + Name = "WellFinalDocuments.edit" + }, + new + { + Id = 505, + Description = "Разрешение просматривать Дело скважины", + Name = "WellFinalDocuments.get" + }, + new + { + Id = 506, + Description = "Разрешение редактировать ответственных за загрузку файла Дело скважины", + Name = "WellFinalDocuments.editPublisher" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationCompanyWell", b => + { + b.Property("IdCompany") + .HasColumnType("integer") + .HasColumnName("id_company"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.HasKey("IdCompany", "IdWell"); + + b.HasIndex("IdWell"); + + b.ToTable("t_relation_company_well"); + + b.HasComment("отношение скважин и компаний"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserDrillingProgramPart", b => + { + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property("IdDrillingProgramPart") + .HasColumnType("integer") + .HasColumnName("id_drilling_program_part"); + + b.Property("IdUserRole") + .HasColumnType("integer") + .HasColumnName("id_role") + .HasComment("1 - publisher, 2 - approver"); + + b.HasKey("IdUser", "IdDrillingProgramPart") + .HasName("t_relation_user_drilling_program_part_pk"); + + b.HasIndex("IdDrillingProgramPart"); + + b.ToTable("t_relation_user_drilling_program_part"); + + b.HasComment("Отношение пользователей и частей ПБ"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserRolePermission", b => + { + b.Property("IdUserRole") + .HasColumnType("integer") + .HasColumnName("id_user_role"); + + b.Property("IdPermission") + .HasColumnType("integer") + .HasColumnName("id_permission"); + + b.HasKey("IdUserRole", "IdPermission"); + + b.HasIndex("IdPermission"); + + b.ToTable("t_relation_user_role_permission"); + + b.HasComment("Отношение ролей пользователей и разрешений доступа"); + + b.HasData( + new + { + IdUserRole = 1100, + IdPermission = 102 + }, + new + { + IdUserRole = 1100, + IdPermission = 111 + }, + new + { + IdUserRole = 1101, + IdPermission = 101 + }, + new + { + IdUserRole = 1101, + IdPermission = 100 + }, + new + { + IdUserRole = 1102, + IdPermission = 105 + }, + new + { + IdUserRole = 1102, + IdPermission = 108 + }, + new + { + IdUserRole = 1103, + IdPermission = 104 + }, + new + { + IdUserRole = 1103, + IdPermission = 103 + }, + new + { + IdUserRole = 1104, + IdPermission = 108 + }, + new + { + IdUserRole = 1105, + IdPermission = 107 + }, + new + { + IdUserRole = 1105, + IdPermission = 106 + }, + new + { + IdUserRole = 1106, + IdPermission = 111 + }, + new + { + IdUserRole = 1107, + IdPermission = 110 + }, + new + { + IdUserRole = 1107, + IdPermission = 109 + }, + new + { + IdUserRole = 1108, + IdPermission = 114 + }, + new + { + IdUserRole = 1109, + IdPermission = 113 + }, + new + { + IdUserRole = 1109, + IdPermission = 112 + }, + new + { + IdUserRole = 1110, + IdPermission = 123 + }, + new + { + IdUserRole = 1110, + IdPermission = 114 + }, + new + { + IdUserRole = 1111, + IdPermission = 122 + }, + new + { + IdUserRole = 1111, + IdPermission = 121 + }, + new + { + IdUserRole = 1112, + IdPermission = 117 + }, + new + { + IdUserRole = 1113, + IdPermission = 105 + }, + new + { + IdUserRole = 1113, + IdPermission = 123 + }, + new + { + IdUserRole = 1113, + IdPermission = 120 + }, + new + { + IdUserRole = 1114, + IdPermission = 119 + }, + new + { + IdUserRole = 1114, + IdPermission = 118 + }, + new + { + IdUserRole = 1114, + IdPermission = 200 + }, + new + { + IdUserRole = 1115, + IdPermission = 223 + }, + new + { + IdUserRole = 1116, + IdPermission = 105 + }, + new + { + IdUserRole = 1116, + IdPermission = 102 + }, + new + { + IdUserRole = 1116, + IdPermission = 117 + }, + new + { + IdUserRole = 1116, + IdPermission = 126 + }, + new + { + IdUserRole = 1117, + IdPermission = 125 + }, + new + { + IdUserRole = 1117, + IdPermission = 124 + }, + new + { + IdUserRole = 1200, + IdPermission = 203 + }, + new + { + IdUserRole = 1200, + IdPermission = 230 + }, + new + { + IdUserRole = 1201, + IdPermission = 202 + }, + new + { + IdUserRole = 1201, + IdPermission = 203 + }, + new + { + IdUserRole = 1201, + IdPermission = 220 + }, + new + { + IdUserRole = 1202, + IdPermission = 203 + }, + new + { + IdUserRole = 1202, + IdPermission = 220 + }, + new + { + IdUserRole = 1202, + IdPermission = 236 + }, + new + { + IdUserRole = 1202, + IdPermission = 212 + }, + new + { + IdUserRole = 1203, + IdPermission = 235 + }, + new + { + IdUserRole = 1204, + IdPermission = 202 + }, + new + { + IdUserRole = 1204, + IdPermission = 203 + }, + new + { + IdUserRole = 1205, + IdPermission = 215 + }, + new + { + IdUserRole = 1206, + IdPermission = 203 + }, + new + { + IdUserRole = 1206, + IdPermission = 206 + }, + new + { + IdUserRole = 1207, + IdPermission = 205 + }, + new + { + IdUserRole = 1208, + IdPermission = 218 + }, + new + { + IdUserRole = 1209, + IdPermission = 217 + }, + new + { + IdUserRole = 1210, + IdPermission = 203 + }, + new + { + IdUserRole = 1210, + IdPermission = 230 + }, + new + { + IdUserRole = 1210, + IdPermission = 219 + }, + new + { + IdUserRole = 1211, + IdPermission = 203 + }, + new + { + IdUserRole = 1211, + IdPermission = 220 + }, + new + { + IdUserRole = 1211, + IdPermission = 239 + }, + new + { + IdUserRole = 1212, + IdPermission = 238 + }, + new + { + IdUserRole = 1212, + IdPermission = 237 + }, + new + { + IdUserRole = 1213, + IdPermission = 203 + }, + new + { + IdUserRole = 1213, + IdPermission = 239 + }, + new + { + IdUserRole = 1213, + IdPermission = 212 + }, + new + { + IdUserRole = 1214, + IdPermission = 211 + }, + new + { + IdUserRole = 1214, + IdPermission = 210 + }, + new + { + IdUserRole = 1215, + IdPermission = 203 + }, + new + { + IdUserRole = 1215, + IdPermission = 222 + }, + new + { + IdUserRole = 1216, + IdPermission = 221 + }, + new + { + IdUserRole = 1217, + IdPermission = 226 + }, + new + { + IdUserRole = 1218, + IdPermission = 225 + }, + new + { + IdUserRole = 1218, + IdPermission = 224 + }, + new + { + IdUserRole = 1219, + IdPermission = 203 + }, + new + { + IdUserRole = 1219, + IdPermission = 206 + }, + new + { + IdUserRole = 1219, + IdPermission = 230 + }, + new + { + IdUserRole = 1219, + IdPermission = 232 + }, + new + { + IdUserRole = 1220, + IdPermission = 203 + }, + new + { + IdUserRole = 1220, + IdPermission = 228 + }, + new + { + IdUserRole = 1221, + IdPermission = 202 + }, + new + { + IdUserRole = 1221, + IdPermission = 203 + }, + new + { + IdUserRole = 1221, + IdPermission = 220 + }, + new + { + IdUserRole = 1221, + IdPermission = 234 + }, + new + { + IdUserRole = 1501, + IdPermission = 214 + }, + new + { + IdUserRole = 1501, + IdPermission = 213 + }, + new + { + IdUserRole = 1502, + IdPermission = 207 + }, + new + { + IdUserRole = 1502, + IdPermission = 208 + }, + new + { + IdUserRole = 2000, + IdPermission = 205 + }, + new + { + IdUserRole = 2000, + IdPermission = 204 + }, + new + { + IdUserRole = 2000, + IdPermission = 245 + }, + new + { + IdUserRole = 2001, + IdPermission = 244 + }, + new + { + IdUserRole = 2001, + IdPermission = 245 + }, + new + { + IdUserRole = 2002, + IdPermission = 244 + }, + new + { + IdUserRole = 2002, + IdPermission = 246 + }, + new + { + IdUserRole = 2002, + IdPermission = 237 + }, + new + { + IdUserRole = 2002, + IdPermission = 238 + }, + new + { + IdUserRole = 2003, + IdPermission = 240 + }, + new + { + IdUserRole = 2003, + IdPermission = 217 + }, + new + { + IdUserRole = 2003, + IdPermission = 216 + }, + new + { + IdUserRole = 2004, + IdPermission = 242 + }, + new + { + IdUserRole = 2004, + IdPermission = 217 + }, + new + { + IdUserRole = 2004, + IdPermission = 216 + }, + new + { + IdUserRole = 2004, + IdPermission = 205 + }, + new + { + IdUserRole = 2004, + IdPermission = 204 + }, + new + { + IdUserRole = 2005, + IdPermission = 247 + }, + new + { + IdUserRole = 2005, + IdPermission = 205 + }, + new + { + IdUserRole = 2005, + IdPermission = 204 + }, + new + { + IdUserRole = 2006, + IdPermission = 243 + }, + new + { + IdUserRole = 2006, + IdPermission = 205 + }, + new + { + IdUserRole = 2006, + IdPermission = 204 + }, + new + { + IdUserRole = 2007, + IdPermission = 241 + }, + new + { + IdUserRole = 2007, + IdPermission = 205 + }, + new + { + IdUserRole = 2007, + IdPermission = 204 + }, + new + { + IdUserRole = 1, + IdPermission = 500 + }, + new + { + IdUserRole = 1, + IdPermission = 501 + }, + new + { + IdUserRole = 1, + IdPermission = 502 + }, + new + { + IdUserRole = 1, + IdPermission = 503 + }, + new + { + IdUserRole = 1, + IdPermission = 504 + }, + new + { + IdUserRole = 1, + IdPermission = 505 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserRoleUserRole", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id_user_role"); + + b.Property("IdInclude") + .HasColumnType("integer") + .HasColumnName("id_include_user_role"); + + b.HasKey("Id", "IdInclude") + .HasName("t_relation_user_role_user_role_pk"); + + b.HasIndex("IdInclude"); + + b.ToTable("t_relation_user_role_user_role"); + + b.HasComment("Отношение ролей к ролям"); + + b.HasData( + new + { + Id = 1101, + IdInclude = 1100 + }, + new + { + Id = 1103, + IdInclude = 1102 + }, + new + { + Id = 1105, + IdInclude = 1104 + }, + new + { + Id = 1107, + IdInclude = 1106 + }, + new + { + Id = 1109, + IdInclude = 1108 + }, + new + { + Id = 1111, + IdInclude = 1110 + }, + new + { + Id = 1114, + IdInclude = 1113 + }, + new + { + Id = 1117, + IdInclude = 1116 + }, + new + { + Id = 1203, + IdInclude = 1202 + }, + new + { + Id = 1207, + IdInclude = 1206 + }, + new + { + Id = 1209, + IdInclude = 1208 + }, + new + { + Id = 1212, + IdInclude = 1211 + }, + new + { + Id = 1214, + IdInclude = 1213 + }, + new + { + Id = 1216, + IdInclude = 1215 + }, + new + { + Id = 1218, + IdInclude = 1217 + }, + new + { + Id = 2000, + IdInclude = 1200 + }, + new + { + Id = 2000, + IdInclude = 1201 + }, + new + { + Id = 2000, + IdInclude = 1202 + }, + new + { + Id = 2000, + IdInclude = 1204 + }, + new + { + Id = 2000, + IdInclude = 1205 + }, + new + { + Id = 2000, + IdInclude = 1206 + }, + new + { + Id = 2000, + IdInclude = 1208 + }, + new + { + Id = 2000, + IdInclude = 1210 + }, + new + { + Id = 2000, + IdInclude = 1211 + }, + new + { + Id = 2000, + IdInclude = 1213 + }, + new + { + Id = 2000, + IdInclude = 1215 + }, + new + { + Id = 2000, + IdInclude = 1217 + }, + new + { + Id = 2000, + IdInclude = 1219 + }, + new + { + Id = 2000, + IdInclude = 1220 + }, + new + { + Id = 2000, + IdInclude = 1221 + }, + new + { + Id = 2000, + IdInclude = 1500 + }, + new + { + Id = 2000, + IdInclude = 1501 + }, + new + { + Id = 2000, + IdInclude = 1502 + }, + new + { + Id = 2001, + IdInclude = 1500 + }, + new + { + Id = 2001, + IdInclude = 1501 + }, + new + { + Id = 2001, + IdInclude = 1502 + }, + new + { + Id = 2002, + IdInclude = 1500 + }, + new + { + Id = 2002, + IdInclude = 1501 + }, + new + { + Id = 2002, + IdInclude = 1502 + }, + new + { + Id = 2003, + IdInclude = 1500 + }, + new + { + Id = 2003, + IdInclude = 1501 + }, + new + { + Id = 2003, + IdInclude = 1502 + }, + new + { + Id = 2004, + IdInclude = 1500 + }, + new + { + Id = 2004, + IdInclude = 1501 + }, + new + { + Id = 2004, + IdInclude = 1502 + }, + new + { + Id = 2005, + IdInclude = 1500 + }, + new + { + Id = 2005, + IdInclude = 1501 + }, + new + { + Id = 2005, + IdInclude = 1502 + }, + new + { + Id = 2006, + IdInclude = 1500 + }, + new + { + Id = 2006, + IdInclude = 1501 + }, + new + { + Id = 2006, + IdInclude = 1502 + }, + new + { + Id = 2007, + IdInclude = 1500 + }, + new + { + Id = 2007, + IdInclude = 1501 + }, + new + { + Id = 2007, + IdInclude = 1502 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserUserRole", b => + { + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property("IdUserRole") + .HasColumnType("integer") + .HasColumnName("id_user_role"); + + b.HasKey("IdUser", "IdUserRole"); + + b.HasIndex("IdUserRole"); + + b.ToTable("t_relation_user_user_role"); + + b.HasComment("Отношение пользователей и ролей"); + + b.HasData( + new + { + IdUser = 1, + IdUserRole = 1 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ReportProperty", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Begin") + .HasColumnType("timestamp with time zone") + .HasColumnName("begin"); + + b.Property("End") + .HasColumnType("timestamp with time zone") + .HasColumnName("end") + .HasComment("timestamp with time zone"); + + b.Property("Format") + .HasColumnType("integer") + .HasColumnName("format") + .HasComment("Формат отчета"); + + b.Property("IdFile") + .HasColumnType("integer") + .HasColumnName("id_file") + .HasComment("id файла-родителя"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property("Step") + .HasColumnType("integer") + .HasColumnName("step") + .HasComment("размер шага в секундах"); + + b.HasKey("Id"); + + b.HasIndex("IdFile"); + + b.HasIndex("IdWell"); + + b.ToTable("t_report_property"); + + b.HasComment("Отчеты с данными по буровым"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Schedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DrillEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("drill_end") + .HasComment("Конец вахты"); + + b.Property("DrillStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("drill_start") + .HasComment("Начало вахты"); + + b.Property("IdDriller") + .HasColumnType("integer") + .HasColumnName("id_driller") + .HasComment("Идентификатор бурильщика"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Идентификатор скважины"); + + b.Property("ShiftEnd") + .HasColumnType("time without time zone") + .HasColumnName("shift_end") + .HasComment("Конец смены"); + + b.Property("ShiftStart") + .HasColumnType("time without time zone") + .HasColumnName("shift_start") + .HasComment("Начало смены"); + + b.HasKey("Id"); + + b.HasIndex("IdDriller"); + + b.HasIndex("IdWell"); + + b.ToTable("t_schedule"); + + b.HasComment("График работы бурильщика"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.SetpointsRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("комментарий для оператора"); + + b.Property("IdAuthor") + .HasColumnType("integer") + .HasColumnName("id_author") + .HasComment("Id пользователя, загрузившего файл"); + + b.Property("IdState") + .HasColumnType("integer") + .HasColumnName("id_state") + .HasComment("0: неизвестно, 1:ожидает отправки, 2: отправлено, 3: принято оператором, 4: отклонено оператором, 5: устарело"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property("ObsolescenceSec") + .HasColumnType("integer") + .HasColumnName("obsolescence") + .HasComment("сек. до устаревания"); + + b.Property("Setpoints") + .HasColumnType("jsonb") + .HasColumnName("setpoint_set") + .HasComment("Набор уставок"); + + b.Property("UploadDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthor"); + + b.HasIndex("IdWell"); + + b.ToTable("t_setpoints_rquest"); + + b.HasComment("Запросы на изменение уставок панели оператора"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Subsystems.Subsystem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("description"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("t_subsystem"); + + b.HasComment("Описание подсистем"); + + b.HasData( + new + { + Id = 1, + Description = "Совместная работа режимов \"Бурение в роторе\" и \"Бурение в слайде\"", + Name = "АКБ" + }, + new + { + Id = 2, + Description = "Алгоритм поиска оптимальных параметров бурения САУБ", + Name = "MSE" + }, + new + { + Id = 65536, + Description = "Spin master", + Name = "Spin master" + }, + new + { + Id = 65537, + Description = "Torque master", + Name = "Torque master" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Subsystems.SubsystemOperationTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_end") + .HasComment("дата/время выключения подсистемы"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start") + .HasComment("дата/время включения подсистемы"); + + b.Property("DepthEnd") + .HasColumnType("real") + .HasColumnName("depth_end") + .HasComment("глубина забоя на момент выключения подсистемы"); + + b.Property("DepthStart") + .HasColumnType("real") + .HasColumnName("depth_start") + .HasComment("глубина забоя на момент включения подсистемы"); + + b.Property("IdSubsystem") + .HasColumnType("integer") + .HasColumnName("id_subsystem"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry") + .HasComment("ИД телеметрии по которой выдается информация"); + + b.HasKey("Id"); + + b.HasIndex("IdSubsystem"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_subsystem_operation_time"); + + b.HasComment("наработки подсистем"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Telemetry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Info") + .HasColumnType("jsonb") + .HasColumnName("info") + .HasComment("Информация с панели о скважине"); + + b.Property("RemoteUid") + .HasColumnType("text") + .HasColumnName("remote_uid") + .HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв."); + + b.Property("TimeZone") + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "RemoteUid" }, "t_telemetry_remote_uid_index"); + + b.ToTable("t_telemetry"); + + b.HasComment("таблица привязки телеметрии от комплектов к конкретной скважине."); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSaub", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date") + .HasComment("'2021-10-19 18:23:54+05'"); + + b.Property("AxialLoad") + .HasColumnType("real") + .HasColumnName("axial_load") + .HasComment("Осевая нагрузка"); + + b.Property("AxialLoadLimitMax") + .HasColumnType("real") + .HasColumnName("axial_load_limit_max") + .HasComment("Осевая нагрузка. Аварийная макс."); + + b.Property("AxialLoadSp") + .HasColumnType("real") + .HasColumnName("axial_load_sp") + .HasComment("Осевая нагрузка. Задание"); + + b.Property("BitDepth") + .HasColumnType("real") + .HasColumnName("bit_depth") + .HasComment("Положение инструмента"); + + b.Property("BlockPosition") + .HasColumnType("real") + .HasColumnName("block_position") + .HasComment("Высота талевого блока"); + + b.Property("BlockPositionMax") + .HasColumnType("real") + .HasColumnName("block_position_max") + .HasComment("Талевый блок. Макс положение"); + + b.Property("BlockPositionMin") + .HasColumnType("real") + .HasColumnName("block_position_min") + .HasComment("Талевый блок. Мин положение"); + + b.Property("BlockSpeed") + .HasColumnType("real") + .HasColumnName("block_speed") + .HasComment("Скорость талевого блока"); + + b.Property("BlockSpeedSp") + .HasColumnType("real") + .HasColumnName("block_speed_sp") + .HasComment("Скорости талевого блока. Задание"); + + b.Property("BlockSpeedSpDevelop") + .HasColumnType("real") + .HasColumnName("block_speed_sp_develop") + .HasComment("Талевый блок. Задание скорости для проработки"); + + b.Property("BlockSpeedSpRotor") + .HasColumnType("real") + .HasColumnName("block_speed_sp_rotor") + .HasComment("Талевый блок. Задание скорости для роторного бурения"); + + b.Property("BlockSpeedSpSlide") + .HasColumnType("real") + .HasColumnName("block_speed_sp_slide") + .HasComment("Талевый блок. Задание скорости для режима слайда"); + + b.Property("Flow") + .HasColumnType("real") + .HasColumnName("flow") + .HasComment("Расход"); + + b.Property("FlowDeltaLimitMax") + .HasColumnType("real") + .HasColumnName("flow_delta_limit_max") + .HasComment("Расход. Аварийный макс."); + + b.Property("FlowIdle") + .HasColumnType("real") + .HasColumnName("flow_idle") + .HasComment("Расход. Холостой ход"); + + b.Property("HookWeight") + .HasColumnType("real") + .HasColumnName("hook_weight") + .HasComment("Вес на крюке"); + + b.Property("HookWeightIdle") + .HasColumnType("real") + .HasColumnName("hook_weight_idle") + .HasComment("Вес на крюке. Холостой ход"); + + b.Property("HookWeightLimitMax") + .HasColumnType("real") + .HasColumnName("hook_weight_limit_max") + .HasComment("Вес на крюке. Затяжка"); + + b.Property("HookWeightLimitMin") + .HasColumnType("real") + .HasColumnName("hook_weight_limit_min") + .HasComment("Вес на крюке. Посадка"); + + b.Property("IdFeedRegulator") + .HasColumnType("smallint") + .HasColumnName("id_feed_regulator") + .HasComment("Текущий критерий бурения"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Пользователь САУБ"); + + b.Property("Mode") + .HasColumnType("smallint") + .HasColumnName("mode") + .HasComment("Режим САУБ"); + + b.Property("Mse") + .HasColumnType("real") + .HasColumnName("mse") + .HasComment("MSE"); + + b.Property("MseState") + .HasColumnType("smallint") + .HasColumnName("mse_state") + .HasComment("Текущее состояние работы MSE"); + + b.Property("Pressure") + .HasColumnType("real") + .HasColumnName("pressure") + .HasComment("Давление"); + + b.Property("PressureDeltaLimitMax") + .HasColumnType("real") + .HasColumnName("pressure_delta_limit_max") + .HasComment("Давление дифф. Аварийное макс."); + + b.Property("PressureIdle") + .HasColumnType("real") + .HasColumnName("pressure_idle") + .HasComment("Давление. Холостой ход"); + + b.Property("PressureSp") + .HasColumnType("real") + .HasColumnName("pressure_sp") + .HasComment("Давление. Задание"); + + b.Property("PressureSpDevelop") + .HasColumnType("real") + .HasColumnName("pressure_sp_develop") + .HasComment("Давление. Задание для проработки"); + + b.Property("PressureSpRotor") + .HasColumnType("real") + .HasColumnName("pressure_sp_rotor") + .HasComment("Давление. Задание для роторного бурения"); + + b.Property("PressureSpSlide") + .HasColumnType("real") + .HasColumnName("pressure_sp_slide") + .HasComment("Давление. Задание для режима слайда"); + + b.Property("RotorSpeed") + .HasColumnType("real") + .HasColumnName("rotor_speed") + .HasComment("Обороты ротора"); + + b.Property("RotorTorque") + .HasColumnType("real") + .HasColumnName("rotor_torque") + .HasComment("Момент на роторе"); + + b.Property("RotorTorqueIdle") + .HasColumnType("real") + .HasColumnName("rotor_torque_idle") + .HasComment("Момент на роторе. Холостой ход"); + + b.Property("RotorTorqueLimitMax") + .HasColumnType("real") + .HasColumnName("rotor_torque_limit_max") + .HasComment("Момент на роторе. Аварийный макс."); + + b.Property("RotorTorqueSp") + .HasColumnType("real") + .HasColumnName("rotor_torque_sp") + .HasComment("Момент на роторе. Задание"); + + b.Property("WellDepth") + .HasColumnType("real") + .HasColumnName("well_depth") + .HasComment("Глубина забоя"); + + b.HasKey("IdTelemetry", "DateTime"); + + b.ToTable("t_telemetry_data_saub"); + + b.HasComment("набор основных данных по SAUB"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSaubStat", b => + { + b.Property("Count") + .HasColumnType("bigint") + .HasColumnName("count_items"); + + b.Property("DateMax") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_max"); + + b.Property("DateMin") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_min"); + + b.Property("DepthMax") + .HasColumnType("real") + .HasColumnName("depth_max"); + + b.Property("DepthMin") + .HasColumnType("real") + .HasColumnName("depth_min"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.ToView("mw_telemetry_datas_saub_stat"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSpin", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date") + .HasComment("'2021-10-19 18:23:54+05'"); + + b.Property("Mode") + .HasColumnType("smallint") + .HasColumnName("mode") + .HasComment("Выбранный режим управления"); + + b.Property("PositionRight") + .HasColumnType("real") + .HasColumnName("position_right") + .HasComment("Крайний правый угол осцилляции"); + + b.Property("PositionZero") + .HasColumnType("real") + .HasColumnName("position_zero") + .HasComment("Нулевая позиция осцилляции"); + + b.Property("RevolsLeftLimit") + .HasColumnType("real") + .HasColumnName("revols_left_limit") + .HasComment("Ограничение числа оборотов влево"); + + b.Property("RevolsLeftTotal") + .HasColumnType("real") + .HasColumnName("revols_left_total") + .HasComment("Суммарное количество оборотов влево"); + + b.Property("RevolsRightLimit") + .HasColumnType("real") + .HasColumnName("revols_right_limit") + .HasComment("Ограничение числа оборотов вправо"); + + b.Property("RevolsRightTotal") + .HasColumnType("real") + .HasColumnName("revols_right_total") + .HasComment("Суммарное количество оборотов вправо"); + + b.Property("SpeedLeftSp") + .HasColumnType("real") + .HasColumnName("speed_left_sp") + .HasComment("Заданная скорость вращения влево"); + + b.Property("SpeedRightSp") + .HasColumnType("real") + .HasColumnName("speed_right_sp") + .HasComment("Заданная скорость вращения вправо"); + + b.Property("State") + .HasColumnType("smallint") + .HasColumnName("state") + .HasComment("Переменная этапа"); + + b.HasKey("IdTelemetry", "DateTime"); + + b.ToTable("t_telemetry_data_spin"); + + b.HasComment("набор основных данных по SpinMaster"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryEvent", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdEvent") + .HasColumnType("integer") + .HasColumnName("id_event"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category"); + + b.Property("MessageTemplate") + .HasColumnType("text") + .HasColumnName("message_template"); + + b.HasKey("IdTelemetry", "IdEvent"); + + b.ToTable("t_telemetry_event"); + + b.HasComment("Справочник событий. События формируют сообщения. Разделено по версиям посылок от телеметрии."); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Arg0") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg0") + .HasComment("Аргумент №0 для вставки в шаблон сообщения"); + + b.Property("Arg1") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg1"); + + b.Property("Arg2") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg2"); + + b.Property("Arg3") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg3"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("IdEvent") + .HasColumnType("integer") + .HasColumnName("id_event"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdTelemetryUser") + .HasColumnType("integer") + .HasColumnName("id_telemetry_user") + .HasComment("Пользователь панели отправляющей телеметрию. не пользователь облака."); + + b.Property("WellDepth") + .HasColumnType("double precision") + .HasColumnName("well_depth"); + + b.HasKey("Id"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_telemetry_message"); + + b.HasComment("Сообщения на буровых"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryUser", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("Patronymic") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("patronymic"); + + b.Property("Surname") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("surname"); + + b.HasKey("IdTelemetry", "IdUser"); + + b.ToTable("t_telemetry_user"); + + b.HasComment("Пользователи панели САУБ. Для сообщений."); + }); + + modelBuilder.Entity("AsbCloudDb.Model.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Email") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("email") + .HasComment("должность"); + + b.Property("IdCompany") + .HasColumnType("integer") + .HasColumnName("id_company"); + + b.Property("IdState") + .HasColumnType("smallint") + .HasColumnName("state") + .HasComment("состояние:\n100 - удален"); + + b.Property("Login") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("login"); + + b.Property("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name") + .HasComment("имя"); + + b.Property("PasswordHash") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("password_hash") + .HasComment("соленый хэш пароля.\nпервые 5 символов - соль"); + + b.Property("Patronymic") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("patronymic") + .HasComment("отчество"); + + b.Property("Phone") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("phone") + .HasComment("номер телефона"); + + b.Property("Position") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("position") + .HasComment("email"); + + b.Property("Surname") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("surname") + .HasComment("фамилия"); + + b.HasKey("Id"); + + b.HasIndex("IdCompany"); + + b.HasIndex("Login") + .IsUnique(); + + b.ToTable("t_user"); + + b.HasComment("Пользователи облака"); + + b.HasData( + new + { + Id = 1, + IdCompany = 1, + Login = "dev", + Name = "Разработчик", + PasswordHash = "Vlcj|4fa529103dde7ff72cfe76185f344d4aa87931f8e1b2044e8a7739947c3d18923464eaad93843e4f809c5e126d013072" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.UserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.Property("IdType") + .HasColumnType("integer") + .HasColumnName("id_type") + .HasComment("0-роль из стандартной матрицы, \n1-специальная роль для какого-либо пользователя"); + + b.HasKey("Id"); + + b.ToTable("t_user_role"); + + b.HasComment("Роли пользователей в системе"); + + b.HasData( + new + { + Id = 1, + Caption = "root", + IdType = 1 + }, + new + { + Id = 1100, + Caption = "admin_cluster.view", + IdType = 1 + }, + new + { + Id = 1101, + Caption = "admin_cluster.edit", + IdType = 1 + }, + new + { + Id = 1102, + Caption = "admin_company.view", + IdType = 1 + }, + new + { + Id = 1103, + Caption = "admin_company.edit", + IdType = 1 + }, + new + { + Id = 1104, + Caption = "admin_company_type.view", + IdType = 1 + }, + new + { + Id = 1105, + Caption = "admin_company_type.edit", + IdType = 1 + }, + new + { + Id = 1106, + Caption = "admin_deposit.view", + IdType = 1 + }, + new + { + Id = 1107, + Caption = "admin_deposit.edit", + IdType = 1 + }, + new + { + Id = 1108, + Caption = "admin_permission.view", + IdType = 1 + }, + new + { + Id = 1109, + Caption = "admin_permission.edit", + IdType = 1 + }, + new + { + Id = 1110, + Caption = "admin_role.view", + IdType = 1 + }, + new + { + Id = 1111, + Caption = "admin_role.edit", + IdType = 1 + }, + new + { + Id = 1112, + Caption = "admin_telemetry.view", + IdType = 1 + }, + new + { + Id = 1113, + Caption = "admin_user.view", + IdType = 1 + }, + new + { + Id = 1114, + Caption = "admin_user.edit", + IdType = 1 + }, + new + { + Id = 1115, + Caption = "admin_visit_log.view", + IdType = 1 + }, + new + { + Id = 1116, + Caption = "admin_well.view", + IdType = 1 + }, + new + { + Id = 1117, + Caption = "admin_well.edit", + IdType = 1 + }, + new + { + Id = 1200, + Caption = "archive.view", + IdType = 1 + }, + new + { + Id = 1201, + Caption = "cluster.view", + IdType = 1 + }, + new + { + Id = 1202, + Caption = "composite.view", + IdType = 1 + }, + new + { + Id = 1203, + Caption = "composite.edit", + IdType = 1 + }, + new + { + Id = 1204, + Caption = "deposit.view", + IdType = 1 + }, + new + { + Id = 1205, + Caption = "document.view", + IdType = 1 + }, + new + { + Id = 1206, + Caption = "drillProcessFlow.view", + IdType = 1 + }, + new + { + Id = 1207, + Caption = "drillProcessFlow.edit", + IdType = 1 + }, + new + { + Id = 1208, + Caption = "measure.view", + IdType = 1 + }, + new + { + Id = 1209, + Caption = "measure.edit", + IdType = 1 + }, + new + { + Id = 1210, + Caption = "message.view", + IdType = 1 + }, + new + { + Id = 1211, + Caption = "operations.view", + IdType = 1 + }, + new + { + Id = 1212, + Caption = "operations.edit", + IdType = 1 + }, + new + { + Id = 1213, + Caption = "params.view", + IdType = 1 + }, + new + { + Id = 1214, + Caption = "params.edit", + IdType = 1 + }, + new + { + Id = 1215, + Caption = "report.view", + IdType = 1 + }, + new + { + Id = 1216, + Caption = "report.edit", + IdType = 1 + }, + new + { + Id = 1217, + Caption = "setpoints.view", + IdType = 1 + }, + new + { + Id = 1218, + Caption = "setpoints.edit", + IdType = 1 + }, + new + { + Id = 1219, + Caption = "telemetry.view", + IdType = 1 + }, + new + { + Id = 1220, + Caption = "telemetryAnalysis.view", + IdType = 1 + }, + new + { + Id = 1221, + Caption = "well.view", + IdType = 1 + }, + new + { + Id = 1500, + Caption = "Просмотр всего", + IdType = 1 + }, + new + { + Id = 1501, + Caption = "file.edit", + IdType = 1 + }, + new + { + Id = 1502, + Caption = "drillingProgram.edit", + IdType = 1 + }, + new + { + Id = 2000, + Caption = "Заказчик", + IdType = 0 + }, + new + { + Id = 2001, + Caption = "Супервайзер", + IdType = 0 + }, + new + { + Id = 2002, + Caption = "Буровой подрядчик", + IdType = 0 + }, + new + { + Id = 2003, + Caption = "Растворщик", + IdType = 0 + }, + new + { + Id = 2004, + Caption = "Телеметрист", + IdType = 0 + }, + new + { + Id = 2005, + Caption = "Долотный сервис", + IdType = 0 + }, + new + { + Id = 2006, + Caption = "ГТИ", + IdType = 0 + }, + new + { + Id = 2007, + Caption = "Цементирование", + IdType = 0 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.UserSetting", b => + { + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property("Key") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("key") + .HasComment("Ключ настроек пользователя"); + + b.Property("Value") + .HasColumnType("jsonb") + .HasColumnName("setting_value") + .HasComment("Значение настроек пользователя"); + + b.HasKey("IdUser", "Key"); + + b.ToTable("t_user_settings"); + + b.HasComment("настройки интерфейса пользователя"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Well", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property("IdCluster") + .HasColumnType("integer") + .HasColumnName("id_cluster"); + + b.Property("IdState") + .HasColumnType("integer") + .HasColumnName("state") + .HasComment("0 - неизвестно, 1 - в работе, 2 - завершена"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdWellType") + .HasColumnType("integer") + .HasColumnName("id_well_type"); + + b.Property("Latitude") + .HasColumnType("double precision") + .HasColumnName("latitude"); + + b.Property("Longitude") + .HasColumnType("double precision") + .HasColumnName("longitude"); + + b.Property("Timezone") + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.HasIndex("IdCluster"); + + b.HasIndex("IdTelemetry") + .IsUnique(); + + b.HasIndex("IdWellType"); + + b.ToTable("t_well"); + + b.HasComment("скважины"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellComposite", b => + { + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины получателя"); + + b.Property("IdWellSrc") + .HasColumnType("integer") + .HasColumnName("id_well_src") + .HasComment("Id скважины композита"); + + b.Property("IdWellSectionType") + .HasColumnType("integer") + .HasColumnName("id_well_section_type") + .HasComment("Id тип секции композита"); + + b.HasKey("IdWell", "IdWellSrc", "IdWellSectionType"); + + b.HasIndex("IdWellSectionType"); + + b.HasIndex("IdWellSrc"); + + b.ToTable("t_well_composite"); + + b.HasComment("Композитная скважина"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellFinalDocument", b => + { + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category"); + + b.HasKey("IdWell", "IdUser", "IdCategory") + .HasName("t_well_final_documents_pk"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdUser"); + + b.ToTable("t_well_final_documents"); + + b.HasComment("Дело скважины"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellOperation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryInfo") + .HasColumnType("text") + .HasColumnName("category_info") + .HasComment("Доп. информация к выбраной категории"); + + b.Property("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("Комментарий"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start") + .HasComment("Дата начала операции"); + + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина после завершения операции, м"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина на начало операции, м"); + + b.Property("DurationHours") + .HasColumnType("double precision") + .HasColumnName("duration_hours") + .HasComment("Продолжительность, часы"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Id категории операции"); + + b.Property("IdType") + .HasColumnType("integer") + .HasColumnName("id_type") + .HasComment("0 = План или 1 = Факт"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины"); + + b.Property("IdWellSectionType") + .HasColumnType("integer") + .HasColumnName("id_well_section_type") + .HasComment("Id тип секции скважины"); + + b.HasKey("Id"); + + b.HasIndex("DateStart"); + + b.HasIndex("DepthEnd"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdWell"); + + b.HasIndex("IdWellSectionType"); + + b.ToTable("t_well_operation"); + + b.HasComment("Данные по операциям на скважине"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellOperationCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Code") + .HasColumnType("integer") + .HasColumnName("code") + .HasComment("Код операции"); + + b.Property("KeyValueName") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("key_value_name") + .HasComment("Название ключевого показателя операции"); + + b.Property("KeyValueUnits") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("key_value_units") + .HasComment("Единицы измерения ключевого показателя операции"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название категории операции"); + + b.HasKey("Id"); + + b.ToTable("t_well_operation_category"); + + b.HasComment("Справочник операций на скважине"); + + b.HasData( + new + { + Id = 1, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Невозможно определить операцию" + }, + new + { + Id = 2, + Code = 0, + KeyValueName = "МСП", + KeyValueUnits = "м/ч", + Name = "Роторное бурение" + }, + new + { + Id = 3, + Code = 0, + KeyValueName = "МСП", + KeyValueUnits = "м/ч", + Name = "Слайдирование" + }, + new + { + Id = 4, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем с проработкой" + }, + new + { + Id = 5, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск с проработкой" + }, + new + { + Id = 6, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем с промывкой" + }, + new + { + Id = 7, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск с промывкой" + }, + new + { + Id = 8, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск в скважину" + }, + new + { + Id = 9, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск с вращением" + }, + new + { + Id = 10, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем из скважины" + }, + new + { + Id = 11, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем с вращением" + }, + new + { + Id = 12, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка в покое" + }, + new + { + Id = 13, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка с вращением" + }, + new + { + Id = 14, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Удержание в клиньях" + }, + new + { + Id = 15, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Неподвижное состояние" + }, + new + { + Id = 16, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Вращение без циркуляции" + }, + new + { + Id = 17, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "На поверхности" + }, + new + { + Id = 18, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Проработка перед наращиванием" + }, + new + { + Id = 19, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Шаблонировка перед наращиванием" + }, + new + { + Id = 20, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка перед наращиванием" + }, + new + { + Id = 21, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Статический замер телесистемы" + }, + new + { + Id = 22, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка" + }, + new + { + Id = 23, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Шаблонировка при бурении" + }, + new + { + Id = 1001, + Code = 0, + KeyValueName = "МСП", + KeyValueUnits = "м/ч", + Name = "Бурение" + }, + new + { + Id = 1002, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ГИС" + }, + new + { + Id = 1003, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ГФР" + }, + new + { + Id = 1004, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Монтаж ПВО" + }, + new + { + Id = 1005, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Демонтаж ПВО" + }, + new + { + Id = 1006, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Установка ФА" + }, + new + { + Id = 1007, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Оборудование устья" + }, + new + { + Id = 1008, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ОЗЦ" + }, + new + { + Id = 1011, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Начало цикла строительства скважины" + }, + new + { + Id = 1012, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Окончание цикла строительства скважины" + }, + new + { + Id = 1013, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Опрессовка ПВО" + }, + new + { + Id = 1014, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Опрессовка Ц.К." + }, + new + { + Id = 1015, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Опрессовка ВЗД" + }, + new + { + Id = 1016, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Перевод скв на другой тип промывочной жидкости" + }, + new + { + Id = 1017, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Перезапись каротажа" + }, + new + { + Id = 1018, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Перетяжка талевого каната" + }, + new + { + Id = 1019, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Наращивание, промывка" + }, + new + { + Id = 1020, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем инструмента" + }, + new + { + Id = 1021, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем инструмента с промывкой" + }, + new + { + Id = 1022, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Обратная проработка" + }, + new + { + Id = 1023, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сборка инструмента с мостков" + }, + new + { + Id = 1024, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подготовительные работы" + }, + new + { + Id = 1025, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сборка КНБК" + }, + new + { + Id = 1026, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Разборка КНБК" + }, + new + { + Id = 1027, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка" + }, + new + { + Id = 1028, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промежуточная промывка" + }, + new + { + Id = 1029, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Прокачка пачек" + }, + new + { + Id = 1030, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Разбуривание тех.оснастки" + }, + new + { + Id = 1031, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Ремонт" + }, + new + { + Id = 1032, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск инструмента" + }, + new + { + Id = 1033, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск инструмента с промывкой" + }, + new + { + Id = 1034, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Прямая проработка" + }, + new + { + Id = 1035, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Принудительная проработка" + }, + new + { + Id = 1037, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Тех СПО-подъем" + }, + new + { + Id = 1038, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Тех СПО-спуск" + }, + new + { + Id = 1039, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Техническое обслуживание" + }, + new + { + Id = 1040, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Цементаж" + }, + new + { + Id = 1041, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Шаблонировка ствола" + }, + new + { + Id = 1042, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Геологическое осложнение" + }, + new + { + Id = 1043, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "НПВ" + }, + new + { + Id = 1044, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ВМР" + }, + new + { + Id = 1045, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Прочее" + }, + new + { + Id = 1046, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск КНБК" + }, + new + { + Id = 1047, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем КНБК" + }, + new + { + Id = 1048, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск ОК" + }, + new + { + Id = 1050, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка при спуске ОК" + }, + new + { + Id = 1051, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Замер ТС" + }, + new + { + Id = 1052, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Тех. отстой" + }, + new + { + Id = 1053, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Циркуляция и Обработка БР" + }, + new + { + Id = 1054, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Срезка ствола" + }, + new + { + Id = 1055, + Code = 0, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Вспомогательные работы" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellSectionType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.HasKey("Id"); + + b.ToTable("t_well_section_type"); + + b.HasComment("конструкция секции скважины"); + + b.HasData( + new + { + Id = 1, + Caption = "Пилотный ствол" + }, + new + { + Id = 2, + Caption = "Направление" + }, + new + { + Id = 3, + Caption = "Кондуктор" + }, + new + { + Id = 4, + Caption = "Эксплуатационная колонна" + }, + new + { + Id = 5, + Caption = "Транспортный ствол" + }, + new + { + Id = 6, + Caption = "Хвостовик" + }, + new + { + Id = 7, + Caption = "Пилотный ствол 2" + }, + new + { + Id = 8, + Caption = "Направление 2" + }, + new + { + Id = 9, + Caption = "Кондуктор 2" + }, + new + { + Id = 10, + Caption = "Эксплуатационная колонна 2" + }, + new + { + Id = 11, + Caption = "Транспортный ствол 2" + }, + new + { + Id = 12, + Caption = "Хвостовик 2" + }, + new + { + Id = 13, + Caption = "Пилотный ствол 3" + }, + new + { + Id = 14, + Caption = "Направление 3" + }, + new + { + Id = 15, + Caption = "Кондуктор 3" + }, + new + { + Id = 16, + Caption = "Эксплуатационная колонна 3" + }, + new + { + Id = 17, + Caption = "Транспортный ствол 3" + }, + new + { + Id = 18, + Caption = "Хвостовик 3" + }, + new + { + Id = 19, + Caption = "Пилотный ствол 4" + }, + new + { + Id = 20, + Caption = "Направление 4" + }, + new + { + Id = 21, + Caption = "Кондуктор 4" + }, + new + { + Id = 22, + Caption = "Эксплуатационная колонна 4" + }, + new + { + Id = 23, + Caption = "Транспортный ствол 4" + }, + new + { + Id = 24, + Caption = "Хвостовик 4" + }, + new + { + Id = 25, + Caption = "Пилотный ствол 5" + }, + new + { + Id = 26, + Caption = "Направление 5" + }, + new + { + Id = 27, + Caption = "Кондуктор 5" + }, + new + { + Id = 28, + Caption = "Эксплуатационная колонна 5" + }, + new + { + Id = 29, + Caption = "Транспортный ствол 5" + }, + new + { + Id = 30, + Caption = "Хвостовик 5" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.HasKey("Id"); + + b.ToTable("t_well_type"); + + b.HasComment("конструкция скважины"); + + b.HasData( + new + { + Id = 1, + Caption = "Наклонно-направленная" + }, + new + { + Id = 2, + Caption = "Горизонтальная" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.RecordBase", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Actcod") + .HasColumnType("smallint") + .HasColumnName("ACTCOD"); + + b.Property("Date") + .HasColumnType("integer") + .HasColumnName("DATE"); + + b.Property("Recid") + .HasColumnType("smallint") + .HasColumnName("RECID"); + + b.Property("Seqid") + .HasColumnType("integer") + .HasColumnName("SEQID"); + + b.Property("Stknum") + .HasColumnType("smallint") + .HasColumnName("STKNUM"); + + b.Property("Time") + .HasColumnType("integer") + .HasColumnName("TIME"); + + b.Property("Wellid") + .HasColumnType("text") + .HasColumnName("WELLID"); + + b.HasKey("IdTelemetry", "DateTime"); + + b.ToTable("t_telemetry_wits_base"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record1", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Blkpos") + .HasColumnType("real") + .HasColumnName("BLKPOS"); + + b.Property("Chkp") + .HasColumnType("real") + .HasColumnName("CHKP"); + + b.Property("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property("Deptbitv") + .HasColumnType("real") + .HasColumnName("DEPTBITV"); + + b.Property("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property("Deptretm") + .HasColumnType("real") + .HasColumnName("DEPTRETM"); + + b.Property("Deptvert") + .HasColumnType("real") + .HasColumnName("DEPTVERT"); + + b.Property("Gasa") + .HasColumnType("real") + .HasColumnName("GASA"); + + b.Property("Hkla") + .HasColumnType("real") + .HasColumnName("HKLA"); + + b.Property("Hklx") + .HasColumnType("real") + .HasColumnName("HKLX"); + + b.Property("Lagstks") + .HasColumnType("smallint") + .HasColumnName("LAGSTKS"); + + b.Property("Mcia") + .HasColumnType("real") + .HasColumnName("MCIA"); + + b.Property("Mcoa") + .HasColumnType("real") + .HasColumnName("MCOA"); + + b.Property("Mdia") + .HasColumnType("real") + .HasColumnName("MDIA"); + + b.Property("Mdoa") + .HasColumnType("real") + .HasColumnName("MDOA"); + + b.Property("Mfia") + .HasColumnType("real") + .HasColumnName("MFIA"); + + b.Property("Mfoa") + .HasColumnType("real") + .HasColumnName("MFOA"); + + b.Property("Mfop") + .HasColumnType("smallint") + .HasColumnName("MFOP"); + + b.Property("Mtia") + .HasColumnType("real") + .HasColumnName("MTIA"); + + b.Property("Mtoa") + .HasColumnType("real") + .HasColumnName("MTOA"); + + b.Property("Ropa") + .HasColumnType("real") + .HasColumnName("ROPA"); + + b.Property("Rpma") + .HasColumnType("smallint") + .HasColumnName("RPMA"); + + b.Property("Spare1") + .HasColumnType("real") + .HasColumnName("SPARE1"); + + b.Property("Spare2") + .HasColumnType("real") + .HasColumnName("SPARE2"); + + b.Property("Spare3") + .HasColumnType("real") + .HasColumnName("SPARE3"); + + b.Property("Spare4") + .HasColumnType("real") + .HasColumnName("SPARE4"); + + b.Property("Spare5") + .HasColumnType("real") + .HasColumnName("SPARE5"); + + b.Property("Spm1") + .HasColumnType("smallint") + .HasColumnName("SPM1"); + + b.Property("Spm2") + .HasColumnType("smallint") + .HasColumnName("SPM2"); + + b.Property("Spm3") + .HasColumnType("smallint") + .HasColumnName("SPM3"); + + b.Property("Sppa") + .HasColumnType("real") + .HasColumnName("SPPA"); + + b.Property("Stkc") + .HasColumnType("integer") + .HasColumnName("STKC"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.Property("Torqa") + .HasColumnType("real") + .HasColumnName("TORQA"); + + b.Property("Torqx") + .HasColumnType("real") + .HasColumnName("TORQX"); + + b.Property("Tvolact") + .HasColumnType("real") + .HasColumnName("TVOLACT"); + + b.Property("Tvolcact") + .HasColumnType("real") + .HasColumnName("TVOLCACT"); + + b.Property("Woba") + .HasColumnType("real") + .HasColumnName("WOBA"); + + b.Property("Wobx") + .HasColumnType("real") + .HasColumnName("WOBX"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_1"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record50", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property("DeptmeasGdpMc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_GDP_mc"); + + b.Property("DeptmeasMcrstat") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_MCRSTAT"); + + b.Property("DeptmeasRa33Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RA33_mc"); + + b.Property("DeptmeasRa33f2Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RA33F2_mc"); + + b.Property("DeptmeasRa33f4Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RA33F4_mc"); + + b.Property("DeptmeasRp33Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RP33_mc"); + + b.Property("DeptmeasRp33f2Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RP33F2_mc"); + + b.Property("DeptmeasRp33f4Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RP33F4_mc"); + + b.Property("DeptmeasSlvlMc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_SLVL_mc"); + + b.Property("GdpMc") + .HasColumnType("real") + .HasColumnName("GDP_mc"); + + b.Property("Mcrstat") + .HasColumnType("real") + .HasColumnName("MCRSTAT"); + + b.Property("Ra33Mc") + .HasColumnType("real") + .HasColumnName("RA33_mc"); + + b.Property("Ra33f2Mc") + .HasColumnType("real") + .HasColumnName("RA33F2_mc"); + + b.Property("Ra33f4Mc") + .HasColumnType("real") + .HasColumnName("RA33F4_mc"); + + b.Property("Rp33Mc") + .HasColumnType("real") + .HasColumnName("RP33_mc"); + + b.Property("Rp33f2Mc") + .HasColumnType("real") + .HasColumnName("RP33F2_mc"); + + b.Property("Rp33f4Mc") + .HasColumnType("real") + .HasColumnName("RP33F4_mc"); + + b.Property("SlvlMc") + .HasColumnType("real") + .HasColumnName("SLVL_mc"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_50"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record60", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Btot") + .HasColumnType("real") + .HasColumnName("Btot"); + + b.Property("Bx") + .HasColumnType("real") + .HasColumnName("Bx"); + + b.Property("By") + .HasColumnType("real") + .HasColumnName("By"); + + b.Property("Bz") + .HasColumnType("real") + .HasColumnName("Bz"); + + b.Property("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property("Gtot") + .HasColumnType("real") + .HasColumnName("Gtot"); + + b.Property("Gx") + .HasColumnType("real") + .HasColumnName("Gx"); + + b.Property("Gy") + .HasColumnType("real") + .HasColumnName("Gy"); + + b.Property("Gz") + .HasColumnType("real") + .HasColumnName("Gz"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_60"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record61", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Att06h") + .HasColumnType("real") + .HasColumnName("ATT06H"); + + b.Property("Att06l") + .HasColumnType("real") + .HasColumnName("ATT06L"); + + b.Property("Att10h") + .HasColumnType("real") + .HasColumnName("ATT10H"); + + b.Property("Att10l") + .HasColumnType("real") + .HasColumnName("ATT10L"); + + b.Property("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property("Phl1f1") + .HasColumnType("real") + .HasColumnName("PHL1F1"); + + b.Property("Phl1f2") + .HasColumnType("real") + .HasColumnName("PHL1F2"); + + b.Property("Phl2f1") + .HasColumnType("real") + .HasColumnName("PHL2F1"); + + b.Property("Phl2f2") + .HasColumnType("real") + .HasColumnName("PHL2F2"); + + b.Property("Status") + .HasColumnType("real") + .HasColumnName("Status"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_61"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record7", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property("Deptsvym") + .HasColumnType("real") + .HasColumnName("DEPTSVYM"); + + b.Property("Deptsvyv") + .HasColumnType("real") + .HasColumnName("DEPTSVYV"); + + b.Property("Passnum") + .HasColumnType("smallint") + .HasColumnName("PASSNUM"); + + b.Property("Spare1") + .HasColumnType("real") + .HasColumnName("SPARE1"); + + b.Property("Spare2") + .HasColumnType("real") + .HasColumnName("SPARE2"); + + b.Property("Spare3") + .HasColumnType("real") + .HasColumnName("SPARE3"); + + b.Property("Spare4") + .HasColumnType("real") + .HasColumnName("SPARE4"); + + b.Property("Spare5") + .HasColumnType("real") + .HasColumnName("SPARE5"); + + b.Property("Svyazc") + .HasColumnType("real") + .HasColumnName("SVYAZC"); + + b.Property("Svyazu") + .HasColumnType("real") + .HasColumnName("SVYAZU"); + + b.Property("Svydls") + .HasColumnType("real") + .HasColumnName("SVYDLS"); + + b.Property("Svyew") + .HasColumnType("real") + .HasColumnName("SVYEW"); + + b.Property("Svygtf") + .HasColumnType("real") + .HasColumnName("SVYGTF"); + + b.Property("Svyinc") + .HasColumnType("real") + .HasColumnName("SVYINC"); + + b.Property("Svymtf") + .HasColumnType("real") + .HasColumnName("SVYMTF"); + + b.Property("Svyns") + .HasColumnType("real") + .HasColumnName("SVYNS"); + + b.Property("Svytype") + .HasColumnType("text") + .HasColumnName("SVYTYPE"); + + b.Property("Svywalk") + .HasColumnType("real") + .HasColumnName("SVYWALK"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_7"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record8", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property("Deptbitv") + .HasColumnType("real") + .HasColumnName("DEPTBITV"); + + b.Property("Deptcalm") + .HasColumnType("real") + .HasColumnName("DEPTCALM"); + + b.Property("Deptcalv") + .HasColumnType("real") + .HasColumnName("DEPTCALV"); + + b.Property("Deptfdm") + .HasColumnType("real") + .HasColumnName("DEPTFDM"); + + b.Property("Deptfdv") + .HasColumnType("real") + .HasColumnName("DEPTFDV"); + + b.Property("Deptgr1m") + .HasColumnType("real") + .HasColumnName("DEPTGR1M"); + + b.Property("Deptgr1v") + .HasColumnType("real") + .HasColumnName("DEPTGR1V"); + + b.Property("Deptgr2m") + .HasColumnType("real") + .HasColumnName("DEPTGR2M"); + + b.Property("Deptgr2v") + .HasColumnType("real") + .HasColumnName("DEPTGR2V"); + + b.Property("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property("Deptp1m") + .HasColumnType("real") + .HasColumnName("DEPTP1M"); + + b.Property("Deptp1v") + .HasColumnType("real") + .HasColumnName("DEPTP1V"); + + b.Property("Deptp2m") + .HasColumnType("real") + .HasColumnName("DEPTP2M"); + + b.Property("Deptp2v") + .HasColumnType("real") + .HasColumnName("DEPTP2V"); + + b.Property("Deptrs1m") + .HasColumnType("real") + .HasColumnName("DEPTRS1M"); + + b.Property("Deptrs1v") + .HasColumnType("real") + .HasColumnName("DEPTRS1V"); + + b.Property("Deptrs2m") + .HasColumnType("real") + .HasColumnName("DEPTRS2M"); + + b.Property("Deptrs2v") + .HasColumnType("real") + .HasColumnName("DEPTRS2V"); + + b.Property("Deptvert") + .HasColumnType("real") + .HasColumnName("DEPTVERT"); + + b.Property("Mclp") + .HasColumnType("real") + .HasColumnName("MCLP"); + + b.Property("Mfd") + .HasColumnType("real") + .HasColumnName("MFD"); + + b.Property("Mffp") + .HasColumnType("real") + .HasColumnName("MFFP"); + + b.Property("Mfpp") + .HasColumnType("real") + .HasColumnName("MFPP"); + + b.Property("Mfrann") + .HasColumnType("real") + .HasColumnName("MFRANN"); + + b.Property("Mfrpipe") + .HasColumnType("real") + .HasColumnName("MFRPIPE"); + + b.Property("Mftann") + .HasColumnType("real") + .HasColumnName("MFTANN"); + + b.Property("Mftpipe") + .HasColumnType("real") + .HasColumnName("MFTPIPE"); + + b.Property("Mg1") + .HasColumnType("real") + .HasColumnName("MG1"); + + b.Property("Mg1c") + .HasColumnType("real") + .HasColumnName("MG1C"); + + b.Property("Mg2") + .HasColumnType("real") + .HasColumnName("MG2"); + + b.Property("Mg2c") + .HasColumnType("real") + .HasColumnName("MG2C"); + + b.Property("Mpo1") + .HasColumnType("real") + .HasColumnName("MPO1"); + + b.Property("Mpo2") + .HasColumnType("real") + .HasColumnName("MPO2"); + + b.Property("Mr1") + .HasColumnType("real") + .HasColumnName("MR1"); + + b.Property("Mr1c") + .HasColumnType("real") + .HasColumnName("MR1C"); + + b.Property("Mr2") + .HasColumnType("real") + .HasColumnName("MR2"); + + b.Property("Mr2c") + .HasColumnType("real") + .HasColumnName("MR2C"); + + b.Property("Passnum") + .HasColumnType("smallint") + .HasColumnName("PASSNUM"); + + b.Property("Spare1") + .HasColumnType("real") + .HasColumnName("SPARE1"); + + b.Property("Spare2") + .HasColumnType("real") + .HasColumnName("SPARE2"); + + b.Property("Spare3") + .HasColumnType("real") + .HasColumnName("SPARE3"); + + b.Property("Spare4") + .HasColumnType("real") + .HasColumnName("SPARE4"); + + b.Property("Spare5") + .HasColumnType("real") + .HasColumnName("SPARE5"); + + b.Property("Spare6") + .HasColumnType("real") + .HasColumnName("SPARE6"); + + b.Property("Spare7") + .HasColumnType("real") + .HasColumnName("SPARE7"); + + b.Property("Spare8") + .HasColumnType("real") + .HasColumnName("SPARE8"); + + b.Property("Spare9") + .HasColumnType("real") + .HasColumnName("SPARE9"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_8"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Cluster", b => + { + b.HasOne("AsbCloudDb.Model.Deposit", "Deposit") + .WithMany("Clusters") + .HasForeignKey("IdDeposit") + .HasConstraintName("t_cluster_t_deposit_id_fk"); + + b.Navigation("Deposit"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Company", b => + { + b.HasOne("AsbCloudDb.Model.CompanyType", "CompanyType") + .WithMany("Companies") + .HasForeignKey("IdCompanyType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CompanyType"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DailyReport.DailyReport", b => + { + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DetectedOperation", b => + { + b.HasOne("AsbCloudDb.Model.WellOperationCategory", "OperationCategory") + .WithMany() + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OperationCategory"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillFlowChart", b => + { + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b => + { + b.HasOne("AsbCloudDb.Model.FileCategory", "FileCategory") + .WithMany() + .HasForeignKey("IdFileCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany("DrillingProgramParts") + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FileCategory"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillParams", b => + { + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.WellSectionType", "WellSectionType") + .WithMany("DrillParamsCollection") + .HasForeignKey("IdWellSectionType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_drill_params_t_well_section_type_id_fk"); + + b.Navigation("Well"); + + b.Navigation("WellSectionType"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileInfo", b => + { + b.HasOne("AsbCloudDb.Model.User", "Author") + .WithMany("Files") + .HasForeignKey("IdAuthor"); + + b.HasOne("AsbCloudDb.Model.FileCategory", "FileCategory") + .WithMany() + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("FileCategory"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileMark", b => + { + b.HasOne("AsbCloudDb.Model.FileInfo", "FileInfo") + .WithMany("FileMarks") + .HasForeignKey("IdFile") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_file_mark_t_file_info_fk"); + + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany("FileMarks") + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_user_t_file_mark_fk"); + + b.Navigation("FileInfo"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Measure", b => + { + b.HasOne("AsbCloudDb.Model.MeasureCategory", "Category") + .WithMany("Measures") + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.OperationValue", b => + { + b.HasOne("AsbCloudDb.Model.WellOperationCategory", "OperationCategory") + .WithMany() + .HasForeignKey("IdOperationCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OperationCategory"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationCompanyWell", b => + { + b.HasOne("AsbCloudDb.Model.Company", "Company") + .WithMany("RelationCompaniesWells") + .HasForeignKey("IdCompany") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_relation_company_well_t_company_id_fk"); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany("RelationCompaniesWells") + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_relation_company_well_t_well_id_fk"); + + b.Navigation("Company"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserDrillingProgramPart", b => + { + b.HasOne("AsbCloudDb.Model.DrillingProgramPart", "DrillingProgramPart") + .WithMany("RelatedUsers") + .HasForeignKey("IdDrillingProgramPart") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DrillingProgramPart"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserRolePermission", b => + { + b.HasOne("AsbCloudDb.Model.Permission", "Permission") + .WithMany("RelationUserRolePermissions") + .HasForeignKey("IdPermission") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.UserRole", "UserRole") + .WithMany("RelationUserRolePermissions") + .HasForeignKey("IdUserRole") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("UserRole"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserRoleUserRole", b => + { + b.HasOne("AsbCloudDb.Model.UserRole", "Role") + .WithMany("RelationUserRoleUserRoles") + .HasForeignKey("Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.UserRole", "IncludeRole") + .WithMany() + .HasForeignKey("IdInclude") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("IncludeRole"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserUserRole", b => + { + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany("RelationUsersUserRoles") + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.UserRole", "UserRole") + .WithMany("RelationUsersUserRoles") + .HasForeignKey("IdUserRole") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("UserRole"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ReportProperty", b => + { + b.HasOne("AsbCloudDb.Model.FileInfo", "File") + .WithMany() + .HasForeignKey("IdFile") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("File"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Schedule", b => + { + b.HasOne("AsbCloudDb.Model.Driller", "Driller") + .WithMany("Schedule") + .HasForeignKey("IdDriller") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_schedule_t_driller_id_driller"); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Driller"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.SetpointsRequest", b => + { + b.HasOne("AsbCloudDb.Model.User", "Author") + .WithMany() + .HasForeignKey("IdAuthor") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Subsystems.SubsystemOperationTime", b => + { + b.HasOne("AsbCloudDb.Model.Subsystems.Subsystem", "Subsystem") + .WithMany() + .HasForeignKey("IdSubsystem") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Subsystem"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSaub", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany("DataSaub") + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_telemetry_data_saub_t_telemetry_id_fk"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSpin", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany("DataSpin") + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_telemetry_data_spin_t_telemetry_id_fk"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryEvent", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany("Events") + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_event_t_telemetry_id_fk"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryMessage", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany("Messages") + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_messages_t_telemetry_id_fk"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryUser", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany("Users") + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_telemetry_user_t_telemetry_id_fk"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.User", b => + { + b.HasOne("AsbCloudDb.Model.Company", "Company") + .WithMany("Users") + .HasForeignKey("IdCompany") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("t_user_t_company_id_fk"); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.UserSetting", b => + { + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Well", b => + { + b.HasOne("AsbCloudDb.Model.Cluster", "Cluster") + .WithMany("Wells") + .HasForeignKey("IdCluster") + .HasConstraintName("t_well_t_cluster_id_fk"); + + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithOne("Well") + .HasForeignKey("AsbCloudDb.Model.Well", "IdTelemetry") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("t_well_t_telemetry_id_fk"); + + b.HasOne("AsbCloudDb.Model.WellType", "WellType") + .WithMany("Wells") + .HasForeignKey("IdWellType"); + + b.Navigation("Cluster"); + + b.Navigation("Telemetry"); + + b.Navigation("WellType"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellComposite", b => + { + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany("WellComposites") + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_well_сomposite_t_well_id_fk"); + + b.HasOne("AsbCloudDb.Model.WellSectionType", "WellSectionType") + .WithMany("WellComposites") + .HasForeignKey("IdWellSectionType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_well_сomposite_t_well_section_type_id_fk"); + + b.HasOne("AsbCloudDb.Model.Well", "WellSrc") + .WithMany("WellCompositeSrcs") + .HasForeignKey("IdWellSrc") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_well_сomposite_src_t_well_id_fk"); + + b.Navigation("Well"); + + b.Navigation("WellSectionType"); + + b.Navigation("WellSrc"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellFinalDocument", b => + { + b.HasOne("AsbCloudDb.Model.FileCategory", "Category") + .WithMany() + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("User"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellOperation", b => + { + b.HasOne("AsbCloudDb.Model.WellOperationCategory", "OperationCategory") + .WithMany() + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany("WellOperations") + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.WellSectionType", "WellSectionType") + .WithMany("WellOperations") + .HasForeignKey("IdWellSectionType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OperationCategory"); + + b.Navigation("Well"); + + b.Navigation("WellSectionType"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record1", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record1", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record50", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record50", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record60", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record60", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record61", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record61", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record7", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record7", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record8", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record8", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Cluster", b => + { + b.Navigation("Wells"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Company", b => + { + b.Navigation("RelationCompaniesWells"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.CompanyType", b => + { + b.Navigation("Companies"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Deposit", b => + { + b.Navigation("Clusters"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Driller", b => + { + b.Navigation("Schedule"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b => + { + b.Navigation("RelatedUsers"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileInfo", b => + { + b.Navigation("FileMarks"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.MeasureCategory", b => + { + b.Navigation("Measures"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Permission", b => + { + b.Navigation("RelationUserRolePermissions"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Telemetry", b => + { + b.Navigation("DataSaub"); + + b.Navigation("DataSpin"); + + b.Navigation("Events"); + + b.Navigation("Messages"); + + b.Navigation("Users"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.User", b => + { + b.Navigation("FileMarks"); + + b.Navigation("Files"); + + b.Navigation("RelationUsersUserRoles"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.UserRole", b => + { + b.Navigation("RelationUserRolePermissions"); + + b.Navigation("RelationUserRoleUserRoles"); + + b.Navigation("RelationUsersUserRoles"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Well", b => + { + b.Navigation("DrillingProgramParts"); + + b.Navigation("RelationCompaniesWells"); + + b.Navigation("WellCompositeSrcs"); + + b.Navigation("WellComposites"); + + b.Navigation("WellOperations"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellSectionType", b => + { + b.Navigation("DrillParamsCollection"); + + b.Navigation("WellComposites"); + + b.Navigation("WellOperations"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellType", b => + { + b.Navigation("Wells"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/AsbCloudDb/Migrations/20221013040242_Delete_colums_table_t_telemetry_data_spin.cs b/AsbCloudDb/Migrations/20221013040242_Delete_colums_table_t_telemetry_data_spin.cs new file mode 100644 index 00000000..0ebf1f57 --- /dev/null +++ b/AsbCloudDb/Migrations/20221013040242_Delete_colums_table_t_telemetry_data_spin.cs @@ -0,0 +1,577 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AsbCloudDb.Migrations +{ + public partial class Delete_colums_table_t_telemetry_data_spin : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "break_angle_k", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "break_angle_left", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "encoder_resolution", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "pid_mux_torque_left_limit", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "ratio", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "reverse_k_torque", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "reverse_speed_sp_zero_time", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "rotor_torque_avg", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_err", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_max", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_min", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_offset", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_sp_from", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_sp_from_err", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_sp_from_max", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_sp_from_min", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_sp_from_offset", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_sp_to", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_sp_to_err", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_sp_to_max", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_sp_to_min", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_speed_sp_to_offset", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_err", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_max", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_min", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_offset", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_sp_from", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_sp_from_err", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_sp_from_max", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_sp_from_min", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_sp_from_offset", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_sp_to", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_sp_to_err", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_sp_to_max", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_sp_to_min", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "top_drive_torque_sp_to_offset", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "torque_left_limit", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "torque_ramp_time", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "torque_right_limit", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "torque_starting", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "turn_left_once_by_angle", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "turn_left_once_by_revols", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "turn_left_once_by_torque", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "turn_right_once_by_angle", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "turn_right_once_by_revols", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "turn_right_once_by_torque", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "unlock_by_sector_out", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "ver", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "w2800", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "w2808", + table: "t_telemetry_data_spin"); + + migrationBuilder.DropColumn( + name: "w2810", + table: "t_telemetry_data_spin"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "break_angle_k", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Коэффициент для расчёта за какой угол нужно тормозить"); + + migrationBuilder.AddColumn( + name: "break_angle_left", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Угол торможения влево при работе по моменту"); + + migrationBuilder.AddColumn( + name: "encoder_resolution", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Разрешение энкодера"); + + migrationBuilder.AddColumn( + name: "pid_mux_torque_left_limit", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: " Момент при котором определяется ехать назад по моменту или по скорости"); + + migrationBuilder.AddColumn( + name: "ratio", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: " Коэффициент редукции редуктора"); + + migrationBuilder.AddColumn( + name: "reverse_k_torque", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Коэффициент на который умножается момент, для того чтобы система поняла что мы движемся в обратную сторону"); + + migrationBuilder.AddColumn( + name: "reverse_speed_sp_zero_time", + table: "t_telemetry_data_spin", + type: "smallint", + nullable: true, + comment: "Время выдачи сигнала нулевой скорости на при смене направления"); + + migrationBuilder.AddColumn( + name: "rotor_torque_avg", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Момент в роторе средний"); + + migrationBuilder.AddColumn( + name: "top_drive_speed", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Скорость СВП"); + + migrationBuilder.AddColumn( + name: "top_drive_speed_err", + table: "t_telemetry_data_spin", + type: "smallint", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_speed_max", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "верхний предел"); + + migrationBuilder.AddColumn( + name: "top_drive_speed_min", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "нижний предел"); + + migrationBuilder.AddColumn( + name: "top_drive_speed_offset", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "смещение"); + + migrationBuilder.AddColumn( + name: "top_drive_speed_sp_from", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Заданная скорость c СВП"); + + migrationBuilder.AddColumn( + name: "top_drive_speed_sp_from_err", + table: "t_telemetry_data_spin", + type: "smallint", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_speed_sp_from_max", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_speed_sp_from_min", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_speed_sp_from_offset", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_speed_sp_to", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Задание скорости на СВП"); + + migrationBuilder.AddColumn( + name: "top_drive_speed_sp_to_err", + table: "t_telemetry_data_spin", + type: "smallint", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_speed_sp_to_max", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_speed_sp_to_min", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_speed_sp_to_offset", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Момент СВП"); + + migrationBuilder.AddColumn( + name: "top_drive_torque_err", + table: "t_telemetry_data_spin", + type: "smallint", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_max", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_min", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_offset", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_sp_from", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Заданный момент c СВП"); + + migrationBuilder.AddColumn( + name: "top_drive_torque_sp_from_err", + table: "t_telemetry_data_spin", + type: "smallint", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_sp_from_max", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_sp_from_min", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_sp_from_offset", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_sp_to", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Задание момента на СВП"); + + migrationBuilder.AddColumn( + name: "top_drive_torque_sp_to_err", + table: "t_telemetry_data_spin", + type: "smallint", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_sp_to_max", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_sp_to_min", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "top_drive_torque_sp_to_offset", + table: "t_telemetry_data_spin", + type: "real", + nullable: true); + + migrationBuilder.AddColumn( + name: "torque_left_limit", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Ограничение крутящего момента влево"); + + migrationBuilder.AddColumn( + name: "torque_ramp_time", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Время нарастания момента"); + + migrationBuilder.AddColumn( + name: "torque_right_limit", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Ограничение крутящего момента вправо"); + + migrationBuilder.AddColumn( + name: "torque_starting", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Страгивающий момент"); + + migrationBuilder.AddColumn( + name: "turn_left_once_by_angle", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Доворот по градусам единожды влево"); + + migrationBuilder.AddColumn( + name: "turn_left_once_by_revols", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Доворот по оборотам единожды влево"); + + migrationBuilder.AddColumn( + name: "turn_left_once_by_torque", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Доворот по моменту единожды влево"); + + migrationBuilder.AddColumn( + name: "turn_right_once_by_angle", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Доворот по градусам единожды вправо"); + + migrationBuilder.AddColumn( + name: "turn_right_once_by_revols", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Доворот по оборотам единожды вправо"); + + migrationBuilder.AddColumn( + name: "turn_right_once_by_torque", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Доворот по моменту единожды вправо"); + + migrationBuilder.AddColumn( + name: "unlock_by_sector_out", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: " Градус отклонения от сектора для автоматического сброса блокировки"); + + migrationBuilder.AddColumn( + name: "ver", + table: "t_telemetry_data_spin", + type: "real", + nullable: true, + comment: "Версия ПО ПЛК"); + + migrationBuilder.AddColumn( + name: "w2800", + table: "t_telemetry_data_spin", + type: "smallint", + nullable: true, + comment: "Установка нуля энкодера"); + + migrationBuilder.AddColumn( + name: "w2808", + table: "t_telemetry_data_spin", + type: "smallint", + nullable: true, + comment: "Неисправность энкодера"); + + migrationBuilder.AddColumn( + name: "w2810", + table: "t_telemetry_data_spin", + type: "smallint", + nullable: true, + comment: " автоматический сброс блокировки"); + } + } +} diff --git a/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs b/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs index aa3f655c..af644955 100644 --- a/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs +++ b/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs @@ -3435,31 +3435,11 @@ namespace AsbCloudDb.Migrations .HasColumnName("date") .HasComment("'2021-10-19 18:23:54+05'"); - b.Property("BreakAngleK") - .HasColumnType("real") - .HasColumnName("break_angle_k") - .HasComment("Коэффициент для расчёта за какой угол нужно тормозить"); - - b.Property("BreakAngleLeft") - .HasColumnType("real") - .HasColumnName("break_angle_left") - .HasComment("Угол торможения влево при работе по моменту"); - - b.Property("EncoderResolution") - .HasColumnType("real") - .HasColumnName("encoder_resolution") - .HasComment("Разрешение энкодера"); - b.Property("Mode") .HasColumnType("smallint") .HasColumnName("mode") .HasComment("Выбранный режим управления"); - b.Property("PidMuxTorqueLeftLimit") - .HasColumnType("real") - .HasColumnName("pid_mux_torque_left_limit") - .HasComment(" Момент при котором определяется ехать назад по моменту или по скорости"); - b.Property("PositionRight") .HasColumnType("real") .HasColumnName("position_right") @@ -3470,21 +3450,6 @@ namespace AsbCloudDb.Migrations .HasColumnName("position_zero") .HasComment("Нулевая позиция осцилляции"); - b.Property("Ratio") - .HasColumnType("real") - .HasColumnName("ratio") - .HasComment(" Коэффициент редукции редуктора"); - - b.Property("ReverseKTorque") - .HasColumnType("real") - .HasColumnName("reverse_k_torque") - .HasComment("Коэффициент на который умножается момент, для того чтобы система поняла что мы движемся в обратную сторону"); - - b.Property("ReverseSpeedSpZeroTime") - .HasColumnType("smallint") - .HasColumnName("reverse_speed_sp_zero_time") - .HasComment("Время выдачи сигнала нулевой скорости на при смене направления"); - b.Property("RevolsLeftLimit") .HasColumnType("real") .HasColumnName("revols_left_limit") @@ -3505,11 +3470,6 @@ namespace AsbCloudDb.Migrations .HasColumnName("revols_right_total") .HasComment("Суммарное количество оборотов вправо"); - b.Property("RotorTorqueAvg") - .HasColumnType("real") - .HasColumnName("rotor_torque_avg") - .HasComment("Момент в роторе средний"); - b.Property("SpeedLeftSp") .HasColumnType("real") .HasColumnName("speed_left_sp") @@ -3525,210 +3485,6 @@ namespace AsbCloudDb.Migrations .HasColumnName("state") .HasComment("Переменная этапа"); - b.Property("TopDriveSpeed") - .HasColumnType("real") - .HasColumnName("top_drive_speed") - .HasComment("Скорость СВП"); - - b.Property("TopDriveSpeedErr") - .HasColumnType("smallint") - .HasColumnName("top_drive_speed_err"); - - b.Property("TopDriveSpeedMax") - .HasColumnType("real") - .HasColumnName("top_drive_speed_max") - .HasComment("верхний предел"); - - b.Property("TopDriveSpeedMin") - .HasColumnType("real") - .HasColumnName("top_drive_speed_min") - .HasComment("нижний предел"); - - b.Property("TopDriveSpeedOffset") - .HasColumnType("real") - .HasColumnName("top_drive_speed_offset") - .HasComment("смещение"); - - b.Property("TopDriveSpeedSpFrom") - .HasColumnType("real") - .HasColumnName("top_drive_speed_sp_from") - .HasComment("Заданная скорость c СВП"); - - b.Property("TopDriveSpeedSpFromErr") - .HasColumnType("smallint") - .HasColumnName("top_drive_speed_sp_from_err"); - - b.Property("TopDriveSpeedSpFromMax") - .HasColumnType("real") - .HasColumnName("top_drive_speed_sp_from_max"); - - b.Property("TopDriveSpeedSpFromMin") - .HasColumnType("real") - .HasColumnName("top_drive_speed_sp_from_min"); - - b.Property("TopDriveSpeedSpFromOffset") - .HasColumnType("real") - .HasColumnName("top_drive_speed_sp_from_offset"); - - b.Property("TopDriveSpeedSpTo") - .HasColumnType("real") - .HasColumnName("top_drive_speed_sp_to") - .HasComment("Задание скорости на СВП"); - - b.Property("TopDriveSpeedSpToErr") - .HasColumnType("smallint") - .HasColumnName("top_drive_speed_sp_to_err"); - - b.Property("TopDriveSpeedSpToMax") - .HasColumnType("real") - .HasColumnName("top_drive_speed_sp_to_max"); - - b.Property("TopDriveSpeedSpToMin") - .HasColumnType("real") - .HasColumnName("top_drive_speed_sp_to_min"); - - b.Property("TopDriveSpeedSpToOffset") - .HasColumnType("real") - .HasColumnName("top_drive_speed_sp_to_offset"); - - b.Property("TopDriveTorque") - .HasColumnType("real") - .HasColumnName("top_drive_torque") - .HasComment("Момент СВП"); - - b.Property("TopDriveTorqueErr") - .HasColumnType("smallint") - .HasColumnName("top_drive_torque_err"); - - b.Property("TopDriveTorqueMax") - .HasColumnType("real") - .HasColumnName("top_drive_torque_max"); - - b.Property("TopDriveTorqueMin") - .HasColumnType("real") - .HasColumnName("top_drive_torque_min"); - - b.Property("TopDriveTorqueOffset") - .HasColumnType("real") - .HasColumnName("top_drive_torque_offset"); - - b.Property("TopDriveTorqueSpFrom") - .HasColumnType("real") - .HasColumnName("top_drive_torque_sp_from") - .HasComment("Заданный момент c СВП"); - - b.Property("TopDriveTorqueSpFromErr") - .HasColumnType("smallint") - .HasColumnName("top_drive_torque_sp_from_err"); - - b.Property("TopDriveTorqueSpFromMax") - .HasColumnType("real") - .HasColumnName("top_drive_torque_sp_from_max"); - - b.Property("TopDriveTorqueSpFromMin") - .HasColumnType("real") - .HasColumnName("top_drive_torque_sp_from_min"); - - b.Property("TopDriveTorqueSpFromOffset") - .HasColumnType("real") - .HasColumnName("top_drive_torque_sp_from_offset"); - - b.Property("TopDriveTorqueSpTo") - .HasColumnType("real") - .HasColumnName("top_drive_torque_sp_to") - .HasComment("Задание момента на СВП"); - - b.Property("TopDriveTorqueSpToErr") - .HasColumnType("smallint") - .HasColumnName("top_drive_torque_sp_to_err"); - - b.Property("TopDriveTorqueSpToMax") - .HasColumnType("real") - .HasColumnName("top_drive_torque_sp_to_max"); - - b.Property("TopDriveTorqueSpToMin") - .HasColumnType("real") - .HasColumnName("top_drive_torque_sp_to_min"); - - b.Property("TopDriveTorqueSpToOffset") - .HasColumnType("real") - .HasColumnName("top_drive_torque_sp_to_offset"); - - b.Property("TorqueLeftLimit") - .HasColumnType("real") - .HasColumnName("torque_left_limit") - .HasComment("Ограничение крутящего момента влево"); - - b.Property("TorqueRampTime") - .HasColumnType("real") - .HasColumnName("torque_ramp_time") - .HasComment("Время нарастания момента"); - - b.Property("TorqueRightLimit") - .HasColumnType("real") - .HasColumnName("torque_right_limit") - .HasComment("Ограничение крутящего момента вправо"); - - b.Property("TorqueStarting") - .HasColumnType("real") - .HasColumnName("torque_starting") - .HasComment("Страгивающий момент"); - - b.Property("TurnLeftOnceByAngle") - .HasColumnType("real") - .HasColumnName("turn_left_once_by_angle") - .HasComment("Доворот по градусам единожды влево"); - - b.Property("TurnLeftOnceByRevols") - .HasColumnType("real") - .HasColumnName("turn_left_once_by_revols") - .HasComment("Доворот по оборотам единожды влево"); - - b.Property("TurnLeftOnceByTorque") - .HasColumnType("real") - .HasColumnName("turn_left_once_by_torque") - .HasComment("Доворот по моменту единожды влево"); - - b.Property("TurnRightOnceByAngle") - .HasColumnType("real") - .HasColumnName("turn_right_once_by_angle") - .HasComment("Доворот по градусам единожды вправо"); - - b.Property("TurnRightOnceByRevols") - .HasColumnType("real") - .HasColumnName("turn_right_once_by_revols") - .HasComment("Доворот по оборотам единожды вправо"); - - b.Property("TurnRightOnceByTorque") - .HasColumnType("real") - .HasColumnName("turn_right_once_by_torque") - .HasComment("Доворот по моменту единожды вправо"); - - b.Property("UnlockBySectorOut") - .HasColumnType("real") - .HasColumnName("unlock_by_sector_out") - .HasComment(" Градус отклонения от сектора для автоматического сброса блокировки"); - - b.Property("Ver") - .HasColumnType("real") - .HasColumnName("ver") - .HasComment("Версия ПО ПЛК"); - - b.Property("W2800") - .HasColumnType("smallint") - .HasColumnName("w2800") - .HasComment("Установка нуля энкодера"); - - b.Property("W2808") - .HasColumnType("smallint") - .HasColumnName("w2808") - .HasComment("Неисправность энкодера"); - - b.Property("W2810") - .HasColumnType("smallint") - .HasColumnName("w2810") - .HasComment(" автоматический сброс блокировки"); - b.HasKey("IdTelemetry", "DateTime"); b.ToTable("t_telemetry_data_spin"); diff --git a/AsbCloudDb/Model/TelemetryDataSpin.cs b/AsbCloudDb/Model/TelemetryDataSpin.cs index 5976860f..320dd2f2 100644 --- a/AsbCloudDb/Model/TelemetryDataSpin.cs +++ b/AsbCloudDb/Model/TelemetryDataSpin.cs @@ -11,135 +11,37 @@ namespace AsbCloudDb.Model { [Column("id_telemetry")] public int IdTelemetry { get; set; } + [Column("date", TypeName = "timestamp with time zone"), Comment("'2021-10-19 18:23:54+05'")] public DateTimeOffset DateTime { get; set; } - [Column("top_drive_speed"), Comment("Скорость СВП")] - public float? TopDriveSpeed { get; set; } - [Column("top_drive_speed_min"), Comment("нижний предел")] - public float? TopDriveSpeedMin { get; set; } - [Column("top_drive_speed_max"), Comment("верхний предел")] - public float? TopDriveSpeedMax { get; set; } - [Column("top_drive_speed_offset"), Comment("смещение")] - public float? TopDriveSpeedOffset { get; set; } - [Column("top_drive_torque"), Comment("Момент СВП")] - public float? TopDriveTorque { get; set; } - [Column("top_drive_torque_min")] - public float? TopDriveTorqueMin { get; set; } - [Column("top_drive_torque_max")] - public float? TopDriveTorqueMax { get; set; } - [Column("top_drive_torque_offset")] - public float? TopDriveTorqueOffset { get; set; } - [Column("top_drive_speed_sp_from"), Comment("Заданная скорость c СВП")] - public float? TopDriveSpeedSpFrom { get; set; } - [Column("top_drive_speed_sp_from_min")] - public float? TopDriveSpeedSpFromMin { get; set; } - [Column("top_drive_speed_sp_from_max")] - public float? TopDriveSpeedSpFromMax { get; set; } - [Column("top_drive_speed_sp_from_offset")] - public float? TopDriveSpeedSpFromOffset { get; set; } - [Column("top_drive_torque_sp_from"), Comment("Заданный момент c СВП")] - public float? TopDriveTorqueSpFrom { get; set; } - [Column("top_drive_torque_sp_from_min")] - public float? TopDriveTorqueSpFromMin { get; set; } - [Column("top_drive_torque_sp_from_max")] - public float? TopDriveTorqueSpFromMax { get; set; } - [Column("top_drive_torque_sp_from_offset")] - public float? TopDriveTorqueSpFromOffset { get; set; } - [Column("top_drive_speed_sp_to"), Comment("Задание скорости на СВП")] - public float? TopDriveSpeedSpTo { get; set; } - [Column("top_drive_speed_sp_to_min")] - public float? TopDriveSpeedSpToMin { get; set; } - [Column("top_drive_speed_sp_to_max")] - public float? TopDriveSpeedSpToMax { get; set; } - [Column("top_drive_speed_sp_to_offset")] - public float? TopDriveSpeedSpToOffset { get; set; } - [Column("top_drive_torque_sp_to"), Comment("Задание момента на СВП")] - public float? TopDriveTorqueSpTo { get; set; } - [Column("top_drive_torque_sp_to_min")] - public float? TopDriveTorqueSpToMin { get; set; } - [Column("top_drive_torque_sp_to_max")] - public float? TopDriveTorqueSpToMax { get; set; } - [Column("top_drive_torque_sp_to_offset")] - public float? TopDriveTorqueSpToOffset { get; set; } - [Column("torque_starting"), Comment("Страгивающий момент")] - public float? TorqueStarting { get; set; } - [Column("rotor_torque_avg"), Comment("Момент в роторе средний")] - public float? RotorTorqueAvg { get; set; } - [Column("encoder_resolution"), Comment("Разрешение энкодера")] - public float? EncoderResolution { get; set; } - [Column("ratio"), Comment(" Коэффициент редукции редуктора")] - public float? Ratio { get; set; } - [Column("torque_right_limit"), Comment("Ограничение крутящего момента вправо")] - public float? TorqueRightLimit { get; set; } - [Column("torque_left_limit"), Comment("Ограничение крутящего момента влево")] - public float? TorqueLeftLimit { get; set; } [Column("revols_right_limit"), Comment("Ограничение числа оборотов вправо")] public float? RevolsRightLimit { get; set; } + [Column("revols_left_limit"), Comment("Ограничение числа оборотов влево")] public float? RevolsLeftLimit { get; set; } + [Column("speed_right_sp"), Comment("Заданная скорость вращения вправо")] public float? SpeedRightSp { get; set; } + [Column("speed_left_sp"), Comment("Заданная скорость вращения влево")] public float? SpeedLeftSp { get; set; } + [Column("revols_right_total"), Comment("Суммарное количество оборотов вправо")] public float? RevolsRightTotal { get; set; } + [Column("revols_left_total"), Comment("Суммарное количество оборотов влево")] public float? RevolsLeftTotal { get; set; } - [Column("turn_right_once_by_torque"), Comment("Доворот по моменту единожды вправо")] - public float? TurnRightOnceByTorque { get; set; } - [Column("turn_left_once_by_torque"), Comment("Доворот по моменту единожды влево")] - public float? TurnLeftOnceByTorque { get; set; } - [Column("turn_right_once_by_angle"), Comment("Доворот по градусам единожды вправо")] - public float? TurnRightOnceByAngle { get; set; } - [Column("turn_left_once_by_angle"), Comment("Доворот по градусам единожды влево")] - public float? TurnLeftOnceByAngle { get; set; } - [Column("turn_right_once_by_revols"), Comment("Доворот по оборотам единожды вправо")] - public float? TurnRightOnceByRevols { get; set; } - [Column("turn_left_once_by_revols"), Comment("Доворот по оборотам единожды влево")] - public float? TurnLeftOnceByRevols { get; set; } - [Column("break_angle_k"), Comment("Коэффициент для расчёта за какой угол нужно тормозить")] - public float? BreakAngleK { get; set; } - [Column("reverse_k_torque"), Comment("Коэффициент на который умножается момент, для того чтобы система поняла что мы движемся в обратную сторону")] - public float? ReverseKTorque { get; set; } + [Column("position_zero"), Comment("Нулевая позиция осцилляции")] public float? PositionZero { get; set; } + [Column("position_right"), Comment("Крайний правый угол осцилляции")] public float? PositionRight { get; set; } - [Column("torque_ramp_time"), Comment("Время нарастания момента")] - public float? TorqueRampTime { get; set; } - [Column("ver"), Comment("Версия ПО ПЛК")] - public float? Ver { get; set; } - [Column("unlock_by_sector_out"), Comment(" Градус отклонения от сектора для автоматического сброса блокировки")] - public float? UnlockBySectorOut { get; set; } - [Column("pid_mux_torque_left_limit"), Comment(" Момент при котором определяется ехать назад по моменту или по скорости")] - public float? PidMuxTorqueLeftLimit { get; set; } - [Column("break_angle_left"), Comment("Угол торможения влево при работе по моменту")] - public float? BreakAngleLeft { get; set; } - - [Column("top_drive_speed_err")] - public short? TopDriveSpeedErr { get; set; } - [Column("top_drive_torque_err")] - public short? TopDriveTorqueErr { get; set; } - [Column("top_drive_speed_sp_from_err")] - public short? TopDriveSpeedSpFromErr { get; set; } - [Column("top_drive_torque_sp_from_err")] - public short? TopDriveTorqueSpFromErr { get; set; } - [Column("top_drive_speed_sp_to_err")] - public short? TopDriveSpeedSpToErr { get; set; } - [Column("top_drive_torque_sp_to_err")] - public short? TopDriveTorqueSpToErr { get; set; } - [Column("w2800"), Comment("Установка нуля энкодера")] - public short? W2800 { get; set; } - [Column("w2810"), Comment(" автоматический сброс блокировки")] - public short? W2810 { get; set; } [Column("mode"), Comment("Выбранный режим управления")] public short? Mode { get; set; } - [Column("w2808"), Comment("Неисправность энкодера")] - public short? W2808 { get; set; } - [Column("reverse_speed_sp_zero_time"), Comment("Время выдачи сигнала нулевой скорости на при смене направления")] - public short? ReverseSpeedSpZeroTime { get; set; } + [Column("state"), Comment("Переменная этапа")] public short? State { get; set; } diff --git a/AsbCloudWebApi/Program.cs b/AsbCloudWebApi/Program.cs index 822d20be..b21fa05f 100644 --- a/AsbCloudWebApi/Program.cs +++ b/AsbCloudWebApi/Program.cs @@ -1,3 +1,4 @@ +using DocumentFormat.OpenXml.InkML; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -25,7 +26,10 @@ namespace AsbCloudWebApi { var connectionStringName = "DefaultConnection"; - AsbCloudInfrastructure.DependencyInjection.MakeContext(configuration.GetConnectionString(connectionStringName)); + var context = AsbCloudInfrastructure.DependencyInjection.MakeContext(configuration.GetConnectionString(connectionStringName)); + context.Database.SetCommandTimeout(TimeSpan.FromSeconds(5 * 60)); + context.Database.Migrate(); + Console.WriteLine(" ."); return; } diff --git a/AsbCloudWebApi/ProtobufModel.cs b/AsbCloudWebApi/ProtobufModel.cs index 4bebb030..c193a1bf 100644 --- a/AsbCloudWebApi/ProtobufModel.cs +++ b/AsbCloudWebApi/ProtobufModel.cs @@ -296,69 +296,16 @@ namespace AsbCloudWebApi RuntimeTypeModel.Default.Add(type, false) .Add(1, nameof(TelemetryDataSpinDto.IdTelemetry)) .Add(2, nameof(TelemetryDataSpinDto.DateTime)) - .Add(3, nameof(TelemetryDataSpinDto.TopDriveSpeed)) - .Add(4, nameof(TelemetryDataSpinDto.TopDriveSpeedMin)) - .Add(5, nameof(TelemetryDataSpinDto.TopDriveSpeedMax)) - .Add(6, nameof(TelemetryDataSpinDto.TopDriveSpeedOffset)) - .Add(7, nameof(TelemetryDataSpinDto.TopDriveSpeedErr)) - .Add(8, nameof(TelemetryDataSpinDto.TopDriveTorque)) - .Add(9, nameof(TelemetryDataSpinDto.TopDriveTorqueMin)) - .Add(10, nameof(TelemetryDataSpinDto.TopDriveTorqueMax)) - .Add(11, nameof(TelemetryDataSpinDto.TopDriveTorqueOffset)) - .Add(12, nameof(TelemetryDataSpinDto.TopDriveTorqueErr)) - .Add(13, nameof(TelemetryDataSpinDto.TopDriveSpeedSpFrom)) - .Add(14, nameof(TelemetryDataSpinDto.TopDriveSpeedSpFromMin)) - .Add(15, nameof(TelemetryDataSpinDto.TopDriveSpeedSpFromMax)) - .Add(16, nameof(TelemetryDataSpinDto.TopDriveSpeedSpFromOffset)) - .Add(17, nameof(TelemetryDataSpinDto.TopDriveSpeedSpFromErr)) - .Add(18, nameof(TelemetryDataSpinDto.TopDriveTorqueSpFrom)) - .Add(19, nameof(TelemetryDataSpinDto.TopDriveTorqueSpFromMin)) - .Add(20, nameof(TelemetryDataSpinDto.TopDriveTorqueSpFromMax)) - .Add(21, nameof(TelemetryDataSpinDto.TopDriveTorqueSpFromOffset)) - .Add(22, nameof(TelemetryDataSpinDto.TopDriveTorqueSpFromErr)) - .Add(23, nameof(TelemetryDataSpinDto.TopDriveSpeedSpTo)) - .Add(24, nameof(TelemetryDataSpinDto.TopDriveSpeedSpToMin)) - .Add(25, nameof(TelemetryDataSpinDto.TopDriveSpeedSpToMax)) - .Add(26, nameof(TelemetryDataSpinDto.TopDriveSpeedSpToOffset)) - .Add(27, nameof(TelemetryDataSpinDto.TopDriveSpeedSpToErr)) - .Add(28, nameof(TelemetryDataSpinDto.TopDriveTorqueSpTo)) - .Add(29, nameof(TelemetryDataSpinDto.TopDriveTorqueSpToMin)) - .Add(30, nameof(TelemetryDataSpinDto.TopDriveTorqueSpToMax)) - .Add(31, nameof(TelemetryDataSpinDto.TopDriveTorqueSpToOffset)) - .Add(32, nameof(TelemetryDataSpinDto.TopDriveTorqueSpToErr)) - .Add(33, nameof(TelemetryDataSpinDto.W2800)) - .Add(34, nameof(TelemetryDataSpinDto.W2810)) .Add(35, nameof(TelemetryDataSpinDto.Mode)) - .Add(36, nameof(TelemetryDataSpinDto.W2808)) - .Add(37, nameof(TelemetryDataSpinDto.TorqueStarting)) - .Add(38, nameof(TelemetryDataSpinDto.RotorTorqueAvg)) - .Add(39, nameof(TelemetryDataSpinDto.EncoderResolution)) - .Add(40, nameof(TelemetryDataSpinDto.Ratio)) - .Add(41, nameof(TelemetryDataSpinDto.TorqueRightLimit)) - .Add(42, nameof(TelemetryDataSpinDto.TorqueLeftLimit)) .Add(43, nameof(TelemetryDataSpinDto.RevolsRightLimit)) .Add(44, nameof(TelemetryDataSpinDto.RevolsLeftLimit)) .Add(45, nameof(TelemetryDataSpinDto.SpeedRightSp)) .Add(46, nameof(TelemetryDataSpinDto.SpeedLeftSp)) .Add(47, nameof(TelemetryDataSpinDto.RevolsRightTotal)) .Add(48, nameof(TelemetryDataSpinDto.RevolsLeftTotal)) - .Add(49, nameof(TelemetryDataSpinDto.TurnRightOnceByTorque)) - .Add(50, nameof(TelemetryDataSpinDto.TurnLeftOnceByTorque)) - .Add(51, nameof(TelemetryDataSpinDto.TurnRightOnceByAngle)) - .Add(52, nameof(TelemetryDataSpinDto.TurnLeftOnceByAngle)) - .Add(53, nameof(TelemetryDataSpinDto.TurnRightOnceByRevols)) - .Add(54, nameof(TelemetryDataSpinDto.TurnLeftOnceByRevols)) - .Add(55, nameof(TelemetryDataSpinDto.BreakAngleK)) - .Add(56, nameof(TelemetryDataSpinDto.ReverseKTorque)) .Add(57, nameof(TelemetryDataSpinDto.PositionZero)) .Add(58, nameof(TelemetryDataSpinDto.PositionRight)) - .Add(59, nameof(TelemetryDataSpinDto.TorqueRampTime)) - .Add(60, nameof(TelemetryDataSpinDto.Ver)) - .Add(61, nameof(TelemetryDataSpinDto.ReverseSpeedSpZeroTime)) - .Add(62, nameof(TelemetryDataSpinDto.UnlockBySectorOut)) - .Add(63, nameof(TelemetryDataSpinDto.PidMuxTorqueLeftLimit)) - .Add(64, nameof(TelemetryDataSpinDto.State)) - .Add(65, nameof(TelemetryDataSpinDto.BreakAngleLeft)); + .Add(64, nameof(TelemetryDataSpinDto.State)); } static void EnshureRegisteredDataSaub() From 8a83194187dda20f97fa2dd77ef6cd911b80a663 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Mon, 17 Oct 2022 08:58:28 +0500 Subject: [PATCH 36/37] =?UTF-8?q?#6385536=20=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B5=D0=BD=D1=83=D0=B6=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2.=20=D0=97=D0=B0?= =?UTF-8?q?=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repositories/IFileStorageRepository.cs | 2 +- AsbCloudApp/Services/FileService.cs | 16 ++- .../Repository/FileRepository.cs | 109 ++++++++++-------- .../Repository/FileStorageRepository.cs | 2 +- .../ServicesTests/FileServiceTest.cs | 4 + AsbCloudWebApi/Controllers/FileController.cs | 3 +- 6 files changed, 81 insertions(+), 55 deletions(-) diff --git a/AsbCloudApp/Repositories/IFileStorageRepository.cs b/AsbCloudApp/Repositories/IFileStorageRepository.cs index 68ce51e9..0d867db0 100644 --- a/AsbCloudApp/Repositories/IFileStorageRepository.cs +++ b/AsbCloudApp/Repositories/IFileStorageRepository.cs @@ -46,7 +46,7 @@ namespace AsbCloudApp.Repositories /// /// /// - int DeleteFilesNotList(int idWell, IEnumerable idsFiles); + int DeleteFilesNotInList(int idWell, IEnumerable idsFiles); /// /// Вывод списка всех файлов из базы, для которых нет файла на диске diff --git a/AsbCloudApp/Services/FileService.cs b/AsbCloudApp/Services/FileService.cs index d16006e1..04b2c65d 100644 --- a/AsbCloudApp/Services/FileService.cs +++ b/AsbCloudApp/Services/FileService.cs @@ -312,7 +312,7 @@ namespace AsbCloudApp.Services IdWell = idWell }, token); - var result = await Task.FromResult(fileStorageRepository.DeleteFilesNotList(idWell, files.Select(x => x.Id))); + var result = await Task.FromResult(fileStorageRepository.DeleteFilesNotInList(idWell, files.Select(x => x.Id))); return result; } @@ -333,6 +333,20 @@ namespace AsbCloudApp.Services var result = fileStorageRepository.GetListFilesNotDisc(files); return result; } + + /// + /// Получить файловый поток по идентификатору файла + /// + /// + /// + /// + public FileStream GetFileStream(FileInfoDto fileInfo) + { + var relativePath = GetUrl(fileInfo); + var fileStream = new FileStream(Path.GetFullPath(relativePath), FileMode.Open); + + return fileStream; + } } #nullable disable } diff --git a/AsbCloudInfrastructure/Repository/FileRepository.cs b/AsbCloudInfrastructure/Repository/FileRepository.cs index 16367b09..6eacf56b 100644 --- a/AsbCloudInfrastructure/Repository/FileRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileRepository.cs @@ -45,23 +45,11 @@ namespace AsbCloudInfrastructure.Repository public async Task> GetInfosAsync(FileServiceRequest request, CancellationToken token = default) { - var query = dbSetConfigured - .Where(e => e.IdWell == request.IdWell && - e.IdCategory == request.IdCategory && - !e.IsDeleted); - - if (request.CompanyName is not null) - query = query.Where(e => (e.Author == null) || - (e.Author.Company == null) || - e.Author.Company.Caption.Contains(request.CompanyName)); - - if (request.FileName is not null) - query = query.Where(e => e.Name.ToLower().Contains(request.FileName.ToLower())); - + var query = GetQuery(request, token); + var firstFile = query.FirstOrDefault(); var skip = request.Skip ?? 0; var take = request.Take ?? 32; - var firstFile = await query.FirstOrDefaultAsync(token); if (firstFile is null) return new PaginationContainer() { @@ -71,21 +59,7 @@ namespace AsbCloudInfrastructure.Repository }; var timezoneOffset = firstFile.Well.Timezone?.Hours ?? 5; - - if (request.Begin is not null) - { - var beginUtc = request.Begin.Value.ToUtcDateTimeOffset(timezoneOffset); - query = query.Where(e => e.UploadDate >= beginUtc); - } - - if (request.End is not null) - { - var endUtc = request.End.Value.ToUtcDateTimeOffset(timezoneOffset); - query = query.Where(e => e.UploadDate <= endUtc); - } - var count = await query.CountAsync(token).ConfigureAwait(false); - var result = new PaginationContainer(count) { Skip = skip, @@ -206,9 +180,7 @@ namespace AsbCloudInfrastructure.Repository public async Task> GetInfosByWellIdAsync(FileServiceRequest request, CancellationToken token) { - var query = dbSetConfigured.Where(e => e.IdWell == request.IdWell); - if (request.IsDeleted is not null) - query = query.Where(x => x.IsDeleted == request.IsDeleted); + var query = GetQuery(request, token); var entities = await query .AsNoTracking() @@ -219,25 +191,6 @@ namespace AsbCloudInfrastructure.Repository return dtos; } - private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity) - { - var timezoneOffset = entity.Well.Timezone?.Hours ?? 5; - return Convert(entity, timezoneOffset); - } - - private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity, double timezoneOffset) - { - var dto = entity.Adapt(); - dto.UploadDate = entity.UploadDate.ToRemoteDateTime(timezoneOffset); - dto.FileMarks = entity.FileMarks.Select(m => - { - var mark = m.Adapt(); - mark.DateCreated = m.DateCreated.ToRemoteDateTime(timezoneOffset); - return mark; - }); - return dto; - } - public async Task> GetAllAsync(CancellationToken token) => await dbSetConfigured.AsNoTracking() .Select(x => Convert(x)) @@ -307,6 +260,62 @@ namespace AsbCloudInfrastructure.Repository { throw new NotImplementedException(); } + + private IQueryable GetQuery(FileServiceRequest request, CancellationToken token = default) + { + var query = dbSetConfigured + .Where(e => e.IdWell == request.IdWell && + e.IdCategory == request.IdCategory); + + if (request.IsDeleted is not null) + query = query.Where(x => x.IsDeleted == request.IsDeleted); + + if (request.CompanyName is not null) + query = query.Where(e => (e.Author == null) || + (e.Author.Company == null) || + e.Author.Company.Caption.Contains(request.CompanyName)); + + if (request.FileName is not null) + query = query.Where(e => e.Name.ToLower().Contains(request.FileName.ToLower())); + + var firstFile = query.FirstOrDefault(); + if (firstFile is null) + return Enumerable.Empty().AsQueryable(); + + var timezoneOffset = firstFile.Well.Timezone?.Hours ?? 5; + if (request.Begin is not null) + { + var beginUtc = request.Begin.Value.ToUtcDateTimeOffset(timezoneOffset); + query = query.Where(e => e.UploadDate >= beginUtc); + } + + if (request.End is not null) + { + var endUtc = request.End.Value.ToUtcDateTimeOffset(timezoneOffset); + query = query.Where(e => e.UploadDate <= endUtc); + } + + return query; + } + + private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity) + { + var timezoneOffset = entity.Well.Timezone?.Hours ?? 5; + return Convert(entity, timezoneOffset); + } + + private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity, double timezoneOffset) + { + var dto = entity.Adapt(); + dto.UploadDate = entity.UploadDate.ToRemoteDateTime(timezoneOffset); + dto.FileMarks = entity.FileMarks.Select(m => + { + var mark = m.Adapt(); + mark.DateCreated = m.DateCreated.ToRemoteDateTime(timezoneOffset); + return mark; + }); + return dto; + } } #nullable disable } diff --git a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs index 37a041b7..0d7a2cf8 100644 --- a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs @@ -57,7 +57,7 @@ namespace AsbCloudInfrastructure.Repository $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); } - public int DeleteFilesNotList(int idWell, IEnumerable idsFilesList) + public int DeleteFilesNotInList(int idWell, IEnumerable idsFilesList) { var allFilesPath = GetFilesPath(idWell); var result = 0; diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs index cf35bcab..4f83e996 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs @@ -133,6 +133,10 @@ namespace AsbCloudWebApi.Tests.ServicesTests }); var storageRepositoryMock = new Mock(); + storageRepositoryMock.Setup(x => x.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((int idWell, int idCategory, int idFile, string dotExtention) => { + return Path.Combine("files", idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); + }); fileService = new FileService(repositoryMock.Object, storageRepositoryMock.Object); } diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index 85c095a3..7d4e395b 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -122,9 +122,8 @@ namespace AsbCloudWebApi.Controllers try { var fileInfo = await fileService.GetInfoAsync(fileId, token); - var relativePath = fileService.GetUrl(fileInfo); + var fileStream = fileService.GetFileStream(fileInfo); - var fileStream = new FileStream(Path.GetFullPath(relativePath), FileMode.Open); return File(fileStream, "application/octet-stream", fileInfo.Name); } catch (FileNotFoundException ex) From 8b68b8276ab772e3410912228392c2aae60e104e Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Mon, 17 Oct 2022 14:42:47 +0500 Subject: [PATCH 37/37] #6385536 refactoring --- AsbCloudApp/Data/FileInfoDto.cs | 5 + AsbCloudApp/Repositories/IFileRepository.cs | 16 +- .../{FileServiceRequest.cs => FileRequest.cs} | 18 +- AsbCloudApp/Services/FileService.cs | 108 ++++------- AsbCloudDb/EFExtentions.cs | 11 ++ .../Repository/FileRepository.cs | 176 ++++++++---------- .../Repository/FileStorageRepository.cs | 12 +- .../DrillingProgram/DrillingProgramService.cs | 7 +- .../Services/WellFinalDocumentsService.cs | 10 +- .../DrillingProgramServiceTest.cs | 4 +- .../ServicesTests/FileServiceTest.cs | 28 +-- AsbCloudWebApi/Controllers/FileController.cs | 45 +++-- 12 files changed, 177 insertions(+), 263 deletions(-) rename AsbCloudApp/Requests/{FileServiceRequest.cs => FileRequest.cs} (71%) diff --git a/AsbCloudApp/Data/FileInfoDto.cs b/AsbCloudApp/Data/FileInfoDto.cs index 63abba8f..badcd5a4 100644 --- a/AsbCloudApp/Data/FileInfoDto.cs +++ b/AsbCloudApp/Data/FileInfoDto.cs @@ -39,6 +39,11 @@ namespace AsbCloudApp.Data /// public long Size { get; set; } + /// + /// Помечен как удаленный + /// + public bool IsDeleted { get; set; } + /// /// DTO автора /// diff --git a/AsbCloudApp/Repositories/IFileRepository.cs b/AsbCloudApp/Repositories/IFileRepository.cs index 4363c204..a05cf909 100644 --- a/AsbCloudApp/Repositories/IFileRepository.cs +++ b/AsbCloudApp/Repositories/IFileRepository.cs @@ -14,13 +14,12 @@ namespace AsbCloudApp.Repositories public interface IFileRepository : ICrudService { /// - /// Получить файлы определенной категории + /// Получение файлов по скважине /// - /// - /// + /// /// /// - Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token); + Task> GetInfosAsync(FileRequest request, CancellationToken token); /// /// Получить список файлов в контейнере @@ -28,7 +27,7 @@ namespace AsbCloudApp.Repositories /// /// /// - Task> GetInfosAsync(FileServiceRequest request, CancellationToken token = default); + Task> GetInfosPaginatedAsync(FileRequest request, CancellationToken token = default); /// /// Пометить файл как удаленный @@ -79,13 +78,6 @@ namespace AsbCloudApp.Repositories /// Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token); - /// - /// Получение файлов по скважине - /// - /// - /// - /// - Task> GetInfosByWellIdAsync(FileServiceRequest request, CancellationToken token); } #nullable disable } diff --git a/AsbCloudApp/Requests/FileServiceRequest.cs b/AsbCloudApp/Requests/FileRequest.cs similarity index 71% rename from AsbCloudApp/Requests/FileServiceRequest.cs rename to AsbCloudApp/Requests/FileRequest.cs index bc561bdd..14a799e0 100644 --- a/AsbCloudApp/Requests/FileServiceRequest.cs +++ b/AsbCloudApp/Requests/FileRequest.cs @@ -7,13 +7,13 @@ namespace AsbCloudApp.Requests /// /// Параметры запроса для файлового сервиса /// - public class FileServiceRequest : RequestBase + public class FileRequest : RequestBase { /// /// Идентификатор скважины /// [Required] - public int? IdWell { get; set; } + public int IdWell { get; set; } /// /// Идентификатор категории файла @@ -24,12 +24,12 @@ namespace AsbCloudApp.Requests /// /// Наименование компании /// - public string? CompanyName { get; set; } + public string? CompanyNamePart { get; set; } /// /// Имя файла /// - public string? FileName { get; set; } + public string? FileNamePart { get; set; } /// /// Дата начала периода @@ -41,16 +41,6 @@ namespace AsbCloudApp.Requests /// public DateTime? End { get; set; } - /// - /// Идентификатор файла - /// - public int? IdFile { get; set; } - - /// - /// Идентификатор отметки - /// - public int? IdMark { get; set; } - /// /// Признак удаления /// diff --git a/AsbCloudApp/Services/FileService.cs b/AsbCloudApp/Services/FileService.cs index 04b2c65d..3ba250aa 100644 --- a/AsbCloudApp/Services/FileService.cs +++ b/AsbCloudApp/Services/FileService.cs @@ -6,8 +6,6 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using static Npgsql.PostgresTypes.PostgresCompositeType; -using static System.Net.WebRequestMethods; namespace AsbCloudApp.Services { @@ -41,7 +39,7 @@ namespace AsbCloudApp.Services /// /// /// - public async Task MoveAsync(int idWell, int? idUser, int idCategory, + public async Task MoveAsync(int idWell, int? idUser, int idCategory, string destinationFileName, string srcFilePath, CancellationToken token = default) { destinationFileName = Path.GetFileName(destinationFileName); @@ -61,8 +59,8 @@ namespace AsbCloudApp.Services string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, destinationFileName, fileId); fileStorageRepository.MoveFile(srcFilePath, filePath); - - return await GetInfoAsync(fileId, token); + + return await GetOrDefaultAsync(fileId, token); } /// @@ -75,7 +73,7 @@ namespace AsbCloudApp.Services /// /// /// - public async Task SaveAsync(int idWell, int? idUser, int idCategory, + public async Task SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token) { //save info to db @@ -85,7 +83,7 @@ namespace AsbCloudApp.Services IdAuthor = idUser, IdCategory = idCategory, Name = Path.GetFileName(fileFullName), - Size = fileStream?.Length ?? 0 + Size = fileStream.Length }; var fileId = await fileRepository.InsertAsync(dto, token) @@ -95,26 +93,7 @@ namespace AsbCloudApp.Services string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, fileFullName, fileId); await fileStorageRepository.SaveFileAsync(filePath, fileStream, token); - return await GetInfoAsync(fileId, token); - } - - /// - /// Инфо о файле - /// - /// - /// - /// - public async Task GetInfoAsync(int idFile, - CancellationToken token) - { - var dto = await fileRepository.GetOrDefaultAsync(idFile, token).ConfigureAwait(false); - - var ext = Path.GetExtension(dto.Name); - - var relativePath = GetUrl(dto.IdWell, dto.IdCategory, dto.Id, ext); - var fullPath = Path.GetFullPath(relativePath); - - return dto; + return await GetOrDefaultAsync(fileId, token); } /// @@ -198,15 +177,23 @@ namespace AsbCloudApp.Services return result; } + /// + /// Получить файлы определенной категории + /// + /// + /// + /// + public Task> GetInfosAsync(FileRequest request, CancellationToken token) + => fileRepository.GetInfosAsync(request, token); + /// /// Получить список файлов в контейнере /// /// /// /// - public async Task> GetInfosAsync(FileServiceRequest request, CancellationToken token) - => await fileRepository.GetInfosAsync(request, token) - .ConfigureAwait(false); + public Task> GetInfosPaginatedAsync(FileRequest request, CancellationToken token) + => fileRepository.GetInfosPaginatedAsync(request, token); /// /// Пометить файл как удаленный @@ -214,9 +201,8 @@ namespace AsbCloudApp.Services /// /// /// - public async Task MarkAsDeletedAsync(int idFile, CancellationToken token = default) - => await fileRepository.MarkAsDeletedAsync(idFile, token) - .ConfigureAwait(false); + public Task MarkAsDeletedAsync(int idFile, CancellationToken token = default) + => fileRepository.MarkAsDeletedAsync(idFile, token); /// /// добавить метку на файл @@ -225,9 +211,8 @@ namespace AsbCloudApp.Services /// /// /// - public async Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) - => await fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token) - .ConfigureAwait(false); + public Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) + => fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token); /// /// Получить запись по id @@ -235,9 +220,8 @@ namespace AsbCloudApp.Services /// /// /// - public async Task GetOrDefaultAsync(int id, CancellationToken token) - => await fileRepository.GetOrDefaultAsync(id, token) - .ConfigureAwait(false); + public Task GetOrDefaultAsync(int id, CancellationToken token) + => fileRepository.GetOrDefaultAsync(id, token); /// /// получить инфо о файле по метке @@ -245,9 +229,8 @@ namespace AsbCloudApp.Services /// /// /// - public async Task GetByMarkId(int idMark, CancellationToken token) - => await fileRepository.GetByMarkId(idMark, token) - .ConfigureAwait(false); + public Task GetByMarkId(int idMark, CancellationToken token) + => fileRepository.GetByMarkId(idMark, token); /// /// получить инфо о файле по метке @@ -255,30 +238,8 @@ namespace AsbCloudApp.Services /// /// /// - public async Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) - => await fileRepository.MarkFileMarkAsDeletedAsync(idsMarks, token) - .ConfigureAwait(false); - - /// - /// Получение файлов по скважине - /// - /// - /// - /// - public async Task> GetInfosByWellIdAsync(int idWell, CancellationToken token) - => await fileRepository.GetInfosByWellIdAsync(new FileServiceRequest { IdWell = idWell, IsDeleted = false }, token) - .ConfigureAwait(false); - - /// - /// Получить файлы определенной категории - /// - /// - /// - /// - /// - public async Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token) - => await fileRepository.GetInfosByCategoryAsync(idWell, idCategory, token) - .ConfigureAwait(false); + public Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) + => fileRepository.MarkFileMarkAsDeletedAsync(idsMarks, token); /// /// Удаление всех файлов по скважине помеченных как удаленные @@ -288,8 +249,8 @@ namespace AsbCloudApp.Services /// public async Task DeleteFilesFromDbMarkedDeletionByIdWell(int idWell, CancellationToken token) { - var files = await fileRepository.GetInfosByWellIdAsync( - new FileServiceRequest + var files = await fileRepository.GetInfosAsync( + new FileRequest { IdWell = idWell, IsDeleted = true @@ -306,8 +267,8 @@ namespace AsbCloudApp.Services /// public async Task DeleteFilesNotExistStorage(int idWell, CancellationToken token) { - var files = await fileRepository.GetInfosByWellIdAsync( - new FileServiceRequest + var files = await fileRepository.GetInfosAsync( + new FileRequest { IdWell = idWell }, @@ -324,8 +285,8 @@ namespace AsbCloudApp.Services /// public async Task> GetListFilesNotDisc(int idWell, CancellationToken token) { - var files = await fileRepository.GetInfosByWellIdAsync( - new FileServiceRequest + var files = await fileRepository.GetInfosAsync( + new FileRequest { IdWell = idWell }, @@ -338,9 +299,8 @@ namespace AsbCloudApp.Services /// Получить файловый поток по идентификатору файла /// /// - /// /// - public FileStream GetFileStream(FileInfoDto fileInfo) + public Stream GetFileStream(FileInfoDto fileInfo) { var relativePath = GetUrl(fileInfo); var fileStream = new FileStream(Path.GetFullPath(relativePath), FileMode.Open); diff --git a/AsbCloudDb/EFExtentions.cs b/AsbCloudDb/EFExtentions.cs index f0523294..3cbf3509 100644 --- a/AsbCloudDb/EFExtentions.cs +++ b/AsbCloudDb/EFExtentions.cs @@ -117,6 +117,17 @@ namespace AsbCloudDb } return stat; } + + public static IQueryable SkipTake(this IQueryable query, int? skip, int? take) + { + if (skip > 0) + query = query.Skip((int)skip); + + if (take > 0) + query = query.Take((int)take); + + return query; + } } interface IQueryStringFactory { } diff --git a/AsbCloudInfrastructure/Repository/FileRepository.cs b/AsbCloudInfrastructure/Repository/FileRepository.cs index 6eacf56b..deb43445 100644 --- a/AsbCloudInfrastructure/Repository/FileRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileRepository.cs @@ -1,12 +1,17 @@ using AsbCloudApp.Data; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using AsbCloudDb; using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services; +using DocumentFormat.OpenXml.Drawing.Charts; +using DocumentFormat.OpenXml.Wordprocessing; using Mapster; using Microsoft.EntityFrameworkCore; +using Org.BouncyCastle.Asn1.Ocsp; using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -16,7 +21,7 @@ namespace AsbCloudInfrastructure.Repository #nullable enable public class FileRepository : IFileRepository { - private readonly IQueryable dbSetConfigured; + private readonly IQueryable dbSetConfigured; private readonly IAsbCloudDbContext db; public FileRepository(IAsbCloudDbContext db) @@ -31,10 +36,55 @@ namespace AsbCloudInfrastructure.Repository .Include(f => f.Well); } - public async Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token) + private IQueryable BuildQuery(FileRequest request) { - var entities = await dbSetConfigured - .Where(e => e.IdWell == idWell && e.IdCategory == idCategory && e.IsDeleted == false) + var query = dbSetConfigured + .Where(e => e.IdWell == request.IdWell); + + double timezoneOffsetHours = query.FirstOrDefault() + ?.Well.Timezone.Hours ?? 5d; + + if (request.IdCategory is not null) + query = query.Where(x => x.IdCategory == request.IdCategory); + + if (request.IsDeleted is not null) + query = query.Where(x => x.IsDeleted == request.IsDeleted); + + if (request.CompanyNamePart is not null) + query = query.Where(e => e.Author.Company.Caption.ToLower().Contains(request.CompanyNamePart.ToLower())); + + if (request.FileNamePart is not null) + query = query.Where(e => e.Name.ToLower().Contains(request.FileNamePart.ToLower())); + + if (request.Begin is not null) + { + var beginUtc = request.Begin.Value.ToUtcDateTimeOffset(timezoneOffsetHours); + query = query.Where(e => e.UploadDate >= beginUtc); + } + + if (request.End is not null) + { + var endUtc = request.End.Value.ToUtcDateTimeOffset(timezoneOffsetHours); + query = query.Where(e => e.UploadDate <= endUtc); + } + + if (request?.SortFields?.Any() == true) + { + query = query.SortBy(request.SortFields); + } + else + query = query + .OrderBy(o => o.UploadDate); + + return query; + } + + public async Task> GetInfosAsync(FileRequest request, CancellationToken token) + { + var query = BuildQuery(request); + + var entities = await query + .SkipTake(request.Skip, request.Take) .AsNoTracking() .ToListAsync(token) .ConfigureAwait(false); @@ -43,51 +93,37 @@ namespace AsbCloudInfrastructure.Repository return dtos; } - public async Task> GetInfosAsync(FileServiceRequest request, CancellationToken token = default) + public async Task> GetInfosPaginatedAsync(FileRequest request, CancellationToken token = default) { - var query = GetQuery(request, token); - var firstFile = query.FirstOrDefault(); var skip = request.Skip ?? 0; var take = request.Take ?? 32; - if (firstFile is null) - return new PaginationContainer() - { - Skip = skip, - Take = take, - Count = 0, - }; + var query = BuildQuery(request); - var timezoneOffset = firstFile.Well.Timezone?.Hours ?? 5; - var count = await query.CountAsync(token).ConfigureAwait(false); - var result = new PaginationContainer(count) + var result = new PaginationContainer() { Skip = skip, Take = take, - Count = count, + Count = await query.CountAsync(token), }; - if (count <= skip) + if (result.Count == 0) return result; - query = query.OrderBy(e => e.UploadDate); - - if (skip > 0) - query = query.Skip(skip); - query = query.Take(take); - var entities = await query - .Take(take).AsNoTracking().ToListAsync(token) + .SkipTake(skip, take) + .AsNoTracking() + .ToListAsync(token) .ConfigureAwait(false); - var dtos = entities.Select(e => Convert(e, timezoneOffset)); - result.Items.AddRange(dtos); + result.Items = entities.Select(e => Convert(e)).ToList(); + return result; } public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) { - var result = new List(); + var result = Enumerable.Empty(); var entities = await dbSetConfigured .AsNoTracking() @@ -95,14 +131,8 @@ namespace AsbCloudInfrastructure.Repository .ToListAsync(token) .ConfigureAwait(false); - foreach (var entity in entities) - { - if (entity is null) - { - throw new FileNotFoundException($"fileId:{entity.Id} not found"); - } - result.Add(Convert(entity)); - } + if (entities is not null) + result = entities.Select(entity => Convert(entity)); return result; } @@ -140,7 +170,7 @@ namespace AsbCloudInfrastructure.Repository .FirstOrDefaultAsync(f => f.FileMarks.Any(m => m.Id == idMark), token) .ConfigureAwait(false); - FileInfoDto dto = Convert(entity); + FileInfoDto dto = Convert(entity!); return dto; } @@ -178,26 +208,13 @@ namespace AsbCloudInfrastructure.Repository return await db.SaveChangesAsync(token); } - public async Task> GetInfosByWellIdAsync(FileServiceRequest request, CancellationToken token) - { - var query = GetQuery(request, token); - - var entities = await query - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); - - var dtos = entities.Select(e => Convert(e)); - return dtos; - } - public async Task> GetAllAsync(CancellationToken token) => await dbSetConfigured.AsNoTracking() .Select(x => Convert(x)) .ToListAsync(token) .ConfigureAwait(false); - public async Task GetOrDefaultAsync(int id, CancellationToken token) + public async Task GetOrDefaultAsync(int id, CancellationToken token) { var entity = await dbSetConfigured .AsNoTracking() @@ -205,24 +222,20 @@ namespace AsbCloudInfrastructure.Repository .ConfigureAwait(false); if (entity is null) - { - throw new FileNotFoundException($"fileId:{id} not found"); - } + return null; var dto = Convert(entity); return dto; } - public FileInfoDto GetOrDefault(int id) + public FileInfoDto? GetOrDefault(int id) { var entity = dbSetConfigured .AsNoTracking() .FirstOrDefault(f => f.Id == id); if (entity is null) - { - throw new FileNotFoundException($"fileId:{id} not found"); - } + return null; var dto = Convert(entity); return dto; @@ -230,7 +243,7 @@ namespace AsbCloudInfrastructure.Repository public async Task InsertAsync(FileInfoDto newItem, CancellationToken token) { - var fileInfo = new AsbCloudDb.Model.FileInfo() + var fileInfo = new FileInfo() { IdWell = newItem.IdWell, IdAuthor = newItem.IdAuthor, @@ -261,50 +274,13 @@ namespace AsbCloudInfrastructure.Repository throw new NotImplementedException(); } - private IQueryable GetQuery(FileServiceRequest request, CancellationToken token = default) - { - var query = dbSetConfigured - .Where(e => e.IdWell == request.IdWell && - e.IdCategory == request.IdCategory); - - if (request.IsDeleted is not null) - query = query.Where(x => x.IsDeleted == request.IsDeleted); - - if (request.CompanyName is not null) - query = query.Where(e => (e.Author == null) || - (e.Author.Company == null) || - e.Author.Company.Caption.Contains(request.CompanyName)); - - if (request.FileName is not null) - query = query.Where(e => e.Name.ToLower().Contains(request.FileName.ToLower())); - - var firstFile = query.FirstOrDefault(); - if (firstFile is null) - return Enumerable.Empty().AsQueryable(); - - var timezoneOffset = firstFile.Well.Timezone?.Hours ?? 5; - if (request.Begin is not null) - { - var beginUtc = request.Begin.Value.ToUtcDateTimeOffset(timezoneOffset); - query = query.Where(e => e.UploadDate >= beginUtc); - } - - if (request.End is not null) - { - var endUtc = request.End.Value.ToUtcDateTimeOffset(timezoneOffset); - query = query.Where(e => e.UploadDate <= endUtc); - } - - return query; - } - - private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity) + private static FileInfoDto Convert(FileInfo entity) { var timezoneOffset = entity.Well.Timezone?.Hours ?? 5; return Convert(entity, timezoneOffset); } - private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity, double timezoneOffset) + private static FileInfoDto Convert(FileInfo entity, double timezoneOffset) { var dto = entity.Adapt(); dto.UploadDate = entity.UploadDate.ToRemoteDateTime(timezoneOffset); diff --git a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs index 0d7a2cf8..8bd61e2f 100644 --- a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs @@ -1,13 +1,10 @@ using AsbCloudApp.Data; -using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; -using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using FileInfo = System.IO.FileInfo; namespace AsbCloudInfrastructure.Repository { @@ -102,10 +99,8 @@ namespace AsbCloudInfrastructure.Repository var allFilesPath = GetFilesPath(idWell); foreach (var filePath in allFilesPath) - { - int.TryParse(Path.GetFileNameWithoutExtension(filePath), out int idFile); - result.Add(idFile); - } + if(int.TryParse(Path.GetFileNameWithoutExtension(filePath), out int idFile)) + result.Add(idFile); return result; } @@ -118,7 +113,8 @@ namespace AsbCloudInfrastructure.Repository private static void CreateDirectory(string filePath) { - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); + var directoryName = Path.GetDirectoryName(filePath)!; + Directory.CreateDirectory(directoryName); } } #nullable disable diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index ca0827b0..e926a886 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -282,7 +282,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram fileMarkDto.IdMarkType != idMarkTypeReject) throw new ArgumentInvalidException($"В этом методе допустимы только отметки о принятии или отклонении.", nameof(fileMarkDto)); - var fileInfo = await fileService.GetInfoAsync(fileMarkDto.IdFile, token) + var fileInfo = await fileService.GetOrDefaultAsync(fileMarkDto.IdFile, token) .ConfigureAwait(false); if (fileInfo is null) @@ -357,7 +357,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram private async Task NotifyPublisherOnFullAccepAsync(FileMarkDto fileMark, CancellationToken token) { - var file = await fileService.GetInfoAsync(fileMark.IdFile, token); + var file = await fileService.GetOrDefaultAsync(fileMark.IdFile, token); var well = await wellService.GetOrDefaultAsync(file.IdWell, token); var user = file.Author; var factory = new DrillingMailBodyFactory(configuration); @@ -369,7 +369,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram private async Task NotifyPublisherOnRejectAsync(FileMarkDto fileMark, CancellationToken token) { - var file = await fileService.GetInfoAsync(fileMark.IdFile, token); + var file = await fileService.GetOrDefaultAsync(fileMark.IdFile, token); var well = await wellService.GetOrDefaultAsync(file.IdWell, token); var user = file.Author; var factory = new DrillingMailBodyFactory(configuration); @@ -473,7 +473,6 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram var well = await wellService.GetOrDefaultAsync(idWell, token); var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.xlsx"; var tempResultFilePath = Path.Combine(Path.GetTempPath(), "drillingProgram", resultFileName); - var mailService = new EmailService(backgroundWorker, configuration); async Task funcProgramMake(string id, CancellationToken token) { var contextOptions = new DbContextOptionsBuilder() diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs index 62d82522..4d44f38c 100644 --- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs +++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs @@ -1,5 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Exceptions; +using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Repository; @@ -96,7 +97,7 @@ namespace AsbCloudInfrastructure.Services .Select(g => g.Key); var files = (await fileService - .GetInfosByWellIdAsync(idWell, token) + .GetInfosAsync(new FileRequest { IdWell = idWell}, token) .ConfigureAwait(false)) .Where(f => categoriesIds.Contains(f.IdCategory)) .ToArray(); @@ -162,7 +163,12 @@ namespace AsbCloudInfrastructure.Services public async Task GetFilesHistoryByIdCategory(int idWell, int idCategory, CancellationToken token) { - var files = await fileService.GetInfosByCategoryAsync(idWell, idCategory, token).ConfigureAwait(false); + var request = new FileRequest + { + IdWell = idWell, + IdCategory = idCategory, + }; + var files = await fileService.GetInfosAsync(request, token).ConfigureAwait(false); return new WellFinalDocumentsHistoryDto { IdWell = idWell, diff --git a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs index fa72df35..a1e275b9 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs @@ -220,7 +220,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests { ConfigureNotApproved(); fileServiceMock - .Setup(s => s.GetInfoAsync(It.IsAny(), It.IsAny())) + .Setup(s => s.GetOrDefaultAsync(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(file1002.Adapt())); fileServiceMock @@ -251,7 +251,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests { ConfigureNotApproved(); fileServiceMock - .Setup(s => s.GetInfoAsync(It.IsAny(), It.IsAny())) + .Setup(s => s.GetOrDefaultAsync(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(file1002.Adapt())); fileServiceMock diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs index 4f83e996..698f83cd 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs @@ -109,18 +109,12 @@ namespace AsbCloudWebApi.Tests.ServicesTests return Task.FromResult(result); }); - repositoryMock.Setup(x => x.GetInfosByWellIdAsync(It.IsAny(), It.IsAny())) - .Returns((FileServiceRequest request, CancellationToken token) => { + repositoryMock.Setup(x => x.GetInfosAsync(It.IsAny(), It.IsAny())) + .Returns((FileRequest request, CancellationToken token) => { var data = Files.Where(x => x.IdWell == request.IdWell); return Task.FromResult(data); }); - repositoryMock.Setup(x => x.GetInfosByCategoryAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns((int idWell, int idCategory, CancellationToken token) => { - var data = Files.Where(x => x.IdWell == idWell && x.IdCategory == idCategory); - return Task.FromResult(data); - }); - repositoryMock.Setup(x => x.CreateFileMarkAsync(It.IsAny(), It.IsAny(), It.IsAny())) .Returns((FileMarkDto dto, int idUser, CancellationToken token) => { dto.Id = FileMarks.Max(x => x.Id) + 1; @@ -149,9 +143,9 @@ namespace AsbCloudWebApi.Tests.ServicesTests } [Fact] - public async Task GetInfoAsync_returns_FileInfo() + public async Task GetOrDefaultAsync_returns_FileInfo() { - var data = await fileService.GetInfoAsync(1742, CancellationToken.None); + var data = await fileService.GetOrDefaultAsync(1742, CancellationToken.None); Assert.NotNull(data); } @@ -191,20 +185,6 @@ namespace AsbCloudWebApi.Tests.ServicesTests Assert.True(result > 0); } - [Fact] - public async Task GetInfosByWellIdAsync_returns_FileInfo() - { - var data = await fileService.GetInfosByWellIdAsync(90, CancellationToken.None); - Assert.NotNull(data); - } - - [Fact] - public async Task GetInfosByCategoryAsync_returns_FileInfo() - { - var data = await fileService.GetInfosByCategoryAsync(90, 10040, CancellationToken.None); - Assert.NotNull(data); - } - [Fact] public async Task CreateFileMarkAsync() { diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index 7d4e395b..d4dfad33 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -7,8 +7,7 @@ using Microsoft.AspNetCore.Mvc; using System.IO; using System.Threading; using System.Threading.Tasks; -using System.Text; -using static System.Net.WebRequestMethods; +using AsbCloudDb.Model; namespace AsbCloudWebApi.Controllers { @@ -79,19 +78,19 @@ namespace AsbCloudWebApi.Controllers [Permission] [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] public async Task GetFilesInfoAsync( - [FromQuery] FileServiceRequest request, + [FromQuery] FileRequest request, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); - if (request.IdWell is null || request.IdCategory is null || idCompany is null) + if (request.IdCategory is null || idCompany is null) return Forbid(); if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, - request.IdWell.Value, token).ConfigureAwait(false)) + request.IdWell, token).ConfigureAwait(false)) return Forbid(); - var filesInfo = await fileService.GetInfosAsync(request, token).ConfigureAwait(false); + var filesInfo = await fileService.GetInfosPaginatedAsync(request, token).ConfigureAwait(false); return Ok(filesInfo); } @@ -100,36 +99,33 @@ namespace AsbCloudWebApi.Controllers /// Возвращает файл с диска на сервере /// /// id скважины - /// id запрашиваемого файла + /// id запрашиваемого файла /// Токен отмены задачи /// Запрашиваемый файл [HttpGet] - [Route("{fileId}")] + [Route("{idFile}")] [Permission] [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] public async Task GetFileAsync([FromRoute] int idWell, - int fileId, CancellationToken token = default) + int idFile, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); if (idCompany is null) return Forbid(); + var fileInfo = await fileService.GetOrDefaultAsync(idFile, token); + + if (fileInfo is null) + return NotFound(idFile); + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) + fileInfo.IdWell, token).ConfigureAwait(false)) return Forbid(); - try - { - var fileInfo = await fileService.GetInfoAsync(fileId, token); - var fileStream = fileService.GetFileStream(fileInfo); + var fileStream = fileService.GetFileStream(fileInfo); - return File(fileStream, "application/octet-stream", fileInfo.Name); - } - catch (FileNotFoundException ex) - { - return NotFound(ex.FileName); - } + return File(fileStream, "application/octet-stream", fileInfo.Name); } /// @@ -151,13 +147,16 @@ namespace AsbCloudWebApi.Controllers int? idCompany = User.GetCompanyId(); - if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + if (idUser is null || idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); - var file = await fileService.GetInfoAsync((int)idFile, token); + var fileInfo = await fileService.GetOrDefaultAsync(idFile, token); - if (!userService.HasPermission((int)idUser, $"File.edit{file.IdCategory}")) + if (fileInfo is null) + return NotFound(idFile); + + if (!userService.HasPermission((int)idUser, $"File.edit{fileInfo?.IdCategory}")) return Forbid(); var result = await fileService.MarkAsDeletedAsync(idFile, token);