forked from ddrilling/AsbCloudServer
Reviewed-on: http://test.digitaldrilling.ru:8080/DDrilling/AsbCloudServer/pulls/199 Reviewed-by: on.nemtina <on.nemtina@digitaldrilling.ru> Reviewed-by: Степанов Дмитрий Александрович <da.stepanov@digitaldrilling.ru>
This commit is contained in:
commit
6045333f53
58
AsbCloudApp/Data/ChangeLogAbstract.cs
Normal file
58
AsbCloudApp/Data/ChangeLogAbstract.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
|
||||
namespace AsbCloudApp.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Часть записи описывающая изменение
|
||||
/// </summary>
|
||||
public abstract class ChangeLogAbstract
|
||||
{
|
||||
/// <summary>
|
||||
/// ИД записи
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Автор изменения
|
||||
/// </summary>
|
||||
public int IdAuthor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Редактор
|
||||
/// </summary>
|
||||
public int? IdEditor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата создания записи
|
||||
/// </summary>
|
||||
public DateTimeOffset Creation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата устаревания (например при удалении)
|
||||
/// </summary>
|
||||
public DateTimeOffset? Obsolete { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ИД состояния записи:
|
||||
/// <list type="table">
|
||||
/// <item>
|
||||
/// <term>0</term>
|
||||
/// <description>актуальная запись</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>1</term>
|
||||
/// <description>замененная запись</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>2</term>
|
||||
/// <description>удаленная запись</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public int IdState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id заменяемой записи
|
||||
/// </summary>
|
||||
public int? IdPrevious { get; set; }
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AsbCloudApp.Data
|
||||
{
|
||||
@ -19,5 +21,66 @@ namespace AsbCloudApp.Data
|
||||
[Required]
|
||||
public double LimitMax { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Валидация
|
||||
/// </summary>
|
||||
/// <param name="commonRange">Общий диапазон для плана и ограничения</param>
|
||||
/// <param name="paramName"></param>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<ValidationResult> Validate((double GE, double LE) commonRange, string paramName)
|
||||
=> Validate(commonRange, commonRange, paramName);
|
||||
|
||||
/// <summary>
|
||||
/// Валидация
|
||||
/// </summary>
|
||||
/// <param name="planRange"></param>
|
||||
/// <param name="limitMaxRange"></param>
|
||||
/// <param name="paramName">Название параметра для которого задается план и ограничение</param>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<ValidationResult> Validate((double GE, double LE) planRange, (double GE, double LE) limitMaxRange, string paramName)
|
||||
{
|
||||
if (Plan < planRange.GE || Plan > planRange.LE)
|
||||
yield return new ValidationResult($"{paramName} плановое значение должно быть в диапазоне [{planRange.GE}; {planRange.LE}].");
|
||||
|
||||
if (Plan < planRange.GE || Plan > planRange.LE)
|
||||
yield return new ValidationResult($"{paramName} ограничивающее значение должно быть в диапазоне [{limitMaxRange.GE}; {limitMaxRange.LE}].");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализация RangeAttribute для PlanLimitDto
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,
|
||||
AllowMultiple = false)]
|
||||
public class RangePlanLimitAttribute : ValidationAttribute
|
||||
{
|
||||
private readonly double minimum;
|
||||
private readonly double maximum;
|
||||
|
||||
/// <summary>
|
||||
/// Реализация RangeAttribute для PlanLimitDto
|
||||
/// </summary>
|
||||
/// <param name="minimum"></param>
|
||||
/// <param name="maximum"></param>
|
||||
public RangePlanLimitAttribute(double minimum, double maximum)
|
||||
{
|
||||
this.minimum = minimum;
|
||||
this.maximum = maximum;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(value is PlanLimitDto dto)
|
||||
{
|
||||
var isPlanValid = dto.Plan <= maximum && dto.Plan >= minimum;
|
||||
var isLimitMaxValid = dto.LimitMax <= maximum && dto.LimitMax >= minimum;
|
||||
return isPlanValid && isLimitMaxValid;
|
||||
}
|
||||
}catch{}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanBaseDto.cs
Normal file
46
AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanBaseDto.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AsbCloudApp.Data.ProcessMapPlan;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract class ProcessMapPlanBaseDto : ChangeLogAbstract, IId, IWellRelated, IValidatableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Id скважины
|
||||
/// </summary>
|
||||
[Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")]
|
||||
public int IdWell { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Тип секции
|
||||
/// </summary>
|
||||
[Range(1, int.MaxValue, ErrorMessage = "Id секции скважины не может быть меньше 1")]
|
||||
public int IdWellSectionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Глубина по стволу от, м
|
||||
/// <para>
|
||||
/// на начало интервала
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Глубина не может быть отрицательной")]
|
||||
public double DepthStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Глубина по стволу до, м
|
||||
/// <para>
|
||||
/// на конец интервала
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Глубина не может быть отрицательной")]
|
||||
public double DepthEnd { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if(DepthEnd <= DepthStart)
|
||||
yield return new ("глубина окончания должна быть больше глубины начала", new string[] {nameof(DepthEnd), nameof(DepthStart) });
|
||||
}
|
||||
}
|
98
AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanDrillingDto.cs
Normal file
98
AsbCloudApp/Data/ProcessMapPlan/ProcessMapPlanDrillingDto.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AsbCloudApp.Data.ProcessMapPlan;
|
||||
|
||||
/// <summary>
|
||||
/// РТК план бурение скважины
|
||||
/// </summary>
|
||||
public class ProcessMapPlanDrillingDto : ProcessMapPlanBaseDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Id режима 1-ротор, 2 - слайд
|
||||
/// </summary>
|
||||
[Range(1, 2, ErrorMessage = "Id режима должен быть либо 1-ротор либо 2-слайд")]
|
||||
public int IdMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Осевая нагрузка, т план
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Осевая нагрузка, т должна быть в пределах от 0 до 99999.9")]
|
||||
public double AxialLoadPlan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Осевая нагрузка, т ограничение
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Осевая нагрузка, т должна быть в пределах от 0 до 99999.9")]
|
||||
public double AxialLoadLimitMax { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Перепад давления, атм план
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Перепад давления, атм должна быть в пределах от 0 до 99999.9")]
|
||||
public double DeltaPressurePlan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Перепад давления, атм ограничение
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Перепад давления, атм должна быть в пределах от 0 до 99999.9")]
|
||||
public double DeltaPressureLimitMax { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Момент на ВСП, кН*м план
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Момент на ВСП, кН*м должна быть в пределах от 0 до 99999.9")]
|
||||
public double TopDriveTorquePlan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Момент на ВСП, кН*м ограничение
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Момент на ВСП, кН*м должна быть в пределах от 0 до 99999.9")]
|
||||
public double TopDriveTorqueLimitMax { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Обороты на ВСП, об/мин план
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Обороты на ВСП, об/мин должна быть в пределах от 0 до 99999.9")]
|
||||
public double TopDriveSpeedPlan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Обороты на ВСП, об/мин ограничение
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Обороты на ВСП, об/мин должна быть в пределах от 0 до 99999.9")]
|
||||
public double TopDriveSpeedLimitMax { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Расход, л/с план
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Расход, л/с должна быть в пределах от 0 до 99999.9")]
|
||||
public double FlowPlan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Расход, л/с ограничение
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Расход, л/с должна быть в пределах от 0 до 99999.9")]
|
||||
public double FlowLimitMax { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Плановая механическая скорость, м/ч
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Плановая механическая скорость, м/ч должно быть в пределах от 0 до 99999.9")]
|
||||
public double RopPlan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Плановый процент использования АКБ
|
||||
/// </summary>
|
||||
[Range(0, 100, ErrorMessage = "Процент использования АКБ должен быть в пределах от 0 до 100")]
|
||||
public double UsageSaub { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Плановый процент использования spin master
|
||||
/// </summary>
|
||||
[Range(0, 100, ErrorMessage = "Процент использования spin master должен быть в пределах от 0 до 100")]
|
||||
public double UsageSpin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Комментарий
|
||||
/// </summary>
|
||||
public string Comment { get; set; } = string.Empty;
|
||||
}
|
41
AsbCloudApp/Repositories/IChangeLogRepository.cs
Normal file
41
AsbCloudApp/Repositories/IChangeLogRepository.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data;
|
||||
|
||||
namespace AsbCloudApp.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Репозиторий для записей с историей
|
||||
/// </summary>
|
||||
public interface IChangeLogRepository<T>
|
||||
where T : ChangeLogAbstract
|
||||
{
|
||||
/// <summary>
|
||||
/// Добавление записей
|
||||
/// </summary>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> InsertRange(int idUser, IEnumerable<T> dtos, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Редактирование записей
|
||||
/// </summary>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> UpdateRange(int idUser, IEnumerable<T> dtos, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление записей
|
||||
/// </summary>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> DeleteRange(int idUser, IEnumerable<int> ids, CancellationToken token);
|
||||
|
||||
}
|
51
AsbCloudApp/Repositories/IProcessMapPlanBaseRepository.cs
Normal file
51
AsbCloudApp/Repositories/IProcessMapPlanBaseRepository.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.ProcessMapPlan;
|
||||
using AsbCloudApp.Requests;
|
||||
|
||||
namespace AsbCloudApp.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Общий интерфейс для РТК план с учетом истории изменений
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public interface IProcessMapPlanBaseRepository<T>: IChangeLogRepository<T>
|
||||
where T: ProcessMapPlanBaseDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Добавление записей с удалением старых (для импорта)
|
||||
/// </summary>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> ClearAndInsertRange(int idUser, int idWell, IEnumerable<T> dtos, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получение дат изменений записей
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<DateOnly>> GetDatesChange(int idWell, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получение журнала изменений
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="date"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<T>> GetChangeLog(int idWell, DateOnly? date, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получение записей по параметрам
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<T>> Get(ProcessMapPlanBaseRequest request, CancellationToken token);
|
||||
}
|
14
AsbCloudApp/Requests/ChangeLogBaseRequest.cs
Normal file
14
AsbCloudApp/Requests/ChangeLogBaseRequest.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace AsbCloudApp.Requests;
|
||||
|
||||
/// <summary>
|
||||
/// Базовый запрос актуальных данных
|
||||
/// </summary>
|
||||
public class ChangeLogBaseRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Дата/время на которую записи были актуальны. Если не задано, то не фильтруется
|
||||
/// </summary>
|
||||
public DateTimeOffset? Moment { get; set; }
|
||||
}
|
27
AsbCloudApp/Requests/ProcessMapPlanBaseRequest.cs
Normal file
27
AsbCloudApp/Requests/ProcessMapPlanBaseRequest.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AsbCloudApp.Requests;
|
||||
|
||||
/// <summary>
|
||||
/// Запрос для получения РТК план
|
||||
/// </summary>
|
||||
public class ProcessMapPlanBaseRequest: ChangeLogBaseRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Идентификатор скважины
|
||||
/// </summary>
|
||||
[Range(1, int.MaxValue, ErrorMessage = "Id скважины - положительное число")]
|
||||
public int IdWell { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Тип секции
|
||||
/// </summary>
|
||||
[Range(1, int.MaxValue, ErrorMessage = "Id секции - положительное число")]
|
||||
public int? IdWellSectionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Вернуть данные, которые поменялись с указанной даты
|
||||
/// </summary>
|
||||
public DateTimeOffset? UpdateFrom { get; set; }
|
||||
}
|
9309
AsbCloudDb/Migrations/20240119062443_Add_processmap_plan_drilling_with_changeLog.Designer.cs
generated
Normal file
9309
AsbCloudDb/Migrations/20240119062443_Add_processmap_plan_drilling_with_changeLog.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Add_processmap_plan_drilling_with_changeLog : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "t_process_map_plan_drilling",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false, comment: "Идентификатор")
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
id_mode = table.Column<int>(type: "integer", nullable: false, comment: "Id режима (1- ротор, 2 слайд)"),
|
||||
axial_load_plan = table.Column<double>(type: "double precision", nullable: false, comment: "Осевая нагрузка, т, план"),
|
||||
axial_load_limit_max = table.Column<double>(type: "double precision", nullable: false, comment: "Осевая нагрузка, т, допустимый максимум"),
|
||||
delta_pressure_plan = table.Column<double>(type: "double precision", nullable: false, comment: "Перепад давления, атм, план"),
|
||||
delta_pressure_limit_max = table.Column<double>(type: "double precision", nullable: false, comment: "Перепад давления, атм, допустимый максимум"),
|
||||
top_drive_torque_plan = table.Column<double>(type: "double precision", nullable: false, comment: "Момент на ВСП, план"),
|
||||
top_drive_torque_limit_max = table.Column<double>(type: "double precision", nullable: false, comment: "Момент на ВСП, допустимый максимум"),
|
||||
top_drive_speed_plan = table.Column<double>(type: "double precision", nullable: false, comment: "Обороты на ВСП, план"),
|
||||
top_drive_speed_limit_max = table.Column<double>(type: "double precision", nullable: false, comment: "Обороты на ВСП, допустимый максимум"),
|
||||
flow_plan = table.Column<double>(type: "double precision", nullable: false, comment: "Расход, л/с, план"),
|
||||
flow_limit_max = table.Column<double>(type: "double precision", nullable: false, comment: "Расход, л/с, допустимый максимум"),
|
||||
rop_plan = table.Column<double>(type: "double precision", nullable: false, comment: "Плановая механическая скорость, м/ч"),
|
||||
usage_saub = table.Column<double>(type: "double precision", nullable: false, comment: "Плановый процент использования АКБ"),
|
||||
usage_spin = table.Column<double>(type: "double precision", nullable: false, comment: "Плановый процент использования spin master"),
|
||||
comment = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false, comment: "Комментарий"),
|
||||
id_author = table.Column<int>(type: "integer", nullable: false, comment: "Автор"),
|
||||
id_editor = table.Column<int>(type: "integer", nullable: true, comment: "Редактор"),
|
||||
creation = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "дата создания"),
|
||||
obsolete = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true, comment: "дата устаревания"),
|
||||
id_state = table.Column<int>(type: "integer", nullable: false, comment: "ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная"),
|
||||
id_previous = table.Column<int>(type: "integer", nullable: true, comment: "ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная"),
|
||||
id_well = table.Column<int>(type: "integer", nullable: false, comment: "Id скважины"),
|
||||
id_wellsection_type = table.Column<int>(type: "integer", nullable: false, comment: "Тип секции"),
|
||||
depth_start = table.Column<double>(type: "double precision", nullable: false, comment: "Глубина по стволу от, м"),
|
||||
depth_end = table.Column<double>(type: "double precision", nullable: false, comment: "Глубина по стволу до, м")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_t_process_map_plan_drilling", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_process_map_plan_drilling_t_process_map_plan_drilling_id_~",
|
||||
column: x => x.id_previous,
|
||||
principalTable: "t_process_map_plan_drilling",
|
||||
principalColumn: "id");
|
||||
table.ForeignKey(
|
||||
name: "FK_t_process_map_plan_drilling_t_user_id_author",
|
||||
column: x => x.id_author,
|
||||
principalTable: "t_user",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_process_map_plan_drilling_t_user_id_editor",
|
||||
column: x => x.id_editor,
|
||||
principalTable: "t_user",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_process_map_plan_drilling_t_well_id_well",
|
||||
column: x => x.id_well,
|
||||
principalTable: "t_well",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_process_map_plan_drilling_t_well_section_type_id_wellsect~",
|
||||
column: x => x.id_wellsection_type,
|
||||
principalTable: "t_well_section_type",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
},
|
||||
comment: "РТК план бурение");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_process_map_plan_drilling_id_author",
|
||||
table: "t_process_map_plan_drilling",
|
||||
column: "id_author");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_process_map_plan_drilling_id_editor",
|
||||
table: "t_process_map_plan_drilling",
|
||||
column: "id_editor");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_process_map_plan_drilling_id_previous",
|
||||
table: "t_process_map_plan_drilling",
|
||||
column: "id_previous");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_process_map_plan_drilling_id_well",
|
||||
table: "t_process_map_plan_drilling",
|
||||
column: "id_well");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_process_map_plan_drilling_id_wellsection_type",
|
||||
table: "t_process_map_plan_drilling",
|
||||
column: "id_wellsection_type");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "t_process_map_plan_drilling");
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#nullable disable
|
||||
|
||||
@ -20,7 +19,7 @@ namespace AsbCloudDb.Migrations
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.UseCollation("Russian_Russia.1251")
|
||||
.HasAnnotation("ProductVersion", "6.0.7")
|
||||
.HasAnnotation("ProductVersion", "6.0.22")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
|
||||
@ -388,7 +387,7 @@ namespace AsbCloudDb.Migrations
|
||||
.HasColumnName("enabled_subsystems")
|
||||
.HasComment("флаги включенных подсистем");
|
||||
|
||||
b.Property<IDictionary<string, object>>("ExtraData")
|
||||
b.Property<string>("ExtraData")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("extra_data")
|
||||
@ -2464,6 +2463,160 @@ namespace AsbCloudDb.Migrations
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapPlanDrilling", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id")
|
||||
.HasComment("Идентификатор");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<double>("AxialLoadLimitMax")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("axial_load_limit_max")
|
||||
.HasComment("Осевая нагрузка, т, допустимый максимум");
|
||||
|
||||
b.Property<double>("AxialLoadPlan")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("axial_load_plan")
|
||||
.HasComment("Осевая нагрузка, т, план");
|
||||
|
||||
b.Property<string>("Comment")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1024)
|
||||
.HasColumnType("character varying(1024)")
|
||||
.HasColumnName("comment")
|
||||
.HasComment("Комментарий");
|
||||
|
||||
b.Property<DateTimeOffset>("Creation")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("creation")
|
||||
.HasComment("дата создания");
|
||||
|
||||
b.Property<double>("DeltaPressureLimitMax")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("delta_pressure_limit_max")
|
||||
.HasComment("Перепад давления, атм, допустимый максимум");
|
||||
|
||||
b.Property<double>("DeltaPressurePlan")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("delta_pressure_plan")
|
||||
.HasComment("Перепад давления, атм, план");
|
||||
|
||||
b.Property<double>("DepthEnd")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("depth_end")
|
||||
.HasComment("Глубина по стволу до, м");
|
||||
|
||||
b.Property<double>("DepthStart")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("depth_start")
|
||||
.HasComment("Глубина по стволу от, м");
|
||||
|
||||
b.Property<double>("FlowLimitMax")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("flow_limit_max")
|
||||
.HasComment("Расход, л/с, допустимый максимум");
|
||||
|
||||
b.Property<double>("FlowPlan")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("flow_plan")
|
||||
.HasComment("Расход, л/с, план");
|
||||
|
||||
b.Property<int>("IdAuthor")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_author")
|
||||
.HasComment("Автор");
|
||||
|
||||
b.Property<int?>("IdEditor")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_editor")
|
||||
.HasComment("Редактор");
|
||||
|
||||
b.Property<int>("IdMode")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_mode")
|
||||
.HasComment("Id режима (1- ротор, 2 слайд)");
|
||||
|
||||
b.Property<int?>("IdPrevious")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_previous")
|
||||
.HasComment("ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная");
|
||||
|
||||
b.Property<int>("IdState")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_state")
|
||||
.HasComment("ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная");
|
||||
|
||||
b.Property<int>("IdWell")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_well")
|
||||
.HasComment("Id скважины");
|
||||
|
||||
b.Property<int>("IdWellSectionType")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_wellsection_type")
|
||||
.HasComment("Тип секции");
|
||||
|
||||
b.Property<DateTimeOffset?>("Obsolete")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("obsolete")
|
||||
.HasComment("дата устаревания");
|
||||
|
||||
b.Property<double>("RopPlan")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("rop_plan")
|
||||
.HasComment("Плановая механическая скорость, м/ч");
|
||||
|
||||
b.Property<double>("TopDriveSpeedLimitMax")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("top_drive_speed_limit_max")
|
||||
.HasComment("Обороты на ВСП, допустимый максимум");
|
||||
|
||||
b.Property<double>("TopDriveSpeedPlan")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("top_drive_speed_plan")
|
||||
.HasComment("Обороты на ВСП, план");
|
||||
|
||||
b.Property<double>("TopDriveTorqueLimitMax")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("top_drive_torque_limit_max")
|
||||
.HasComment("Момент на ВСП, допустимый максимум");
|
||||
|
||||
b.Property<double>("TopDriveTorquePlan")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("top_drive_torque_plan")
|
||||
.HasComment("Момент на ВСП, план");
|
||||
|
||||
b.Property<double>("UsageSaub")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("usage_saub")
|
||||
.HasComment("Плановый процент использования АКБ");
|
||||
|
||||
b.Property<double>("UsageSpin")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("usage_spin")
|
||||
.HasComment("Плановый процент использования spin master");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("IdAuthor");
|
||||
|
||||
b.HasIndex("IdEditor");
|
||||
|
||||
b.HasIndex("IdPrevious");
|
||||
|
||||
b.HasIndex("IdWell");
|
||||
|
||||
b.HasIndex("IdWellSectionType");
|
||||
|
||||
b.ToTable("t_process_map_plan_drilling");
|
||||
|
||||
b.HasComment("РТК план бурение");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapWellDrilling", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@ -8400,6 +8553,46 @@ namespace AsbCloudDb.Migrations
|
||||
b.Navigation("Well");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapPlanDrilling", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.User", "Author")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdAuthor")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("AsbCloudDb.Model.User", "Editor")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdEditor")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("AsbCloudDb.Model.ProcessMaps.ProcessMapPlanDrilling", "Previous")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdPrevious");
|
||||
|
||||
b.HasOne("AsbCloudDb.Model.Well", "Well")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdWell")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("AsbCloudDb.Model.WellSectionType", "WellSectionType")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdWellSectionType")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Author");
|
||||
|
||||
b.Navigation("Editor");
|
||||
|
||||
b.Navigation("Previous");
|
||||
|
||||
b.Navigation("Well");
|
||||
|
||||
b.Navigation("WellSectionType");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapWellDrilling", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.User", "User")
|
||||
|
@ -21,6 +21,7 @@ namespace AsbCloudDb.Model
|
||||
public virtual DbSet<TrajectoryPlan> TrajectoriesPlan => Set<TrajectoryPlan>();
|
||||
public virtual DbSet<ProcessMapWellDrilling> ProcessMapWellDrillings => Set<ProcessMapWellDrilling>();
|
||||
public virtual DbSet<ProcessMapWellReam> ProcessMapWellReams => Set<ProcessMapWellReam>();
|
||||
public virtual DbSet<ProcessMapPlanDrilling> ProcessMapPlanDrilling => Set<ProcessMapPlanDrilling>();
|
||||
public virtual DbSet<DrillingProgramPart> DrillingProgramParts => Set<DrillingProgramPart>();
|
||||
public virtual DbSet<FileCategory> FileCategories => Set<FileCategory>();
|
||||
public virtual DbSet<FileInfo> Files => Set<FileInfo>();
|
||||
@ -440,6 +441,16 @@ namespace AsbCloudDb.Model
|
||||
.HasIndex(w => new { w.IdWell, w.IdSectionType })
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<ProcessMapPlanDrilling>()
|
||||
.HasOne(p => p.Author)
|
||||
.WithMany()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<ProcessMapPlanDrilling>()
|
||||
.HasOne(p => p.Editor)
|
||||
.WithMany()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
DefaultData.DefaultContextData.Fill(modelBuilder);
|
||||
}
|
||||
|
||||
|
89
AsbCloudDb/Model/ChangeLogAbstract.cs
Normal file
89
AsbCloudDb/Model/ChangeLogAbstract.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace AsbCloudDb.Model;
|
||||
|
||||
/// <summary>
|
||||
/// Часть записи описывающая изменение
|
||||
/// </summary>
|
||||
public abstract class ChangeLogAbstract
|
||||
{
|
||||
/// <summary>
|
||||
/// Актуальная
|
||||
/// </summary>
|
||||
public const int IdStateActual = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Замененная
|
||||
/// </summary>
|
||||
public const int IdStateReplaced = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Удаленная
|
||||
/// </summary>
|
||||
public const int IdStateDeleted = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Очищено при импорте
|
||||
/// </summary>
|
||||
public const int IdClearedOnImport = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Ид записи
|
||||
/// </summary>
|
||||
[Key]
|
||||
[Column("id"), Comment("Идентификатор")]
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Автор изменения
|
||||
/// </summary>
|
||||
[Column("id_author"), Comment("Автор")]
|
||||
public int IdAuthor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Редактор
|
||||
/// </summary>
|
||||
[Column("id_editor"), Comment("Редактор")]
|
||||
public int? IdEditor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата создания записи
|
||||
/// </summary>
|
||||
[Column("creation"), Comment("дата создания")]
|
||||
public DateTimeOffset Creation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата устаревания (например при удалении)
|
||||
/// </summary>
|
||||
[Column("obsolete"), Comment("дата устаревания")]
|
||||
public DateTimeOffset? Obsolete { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ИД состояния записи:
|
||||
/// <list type="table">
|
||||
/// <item>
|
||||
/// <term>0</term>
|
||||
/// <description>актуальная запись</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>1</term>
|
||||
/// <description>замененная запись</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>2</term>
|
||||
/// <description>удаленная запись</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[Column("id_state"), Comment("ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная")]
|
||||
public int IdState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id заменяемой записи
|
||||
/// </summary>
|
||||
[Column("id_previous"), Comment("ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная")]
|
||||
public int? IdPrevious { get; set; }
|
||||
}
|
31
AsbCloudDb/Model/ProcessMapPlan/ProcessMapPlanBase.cs
Normal file
31
AsbCloudDb/Model/ProcessMapPlan/ProcessMapPlanBase.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace AsbCloudDb.Model.ProcessMapPlan;
|
||||
|
||||
public abstract class ProcessMapPlanBase : ChangeLogAbstract, IId, IWellRelated
|
||||
{
|
||||
[Column("id_well"), Comment("Id скважины")]
|
||||
public int IdWell { get; set; }
|
||||
|
||||
[Column("id_wellsection_type"), Comment("Тип секции")]
|
||||
public int IdWellSectionType { get; set; }
|
||||
|
||||
[Column("depth_start"), Comment("Глубина по стволу от, м")]
|
||||
public double DepthStart { get; set; }
|
||||
|
||||
[Column("depth_end"), Comment("Глубина по стволу до, м")]
|
||||
public double DepthEnd { get; set; }
|
||||
|
||||
[ForeignKey(nameof(IdWell))]
|
||||
public virtual Well Well { get; set; } = null!;
|
||||
|
||||
[ForeignKey(nameof(IdAuthor))]
|
||||
public virtual User Author { get; set; } = null!;
|
||||
|
||||
[ForeignKey(nameof(IdEditor))]
|
||||
public virtual User? Editor { get; set; } = null!;
|
||||
|
||||
[ForeignKey(nameof(IdWellSectionType))]
|
||||
public virtual WellSectionType WellSectionType { get; set; } = null!;
|
||||
}
|
58
AsbCloudDb/Model/ProcessMapPlan/ProcessMapPlanDrilling.cs
Normal file
58
AsbCloudDb/Model/ProcessMapPlan/ProcessMapPlanDrilling.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using AsbCloudDb.Model.ProcessMapPlan;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AsbCloudDb.Model.ProcessMaps;
|
||||
|
||||
[Table("t_process_map_plan_drilling"), Comment("РТК план бурение")]
|
||||
public class ProcessMapPlanDrilling : ProcessMapPlanBase
|
||||
{
|
||||
[Column("id_mode"), Comment("Id режима (1- ротор, 2 слайд)")]
|
||||
public int IdMode { get; set; }
|
||||
|
||||
[Column("axial_load_plan"), Comment("Осевая нагрузка, т, план")]
|
||||
public double AxialLoadPlan { get; set; }
|
||||
|
||||
[Column("axial_load_limit_max"), Comment("Осевая нагрузка, т, допустимый максимум")]
|
||||
public double AxialLoadLimitMax { get; set; }
|
||||
|
||||
[Column("delta_pressure_plan"), Comment("Перепад давления, атм, план")]
|
||||
public double DeltaPressurePlan { get; set; }
|
||||
|
||||
[Column("delta_pressure_limit_max"), Comment("Перепад давления, атм, допустимый максимум")]
|
||||
public double DeltaPressureLimitMax { get; set; }
|
||||
|
||||
[Column("top_drive_torque_plan"), Comment("Момент на ВСП, план")]
|
||||
public double TopDriveTorquePlan { get; set; }
|
||||
|
||||
[Column("top_drive_torque_limit_max"), Comment("Момент на ВСП, допустимый максимум")]
|
||||
public double TopDriveTorqueLimitMax { get; set; }
|
||||
|
||||
[Column("top_drive_speed_plan"), Comment("Обороты на ВСП, план")]
|
||||
public double TopDriveSpeedPlan { get; set; }
|
||||
|
||||
[Column("top_drive_speed_limit_max"), Comment("Обороты на ВСП, допустимый максимум")]
|
||||
public double TopDriveSpeedLimitMax { get; set; }
|
||||
|
||||
[Column("flow_plan"), Comment("Расход, л/с, план")]
|
||||
public double FlowPlan { get; set; }
|
||||
|
||||
[Column("flow_limit_max"), Comment("Расход, л/с, допустимый максимум")]
|
||||
public double FlowLimitMax { get; set; }
|
||||
|
||||
[Column("rop_plan"), Comment("Плановая механическая скорость, м/ч")]
|
||||
public double RopPlan { get; set; }
|
||||
|
||||
[Column("usage_saub"), Comment("Плановый процент использования АКБ")]
|
||||
public double UsageSaub { get; set; }
|
||||
|
||||
[Column("usage_spin"), Comment("Плановый процент использования spin master")]
|
||||
public double UsageSpin { get; set; }
|
||||
|
||||
[Column("comment"), Comment("Комментарий"), StringLength(1024)]
|
||||
public string Comment { get; set; } = string.Empty;
|
||||
|
||||
[ForeignKey(nameof(IdPrevious))]
|
||||
public virtual ProcessMapPlanDrilling? Previous { get; set; }
|
||||
}
|
@ -44,10 +44,10 @@ using AsbCloudApp.Services.DailyReport;
|
||||
using AsbCloudDb.Model.DailyReports.Blocks.TimeBalance;
|
||||
using AsbCloudDb.Model.WellSections;
|
||||
using AsbCloudInfrastructure.Services.ProcessMaps;
|
||||
using AsbCloudApp.Data.ProcessMapPlan;
|
||||
|
||||
namespace AsbCloudInfrastructure
|
||||
{
|
||||
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static void MapsterSetup()
|
||||
@ -222,6 +222,8 @@ namespace AsbCloudInfrastructure
|
||||
services.AddTransient<IHelpPageService, HelpPageService>();
|
||||
services.AddTransient<IScheduleReportService, ScheduleReportService>();
|
||||
|
||||
services.AddTransient<IProcessMapPlanBaseRepository<ProcessMapPlanDrillingDto>, ProcessMapPlanBaseRepository<ProcessMapPlanDrillingDto, ProcessMapPlanDrilling>>();
|
||||
|
||||
services.AddTransient<TrajectoryService>();
|
||||
|
||||
services.AddTransient<IGtrRepository, GtrWitsRepository>();
|
||||
|
@ -0,0 +1,277 @@
|
||||
using AsbCloudApp.Data.ProcessMapPlan;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudDb.Model.ProcessMapPlan;
|
||||
using AsbCloudDb.Model.WellSections;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Npgsql;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Repository;
|
||||
|
||||
public class ProcessMapPlanBaseRepository<TDto, TEntity> : IProcessMapPlanBaseRepository<TDto>
|
||||
where TDto : ProcessMapPlanBaseDto
|
||||
where TEntity : ProcessMapPlanBase
|
||||
{
|
||||
private readonly IAsbCloudDbContext context;
|
||||
private readonly IWellService wellService;
|
||||
|
||||
public ProcessMapPlanBaseRepository(IAsbCloudDbContext context, IWellService wellService)
|
||||
{
|
||||
this.context = context;
|
||||
this.wellService = wellService;
|
||||
}
|
||||
|
||||
public async Task<int> InsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
|
||||
{
|
||||
var result = 0;
|
||||
if (dtos.Any())
|
||||
{
|
||||
var entities = dtos.Select(Convert);
|
||||
var creation = DateTimeOffset.UtcNow;
|
||||
var dbSet = context.Set<TEntity>();
|
||||
foreach (var entity in entities) {
|
||||
entity.Id = default;
|
||||
entity.IdAuthor = idUser;
|
||||
entity.Creation = creation;
|
||||
entity.IdState = ChangeLogAbstract.IdStateActual;
|
||||
entity.IdEditor = null;
|
||||
entity.Editor = null;
|
||||
entity.IdPrevious = null;
|
||||
entity.Obsolete = null;
|
||||
dbSet.Add(entity);
|
||||
}
|
||||
|
||||
result += await SaveChangesWithExceptionHandling(token);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<int> ClearAndInsertRange(int idUser, int idWell, IEnumerable<TDto> dtos, CancellationToken token)
|
||||
{
|
||||
if (dtos.Any(d => d.IdWell != idWell))
|
||||
throw new ArgumentInvalidException(nameof(dtos), $"Все записи должны относиться к скважине idWell = {idWell}");
|
||||
|
||||
using var transaction = context.Database.BeginTransaction();
|
||||
var result = 0;
|
||||
|
||||
var dbSet = context.Set<TEntity>();
|
||||
var entitiesToMarkDeleted = dbSet
|
||||
.Where(e => e.IdWell == idWell)
|
||||
.Where(e => e.Obsolete == null);
|
||||
var obsolete = DateTimeOffset.UtcNow;
|
||||
foreach (var entity in entitiesToMarkDeleted)
|
||||
{
|
||||
entity.IdState = ChangeLogAbstract.IdClearedOnImport;
|
||||
entity.Obsolete = obsolete;
|
||||
entity.IdEditor = idUser;
|
||||
}
|
||||
result += await SaveChangesWithExceptionHandling(token);
|
||||
result += await InsertRange(idUser, dtos, token);
|
||||
await transaction.CommitAsync(token);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<int> DeleteRange(int idUser, IEnumerable<int> ids, CancellationToken token)
|
||||
{
|
||||
var dbSet = context.Set<TEntity>();
|
||||
var entitiesToMarkDeleted = dbSet
|
||||
.Where(e => ids.Contains(e.Id))
|
||||
.Where(e => e.Obsolete == null);
|
||||
var obsolete = DateTimeOffset.UtcNow;
|
||||
foreach (var entity in entitiesToMarkDeleted)
|
||||
{
|
||||
entity.IdState = ChangeLogAbstract.IdStateDeleted;
|
||||
entity.Obsolete = obsolete;
|
||||
entity.IdEditor = idUser;
|
||||
}
|
||||
var result = await SaveChangesWithExceptionHandling(token);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TDto>> Get(ProcessMapPlanBaseRequest request, CancellationToken token)
|
||||
{
|
||||
var timezone = wellService.GetTimezone(request.IdWell);
|
||||
var offset = TimeSpan.FromHours(timezone.Hours);
|
||||
|
||||
var query = context
|
||||
.Set<TEntity>()
|
||||
.Where(e => e.IdWell == request.IdWell);
|
||||
|
||||
if(request.IdWellSectionType.HasValue)
|
||||
query = query.Where(e => e.IdWellSectionType == request.IdWellSectionType);
|
||||
|
||||
if (request.UpdateFrom.HasValue)
|
||||
{
|
||||
var from = request.UpdateFrom.Value.ToUniversalTime();
|
||||
query = query.Where(e => e.Creation >= from || e.Obsolete >= from);
|
||||
}
|
||||
|
||||
if (request.Moment.HasValue)
|
||||
{
|
||||
var moment = request.Moment.Value.ToUniversalTime();
|
||||
query = query
|
||||
.Where(e => e.Creation <= moment)
|
||||
.Where(e => e.Obsolete == null || e.Obsolete >= moment);
|
||||
}
|
||||
|
||||
var entities = await query.ToArrayAsync(token);
|
||||
var dtos = entities.Select(e => Convert(e, offset));
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TDto>> GetChangeLog(int idWell, DateOnly? date, CancellationToken token)
|
||||
{
|
||||
var query = context
|
||||
.Set<TEntity>()
|
||||
.Where(e => e.IdWell == idWell);
|
||||
|
||||
var timezone = wellService.GetTimezone(idWell);
|
||||
var offset = TimeSpan.FromHours(timezone.Hours);
|
||||
|
||||
if (date.HasValue)
|
||||
{
|
||||
var min = new DateTimeOffset(date.Value.Year, date.Value.Month, date.Value.Day, 0, 0, 0, offset).ToUniversalTime();
|
||||
var max = min.AddDays(1);
|
||||
|
||||
var createdQuery = query.Where(e => e.Creation >= min && e.Creation <= max);
|
||||
var editedQuery = query.Where(e => e.Obsolete != null && e.Obsolete >= min && e.Obsolete <= max);
|
||||
|
||||
query = createdQuery.Union(editedQuery);
|
||||
}
|
||||
|
||||
var entities = await query.ToListAsync(token);
|
||||
var dtos = entities.Select(e => Convert(e, offset));
|
||||
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<DateOnly>> GetDatesChange(int idWell, CancellationToken token)
|
||||
{
|
||||
var wellEntitiesQuery = context
|
||||
.Set<TEntity>()
|
||||
.Where(e => e.IdWell == idWell);
|
||||
|
||||
var datesCreateQuery = wellEntitiesQuery
|
||||
.Select(e => e.Creation)
|
||||
.Distinct();
|
||||
|
||||
var datesCreate = await datesCreateQuery.ToArrayAsync(token);
|
||||
|
||||
var datesUpdateQuery = wellEntitiesQuery
|
||||
.Where(e => e.Obsolete != null)
|
||||
.Select(e => e.Obsolete!.Value)
|
||||
.Distinct();
|
||||
|
||||
var datesUpdate = await datesUpdateQuery.ToArrayAsync(token);
|
||||
|
||||
var timezone = wellService.GetTimezone(idWell);
|
||||
var offset = TimeSpan.FromHours(timezone.Hours);
|
||||
|
||||
var dates = Enumerable.Concat( datesCreate, datesUpdate);
|
||||
dates = dates.Select(date => date.ToOffset(offset));
|
||||
var datesOnly = dates
|
||||
.Select(d => new DateOnly(d.Year, d.Month, d.Day))
|
||||
.Distinct();
|
||||
|
||||
return datesOnly;
|
||||
}
|
||||
|
||||
public async Task<int> UpdateRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
|
||||
{
|
||||
if (dtos.Any(d => d.Id == 0))
|
||||
throw new ArgumentInvalidException(nameof(dtos), "Отредактированные значения должны иметь id больше 0");
|
||||
|
||||
if (!dtos.Any())
|
||||
return 0;
|
||||
|
||||
using var transaction = context.Database.BeginTransaction();
|
||||
var result = 0;
|
||||
|
||||
var ids = dtos.Select(d => d.Id);
|
||||
var dbSet = context.Set<TEntity>();
|
||||
|
||||
var entitiesToDelete = dbSet
|
||||
.Where(e => ids.Contains(e.Id));
|
||||
|
||||
var updateTime = DateTimeOffset.UtcNow;
|
||||
foreach (var entity in entitiesToDelete)
|
||||
{
|
||||
if(entity.Obsolete is not null)
|
||||
throw new ArgumentInvalidException(nameof(dtos), "Недопустимо редактировать устаревшие записи");
|
||||
entity.IdState = ChangeLogAbstract.IdStateReplaced;
|
||||
entity.Obsolete = updateTime;
|
||||
entity.IdEditor = idUser;
|
||||
}
|
||||
result += await context.SaveChangesAsync(token);
|
||||
|
||||
var entitiesNew = dtos.Select(Convert);
|
||||
foreach (var entity in entitiesNew)
|
||||
{
|
||||
entity.IdPrevious = entity.Id;
|
||||
entity.Id = default;
|
||||
entity.Creation = updateTime;
|
||||
entity.IdAuthor = idUser;
|
||||
entity.Obsolete = null;
|
||||
entity.IdEditor = null;
|
||||
entity.IdState = ChangeLogAbstract.IdStateActual;
|
||||
dbSet.Add(entity);
|
||||
}
|
||||
|
||||
result += await SaveChangesWithExceptionHandling(token);
|
||||
await transaction.CommitAsync(token);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected virtual TEntity Convert(TDto dto)
|
||||
{
|
||||
var entity = dto.Adapt<TEntity>();
|
||||
entity.Creation = entity.Creation.ToUniversalTime();
|
||||
|
||||
if(entity.Obsolete.HasValue)
|
||||
entity.Obsolete = entity.Obsolete.Value.ToUniversalTime();
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
protected virtual TDto Convert(TEntity entity, TimeSpan offset)
|
||||
{
|
||||
var dto = entity.Adapt<TDto>();
|
||||
dto.Creation = entity.Creation.ToOffset(offset);
|
||||
|
||||
if (entity.Obsolete.HasValue)
|
||||
dto.Obsolete = entity.Obsolete.Value.ToOffset(offset);
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
private async Task<int> SaveChangesWithExceptionHandling(CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await context.SaveChangesAsync(token);
|
||||
return result;
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (ex.InnerException is PostgresException pgException)
|
||||
TryConvertPostgresExceptionToValidateException(pgException);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryConvertPostgresExceptionToValidateException(PostgresException pgException)
|
||||
{
|
||||
if (pgException.SqlState == PostgresErrorCodes.ForeignKeyViolation)
|
||||
throw new ArgumentInvalidException("dtos", pgException.Message + "\r\n" + pgException.Detail);
|
||||
}
|
||||
}
|
@ -10,31 +10,14 @@ namespace AsbCloudWebApi.IntegrationTests;
|
||||
|
||||
public abstract class BaseIntegrationTest : IClassFixture<WebAppFactoryFixture>
|
||||
{
|
||||
private readonly IServiceScope scope;
|
||||
private readonly HttpClient httpClient;
|
||||
|
||||
protected readonly IServiceScope scope;
|
||||
protected readonly IAsbCloudDbContext dbContext;
|
||||
protected readonly WebAppFactoryFixture factory;
|
||||
|
||||
protected IAdminDepositClient adminDepositClient;
|
||||
|
||||
protected BaseIntegrationTest(WebAppFactoryFixture factory)
|
||||
protected BaseIntegrationTest(WebAppFactoryFixture factory)
|
||||
{
|
||||
scope = factory.Services.CreateScope();
|
||||
httpClient = factory.CreateClient();
|
||||
|
||||
dbContext = scope.ServiceProvider.GetRequiredService<IAsbCloudDbContext>();
|
||||
|
||||
var jwtToken = ApiTokenHelper.GetAdminUserToken();
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
|
||||
|
||||
var jsonSerializerOptions = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
var refitSettings = new RefitSettings(new SystemTextJsonContentSerializer(jsonSerializerOptions));
|
||||
|
||||
adminDepositClient = RestService.For<IAdminDepositClient>(httpClient, refitSettings);
|
||||
}
|
||||
this.factory = factory;
|
||||
}
|
||||
}
|
@ -24,4 +24,4 @@ public interface IAdminDepositClient
|
||||
|
||||
[Delete(BaseRoute + "/{id}")]
|
||||
Task<IApiResponse<int>> DeleteAsync(int id);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
using AsbCloudApp.Data.ProcessMapPlan;
|
||||
using AsbCloudApp.Requests;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Refit;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.Clients;
|
||||
|
||||
public interface IProcessMapPlanDrillingClient
|
||||
{
|
||||
private const string BaseRoute = "/api/well/{idWell}/ProcessMapPlanDrilling";
|
||||
|
||||
[Post(BaseRoute)]
|
||||
Task<IApiResponse<int>> InsertRange(int idWell, [Body] IEnumerable<ProcessMapPlanDrillingDto> dtos);
|
||||
|
||||
[Post($"{BaseRoute}/replace")]
|
||||
Task<IApiResponse<int>> ClearAndInsertRange(int idWell, [Body] IEnumerable<ProcessMapPlanDrillingDto> dtos);
|
||||
|
||||
[Delete(BaseRoute)]
|
||||
Task<IApiResponse<int>> DeleteRange(int idWell, [Body] IEnumerable<int> ids);
|
||||
|
||||
[Get(BaseRoute)]
|
||||
Task<IApiResponse<IEnumerable<ProcessMapPlanDrillingDto>>> Get(int idWell, ProcessMapPlanBaseRequest request);
|
||||
|
||||
[Get($"{BaseRoute}/changeLog")]
|
||||
Task<IApiResponse<IEnumerable<ProcessMapPlanDrillingDto>>> GetChangeLog(int idWell, DateOnly? date);
|
||||
|
||||
[Get($"{BaseRoute}/dates")]
|
||||
Task<IApiResponse<IEnumerable<DateOnly>>> GetDatesChange(int idWell);
|
||||
|
||||
[Put(BaseRoute)]
|
||||
Task<IApiResponse<int>> UpdateRangeAsync(int idWell, IEnumerable<ProcessMapPlanDrillingDto> dtos);
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
using System.Net;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudDb.Model.ProcessMaps;
|
||||
using AsbCloudWebApi.IntegrationTests.Clients;
|
||||
using AsbCloudWebApi.IntegrationTests.TestFakers;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -9,19 +12,26 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers;
|
||||
|
||||
public class AdminDepositControllerTests : BaseIntegrationTest
|
||||
{
|
||||
public AdminDepositControllerTests(WebAppFactoryFixture factory)
|
||||
: base(factory)
|
||||
{
|
||||
}
|
||||
protected IAdminDepositClient client;
|
||||
|
||||
public AdminDepositControllerTests(WebAppFactoryFixture factory)
|
||||
: base(factory)
|
||||
{
|
||||
client = factory.GetAuthorizedHttpClient<IAdminDepositClient>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InsertAsync_ReturnsSuccess_WhenNewItemIsValid()
|
||||
{
|
||||
//arrange
|
||||
var expectedDto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
||||
//arrange
|
||||
var dbset = dbContext.Set<Deposit>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
var expectedDto = EntitiesFaker.Deposit.Generate().Adapt<DepositBaseDto>();
|
||||
|
||||
//act
|
||||
var response = await adminDepositClient.InsertAsync(expectedDto);
|
||||
var response = await client.InsertAsync(expectedDto);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
@ -37,11 +47,15 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
||||
[Fact]
|
||||
public async Task InsertRangeAsync_ReturnsSuccess_WhenAllNewItemsIsValid()
|
||||
{
|
||||
//arrange
|
||||
var dto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
||||
//arrange
|
||||
var dbset = dbContext.Set<Deposit>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
//act
|
||||
var responce = await adminDepositClient.InsertRangeAsync(new[] { dto });
|
||||
var dto = EntitiesFaker.Deposit.Generate().Adapt<DepositBaseDto>();
|
||||
|
||||
//act
|
||||
var responce = await client.InsertRangeAsync(new[] { dto });
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, responce.StatusCode);
|
||||
@ -58,10 +72,10 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
||||
public async Task UpdateAsync_ReturnsBadRequest_WhenUpdatedItemHasInvalidId()
|
||||
{
|
||||
//arrange
|
||||
var dto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
||||
var dto = EntitiesFaker.Deposit.Generate().Adapt<DepositBaseDto>();
|
||||
|
||||
//act
|
||||
var response = await adminDepositClient.UpdateAsync(dto);
|
||||
var response = await client.UpdateAsync(dto);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
@ -71,8 +85,8 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
||||
public async Task UpdateAsync_ReturnsSuccess_WhenUpdatedItemIsValid()
|
||||
{
|
||||
//arrange
|
||||
var dto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
||||
var insertResponse = await adminDepositClient.InsertAsync(dto);
|
||||
var dto = EntitiesFaker.Deposit.Generate().Adapt<DepositBaseDto>();
|
||||
var insertResponse = await client.InsertAsync(dto);
|
||||
|
||||
dto.Id = insertResponse.Content;
|
||||
dto.Caption = "Test";
|
||||
@ -85,7 +99,7 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
||||
};
|
||||
|
||||
//act
|
||||
var response = await adminDepositClient.UpdateAsync(dto);
|
||||
var response = await client.UpdateAsync(dto);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
@ -101,22 +115,17 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
||||
public async Task GetOrDefaultAsync_ReturnsSuccess_WhenIdIsValid()
|
||||
{
|
||||
//arrange
|
||||
var dto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
||||
var insertResponse = await adminDepositClient.InsertAsync(dto);
|
||||
var id = insertResponse.Content;
|
||||
var entity = await dbContext.Deposits.FirstAsync();
|
||||
var expected = entity.Adapt<DepositBaseDto>();
|
||||
|
||||
//act
|
||||
var response = await adminDepositClient.GetOrDefaultAsync(id);
|
||||
//act
|
||||
var response = await client.GetOrDefaultAsync(entity.Id);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.NotNull(response.Content);
|
||||
|
||||
var entity = await dbContext.Deposits.FirstOrDefaultAsync(d => d.Id == response.Content.Id);
|
||||
var deposit = entity?.Adapt<DepositBaseDto>();
|
||||
|
||||
var excludeProps = new[] { nameof(DepositBaseDto.Id) };
|
||||
MatchHelper.Match(dto, deposit, excludeProps);
|
||||
MatchHelper.Match(expected, response.Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -126,7 +135,7 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
||||
const int id = 0;
|
||||
|
||||
//act
|
||||
var responce = await adminDepositClient.GetOrDefaultAsync(id);
|
||||
var responce = await client.GetOrDefaultAsync(id);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.NoContent, responce.StatusCode);
|
||||
@ -136,7 +145,7 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
||||
public async Task GetAllAsync_ReturnsSuccess()
|
||||
{
|
||||
//act
|
||||
var response = await adminDepositClient.GetAllAsync();
|
||||
var response = await client.GetAllAsync();
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
@ -156,12 +165,12 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
||||
public async Task DeleteAsync_ReturnsSuccess_WhenIdIsValid()
|
||||
{
|
||||
//arrange
|
||||
var dto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
||||
var insertResponse = await adminDepositClient.InsertAsync(dto);
|
||||
var dto = EntitiesFaker.Deposit.Generate().Adapt<DepositBaseDto>();
|
||||
var insertResponse = await client.InsertAsync(dto);
|
||||
var id = insertResponse.Content;
|
||||
|
||||
//act
|
||||
var response = await adminDepositClient.DeleteAsync(id);
|
||||
var response = await client.DeleteAsync(id);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
@ -178,7 +187,7 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
||||
const int id = 0;
|
||||
|
||||
//act
|
||||
var response = await adminDepositClient.DeleteAsync(id);
|
||||
var response = await client.DeleteAsync(id);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
|
||||
|
@ -0,0 +1,550 @@
|
||||
using AsbCloudApp.Data.ProcessMapPlan;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudDb.Model.ProcessMapPlan;
|
||||
using AsbCloudDb.Model.ProcessMaps;
|
||||
using AsbCloudWebApi.IntegrationTests.Clients;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Net;
|
||||
using Xunit;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.Controllers;
|
||||
|
||||
public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest
|
||||
{
|
||||
private IProcessMapPlanDrillingClient client;
|
||||
private readonly ProcessMapPlanDrillingDto dto = new (){
|
||||
Id = 0,
|
||||
IdAuthor = 0,
|
||||
IdEditor = null,
|
||||
Creation = new(),
|
||||
Obsolete = null,
|
||||
IdState = 0,
|
||||
IdPrevious = null,
|
||||
|
||||
IdWell = 1,
|
||||
IdWellSectionType = 1,
|
||||
DepthStart = 0.5,
|
||||
DepthEnd = 1.5,
|
||||
|
||||
IdMode = 1,
|
||||
AxialLoadPlan = 2.718281,
|
||||
AxialLoadLimitMax = 3.1415926,
|
||||
DeltaPressurePlan = 4,
|
||||
DeltaPressureLimitMax = 5,
|
||||
TopDriveTorquePlan = 6,
|
||||
TopDriveTorqueLimitMax = 7,
|
||||
TopDriveSpeedPlan = 8,
|
||||
TopDriveSpeedLimitMax = 9,
|
||||
FlowPlan = 10,
|
||||
FlowLimitMax = 11,
|
||||
RopPlan = 12,
|
||||
UsageSaub = 13,
|
||||
UsageSpin = 14,
|
||||
Comment = "это тестовая запись",
|
||||
};
|
||||
private readonly ProcessMapPlanDrilling entity = new ()
|
||||
{
|
||||
Id = 0,
|
||||
IdAuthor = 1,
|
||||
IdEditor = null,
|
||||
Creation = DateTimeOffset.UtcNow,
|
||||
Obsolete = null,
|
||||
IdState = AsbCloudDb.Model.ChangeLogAbstract.IdStateActual,
|
||||
IdPrevious = null,
|
||||
|
||||
IdWell = 1,
|
||||
IdWellSectionType = 1,
|
||||
DepthStart = 0.5,
|
||||
DepthEnd = 1.5,
|
||||
|
||||
IdMode = 1,
|
||||
AxialLoadPlan = 2.718281,
|
||||
AxialLoadLimitMax = 3.1415926,
|
||||
DeltaPressurePlan = 4,
|
||||
DeltaPressureLimitMax = 5,
|
||||
TopDriveTorquePlan = 6,
|
||||
TopDriveTorqueLimitMax = 7,
|
||||
TopDriveSpeedPlan = 8,
|
||||
TopDriveSpeedLimitMax = 9,
|
||||
FlowPlan = 10,
|
||||
FlowLimitMax = 11,
|
||||
RopPlan = 12,
|
||||
UsageSaub = 13,
|
||||
UsageSpin = 14,
|
||||
Comment = "это тестовая запись",
|
||||
};
|
||||
|
||||
public ProcessMapPlanDrillingControllerTest(WebAppFactoryFixture factory) : base(factory)
|
||||
{
|
||||
client = factory.GetAuthorizedHttpClient<IProcessMapPlanDrillingClient>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InsertRange_returns_success()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
var expected = dto.Adapt<ProcessMapPlanDrillingDto>();
|
||||
|
||||
//act
|
||||
var response = await client.InsertRange(dto.IdWell, new[] { expected });
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(1, response.Content);
|
||||
|
||||
var entity = dbContext.Set<ProcessMapPlanDrilling>()
|
||||
.Where(p => p.AxialLoadPlan == dto.AxialLoadPlan)
|
||||
.Where(p => p.AxialLoadLimitMax == dto.AxialLoadLimitMax)
|
||||
.Where(p => p.Comment == dto.Comment)
|
||||
.Where(p => p.IdWell == dto.IdWell)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.NotNull(entity);
|
||||
|
||||
var actual = entity.Adapt<ProcessMapPlanDrillingDto>();
|
||||
Assert.Equal(ProcessMapPlanBase.IdStateActual, actual.IdState);
|
||||
|
||||
var excludeProps = new[] {
|
||||
nameof(ProcessMapPlanDrillingDto.Id),
|
||||
nameof(ProcessMapPlanDrillingDto.IdState),
|
||||
nameof(ProcessMapPlanDrillingDto.IdAuthor),
|
||||
nameof(ProcessMapPlanDrillingDto.Creation),
|
||||
};
|
||||
MatchHelper.Match(expected, actual, excludeProps);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InsertRange_returns_BadRequest_for_IdWellSectionType()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
var badDto = dto.Adapt<ProcessMapPlanDrillingDto>();
|
||||
badDto.IdWellSectionType = int.MaxValue;
|
||||
|
||||
//act
|
||||
var response = await client.InsertRange(dto.IdWell, new[] { badDto });
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InsertRange_returns_BadRequest_for_IdMode()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
var badDto = dto.Adapt<ProcessMapPlanDrillingDto>();
|
||||
badDto.IdMode = int.MaxValue;
|
||||
|
||||
//act
|
||||
var response = await client.InsertRange(dto.IdWell, new[] { badDto });
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InsertRange_returns_BadRequest_for_IdWell()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
var badDto = dto.Adapt<ProcessMapPlanDrillingDto>();
|
||||
badDto.IdWell = int.MaxValue;
|
||||
|
||||
//act
|
||||
var response = await client.InsertRange(dto.IdWell, new[] { badDto });
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ClearAndInsertRange_returns_success()
|
||||
{
|
||||
// arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
var startTime = DateTimeOffset.UtcNow;
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
var entry = dbset.Add(entity);
|
||||
dbContext.SaveChanges();
|
||||
entry.State = EntityState.Detached;
|
||||
|
||||
// act
|
||||
var result = await client.ClearAndInsertRange(entity.IdWell, new ProcessMapPlanDrillingDto[] { dto });
|
||||
|
||||
// assert
|
||||
var doneTime = DateTimeOffset.UtcNow;
|
||||
Assert.Equal(HttpStatusCode.OK, result.StatusCode);
|
||||
Assert.Equal(2, result.Content);
|
||||
|
||||
var count = dbset.Count();
|
||||
Assert.Equal(2, count);
|
||||
|
||||
var oldEntity = dbset.First(p => p.Id == entry.Entity.Id);
|
||||
Assert.Equal(ProcessMapPlanBase.IdClearedOnImport, oldEntity.IdState);
|
||||
Assert.Equal(1, oldEntity.IdEditor);
|
||||
Assert.NotNull(oldEntity.Obsolete);
|
||||
Assert.InRange(oldEntity.Obsolete.Value, startTime, doneTime);
|
||||
|
||||
var newEntity = dbset.First(p => p.Id != entry.Entity.Id);
|
||||
Assert.Equal(ProcessMapPlanBase.IdStateActual, newEntity.IdState);
|
||||
Assert.Equal(1, newEntity.IdAuthor);
|
||||
Assert.Null(newEntity.IdEditor);
|
||||
Assert.Null(newEntity.Obsolete);
|
||||
Assert.Null(newEntity.IdPrevious);
|
||||
Assert.InRange(newEntity.Creation, startTime, doneTime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateRange_returns_success()
|
||||
{
|
||||
// arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
var startTime = DateTimeOffset.UtcNow;
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
var entry = dbset.Add(entity);
|
||||
dbContext.SaveChanges();
|
||||
entry.State = EntityState.Detached;
|
||||
|
||||
var dtoCopy = dto.Adapt<ProcessMapPlanDrillingDto>();
|
||||
dtoCopy.Id = entry.Entity.Id;
|
||||
dtoCopy.Comment = "nebuchadnezzar";
|
||||
dtoCopy.DeltaPressureLimitMax ++;
|
||||
dtoCopy.DeltaPressurePlan ++;
|
||||
dtoCopy.FlowPlan ++;
|
||||
dtoCopy.FlowLimitMax ++;
|
||||
dtoCopy.RopPlan ++;
|
||||
dtoCopy.AxialLoadPlan ++;
|
||||
dtoCopy.AxialLoadLimitMax ++;
|
||||
dtoCopy.DepthStart ++;
|
||||
dtoCopy.DepthEnd ++;
|
||||
dtoCopy.TopDriveSpeedPlan ++;
|
||||
dtoCopy.TopDriveSpeedLimitMax ++;
|
||||
dtoCopy.TopDriveTorquePlan ++;
|
||||
dtoCopy.TopDriveTorqueLimitMax ++;
|
||||
|
||||
// act
|
||||
var result = await client.UpdateRangeAsync(entity.IdWell, new ProcessMapPlanDrillingDto[] { dtoCopy });
|
||||
|
||||
// assert
|
||||
var doneTime = DateTimeOffset.UtcNow;
|
||||
Assert.Equal(HttpStatusCode.OK, result.StatusCode);
|
||||
Assert.Equal(2, result.Content);
|
||||
|
||||
var count = dbset.Count();
|
||||
Assert.Equal(2, count);
|
||||
|
||||
var oldEntity = dbset.First(p => p.Id == entry.Entity.Id);
|
||||
Assert.Equal(ProcessMapPlanBase.IdStateReplaced, oldEntity.IdState);
|
||||
Assert.Equal(1, oldEntity.IdEditor);
|
||||
Assert.NotNull(oldEntity.Obsolete);
|
||||
Assert.InRange(oldEntity.Obsolete.Value, startTime, doneTime);
|
||||
|
||||
var newEntity = dbset.First(p => p.Id != entry.Entity.Id);
|
||||
Assert.Equal(ProcessMapPlanBase.IdStateActual, newEntity.IdState);
|
||||
Assert.Equal(1, newEntity.IdAuthor);
|
||||
Assert.Null(newEntity.IdEditor);
|
||||
Assert.Null(newEntity.Obsolete);
|
||||
Assert.Equal(oldEntity.Id, newEntity.IdPrevious);
|
||||
Assert.InRange(newEntity.Creation, startTime, doneTime);
|
||||
|
||||
var expected = dtoCopy.Adapt<ProcessMapPlanDrilling>();
|
||||
var excludeProps = new[] {
|
||||
nameof(ProcessMapPlanDrillingDto.Id),
|
||||
nameof(ProcessMapPlanDrillingDto.IdAuthor),
|
||||
nameof(ProcessMapPlanDrillingDto.Creation),
|
||||
};
|
||||
MatchHelper.Match(expected, newEntity!, excludeProps);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteRange_returns_success()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
var startTime = DateTimeOffset.UtcNow;
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
var entry = dbset.Add(entity);
|
||||
dbContext.SaveChanges();
|
||||
entry.State = EntityState.Detached;
|
||||
|
||||
//act
|
||||
var response = await client.DeleteRange(dto.IdWell, new[] { entry.Entity.Id });
|
||||
|
||||
//assert
|
||||
var doneTime = DateTimeOffset.UtcNow;
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(1, response.Content);
|
||||
|
||||
var actual = dbContext.Set<ProcessMapPlanDrilling>()
|
||||
.Where(p => p.Id == entry.Entity.Id)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.NotNull(actual);
|
||||
Assert.Equal(ProcessMapPlanBase.IdStateDeleted, actual.IdState);
|
||||
Assert.Equal(1, actual.IdEditor);
|
||||
Assert.NotNull(actual.Obsolete);
|
||||
Assert.InRange(actual.Obsolete.Value, startTime, doneTime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetDatesChange_returns_success()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
var entity2 = entity.Adapt<ProcessMapPlanDrilling>();
|
||||
entity2.Creation = entity.Creation.AddDays(1);
|
||||
dbset.Add(entity);
|
||||
dbset.Add(entity2);
|
||||
dbContext.SaveChanges();
|
||||
var timezoneHours = Data.Defaults.Wells[0].Timezone.Hours;
|
||||
var offset = TimeSpan.FromHours(timezoneHours);
|
||||
var dates = new[] { entity.Creation, entity2.Creation }
|
||||
.Select(d => d.ToOffset(offset))
|
||||
.Select(d => new DateOnly(d.Year, d.Month, d.Day));
|
||||
|
||||
//act
|
||||
var response = await client.GetDatesChange(dto.IdWell);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.NotNull(response.Content);
|
||||
Assert.Equal(2, response.Content.Count());
|
||||
Assert.All(response.Content, d => dates.Contains(d));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Get_all_returns_success()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
dbset.Add(entity);
|
||||
|
||||
var entityDeleted = entity.Adapt<ProcessMapPlanDrilling>();
|
||||
entityDeleted.Creation = entity.Creation.AddDays(-1);
|
||||
entityDeleted.Obsolete = entity.Creation;
|
||||
entityDeleted.IdState = ProcessMapPlanBase.IdStateDeleted;
|
||||
entityDeleted.IdEditor = 1;
|
||||
dbset.Add(entityDeleted);
|
||||
|
||||
dbContext.SaveChanges();
|
||||
|
||||
var timezoneHours = Data.Defaults.Wells[0].Timezone.Hours;
|
||||
var offset = TimeSpan.FromHours(timezoneHours);
|
||||
|
||||
//act
|
||||
var request = new ProcessMapPlanBaseRequest
|
||||
{
|
||||
IdWell = dto.IdWell,
|
||||
};
|
||||
var response = await client.Get(dto.IdWell, request);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.NotNull(response.Content);
|
||||
Assert.Equal(2, response.Content.Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Get_actual_returns_success()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
dbset.Add(entity);
|
||||
|
||||
var entityDeleted = entity.Adapt<ProcessMapPlanDrilling>();
|
||||
entityDeleted.Creation = entity.Creation.AddDays(-1);
|
||||
entityDeleted.Obsolete = entity.Creation;
|
||||
entityDeleted.IdState = ProcessMapPlanBase.IdStateDeleted;
|
||||
entityDeleted.IdEditor = 1;
|
||||
entityDeleted.Comment = "nothing";
|
||||
dbset.Add(entityDeleted);
|
||||
|
||||
dbContext.SaveChanges();
|
||||
|
||||
var timezoneHours = Data.Defaults.Wells[0].Timezone.Hours;
|
||||
var offset = TimeSpan.FromHours(timezoneHours);
|
||||
|
||||
//act
|
||||
var request = new ProcessMapPlanBaseRequest {
|
||||
IdWell = dto.IdWell,
|
||||
Moment = new DateTimeOffset(3000, 1, 1, 0, 0, 0, 0, TimeSpan.Zero)
|
||||
};
|
||||
var response = await client.Get(dto.IdWell, request);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.NotNull(response.Content);
|
||||
Assert.Single(response.Content);
|
||||
|
||||
var actual = response.Content.First()!;
|
||||
|
||||
var expected = entity.Adapt<ProcessMapPlanDrillingDto>()!;
|
||||
var excludeProps = new[] {
|
||||
nameof(ProcessMapPlanDrillingDto.Id),
|
||||
nameof(ProcessMapPlanDrillingDto.IdAuthor),
|
||||
nameof(ProcessMapPlanDrillingDto.Creation),
|
||||
};
|
||||
MatchHelper.Match(expected, actual, excludeProps);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Get_at_moment_returns_success()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var entityDeleted = entity.Adapt<ProcessMapPlanDrilling>();
|
||||
entityDeleted.Creation = now;
|
||||
entityDeleted.Obsolete = now.AddMinutes(1);
|
||||
entityDeleted.IdState = ProcessMapPlanBase.IdStateDeleted;
|
||||
entityDeleted.IdEditor = 1;
|
||||
entityDeleted.Comment = "nothing";
|
||||
dbset.Add(entityDeleted);
|
||||
|
||||
var entityDeleted2 = entity.Adapt<ProcessMapPlanDrilling>();
|
||||
entityDeleted2.Creation = now.AddMinutes(1);
|
||||
entityDeleted2.Obsolete = now.AddMinutes(2);
|
||||
entityDeleted2.IdState = ProcessMapPlanBase.IdStateDeleted;
|
||||
entityDeleted2.IdEditor = 1;
|
||||
entityDeleted2.Comment = "nothing";
|
||||
dbset.Add(entityDeleted2);
|
||||
|
||||
dbContext.SaveChanges();
|
||||
|
||||
var timezoneHours = Data.Defaults.Wells[0].Timezone.Hours;
|
||||
var offset = TimeSpan.FromHours(timezoneHours);
|
||||
|
||||
//act
|
||||
var request = new ProcessMapPlanBaseRequest
|
||||
{
|
||||
IdWell = dto.IdWell,
|
||||
Moment = now.AddMinutes(0.5),
|
||||
};
|
||||
var response = await client.Get(dto.IdWell, request);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.NotNull(response.Content);
|
||||
Assert.Equal(1, response.Content.Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Get_section_returns_success()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
dbset.Add(entity);
|
||||
|
||||
var entity2 = entity.Adapt<ProcessMapPlanDrilling>();
|
||||
entity2.IdWellSectionType = 2;
|
||||
entity2.Comment = "IdWellSectionType = 2";
|
||||
dbset.Add(entity2);
|
||||
|
||||
dbContext.SaveChanges();
|
||||
|
||||
var timezoneHours = Data.Defaults.Wells[0].Timezone.Hours;
|
||||
var offset = TimeSpan.FromHours(timezoneHours);
|
||||
|
||||
//act
|
||||
var request = new ProcessMapPlanBaseRequest
|
||||
{
|
||||
IdWell = dto.IdWell,
|
||||
IdWellSectionType = 2,
|
||||
};
|
||||
var response = await client.Get(dto.IdWell, request);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.NotNull(response.Content);
|
||||
Assert.Single(response.Content);
|
||||
|
||||
var actual = response.Content.First()!;
|
||||
|
||||
var expected = entity2.Adapt<ProcessMapPlanDrillingDto>()!;
|
||||
var excludeProps = new[] {
|
||||
nameof(ProcessMapPlanDrillingDto.Id),
|
||||
nameof(ProcessMapPlanDrillingDto.IdAuthor),
|
||||
nameof(ProcessMapPlanDrillingDto.Creation),
|
||||
};
|
||||
MatchHelper.Match(expected, actual, excludeProps);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Get_updated_returns_success()
|
||||
{
|
||||
//arrange
|
||||
var dbset = dbContext.Set<ProcessMapPlanDrilling>();
|
||||
dbset.RemoveRange(dbset);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
dbset.Add(entity);
|
||||
|
||||
var entity2 = entity.Adapt<ProcessMapPlanDrilling>();
|
||||
entity2.Creation = entity.Creation.AddHours(1);
|
||||
entity2.Comment = "IdWellSectionType = 2";
|
||||
dbset.Add(entity2);
|
||||
|
||||
var entity3 = entity.Adapt<ProcessMapPlanDrilling>();
|
||||
entity3.Obsolete = entity.Creation.AddHours(1);
|
||||
entity3.Comment = "IdWellSectionType = 3";
|
||||
dbset.Add(entity3);
|
||||
|
||||
dbContext.SaveChanges();
|
||||
|
||||
var timezoneHours = Data.Defaults.Wells[0].Timezone.Hours;
|
||||
var offset = TimeSpan.FromHours(timezoneHours);
|
||||
var updateFrom = entity.Creation.ToOffset(offset).AddHours(0.5);
|
||||
|
||||
//act
|
||||
var request = new ProcessMapPlanBaseRequest
|
||||
{
|
||||
IdWell = dto.IdWell,
|
||||
UpdateFrom = updateFrom,
|
||||
};
|
||||
var response = await client.Get(dto.IdWell, request);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.NotNull(response.Content);
|
||||
Assert.Equal(2, response.Content.Count());
|
||||
|
||||
var actual = response.Content
|
||||
.Where(p=>p.Comment == entity2.Comment)
|
||||
.First();
|
||||
|
||||
var expected = entity2.Adapt<ProcessMapPlanDrillingDto>();
|
||||
var excludeProps = new[] {
|
||||
nameof(ProcessMapPlanDrillingDto.Id),
|
||||
nameof(ProcessMapPlanDrillingDto.IdAuthor),
|
||||
nameof(ProcessMapPlanDrillingDto.Creation),
|
||||
};
|
||||
MatchHelper.Match(expected, actual, excludeProps);
|
||||
}
|
||||
}
|
63
AsbCloudWebApi.IntegrationTests/Data/Defaults.cs
Normal file
63
AsbCloudWebApi.IntegrationTests/Data/Defaults.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.Data
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2211:Поля, не являющиеся константами, не должны быть видимыми", Justification = "<Ожидание>")]
|
||||
public static class Defaults
|
||||
{
|
||||
public static Deposit[] Deposits = new Deposit[] {
|
||||
new()
|
||||
{
|
||||
Id = 1,
|
||||
Caption = "Deposit1",
|
||||
Latitude = 10,
|
||||
Longitude = 20,
|
||||
Timezone = new SimpleTimezone{
|
||||
Hours = 1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static Cluster[] Clusters = new Cluster[] {
|
||||
new()
|
||||
{
|
||||
Id = 1,
|
||||
IdDeposit = Deposits[0].Id,
|
||||
Caption = "Cluster1",
|
||||
Latitude = 10,
|
||||
Longitude = 20,
|
||||
Timezone = new SimpleTimezone{
|
||||
Hours = 1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static Well[] Wells = new Well[] {
|
||||
new()
|
||||
{
|
||||
Id = 1,
|
||||
IdCluster = Clusters[0].Id,
|
||||
IdWellType = 1,
|
||||
IdState = 1,
|
||||
Caption = "Well1",
|
||||
Latitude = 10,
|
||||
Longitude = 20,
|
||||
IdTelemetry = null,
|
||||
Timezone = new SimpleTimezone{
|
||||
Hours = 1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static RelationCompanyWell[] RelationsCompanyWell = new RelationCompanyWell[]
|
||||
{
|
||||
new(){IdCompany= 1, IdWell = Wells[0].Id},
|
||||
};
|
||||
|
||||
public static RelationUserUserRole[] RelationsUserUserRole = new RelationUserUserRole[]
|
||||
{
|
||||
new(){ IdUserRole= 1, IdUser = 1}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using AsbCloudDb.Model;
|
||||
using Bogus;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.TestFakers;
|
||||
|
||||
public static class DepositTestFaker
|
||||
{
|
||||
public static Deposit GetDeposit() =>
|
||||
GetDepositFaker().Generate();
|
||||
|
||||
public static IEnumerable<Deposit> GetDeposits(int count) =>
|
||||
GetDepositFaker().Generate(count);
|
||||
|
||||
private static Faker<Deposit> GetDepositFaker() =>
|
||||
new Faker<Deposit>()
|
||||
.RuleFor(d => d.Id, 0)
|
||||
.RuleFor(d => d.Caption, f => f.Random.String2(1, 50))
|
||||
.RuleFor(d => d.Latitude, f => f.Random.Int(-90, 90))
|
||||
.RuleFor(d => d.Longitude, f => f.Random.Int(-180, 180))
|
||||
.RuleFor(d => d.Timezone, f => new SimpleTimezone
|
||||
{
|
||||
Hours = f.Random.Int(1, 12),
|
||||
IsOverride = f.Random.Bool()
|
||||
});
|
||||
}
|
40
AsbCloudWebApi.IntegrationTests/TestFakers/EntitiesFaker.cs
Normal file
40
AsbCloudWebApi.IntegrationTests/TestFakers/EntitiesFaker.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using AsbCloudDb.Model;
|
||||
using Bogus;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.TestFakers;
|
||||
|
||||
public static class EntitiesFaker
|
||||
{
|
||||
public static Faker<Deposit> Deposit { get; } = new Faker<Deposit>()
|
||||
.RuleFor(d => d.Id, 0)
|
||||
.RuleFor(d => d.Caption, f => f.Random.String2(1, 50))
|
||||
.RuleFor(d => d.Latitude, f => f.Random.Double(-90, 90))
|
||||
.RuleFor(d => d.Longitude, f => f.Random.Double(-180, 180))
|
||||
.RuleFor(d => d.Timezone, f => new SimpleTimezone
|
||||
{
|
||||
Hours = f.Random.Int(1, 12),
|
||||
IsOverride = f.Random.Bool()
|
||||
});
|
||||
|
||||
public static Faker<Cluster> Cluster { get; } = new Faker<Cluster>()
|
||||
.RuleFor(d => d.Id, 0)
|
||||
.RuleFor(d => d.Caption, f => f.Random.String2(1, 50))
|
||||
.RuleFor(d => d.Latitude, f => f.Random.Double(-90, 90))
|
||||
.RuleFor(d => d.Longitude, f => f.Random.Double(-180, 180))
|
||||
.RuleFor(d => d.Timezone, f => new SimpleTimezone
|
||||
{
|
||||
Hours = f.Random.Int(1, 12),
|
||||
IsOverride = f.Random.Bool()
|
||||
});
|
||||
|
||||
public static Faker<Well> Well { get; } = new Faker<Well>()
|
||||
.RuleFor(d => d.Id, 0)
|
||||
.RuleFor(d => d.Caption, f => f.Random.String2(1, 50))
|
||||
.RuleFor(d => d.Latitude, f => f.Random.Double(-90, 90))
|
||||
.RuleFor(d => d.Longitude, f => f.Random.Double(-180, 180))
|
||||
.RuleFor(d => d.Timezone, f => new SimpleTimezone
|
||||
{
|
||||
Hours = f.Random.Int(1, 12),
|
||||
IsOverride = f.Random.Bool()
|
||||
});
|
||||
}
|
@ -6,6 +6,10 @@ using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ProtoBuf.Serializers;
|
||||
using Refit;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests;
|
||||
@ -13,12 +17,20 @@ namespace AsbCloudWebApi.IntegrationTests;
|
||||
public class WebAppFactoryFixture : WebApplicationFactory<Startup>,
|
||||
IAsyncLifetime
|
||||
{
|
||||
private static readonly JsonSerializerOptions jsonSerializerOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
private static readonly RefitSettings refitSettings = new RefitSettings(new SystemTextJsonContentSerializer(jsonSerializerOptions));
|
||||
|
||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.Build();
|
||||
var connectionString = configuration.GetConnectionString("TestConnection");
|
||||
var connectionString = configuration.GetConnectionString("TestConnection")!;
|
||||
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
@ -37,19 +49,41 @@ public class WebAppFactoryFixture : WebApplicationFactory<Startup>,
|
||||
using var scope = Services.CreateScope();
|
||||
var scopedServices = scope.ServiceProvider;
|
||||
var dbContext = scopedServices.GetRequiredService<AsbCloudDbContext>();
|
||||
|
||||
dbContext.Database.EnsureCreatedAndMigrated();
|
||||
|
||||
dbContext.Deposits.AddRange(DepositTestFaker.GetDeposits(15));
|
||||
await dbContext.SaveChangesAsync();
|
||||
dbContext.Database.EnsureDeleted();
|
||||
dbContext.Database.EnsureCreatedAndMigrated();
|
||||
await FillBaseDatasets(dbContext);
|
||||
}
|
||||
|
||||
public new async Task DisposeAsync()
|
||||
private static async Task FillBaseDatasets(AsbCloudDbContext dbContext)
|
||||
{
|
||||
dbContext.AddRange(Data.Defaults.Deposits);
|
||||
dbContext.AddRange(Data.Defaults.Clusters);
|
||||
dbContext.AddRange(Data.Defaults.Wells);
|
||||
dbContext.AddRange(Data.Defaults.RelationsCompanyWell);
|
||||
await dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public new async Task DisposeAsync()
|
||||
{
|
||||
using var scope = Services.CreateScope();
|
||||
var scopedServices = scope.ServiceProvider;
|
||||
var dbContext = scopedServices.GetRequiredService<AsbCloudDbContext>();
|
||||
|
||||
await dbContext.Database.EnsureDeletedAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public HttpClient GetAuthorizedHttpClient()
|
||||
{
|
||||
var httpClient = CreateClient();
|
||||
var jwtToken = ApiTokenHelper.GetAdminUserToken();
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
public T GetAuthorizedHttpClient<T>()
|
||||
{
|
||||
var httpClient = GetAuthorizedHttpClient();
|
||||
return RestService.For<T>(httpClient, refitSettings);
|
||||
}
|
||||
|
||||
}
|
2
AsbCloudWebApi.IntegrationTests/readme.md
Normal file
2
AsbCloudWebApi.IntegrationTests/readme.md
Normal file
@ -0,0 +1,2 @@
|
||||
Статья от ms https://learn.microsoft.com/ru-ru/aspnet/core/test/integration-tests?view=aspnetcore-6.0
|
||||
refit https://github.com/reactiveui/refit
|
@ -0,0 +1,198 @@
|
||||
using AsbCloudApp.Data.ProcessMapPlan;
|
||||
using AsbCloudApp.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Requests;
|
||||
using System;
|
||||
using AsbCloudApp.Services;
|
||||
using System.Linq;
|
||||
|
||||
namespace AsbCloudWebApi.Controllers.ProcessMapPlan;
|
||||
|
||||
/// <summary>
|
||||
/// РТК план
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/well/{idWell}/[controller]")]
|
||||
[Authorize]
|
||||
public abstract class ProcessMapPlanBaseController<TDto> : ControllerBase
|
||||
where TDto : ProcessMapPlanBaseDto
|
||||
{
|
||||
private readonly IProcessMapPlanBaseRepository<TDto> repository;
|
||||
private readonly IWellService wellService;
|
||||
|
||||
public ProcessMapPlanBaseController(IProcessMapPlanBaseRepository<TDto> repository, IWellService wellService)
|
||||
{
|
||||
this.repository = repository;
|
||||
this.wellService = wellService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавление
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> InsertRange([FromRoute] int idWell, IEnumerable<TDto> dtos, CancellationToken token)
|
||||
{
|
||||
if (idWell == 0 || dtos.Any(d => d.IdWell != idWell))
|
||||
return this.ValidationBadRequest(nameof(dtos), "all dtos should contain same idWell");
|
||||
|
||||
var idUser = await AssertUserHasAccessToWell(idWell, token);
|
||||
var result = await repository.InsertRange(idUser, dtos, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удалить все по скважине и добавить новые
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("replace")]
|
||||
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> ClearAndInsertRange([FromRoute] int idWell, IEnumerable<TDto> dtos, CancellationToken token)
|
||||
{
|
||||
if (idWell == 0 || dtos.Any(d => d.IdWell != idWell))
|
||||
return this.ValidationBadRequest(nameof(dtos), "all dtos should contain same idWell");
|
||||
|
||||
var idUser = await AssertUserHasAccessToWell(idWell, token);
|
||||
var result = await repository.ClearAndInsertRange(idUser, idWell, dtos, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> DeleteRange([FromRoute]int idWell, IEnumerable<int> ids, CancellationToken token)
|
||||
{
|
||||
var idUser = await AssertUserHasAccessToWell(idWell, token);
|
||||
var result = await repository.DeleteRange(idUser, ids, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
public async Task<ActionResult<IEnumerable<TDto>>> Get([FromRoute] int idWell, [FromQuery]ProcessMapPlanBaseRequest request, CancellationToken token)
|
||||
{
|
||||
request.IdWell = idWell;
|
||||
await AssertUserHasAccessToWell(request.IdWell, token);
|
||||
var result = await repository.Get(request, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Изменения за определенную дату
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="date"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("changeLog")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
public async Task<ActionResult<IEnumerable<TDto>>> GetChangeLog([FromRoute] int idWell, [FromQuery] DateOnly? date, CancellationToken token)
|
||||
{
|
||||
await AssertUserHasAccessToWell(idWell, token);
|
||||
var result = await repository.GetChangeLog(idWell, date, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Даты за которые есть изменения
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("dates")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
public async Task<ActionResult<IEnumerable<DateOnly>>> GetDatesChange([FromRoute] int idWell, CancellationToken token)
|
||||
{
|
||||
await AssertUserHasAccessToWell(idWell, token);
|
||||
var result = await repository.GetDatesChange(idWell, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Редактирование
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPut]
|
||||
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> UpdateRange([FromRoute] int idWell, IEnumerable<TDto> dtos, CancellationToken token)
|
||||
{
|
||||
var first = dtos.FirstOrDefault();
|
||||
if(first is null)
|
||||
return NoContent();
|
||||
|
||||
if (idWell == 0 || dtos.Any(d => d.IdWell != idWell))
|
||||
return this.ValidationBadRequest(nameof(dtos), "all dtos should contain same idWell");
|
||||
|
||||
var idUser = await AssertUserHasAccessToWell(idWell, token);
|
||||
|
||||
var result = await repository.UpdateRange(idUser, dtos, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns user id, if he has access to well
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ForbidException"></exception>
|
||||
private async Task<int> AssertUserHasAccessToWell(int idWell, CancellationToken token)
|
||||
{
|
||||
var idUser = GetUserId();
|
||||
var idCompany = User.GetCompanyId();
|
||||
|
||||
if (!idCompany.HasValue)
|
||||
throw new ForbidException("Нет доступа к скважине");
|
||||
|
||||
if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, token))
|
||||
throw new ForbidException("Нет доступа к скважине");
|
||||
return idUser;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns user id or throw
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ForbidException"></exception>
|
||||
private int GetUserId()
|
||||
{
|
||||
var idUser = User.GetUserId() ?? throw new ForbidException("Неизвестный пользователь");
|
||||
return idUser;
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
using AsbCloudApp.Data.ProcessMapPlan;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Services;
|
||||
|
||||
namespace AsbCloudWebApi.Controllers.ProcessMapPlan;
|
||||
|
||||
public class ProcessMapPlanDrillingController : ProcessMapPlanBaseController<ProcessMapPlanDrillingDto>
|
||||
{
|
||||
public ProcessMapPlanDrillingController(IProcessMapPlanBaseRepository<ProcessMapPlanDrillingDto> repository, IWellService wellService)
|
||||
: base(repository, wellService)
|
||||
{
|
||||
}
|
||||
}
|
132
AsbCloudWebApi/Rest/ProcessMapPlanDrilling.http
Normal file
132
AsbCloudWebApi/Rest/ProcessMapPlanDrilling.http
Normal file
@ -0,0 +1,132 @@
|
||||
@baseUrl = http://127.0.0.1:5000
|
||||
@contentType = application/json
|
||||
@contentTypeForFiles = application/octet-stream
|
||||
@auth = Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2OTc0MzcwMzEsImV4cCI6MTcyODk5NDYzMSwiaXNzIjoiYSIsImF1ZCI6ImEifQ.vB7Qb3K9gG77iP8y25zB3RcZIQk9cHkq3I1SkcooYJs
|
||||
|
||||
@uid = 20210101_000000000
|
||||
@id = 1
|
||||
@idWell = 1
|
||||
|
||||
### получение данных drill test с панели и сохранение их в ЕЦП
|
||||
POST {{baseUrl}}/api/well/{{idWell}}/ProcessMapPlanDrilling
|
||||
Content-Type: {{contentType}}
|
||||
accept: */*
|
||||
Authorization: {{auth}}
|
||||
|
||||
[
|
||||
{
|
||||
"id": 0,
|
||||
"idAuthor": 0,
|
||||
"idEditor": 0,
|
||||
"creation": "2024-01-18T12:45:58.205Z",
|
||||
"obsolete": "2024-01-18T12:45:58.205Z",
|
||||
"idState": 0,
|
||||
"idPrevious": 0,
|
||||
"idWell": 1,
|
||||
"idWellSectionType": 1,
|
||||
"depthStart": 0,
|
||||
"depthEnd": 10,
|
||||
"idMode": 2,
|
||||
"axialLoad": {
|
||||
"plan": 0,
|
||||
"limitMax": 0
|
||||
},
|
||||
"deltaPressure": {
|
||||
"plan": 0,
|
||||
"limitMax": 0
|
||||
},
|
||||
"topDriveTorque": {
|
||||
"plan": 0,
|
||||
"limitMax": 0
|
||||
},
|
||||
"topDriveSpeed": {
|
||||
"plan": 0,
|
||||
"limitMax": 0
|
||||
},
|
||||
"flow": {
|
||||
"plan": 0,
|
||||
"limitMax": 0
|
||||
},
|
||||
"ropPlan": 99999.9,
|
||||
"usageSaub": 100,
|
||||
"usageSpin": 100,
|
||||
"comment": ""
|
||||
}
|
||||
]
|
||||
|
||||
### Получение всех
|
||||
GET {{baseUrl}}/api/well/{{idWell}}/ProcessMapPlanDrilling
|
||||
accept: */*
|
||||
Authorization: {{auth}}
|
||||
|
||||
### замена старых записей новыми
|
||||
POST {{baseUrl}}/api/well/{{idWell}}/ProcessMapPlanDrilling/replace
|
||||
Content-Type: {{contentType}}
|
||||
accept: */*
|
||||
Authorization: {{auth}}
|
||||
|
||||
[
|
||||
{
|
||||
"id": 0,
|
||||
"idAuthor": 0,
|
||||
"idEditor": 0,
|
||||
"creation": "2024-01-19T05:31:54.762Z",
|
||||
"obsolete": "2024-01-19T05:31:54.762Z",
|
||||
"idState": 0,
|
||||
"idPrevious": 0,
|
||||
"idWell": 1,
|
||||
"idWellSectionType": 1500,
|
||||
"depthStart": 0,
|
||||
"depthEnd": 10,
|
||||
"idMode": 2,
|
||||
"axialLoad": {
|
||||
"plan": 0,
|
||||
"limitMax": 0
|
||||
},
|
||||
"deltaPressure": {
|
||||
"plan": 0,
|
||||
"limitMax": 0
|
||||
},
|
||||
"topDriveTorque": {
|
||||
"plan": 0,
|
||||
"limitMax": 0
|
||||
},
|
||||
"topDriveSpeed": {
|
||||
"plan": 0,
|
||||
"limitMax": 0
|
||||
},
|
||||
"flow": {
|
||||
"plan": 0,
|
||||
"limitMax": 0
|
||||
},
|
||||
"ropPlan": 99999.9,
|
||||
"usageSaub": 100,
|
||||
"usageSpin": 100,
|
||||
"comment": "There is no spoon"
|
||||
}
|
||||
]
|
||||
|
||||
### Получение только актуальных
|
||||
GET {{baseUrl}}/api/well/{{idWell}}/ProcessMapPlanDrilling?Moment=3000-01-01
|
||||
accept: */*
|
||||
Authorization: {{auth}}
|
||||
|
||||
### Получение
|
||||
GET {{baseUrl}}/api/well/{{idWell}}/ProcessMapPlanDrilling/dates
|
||||
accept: */*
|
||||
Authorization: {{auth}}
|
||||
|
||||
### Получение изменений за дату
|
||||
GET {{baseUrl}}/api/well/{{idWell}}/ProcessMapPlanDrilling/changeLog?date=2024-01-19
|
||||
accept: */*
|
||||
Authorization: {{auth}}
|
||||
|
||||
### удаление
|
||||
DELETE {{baseUrl}}/api/well/{{idWell}}/ProcessMapPlanDrilling
|
||||
Content-Type: {{contentType}}
|
||||
accept: */*
|
||||
Authorization: {{auth}}
|
||||
|
||||
[
|
||||
1
|
||||
]
|
Loading…
Reference in New Issue
Block a user