forked from ddrilling/AsbCloudServer
Merge branch 'dev' into fix/23754474--SignalR-UpdateProcessMap-Method
This commit is contained in:
commit
6f10f2091f
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
|
namespace AsbCloudApp.Data
|
||||||
{
|
{
|
||||||
@ -19,5 +21,66 @@ namespace AsbCloudApp.Data
|
|||||||
[Required]
|
[Required]
|
||||||
public double LimitMax { get; set; }
|
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.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
@ -20,7 +19,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.UseCollation("Russian_Russia.1251")
|
.UseCollation("Russian_Russia.1251")
|
||||||
.HasAnnotation("ProductVersion", "6.0.7")
|
.HasAnnotation("ProductVersion", "6.0.22")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
|
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
|
||||||
@ -388,7 +387,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
.HasColumnName("enabled_subsystems")
|
.HasColumnName("enabled_subsystems")
|
||||||
.HasComment("флаги включенных подсистем");
|
.HasComment("флаги включенных подсистем");
|
||||||
|
|
||||||
b.Property<IDictionary<string, object>>("ExtraData")
|
b.Property<string>("ExtraData")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("extra_data")
|
.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 =>
|
modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapWellDrilling", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -8400,6 +8553,46 @@ namespace AsbCloudDb.Migrations
|
|||||||
b.Navigation("Well");
|
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 =>
|
modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapWellDrilling", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("AsbCloudDb.Model.User", "User")
|
b.HasOne("AsbCloudDb.Model.User", "User")
|
||||||
|
@ -21,6 +21,7 @@ namespace AsbCloudDb.Model
|
|||||||
public virtual DbSet<TrajectoryPlan> TrajectoriesPlan => Set<TrajectoryPlan>();
|
public virtual DbSet<TrajectoryPlan> TrajectoriesPlan => Set<TrajectoryPlan>();
|
||||||
public virtual DbSet<ProcessMapWellDrilling> ProcessMapWellDrillings => Set<ProcessMapWellDrilling>();
|
public virtual DbSet<ProcessMapWellDrilling> ProcessMapWellDrillings => Set<ProcessMapWellDrilling>();
|
||||||
public virtual DbSet<ProcessMapWellReam> ProcessMapWellReams => Set<ProcessMapWellReam>();
|
public virtual DbSet<ProcessMapWellReam> ProcessMapWellReams => Set<ProcessMapWellReam>();
|
||||||
|
public virtual DbSet<ProcessMapPlanDrilling> ProcessMapPlanDrilling => Set<ProcessMapPlanDrilling>();
|
||||||
public virtual DbSet<DrillingProgramPart> DrillingProgramParts => Set<DrillingProgramPart>();
|
public virtual DbSet<DrillingProgramPart> DrillingProgramParts => Set<DrillingProgramPart>();
|
||||||
public virtual DbSet<FileCategory> FileCategories => Set<FileCategory>();
|
public virtual DbSet<FileCategory> FileCategories => Set<FileCategory>();
|
||||||
public virtual DbSet<FileInfo> Files => Set<FileInfo>();
|
public virtual DbSet<FileInfo> Files => Set<FileInfo>();
|
||||||
@ -440,6 +441,16 @@ namespace AsbCloudDb.Model
|
|||||||
.HasIndex(w => new { w.IdWell, w.IdSectionType })
|
.HasIndex(w => new { w.IdWell, w.IdSectionType })
|
||||||
.IsUnique();
|
.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);
|
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.DailyReports.Blocks.TimeBalance;
|
||||||
using AsbCloudDb.Model.WellSections;
|
using AsbCloudDb.Model.WellSections;
|
||||||
using AsbCloudInfrastructure.Services.ProcessMaps;
|
using AsbCloudInfrastructure.Services.ProcessMaps;
|
||||||
|
using AsbCloudApp.Data.ProcessMapPlan;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure
|
namespace AsbCloudInfrastructure
|
||||||
{
|
{
|
||||||
|
|
||||||
public static class DependencyInjection
|
public static class DependencyInjection
|
||||||
{
|
{
|
||||||
public static void MapsterSetup()
|
public static void MapsterSetup()
|
||||||
@ -222,6 +222,8 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddTransient<IHelpPageService, HelpPageService>();
|
services.AddTransient<IHelpPageService, HelpPageService>();
|
||||||
services.AddTransient<IScheduleReportService, ScheduleReportService>();
|
services.AddTransient<IScheduleReportService, ScheduleReportService>();
|
||||||
|
|
||||||
|
services.AddTransient<IProcessMapPlanBaseRepository<ProcessMapPlanDrillingDto>, ProcessMapPlanBaseRepository<ProcessMapPlanDrillingDto, ProcessMapPlanDrilling>>();
|
||||||
|
|
||||||
services.AddTransient<TrajectoryService>();
|
services.AddTransient<TrajectoryService>();
|
||||||
|
|
||||||
services.AddTransient<IGtrRepository, GtrWitsRepository>();
|
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>
|
public abstract class BaseIntegrationTest : IClassFixture<WebAppFactoryFixture>
|
||||||
{
|
{
|
||||||
private readonly IServiceScope scope;
|
protected readonly IServiceScope scope;
|
||||||
private readonly HttpClient httpClient;
|
|
||||||
|
|
||||||
protected readonly IAsbCloudDbContext dbContext;
|
protected readonly IAsbCloudDbContext dbContext;
|
||||||
|
protected readonly WebAppFactoryFixture factory;
|
||||||
|
|
||||||
protected IAdminDepositClient adminDepositClient;
|
protected BaseIntegrationTest(WebAppFactoryFixture factory)
|
||||||
|
|
||||||
protected BaseIntegrationTest(WebAppFactoryFixture factory)
|
|
||||||
{
|
{
|
||||||
scope = factory.Services.CreateScope();
|
scope = factory.Services.CreateScope();
|
||||||
httpClient = factory.CreateClient();
|
|
||||||
|
|
||||||
dbContext = scope.ServiceProvider.GetRequiredService<IAsbCloudDbContext>();
|
dbContext = scope.ServiceProvider.GetRequiredService<IAsbCloudDbContext>();
|
||||||
|
this.factory = factory;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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 System.Net;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudDb.Model.ProcessMaps;
|
||||||
|
using AsbCloudWebApi.IntegrationTests.Clients;
|
||||||
using AsbCloudWebApi.IntegrationTests.TestFakers;
|
using AsbCloudWebApi.IntegrationTests.TestFakers;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -9,19 +12,26 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers;
|
|||||||
|
|
||||||
public class AdminDepositControllerTests : BaseIntegrationTest
|
public class AdminDepositControllerTests : BaseIntegrationTest
|
||||||
{
|
{
|
||||||
public AdminDepositControllerTests(WebAppFactoryFixture factory)
|
protected IAdminDepositClient client;
|
||||||
: base(factory)
|
|
||||||
{
|
public AdminDepositControllerTests(WebAppFactoryFixture factory)
|
||||||
}
|
: base(factory)
|
||||||
|
{
|
||||||
|
client = factory.GetAuthorizedHttpClient<IAdminDepositClient>();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task InsertAsync_ReturnsSuccess_WhenNewItemIsValid()
|
public async Task InsertAsync_ReturnsSuccess_WhenNewItemIsValid()
|
||||||
{
|
{
|
||||||
//arrange
|
//arrange
|
||||||
var expectedDto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
var dbset = dbContext.Set<Deposit>();
|
||||||
|
dbset.RemoveRange(dbset);
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var expectedDto = EntitiesFaker.Deposit.Generate().Adapt<DepositBaseDto>();
|
||||||
|
|
||||||
//act
|
//act
|
||||||
var response = await adminDepositClient.InsertAsync(expectedDto);
|
var response = await client.InsertAsync(expectedDto);
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
@ -37,11 +47,15 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
|||||||
[Fact]
|
[Fact]
|
||||||
public async Task InsertRangeAsync_ReturnsSuccess_WhenAllNewItemsIsValid()
|
public async Task InsertRangeAsync_ReturnsSuccess_WhenAllNewItemsIsValid()
|
||||||
{
|
{
|
||||||
//arrange
|
//arrange
|
||||||
var dto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
var dbset = dbContext.Set<Deposit>();
|
||||||
|
dbset.RemoveRange(dbset);
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
//act
|
var dto = EntitiesFaker.Deposit.Generate().Adapt<DepositBaseDto>();
|
||||||
var responce = await adminDepositClient.InsertRangeAsync(new[] { dto });
|
|
||||||
|
//act
|
||||||
|
var responce = await client.InsertRangeAsync(new[] { dto });
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(HttpStatusCode.OK, responce.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, responce.StatusCode);
|
||||||
@ -58,10 +72,10 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
|||||||
public async Task UpdateAsync_ReturnsBadRequest_WhenUpdatedItemHasInvalidId()
|
public async Task UpdateAsync_ReturnsBadRequest_WhenUpdatedItemHasInvalidId()
|
||||||
{
|
{
|
||||||
//arrange
|
//arrange
|
||||||
var dto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
var dto = EntitiesFaker.Deposit.Generate().Adapt<DepositBaseDto>();
|
||||||
|
|
||||||
//act
|
//act
|
||||||
var response = await adminDepositClient.UpdateAsync(dto);
|
var response = await client.UpdateAsync(dto);
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||||
@ -71,8 +85,8 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
|||||||
public async Task UpdateAsync_ReturnsSuccess_WhenUpdatedItemIsValid()
|
public async Task UpdateAsync_ReturnsSuccess_WhenUpdatedItemIsValid()
|
||||||
{
|
{
|
||||||
//arrange
|
//arrange
|
||||||
var dto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
var dto = EntitiesFaker.Deposit.Generate().Adapt<DepositBaseDto>();
|
||||||
var insertResponse = await adminDepositClient.InsertAsync(dto);
|
var insertResponse = await client.InsertAsync(dto);
|
||||||
|
|
||||||
dto.Id = insertResponse.Content;
|
dto.Id = insertResponse.Content;
|
||||||
dto.Caption = "Test";
|
dto.Caption = "Test";
|
||||||
@ -85,7 +99,7 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
|||||||
};
|
};
|
||||||
|
|
||||||
//act
|
//act
|
||||||
var response = await adminDepositClient.UpdateAsync(dto);
|
var response = await client.UpdateAsync(dto);
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
@ -101,22 +115,17 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
|||||||
public async Task GetOrDefaultAsync_ReturnsSuccess_WhenIdIsValid()
|
public async Task GetOrDefaultAsync_ReturnsSuccess_WhenIdIsValid()
|
||||||
{
|
{
|
||||||
//arrange
|
//arrange
|
||||||
var dto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
var entity = await dbContext.Deposits.FirstAsync();
|
||||||
var insertResponse = await adminDepositClient.InsertAsync(dto);
|
var expected = entity.Adapt<DepositBaseDto>();
|
||||||
var id = insertResponse.Content;
|
|
||||||
|
|
||||||
//act
|
//act
|
||||||
var response = await adminDepositClient.GetOrDefaultAsync(id);
|
var response = await client.GetOrDefaultAsync(entity.Id);
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
Assert.NotNull(response.Content);
|
Assert.NotNull(response.Content);
|
||||||
|
|
||||||
var entity = await dbContext.Deposits.FirstOrDefaultAsync(d => d.Id == response.Content.Id);
|
MatchHelper.Match(expected, response.Content);
|
||||||
var deposit = entity?.Adapt<DepositBaseDto>();
|
|
||||||
|
|
||||||
var excludeProps = new[] { nameof(DepositBaseDto.Id) };
|
|
||||||
MatchHelper.Match(dto, deposit, excludeProps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -126,7 +135,7 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
|||||||
const int id = 0;
|
const int id = 0;
|
||||||
|
|
||||||
//act
|
//act
|
||||||
var responce = await adminDepositClient.GetOrDefaultAsync(id);
|
var responce = await client.GetOrDefaultAsync(id);
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(HttpStatusCode.NoContent, responce.StatusCode);
|
Assert.Equal(HttpStatusCode.NoContent, responce.StatusCode);
|
||||||
@ -136,7 +145,7 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
|||||||
public async Task GetAllAsync_ReturnsSuccess()
|
public async Task GetAllAsync_ReturnsSuccess()
|
||||||
{
|
{
|
||||||
//act
|
//act
|
||||||
var response = await adminDepositClient.GetAllAsync();
|
var response = await client.GetAllAsync();
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
@ -156,12 +165,12 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
|||||||
public async Task DeleteAsync_ReturnsSuccess_WhenIdIsValid()
|
public async Task DeleteAsync_ReturnsSuccess_WhenIdIsValid()
|
||||||
{
|
{
|
||||||
//arrange
|
//arrange
|
||||||
var dto = DepositTestFaker.GetDeposit().Adapt<DepositBaseDto>();
|
var dto = EntitiesFaker.Deposit.Generate().Adapt<DepositBaseDto>();
|
||||||
var insertResponse = await adminDepositClient.InsertAsync(dto);
|
var insertResponse = await client.InsertAsync(dto);
|
||||||
var id = insertResponse.Content;
|
var id = insertResponse.Content;
|
||||||
|
|
||||||
//act
|
//act
|
||||||
var response = await adminDepositClient.DeleteAsync(id);
|
var response = await client.DeleteAsync(id);
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
@ -178,7 +187,7 @@ public class AdminDepositControllerTests : BaseIntegrationTest
|
|||||||
const int id = 0;
|
const int id = 0;
|
||||||
|
|
||||||
//act
|
//act
|
||||||
var response = await adminDepositClient.DeleteAsync(id);
|
var response = await client.DeleteAsync(id);
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
|
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.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using ProtoBuf.Serializers;
|
||||||
|
using Refit;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text.Json;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.IntegrationTests;
|
namespace AsbCloudWebApi.IntegrationTests;
|
||||||
@ -13,12 +17,20 @@ namespace AsbCloudWebApi.IntegrationTests;
|
|||||||
public class WebAppFactoryFixture : WebApplicationFactory<Startup>,
|
public class WebAppFactoryFixture : WebApplicationFactory<Startup>,
|
||||||
IAsyncLifetime
|
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)
|
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||||
{
|
{
|
||||||
var configuration = new ConfigurationBuilder()
|
var configuration = new ConfigurationBuilder()
|
||||||
.AddJsonFile("appsettings.json")
|
.AddJsonFile("appsettings.json")
|
||||||
.Build();
|
.Build();
|
||||||
var connectionString = configuration.GetConnectionString("TestConnection");
|
var connectionString = configuration.GetConnectionString("TestConnection")!;
|
||||||
|
|
||||||
builder.ConfigureServices(services =>
|
builder.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
@ -37,19 +49,41 @@ public class WebAppFactoryFixture : WebApplicationFactory<Startup>,
|
|||||||
using var scope = Services.CreateScope();
|
using var scope = Services.CreateScope();
|
||||||
var scopedServices = scope.ServiceProvider;
|
var scopedServices = scope.ServiceProvider;
|
||||||
var dbContext = scopedServices.GetRequiredService<AsbCloudDbContext>();
|
var dbContext = scopedServices.GetRequiredService<AsbCloudDbContext>();
|
||||||
|
dbContext.Database.EnsureDeleted();
|
||||||
dbContext.Database.EnsureCreatedAndMigrated();
|
dbContext.Database.EnsureCreatedAndMigrated();
|
||||||
|
await FillBaseDatasets(dbContext);
|
||||||
dbContext.Deposits.AddRange(DepositTestFaker.GetDeposits(15));
|
|
||||||
await dbContext.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
using var scope = Services.CreateScope();
|
||||||
var scopedServices = scope.ServiceProvider;
|
var scopedServices = scope.ServiceProvider;
|
||||||
var dbContext = scopedServices.GetRequiredService<AsbCloudDbContext>();
|
var dbContext = scopedServices.GetRequiredService<AsbCloudDbContext>();
|
||||||
|
|
||||||
await dbContext.Database.EnsureDeletedAsync();
|
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