Импорт фактических траекторий + разбиение фактических тракторий на 2 таба (импортированные траектории и траектории из ннб)

This commit is contained in:
Olga Nemt 2023-11-21 15:10:22 +05:00
parent 4d69e4ecbb
commit 98ec7637eb
36 changed files with 28212 additions and 357 deletions

View File

@ -4,7 +4,7 @@
/// DTO объединяющее плановые и фактические значения /// DTO объединяющее плановые и фактические значения
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public class PlanFactDto<T> : PlanFactBase<T, T> public class PlanFactDto<T> : PlanFactBase<T, T, T>
{ {
} }
@ -14,7 +14,8 @@
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <typeparam name="V"></typeparam> /// <typeparam name="V"></typeparam>
public class PlanFactBase<T, V> /// <typeparam name="K"></typeparam>
public class PlanFactBase<T, V, K>
{ {
/// <summary> /// <summary>
/// Плановое значение /// Плановое значение
@ -25,5 +26,10 @@
/// Фактическое значение /// Фактическое значение
/// </summary> /// </summary>
public V? Fact { get; set; } public V? Fact { get; set; }
/// <summary>
/// Фактическое ннб-значение
/// </summary>
public V? Nnb { get; set; }
} }
} }

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AsbCloudApp.Data
{
/// <summary>
/// Базовая географическая траектория
/// </summary>
public abstract class TrajectoryGeoDto
{
/// <summary>
/// Id скважины
/// </summary>
public int IdWell { get; set; }
/// <summary>
/// Глубина по стволу
/// </summary>
public double WellboreDepth { get; set; }
/// <summary>
/// Угол зенитный
/// </summary>
public double ZenithAngle { get; set; }
/// <summary>
/// Азимут Географ.
/// </summary>
public double AzimuthGeo { get; set; }
/// <summary>
/// Азимут Магнитный
/// </summary>
public double? AzimuthMagnetic { get; set; }
/// <summary>
/// Глубина вертикальная
/// </summary>
public double? VerticalDepth { get; set; }
/// <summary>
/// Дата загрузки
/// </summary>
public DateTime UpdateDate { get; set; }
/// <summary>
/// ИД пользователя
/// </summary>
public int IdUser { get; set; }
}
}

View File

@ -1,45 +1,27 @@
namespace AsbCloudApp.Data; using System;
/// <summary> namespace AsbCloudApp.Data;
/// Базовая географическая траектория
/// </summary>
public abstract class TrajectoryGeoDto
{
/// <summary>
/// Id скважины
/// </summary>
public int IdWell { get; set; }
/// <summary>
/// Глубина по стволу
/// </summary>
public double WellboreDepth { get; set; }
/// <summary>
/// Угол зенитный
/// </summary>
public double ZenithAngle { get; set; }
/// <summary>
/// Азимут Географ.
/// </summary>
public double AzimuthGeo { get; set; }
/// <summary>
/// Азимут Магнитный
/// </summary>
public double? AzimuthMagnetic { get; set; }
/// <summary>
/// Глубина вертикальная
/// </summary>
public double? VerticalDepth { get; set; }
}
/// <summary> /// <summary>
/// Формирование данных по фактической географической траектории /// Формирование данных по фактической географической траектории
/// </summary> /// </summary>
public class TrajectoryGeoFactDto : TrajectoryGeoDto public class TrajectoryGeoFactDto : TrajectoryGeoDto
{ } {
/// <summary>
/// ИД строки с координатами
/// </summary>
public int Id { get; set; }
/// <summary>
/// Радиус цели
/// </summary>
public double? Radius { get; set; }
/// <summary>
/// Комментарии
/// </summary>
public string? Comment { get; set; }
}

View File

@ -10,16 +10,6 @@ namespace AsbCloudApp.Data
/// ИД строки с координатами /// ИД строки с координатами
/// </summary> /// </summary>
public int Id { get; set; } public int Id { get; set; }
/// <summary>
/// Дата загрузки
/// </summary>
public DateTime UpdateDate { get; set; }
/// <summary>
/// ИД пользователя
/// </summary>
public int IdUser { get; set; }
/// <summary> /// <summary>
/// Радиус цели /// Радиус цели

View File

@ -9,7 +9,8 @@ namespace AsbCloudApp.Repositories
/// CRUD для работы с плановой траекторией из клиента /// CRUD для работы с плановой траекторией из клиента
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public interface ITrajectoryPlanRepository : ITrajectoryRepository<TrajectoryGeoPlanDto> //TrajectoryGeoPlanDto
public interface ITrajectoryEditableRepository<T> : ITrajectoryRepository<T> where T : TrajectoryGeoDto
{ {
/// <summary> /// <summary>
/// Добавить строки с координатами по одной скважине. Если в коллекции координаты для разных скважин получаем exception. /// Добавить строки с координатами по одной скважине. Если в коллекции координаты для разных скважин получаем exception.
@ -17,7 +18,7 @@ namespace AsbCloudApp.Repositories
/// <param name="plannedTrajectoryRows"></param> /// <param name="plannedTrajectoryRows"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns>количество записанных строк или exception с описанием</returns> /// <returns>количество записанных строк или exception с описанием</returns>
Task<int> AddRangeAsync(IEnumerable<TrajectoryGeoPlanDto> plannedTrajectoryRows, CancellationToken token); Task<int> AddRangeAsync(IEnumerable<T> plannedTrajectoryRows, CancellationToken token);
/// <summary> /// <summary>
/// Добавить одну строку с координатами /// Добавить одну строку с координатами
@ -25,7 +26,7 @@ namespace AsbCloudApp.Repositories
/// <param name="plannedTrajectoryRow"></param> /// <param name="plannedTrajectoryRow"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> AddAsync(TrajectoryGeoPlanDto plannedTrajectoryRow, CancellationToken token); Task<int> AddAsync(T plannedTrajectoryRow, CancellationToken token);
/// <summary> /// <summary>
/// Обновить строку с координатами /// Обновить строку с координатами
@ -33,7 +34,7 @@ namespace AsbCloudApp.Repositories
/// <param name="row"></param> /// <param name="row"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> UpdateAsync(TrajectoryGeoPlanDto row, Task<int> UpdateAsync(T row,
CancellationToken token); CancellationToken token);
/// <summary> /// <summary>

View File

@ -10,7 +10,7 @@ namespace AsbCloudApp.Repositories
/// CRUD для работы с фактической траекторией из клиента /// CRUD для работы с фактической траекторией из клиента
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public interface ITrajectoryFactRepository : ITrajectoryRepository<TrajectoryGeoFactDto> public interface ITrajectoryNnbRepository : ITrajectoryRepository<TrajectoryGeoFactDto>
{ {
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AsbCloudDb.Migrations
{
public partial class Add_Permissions_For_Trajectory_Fact : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "t_permission",
columns: new[] { "id", "description", "name" },
values: new object[,]
{
{ 530, "Разрешение просматривать фактические траектории", "FactTrajectory.get" },
{ 531, "Разрешение редактировать фактические траектории", "FactTrajectory.edit" }
});
migrationBuilder.InsertData(
table: "t_relation_user_role_permission",
columns: new[] { "id_permission", "id_user_role" },
values: new object[,]
{
{ 530, 1 },
{ 531, 1 }
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
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);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace AsbCloudDb.Migrations
{
public partial class Add_Fact_Trajectory_Table : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "t_fact_trajectory",
columns: table => new
{
id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
id_user = table.Column<int>(type: "integer", nullable: false, comment: "ID пользователя который внес/изменил запись"),
id_well = table.Column<int>(type: "integer", nullable: false, comment: "ID скважины"),
update_date = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Дата загрузки траектории"),
wellbore_depth = table.Column<double>(type: "double precision", nullable: false, comment: "Глубина по стволу"),
zenith_angle = table.Column<double>(type: "double precision", nullable: false, comment: "Угол зенитный"),
azimuth_geo = table.Column<double>(type: "double precision", nullable: false, comment: "Азимут Географ."),
azimuth_magnetic = table.Column<double>(type: "double precision", nullable: false, comment: "Азимут Магнитный"),
vertical_depth = table.Column<double>(type: "double precision", nullable: false, comment: "Глубина вертикальная"),
comment = table.Column<string>(type: "text", nullable: true, comment: "Комментарии"),
radius = table.Column<double>(type: "double precision", nullable: true, comment: "Радиус цели")
},
constraints: table =>
{
table.PrimaryKey("PK_t_fact_trajectory", x => x.id);
table.ForeignKey(
name: "FK_t_fact_trajectory_t_user_id_user",
column: x => x.id_user,
principalTable: "t_user",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_t_fact_trajectory_t_well_id_well",
column: x => x.id_well,
principalTable: "t_well",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
},
comment: "Загрузка фактической траектории");
migrationBuilder.CreateIndex(
name: "IX_t_fact_trajectory_id_user",
table: "t_fact_trajectory",
column: "id_user");
migrationBuilder.CreateIndex(
name: "IX_t_fact_trajectory_id_well",
table: "t_fact_trajectory",
column: "id_well");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "t_fact_trajectory");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AsbCloudDb.Migrations
{
public partial class Add_Permissions_For_Trajectory_Nnb : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "t_permission",
columns: new[] { "id", "description", "name" },
values: new object[] { 532, "Разрешение просматривать фактические ннб-траектории", "NnbTrajectory.get" });
migrationBuilder.InsertData(
table: "t_relation_user_role_permission",
columns: new[] { "id_permission", "id_user_role" },
values: new object[] { 532, 1 });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "t_relation_user_role_permission",
keyColumns: new[] { "id_permission", "id_user_role" },
keyValues: new object[] { 532, 1 });
migrationBuilder.DeleteData(
table: "t_permission",
keyColumn: "id",
keyValue: 532);
}
}
}

View File

