forked from ddrilling/AsbCloudServer
Merge branch 'dev' into feature/integration_tests
This commit is contained in:
commit
b34b7c7206
69
AsbCloudApp/Data/ProcessMaps/WellSectionPlanDto.cs
Normal file
69
AsbCloudApp/Data/ProcessMaps/WellSectionPlanDto.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Data.ProcessMaps;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Секция скважины - план
|
||||||
|
/// </summary>
|
||||||
|
public class WellSectionPlanDto : ItemInfoDto,
|
||||||
|
IId,
|
||||||
|
IWellRelated,
|
||||||
|
IValidatableObject
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int IdWell { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Тип секции
|
||||||
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "Поле обязательно для заполнение")]
|
||||||
|
[Range(1, int.MaxValue)]
|
||||||
|
public int IdSectionType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Начальная глубина бурения, м
|
||||||
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "Поле обязательно для заполнение")]
|
||||||
|
[Range(0, 10000, ErrorMessage = "Допустимое значение от 0 до 10000")]
|
||||||
|
public double DepthStart { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Конечная глубина бурения, м
|
||||||
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "Поле обязательно для заполнение")]
|
||||||
|
[Range(0, 10000, ErrorMessage = "Допустимое значение от 0 до 10000")]
|
||||||
|
public double DepthEnd { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Внешний диаметр
|
||||||
|
/// </summary>
|
||||||
|
[Range(1, 10000, ErrorMessage = "Допустимое значение от 1 до 10000")]
|
||||||
|
public double? OuterDiameter { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Внутренний диаметр
|
||||||
|
/// </summary>
|
||||||
|
[Range(1, 10000, ErrorMessage = "Допустимое значение от 1 до 10000")]
|
||||||
|
public double? InnerDiameter { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||||
|
{
|
||||||
|
if (!OuterDiameter.HasValue && !InnerDiameter.HasValue)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
if (!OuterDiameter.HasValue)
|
||||||
|
yield return new ValidationResult("Поле обязательно для заполнение", new[] { nameof(OuterDiameter) });
|
||||||
|
|
||||||
|
if (!InnerDiameter.HasValue)
|
||||||
|
yield return new ValidationResult("Поле обязательно для заполнение", new[] { nameof(InnerDiameter) });
|
||||||
|
|
||||||
|
if (OuterDiameter <= InnerDiameter)
|
||||||
|
yield return new ValidationResult("Внешний диаметр не должен быть больше или равен внутреннему",
|
||||||
|
new[] { nameof(OuterDiameter) });
|
||||||
|
}
|
||||||
|
}
|
27
AsbCloudApp/Data/ValidationResultDto.cs
Normal file
27
AsbCloudApp/Data/ValidationResultDto.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Data;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Результат валидации объекта
|
||||||
|
/// </summary>
|
||||||
|
public class ValidationResultDto<T>
|
||||||
|
where T : class
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Флаг валидности
|
||||||
|
/// </summary>
|
||||||
|
public bool IsValid => !Warnings.Any();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Объект валидации
|
||||||
|
/// </summary>
|
||||||
|
public T Item { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Предупреждения
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<ValidationResult> Warnings { get; set; } = Enumerable.Empty<ValidationResult>();
|
||||||
|
}
|
@ -105,5 +105,14 @@ namespace AsbCloudApp.Repositories
|
|||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IEnumerable<SectionByOperationsDto>> GetSectionsAsync(IEnumerable<int> idsWells, CancellationToken token);
|
Task<IEnumerable<SectionByOperationsDto>> GetSectionsAsync(IEnumerable<int> idsWells, CancellationToken token);
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить диапазон дат выполнения операций
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell"></param>
|
||||||
|
/// <param name="idType"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
}
|
}
|
22
AsbCloudApp/Repositories/IWellSectionPlanRepository.cs
Normal file
22
AsbCloudApp/Repositories/IWellSectionPlanRepository.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.ProcessMaps;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Repositories;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Секция скважины - план
|
||||||
|
/// </summary>
|
||||||
|
public interface IWellSectionPlanRepository : IRepositoryWellRelated<WellSectionPlanDto>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Получить типы секций
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<WellSectionTypeDto>> GetWellSectionTypesAsync(int idWell, CancellationToken cancellationToken);
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.SAUB;
|
using AsbCloudApp.Data.SAUB;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -67,5 +70,6 @@ namespace AsbCloudApp.Services
|
|||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> MergeAsync(int from, int to, CancellationToken token);
|
Task<int> MergeAsync(int from, int to, CancellationToken token);
|
||||||
|
Task<Stream> GetTelemetriesInfoByLastData(DateTimeOffset from, CancellationToken token);
|
||||||
}
|
}
|
||||||
}
|
}
|
22
AsbCloudApp/Services/ProcessMaps/IProcessMapPlanService.cs
Normal file
22
AsbCloudApp/Services/ProcessMaps/IProcessMapPlanService.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.ProcessMaps;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Services.ProcessMaps;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// РТК
|
||||||
|
/// </summary>
|
||||||
|
public interface IProcessMapPlanService<T>
|
||||||
|
where T : ProcessMapPlanBaseDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Получение РТК план по скважине
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<ValidationResultDto<T>>> GetAsync(int idWell, CancellationToken cancellationToken);
|
||||||
|
}
|
9110
AsbCloudDb/Migrations/20231204094830_Add_WellSectionPlan.Designer.cs
generated
Normal file
9110
AsbCloudDb/Migrations/20231204094830_Add_WellSectionPlan.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
101
AsbCloudDb/Migrations/20231204094830_Add_WellSectionPlan.cs
Normal file
101
AsbCloudDb/Migrations/20231204094830_Add_WellSectionPlan.cs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace AsbCloudDb.Migrations
|
||||||
|
{
|
||||||
|
public partial class Add_WellSectionPlan : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "t_well_section_plan",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
id_well = table.Column<int>(type: "integer", nullable: false, comment: "Id скважины"),
|
||||||
|
id_section_type = table.Column<int>(type: "integer", nullable: false, comment: "Тип секции"),
|
||||||
|
id_user = table.Column<int>(type: "integer", nullable: false, comment: "Id пользователя"),
|
||||||
|
date_last_update = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true, comment: "Дата последнего обновления"),
|
||||||
|
depth_start = table.Column<double>(type: "double precision", nullable: false, comment: "Начальная глубина бурения, м"),
|
||||||
|
depth_end = table.Column<double>(type: "double precision", nullable: false, comment: "Конечная глубина бурения, м"),
|
||||||
|
outer_diameter = table.Column<double>(type: "double precision", nullable: true, comment: "Внешний диаметр"),
|
||||||
|
inner_diameter = table.Column<double>(type: "double precision", nullable: true, comment: "Внутренний диаметр")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_t_well_section_plan", x => x.id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_t_well_section_plan_t_well_id_well",
|
||||||
|
column: x => x.id_well,
|
||||||
|
principalTable: "t_well",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_t_well_section_plan_t_well_section_type_id_section_type",
|
||||||
|
column: x => x.id_section_type,
|
||||||
|
principalTable: "t_well_section_type",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "t_permission",
|
||||||
|
columns: new[] { "id", "description", "name" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ 530, "Разрешение на редактирование плановой конструкции скважины", "WellSectionPlan.edit" },
|
||||||
|
{ 531, "Разрешение на удаление плановой конструкции скважины", "WellSectionPlan.delete" }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "t_relation_user_role_permission",
|
||||||
|
columns: new[] { "id_permission", "id_user_role" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ 530, 1 },
|
||||||
|
{ 531, 1 }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_t_well_section_plan_id_section_type",
|
||||||
|
table: "t_well_section_plan",
|
||||||
|
column: "id_section_type");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_t_well_section_plan_id_well_id_section_type",
|
||||||
|
table: "t_well_section_plan",
|
||||||
|
columns: new[] { "id_well", "id_section_type" },
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "t_well_section_plan");
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "t_relation_user_role_permission",
|
||||||
|
keyColumns: new[] { "id_permission", "id_user_role" },
|
||||||
|
keyValues: new object[] { 530, 1 });
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "t_relation_user_role_permission",
|
||||||
|
keyColumns: new[] { "id_permission", "id_user_role" },
|
||||||
|
keyValues: new object[] { 531, 1 });
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "t_permission",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 530);
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "t_permission",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 531);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2449,6 +2449,18 @@ namespace AsbCloudDb.Migrations
|
|||||||
Id = 528,
|
Id = 528,
|
||||||
Description = "Разрешение на удаление контакта",
|
Description = "Разрешение на удаление контакта",
|
||||||
Name = "WellContact.delete"
|
Name = "WellContact.delete"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = 530,
|
||||||
|
Description = "Разрешение на редактирование плановой конструкции скважины",
|
||||||
|
Name = "WellSectionPlan.edit"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = 531,
|
||||||
|
Description = "Разрешение на удаление плановой конструкции скважины",
|
||||||
|
Name = "WellSectionPlan.delete"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -4045,6 +4057,16 @@ namespace AsbCloudDb.Migrations
|
|||||||
{
|
{
|
||||||
IdUserRole = 1,
|
IdUserRole = 1,
|
||||||
IdPermission = 528
|
IdPermission = 528
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
IdUserRole = 1,
|
||||||
|
IdPermission = 530
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
IdUserRole = 1,
|
||||||
|
IdPermission = 531
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -7072,6 +7094,65 @@ namespace AsbCloudDb.Migrations
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("AsbCloudDb.Model.WellSections.WellSectionPlan", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<double>("DepthEnd")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("depth_end")
|
||||||
|
.HasComment("Конечная глубина бурения, м");
|
||||||
|
|
||||||
|
b.Property<double>("DepthStart")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("depth_start")
|
||||||
|
.HasComment("Начальная глубина бурения, м");
|
||||||
|
|
||||||
|
b.Property<int>("IdSectionType")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_section_type")
|
||||||
|
.HasComment("Тип секции");
|
||||||
|
|
||||||
|
b.Property<int>("IdUser")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_user")
|
||||||
|
.HasComment("Id пользователя");
|
||||||
|
|
||||||
|
b.Property<int>("IdWell")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_well")
|
||||||
|
.HasComment("Id скважины");
|
||||||
|
|
||||||
|
b.Property<double?>("InnerDiameter")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("inner_diameter")
|
||||||
|
.HasComment("Внутренний диаметр");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LastUpdateDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("date_last_update")
|
||||||
|
.HasComment("Дата последнего обновления");
|
||||||
|
|
||||||
|
b.Property<double?>("OuterDiameter")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("outer_diameter")
|
||||||
|
.HasComment("Внешний диаметр");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IdSectionType");
|
||||||
|
|
||||||
|
b.HasIndex("IdWell", "IdSectionType")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("t_well_section_plan");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("AsbCloudDb.Model.WellSectionType", b =>
|
modelBuilder.Entity("AsbCloudDb.Model.WellSectionType", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -8870,6 +8951,25 @@ namespace AsbCloudDb.Migrations
|
|||||||
b.Navigation("Parent");
|
b.Navigation("Parent");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("AsbCloudDb.Model.WellSections.WellSectionPlan", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("AsbCloudDb.Model.WellSectionType", "SectionType")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("IdSectionType")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("AsbCloudDb.Model.Well", "Well")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("IdWell")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("SectionType");
|
||||||
|
|
||||||
|
b.Navigation("Well");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("AsbCloudDb.Model.WITS.Record1", b =>
|
modelBuilder.Entity("AsbCloudDb.Model.WITS.Record1", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry")
|
b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry")
|
||||||
|
@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
|||||||
using AsbCloudDb.Model.DailyReports;
|
using AsbCloudDb.Model.DailyReports;
|
||||||
using AsbCloudDb.Model.Manuals;
|
using AsbCloudDb.Model.Manuals;
|
||||||
using AsbCloudDb.Model.ProcessMaps;
|
using AsbCloudDb.Model.ProcessMaps;
|
||||||
|
using AsbCloudDb.Model.WellSections;
|
||||||
using AsbCloudDb.Model.Trajectory;
|
using AsbCloudDb.Model.Trajectory;
|
||||||
|
|
||||||
namespace AsbCloudDb.Model
|
namespace AsbCloudDb.Model
|
||||||
@ -62,6 +63,8 @@ namespace AsbCloudDb.Model
|
|||||||
|
|
||||||
public virtual DbSet<TelemetryWirelineRunOut> TelemetryWirelineRunOut => Set<TelemetryWirelineRunOut>();
|
public virtual DbSet<TelemetryWirelineRunOut> TelemetryWirelineRunOut => Set<TelemetryWirelineRunOut>();
|
||||||
public virtual DbSet<TrajectoryFact> TrajectoriesFact => Set<TrajectoryFact>();
|
public virtual DbSet<TrajectoryFact> TrajectoriesFact => Set<TrajectoryFact>();
|
||||||
|
|
||||||
|
public virtual DbSet<WellSectionPlan> WellSectionsPlan => Set<WellSectionPlan>();
|
||||||
|
|
||||||
// GTR WITS
|
// GTR WITS
|
||||||
public DbSet<WitsItemFloat> WitsItemFloat => Set<WitsItemFloat>();
|
public DbSet<WitsItemFloat> WitsItemFloat => Set<WitsItemFloat>();
|
||||||
@ -435,6 +438,10 @@ namespace AsbCloudDb.Model
|
|||||||
.HasJsonConversion();
|
.HasJsonConversion();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<WellSectionPlan>()
|
||||||
|
.HasIndex(w => new { w.IdWell, w.IdSectionType })
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
DefaultData.DefaultContextData.Fill(modelBuilder);
|
DefaultData.DefaultContextData.Fill(modelBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,9 +158,12 @@
|
|||||||
|
|
||||||
new (){ Id = 525, Name = "ProcessMap.editCompletedWell", Description = "Разрешение на редактирование РТК у завершенной скважины"},
|
new (){ Id = 525, Name = "ProcessMap.editCompletedWell", Description = "Разрешение на редактирование РТК у завершенной скважины"},
|
||||||
new (){ Id = 526, Name = "WellOperation.editCompletedWell", Description = "Разрешение на редактирование операций у завершенной скважины"},
|
new (){ Id = 526, Name = "WellOperation.editCompletedWell", Description = "Разрешение на редактирование операций у завершенной скважины"},
|
||||||
|
|
||||||
new() { Id = 527, Name = "Manual.delete", Description = "Разрешение на удаление инструкций"},
|
new() { Id = 527, Name = "Manual.delete", Description = "Разрешение на удаление инструкций" },
|
||||||
new (){ Id = 528, Name="WellContact.delete", Description="Разрешение на удаление контакта"}
|
new() { Id = 528, Name = "WellContact.delete", Description = "Разрешение на удаление контакта" },
|
||||||
|
|
||||||
|
new() { Id = 530, Name = "WellSectionPlan.edit", Description = "Разрешение на редактирование плановой конструкции скважины"},
|
||||||
|
new() { Id = 531, Name = "WellSectionPlan.delete", Description = "Разрешение на удаление плановой конструкции скважины"}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ using System.Threading.Tasks;
|
|||||||
using AsbCloudDb.Model.DailyReports;
|
using AsbCloudDb.Model.DailyReports;
|
||||||
using AsbCloudDb.Model.Manuals;
|
using AsbCloudDb.Model.Manuals;
|
||||||
using AsbCloudDb.Model.ProcessMaps;
|
using AsbCloudDb.Model.ProcessMaps;
|
||||||
|
using AsbCloudDb.Model.WellSections;
|
||||||
using AsbCloudDb.Model.Trajectory;
|
using AsbCloudDb.Model.Trajectory;
|
||||||
|
|
||||||
namespace AsbCloudDb.Model
|
namespace AsbCloudDb.Model
|
||||||
@ -80,6 +81,7 @@ namespace AsbCloudDb.Model
|
|||||||
DbSet<Contact> Contacts { get; }
|
DbSet<Contact> Contacts { get; }
|
||||||
DbSet<DrillTest> DrillTests { get; }
|
DbSet<DrillTest> DrillTests { get; }
|
||||||
DbSet<TrajectoryFact> TrajectoriesFact { get; }
|
DbSet<TrajectoryFact> TrajectoriesFact { get; }
|
||||||
|
DbSet<WellSectionPlan> WellSectionsPlan { get; }
|
||||||
DatabaseFacade Database { get; }
|
DatabaseFacade Database { get; }
|
||||||
|
|
||||||
Task<int> RefreshMaterializedViewAsync(string mwName, CancellationToken token);
|
Task<int> RefreshMaterializedViewAsync(string mwName, CancellationToken token);
|
||||||
|
45
AsbCloudDb/Model/WellSections/WellSectionPlan.cs
Normal file
45
AsbCloudDb/Model/WellSections/WellSectionPlan.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace AsbCloudDb.Model.WellSections;
|
||||||
|
|
||||||
|
[Table("t_well_section_plan")]
|
||||||
|
public class WellSectionPlan : IId,
|
||||||
|
IWellRelated
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
[Column("id")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Column("id_well"), Comment("Id скважины")]
|
||||||
|
public int IdWell { get; set; }
|
||||||
|
|
||||||
|
[Column("id_section_type"), Comment("Тип секции")]
|
||||||
|
public int IdSectionType { get; set; }
|
||||||
|
|
||||||
|
[Column("id_user"), Comment("Id пользователя")]
|
||||||
|
public int IdUser { get; set; }
|
||||||
|
|
||||||
|
[Column("date_last_update", TypeName = "timestamp with time zone"), Comment("Дата последнего обновления")]
|
||||||
|
public DateTimeOffset? LastUpdateDate { get; set; }
|
||||||
|
|
||||||
|
[Column("depth_start"), Comment("Начальная глубина бурения, м")]
|
||||||
|
public double DepthStart { get; set; }
|
||||||
|
|
||||||
|
[Column("depth_end"), Comment("Конечная глубина бурения, м")]
|
||||||
|
public double DepthEnd { get; set; }
|
||||||
|
|
||||||
|
[Column("outer_diameter"), Comment("Внешний диаметр")]
|
||||||
|
public double? OuterDiameter { get; set; }
|
||||||
|
|
||||||
|
[Column("inner_diameter"), Comment("Внутренний диаметр")]
|
||||||
|
public double? InnerDiameter { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey(nameof(IdWell))]
|
||||||
|
public virtual Well Well { get; set; } = null!;
|
||||||
|
|
||||||
|
[ForeignKey(nameof(IdSectionType))]
|
||||||
|
public virtual WellSectionType SectionType { get; set; } = null!;
|
||||||
|
}
|
@ -56,6 +56,7 @@
|
|||||||
<PackageReference Include="ClosedXML" Version="0.96.0" />
|
<PackageReference Include="ClosedXML" Version="0.96.0" />
|
||||||
<PackageReference Include="itext7" Version="7.2.3" />
|
<PackageReference Include="itext7" Version="7.2.3" />
|
||||||
<PackageReference Include="Mapster" Version="7.3.0" />
|
<PackageReference Include="Mapster" Version="7.3.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
|
||||||
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.23.1" />
|
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.23.1" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.23.1" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.23.1" />
|
||||||
|
@ -44,6 +44,8 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
|
using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
|
||||||
using AsbCloudApp.Services.DailyReport;
|
using AsbCloudApp.Services.DailyReport;
|
||||||
using AsbCloudDb.Model.DailyReports.Blocks.TimeBalance;
|
using AsbCloudDb.Model.DailyReports.Blocks.TimeBalance;
|
||||||
|
using AsbCloudDb.Model.WellSections;
|
||||||
|
using AsbCloudInfrastructure.Services.ProcessMaps;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure
|
namespace AsbCloudInfrastructure
|
||||||
{
|
{
|
||||||
@ -220,6 +222,7 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddTransient<IProcessMapPlanImportService, ProcessMapPlanImportWellDrillingService>();
|
services.AddTransient<IProcessMapPlanImportService, ProcessMapPlanImportWellDrillingService>();
|
||||||
services.AddTransient<WellInfoService>();
|
services.AddTransient<WellInfoService>();
|
||||||
services.AddTransient<IHelpPageService, HelpPageService>();
|
services.AddTransient<IHelpPageService, HelpPageService>();
|
||||||
|
services.AddTransient<IScheduleReportService, ScheduleReportService>();
|
||||||
|
|
||||||
services.AddTransient<TrajectoryService>();
|
services.AddTransient<TrajectoryService>();
|
||||||
|
|
||||||
@ -315,6 +318,13 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddTransient<IDailyReportRepository, DailyReportRepository>();
|
services.AddTransient<IDailyReportRepository, DailyReportRepository>();
|
||||||
services.AddTransient<IDailyReportExportService, DailyReportExportService>();
|
services.AddTransient<IDailyReportExportService, DailyReportExportService>();
|
||||||
|
|
||||||
|
services.AddTransient<IRepositoryWellRelated<WellSectionPlanDto>, CrudWellRelatedRepositoryBase<WellSectionPlanDto, WellSectionPlan>>();
|
||||||
|
|
||||||
|
services.AddTransient<IProcessMapPlanService<ProcessMapPlanWellDrillingDto>, ProcessMapPlanService<ProcessMapPlanWellDrillingDto>>();
|
||||||
|
services.AddTransient<IProcessMapPlanService<ProcessMapPlanWellReamDto>, ProcessMapPlanService<ProcessMapPlanWellReamDto>>();
|
||||||
|
|
||||||
|
services.AddTransient<IWellSectionPlanRepository, WellSectionPlanRepository>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,8 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
{
|
{
|
||||||
var entities = await GetQuery()
|
var entities = await GetQuery()
|
||||||
.Where(e => e.IdWell == idWell)
|
.Where(e => e.IdWell == idWell)
|
||||||
.ToListAsync(token);
|
.AsNoTracking()
|
||||||
|
.ToArrayAsync(token);
|
||||||
var dtos = entities.Select(Convert).ToList();
|
var dtos = entities.Select(Convert).ToList();
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
@ -36,7 +37,8 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
|
|
||||||
var entities = await GetQuery()
|
var entities = await GetQuery()
|
||||||
.Where(e => idsWells.Contains(e.IdWell))
|
.Where(e => idsWells.Contains(e.IdWell))
|
||||||
.ToListAsync(token);
|
.AsNoTracking()
|
||||||
|
.ToArrayAsync(token);
|
||||||
var dtos = entities.Select(Convert).ToList();
|
var dtos = entities.Select(Convert).ToList();
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
@ -184,6 +184,20 @@ public class WellOperationRepository : IWellOperationRepository
|
|||||||
return sections;
|
return sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var query = db.WellOperations.Where(o => o.IdWell == idWell && o.IdType == idType);
|
||||||
|
|
||||||
|
if (!await query.AnyAsync(cancellationToken))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new DatesRangeDto
|
||||||
|
{
|
||||||
|
From = (await query.MinAsync(o => o.DateStart, cancellationToken)).Date,
|
||||||
|
To = (await query.MaxAsync(o => o.DateStart, cancellationToken)).Date
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public DateTimeOffset? FirstOperationDate(int idWell)
|
public DateTimeOffset? FirstOperationDate(int idWell)
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.ProcessMaps;
|
||||||
|
using AsbCloudApp.Exceptions;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudDb.Model.WellSections;
|
||||||
|
using Mapster;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Npgsql;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Repository;
|
||||||
|
|
||||||
|
public class WellSectionPlanRepository : CrudWellRelatedRepositoryBase<WellSectionPlanDto, WellSectionPlan>,
|
||||||
|
IWellSectionPlanRepository
|
||||||
|
{
|
||||||
|
public WellSectionPlanRepository(IAsbCloudDbContext context)
|
||||||
|
: base(context, query => query.Include(w => w.SectionType))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> InsertAsync(WellSectionPlanDto item, CancellationToken token)
|
||||||
|
{
|
||||||
|
var id = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
id = await base.InsertAsync(item, token);
|
||||||
|
}
|
||||||
|
catch (DbUpdateException ex)
|
||||||
|
{
|
||||||
|
if (ex.InnerException is PostgresException pgException)
|
||||||
|
HandlePostgresException(pgException, item);
|
||||||
|
else
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> UpdateAsync(WellSectionPlanDto item, CancellationToken token)
|
||||||
|
{
|
||||||
|
var id = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
id = await base.UpdateAsync(item, token);
|
||||||
|
}
|
||||||
|
catch (DbUpdateException ex)
|
||||||
|
{
|
||||||
|
if (ex.InnerException is PostgresException pgException)
|
||||||
|
HandlePostgresException(pgException, item);
|
||||||
|
else
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<WellSectionTypeDto>> GetWellSectionTypesAsync(int idWell, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var query = from wellSectionType in dbContext.WellSectionTypes
|
||||||
|
join wellSectionPlan in dbContext.WellSectionsPlan on wellSectionType.Id equals wellSectionPlan.IdSectionType
|
||||||
|
where wellSectionPlan.IdWell == idWell
|
||||||
|
orderby wellSectionType.Order
|
||||||
|
select wellSectionType;
|
||||||
|
|
||||||
|
IEnumerable<WellSectionType> entities = await query.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!entities.Any())
|
||||||
|
entities = await dbContext.WellSectionTypes.OrderBy(w => w.Order).ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return entities.Select(w => w.Adapt<WellSectionTypeDto>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandlePostgresException(PostgresException pgException, WellSectionPlanDto wellSectionPlan)
|
||||||
|
{
|
||||||
|
if (pgException.SqlState == PostgresErrorCodes.UniqueViolation)
|
||||||
|
throw new ArgumentInvalidException($"Секция уже добавлена в конструкцию скважины",
|
||||||
|
nameof(wellSectionPlan.IdSectionType));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,6 @@ using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
|||||||
using AsbCloudApp.Services.Subsystems;
|
using AsbCloudApp.Services.Subsystems;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using AsbCloudApp.Data.Trajectory;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DailyReport;
|
namespace AsbCloudInfrastructure.Services.DailyReport;
|
||||||
|
|
||||||
@ -108,7 +107,15 @@ public class DailyReportService : IDailyReportService
|
|||||||
IdWell = well.Id
|
IdWell = well.Id
|
||||||
};
|
};
|
||||||
|
|
||||||
var factWellOperations = (await GetFactWellOperationsAsync(idWell, dailyReport.Date, cancellationToken))
|
var factOperationRequest = new WellOperationRequest
|
||||||
|
{
|
||||||
|
IdWell = idWell,
|
||||||
|
OperationType = WellOperation.IdOperationTypeFact,
|
||||||
|
GeDate = dateDailyReport,
|
||||||
|
LtDate = dateDailyReport.AddHours(24)
|
||||||
|
};
|
||||||
|
|
||||||
|
var factWellOperations = (await wellOperationRepository.GetAsync(factOperationRequest, cancellationToken))
|
||||||
.OrderBy(o => o.DateStart)
|
.OrderBy(o => o.DateStart)
|
||||||
.ThenBy(o => o.DepthStart);
|
.ThenBy(o => o.DepthStart);
|
||||||
|
|
||||||
@ -149,10 +156,7 @@ public class DailyReportService : IDailyReportService
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
var dailyReports = new List<DailyReportDto>();
|
var dailyReports = new List<DailyReportDto>();
|
||||||
|
|
||||||
var existingDailyReports = await dailyReportRepository.GetAsync(idWell, request, cancellationToken);
|
|
||||||
var factWellOperations = await GetFactWellOperationsAsync(idWell, null, cancellationToken);
|
|
||||||
|
|
||||||
if (request.GeDate.HasValue)
|
if (request.GeDate.HasValue)
|
||||||
{
|
{
|
||||||
var startDate = new DateTime(request.GeDate.Value.Year, request.GeDate.Value.Month,
|
var startDate = new DateTime(request.GeDate.Value.Year, request.GeDate.Value.Month,
|
||||||
@ -173,8 +177,22 @@ public class DailyReportService : IDailyReportService
|
|||||||
|
|
||||||
if (datesRange.From.AddDays(result.Skip) <= datesRange.To)
|
if (datesRange.From.AddDays(result.Skip) <= datesRange.To)
|
||||||
result.Count = (int)(Math.Ceiling((datesRange.To - DateTime.UnixEpoch).TotalDays) -
|
result.Count = (int)(Math.Ceiling((datesRange.To - DateTime.UnixEpoch).TotalDays) -
|
||||||
Math.Floor((datesRange.From - DateTime.UnixEpoch).TotalDays));
|
Math.Floor((datesRange.From - DateTime.UnixEpoch).TotalDays)) + 1;
|
||||||
|
|
||||||
|
var existingDailyReports = await dailyReportRepository.GetAsync(idWell, request, cancellationToken);
|
||||||
|
|
||||||
|
var geDateFactWellOperation = datesRange.From.AddDays(result.Skip);
|
||||||
|
var ltDateFactWellOperation = geDateFactWellOperation.AddDays(result.Take);
|
||||||
|
|
||||||
|
var factWellOperationRequest = new WellOperationRequest
|
||||||
|
{
|
||||||
|
IdWell = idWell,
|
||||||
|
OperationType = WellOperation.IdOperationTypeFact,
|
||||||
|
GeDate = geDateFactWellOperation,
|
||||||
|
LtDate = ltDateFactWellOperation
|
||||||
|
};
|
||||||
|
|
||||||
|
var factWellOperations = await wellOperationRepository.GetAsync(factWellOperationRequest, cancellationToken);
|
||||||
|
|
||||||
if (request.SortFields?.Contains("DateStart desc") == true)
|
if (request.SortFields?.Contains("DateStart desc") == true)
|
||||||
{
|
{
|
||||||
@ -208,7 +226,9 @@ public class DailyReportService : IDailyReportService
|
|||||||
IdWell = idWell
|
IdWell = idWell
|
||||||
};
|
};
|
||||||
|
|
||||||
AddFactWellOperationBlock(dailyReport, factWellOperations.Where(o => o.DateStart >= date && o.DateStart <= date.AddDays(1)));
|
var factWellOperationPerDay = factWellOperations.Where(o => o.DateStart.Date >= date && o.DateStart.Date <= date.AddDays(1));
|
||||||
|
|
||||||
|
AddFactWellOperationBlock(dailyReport, factWellOperationPerDay);
|
||||||
|
|
||||||
dailyReports.Add(dailyReport);
|
dailyReports.Add(dailyReport);
|
||||||
}
|
}
|
||||||
@ -216,18 +236,16 @@ public class DailyReportService : IDailyReportService
|
|||||||
|
|
||||||
public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken)
|
public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var factOperations = await GetFactWellOperationsAsync(idWell, null, cancellationToken);
|
var factOperationDatesRange = await wellOperationRepository.GetDatesRangeAsync(idWell, WellOperation.IdOperationTypeFact,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
if (!factOperations.Any())
|
if (factOperationDatesRange is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var minDateStart = factOperations.Min(o => o.DateStart).Date;
|
|
||||||
var maxDateStart = factOperations.Max(o => o.DateStart).Date;
|
|
||||||
|
|
||||||
return new DatesRangeDto
|
return new DatesRangeDto
|
||||||
{
|
{
|
||||||
From = minDateStart.AddDays(1) <= DateTime.UtcNow ? minDateStart : DateTime.UtcNow.Date.AddDays(-1),
|
From = factOperationDatesRange.From.AddDays(1) <= DateTime.UtcNow ? factOperationDatesRange.From : DateTime.UtcNow.Date.AddDays(-1),
|
||||||
To = maxDateStart.AddDays(1) <= DateTime.UtcNow ? maxDateStart : DateTime.UtcNow.Date.AddDays(-1)
|
To = factOperationDatesRange.To.AddDays(1) <= DateTime.UtcNow ? factOperationDatesRange.To : DateTime.UtcNow.Date.AddDays(-1)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,15 +376,6 @@ public class DailyReportService : IDailyReportService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<IEnumerable<WellOperationDto>> GetFactWellOperationsAsync(int idWell, DateTime? dateDailyReport, CancellationToken cancellationToken) =>
|
|
||||||
wellOperationRepository.GetAsync(new WellOperationRequest
|
|
||||||
{
|
|
||||||
IdWell = idWell,
|
|
||||||
OperationType = WellOperation.IdOperationTypeFact,
|
|
||||||
GeDate = dateDailyReport,
|
|
||||||
LtDate = dateDailyReport?.AddHours(24)
|
|
||||||
}, cancellationToken);
|
|
||||||
|
|
||||||
private async Task<bool> IsDateDailyReportInRangeAsync(int idWell, DateTime dateDailyReport, CancellationToken cancellationToken)
|
private async Task<bool> IsDateDailyReportInRangeAsync(int idWell, DateTime dateDailyReport, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var datesRange = await GetDatesRangeAsync(idWell, cancellationToken);
|
var datesRange = await GetDatesRangeAsync(idWell, cancellationToken);
|
||||||
|
@ -10,6 +10,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
|
using Microsoft.AspNetCore.Http.Extensions;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
||||||
|
|
||||||
@ -21,12 +22,6 @@ public class DetectedOperationExportService
|
|||||||
new DetectorSlipsTime()
|
new DetectorSlipsTime()
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly IDictionary<int, string> domains = new Dictionary<int, string>
|
|
||||||
{
|
|
||||||
{ 1, "https://cloud.digitaldrilling.ru" },
|
|
||||||
{ 2, "https://cloud.autodrilling.ru" }
|
|
||||||
};
|
|
||||||
|
|
||||||
private const int headerRowsCount = 1;
|
private const int headerRowsCount = 1;
|
||||||
|
|
||||||
private const string cellDepositName = "B1";
|
private const string cellDepositName = "B1";
|
||||||
@ -54,7 +49,15 @@ public class DetectedOperationExportService
|
|||||||
this.wellOperationRepository = wellOperationRepository;
|
this.wellOperationRepository = wellOperationRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Stream> ExportAsync(int idWell, int idDomain, CancellationToken cancellationToken)
|
/// <summary>
|
||||||
|
/// Экспорт excel файла с операциями по скважине
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell">ключ скважины</param>
|
||||||
|
/// <param name="host">хост</param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ArgumentNullException"></exception>
|
||||||
|
public async Task<Stream> ExportAsync(int idWell, string host, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var well = await dbContext.Wells
|
var well = await dbContext.Wells
|
||||||
.Include(w => w.Cluster)
|
.Include(w => w.Cluster)
|
||||||
@ -69,17 +72,17 @@ public class DetectedOperationExportService
|
|||||||
|
|
||||||
var operations = await DetectOperationsAsync(well.IdTelemetry.Value, DateTime.UnixEpoch, cancellationToken);
|
var operations = await DetectOperationsAsync(well.IdTelemetry.Value, DateTime.UnixEpoch, cancellationToken);
|
||||||
|
|
||||||
return await GenerateExcelFileStreamAsync(well, idDomain, operations, cancellationToken);
|
return await GenerateExcelFileStreamAsync(well, host, operations, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Stream> GenerateExcelFileStreamAsync(Well well, int idDomain, IEnumerable<OperationDetectorResult> operationDetectorResults,
|
private async Task<Stream> GenerateExcelFileStreamAsync(Well well, string host, IEnumerable<OperationDetectorResult> operationDetectorResults,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
|
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
|
||||||
|
|
||||||
using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled);
|
using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled);
|
||||||
|
|
||||||
await AddToWorkbookAsync(workbook, well, idDomain, operationDetectorResults, cancellationToken);
|
await AddToWorkbookAsync(workbook, well, host, operationDetectorResults, cancellationToken);
|
||||||
|
|
||||||
MemoryStream memoryStream = new MemoryStream();
|
MemoryStream memoryStream = new MemoryStream();
|
||||||
workbook.SaveAs(memoryStream, new SaveOptions { });
|
workbook.SaveAs(memoryStream, new SaveOptions { });
|
||||||
@ -87,7 +90,7 @@ public class DetectedOperationExportService
|
|||||||
return memoryStream;
|
return memoryStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddToWorkbookAsync(XLWorkbook workbook, Well well, int idDomain, IEnumerable<OperationDetectorResult> operationDetectorResults,
|
private async Task AddToWorkbookAsync(XLWorkbook workbook, Well well, string host, IEnumerable<OperationDetectorResult> operationDetectorResults,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
const string sheetName = "Операции";
|
const string sheetName = "Операции";
|
||||||
@ -98,12 +101,12 @@ public class DetectedOperationExportService
|
|||||||
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetName)
|
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetName)
|
||||||
?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}.");
|
?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}.");
|
||||||
|
|
||||||
await AddToSheetAsync(sheet, well, idDomain, operationDetectorResults
|
await AddToSheetAsync(sheet, well, host, operationDetectorResults
|
||||||
.OrderBy(x => x.Operation.DateStart).ThenBy(x => x.Operation.DepthStart).ToArray(),
|
.OrderBy(x => x.Operation.DateStart).ThenBy(x => x.Operation.DepthStart).ToArray(),
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddToSheetAsync(IXLWorksheet sheet, Well well, int idDomain, IList<OperationDetectorResult> operationDetectorResults,
|
private async Task AddToSheetAsync(IXLWorksheet sheet, Well well, string host, IList<OperationDetectorResult> operationDetectorResults,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var wellOperationCategories = await dbContext.WellOperationCategories.ToListAsync(cancellationToken);
|
var wellOperationCategories = await dbContext.WellOperationCategories.ToListAsync(cancellationToken);
|
||||||
@ -134,8 +137,11 @@ public class DetectedOperationExportService
|
|||||||
&& idReasonOfEndObject is int idReasonOfEnd)
|
&& idReasonOfEndObject is int idReasonOfEnd)
|
||||||
row.Cell(columnIdReasonOfEnd).Value = GetIdReasonOfEnd(idReasonOfEnd);
|
row.Cell(columnIdReasonOfEnd).Value = GetIdReasonOfEnd(idReasonOfEnd);
|
||||||
|
|
||||||
var link =
|
var query = new QueryBuilder();
|
||||||
$"{domains[idDomain]}/well/{well.Id}/telemetry/monitoring?end={Uri.EscapeDataString(dateStart.AddSeconds(1800 * 0.9).ToString("yyyy-MM-ddTHH:mm:ss.fff"))}&range=1800";
|
query.Add("end", dateStart.AddSeconds(1800 * 0.9).ToString("yyyy-MM-ddTHH:mm:ss.fff"));
|
||||||
|
query.Add("range", "1800");
|
||||||
|
|
||||||
|
var link = $"{host}/well/{well.Id}/telemetry/monitoring{query}";
|
||||||
|
|
||||||
row.Cell(columnDateStart).Value = dateStart;
|
row.Cell(columnDateStart).Value = dateStart;
|
||||||
row.Cell(columnDateStart).SetHyperlink(new XLHyperlink(link));
|
row.Cell(columnDateStart).SetHyperlink(new XLHyperlink(link));
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.ProcessMaps;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudApp.Services.ProcessMaps;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.ProcessMaps;
|
||||||
|
|
||||||
|
public class ProcessMapPlanService<T> : IProcessMapPlanService<T>
|
||||||
|
where T : ProcessMapPlanBaseDto
|
||||||
|
{
|
||||||
|
private readonly ICrudRepository<WellSectionTypeDto> wellSectionTypeRepository;
|
||||||
|
private readonly IProcessMapPlanRepository<T> processMapPlanRepository;
|
||||||
|
private readonly IRepositoryWellRelated<WellSectionPlanDto> wellSectionPlanRepository;
|
||||||
|
|
||||||
|
public ProcessMapPlanService(ICrudRepository<WellSectionTypeDto> wellSectionTypeRepository,
|
||||||
|
IProcessMapPlanRepository<T> processMapPlanRepository,
|
||||||
|
IRepositoryWellRelated<WellSectionPlanDto> wellSectionPlanRepository)
|
||||||
|
{
|
||||||
|
this.wellSectionTypeRepository = wellSectionTypeRepository;
|
||||||
|
this.processMapPlanRepository = processMapPlanRepository;
|
||||||
|
this.wellSectionPlanRepository = wellSectionPlanRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<ValidationResultDto<T>>> GetAsync(int idWell, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var wellSectionTypes = await wellSectionTypeRepository.GetAllAsync(cancellationToken);
|
||||||
|
|
||||||
|
var processMapsPlan = await processMapPlanRepository.GetByIdWellAsync(idWell, cancellationToken);
|
||||||
|
|
||||||
|
var wellSectionsPlan = await wellSectionPlanRepository.GetByIdWellAsync(idWell, cancellationToken);
|
||||||
|
|
||||||
|
return processMapsPlan.Select(processMapPlan =>
|
||||||
|
{
|
||||||
|
var wellSectionPlan = wellSectionsPlan.FirstOrDefault(s => s.IdSectionType == processMapPlan.IdWellSectionType);
|
||||||
|
|
||||||
|
var isValid = wellSectionPlan is not null && wellSectionPlan.DepthStart <= processMapPlan.DepthStart &&
|
||||||
|
wellSectionPlan.DepthEnd >= processMapPlan.DepthEnd;
|
||||||
|
|
||||||
|
var validationResult = new ValidationResultDto<T>
|
||||||
|
{
|
||||||
|
Item = processMapPlan
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isValid)
|
||||||
|
return validationResult;
|
||||||
|
|
||||||
|
var wellSectionType = wellSectionTypes.FirstOrDefault(s => s.Id == processMapPlan.IdWellSectionType);
|
||||||
|
|
||||||
|
validationResult.Warnings = new ValidationResult[]
|
||||||
|
{
|
||||||
|
new($"Конструкция секции: {wellSectionType?.Caption}; " +
|
||||||
|
$"Интервал бурения от {processMapPlan.DepthStart} до {processMapPlan.DepthEnd} не совпадает с данными указанными на странице " +
|
||||||
|
$"Конструкция скважины / План", new[] { nameof(processMapPlan.DepthStart), nameof(processMapPlan.DepthEnd) })
|
||||||
|
};
|
||||||
|
|
||||||
|
return validationResult;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,9 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.Csv;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -153,6 +155,41 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
return telemetry;
|
return telemetry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Stream> GetTelemetriesInfoByLastData(DateTimeOffset from, CancellationToken token)
|
||||||
|
{
|
||||||
|
var fromUtc = from.UtcDateTime;
|
||||||
|
var query = db.TelemetryDataSaub
|
||||||
|
.Where(i => i.DateTime >= fromUtc)
|
||||||
|
.GroupBy(i => i.IdTelemetry)
|
||||||
|
.Select(i => new
|
||||||
|
{
|
||||||
|
i.First().Telemetry,
|
||||||
|
LastDate = i.Max(i => i.DateTime)
|
||||||
|
});
|
||||||
|
|
||||||
|
var data = await query.ToArrayAsync(token);
|
||||||
|
|
||||||
|
var infos = data.Select(i => new TelemetryWithSoftwareVersionsDto(
|
||||||
|
i.Telemetry.Id,
|
||||||
|
i.Telemetry.RemoteUid,
|
||||||
|
i.LastDate,
|
||||||
|
i.Telemetry.Info.Deposit,
|
||||||
|
i.Telemetry.Info.Cluster,
|
||||||
|
i.Telemetry.Info.Well,
|
||||||
|
i.Telemetry.Info.HmiVersion,
|
||||||
|
i.Telemetry.Info.SaubPlcVersion,
|
||||||
|
i.Telemetry.Info.SpinPlcVersion)
|
||||||
|
);
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
if (!data.Any())
|
||||||
|
return stream;
|
||||||
|
|
||||||
|
var serializer = new CsvSerializer<TelemetryWithSoftwareVersionsDto>();
|
||||||
|
serializer.Serialize(infos, stream);
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<int> MergeAsync(int from, int to, CancellationToken token)
|
public async Task<int> MergeAsync(int from, int to, CancellationToken token)
|
||||||
{
|
{
|
||||||
if (from == to)
|
if (from == to)
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.SAUB;
|
||||||
|
|
||||||
|
internal record TelemetryWithSoftwareVersionsDto(int Id,
|
||||||
|
string RemoteUid,
|
||||||
|
DateTimeOffset LastData,
|
||||||
|
string Deposit,
|
||||||
|
string Cluster,
|
||||||
|
string Well,
|
||||||
|
string? HmiVersion,
|
||||||
|
string? SaubPlcVersion,
|
||||||
|
string? SpinPlcVersion);
|
@ -212,6 +212,7 @@ public class DailyReportServiceTest
|
|||||||
|
|
||||||
private readonly DailyReportDto fakeDailyReport;
|
private readonly DailyReportDto fakeDailyReport;
|
||||||
private readonly WellDto fakeWell;
|
private readonly WellDto fakeWell;
|
||||||
|
private readonly DatesRangeDto fakeDatesRange;
|
||||||
|
|
||||||
public DailyReportServiceTest()
|
public DailyReportServiceTest()
|
||||||
{
|
{
|
||||||
@ -233,6 +234,12 @@ public class DailyReportServiceTest
|
|||||||
Companies = new[] { fakeCustomer, fakeContractor }
|
Companies = new[] { fakeCustomer, fakeContractor }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fakeDatesRange = new DatesRangeDto
|
||||||
|
{
|
||||||
|
From = fakeFirstFactWellOperation.DateStart,
|
||||||
|
To = fakeLastFactWellOperation.DateStart
|
||||||
|
};
|
||||||
|
|
||||||
dailyReportService = new DailyReportService(wellServiceMock,
|
dailyReportService = new DailyReportService(wellServiceMock,
|
||||||
trajectoryFactNnbRepositoryMock,
|
trajectoryFactNnbRepositoryMock,
|
||||||
dailyReportRepositoryMock,
|
dailyReportRepositoryMock,
|
||||||
@ -260,6 +267,9 @@ public class DailyReportServiceTest
|
|||||||
wellOperationRepositoryMock.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>())
|
wellOperationRepositoryMock.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>())
|
||||||
.ReturnsForAnyArgs(new[] { fakeFirstFactWellOperation, fakeLastFactWellOperation });
|
.ReturnsForAnyArgs(new[] { fakeFirstFactWellOperation, fakeLastFactWellOperation });
|
||||||
|
|
||||||
|
wellOperationRepositoryMock.GetDatesRangeAsync(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<CancellationToken>())
|
||||||
|
.ReturnsForAnyArgs(fakeDatesRange);
|
||||||
|
|
||||||
wellOperationRepositoryMock.GetSectionTypes()
|
wellOperationRepositoryMock.GetSectionTypes()
|
||||||
.ReturnsForAnyArgs(new[] { fakeSectionType });
|
.ReturnsForAnyArgs(new[] { fakeSectionType });
|
||||||
|
|
||||||
@ -490,20 +500,23 @@ public class DailyReportServiceTest
|
|||||||
[Fact]
|
[Fact]
|
||||||
public async Task GetAsync_ShouldReturn_FictiveDailyReport()
|
public async Task GetAsync_ShouldReturn_FictiveDailyReport()
|
||||||
{
|
{
|
||||||
|
//arrange
|
||||||
|
var expectedCount = (fakeLastFactWellOperation.DateStart - fakeFirstFactWellOperation.DateStart).TotalDays + 1;
|
||||||
|
|
||||||
//act
|
//act
|
||||||
var result = await dailyReportService.GetAsync(idWell, new FileReportRequest(), CancellationToken.None);
|
var result = await dailyReportService.GetAsync(idWell, new FileReportRequest(), CancellationToken.None);
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.True((fakeLastFactWellOperation.DateStart - fakeFirstFactWellOperation.DateStart).Days == result.Count);
|
Assert.Equal(expectedCount, result.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(FactWellOperationDates))]
|
[MemberData(nameof(FactWellOperationDatesRange))]
|
||||||
public async Task GetDatesRangeAsync_ShouldReturn_DateRangeByFactWellOperations(IEnumerable<DateTime> factWellOperationDates)
|
public async Task GetDatesRangeAsync_ShouldReturn_DateRangeByFactWellOperations(DatesRangeDto datesRange)
|
||||||
{
|
{
|
||||||
//arrange
|
//arrange
|
||||||
wellOperationRepositoryMock.GetAsync(Arg.Any<WellOperationRequest>(), CancellationToken.None)
|
wellOperationRepositoryMock.GetDatesRangeAsync(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<CancellationToken>())
|
||||||
.ReturnsForAnyArgs(factWellOperationDates.Select(dateStart => new WellOperationDto { DateStart = dateStart }));
|
.Returns(datesRange);
|
||||||
|
|
||||||
//act
|
//act
|
||||||
var result = await dailyReportService.GetDatesRangeAsync(idWell, CancellationToken.None);
|
var result = await dailyReportService.GetDatesRangeAsync(idWell, CancellationToken.None);
|
||||||
@ -514,43 +527,41 @@ public class DailyReportServiceTest
|
|||||||
Assert.True(result.To < DateTime.UtcNow.Date);
|
Assert.True(result.To < DateTime.UtcNow.Date);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<object[]> FactWellOperationDates()
|
public static IEnumerable<object[]> FactWellOperationDatesRange()
|
||||||
{
|
{
|
||||||
yield return new object[]
|
yield return new object[]
|
||||||
{
|
{
|
||||||
new[]
|
new DatesRangeDto
|
||||||
{
|
{
|
||||||
new DateTime(2023, 11, 1),
|
From = new DateTime(2023, 11, 1),
|
||||||
new DateTime(2023, 11, 9),
|
To = new DateTime(2023, 11, 9)
|
||||||
DateTime.UtcNow
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
yield return new object[]
|
yield return new object[]
|
||||||
{
|
{
|
||||||
new[]
|
new DatesRangeDto
|
||||||
{
|
{
|
||||||
new DateTime(2023, 11, 1),
|
From = new DateTime(2023, 11, 1),
|
||||||
new DateTime(2023, 11, 1)
|
To = new DateTime(2023, 11, 1)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
yield return new object[]
|
yield return new object[]
|
||||||
{
|
{
|
||||||
new[]
|
new DatesRangeDto
|
||||||
{
|
{
|
||||||
DateTime.UtcNow,
|
From = DateTime.UtcNow,
|
||||||
DateTime.UtcNow
|
To = DateTime.UtcNow
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
yield return new object[]
|
yield return new object[]
|
||||||
{
|
{
|
||||||
new[]
|
new DatesRangeDto
|
||||||
{
|
{
|
||||||
new DateTime(2023, 11, 1),
|
From = new DateTime(2023, 11, 1),
|
||||||
new DateTime(2023, 11, 9),
|
To = new DateTime(2023, 11, 11)
|
||||||
new DateTime(2023, 11, 11)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,94 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.ProcessMaps;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudInfrastructure.Services.ProcessMaps;
|
||||||
|
using NSubstitute;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Tests.UnitTests.Services.ProcessMaps;
|
||||||
|
|
||||||
|
public class ProcessMapPlanServiceTests
|
||||||
|
{
|
||||||
|
private const int idWellSectionPlan = 1;
|
||||||
|
private const int idWell = 3;
|
||||||
|
private const int idWellSectionType = 54;
|
||||||
|
|
||||||
|
private readonly IEnumerable<WellSectionPlanDto> fakeCollectionWellSectionPlan = new WellSectionPlanDto[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = idWellSectionPlan,
|
||||||
|
IdWell = idWell,
|
||||||
|
IdSectionType = idWellSectionType,
|
||||||
|
DepthStart = 80,
|
||||||
|
DepthEnd = 150
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly IEnumerable<WellSectionTypeDto> fakeCollectionWellSectionTypes = new WellSectionTypeDto[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = idWellSectionType,
|
||||||
|
Caption = "Направление 1",
|
||||||
|
Order = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ICrudRepository<WellSectionTypeDto> wellSectionTypeRepositoryMock =
|
||||||
|
Substitute.For<ICrudRepository<WellSectionTypeDto>>();
|
||||||
|
|
||||||
|
private readonly IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto> processMapPlanRepositoryMock =
|
||||||
|
Substitute.For<IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto>>();
|
||||||
|
|
||||||
|
private readonly IRepositoryWellRelated<WellSectionPlanDto> wellSectionPlanRepositoryMock =
|
||||||
|
Substitute.For<IRepositoryWellRelated<WellSectionPlanDto>>();
|
||||||
|
|
||||||
|
private readonly ProcessMapPlanService<ProcessMapPlanWellDrillingDto> processMapPlanService;
|
||||||
|
|
||||||
|
public ProcessMapPlanServiceTests()
|
||||||
|
{
|
||||||
|
processMapPlanService = new ProcessMapPlanService<ProcessMapPlanWellDrillingDto>(wellSectionTypeRepositoryMock,
|
||||||
|
processMapPlanRepositoryMock, wellSectionPlanRepositoryMock);
|
||||||
|
|
||||||
|
wellSectionPlanRepositoryMock.GetByIdWellAsync(Arg.Any<int>(), Arg.Any<CancellationToken>())
|
||||||
|
.ReturnsForAnyArgs(fakeCollectionWellSectionPlan);
|
||||||
|
|
||||||
|
wellSectionTypeRepositoryMock.GetAllAsync(Arg.Any<CancellationToken>())
|
||||||
|
.ReturnsForAnyArgs(fakeCollectionWellSectionTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(80, 150, true)]
|
||||||
|
[InlineData(90, 140, true)]
|
||||||
|
[InlineData(0, 110, false)]
|
||||||
|
[InlineData(110, 200, false)]
|
||||||
|
public async Task GetAsync_ReturnsValidatedCollectionProcessMapPlanWellDrilling(int depthStart, int depthEnd, bool isValidCollection)
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
var fakeCollectionProcessMapPlanWellDrilling = new ProcessMapPlanWellDrillingDto[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
IdWellSectionType = idWellSectionType,
|
||||||
|
DepthStart = depthStart,
|
||||||
|
DepthEnd = depthEnd
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
processMapPlanRepositoryMock.GetByIdWellAsync(Arg.Any<int>(), Arg.Any<CancellationToken>())
|
||||||
|
.ReturnsForAnyArgs(fakeCollectionProcessMapPlanWellDrilling);
|
||||||
|
|
||||||
|
//act
|
||||||
|
var result = (await processMapPlanService.GetAsync(idWell, CancellationToken.None)).ToArray();
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(isValidCollection, result.All(r => r.IsValid));
|
||||||
|
Assert.Single(result);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
@ -8,6 +9,7 @@ using AsbCloudApp.Exceptions;
|
|||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudApp.Services.ProcessMaps;
|
||||||
using AsbCloudWebApi.SignalR;
|
using AsbCloudWebApi.SignalR;
|
||||||
using AsbCloudWebApi.SignalR.Clients;
|
using AsbCloudWebApi.SignalR.Clients;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
@ -32,13 +34,15 @@ public abstract class ProcessMapBaseController<T> : ControllerBase
|
|||||||
private readonly IUserRepository userRepository;
|
private readonly IUserRepository userRepository;
|
||||||
private readonly ICrudRepository<WellSectionTypeDto> wellSectionRepository;
|
private readonly ICrudRepository<WellSectionTypeDto> wellSectionRepository;
|
||||||
private readonly IProcessMapPlanRepository<T> repository;
|
private readonly IProcessMapPlanRepository<T> repository;
|
||||||
|
private readonly IProcessMapPlanService<T> service;
|
||||||
|
|
||||||
protected ProcessMapBaseController(IWellService wellService,
|
protected ProcessMapBaseController(IWellService wellService,
|
||||||
IProcessMapPlanRepository<T> repository,
|
IProcessMapPlanRepository<T> repository,
|
||||||
IUserRepository userRepository,
|
IUserRepository userRepository,
|
||||||
ICrudRepository<WellSectionTypeDto> wellSectionRepository,
|
ICrudRepository<WellSectionTypeDto> wellSectionRepository,
|
||||||
IHubContext<TelemetryHub, ITelemetryHubClient> telemetryHubContext,
|
IHubContext<TelemetryHub, ITelemetryHubClient> telemetryHubContext,
|
||||||
ITelemetryService telemetryService)
|
ITelemetryService telemetryService,
|
||||||
|
IProcessMapPlanService<T> service)
|
||||||
{
|
{
|
||||||
this.wellService = wellService;
|
this.wellService = wellService;
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
@ -46,9 +50,10 @@ public abstract class ProcessMapBaseController<T> : ControllerBase
|
|||||||
this.wellSectionRepository = wellSectionRepository;
|
this.wellSectionRepository = wellSectionRepository;
|
||||||
this.telemetryHubContext = telemetryHubContext;
|
this.telemetryHubContext = telemetryHubContext;
|
||||||
this.telemetryService = telemetryService;
|
this.telemetryService = telemetryService;
|
||||||
|
this.service = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract string SignalRMethod { get; }
|
protected abstract string SignalRGroup { get; }
|
||||||
|
|
||||||
protected int IdUser
|
protected int IdUser
|
||||||
{
|
{
|
||||||
@ -147,10 +152,16 @@ public abstract class ProcessMapBaseController<T> : ControllerBase
|
|||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<ActionResult<IEnumerable<T>>> GetAsync(int idWell, CancellationToken cancellationToken)
|
[ProducesResponseType(typeof(ValidationResultDto<>), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
public async Task<ActionResult<ValidationResultDto<T>>> GetAsync(int idWell, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var processMaps = await repository.GetByIdWellAsync(idWell, cancellationToken);
|
var processMaps = await service.GetAsync(idWell, cancellationToken);
|
||||||
|
|
||||||
|
if (!processMaps.Any())
|
||||||
|
return NoContent();
|
||||||
|
|
||||||
return Ok(processMaps);
|
return Ok(processMaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +215,7 @@ public abstract class ProcessMapBaseController<T> : ControllerBase
|
|||||||
var dtos = await repository.GetByIdWellAsync(idWell, cancellationToken);
|
var dtos = await repository.GetByIdWellAsync(idWell, cancellationToken);
|
||||||
|
|
||||||
await telemetryHubContext.Clients
|
await telemetryHubContext.Clients
|
||||||
.Group($"{SignalRMethod}_{idWell}")
|
.Group($"{SignalRGroup}_{idWell}")
|
||||||
.UpdateProcessMap(dtos, cancellationToken);
|
.UpdateProcessMap(dtos, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ public class ProcessMapWellDrillingController : ProcessMapBaseController<Process
|
|||||||
private readonly IProcessMapReportWellDrillingExportService processMapReportWellDrillingExportService;
|
private readonly IProcessMapReportWellDrillingExportService processMapReportWellDrillingExportService;
|
||||||
private readonly IProcessMapPlanImportService processMapPlanImportService;
|
private readonly IProcessMapPlanImportService processMapPlanImportService;
|
||||||
|
|
||||||
public override string SignalRMethod => "ProcessMapWellDrilling";
|
protected override string SignalRGroup => "ProcessMapWellDrilling";
|
||||||
|
|
||||||
public ProcessMapWellDrillingController(IWellService wellService,
|
public ProcessMapWellDrillingController(IWellService wellService,
|
||||||
IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto> repository,
|
IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto> repository,
|
||||||
@ -36,8 +36,9 @@ public class ProcessMapWellDrillingController : ProcessMapBaseController<Process
|
|||||||
IProcessMapReportWellDrillingService processMapReportWellDrillingService,
|
IProcessMapReportWellDrillingService processMapReportWellDrillingService,
|
||||||
ICrudRepository<WellSectionTypeDto> wellSectionRepository,
|
ICrudRepository<WellSectionTypeDto> wellSectionRepository,
|
||||||
IHubContext<TelemetryHub, ITelemetryHubClient> telemetryHubContext,
|
IHubContext<TelemetryHub, ITelemetryHubClient> telemetryHubContext,
|
||||||
ITelemetryService telemetryService)
|
ITelemetryService telemetryService,
|
||||||
: base(wellService, repository, userRepository, wellSectionRepository, telemetryHubContext, telemetryService)
|
IProcessMapPlanService<ProcessMapPlanWellDrillingDto> service)
|
||||||
|
: base(wellService, repository, userRepository, wellSectionRepository, telemetryHubContext, telemetryService, service)
|
||||||
{
|
{
|
||||||
this.processMapReportWellDrillingExportService = processMapReportWellDrillingExportService;
|
this.processMapReportWellDrillingExportService = processMapReportWellDrillingExportService;
|
||||||
this.processMapPlanImportService = processMapPlanImportService;
|
this.processMapPlanImportService = processMapPlanImportService;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using AsbCloudApp.Data.ProcessMaps;
|
using AsbCloudApp.Data.ProcessMaps;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudApp.Services.ProcessMaps;
|
||||||
using AsbCloudWebApi.SignalR;
|
using AsbCloudWebApi.SignalR;
|
||||||
using AsbCloudWebApi.SignalR.Clients;
|
using AsbCloudWebApi.SignalR.Clients;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
@ -13,15 +14,16 @@ namespace AsbCloudWebApi.Controllers.ProcessMaps;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ProcessMapWellReamController : ProcessMapBaseController<ProcessMapPlanWellReamDto>
|
public class ProcessMapWellReamController : ProcessMapBaseController<ProcessMapPlanWellReamDto>
|
||||||
{
|
{
|
||||||
public ProcessMapWellReamController(IWellService wellService,
|
public ProcessMapWellReamController(IWellService wellService,
|
||||||
IProcessMapPlanRepository<ProcessMapPlanWellReamDto> repository,
|
IProcessMapPlanRepository<ProcessMapPlanWellReamDto> repository,
|
||||||
IUserRepository userRepository,
|
IUserRepository userRepository,
|
||||||
ICrudRepository<WellSectionTypeDto> wellSectionRepository,
|
ICrudRepository<WellSectionTypeDto> wellSectionRepository,
|
||||||
IHubContext<TelemetryHub, ITelemetryHubClient> telemetryHubContext,
|
IHubContext<TelemetryHub, ITelemetryHubClient> telemetryHubContext,
|
||||||
ITelemetryService telemetryService)
|
ITelemetryService telemetryService,
|
||||||
: base(wellService, repository, userRepository, wellSectionRepository, telemetryHubContext, telemetryService)
|
IProcessMapPlanService<ProcessMapPlanWellReamDto> service)
|
||||||
{
|
: base(wellService, repository, userRepository, wellSectionRepository, telemetryHubContext, telemetryService, service)
|
||||||
}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public override string SignalRMethod => "ProccessMapWellReam";
|
protected override string SignalRGroup => "ProcessMapWellReam";
|
||||||
}
|
}
|
@ -0,0 +1,188 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.ProcessMaps;
|
||||||
|
using AsbCloudApp.Exceptions;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Controllers.ProcessMaps;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Конструкция скважины - план
|
||||||
|
/// </summary>
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/well/{idWell:int}/[controller]")]
|
||||||
|
[Authorize]
|
||||||
|
public class WellSectionPlanController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IWellService wellService;
|
||||||
|
private readonly IWellSectionPlanRepository wellSectionPlanRepository;
|
||||||
|
private readonly ICrudRepository<WellSectionTypeDto> wellSectionRepository;
|
||||||
|
|
||||||
|
public WellSectionPlanController(IWellService wellService,
|
||||||
|
IWellSectionPlanRepository wellSectionPlanRepository,
|
||||||
|
ICrudRepository<WellSectionTypeDto> wellSectionRepository)
|
||||||
|
{
|
||||||
|
this.wellService = wellService;
|
||||||
|
this.wellSectionPlanRepository = wellSectionPlanRepository;
|
||||||
|
this.wellSectionRepository = wellSectionRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: так же следует вынести в базовый контроллер
|
||||||
|
private int IdUser
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var idUser = User.GetUserId();
|
||||||
|
|
||||||
|
if (!idUser.HasValue)
|
||||||
|
throw new ForbidException("Неизвестный пользователь");
|
||||||
|
|
||||||
|
return idUser.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Добавить секцию
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell">Идентификатор скважины</param>
|
||||||
|
/// <param name="wellSection">Секция скважины - план</param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
[Permission]
|
||||||
|
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
public async Task<IActionResult> InsertAsync(int idWell, WellSectionPlanDto wellSection, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
wellSection.IdWell = idWell;
|
||||||
|
wellSection.IdUser = IdUser;
|
||||||
|
|
||||||
|
await CheckIsExistsWellSectionTypeAsync(wellSection.IdSectionType, cancellationToken);
|
||||||
|
|
||||||
|
await AssertUserAccessToWell(idWell, cancellationToken);
|
||||||
|
|
||||||
|
var wellSectionId = await wellSectionPlanRepository.InsertAsync(wellSection, cancellationToken);
|
||||||
|
|
||||||
|
return Ok(wellSectionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Обновить секцию
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell">Идентификатор скважины</param>
|
||||||
|
/// <param name="wellSection">Секция скважины - план</param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPut]
|
||||||
|
[Permission]
|
||||||
|
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
public async Task<IActionResult> UpdateAsync(int idWell, WellSectionPlanDto wellSection, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
wellSection.IdWell = idWell;
|
||||||
|
wellSection.IdUser = IdUser;
|
||||||
|
wellSection.LastUpdateDate = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
|
await CheckIsExistsWellSectionTypeAsync(wellSection.IdSectionType, cancellationToken);
|
||||||
|
|
||||||
|
await AssertUserAccessToWell(idWell, cancellationToken);
|
||||||
|
|
||||||
|
var wellSectionId = await wellSectionPlanRepository.UpdateAsync(wellSection, cancellationToken);
|
||||||
|
|
||||||
|
if (wellSectionId == ICrudRepository<WellSectionPlanDto>.ErrorIdNotFound)
|
||||||
|
return this.ValidationBadRequest(nameof(wellSection.Id), $"Секции скважины с Id: {wellSection.Id} не существует");
|
||||||
|
|
||||||
|
return Ok(wellSectionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить типы секций
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell">Идентификатор скважины</param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("wellSectionTypes")]
|
||||||
|
[ProducesResponseType(typeof(IEnumerable<WellSectionTypeDto>), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
public async Task<IActionResult> GetWellSectionTypesAsync(int idWell, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await AssertUserAccessToWell(idWell, cancellationToken);
|
||||||
|
|
||||||
|
var wellSectionTypes = await wellSectionPlanRepository.GetWellSectionTypesAsync(idWell, cancellationToken);
|
||||||
|
|
||||||
|
if (!wellSectionTypes.Any())
|
||||||
|
return NoContent();
|
||||||
|
|
||||||
|
return Ok(wellSectionTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить список секций
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell">Идентификатор скважины</param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType(typeof(IEnumerable<WellSectionPlanDto>), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
public async Task<IActionResult> GetPlanWellSectionsAsync(int idWell, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await AssertUserAccessToWell(idWell, cancellationToken);
|
||||||
|
|
||||||
|
var planWellSections = await wellSectionPlanRepository.GetByIdWellAsync(idWell, cancellationToken);
|
||||||
|
|
||||||
|
if (!planWellSections.Any())
|
||||||
|
return NoContent();
|
||||||
|
|
||||||
|
return Ok(planWellSections);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Удалить секцию
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell">Идентификатор скважины</param>
|
||||||
|
/// <param name="id">Идентификатор плановой секции</param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpDelete]
|
||||||
|
[Permission]
|
||||||
|
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
public async Task<IActionResult> DeleteAsync(int idWell, int id, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await AssertUserAccessToWell(idWell, cancellationToken);
|
||||||
|
|
||||||
|
var deletedWellSectionPlanCount = await wellSectionPlanRepository.DeleteAsync(id, cancellationToken);
|
||||||
|
|
||||||
|
return Ok(deletedWellSectionPlanCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: нужно создать базовый контроллер связанный со скважиной и вынести этот метод туда. Данный метод много где дублируется
|
||||||
|
private async Task AssertUserAccessToWell(int idWell, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var idCompany = User.GetCompanyId();
|
||||||
|
|
||||||
|
if (!idCompany.HasValue || !await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, cancellationToken))
|
||||||
|
throw new ForbidException("Нет доступа к скважине");
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: тоже нужно вынести в базовый контроллер
|
||||||
|
private async Task CheckIsExistsWellSectionTypeAsync(int idWellSectionType, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_ = await wellSectionRepository.GetOrDefaultAsync(idWellSectionType, cancellationToken)
|
||||||
|
?? throw new ArgumentInvalidException(nameof(ProcessMapPlanWellDrillingDto.IdWellSectionType),
|
||||||
|
$"Тип секции с Id: {idWellSectionType} не найден");
|
||||||
|
}
|
||||||
|
}
|
@ -122,21 +122,21 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
/// Создает excel файл с операциями по скважине
|
/// Создает excel файл с операциями по скважине
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell">id скважины</param>
|
/// <param name="idWell">id скважины</param>
|
||||||
/// <param name="idDomain">Идентификатор домена</param>
|
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
[HttpGet("export")]
|
[HttpGet("export")]
|
||||||
[Permission]
|
[Permission]
|
||||||
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")]
|
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
|
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
|
||||||
public async Task<IActionResult> ExportAsync(int idWell, [Range(1, 2)] int idDomain, CancellationToken token)
|
public async Task<IActionResult> ExportAsync(int idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
var idCompany = User.GetCompanyId();
|
var idCompany = User.GetCompanyId();
|
||||||
|
|
||||||
if (idCompany is null)
|
if (idCompany is null)
|
||||||
return Forbid();
|
return Forbid();
|
||||||
|
|
||||||
var stream = await detectedOperationExportService.ExportAsync(idWell, idDomain, token);
|
var host = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}";
|
||||||
|
var stream = await detectedOperationExportService.ExportAsync(idWell, host, token);
|
||||||
|
|
||||||
return File(stream, "application/octet-stream", "operations.xlsx");
|
return File(stream, "application/octet-stream", "operations.xlsx");
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ using AsbCloudApp.Services;
|
|||||||
using AsbCloudWebApi.SignalR;
|
using AsbCloudWebApi.SignalR;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -37,6 +39,19 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
this.telemetryHubContext = telemetryHubContext;
|
this.telemetryHubContext = telemetryHubContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Информация о версиях ПО по телеметриям, данные от которых приходили не позднее From
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("Active")]
|
||||||
|
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
|
||||||
|
public async Task<IActionResult> GetTelemetriesInfoByLastData(CancellationToken token)
|
||||||
|
{
|
||||||
|
var from = DateTimeOffset.UtcNow.AddDays(-1);
|
||||||
|
var stream = await telemetryService.GetTelemetriesInfoByLastData(from, token);
|
||||||
|
return File(stream, "text/csv", $"Software versions by active telemetries from {from :yy-MM-dd hh-mm}.csv");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Принимает общую информацию по скважине
|
/// Принимает общую информацию по скважине
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user