@ -19,7 +19,7 @@ namespace AsbCloudDb.Migrations
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.UseCollation("Russian_Russia.1251") .UseCollation("Russian_Russia.1251")
.HasAnnotation("ProductVersion", "6.0.22") .HasAnnotation("ProductVersion", "6.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63); .HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack"); NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
@ -136,21 +136,21 @@ namespace AsbCloudDb.Migrations
{ {
Id = 1, Id = 1,
Caption = "Недропользователь", Caption = "Недропользователь",
IsContact = false, IsContact = true,
Order = 3 Order = 3
}, },
new new
{ {
Id = 2, Id = 2,
Caption = "Буровой подрядчик", Caption = "Буровой подрядчик",
IsContact = false, IsContact = true,
Order = 2 Order = 2
}, },
new new
{ {
Id = 3, Id = 3,
Caption = "Сервис автоматизации бурения", Caption = "Сервис автоматизации бурения",
IsContact = false, IsContact = true,
Order = 0 Order = 0
}, },
new new
@ -178,7 +178,7 @@ namespace AsbCloudDb.Migrations
{ {
Id = 7, Id = 7,
Caption = "Служба супервайзинга", Caption = "Служба супервайзинга",
IsContact = true, IsContact = false,
Order = 1 Order = 1
}, },
new new
@ -189,11 +189,18 @@ namespace AsbCloudDb.Migrations
Order = 7 Order = 7
}, },
new new
{
Id = 11,
Caption = "Дизельный сервис",
IsContact = false,
Order = 9
},
new
{ {
Id = 12, Id = 12,
Caption = "Сервис по обслуживанию верхних силовых приводов", Caption = "Сервис по обслуживанию верхних силовых приводов",
IsContact = true, IsContact = true,
Order = 7 Order = 8
}); });
}); });
@ -493,6 +500,76 @@ namespace AsbCloudDb.Migrations
b.HasComment("Drill_test"); b.HasComment("Drill_test");
}); });
modelBuilder.Entity("AsbCloudDb.Model.FactTrajectory", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<double>("AzimuthGeo")
.HasColumnType("double precision")
.HasColumnName("azimuth_geo")
.HasComment("Азимут Географ.");
b.Property<double>("AzimuthMagnetic")
.HasColumnType("double precision")
.HasColumnName("azimuth_magnetic")
.HasComment("Азимут Магнитный");
b.Property<string>("Comment")
.HasColumnType("text")
.HasColumnName("comment")
.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?>("Radius")
.HasColumnType("double precision")
.HasColumnName("radius")
.HasComment("Радиус цели");
b.Property<DateTimeOffset>("UpdateDate")
.HasColumnType("timestamp with time zone")
.HasColumnName("update_date")
.HasComment("Дата загрузки траектории");
b.Property<double>("VerticalDepth")
.HasColumnType("double precision")
.HasColumnName("vertical_depth")
.HasComment("Глубина вертикальная");
b.Property<double>("WellboreDepth")
.HasColumnType("double precision")
.HasColumnName("wellbore_depth")
.HasComment("Глубина по стволу");
b.Property<double>("ZenithAngle")
.HasColumnType("double precision")
.HasColumnName("zenith_angle")
.HasComment("Угол зенитный");
b.HasKey("Id");
b.HasIndex("IdUser");
b.HasIndex("IdWell");
b.ToTable("t_fact_trajectory");
b.HasComment("Загрузка фактической траектории");
});
modelBuilder.Entity("AsbCloudDb.Model.Faq", b => modelBuilder.Entity("AsbCloudDb.Model.Faq", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -2415,6 +2492,30 @@ namespace AsbCloudDb.Migrations
Id = 528, Id = 528,
Description = "Разрешение на удаление контакта", Description = "Разрешение на удаление контакта",
Name = "WellContact.delete" Name = "WellContact.delete"
},
new
{
Id = 529,
Description = "Разрешение на получение отчетов drill test",
Name = "DrillTestReport.get"
},
new
{
Id = 530,
Description = "Разрешение просматривать фактические траектории",
Name = "FactTrajectory.get"
},
new
{
Id = 531,
Description = "Разрешение редактировать фактические траектории",
Name = "FactTrajectory.edit"
},
new
{
Id = 532,
Description = "Разрешение просматривать фактические ннб-траектории",
Name = "NnbTrajectory.get"
}); });
}); });
@ -4081,6 +4182,26 @@ namespace AsbCloudDb.Migrations
{ {
IdUserRole = 1, IdUserRole = 1,
IdPermission = 528 IdPermission = 528
},
new
{
IdUserRole = 1,
IdPermission = 529
},
new
{
IdUserRole = 1,
IdPermission = 530
},
new
{
IdUserRole = 1,
IdPermission = 531
},
new
{
IdUserRole = 1,
IdPermission = 532
}); });
}); });
@ -7967,6 +8088,25 @@ namespace AsbCloudDb.Migrations
b.Navigation("Telemetry"); b.Navigation("Telemetry");
}); });
modelBuilder.Entity("AsbCloudDb.Model.FactTrajectory", b =>
{
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("User");
b.Navigation("Well");
});
modelBuilder.Entity("AsbCloudDb.Model.Faq", b => modelBuilder.Entity("AsbCloudDb.Model.Faq", b =>
{ {
b.HasOne("AsbCloudDb.Model.User", "AuthorAnswer") b.HasOne("AsbCloudDb.Model.User", "AuthorAnswer")

View File

@ -5,6 +5,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using AsbCloudDb.Model.Manuals; using AsbCloudDb.Model.Manuals;
using AsbCloudDb.Model.ProcessMaps; using AsbCloudDb.Model.ProcessMaps;
using AsbCloudDb.Model.Trajectory;
namespace AsbCloudDb.Model namespace AsbCloudDb.Model
{ {
@ -59,6 +60,7 @@ namespace AsbCloudDb.Model
public virtual DbSet<LimitingParameter> LimitingParameter => Set<LimitingParameter>(); public virtual DbSet<LimitingParameter> LimitingParameter => Set<LimitingParameter>();
public virtual DbSet<TelemetryWirelineRunOut> TelemetryWirelineRunOut => Set<TelemetryWirelineRunOut>(); public virtual DbSet<TelemetryWirelineRunOut> TelemetryWirelineRunOut => Set<TelemetryWirelineRunOut>();
public virtual DbSet<FactTrajectory> FactTrajectories => Set<FactTrajectory>();
// GTR WITS // GTR WITS
public DbSet<WitsItemFloat> WitsItemFloat => Set<WitsItemFloat>(); public DbSet<WitsItemFloat> WitsItemFloat => Set<WitsItemFloat>();

View File

@ -163,6 +163,10 @@
new (){ Id = 528, Name="WellContact.delete", Description="Разрешение на удаление контакта"}, new (){ Id = 528, Name="WellContact.delete", Description="Разрешение на удаление контакта"},
new (){ Id = 529, Name="DrillTestReport.get", Description="Разрешение на получение отчетов drill test"}, new (){ Id = 529, Name="DrillTestReport.get", Description="Разрешение на получение отчетов drill test"},
new (){ Id = 530, Name="FactTrajectory.get", Description="Разрешение просматривать фактические траектории"},
new (){ Id = 531, Name="FactTrajectory.edit", Description="Разрешение редактировать фактические траектории"},
new (){ Id = 532, Name="NnbTrajectory.get", Description="Разрешение просматривать фактические ннб-траектории"},
}; };
} }
} }

View File

@ -9,6 +9,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using AsbCloudDb.Model.Manuals; using AsbCloudDb.Model.Manuals;
using AsbCloudDb.Model.ProcessMaps; using AsbCloudDb.Model.ProcessMaps;
using AsbCloudDb.Model.Trajectory;
namespace AsbCloudDb.Model namespace AsbCloudDb.Model
{ {
@ -77,6 +78,7 @@ namespace AsbCloudDb.Model
DbSet<ManualDirectory> ManualDirectories { get; } DbSet<ManualDirectory> ManualDirectories { get; }
DbSet<Contact> Contacts { get; } DbSet<Contact> Contacts { get; }
DbSet<DrillTest> DrillTests { get; } DbSet<DrillTest> DrillTests { get; }
DbSet<FactTrajectory> FactTrajectories { get; }
DatabaseFacade Database { get; } DatabaseFacade Database { get; }
Task<int> RefreshMaterializedViewAsync(string mwName, CancellationToken token); Task<int> RefreshMaterializedViewAsync(string mwName, CancellationToken token);

View File

@ -0,0 +1,10 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;
namespace AsbCloudDb.Model.Trajectory
{
[Table("t_fact_trajectory"), Comment("Загрузка фактической траектории")]
public class FactTrajectory : Trajectory
{
}
}

View File

@ -0,0 +1,13 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace AsbCloudDb.Model.Trajectory
{
[Table("t_planned_trajectory"), Comment("Загрузка плановой траектории")]
public class PlannedTrajectory : Trajectory
{
}
}

View File

@ -3,10 +3,9 @@ using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace AsbCloudDb.Model namespace AsbCloudDb.Model.Trajectory
{ {
[Table("t_planned_trajectory"), Comment("Загрузка плановой траектории")] public class Trajectory : IId, IWellRelated
public class PlannedTrajectory : IId, IWellRelated
{ {
[Column("id"), Key] [Column("id"), Key]
public int Id { get; set; } public int Id { get; set; }

View File

@ -14,6 +14,8 @@
<None Remove="CommonLibs\Readme.md" /> <None Remove="CommonLibs\Readme.md" />
<None Remove="Services\DailyReport\DailyReportTemplate.xlsx" /> <None Remove="Services\DailyReport\DailyReportTemplate.xlsx" />
<None Remove="Services\DrillTestReport\DrillTestReportTemplate.xlsx" /> <None Remove="Services\DrillTestReport\DrillTestReportTemplate.xlsx" />
<None Remove="Services\Trajectory\FactTrajectoryTemplate.xlsx" />
<None Remove="Services\Trajectory\NnbTrajectoryTemplate.xlsx" />
<None Remove="Services\Trajectory\PlannedTrajectoryTemplate.xlsx" /> <None Remove="Services\Trajectory\PlannedTrajectoryTemplate.xlsx" />
<None Remove="Services\WellOperationService\ScheduleReportTemplate.xlsx" /> <None Remove="Services\WellOperationService\ScheduleReportTemplate.xlsx" />
<None Remove="Services\WellOperationService\WellOperationImportTemplate.xlsx" /> <None Remove="Services\WellOperationService\WellOperationImportTemplate.xlsx" />
@ -32,6 +34,8 @@
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Services\DailyReport\DailyReportTemplate.xlsx" /> <EmbeddedResource Include="Services\DailyReport\DailyReportTemplate.xlsx" />
<EmbeddedResource Include="Services\DrillTestReport\DrillTestReportTemplate.xlsx" /> <EmbeddedResource Include="Services\DrillTestReport\DrillTestReportTemplate.xlsx" />
<EmbeddedResource Include="Services\Trajectory\FactTrajectoryTemplate.xlsx" />
<EmbeddedResource Include="Services\Trajectory\NnbTrajectoryTemplate.xlsx" />
<EmbeddedResource Include="Services\Trajectory\PlannedTrajectoryTemplate.xlsx" /> <EmbeddedResource Include="Services\Trajectory\PlannedTrajectoryTemplate.xlsx" />
<EmbeddedResource Include="Services\WellOperationService\ScheduleReportTemplate.xlsx" /> <EmbeddedResource Include="Services\WellOperationService\ScheduleReportTemplate.xlsx" />
<EmbeddedResource Include="Services\AutoGeneratedDailyReports\AutogeneratedDailyReportTemplate.xlsx" /> <EmbeddedResource Include="Services\AutoGeneratedDailyReports\AutogeneratedDailyReportTemplate.xlsx" />

View File

@ -18,6 +18,7 @@ using AsbCloudDb.Model;
using AsbCloudDb.Model.Manuals; using AsbCloudDb.Model.Manuals;
using AsbCloudDb.Model.ProcessMaps; using AsbCloudDb.Model.ProcessMaps;
using AsbCloudDb.Model.Subsystems; using AsbCloudDb.Model.Subsystems;
using AsbCloudDb.Model.Trajectory;
using AsbCloudInfrastructure.Background; using AsbCloudInfrastructure.Background;
using AsbCloudInfrastructure.Repository; using AsbCloudInfrastructure.Repository;
using AsbCloudInfrastructure.Services; using AsbCloudInfrastructure.Services;
@ -188,7 +189,10 @@ namespace AsbCloudInfrastructure
services.AddTransient<IWellService, WellService>(); services.AddTransient<IWellService, WellService>();
services.AddTransient<IWellOperationImportService, WellOperationImportService>(); services.AddTransient<IWellOperationImportService, WellOperationImportService>();
services.AddTransient<IProcessMapReportWellDrillingExportService, ProcessMapReportWellDrillingExportService>(); services.AddTransient<IProcessMapReportWellDrillingExportService, ProcessMapReportWellDrillingExportService>();
services.AddTransient<IPlannedTrajectoryImportService, PlannedTrajectoryImportService>(); //services.AddTransient<IPlannedTrajectoryImportService, PlannedTrajectoryImportService>();
services.AddTransient<PlannedTrajectoryImportService>();
services.AddTransient<FactTrajectoryImportService>();
services.AddTransient<NnbTrajectoryImportService>();
services.AddTransient<IWellOperationRepository, WellOperationRepository>(); services.AddTransient<IWellOperationRepository, WellOperationRepository>();
services.AddTransient<IDailyReportService, DailyReportService>(); services.AddTransient<IDailyReportService, DailyReportService>();
services.AddTransient<IDetectedOperationService, DetectedOperationService>(); services.AddTransient<IDetectedOperationService, DetectedOperationService>();
@ -251,8 +255,9 @@ namespace AsbCloudInfrastructure
services.AddTransient<ILimitingParameterRepository, LimitingParameterRepository>(); services.AddTransient<ILimitingParameterRepository, LimitingParameterRepository>();
services.AddTransient<ITelemetryWirelineRunOutRepository, TelemetryWirelineRunOutRepository>(); services.AddTransient<ITelemetryWirelineRunOutRepository, TelemetryWirelineRunOutRepository>();
services.AddTransient<IWellFinalDocumentsRepository, WellFinalDocumentsRepository>(); services.AddTransient<IWellFinalDocumentsRepository, WellFinalDocumentsRepository>();
services.AddTransient<ITrajectoryPlanRepository, TrajectoryPlanRepository>(); services.AddTransient<ITrajectoryEditableRepository<TrajectoryGeoPlanDto>, TrajectoryPlanRepository<PlannedTrajectory, TrajectoryGeoPlanDto>>();
services.AddTransient<ITrajectoryFactRepository, TrajectoryFactRepository>(); services.AddTransient<ITrajectoryEditableRepository<TrajectoryGeoFactDto>, TrajectoryPlanRepository<PlannedTrajectory, TrajectoryGeoFactDto>>();
services.AddTransient<ITrajectoryNnbRepository, TrajectoryNnbRepository>();
services.AddTransient<IFaqRepository, FaqRepository>(); services.AddTransient<IFaqRepository, FaqRepository>();
services.AddTransient<ISlipsStatService, SlipsStatService>(); services.AddTransient<ISlipsStatService, SlipsStatService>();
services.AddTransient<IWellContactService, WellContactService>(); services.AddTransient<IWellContactService, WellContactService>();

View File

@ -1,53 +1,116 @@
using AsbCloudApp.Data; //using AsbCloudApp.Data;
using AsbCloudApp.Repositories; //using AsbCloudApp.Exceptions;
using AsbCloudApp.Services; //using AsbCloudApp.Repositories;
using AsbCloudDb.Model; //using AsbCloudApp.Services;
using Microsoft.EntityFrameworkCore; //using AsbCloudDb.Model;
using System.Collections.Generic; //using Mapster;
using System.Linq; //using Microsoft.EntityFrameworkCore;
using System.Threading; //using System;
using System.Threading.Tasks; //using System.Collections.Generic;
//using System.Linq;
//using System.Threading;
//using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository //namespace AsbCloudInfrastructure.Repository
{ //{
internal class TrajectoryFactRepository : ITrajectoryFactRepository // internal class TrajectoryFactRepository : ITrajectoryEditableRepository<TrajectoryGeoFactDto>
{ // {
private readonly IAsbCloudDbContext db; // private readonly IAsbCloudDbContext db;
private readonly IWellService wellService; // private readonly IWellService wellService;
public TrajectoryFactRepository(IAsbCloudDbContext db, IWellService wellService) // public TrajectoryFactRepository(IAsbCloudDbContext db, IWellService wellService)
{ // {
this.db = db; // this.db = db;
this.wellService = wellService; // this.wellService = wellService;
} // }
public async Task<IEnumerable<TrajectoryGeoFactDto>> GetAsync(int idWell, CancellationToken token)
{
var well = await wellService.GetOrDefaultAsync(idWell,
token);
if (well is null)
return Enumerable.Empty<TrajectoryGeoFactDto>();
var entities = await db.Record7 // public async Task<int> AddAsync(TrajectoryGeoFactDto importedFactTrajectoryRow, CancellationToken token)
.AsNoTracking() // {
.Where(x => x.IdTelemetry == well.IdTelemetry) // var offsetHours = wellService.GetTimezone(importedFactTrajectoryRow.IdWell).Hours;
.Where(coord => coord.Deptsvym != null && coord.Svyinc != null && coord.Svyazc != null) // var entity = Convert(importedFactTrajectoryRow, offsetHours);
.OrderBy(e => e.Deptsvym) // entity.Id = 0;
.ToArrayAsync(token); // db.FactTrajectories.Add(entity);
// return await db.SaveChangesAsync(token)
// .ConfigureAwait(false);
// }
var result = entities // public async Task<int> AddRangeAsync(IEnumerable<TrajectoryGeoFactDto> trajectoryRows, CancellationToken token)
.Select(coord => new TrajectoryGeoFactDto // {
{ // var idWell = trajectoryRows.First().IdWell;
IdWell = idWell, // if (!trajectoryRows.All(r => r.IdWell == idWell))
AzimuthMagnetic = coord.Svymtf, // throw new ArgumentInvalidException(nameof(trajectoryRows), "Все строки должны относиться к одной скважине");
VerticalDepth = coord.Deptsvyv,
WellboreDepth = coord.Deptsvym!.Value,
ZenithAngle = coord.Svyinc!.Value,
AzimuthGeo = coord.Svyazc!.Value
})
.ToArray();
return result; // var offsetHours = wellService.GetTimezone(idWell).Hours;
} // var entities = trajectoryRows
} // .Select(e =>
} // {
// var entity = Convert(e, offsetHours);
// entity.Id = 0;
// return entity;
// });
// db.FactTrajectories.AddRange(entities);
// return await db.SaveChangesAsync(token)
// .ConfigureAwait(false);
// }
// public async Task<int> DeleteByIdWellAsync(int idWell, CancellationToken token)
// {
// var query = db.FactTrajectories
// .Where(e => e.IdWell == idWell);
// db.FactTrajectories.RemoveRange(query);
// return await db.SaveChangesAsync(token)
// .ConfigureAwait(false);
// }
// public async Task<int> DeleteRangeAsync(IEnumerable<int> ids, CancellationToken token)
// {
// var query = db.FactTrajectories
// .Where(e => ids.Contains(e.Id));
// db.FactTrajectories.RemoveRange(query);
// return await db.SaveChangesAsync(token)
// .ConfigureAwait(false);
// }
// public async Task<IEnumerable<TrajectoryGeoFactDto>> GetAsync(int idWell, CancellationToken token)
// {
// var well = wellService.GetOrDefault(idWell)
// ?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist");
// var offsetHours = well.Timezone.Hours;
// var query = db.FactTrajectories
// .AsNoTracking()
// .Where(x => x.IdWell == idWell);
// var entities = await query
// .OrderBy(e => e.WellboreDepth)
// .ToArrayAsync(token);
// var result = entities
// .Select(r => Convert(r, offsetHours));
// return result;
// }
// public async Task<int> UpdateAsync(TrajectoryGeoFactDto row, CancellationToken token)
// {
// var offsetHours = wellService.GetTimezone(row.IdWell).Hours;
// var entity = Convert(row, offsetHours);
// db.FactTrajectories.Update(entity);
// return await db.SaveChangesAsync(token)
// .ConfigureAwait(false);
// }
// private TrajectoryGeoFactDto Convert(FactTrajectory entity, double offsetHours)
// {
// var dto = entity.Adapt<TrajectoryGeoFactDto>();
// dto.UpdateDate = entity.UpdateDate.ToRemoteDateTime(offsetHours);
// return dto;
// }
// private FactTrajectory Convert(TrajectoryGeoFactDto dto, double offsetHours)
// {
// var entity = dto.Adapt<FactTrajectory>();
// entity.UpdateDate = DateTime.Now.ToUtcDateTimeOffset(offsetHours);
// return entity;
// }
// }
//}

View File

@ -0,0 +1,53 @@
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository
{
internal class TrajectoryNnbRepository : ITrajectoryNnbRepository
{
private readonly IAsbCloudDbContext db;
private readonly IWellService wellService;
public TrajectoryNnbRepository(IAsbCloudDbContext db, IWellService wellService)
{
this.db = db;
this.wellService = wellService;
}
public async Task<IEnumerable<TrajectoryGeoFactDto>> GetAsync(int idWell, CancellationToken token)
{
var well = await wellService.GetOrDefaultAsync(idWell,
token);
if (well is null)
return Enumerable.Empty<TrajectoryGeoFactDto>();
var entities = await db.Record7
.AsNoTracking()
.Where(x => x.IdTelemetry == well.IdTelemetry)
.Where(coord => coord.Deptsvym != null && coord.Svyinc != null && coord.Svyazc != null)
.OrderBy(e => e.Deptsvym)
.ToArrayAsync(token);
var result = entities
.Select(coord => new TrajectoryGeoFactDto
{
IdWell = idWell,
AzimuthMagnetic = coord.Svymtf,
VerticalDepth = coord.Deptsvyv,
WellboreDepth = coord.Deptsvym!.Value,
ZenithAngle = coord.Svyinc!.Value,
AzimuthGeo = coord.Svyazc!.Value
})
.ToArray();
return result;
}
}
}

View File

@ -3,6 +3,7 @@ using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories; using AsbCloudApp.Repositories;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudDb.Model.Trajectory;
using Mapster; using Mapster;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System; using System;
@ -14,7 +15,9 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository namespace AsbCloudInfrastructure.Repository
{ {
public class TrajectoryPlanRepository : ITrajectoryPlanRepository public class TrajectoryPlanRepository<TEntity, Tdto> : ITrajectoryEditableRepository<Tdto>
where TEntity : Trajectory
where Tdto : TrajectoryGeoDto
{ {
private readonly IAsbCloudDbContext db; private readonly IAsbCloudDbContext db;
private readonly IWellService wellService; private readonly IWellService wellService;
@ -24,14 +27,14 @@ namespace AsbCloudInfrastructure.Repository
this.wellService = wellService; this.wellService = wellService;
} }
/// <inheritdoc/> /// <inheritdoc/>
public async Task<int> AddRangeAsync(IEnumerable<TrajectoryGeoPlanDto> plannedTrajectoryRows, CancellationToken token) public async Task<int> AddRangeAsync(IEnumerable<Tdto> trajectoryRows, CancellationToken token)
{ {
var idWell = plannedTrajectoryRows.First().IdWell; var idWell = trajectoryRows.First().IdWell;
if (!plannedTrajectoryRows.All(r => r.IdWell == idWell)) if (!trajectoryRows.All(r => r.IdWell == idWell))
throw new ArgumentInvalidException(nameof(plannedTrajectoryRows), "Все строки должны относиться к одной скважине"); throw new ArgumentInvalidException(nameof(trajectoryRows), "Все строки должны относиться к одной скважине");
var offsetHours = wellService.GetTimezone(idWell).Hours; var offsetHours = wellService.GetTimezone(idWell).Hours;
var entities = plannedTrajectoryRows var entities = trajectoryRows
.Select(e => .Select(e =>
{ {
var entity = Convert(e, offsetHours); var entity = Convert(e, offsetHours);
@ -39,18 +42,18 @@ namespace AsbCloudInfrastructure.Repository
return entity; return entity;
}); });
db.PlannedTrajectories.AddRange(entities); db.Set<TEntity>().AddRange(entities);
return await db.SaveChangesAsync(token) return await db.SaveChangesAsync(token)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
/// <inheritdoc/> /// <inheritdoc/>
public async Task<int> AddAsync(TrajectoryGeoPlanDto plannedTrajectoryRow, CancellationToken token) public async Task<int> AddAsync(Tdto trajectoryRow, CancellationToken token)
{ {
var offsetHours = wellService.GetTimezone(plannedTrajectoryRow.IdWell).Hours; var offsetHours = wellService.GetTimezone(trajectoryRow.IdWell).Hours;
var entity = Convert(plannedTrajectoryRow, offsetHours); var entity = Convert(trajectoryRow, offsetHours);
entity.Id = 0; entity.Id = 0;
db.PlannedTrajectories.Add(entity); db.Set<TEntity>().Add(entity);
return await db.SaveChangesAsync(token) return await db.SaveChangesAsync(token)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -58,9 +61,9 @@ namespace AsbCloudInfrastructure.Repository
/// <inheritdoc/> /// <inheritdoc/>
public async Task<int> DeleteRangeAsync(IEnumerable<int> ids, CancellationToken token) public async Task<int> DeleteRangeAsync(IEnumerable<int> ids, CancellationToken token)
{ {
var query = db.PlannedTrajectories var query = db.Set<TEntity>()
.Where(e => ids.Contains(e.Id)); .Where(e => ids.Contains(e.Id));
db.PlannedTrajectories.RemoveRange(query); db.Set<TEntity>().RemoveRange(query);
return await db.SaveChangesAsync(token) return await db.SaveChangesAsync(token)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -68,21 +71,21 @@ namespace AsbCloudInfrastructure.Repository
/// <inheritdoc/> /// <inheritdoc/>
public async Task<int> DeleteByIdWellAsync(int idWell, CancellationToken token) public async Task<int> DeleteByIdWellAsync(int idWell, CancellationToken token)
{ {
var query = db.PlannedTrajectories var query = db.Set<TEntity>()
.Where(e => e.IdWell == idWell); .Where(e => e.IdWell == idWell);
db.PlannedTrajectories.RemoveRange(query); db.Set<TEntity>().RemoveRange(query);
return await db.SaveChangesAsync(token) return await db.SaveChangesAsync(token)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
/// <inheritdoc/> /// <inheritdoc/>
public async Task<IEnumerable<TrajectoryGeoPlanDto>> GetAsync(int idWell, CancellationToken token) public async Task<IEnumerable<Tdto>> GetAsync(int idWell, CancellationToken token)
{ {
var well = wellService.GetOrDefault(idWell) var well = wellService.GetOrDefault(idWell)
?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist"); ?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist");
var offsetHours = well.Timezone.Hours; var offsetHours = well.Timezone.Hours;
var query = db.PlannedTrajectories var query = db.Set<TEntity>()
.AsNoTracking() .AsNoTracking()
.Where(x => x.IdWell == idWell); .Where(x => x.IdWell == idWell);
var entities = await query var entities = await query
@ -94,25 +97,25 @@ namespace AsbCloudInfrastructure.Repository
} }
/// <inheritdoc/> /// <inheritdoc/>
public async Task<int> UpdateAsync(TrajectoryGeoPlanDto row, CancellationToken token) public async Task<int> UpdateAsync(Tdto row, CancellationToken token)
{ {
var offsetHours = wellService.GetTimezone(row.IdWell).Hours; var offsetHours = wellService.GetTimezone(row.IdWell).Hours;
var entity = Convert(row, offsetHours); var entity = Convert(row, offsetHours);
db.PlannedTrajectories.Update(entity); db.Set<TEntity>().Update(entity);
return await db.SaveChangesAsync(token) return await db.SaveChangesAsync(token)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
private TrajectoryGeoPlanDto Convert(PlannedTrajectory entity, double offsetHours) private Tdto Convert(TEntity entity, double offsetHours)
{ {
var dto = entity.Adapt<TrajectoryGeoPlanDto>(); var dto = entity.Adapt<Tdto>();
dto.UpdateDate = entity.UpdateDate.ToRemoteDateTime(offsetHours); dto.UpdateDate = entity.UpdateDate.ToRemoteDateTime(offsetHours);
return dto; return dto;
} }
private PlannedTrajectory Convert(TrajectoryGeoPlanDto dto, double offsetHours) private TEntity Convert(Tdto dto, double offsetHours)
{ {
var entity = dto.Adapt<PlannedTrajectory>(); var entity = dto.Adapt<TEntity>();
entity.UpdateDate = DateTime.Now.ToUtcDateTimeOffset(offsetHours); entity.UpdateDate = DateTime.Now.ToUtcDateTimeOffset(offsetHours);
return entity; return entity;
} }

View File

@ -0,0 +1,59 @@
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.Trajectory
{
public class FactTrajectoryImportService : TrajectoryImportService<TrajectoryGeoFactDto>
{
public override string templateFileName { get; set; } = "FactTrajectoryTemplate.xlsx";
public override string usingTemplateFile { get; set; } = "AsbCloudInfrastructure.Services.Trajectory";
public override string sheetNamePlannedTrajectory { get; set; } = "Плановая траектория";
public override int headerRowsCount { get; set; } = 2;
public override int ColumnWellboreDepth { get; set; } = 1;
public override int ColumnZenithAngle { get; set; } = 2;
public override int ColumnAzimuthGeo { get; set; } = 3;
public override int ColumnAzimuthMagnetic { get; set; } = 4;
public override int ColumnVerticalDepth { get; set; } = 5;
public override int ColumnRadius { get; set; } = 6;
public override int ColumnComment { get; set; } = 7;
public FactTrajectoryImportService(
IWellService wellService,
ITrajectoryEditableRepository<TrajectoryGeoFactDto> factTrajectoryService)
: base(factTrajectoryService, wellService)
{
}
protected override void AddCoordinatesToRow(IXLRow row, TrajectoryGeoFactDto trajectory)
{
row.Cell(ColumnWellboreDepth).Value = trajectory.WellboreDepth;
row.Cell(ColumnZenithAngle).Value = trajectory.ZenithAngle;
row.Cell(ColumnAzimuthGeo).Value = trajectory.AzimuthGeo;
row.Cell(ColumnAzimuthMagnetic).Value = trajectory.AzimuthMagnetic;
row.Cell(ColumnVerticalDepth).Value = trajectory.VerticalDepth;
row.Cell(ColumnRadius).Value = trajectory.Radius;
row.Cell(ColumnComment).Value = trajectory.Comment;
}
protected override TrajectoryGeoFactDto ParseRow(IXLRow row)
{
var trajectoryRow = new TrajectoryGeoFactDto
{
WellboreDepth = row.Cell(ColumnWellboreDepth).GetCellValue<double>(),
ZenithAngle = row.Cell(ColumnZenithAngle).GetCellValue<double>(),
AzimuthGeo = row.Cell(ColumnAzimuthGeo).GetCellValue<double>(),
AzimuthMagnetic = row.Cell(ColumnAzimuthMagnetic).GetCellValue<double>(),
VerticalDepth = row.Cell(ColumnVerticalDepth).GetCellValue<double>(),
Radius = row.Cell(ColumnRadius).GetCellValue<double>(),
Comment = row.Cell(ColumnComment).GetCellValue<string?>()
};
return trajectoryRow;
}
}
}

View File

@ -0,0 +1,59 @@
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services.Trajectory
{
public class NnbTrajectoryImportService : TrajectoryImportService<TrajectoryGeoFactDto>
{
public override string templateFileName { get; set; } = "NnbTrajectoryTemplate.xlsx";
public override string usingTemplateFile { get; set; } = "AsbCloudInfrastructure.Services.Trajectory";
public override string sheetNamePlannedTrajectory { get; set; } = "Плановая траектория";
public override int headerRowsCount { get; set; } = 2;
public override int ColumnWellboreDepth { get; set; } = 1;
public override int ColumnZenithAngle { get; set; } = 2;
public override int ColumnAzimuthGeo { get; set; } = 3;
public override int ColumnAzimuthMagnetic { get; set; } = 4;
public override int ColumnVerticalDepth { get; set; } = 5;
public override int ColumnRadius { get; set; } = 6;
public override int ColumnComment { get; set; } = 7;
public NnbTrajectoryImportService(
IWellService wellService,
ITrajectoryNnbRepository nnbTrajectoryService)
: base(nnbTrajectoryService, wellService)
{
}
protected override void AddCoordinatesToRow(IXLRow row, TrajectoryGeoFactDto trajectory)
{
row.Cell(ColumnWellboreDepth).Value = trajectory.WellboreDepth;
row.Cell(ColumnZenithAngle).Value = trajectory.ZenithAngle;
row.Cell(ColumnAzimuthGeo).Value = trajectory.AzimuthGeo;
row.Cell(ColumnAzimuthMagnetic).Value = trajectory.AzimuthMagnetic;
row.Cell(ColumnVerticalDepth).Value = trajectory.VerticalDepth;
row.Cell(ColumnRadius).Value = trajectory.Radius;
row.Cell(ColumnComment).Value = trajectory.Comment;
}
protected override TrajectoryGeoFactDto ParseRow(IXLRow row)
{
var trajectoryRow = new TrajectoryGeoFactDto
{
WellboreDepth = row.Cell(ColumnWellboreDepth).GetCellValue<double>(),
ZenithAngle = row.Cell(ColumnZenithAngle).GetCellValue<double>(),
AzimuthGeo = row.Cell(ColumnAzimuthGeo).GetCellValue<double>(),
AzimuthMagnetic = row.Cell(ColumnAzimuthMagnetic).GetCellValue<double>(),
VerticalDepth = row.Cell(ColumnVerticalDepth).GetCellValue<double>(),
Radius = row.Cell(ColumnRadius).GetCellValue<double>(),
Comment = row.Cell(ColumnComment).GetCellValue<string?>()
};
return trajectoryRow;
}
}
}

View File

@ -1,6 +1,7 @@
using AsbCloudApp.Data; using AsbCloudApp.Data;
using AsbCloudApp.Repositories; using AsbCloudApp.Repositories;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb.Model;
using ClosedXML.Excel; using ClosedXML.Excel;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -12,170 +13,47 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.Trajectory namespace AsbCloudInfrastructure.Services.Trajectory
{ {
public class PlannedTrajectoryImportService : IPlannedTrajectoryImportService public class PlannedTrajectoryImportService : TrajectoryImportService<TrajectoryGeoPlanDto> //IPlannedTrajectoryImportService
{ {
/* /*
* password for PlannedTrajectoryTemplate.xlsx is Drill2022 * password for PlannedTrajectoryTemplate.xlsx is Drill2022
*/ */
private readonly IWellService wellService; private readonly IWellService wellService;
private readonly ITrajectoryPlanRepository plannedTrajectoryService; private readonly ITrajectoryEditableRepository<TrajectoryGeoPlanDto> plannedTrajectoryService;
private const string templateFileName = "PlannedTrajectoryTemplate.xlsx"; //private const string templateFileName = "PlannedTrajectoryTemplate.xlsx";
private const string usingTemplateFile = "AsbCloudInfrastructure.Services.Trajectory"; //private const string usingTemplateFile = "AsbCloudInfrastructure.Services.Trajectory";
private const string sheetNamePlannedTrajectory = "Плановая траектория"; //private const string sheetNamePlannedTrajectory = "Плановая траектория";
private const int headerRowsCount = 2; //private const int headerRowsCount = 2;
private const int ColumnWellboreDepth = 1; //private const int ColumnWellboreDepth = 1;
private const int ColumnZenithAngle = 2; //private const int ColumnZenithAngle = 2;
private const int ColumnAzimuthGeo = 3; //private const int ColumnAzimuthGeo = 3;
private const int ColumnAzimuthMagnetic = 4; //private const int ColumnAzimuthMagnetic = 4;
private const int ColumnVerticalDepth = 5; //private const int ColumnVerticalDepth = 5;
private const int ColumnRadius = 6; //private const int ColumnRadius = 6;
private const int ColumnComment = 7; //private const int ColumnComment = 7;
public override string templateFileName { get; set; } = "PlannedTrajectoryTemplate.xlsx";
public override string usingTemplateFile { get; set; } = "AsbCloudInfrastructure.Services.Trajectory";
public override string sheetNamePlannedTrajectory { get; set; } = "Плановая траектория";
public override int headerRowsCount { get; set; } = 2;
public override int ColumnWellboreDepth { get; set; } = 1;
public override int ColumnZenithAngle { get; set; } = 2;
public override int ColumnAzimuthGeo { get; set; } = 3;
public override int ColumnAzimuthMagnetic { get; set; } = 4;
public override int ColumnVerticalDepth { get; set; } = 5;
public override int ColumnRadius { get; set; } = 6;
public override int ColumnComment { get; set; } = 7;
public PlannedTrajectoryImportService(IWellService wellService, ITrajectoryPlanRepository plannedTrajectoryService) public PlannedTrajectoryImportService(
IWellService wellService,
ITrajectoryEditableRepository<TrajectoryGeoPlanDto> plannedTrajectoryService)
: base(plannedTrajectoryService, wellService)
{ {
this.wellService = wellService; this.wellService = wellService;
this.plannedTrajectoryService = plannedTrajectoryService; }
}
public Stream GetTemplateFile() protected override TrajectoryGeoPlanDto ParseRow(IXLRow row)
{
var stream = System.Reflection.Assembly.GetExecutingAssembly()
.GetManifestResourceStream($"{usingTemplateFile}.{templateFileName}");
if (stream is null)
throw new Exception($"Область {usingTemplateFile} не содержит файла с названием {templateFileName}");
return stream;
}
public async Task<string> GetFileNameAsync(int idWell, CancellationToken token)
{
var fileName = await wellService.GetWellCaptionByIdAsync(idWell, token) + "_plannedTrajectory.xlsx";
return fileName;
}
public async Task<Stream> ExportAsync(int idWell, CancellationToken token)
{
var plannedTrajectorys = await plannedTrajectoryService.GetAsync(idWell, token);
return MakeExelFileStream(plannedTrajectorys);
}
private Stream MakeExelFileStream(IEnumerable<TrajectoryGeoPlanDto> plannedTrajectories)
{
using Stream ecxelTemplateStream = GetTemplateFile();
using var workbook = new XLWorkbook(ecxelTemplateStream, XLEventTracking.Disabled);
AddPlannedTrajecoryToWorkbook(workbook, plannedTrajectories);
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
private static void AddPlannedTrajecoryToWorkbook(XLWorkbook workbook, IEnumerable<TrajectoryGeoPlanDto> plannedTrajectories)
{
if (plannedTrajectories.Any())
{
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlannedTrajectory);
if (sheet is null)
throw new FileFormatException($"Лист с именем {sheetNamePlannedTrajectory} отсутствует, либо имеет некорректное название");
AddPlannedTrajecoryToSheet(sheet, plannedTrajectories);
}
}
private static void AddPlannedTrajecoryToSheet(IXLWorksheet sheet, IEnumerable<TrajectoryGeoPlanDto> plannedTrajectories)
{
var rowList = plannedTrajectories.ToList();
for (int i = 0; i < rowList.Count; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
AddCoordinatesToRow(row, rowList[i]);
}
}
private static void AddCoordinatesToRow(IXLRow row, TrajectoryGeoPlanDto trajectory)
{
row.Cell(ColumnWellboreDepth).Value = trajectory.WellboreDepth;
row.Cell(ColumnZenithAngle).Value = trajectory.ZenithAngle;
row.Cell(ColumnAzimuthGeo).Value = trajectory.AzimuthGeo;
row.Cell(ColumnAzimuthMagnetic).Value = trajectory.AzimuthMagnetic;
row.Cell(ColumnVerticalDepth).Value = trajectory.VerticalDepth;
row.Cell(ColumnRadius).Value = trajectory.Radius;
row.Cell(ColumnComment).Value = trajectory.Comment;
}
public async Task<int> ImportAsync(int idWell, int idUser, Stream stream, bool deletePrevRows, CancellationToken token)
{
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
var trajectoryRows = ParseFileStream(stream);
foreach (var row in trajectoryRows)
{
row.IdWell = idWell;
row.IdUser = idUser;
}
var rowsCount = await SavePlannedTrajectoryAsync(idWell, trajectoryRows, deletePrevRows, token);
return rowsCount;
}
private async Task<int> SavePlannedTrajectoryAsync(int idWell, IEnumerable<TrajectoryGeoPlanDto> newRows, bool deletePrevRow, CancellationToken token)
{
if (deletePrevRow)
await plannedTrajectoryService.DeleteByIdWellAsync(idWell, token);
var rowsCount = await plannedTrajectoryService.AddRangeAsync(newRows, token);
return rowsCount;
}
private IEnumerable<TrajectoryGeoPlanDto> ParseFileStream(Stream stream)
{
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
return ParseWorkbook(workbook);
}
private IEnumerable<TrajectoryGeoPlanDto> ParseWorkbook(IXLWorkbook workbook)
{
var sheetPlannedTrajectory = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlannedTrajectory);
if (sheetPlannedTrajectory is null)
throw new FileFormatException($"Книга excel не содержит листа {sheetNamePlannedTrajectory}.");
var plannedTrajectoryRows = ParseSheet(sheetPlannedTrajectory);
return plannedTrajectoryRows;
}
private IEnumerable<TrajectoryGeoPlanDto> ParseSheet(IXLWorksheet sheet)
{
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 7)
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
var count = sheet.RowsUsed().Count() - headerRowsCount;
if (count > 1024)
throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество строк.");
if (count <= 0)
throw new FileFormatException($"Лист {sheet.Name} некорректного формата либо пустой");
var trajectoryRows = new List<TrajectoryGeoPlanDto>(count);
var parseErrors = new List<string>();
for (int i = 0; i < count; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
try
{
var trajectoryRow = ParseRow(row);
trajectoryRows.Add(trajectoryRow);
}
catch (FileFormatException ex)
{
parseErrors.Add(ex.Message);
}
}
if (parseErrors.Any())
throw new FileFormatException(string.Join("\r\n", parseErrors));
return trajectoryRows;
}
private TrajectoryGeoPlanDto ParseRow(IXLRow row)
{ {
var trajectoryRow = new TrajectoryGeoPlanDto var trajectoryRow = new TrajectoryGeoPlanDto
{ {
@ -190,6 +68,17 @@ namespace AsbCloudInfrastructure.Services.Trajectory
return trajectoryRow; return trajectoryRow;
} }
protected override void AddCoordinatesToRow(IXLRow row, TrajectoryGeoPlanDto trajectory)
{
row.Cell(ColumnWellboreDepth).Value = trajectory.WellboreDepth;
row.Cell(ColumnZenithAngle).Value = trajectory.ZenithAngle;
row.Cell(ColumnAzimuthGeo).Value = trajectory.AzimuthGeo;
row.Cell(ColumnAzimuthMagnetic).Value = trajectory.AzimuthMagnetic;
row.Cell(ColumnVerticalDepth).Value = trajectory.VerticalDepth;
row.Cell(ColumnRadius).Value = trajectory.Radius;
row.Cell(ColumnComment).Value = trajectory.Comment;
}
} }
} }

View File

@ -0,0 +1,159 @@
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.SAUB;
using ClosedXML.Excel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.Trajectory
{
public abstract class TrajectoryImportService<T> where T: TrajectoryGeoDto
{
protected readonly IWellService wellService;
protected readonly ITrajectoryRepository<T> trajectoryService;
public abstract string templateFileName { get; set; }
public abstract string usingTemplateFile { get; set; }
public abstract string sheetNamePlannedTrajectory { get; set; }
public abstract int headerRowsCount { get; set; }
public abstract int ColumnWellboreDepth { get; set; }
public abstract int ColumnZenithAngle { get; set; }
public abstract int ColumnAzimuthGeo { get; set; }
public abstract int ColumnAzimuthMagnetic { get; set; }
public abstract int ColumnVerticalDepth { get; set; }
public abstract int ColumnRadius { get; set; }
public abstract int ColumnComment { get; set; }
protected abstract void AddCoordinatesToRow(IXLRow row, T trajectory);
protected abstract T ParseRow(IXLRow row);
public TrajectoryImportService(ITrajectoryRepository<T> trajectoryService, IWellService wellService)
{
this.trajectoryService = trajectoryService;
this.wellService = wellService;
}
public Stream GetTemplateFile()
{
var stream = System.Reflection.Assembly.GetExecutingAssembly()
.GetManifestResourceStream($"{usingTemplateFile}.{templateFileName}");
if (stream is null)
throw new Exception($"Область {usingTemplateFile} не содержит файла с названием {templateFileName}");
return stream;
}
public async Task<Stream> ExportAsync(int idWell, CancellationToken token)
{
var plannedTrajectorys = await trajectoryService.GetAsync(idWell, token);
return MakeExelFileStream(plannedTrajectorys);
}
private Stream MakeExelFileStream(IEnumerable<T> plannedTrajectories)
{
using Stream ecxelTemplateStream = GetTemplateFile();
using var workbook = new XLWorkbook(ecxelTemplateStream, XLEventTracking.Disabled);
AddPlannedTrajecoryToWorkbook(workbook, plannedTrajectories);
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
private void AddPlannedTrajecoryToWorkbook(XLWorkbook workbook, IEnumerable<T> plannedTrajectories)
{
if (plannedTrajectories.Any())
{
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlannedTrajectory);
if (sheet is null)
throw new FileFormatException($"Лист с именем {sheetNamePlannedTrajectory} отсутствует, либо имеет некорректное название");
AddPlannedTrajecoryToSheet(sheet, plannedTrajectories);
}
}
private void AddPlannedTrajecoryToSheet(IXLWorksheet sheet, IEnumerable<T> plannedTrajectories)
{
var rowList = plannedTrajectories.ToList();
for (int i = 0; i < rowList.Count; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
AddCoordinatesToRow(row, rowList[i]);
}
}
public async Task<string> GetFileNameAsync(int idWell, CancellationToken token)
{
var caption = await wellService.GetWellCaptionByIdAsync(idWell, token);
return string.Format("{0}_{1}", caption, templateFileName);
}
public async Task<IEnumerable<T>> ImportAsync(int idWell, int idUser, Stream stream, CancellationToken token)
{
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
var trajectoryRows = ParseFileStream(stream);
foreach (var row in trajectoryRows)
{
row.IdWell = idWell;
row.IdUser = idUser;
}
return trajectoryRows;
}
private IEnumerable<T> ParseFileStream(Stream stream)
{
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
return ParseWorkbook(workbook);
}
private IEnumerable<T> ParseWorkbook(IXLWorkbook workbook)
{
var sheetTrajectory = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlannedTrajectory);
if (sheetTrajectory is null)
throw new FileFormatException($"Книга excel не содержит листа {sheetNamePlannedTrajectory}.");
var trajectoryRows = ParseSheet(sheetTrajectory);
return trajectoryRows;
}
private IEnumerable<T> ParseSheet(IXLWorksheet sheet)
{
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 7)
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
var count = sheet.RowsUsed().Count() - headerRowsCount;
if (count > 1024)
throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество строк.");
if (count <= 0)
throw new FileFormatException($"Лист {sheet.Name} некорректного формата либо пустой");
var trajectoryRows = new List<T>(count);
var parseErrors = new List<string>();
for (int i = 0; i < count; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
try
{
var trajectoryRow = ParseRow(row);
trajectoryRows.Add(trajectoryRow);
}
catch (FileFormatException ex)
{
parseErrors.Add(ex.Message);
}
}
if (parseErrors.Any())
throw new FileFormatException(string.Join("\r\n", parseErrors));
return trajectoryRows;
}
}
}

View File

@ -91,7 +91,7 @@ abstract class TrajectoryBaseService<TGeo, TCartesian>
class TrajectoryPlanService: TrajectoryBaseService<TrajectoryGeoPlanDto, TrajectoryCartesianPlanDto> class TrajectoryPlanService: TrajectoryBaseService<TrajectoryGeoPlanDto, TrajectoryCartesianPlanDto>
{ {
public TrajectoryPlanService(ITrajectoryPlanRepository repository) public TrajectoryPlanService(ITrajectoryEditableRepository<TrajectoryGeoPlanDto> repository)
:base(repository) :base(repository)
{} {}
@ -109,7 +109,14 @@ class TrajectoryPlanService: TrajectoryBaseService<TrajectoryGeoPlanDto, Traject
class TrajectoryFactService : TrajectoryBaseService<TrajectoryGeoFactDto, TrajectoryCartesianFactDto> class TrajectoryFactService : TrajectoryBaseService<TrajectoryGeoFactDto, TrajectoryCartesianFactDto>
{ {
public TrajectoryFactService(ITrajectoryFactRepository repository) public TrajectoryFactService(ITrajectoryEditableRepository<TrajectoryGeoFactDto> repository)
: base(repository)
{ }
}
class TrajectoryNnbService : TrajectoryBaseService<TrajectoryGeoFactDto, TrajectoryCartesianFactDto>
{
public TrajectoryNnbService(ITrajectoryNnbRepository repository)
: base(repository) : base(repository)
{ } { }
} }
@ -119,11 +126,16 @@ public class TrajectoryService
{ {
private TrajectoryPlanService trajectoryPlanService; private TrajectoryPlanService trajectoryPlanService;
private TrajectoryFactService trajectoryFactService; private TrajectoryFactService trajectoryFactService;
private TrajectoryNnbService trajectoryNnbService;
public TrajectoryService(ITrajectoryPlanRepository plannedRepository, ITrajectoryFactRepository factRepository) public TrajectoryService(
ITrajectoryEditableRepository<TrajectoryGeoPlanDto> plannedRepository,
ITrajectoryEditableRepository<TrajectoryGeoFactDto> factRepository,
ITrajectoryNnbRepository nnbRepository)
{ {
trajectoryPlanService = new TrajectoryPlanService(plannedRepository); trajectoryPlanService = new TrajectoryPlanService(plannedRepository);
trajectoryFactService = new TrajectoryFactService(factRepository); trajectoryFactService = new TrajectoryFactService(factRepository);
trajectoryNnbService = new TrajectoryNnbService(nnbRepository);
} }
/// <summary> /// <summary>
@ -132,12 +144,13 @@ public class TrajectoryService
/// <param name="idWell">ключ скважины</param> /// <param name="idWell">ключ скважины</param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
public async Task<PlanFactBase<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>> GetTrajectoryCartesianAsync(int idWell, CancellationToken token) public async Task<PlanFactBase<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>, IEnumerable<TrajectoryCartesianFactDto>>> GetTrajectoryCartesianAsync(int idWell, CancellationToken token)
{ {
var result = new PlanFactBase<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>(); var result = new PlanFactBase<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>, IEnumerable<TrajectoryCartesianFactDto>>();
result.Plan = await trajectoryPlanService.GetAsync(idWell, token); result.Plan = await trajectoryPlanService.GetAsync(idWell, token);
result.Fact = await trajectoryFactService.GetAsync(idWell, token); result.Fact = await trajectoryFactService.GetAsync(idWell, token);
result.Nnb = await trajectoryNnbService.GetAsync(idWell, token);
return result; return result;
} }

View File

@ -44,9 +44,10 @@ namespace AsbCloudWebApi.Tests.ServicesTests
new TrajectoryGeoFactDto() { WellboreDepth = 0, ZenithAngle = 0, AzimuthGeo = 20 }, new TrajectoryGeoFactDto() { WellboreDepth = 0, ZenithAngle = 0, AzimuthGeo = 20 },
}; };
var mockPlan = MakeTrajectoryRepositoryMock<ITrajectoryPlanRepository, TrajectoryGeoPlanDto>(plannedTrajectory); var mockPlan = MakeTrajectoryRepositoryMock<ITrajectoryEditableRepository<TrajectoryGeoPlanDto>, TrajectoryGeoPlanDto>(plannedTrajectory);
var mockFact = MakeTrajectoryRepositoryMock<ITrajectoryFactRepository, TrajectoryGeoFactDto>(actualTrajectory); var mockFact = MakeTrajectoryRepositoryMock<ITrajectoryEditableRepository<TrajectoryGeoFactDto>, TrajectoryGeoFactDto>(actualTrajectory);
var service = new TrajectoryService(mockPlan.Object, mockFact.Object); var mockNnb = MakeTrajectoryRepositoryMock<ITrajectoryNnbRepository, TrajectoryGeoFactDto>(actualTrajectory);
var service = new TrajectoryService(mockPlan.Object, mockFact.Object, mockNnb.Object);
var result = await service.GetTrajectoryCartesianAsync(1, CancellationToken.None); var result = await service.GetTrajectoryCartesianAsync(1, CancellationToken.None);
Assert.Equal(plannedTrajectory.Length, result.Plan?.Count()); Assert.Equal(plannedTrajectory.Length, result.Plan?.Count());
Assert.Equal(actualTrajectory.Length, result.Fact?.Count()); Assert.Equal(actualTrajectory.Length, result.Fact?.Count());
@ -75,9 +76,10 @@ namespace AsbCloudWebApi.Tests.ServicesTests
new TrajectoryGeoFactDto() { WellboreDepth = 50, ZenithAngle = 0, AzimuthGeo = 0 }, new TrajectoryGeoFactDto() { WellboreDepth = 50, ZenithAngle = 0, AzimuthGeo = 0 },
}; };
var mockPlan = MakeTrajectoryRepositoryMock<ITrajectoryPlanRepository, TrajectoryGeoPlanDto>(plannedTrajectory); var mockPlan = MakeTrajectoryRepositoryMock<ITrajectoryEditableRepository<TrajectoryGeoPlanDto>, TrajectoryGeoPlanDto>(plannedTrajectory);
var mockFact = MakeTrajectoryRepositoryMock<ITrajectoryFactRepository, TrajectoryGeoFactDto>(actualTrajectory); var mockFact = MakeTrajectoryRepositoryMock<ITrajectoryEditableRepository<TrajectoryGeoFactDto>, TrajectoryGeoFactDto>(actualTrajectory);
var service = new TrajectoryService(mockPlan.Object, mockFact.Object); var mockNnb = MakeTrajectoryRepositoryMock<ITrajectoryNnbRepository, TrajectoryGeoFactDto>(actualTrajectory);
var service = new TrajectoryService(mockPlan.Object, mockFact.Object, mockNnb.Object);
var result = await service.GetTrajectoryCartesianAsync(1, CancellationToken.None); var result = await service.GetTrajectoryCartesianAsync(1, CancellationToken.None);
var lastPointPlan = result.Plan!.Last(); var lastPointPlan = result.Plan!.Last();
var lastPointFact = result.Fact!.Last(); var lastPointFact = result.Fact!.Last();
@ -108,9 +110,10 @@ namespace AsbCloudWebApi.Tests.ServicesTests
new TrajectoryGeoFactDto() { WellboreDepth = 20, ZenithAngle = 0, AzimuthGeo = 0 }, new TrajectoryGeoFactDto() { WellboreDepth = 20, ZenithAngle = 0, AzimuthGeo = 0 },
}; };
var mockPlanned = MakeTrajectoryRepositoryMock<ITrajectoryPlanRepository, TrajectoryGeoPlanDto>(plannedTrajectory); var mockPlanned = MakeTrajectoryRepositoryMock<ITrajectoryEditableRepository<TrajectoryGeoPlanDto>, TrajectoryGeoPlanDto>(plannedTrajectory);
var mockFactual = MakeTrajectoryRepositoryMock<ITrajectoryFactRepository, TrajectoryGeoFactDto>(actualTrajectory); var mockFactual = MakeTrajectoryRepositoryMock<ITrajectoryEditableRepository<TrajectoryGeoFactDto>, TrajectoryGeoFactDto>(actualTrajectory);
var service = new TrajectoryService(mockPlanned.Object, mockFactual.Object); var mockNnb = MakeTrajectoryRepositoryMock<ITrajectoryNnbRepository, TrajectoryGeoFactDto>(actualTrajectory);
var service = new TrajectoryService(mockPlanned.Object, mockFactual.Object, mockNnb.Object);
var result = await service.GetTrajectoryCartesianAsync(1, CancellationToken.None); var result = await service.GetTrajectoryCartesianAsync(1, CancellationToken.None);
var lastPointPlan = result.Plan!.Last(); var lastPointPlan = result.Plan!.Last();
var lastPointFact = result.Fact!.Last(); var lastPointFact = result.Fact!.Last();

View File

@ -1,42 +0,0 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace AsbCloudWebApi.Controllers;
/// <summary>
/// Фактическая траектория
/// </summary>
[Authorize]
[ApiController]
[Route("api/well/{idWell}/[controller]")]
public class FactTrajectoryController : ControllerBase
{
private readonly ITrajectoryFactRepository trajectoryFactRepository;
public FactTrajectoryController(ITrajectoryFactRepository trajectoryFactRepository)
{
this.trajectoryFactRepository = trajectoryFactRepository;
}
/// <summary>
/// Метод получения всех строк траекторий по id скважины
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="cancellationToken">Токен отмены операции</param>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<TrajectoryGeoPlanDto>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetRowsAsync([FromRoute] int idWell,
CancellationToken cancellationToken)
{
var factTrajectories = await trajectoryFactRepository.GetAsync(idWell,
cancellationToken);
return Ok(factTrajectories);
}
}

View File

@ -0,0 +1,209 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudInfrastructure.Services;
using AsbCloudInfrastructure.Services.Trajectory;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace AsbCloudWebApi.Controllers.Trajectory;
/// <summary>
/// Фактическая траектория
/// </summary>
[Authorize]
[ApiController]
[Route("api/well/{idWell}/[controller]")]
public class FactTrajectoryController : ControllerBase
{
private readonly ITrajectoryEditableRepository<TrajectoryGeoFactDto> trajectoryFactRepository;
private readonly IWellService wellService;
private readonly FactTrajectoryImportService factTrajectoryImportService;
public FactTrajectoryController(
ITrajectoryEditableRepository<TrajectoryGeoFactDto> trajectoryFactRepository,
IWellService wellService,
FactTrajectoryImportService factTrajectoryImportService)
{
this.trajectoryFactRepository = trajectoryFactRepository;
this.wellService = wellService;
this.factTrajectoryImportService = factTrajectoryImportService;
}
/// <summary>
/// Метод получения всех строк фактических траекторий по id скважины
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="cancellationToken">Токен отмены операции</param>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<TrajectoryGeoFactDto>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetRowsAsync([FromRoute] int idWell,
CancellationToken cancellationToken)
{
var importedFactTrajectories = await trajectoryFactRepository.GetAsync(idWell,
cancellationToken);
return Ok(importedFactTrajectories);
}
/// <summary>
/// Добавить одну новую строчку координат для фактической траектории
/// </summary>
/// <param name="idWell"></param>
/// <param name="row"></param>
/// <param name="token"></param>
/// <returns>количество успешно записанных строк в БД</returns>
[HttpPost]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> AddAsync(int idWell, [FromBody] TrajectoryGeoFactDto row,
CancellationToken token)
{
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
return Forbid();
var idUser = User.GetUserId();
if (!idUser.HasValue)
return Forbid();
row.IdUser = idUser.Value;
row.IdWell = idWell;
var result = await trajectoryFactRepository.AddAsync(row, token);
return Ok(result);
}
/// <summary>
/// Изменить выбранную строку с координатами
/// </summary>
/// <param name="idWell"></param>
/// <param name="idRow"></param>
/// <param name="row"></param>
/// <param name="token"></param>
/// <returns>количество успешно обновленных строк в БД</returns>
[HttpPut("{idRow}")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> UpdateAsync(int idWell, int idRow,
[FromBody] TrajectoryGeoFactDto row, CancellationToken token)
{
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
return Forbid();
int? idUser = User.GetUserId();
if (!idUser.HasValue)
return Forbid();
row.Id = idRow;
row.IdUser = idUser.Value;
row.IdWell = idWell;
var result = await trajectoryFactRepository.UpdateAsync(row, token);
return Ok(result);
}
/// <summary>
/// Удалить выбранную строку с координатами
/// </summary>
/// <param name="idWell"></param>
/// <param name="idRow"></param>
/// <param name="token"></param>
/// <returns>количество успешно удаленных строк из БД</returns>
[HttpDelete("{idRow}")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> DeleteAsync(int idWell, int idRow, CancellationToken token)
{
if (!await CanUserAccessToWellAsync(idWell,
token).ConfigureAwait(false))
return Forbid();
var result = await trajectoryFactRepository.DeleteRangeAsync(new int[] { idRow }, token);
return Ok(result);
}
/// <summary>
/// Формируем excel файл с текущими строками фактической траектории
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns>Запрашиваемый файл</returns>
[HttpGet("export")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<IActionResult> ExportAsync([FromRoute] int idWell, CancellationToken token)
{
if (!await CanUserAccessToWellAsync(idWell,
token).ConfigureAwait(false))
return Forbid();
var stream = await factTrajectoryImportService.ExportAsync(idWell, token);
var fileName = await factTrajectoryImportService.GetFileNameAsync(idWell, token);
return File(stream, "application/octet-stream", fileName);
}
/// <summary>
/// Возвращает excel шаблон для заполнения строк фактической траектории
/// </summary>
/// <returns>Запрашиваемый файл</returns>
[HttpGet("template")]
[AllowAnonymous]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public IActionResult GetTemplate()
{
var stream = factTrajectoryImportService.GetTemplateFile();
var fileName = "ЕЦП_шаблон_файлаактическая_импортируемая_траектория.xlsx";
return File(stream, "application/octet-stream", fileName);
}
/// <summary>
/// Импортирует координаты из excel (xlsx) файла
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="files">Коллекция из одного файла xlsx</param>
/// <param name="deleteBeforeImport">Удалить операции перед импортом, если фал валидный</param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns>количество успешно записанных строк в БД</returns>
[HttpPost("import/{deleteBeforeImport}")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
public async Task<IActionResult> ImportAsync(int idWell,
[FromForm] IFormFileCollection files,
bool deleteBeforeImport,
CancellationToken token)
{
int? idUser = User.GetUserId();
if (!idUser.HasValue)
return Forbid();
if (!await CanUserAccessToWellAsync(idWell,
token).ConfigureAwait(false))
return Forbid();
if (files.Count < 1)
return this.ValidationBadRequest(nameof(files), "нет файла");
var file = files[0];
if (Path.GetExtension(file.FileName).ToLower() != ".xlsx")
return this.ValidationBadRequest(nameof(files), "Требуется xlsx файл.");
using Stream stream = file.OpenReadStream();
try
{
var trajectoryRows = await factTrajectoryImportService.ImportAsync(idWell, idUser.Value, stream, token);
if (deleteBeforeImport)
await trajectoryFactRepository.DeleteByIdWellAsync(idWell, token);
var rowsCount = await trajectoryFactRepository.AddRangeAsync(trajectoryRows, token);
return Ok(rowsCount);
}
catch (FileFormatException ex)
{
return this.ValidationBadRequest(nameof(files), ex.Message);
}
}
private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token)
{
int? idCompany = User.GetCompanyId();
return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,80 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudInfrastructure.Services;
using AsbCloudInfrastructure.Services.Trajectory;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace AsbCloudWebApi.Controllers.Trajectory;
/// <summary>
/// Фактическая траектория из ННБ
/// </summary>
[Authorize]
[ApiController]
[Route("api/well/{idWell}/[controller]")]
public class NnbTrajectoryController : ControllerBase
{
private readonly ITrajectoryNnbRepository trajectoryNnbRepository;
private readonly NnbTrajectoryImportService factNnbTrajectoryImportService;
private readonly IWellService wellService;
public NnbTrajectoryController(
ITrajectoryNnbRepository trajectoryNnbRepository,
NnbTrajectoryImportService factNnbTrajectoryImportService,
IWellService wellService)
{
this.trajectoryNnbRepository = trajectoryNnbRepository;
this.factNnbTrajectoryImportService = factNnbTrajectoryImportService;
this.wellService = wellService;
this.wellService = wellService;
}
/// <summary>
/// Метод получения всех строк фактических траекторий по id скважины из ННБ
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="cancellationToken">Токен отмены операции</param>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<TrajectoryGeoFactDto>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetRowsAsync([FromRoute] int idWell,
CancellationToken cancellationToken)
{
var nnbFactTrajectories = await trajectoryNnbRepository.GetAsync(idWell,
cancellationToken);
return Ok(nnbFactTrajectories);
}
/// <summary>
/// Формируем excel файл с текущими строками фактической ннб-траектории
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns>Запрашиваемый файл</returns>
[HttpGet("export")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<IActionResult> ExportAsync([FromRoute] int idWell, CancellationToken token)
{
if (!await CanUserAccessToWellAsync(idWell,
token).ConfigureAwait(false))
return Forbid();
var stream = await factNnbTrajectoryImportService.ExportAsync(idWell, token);
var fileName = await factNnbTrajectoryImportService.GetFileNameAsync(idWell, token);
return File(stream, "application/octet-stream", fileName);
}
private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token)
{
int? idCompany = User.GetCompanyId();
return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false);
}
}

View File

@ -10,7 +10,7 @@ using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AsbCloudWebApi.Controllers namespace AsbCloudWebApi.Controllers.Trajectory
{ {
/// <summary> /// <summary>
@ -22,13 +22,13 @@ namespace AsbCloudWebApi.Controllers
public class PlannedTrajectoryController : ControllerBase public class PlannedTrajectoryController : ControllerBase
{ {
private readonly IWellService wellService; private readonly IWellService wellService;
private readonly IPlannedTrajectoryImportService plannedTrajectoryImportService; private readonly PlannedTrajectoryImportService plannedTrajectoryImportService;
private readonly ITrajectoryPlanRepository plannedTrajectoryRepository; private readonly ITrajectoryEditableRepository<TrajectoryGeoPlanDto> plannedTrajectoryRepository;
private readonly TrajectoryService trajectoryVisualizationService; private readonly TrajectoryService trajectoryVisualizationService;
public PlannedTrajectoryController(IWellService wellService, public PlannedTrajectoryController(IWellService wellService,
IPlannedTrajectoryImportService plannedTrajectoryImportService, PlannedTrajectoryImportService plannedTrajectoryImportService,
ITrajectoryPlanRepository plannedTrajectoryRepository, ITrajectoryEditableRepository<TrajectoryGeoPlanDto> plannedTrajectoryRepository,
TrajectoryService trajectoryVisualizationService) TrajectoryService trajectoryVisualizationService)
{ {
this.plannedTrajectoryImportService = plannedTrajectoryImportService; this.plannedTrajectoryImportService = plannedTrajectoryImportService;
@ -43,7 +43,7 @@ namespace AsbCloudWebApi.Controllers
/// <returns>Запрашиваемый файл</returns> /// <returns>Запрашиваемый файл</returns>
[HttpGet("template")] [HttpGet("template")]
[AllowAnonymous] [AllowAnonymous]
[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)]
public IActionResult GetTemplate() public IActionResult GetTemplate()
{ {
@ -102,8 +102,14 @@ namespace AsbCloudWebApi.Controllers
try try
{ {
var result = await plannedTrajectoryImportService.ImportAsync(idWell, idUser.Value, stream, deleteBeforeImport, token); var trajectoryRows = await plannedTrajectoryImportService.ImportAsync(idWell, idUser.Value, stream, token);
return Ok(result);
if (deleteBeforeImport)
await plannedTrajectoryRepository.DeleteByIdWellAsync(idWell, token);
var rowsCount = await plannedTrajectoryRepository.AddRangeAsync(trajectoryRows, token);
return Ok(rowsCount);
} }
catch (FileFormatException ex) catch (FileFormatException ex)
{ {
@ -229,7 +235,7 @@ namespace AsbCloudWebApi.Controllers
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet("trajectoryCartesianPlanFact")] [HttpGet("trajectoryCartesianPlanFact")]
[ProducesResponseType(typeof(PlanFactBase<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>), (int)System.Net.HttpStatusCode.OK)] [ProducesResponseType(typeof(PlanFactBase<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>, IEnumerable<TrajectoryCartesianFactDto>>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetTrajectoryCartesianPlanFactAsync(int idWell, CancellationToken token) public async Task<IActionResult> GetTrajectoryCartesianPlanFactAsync(int idWell, CancellationToken token)
{ {
if (!await CanUserAccessToWellAsync(idWell, if (!await CanUserAccessToWellAsync(idWell,
@ -245,7 +251,7 @@ namespace AsbCloudWebApi.Controllers
int? idCompany = User.GetCompanyId(); int? idCompany = User.GetCompanyId();
return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false); idWell, token).ConfigureAwait(false);
} }
} }
} }