CS2-135. Db model uses DateTimeOffset. see about using DateTime[Offset].md

This commit is contained in:
Фролов 2022-01-05 17:50:45 +05:00
parent 7ffb6d96fd
commit 345ca47f87
100 changed files with 4151 additions and 736 deletions

View File

@ -8,6 +8,7 @@ namespace AsbCloudApp.Data
public string Caption { get; set; }
public double? Latitude { get; set; }
public double? Longitude { get; set; }
public SimpleTimezoneDto Timezone { get; set; }
public int? IdDeposit { get; set; }
public DepositBaseDto Deposit { get; set; }
public IEnumerable<WellDto> Wells { get; set; }

View File

@ -8,6 +8,7 @@ namespace AsbCloudApp.Data
public string Caption { get; set; }
public double? Latitude { get; set; }
public double? Longitude { get; set; }
public SimpleTimezoneDto Timezone { get; set; }
}
public class DepositDto : DepositBaseDto

View File

@ -3,7 +3,7 @@ using System;
namespace AsbCloudApp.Data
{
/// <summary>
/// Параметры корридоров бурения (диапазоны параметров бурения)
/// Параметры коридоров бурения (диапазоны параметров бурения)
/// </summary>
public class DrillFlowChartDto : IId
{

View File

@ -4,5 +4,6 @@
{
double? Latitude { get; set; }
double? Longitude { get; set; }
SimpleTimezoneDto Timezone { get; set; }
}
}

View File

@ -19,7 +19,7 @@ namespace AsbCloudApp.Data
}
/// <summary>
/// Кол-во записей пропущеных с начала таблицы в запросе от api
/// Кол-во записей пропущенных с начала таблицы в запросе от api
/// </summary>
public int Skip { get; set; }

View File

@ -1,16 +1,16 @@
namespace AsbCloudApp.Data
{
public class TelemetryTimeZoneDto
public class SimpleTimezoneDto
{
public double Hours { get; set; }
public string TimeZoneId { get; set; }
public string TimezoneId { get; set; }
public bool IsOverride { get; set; }
public override bool Equals(object obj)
{
if(obj is TelemetryTimeZoneDto tTimeZone
if(obj is SimpleTimezoneDto tTimeZone
&& tTimeZone.Hours == Hours
&& tTimeZone.TimeZoneId == TimeZoneId
&& tTimeZone.TimezoneId == TimezoneId
&& tTimeZone.IsOverride == IsOverride)
return true;
return false;
@ -18,7 +18,7 @@ namespace AsbCloudApp.Data
public override int GetHashCode()
=> Hours.GetHashCode()
| TimeZoneId.GetHashCode()
| TimezoneId.GetHashCode()
| IsOverride.GetHashCode();
}
}

View File

@ -38,7 +38,7 @@ namespace AsbCloudApp.Data
public float? WellDepth { get; set; }
/// <summary>
/// Глубина долта
/// Глубина долота
/// </summary>
public float? BitDepth { get; set; }
@ -83,12 +83,12 @@ namespace AsbCloudApp.Data
public float? BlockSpeedSpDevelop { get; set; }
/// <summary>
/// Давтение
/// Давление
/// </summary>
public float? Pressure { get; set; }
/// <summary>
/// Давтение при холостом ходе.
/// Давление при холостом ходе.
/// </summary>
public float? PressureIdle { get; set; }

View File

@ -8,12 +8,13 @@ namespace AsbCloudApp.Data
public int Id { get; set; }
public double? Latitude { get; set; }
public double? Longitude { get; set; }
public SimpleTimezoneDto Timezone { get; set; }
public string WellType { get; set; }
public int IdWellType { get; set; }
public int? IdCluster { get; set; }
/// <summary>
/// 0 - незвестно,
/// 0 - неизвестно,
/// 1 - в работе,
/// 2 - завершена
/// </summary>

View File

@ -11,10 +11,9 @@ namespace AsbCloudApp.Services
Task<PaginationContainer<MessageDto>> GetMessagesAsync(int idWell,
IEnumerable<int> categoryids = default, DateTime begin = default,
DateTime end = default, string searchString = default,
int skip = 0, int take = 32, bool isUtc = true,
CancellationToken token = default);
Task<DatesRangeDto> GetMessagesDatesRangeAsync(int idWell, bool isUtc,
int skip = 0, int take = 32,
CancellationToken token = default);
Task InsertAsync(string uid, IEnumerable<TelemetryMessageDto> dtos,
CancellationToken token);
}

View File

@ -14,8 +14,7 @@ namespace AsbCloudApp.Services
Action<object, int> handleReportProgress);
int GetReportPagesCount(int idWell, DateTime begin, DateTime end,
int stepSeconds, int format);
Task<DatesRangeDto> GetReportsDatesRangeAsync(int idWell, bool isUtc,
CancellationToken token = default);
Task<List<ReportPropertiesDto>> GetAllReportsByWellAsync(int idWell, CancellationToken token);
DatesRangeDto GetDatesRangeOrDefault(int idWell);
Task<IEnumerable<ReportPropertiesDto>> GetAllReportsByWellAsync(int idWell, CancellationToken token);
}
}

View File

@ -24,7 +24,7 @@ namespace AsbCloudApp.Services
int intervalHoursTimestamp, int workBeginTimestamp,
CancellationToken token = default);
Task AnalyzeAndSaveTelemetriesAsync(CancellationToken token = default);
Task<DatesRangeDto> GetOperationsDateRangeAsync(int idWell, bool isUtc,
Task<DatesRangeDto> GetOperationsDateRangeAsync(int idWell,
CancellationToken token = default);
}
}

View File

@ -10,9 +10,8 @@ namespace AsbCloudApp.Services
{
Task<IEnumerable<TDto>> GetAsync(int idWell,
DateTime dateBegin = default, double intervalSec = 600d,
int approxPointsCount = 1024, bool isUtc = false, CancellationToken token = default);
Task<DatesRangeDto> GetDataDatesRangeAsync(int idWell, bool isUtc = false,
CancellationToken token = default);
int approxPointsCount = 1024, CancellationToken token = default);
Task<int> UpdateDataAsync(string uid, IEnumerable<TDto> dtos, CancellationToken token = default);
}
}

View File

@ -8,22 +8,17 @@ namespace AsbCloudApp.Services
{
public interface ITelemetryService
{
ITimeZoneService TimeZoneService { get; }
ITimezoneService TimeZoneService { get; }
ITelemetryTracker TelemetryTracker { get; }
int? GetIdWellByTelemetryUid(string uid);
int GetOrCreateTelemetryIdByUid(string uid);
double GetTimezoneOffset(int idTelemetry);
Task<double?> GetTimeZoneOffsetAsync(int idTelemetry, CancellationToken token);
SimpleTimezoneDto GetTimezone(int idTelemetry);
IEnumerable<TelemetryDto> GetTransmittingTelemetries();
DateTimeOffset GetLastTelemetryDate(string telemetryUid);
DateTimeOffset GetLastTelemetryDate(int telemetryId);
DateTime GetLastTelemetryDate(int idTelemetry, bool useUtc = false);
int? GetIdTelemetryByIdWell(int idWell);
DatesRangeDto GetDatesRange(int idTelemetry);
Task UpdateInfoAsync(string uid, TelemetryInfoDto info, CancellationToken token);
Task<DatesRangeDto> DatesRangeToTelemetryTimeZoneAsync(int telemetryId, DatesRangeDto result,
CancellationToken token);
Task UpdateTimeZoneAsync(string uid, TelemetryTimeZoneDto telemetryTimeZoneInfo, CancellationToken token);
Task UpdateTimezoneAsync(string uid, SimpleTimezoneDto telemetryTimeZoneInfo, CancellationToken token);
/// <summary>
/// Слить данные телеметрии в одну
@ -32,8 +27,6 @@ namespace AsbCloudApp.Services
/// <param name="to">новая</param>
/// <returns></returns>
Task<int> MergeAsync(int from, int to, CancellationToken token);
void SaveRequestDate(string uid, DateTimeOffset remoteDate);
Task<DatesRangeDto> GetDatesRangeAsync(int idWell, bool isUtc, CancellationToken token = default);
}
}

View File

@ -1,11 +1,13 @@
using System;
using AsbCloudApp.Data;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services
{
public interface ITimeZoneService
public interface ITimezoneService
{
Task<Data.TelemetryTimeZoneDto> GetByCoordinatesAsync(double latitude, double longitude, CancellationToken token);
SimpleTimezoneDto GetByCoordinates(double latitude, double longitude);
Task<Data.SimpleTimezoneDto> GetByCoordinatesAsync(double latitude, double longitude, CancellationToken token);
}
}

View File

@ -19,6 +19,8 @@ namespace AsbCloudApp.Services
string GetStateText(int state);
DateTimeOffset GetLastTelemetryDate(int idWell);
Task<IEnumerable<int>> GetClusterWellsIdsAsync(int idWell, CancellationToken token);
double? GetTimeZoneOffset(int idWell);
SimpleTimezoneDto GetTimezone(int idWell);
DatesRangeDto GetDatesRange(int idWell);
void EnshureTimezonesIsSet();
}
}

View File

@ -125,6 +125,7 @@ namespace AsbCloudDb
{
string vStr => $"'{vStr}'",
DateTime vDate => $"'{FormatDateValue(vDate)}'",
DateTimeOffset vDate => $"'{FormatDateValue(vDate.UtcDateTime)}'",
IFormattable vFormattable=> FormatFormattableValue(vFormattable),
_ => System.Text.Json.JsonSerializer.Serialize(v),
};

View File

@ -770,7 +770,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -7,7 +7,7 @@ namespace AsbCloudDb.Migrations
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<SimpleTimeZone>(
migrationBuilder.AddColumn<SimpleTimezone>(
name: "timezone",
table: "t_telemetry",
type: "jsonb",

View File

@ -853,7 +853,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -824,7 +824,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -854,7 +854,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -854,7 +854,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -854,7 +854,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -854,7 +854,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -824,7 +824,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -908,7 +908,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -908,7 +908,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -908,7 +908,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -899,7 +899,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -902,7 +902,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -893,7 +893,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -893,7 +893,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -893,7 +893,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -896,7 +896,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TelemetryTimeZone")
b.Property<SimpleTimezone>("TelemetryTimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -54,7 +54,7 @@ namespace AsbCloudDb.Migrations
.HasColumnType("double precision")
.HasColumnName("longitude");
b.Property<SimpleTimeZone>("TimeZone")
b.Property<SimpleTimezone>("TimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");
@ -161,7 +161,7 @@ namespace AsbCloudDb.Migrations
.HasColumnType("double precision")
.HasColumnName("longitude");
b.Property<SimpleTimeZone>("TimeZone")
b.Property<SimpleTimezone>("TimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");
@ -906,7 +906,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TimeZone")
b.Property<SimpleTimezone>("TimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");
@ -1836,7 +1836,7 @@ namespace AsbCloudDb.Migrations
.HasColumnType("double precision")
.HasColumnName("longitude");
b.Property<SimpleTimeZone>("TimeZone")
b.Property<SimpleTimezone>("TimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -9,21 +9,21 @@ namespace AsbCloudDb.Migrations
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<SimpleTimeZone>(
migrationBuilder.AddColumn<SimpleTimezone>(
name: "timezone",
table: "t_well",
type: "jsonb",
nullable: true,
comment: "Смещение часового пояса от UTC");
migrationBuilder.AddColumn<SimpleTimeZone>(
migrationBuilder.AddColumn<SimpleTimezone>(
name: "timezone",
table: "t_deposit",
type: "jsonb",
nullable: true,
comment: "Смещение часового пояса от UTC");
migrationBuilder.AddColumn<SimpleTimeZone>(
migrationBuilder.AddColumn<SimpleTimezone>(
name: "timezone",
table: "t_cluster",
type: "jsonb",

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AsbCloudDb.Migrations
{
public partial class Fix_Spelling : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterTable(
name: "t_drill_flow_chart",
comment: "Параметры коридоров бурения (диапазоны параметров бурения)",
oldComment: "Параметры корридоров бурения (диапазоны параметров бурения)");
migrationBuilder.AlterColumn<float>(
name: "torque_starting",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: "Страгивающий момент",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: " Страгивающий момент");
migrationBuilder.AlterColumn<float>(
name: "rotor_torque_avg",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: "Момент в роторе средний",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: " Момент в роторе средний");
migrationBuilder.AlterColumn<float>(
name: "ratio",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: " Коэффициент редукции редуктора",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: " Коэффициент редукции редектора");
migrationBuilder.AlterColumn<float>(
name: "position_zero",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: "Нулевая позиция осцилляции",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: "Нулевая позиция осциляции");
migrationBuilder.AlterColumn<float>(
name: "position_right",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: "Крайний правый угол осцилляции",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: "Крайний правый угол осциляции");
migrationBuilder.AlterColumn<float>(
name: "encoder_resolution",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: "Разрешение энкодера",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: " Разрешение энкодера");
migrationBuilder.AlterColumn<bool>(
name: "is_pressure_gt_20",
table: "t_telemetry_analysis",
type: "boolean",
nullable: false,
comment: "Давление более 20",
oldClrType: typeof(bool),
oldType: "boolean",
oldComment: "Давоение более 20");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterTable(
name: "t_drill_flow_chart",
comment: "Параметры корридоров бурения (диапазоны параметров бурения)",
oldComment: "Параметры коридоров бурения (диапазоны параметров бурения)");
migrationBuilder.AlterColumn<float>(
name: "torque_starting",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: " Страгивающий момент",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: "Страгивающий момент");
migrationBuilder.AlterColumn<float>(
name: "rotor_torque_avg",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: " Момент в роторе средний",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: "Момент в роторе средний");
migrationBuilder.AlterColumn<float>(
name: "ratio",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: " Коэффициент редукции редектора",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: " Коэффициент редукции редуктора");
migrationBuilder.AlterColumn<float>(
name: "position_zero",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: "Нулевая позиция осциляции",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: "Нулевая позиция осцилляции");
migrationBuilder.AlterColumn<float>(
name: "position_right",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: "Крайний правый угол осциляции",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: "Крайний правый угол осцилляции");
migrationBuilder.AlterColumn<float>(
name: "encoder_resolution",
table: "t_telemetry_data_spin",
type: "real",
nullable: true,
comment: " Разрешение энкодера",
oldClrType: typeof(float),
oldType: "real",
oldNullable: true,
oldComment: "Разрешение энкодера");
migrationBuilder.AlterColumn<bool>(
name: "is_pressure_gt_20",
table: "t_telemetry_analysis",
type: "boolean",
nullable: false,
comment: "Давоение более 20",
oldClrType: typeof(bool),
oldType: "boolean",
oldComment: "Давление более 20");
}
}
}

View File

@ -52,7 +52,7 @@ namespace AsbCloudDb.Migrations
.HasColumnType("double precision")
.HasColumnName("longitude");
b.Property<SimpleTimeZone>("TimeZone")
b.Property<SimpleTimezone>("Timezone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");
@ -159,7 +159,7 @@ namespace AsbCloudDb.Migrations
.HasColumnType("double precision")
.HasColumnName("longitude");
b.Property<SimpleTimeZone>("TimeZone")
b.Property<SimpleTimezone>("Timezone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");
@ -263,7 +263,7 @@ namespace AsbCloudDb.Migrations
b.ToTable("t_drill_flow_chart");
b.HasComment("Параметры корридоров бурения (диапазоны параметров бурения)");
b.HasComment("Параметры коридоров бурения (диапазоны параметров бурения)");
});
modelBuilder.Entity("AsbCloudDb.Model.DrillParams", b =>
@ -904,7 +904,7 @@ namespace AsbCloudDb.Migrations
.HasColumnName("remote_uid")
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
b.Property<SimpleTimeZone>("TimeZone")
b.Property<SimpleTimezone>("TimeZone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");
@ -978,7 +978,7 @@ namespace AsbCloudDb.Migrations
b.Property<bool>("IsPressureGt20")
.HasColumnType("boolean")
.HasColumnName("is_pressure_gt_20")
.HasComment("Давоение более 20");
.HasComment("Давление более 20");
b.Property<bool>("IsPressureLt20")
.HasColumnType("boolean")
@ -1253,7 +1253,7 @@ namespace AsbCloudDb.Migrations
b.Property<float?>("EncoderResolution")
.HasColumnType("real")
.HasColumnName("encoder_resolution")
.HasComment(" Разрешение энкодера");
.HasComment("Разрешение энкодера");
b.Property<short?>("Mode")
.HasColumnType("smallint")
@ -1268,17 +1268,17 @@ namespace AsbCloudDb.Migrations
b.Property<float?>("PositionRight")
.HasColumnType("real")
.HasColumnName("position_right")
.HasComment("Крайний правый угол осциляции");
.HasComment("Крайний правый угол осцилляции");
b.Property<float?>("PositionZero")
.HasColumnType("real")
.HasColumnName("position_zero")
.HasComment("Нулевая позиция осциляции");
.HasComment("Нулевая позиция осцилляции");
b.Property<float?>("Ratio")
.HasColumnType("real")
.HasColumnName("ratio")
.HasComment(" Коэффициент редукции редектора");
.HasComment(" Коэффициент редукции редуктора");
b.Property<float?>("ReverseKTorque")
.HasColumnType("real")
@ -1313,7 +1313,7 @@ namespace AsbCloudDb.Migrations
b.Property<float?>("RotorTorqueAvg")
.HasColumnType("real")
.HasColumnName("rotor_torque_avg")
.HasComment(" Момент в роторе средний");
.HasComment("Момент в роторе средний");
b.Property<float?>("SpeedLeftSp")
.HasColumnType("real")
@ -1477,7 +1477,7 @@ namespace AsbCloudDb.Migrations
b.Property<float?>("TorqueStarting")
.HasColumnType("real")
.HasColumnName("torque_starting")
.HasComment(" Страгивающий момент");
.HasComment("Страгивающий момент");
b.Property<float?>("TurnLeftOnceByAngle")
.HasColumnType("real")
@ -1834,7 +1834,7 @@ namespace AsbCloudDb.Migrations
.HasColumnType("double precision")
.HasColumnName("longitude");
b.Property<SimpleTimeZone>("TimeZone")
b.Property<SimpleTimezone>("Timezone")
.HasColumnType("jsonb")
.HasColumnName("timezone")
.HasComment("Смещение часового пояса от UTC");

View File

@ -40,6 +40,6 @@ namespace AsbCloudDb.Model
public double? Longitude { get; set; }
[Column("timezone", TypeName = "jsonb"), Comment("Смещение часового пояса от UTC")]
public SimpleTimeZone TimeZone { get; set; }
public SimpleTimezone Timezone { get; set; }
}
}

View File

@ -33,6 +33,6 @@ namespace AsbCloudDb.Model
public double? Longitude { get; set; }
[Column("timezone", TypeName = "jsonb"), Comment("Смещение часового пояса от UTC")]
public SimpleTimeZone TimeZone { get; set; }
public SimpleTimezone Timezone { get; set; }
}
}

View File

@ -6,7 +6,7 @@ using System.Text.Json.Serialization;
namespace AsbCloudDb.Model
{
[Table("t_drill_flow_chart"), Comment("Параметры корридоров бурения (диапазоны параметров бурения)")]
[Table("t_drill_flow_chart"), Comment("Параметры коридоров бурения (диапазоны параметров бурения)")]
public class DrillFlowChart : IId
{
[Key]

View File

@ -6,6 +6,6 @@
double? Longitude { get; set; }
SimpleTimeZone TimeZone { get; set; }
SimpleTimezone Timezone { get; set; }
}
}

View File

@ -1,6 +1,6 @@
namespace AsbCloudDb.Model
{
public class SimpleTimeZone
public class SimpleTimezone
{
public double Hours { get; set; }
public string TimeZoneId { get; set; }

View File

@ -28,7 +28,7 @@ namespace AsbCloudDb.Model
public TelemetryInfo Info { get; set; }
[Column("timezone", TypeName = "jsonb"), Comment("Смещение часового пояса от UTC")]
public SimpleTimeZone TimeZone { get; set; }
public SimpleTimezone TimeZone { get; set; }
[InverseProperty(nameof(Model.Well.Telemetry))]
public virtual Well Well { get; set; }

View File

@ -71,7 +71,7 @@ namespace AsbCloudDb.Model
[Column("is_pressure_lt_20"), Comment("Давление менее 20")]
public bool IsPressureLt20 { get; set; }
[Column("is_pressure_gt_20"), Comment("Давоение более 20")]
[Column("is_pressure_gt_20"), Comment("Давление более 20")]
public bool IsPressureGt20 { get; set; }
[Column("is_hook_weight_not_changes"), Comment("Вес на крюке не меняется")]

View File

@ -62,13 +62,13 @@ namespace AsbCloudDb.Model
public float? TopDriveTorqueSpToMax { get; set; }
[Column("top_drive_torque_sp_to_offset")]
public float? TopDriveTorqueSpToOffset { get; set; }
[Column("torque_starting"), Comment(" Страгивающий момент")]
[Column("torque_starting"), Comment("Страгивающий момент")]
public float? TorqueStarting { get; set; }
[Column("rotor_torque_avg"), Comment(" Момент в роторе средний")]
[Column("rotor_torque_avg"), Comment("Момент в роторе средний")]
public float? RotorTorqueAvg { get; set; }
[Column("encoder_resolution"), Comment(" Разрешение энкодера")]
[Column("encoder_resolution"), Comment("Разрешение энкодера")]
public float? EncoderResolution { get; set; }
[Column("ratio"), Comment(" Коэффициент редукции редектора")]
[Column("ratio"), Comment(" Коэффициент редукции редуктора")]
public float? Ratio { get; set; }
[Column("torque_right_limit"), Comment("Ограничение крутящего момента вправо")]
public float? TorqueRightLimit { get; set; }
@ -102,9 +102,9 @@ namespace AsbCloudDb.Model
public float? BreakAngleK { get; set; }
[Column("reverse_k_torque"), Comment("Коэффициент на который умножается момент, для того чтобы система поняла что мы движемся в обратную сторону")]
public float? ReverseKTorque { get; set; }
[Column("position_zero"), Comment("Нулевая позиция осциляции")]
[Column("position_zero"), Comment("Нулевая позиция осцилляции")]
public float? PositionZero { get; set; }
[Column("position_right"), Comment("Крайний правый угол осциляции")]
[Column("position_right"), Comment("Крайний правый угол осцилляции")]
public float? PositionRight { get; set; }
[Column("torque_ramp_time"), Comment("Время нарастания момента")]
public float? TorqueRampTime { get; set; }

View File

@ -38,7 +38,7 @@ namespace AsbCloudDb.Model
public double? Longitude { get; set; }
[Column("timezone", TypeName = "jsonb"), Comment("Смещение часового пояса от UTC")]
public SimpleTimeZone TimeZone { get; set; }
public SimpleTimezone Timezone { get; set; }
[ForeignKey(nameof(IdWellType))]
[InverseProperty(nameof(Model.WellType.Wells))]

View File

@ -17,10 +17,10 @@ dotnet ef migrations add <MigrationName> --project AsbCloudDb
```
## Откатить миграцию
```
dotnet ef migrations remvoe <MigrationName> --project AsbCloudDb
dotnet ef migrations remove <MigrationName> --project AsbCloudDb
```
\<MigrationName> - Name of migration class.
После создания миграции обязательно прочитать сгенерированый код.
После создания миграции обязательно прочитать генерированный код.
## Применить миграции
При старте проекта применяются автоматически
@ -45,7 +45,7 @@ CREATE DATABASE postgres;
create schema public;
```
### Step 2. Innit timescaledb and prepare DB to restore
### Step 2. Init timescaledb and prepare DB to restore
```
CREATE EXTENSION IF NOT EXISTS timescaledb;
SELECT timescaledb_pre_restore();
@ -60,7 +60,7 @@ OR psql:
```
\! pg_restore -Fc -d postgres dump_2021-11-26.bak
```
Then 'exit resore mode' psql:
Then 'exit restore mode' psql:
```
SELECT timescaledb_post_restore();
```

View File

@ -1,11 +1,11 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v5.0",
"name": ".NETCoreApp,Version=v6.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v5.0": {
".NETCoreApp,Version=v6.0": {
"AsbSaubReport/1.0.0": {
"runtime": {
"AsbSaubReport.dll": {}

View File

@ -1,11 +1,11 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v5.0",
"name": ".NETCoreApp,Version=v6.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v5.0": {
".NETCoreApp,Version=v6.0": {
"AsbSaubReportLas/1.0.0": {
"dependencies": {
"AsbSaubReport": "1.0.0"

View File

@ -1,53 +1,25 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v5.0",
"name": ".NETCoreApp,Version=v6.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v5.0": {
".NETCoreApp,Version=v6.0": {
"AsbSaubReportPdf/1.0.0": {
"dependencies": {
"AsbSaubReport": "1.0.0",
"itext7": "7.1.15"
"itext7": "7.2.0"
},
"runtime": {
"AsbSaubReportPdf.dll": {}
}
},
"Common.Logging/3.4.1": {
"itext7/7.2.0": {
"dependencies": {
"Common.Logging.Core": "3.4.1",
"Microsoft.CSharp": "4.0.1",
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Globalization": "4.3.0",
"System.Reflection.TypeExtensions": "4.1.0",
"System.Runtime.Extensions": "4.3.0",
"System.Threading": "4.3.0"
},
"runtime": {
"lib/netstandard1.3/Common.Logging.dll": {
"assemblyVersion": "3.4.1.0",
"fileVersion": "3.4.0.0"
}
}
},
"Common.Logging.Core/3.4.1": {
"dependencies": {
"Microsoft.CSharp": "4.0.1"
},
"runtime": {
"lib/netstandard1.0/Common.Logging.Core.dll": {
"assemblyVersion": "3.4.1.0",
"fileVersion": "3.4.0.0"
}
}
},
"itext7/7.1.15": {
"dependencies": {
"Common.Logging": "3.4.1",
"Microsoft.DotNet.PlatformAbstractions": "1.1.0",
"Microsoft.Extensions.DependencyModel": "1.1.0",
"Microsoft.Extensions.Logging": "5.0.0",
"Portable.BouncyCastle": "1.8.9",
"System.Collections.NonGeneric": "4.3.0",
"System.Diagnostics.Process": "4.3.0",
@ -58,44 +30,56 @@
"System.Text.Encoding.CodePages": "4.3.0",
"System.Threading.Thread": "4.3.0",
"System.Threading.ThreadPool": "4.3.0",
"System.Xml.XmlDocument": "4.3.0"
"System.Xml.XmlDocument": "4.3.0",
"itext7.commons": "7.2.0"
},
"runtime": {
"lib/netstandard2.0/itext.barcodes.dll": {
"assemblyVersion": "7.1.15.0",
"fileVersion": "7.1.15.0"
"assemblyVersion": "7.2.0.0",
"fileVersion": "7.2.0.0"
},
"lib/netstandard2.0/itext.forms.dll": {
"assemblyVersion": "7.1.15.0",
"fileVersion": "7.1.15.0"
"assemblyVersion": "7.2.0.0",
"fileVersion": "7.2.0.0"
},
"lib/netstandard2.0/itext.io.dll": {
"assemblyVersion": "7.1.15.0",
"fileVersion": "7.1.15.0"
"assemblyVersion": "7.2.0.0",
"fileVersion": "7.2.0.0"
},
"lib/netstandard2.0/itext.kernel.dll": {
"assemblyVersion": "7.1.15.0",
"fileVersion": "7.1.15.0"
"assemblyVersion": "7.2.0.0",
"fileVersion": "7.2.0.0"
},
"lib/netstandard2.0/itext.layout.dll": {
"assemblyVersion": "7.1.15.0",
"fileVersion": "7.1.15.0"
"assemblyVersion": "7.2.0.0",
"fileVersion": "7.2.0.0"
},
"lib/netstandard2.0/itext.pdfa.dll": {
"assemblyVersion": "7.1.15.0",
"fileVersion": "7.1.15.0"
"assemblyVersion": "7.2.0.0",
"fileVersion": "7.2.0.0"
},
"lib/netstandard2.0/itext.sign.dll": {
"assemblyVersion": "7.1.15.0",
"fileVersion": "7.1.15.0"
"assemblyVersion": "7.2.0.0",
"fileVersion": "7.2.0.0"
},
"lib/netstandard2.0/itext.styledxmlparser.dll": {
"assemblyVersion": "7.1.15.0",
"fileVersion": "7.1.15.0"
"assemblyVersion": "7.2.0.0",
"fileVersion": "7.2.0.0"
},
"lib/netstandard2.0/itext.svg.dll": {
"assemblyVersion": "7.1.15.0",
"fileVersion": "7.1.15.0"
"assemblyVersion": "7.2.0.0",
"fileVersion": "7.2.0.0"
}
}
},
"itext7.commons/7.2.0": {
"dependencies": {
"Microsoft.Extensions.Logging": "5.0.0"
},
"runtime": {
"lib/netstandard2.0/itext.commons.dll": {
"assemblyVersion": "7.2.0.0",
"fileVersion": "7.2.0.0"
}
}
},
@ -137,6 +121,25 @@
}
}
},
"Microsoft.Extensions.DependencyInjection/5.0.0": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0"
},
"runtime": {
"lib/net5.0/Microsoft.Extensions.DependencyInjection.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Microsoft.Extensions.DependencyModel/1.1.0": {
"dependencies": {
"Microsoft.DotNet.PlatformAbstractions": "1.1.0",
@ -152,6 +155,48 @@
}
}
},
"Microsoft.Extensions.Logging/5.0.0": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "5.0.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0",
"Microsoft.Extensions.Logging.Abstractions": "5.0.0",
"Microsoft.Extensions.Options": "5.0.0"
},
"runtime": {
"lib/netstandard2.1/Microsoft.Extensions.Logging.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/5.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Microsoft.Extensions.Options/5.0.0": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0",
"Microsoft.Extensions.Primitives": "5.0.0"
},
"runtime": {
"lib/net5.0/Microsoft.Extensions.Options.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Microsoft.Extensions.Primitives/5.0.0": {
"runtime": {
"lib/netcoreapp3.0/Microsoft.Extensions.Primitives.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.20.51904"
}
}
},
"Microsoft.NETCore.Platforms/1.1.0": {},
"Microsoft.NETCore.Targets/1.1.0": {},
"Microsoft.Win32.Primitives/4.3.0": {
@ -757,26 +802,19 @@
"serviceable": false,
"sha512": ""
},
"Common.Logging/3.4.1": {
"itext7/7.2.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-5eZ/vgEOqzLg4PypZqnJ+wMhhgHyckicbZY4iDxqQ4FtOz0CpdYZ0xQ78aszMzeAJZiLLb5VdR9tPfunVQLz6g==",
"path": "common.logging/3.4.1",
"hashPath": "common.logging.3.4.1.nupkg.sha512"
"sha512": "sha512-1MkQiUY0pCevnKWrY/le7BiW/oV/9CLwB2jGD6xfs0tepE5eU5BTSlabgYq7oWZP8OB7KXoGySMqP+Ugj6MeOA==",
"path": "itext7/7.2.0",
"hashPath": "itext7.7.2.0.nupkg.sha512"
},
"Common.Logging.Core/3.4.1": {
"itext7.commons/7.2.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-wLHldZHvxsSD6Ahonfj00/SkfHfKqO+YT6jsUwVm8Rch1REL9IArHAcSLXxYxYfu5/4ydGtmXvOtaH3AkVPu0A==",
"path": "common.logging.core/3.4.1",
"hashPath": "common.logging.core.3.4.1.nupkg.sha512"
},
"itext7/7.1.15": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BJKdScf6C7LlHB5pV5fr0qHGbrPLX1yl+1R1qHroRZxtyTVFMeZ9gPV6IOsmgTRLr2ee9hUXHbb8/ZqKB4pqiA==",
"path": "itext7/7.1.15",
"hashPath": "itext7.7.1.15.nupkg.sha512"
"sha512": "sha512-bfysIirFpBOTc/mSfElJMOy9D/I2LTLeL0uae7xNgV4Vv7P2HF2n2/CJRTe9iZFsL3r8JdH0hd+eusnt0BjA8w==",
"path": "itext7.commons/7.2.0",
"hashPath": "itext7.commons.7.2.0.nupkg.sha512"
},
"Microsoft.CSharp/4.0.1": {
"type": "package",
@ -792,6 +830,20 @@
"path": "microsoft.dotnet.platformabstractions/1.1.0",
"hashPath": "microsoft.dotnet.platformabstractions.1.1.0.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Rc2kb/p3Ze6cP6rhFC3PJRdWGbLvSHZc0ev7YlyeU6FmHciDMLrhoVoTUEzKPhN5ZjFgKF1Cf5fOz8mCMIkvpA==",
"path": "microsoft.extensions.dependencyinjection/5.0.0",
"hashPath": "microsoft.extensions.dependencyinjection.5.0.0.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ORj7Zh81gC69TyvmcUm9tSzytcy8AVousi+IVRAI8nLieQjOFryRusSFh7+aLk16FN9pQNqJAiMd7BTKINK0kA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512"
},
"Microsoft.Extensions.DependencyModel/1.1.0": {
"type": "package",
"serviceable": true,
@ -799,6 +851,34 @@
"path": "microsoft.extensions.dependencymodel/1.1.0",
"hashPath": "microsoft.extensions.dependencymodel.1.1.0.nupkg.sha512"
},
"Microsoft.Extensions.Logging/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-MgOwK6tPzB6YNH21wssJcw/2MKwee8b2gI7SllYfn6rvTpIrVvVS5HAjSU2vqSku1fwqRvWP0MdIi14qjd93Aw==",
"path": "microsoft.extensions.logging/5.0.0",
"hashPath": "microsoft.extensions.logging.5.0.0.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NxP6ahFcBnnSfwNBi2KH2Oz8Xl5Sm2krjId/jRR3I7teFphwiUoUeZPwTNA21EX+5PtjqmyAvKaOeBXcJjcH/w==",
"path": "microsoft.extensions.logging.abstractions/5.0.0",
"hashPath": "microsoft.extensions.logging.abstractions.5.0.0.nupkg.sha512"
},
"Microsoft.Extensions.Options/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-CBvR92TCJ5uBIdd9/HzDSrxYak+0W/3+yxrNg8Qm6Bmrkh5L+nu6m3WeazQehcZ5q1/6dDA7J5YdQjim0165zg==",
"path": "microsoft.extensions.options/5.0.0",
"hashPath": "microsoft.extensions.options.5.0.0.nupkg.sha512"
},
"Microsoft.Extensions.Primitives/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-cI/VWn9G1fghXrNDagX9nYaaB/nokkZn0HYAawGaELQrl8InSezfe9OnfPZLcJq3esXxygh3hkq2c3qoV3SDyQ==",
"path": "microsoft.extensions.primitives/5.0.0",
"hashPath": "microsoft.extensions.primitives.5.0.0.nupkg.sha512"
},
"Microsoft.NETCore.Platforms/1.1.0": {
"type": "package",
"serviceable": true,
@ -830,7 +910,7 @@
"Newtonsoft.Json/9.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-U82mHQSKaIk+lpSVCbWYKNavmNH1i5xrExDEquU1i6I5pV6UMOqRnJRSlKO3cMPfcpp0RgDY+8jUXHdQ4IfXvw==",
"sha512": "sha512-2okXpTRwUcgQb06put5LwwCjtgoFo74zkPksjcvOpnIjx7TagGW5IoBCAA4luZx1+tfiIhoNqoiI7Y7zwWGyKA==",
"path": "newtonsoft.json/9.0.1",
"hashPath": "newtonsoft.json.9.0.1.nupkg.sha512"
},
@ -1145,7 +1225,7 @@
"System.Runtime.InteropServices.RuntimeInformation/4.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-hWPhJxc453RCa8Z29O91EmfGeZIHX1ZH2A8L6lYQVSaKzku2DfArSfMEb1/MYYzPQRJZeu0c9dmYeJKxW5Fgng==",
"sha512": "sha512-Ri015my90h3AB/BsbvEpq1foEPoPBBa9L8b7fu1VE4eA1NMeMe5iZ6guLjoWB+XGQr1u/rEwtXobqofjFBsAgA==",
"path": "system.runtime.interopservices.runtimeinformation/4.0.0",
"hashPath": "system.runtime.interopservices.runtimeinformation.4.0.0.nupkg.sha512"
},

View File

@ -12,10 +12,10 @@ namespace AsbCloudInfrastructure
var dateUtc = date.Kind switch
{
DateTimeKind.Local => date.ToUniversalTime(),
DateTimeKind.Unspecified => date.AddHours(-remoteTimezoneOffsetHours),
DateTimeKind.Unspecified => DateTime.SpecifyKind(date.AddHours(-remoteTimezoneOffsetHours), DateTimeKind.Utc),
_ => date,
};
return new DateTimeOffset(dateUtc);
return new DateTimeOffset( dateUtc);
}
public static DateTime ToRemoteDateTime(this DateTimeOffset date, double remoteTimezoneOffsetHours)

View File

@ -5,6 +5,7 @@ using AsbCloudInfrastructure.Services;
using AsbCloudInfrastructure.Services.Analysis;
using AsbCloudInfrastructure.Services.Cache;
using AsbCloudInfrastructure.Services.WellOperationService;
using Mapster;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -25,6 +26,13 @@ namespace AsbCloudInfrastructure
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
{
TypeAdapterConfig.GlobalSettings.Default.Config
.ForType<DateTimeOffset, DateTime>()
.MapWith((source) => source.DateTime);
TypeAdapterConfig.GlobalSettings.Default.Config
.ForType<DateTime, DateTimeOffset>()
.MapWith((source) => source == default ? new DateTime(0,DateTimeKind.Utc) : source );
services.AddDbContext<AsbCloudDbContext>(options =>
options.UseNpgsql(configuration.GetConnectionString("DefaultConnection")));
@ -54,7 +62,7 @@ namespace AsbCloudInfrastructure
services.AddTransient<ITelemetryAnalyticsService, TelemetryAnalyticsService>();
services.AddTransient<ITelemetryService, TelemetryService>();
services.AddTransient<ITelemetryUserService, TelemetryUserService>();
services.AddTransient<ITimeZoneService, TimeZoneService>();
services.AddTransient<ITimezoneService, TimezoneService>();
services.AddTransient<IUserService, UserService>();
services.AddTransient<IUserRoleService, UserRoleService>();
services.AddTransient<IWellService, WellService>();

View File

@ -16,6 +16,7 @@ namespace AsbCloudInfrastructure
private readonly Dictionary<int, TelemetryEvent> events;
private readonly Dictionary<int, TelemetryUser> users;
private readonly double timezoneOffset;
private readonly Dictionary<int, string> categories = new Dictionary<int, string>
{
{1, "Авария"},
@ -26,6 +27,7 @@ namespace AsbCloudInfrastructure
public ReportDataSourcePgCloud(AsbCloudDbContext context, int idWell)
{
this.context = context;
var well = context.Wells
.Include(w => w.Cluster)
.ThenInclude(c => c.Deposit)
@ -46,15 +48,17 @@ namespace AsbCloudInfrastructure
.Where(u => u.IdTelemetry == idTelemetry)
.ToDictionary(u => u.IdUser, u => u);
timezoneOffset = well?.Telemetry?.Info?.TimeZoneOffsetTotalHours ?? well.Timezone?.Hours ?? 5.0;
info = new WellInfoReport
{
Deposit = well?.Cluster?.Deposit?.Caption,
Cluster = well?.Cluster?.Caption,
Well = well?.Caption,
Customer = well?.RelationCompaniesWells.FirstOrDefault(c => c.Company.IdCompanyType == 1)?.Company.Caption,
DrillingStartDate = well?.Telemetry?.Info?.DrillingStartDate ?? default,
TimeZoneId = well?.Telemetry?.Info?.TimeZoneId ?? default,
TimeZoneOffsetTotalHours = well?.Telemetry?.Info?.TimeZoneOffsetTotalHours ?? default,
Deposit = well.Cluster?.Deposit?.Caption,
Cluster = well.Cluster?.Caption,
Well = well.Caption,
Customer = well.RelationCompaniesWells.FirstOrDefault(c => c.Company.IdCompanyType == 1)?.Company.Caption,
DrillingStartDate = well.Telemetry?.Info?.DrillingStartDate.ToRemoteDateTime(timezoneOffset) ?? default,
TimeZoneId = well.Telemetry?.Info?.TimeZoneId ?? well.Timezone?.TimeZoneId ?? default,
TimeZoneOffsetTotalHours = timezoneOffset,
};
}
@ -74,8 +78,8 @@ namespace AsbCloudInfrastructure
var result = new AnalyzeResult
{
MinDate = dataStat?.min.DateTime ?? messagesStat?.min.DateTime ?? default,
MaxDate = dataStat?.max.DateTime ?? messagesStat?.max.DateTime ?? default,
MinDate = dataStat?.min.UtcDateTime ?? messagesStat?.min.UtcDateTime ?? default,
MaxDate = dataStat?.max.UtcDateTime ?? messagesStat?.max.UtcDateTime ?? default,
MessagesCount = messagesStat?.count ?? 0,
};
@ -83,57 +87,67 @@ namespace AsbCloudInfrastructure
}
public IQueryable<DataSaubReport> GetDataSaubItems(DateTime begin, DateTime end)
=> from item in context.TelemetryDataSaub
where item.IdTelemetry == idTelemetry
&& item.Date >= begin
&& item.Date <= end
orderby item.Date
select new DataSaubReport
{
//Id = item.Id,
Date = item.Date.DateTime,
Mode = item.Mode,
WellDepth = item.WellDepth,
BitDepth = item.BitDepth,
BlockPosition = item.BlockPosition,
BlockSpeed = item.BlockSpeed,
BlockSpeedSp = item.BlockSpeedSp,
BlockSpeedSpDevelop = item.BlockSpeedSpDevelop,
Pressure = item.Pressure,
PressureSp = item.PressureSp,
AxialLoad = item.AxialLoad,
AxialLoadSp = item.AxialLoadSp,
AxialLoadLimitMax = item.AxialLoadLimitMax,
HookWeight = item.HookWeight,
RotorTorque = item.RotorTorque,
RotorTorqueSp = item.RotorTorqueSp,
RotorSpeed = item.RotorSpeed,
Flow = item.Flow,
PressureSpDevelop = item.PressureSpDevelop,
};
{
var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset);
var endUtc = end.ToUtcDateTimeOffset(timezoneOffset);
var query = context.TelemetryDataSaub
.Where(d => d.IdTelemetry == idTelemetry
&& d.Date >= beginUtc
&& d.Date <= endUtc)
.OrderBy(d => d.Date)
.Select(d => new DataSaubReport {
Date = d.Date.DateTime.AddHours(timezoneOffset),
Mode = d.Mode,
WellDepth = d.WellDepth,
BitDepth = d.BitDepth,
BlockPosition = d.BlockPosition,
BlockSpeed = d.BlockSpeed,
BlockSpeedSp = d.BlockSpeedSp,
BlockSpeedSpDevelop = d.BlockSpeedSpDevelop,
Pressure = d.Pressure,
PressureSp = d.PressureSp,
AxialLoad = d.AxialLoad,
AxialLoadSp = d.AxialLoadSp,
AxialLoadLimitMax = d.AxialLoadLimitMax,
HookWeight = d.HookWeight,
RotorTorque = d.RotorTorque,
RotorTorqueSp = d.RotorTorqueSp,
RotorSpeed = d.RotorSpeed,
Flow = d.Flow,
PressureSpDevelop = d.PressureSpDevelop,
});
return query;
}
public IQueryable<MessageReport> GetMessages(DateTime begin, DateTime end)
=> from item in context.TelemetryMessages
where item.IdTelemetry == idTelemetry
&& item.Date >= begin
&& item.Date <= end
orderby item.Date
select new MessageReport
{
Id = item.Id,
Date = item.Date.DateTime,
Category = events.GetValueOrDefault(item.IdEvent) == null
? $""
: categories[events[item.IdEvent].IdCategory],
User = item.IdTelemetryUser == null
? ""
: users.GetValueOrDefault((int)item.IdTelemetryUser) == null
? $"User id{item.IdTelemetryUser}"
: users[(int)item.IdTelemetryUser].MakeDisplayName(),
Text = events.GetValueOrDefault(item.IdEvent) == null
? $"Стбытие {item.IdEvent} {item.Arg0} {item.Arg1} {item.Arg2} {item.Arg3}"
: events[item.IdEvent].MakeMessageText(item)
};
{
var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset);
var endUtc = end.ToUtcDateTimeOffset(timezoneOffset);
var query = from item in context.TelemetryMessages
where item.IdTelemetry == idTelemetry
&& item.Date >= beginUtc
&& item.Date <= endUtc
orderby item.Date
select new MessageReport
{
Id = item.Id,
Date = item.Date.DateTime,
Category = events.GetValueOrDefault(item.IdEvent) == null
? $""
: categories[events[item.IdEvent].IdCategory],
User = item.IdTelemetryUser == null
? ""
: users.GetValueOrDefault((int)item.IdTelemetryUser) == null
? $"User id{item.IdTelemetryUser}"
: users[(int)item.IdTelemetryUser].MakeDisplayName(),
Text = events.GetValueOrDefault(item.IdEvent) == null
? $"Событие {item.IdEvent} {item.Arg0} {item.Arg1} {item.Arg2} {item.Arg3}"
: events[item.IdEvent].MakeMessageText(item)
};
return query;
}
public WellInfoReport GetWellInfo()
=> info;

View File

@ -40,8 +40,8 @@ namespace AsbCloudInfrastructure.Services.Analysis
try
{
using var context = new AsbCloudDbContext(options);
var timeZoneService = new TimeZoneService();
var telemetryService = new TelemetryService(context, telemetryTracker, timeZoneService, cacheDb);
var timezoneService = new TimezoneService();
var telemetryService = new TelemetryService(context, telemetryTracker, timezoneService, cacheDb);
var analyticsService = new TelemetryAnalyticsService(context,
telemetryService, cacheDb);

View File

@ -33,13 +33,14 @@ namespace AsbCloudInfrastructure.Services.Analysis
public async Task<IEnumerable<WellDepthToDayDto>> GetWellDepthToDayAsync(int idWell, CancellationToken token = default)
{
var telemetryId = telemetryService.GetIdTelemetryByIdWell(idWell);
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
if (telemetryId is null)
if (idTelemetry is null)
return null;
var timezone = telemetryService.GetTimezone((int)idTelemetry);
var depthToTimeData = (from d in db.TelemetryDataSaub
where d.IdTelemetry == telemetryId
where d.IdTelemetry == idTelemetry
select new
{
d.WellDepth,
@ -56,7 +57,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
{
WellDepth = d.WellDepth ?? 0.0,
BitDepth = d.BitDepth ?? 0.0,
Date = d.Date
Date = d.Date.ToRemoteDateTime(timezone.Hours),
}).AsNoTracking().ToListAsync(token).ConfigureAwait(false);
}
@ -70,11 +71,11 @@ namespace AsbCloudInfrastructure.Services.Analysis
if (telemetryId is null)
return null;
var timezoneOffset = telemetryService.GetTimezoneOffset((int)telemetryId);
var timezone = telemetryService.GetTimezone((int)telemetryId);
var drillingPeriodsInfo = await db.TelemetryDataSaub
.Where(t => t.IdTelemetry == telemetryId)
.GroupBy(t => Math.Floor((((t.Date.DayOfYear * 24 + t.Date.Hour) * 60 + t.Date.Minute) * 60 + t.Date.Second + timezoneOffset - shiftStartSec) / intervalSeconds))
.GroupBy(t => Math.Floor((((t.Date.DayOfYear * 24 + t.Date.Hour) * 60 + t.Date.Minute) * 60 + t.Date.Second + timezone.Hours - shiftStartSec) / intervalSeconds))
.Select(g => new {
WellDepthMin = g.Min(t => t.WellDepth),
WellDepthMax = g.Max(t => t.WellDepth),
@ -86,7 +87,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
var wellDepthToIntervalData = drillingPeriodsInfo.Select(d => new WellDepthToIntervalDto
{
IntervalStartDate = d.DateMin,
IntervalStartDate = d.DateMin.ToRemoteDateTime(timezone.Hours),
IntervalDepthProgress = (d.WellDepthMax - d.WellDepthMin) ?? 0.0
// / (d.DateMax - d.DateMin).TotalHours,
}).OrderBy(d => d.IntervalStartDate).ToList();
@ -201,7 +202,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
if (telemetryId is null)
return null;
var timezoneOffset = telemetryService.GetTimezoneOffset((int)telemetryId);
var timezone = telemetryService.GetTimezone((int)telemetryId);
// Get'n'Group all operations only by start date and by name (if there were several operations in interval).
// Without dividing these operations duration by given interval
@ -210,7 +211,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
join o in db.WellOperationCategories on a.IdOperation equals o.Id
group a by new
{
Interval = Math.Floor((a.UnixDate - workBeginSeconds + timezoneOffset) / intervalSeconds),
Interval = Math.Floor((a.UnixDate - workBeginSeconds + timezone.Hours) / intervalSeconds),
o.Name
} into g
select new
@ -223,17 +224,15 @@ namespace AsbCloudInfrastructure.Services.Analysis
.ToListAsync(token)
.ConfigureAwait(false);
var groupedOperationsList = new List<TelemetryOperationInfoDto>();
if (operations is not null && operations.Any())
{
var operations = ops.Select(o => (o.IntervalStart, o.OperationName, o.OperationDuration));
var splittedOperationsByInterval = DivideOperationsByIntervalLength(operations, intervalSeconds); // divides good
groupedOperationsList = UniteOperationsInDto(splittedOperationsByInterval, intervalSeconds).ToList(); // unites not good
groupedOperationsList = UniteOperationsInDto(splittedOperationsByInterval, intervalSeconds, timezone.Hours).ToList(); // unites not good
}
return groupedOperationsList;
@ -300,16 +299,17 @@ namespace AsbCloudInfrastructure.Services.Analysis
}
}
public async Task<DatesRangeDto> GetOperationsDateRangeAsync(int idWell, bool isUtc,
CancellationToken token = default)
public async Task<DatesRangeDto> GetOperationsDateRangeAsync(int idWell, CancellationToken token = default)
{
var telemetryId = telemetryService.GetIdTelemetryByIdWell(idWell);
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
if (telemetryId is null)
if (idTelemetry is null)
return null;
var timezone = telemetryService.GetTimezone((int)idTelemetry);
var datesRange = await (from d in db.TelemetryAnalysis
where d.IdTelemetry == telemetryId
where d.IdTelemetry == idTelemetry
select d.UnixDate).DefaultIfEmpty()
.GroupBy(g => true)
.AsNoTracking()
@ -323,18 +323,12 @@ namespace AsbCloudInfrastructure.Services.Analysis
var result = new DatesRangeDto
{
From = DateTimeOffset.FromUnixTimeSeconds(datesRange.From).DateTime,
To = datesRange.To == default
From = DateTimeOffset.FromUnixTimeSeconds(datesRange.From).ToRemoteDateTime(timezone.Hours),
To = (datesRange.To == default
? DateTime.MaxValue
: DateTimeOffset.FromUnixTimeSeconds(datesRange.To).DateTime
: DateTimeOffset.FromUnixTimeSeconds(datesRange.To)).ToRemoteDateTime(timezone.Hours),
};
if (isUtc)
return result;
result = await telemetryService.DatesRangeToTelemetryTimeZoneAsync((int)telemetryId, result, token)
.ConfigureAwait(false);
return result;
}
@ -347,7 +341,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
.LastOrDefaultAsync(token)
.ConfigureAwait(false);
DateTime lastAnalysisDate = default;
DateTime lastAnalysisDate = new DateTime(0, DateTimeKind.Utc);
if(lastAnalysisInDb is not null)
lastAnalysisDate = DateTime.UnixEpoch.AddSeconds(lastAnalysisInDb.DurationSec + lastAnalysisInDb.UnixDate);
@ -396,7 +390,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
operationDurationTimeCounter += OperationDuration;
}
else
{ // if operation duration overflows current interval it shoud be divided into 2 or more parts for this and next intervals
{ // if operation duration overflows current interval it should be divided into 2 or more parts for this and next intervals
var remainingIntervalTime = intervalSeconds - operationDurationTimeCounter;
splittedOperationsByInterval.Add((IntervalStart, OperationName, remainingIntervalTime)); // first part of long operation
@ -432,13 +426,14 @@ namespace AsbCloudInfrastructure.Services.Analysis
}
private static IEnumerable<TelemetryOperationInfoDto> UniteOperationsInDto(
IEnumerable<(long IntervalStart, string OperationName, int OperationDuration)> operations, int intervalSeconds)
IEnumerable<(long IntervalStart, string OperationName, int OperationDuration)> operations, int intervalSeconds, double timezoneOffset)
{
var groupedOperationsList = new List<TelemetryOperationInfoDto>();
var groupedOperationsObj = new TelemetryOperationInfoDto
{
IntervalBegin = DateTimeOffset.FromUnixTimeSeconds(operations.First().IntervalStart),
IntervalBegin = DateTimeOffset.FromUnixTimeSeconds(operations.First().IntervalStart)
.ToRemoteDateTime(timezoneOffset),
Operations = new List<TelemetryOperationDetailsDto>()
};
@ -461,7 +456,8 @@ namespace AsbCloudInfrastructure.Services.Analysis
intervalEndDate = IntervalStart + intervalSeconds;
groupedOperationsObj = new TelemetryOperationInfoDto
{
IntervalBegin = DateTimeOffset.FromUnixTimeSeconds(IntervalStart),
IntervalBegin = DateTimeOffset.FromUnixTimeSeconds(IntervalStart)
.ToRemoteDateTime(timezoneOffset),
Operations = new List<TelemetryOperationDetailsDto>()
};

View File

@ -309,7 +309,7 @@ namespace AsbCloudInfrastructure.Services.Cache
{
foreach (var entity in entities)
{
if (dbSet.Contains(entity)) // TODO: это очень ммедленно
if (dbSet.Contains(entity)) // TODO: это очень медленно
dbSet.Update(entity);
else
dbSet.Add(entity);

View File

@ -148,7 +148,7 @@ namespace AsbCloudInfrastructure.Services
Wells = gCluster.Select(well => {
var dto = well.Adapt<WellDto>();
dto.WellType = well.WellType?.Caption;
dto.LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id);
dto.LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id).DateTime;
dto.Cluster = gCluster.Key.Caption;
dto.Deposit = gDeposit.Key.Caption;
return dto;

View File

@ -15,36 +15,42 @@ namespace AsbCloudInfrastructure.Services
IDrillFlowChartService
{
private readonly IAsbCloudDbContext db;
private readonly IWellService wellService;
public DrillFlowChartService(IAsbCloudDbContext context)
public DrillFlowChartService(IAsbCloudDbContext context, IWellService wellService)
: base(context)
{
this.db = context;
this.wellService = wellService;
}
public async Task<IEnumerable<DrillFlowChartDto>> GetAllAsync(int idWell,
DateTime updateFrom, CancellationToken token = default)
{
var timezone = wellService.GetTimezone(idWell);
var updateFromUtc = updateFrom.ToUtcDateTimeOffset(timezone.Hours);
var entities = await (from p in db.DrillFlowChart
where p.IdWell == idWell &&
p.LastUpdate > updateFrom
p.LastUpdate > updateFromUtc
orderby p.DepthStart, p.Id
select p)
.ToListAsync(token)
.ConfigureAwait(false);
var dto = entities.Adapt<DrillFlowChartDto>();
return dto;
var dtos = entities.Select(entity => {
var dto = entity.Adapt<DrillFlowChartDto>();
dto.LastUpdate = entity.LastUpdate.ToRemoteDateTime(timezone.Hours);
return dto;
});
return dtos;
}
public async Task<int> InsertAsync(int idWell, DrillFlowChartDto dto,
CancellationToken token = default)
{
dto.IdWell = idWell;
dto.LastUpdate = DateTime.Now;
dto.LastUpdate = DateTime.UtcNow;
var result = await base.InsertAsync(dto, token).ConfigureAwait(false);
return result;
}
@ -54,7 +60,7 @@ namespace AsbCloudInfrastructure.Services
foreach (var dto in dtos)
{
dto.IdWell = idWell;
dto.LastUpdate = DateTime.Now;
dto.LastUpdate = DateTime.UtcNow;
}
var result = await base.InsertRangeAsync(dtos, token).ConfigureAwait(false);

View File

@ -164,7 +164,7 @@ namespace AsbCloudInfrastructure.Services
newSheetName = sheetSrc.Name;
suffix = $"_{index++}";
if (newSheetName.Length + suffix.Length >= 31)
newSheetName = newSheetName.Substring(0, (31 - suffix.Length));
newSheetName = newSheetName[..(31 - suffix.Length)];
newSheetName += suffix;
}

View File

@ -28,7 +28,8 @@ namespace AsbCloudInfrastructure.Services
.ThenInclude(u => u.Company)
.ThenInclude(c => c.CompanyType)
.Include(f => f.FileMarks)
.ThenInclude(m => m.User);
.ThenInclude(m => m.User)
.Include(f=>f.Well);
}
public async Task<string> GetSharedUrlAsync(int idFileInfo, int idUser, IFileShareService fileShareService,
@ -75,7 +76,7 @@ namespace AsbCloudInfrastructure.Services
IdAuthor = idUser,
IdCategory = idCategory,
Name = destinationFileName,
UploadDate = DateTime.Now,
UploadDate = DateTime.UtcNow,
IsDeleted = false,
Size = sysFileInfo.Length,
};
@ -87,8 +88,7 @@ namespace AsbCloudInfrastructure.Services
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
File.Move(srcFilePath, filePath);
var dto = entry.Entity.Adapt<FileInfoDto>();
return dto;
return await GetInfoAsync(entry.Entity.Id, token);
}
public async Task<FileInfoDto> SaveAsync(int idWell, int? idUser, int idCategory,
@ -101,7 +101,7 @@ namespace AsbCloudInfrastructure.Services
IdAuthor = idUser,
IdCategory = idCategory,
Name = Path.GetFileName(fileFullName),
UploadDate = DateTime.Now,
UploadDate = DateTime.UtcNow,
IsDeleted = false,
Size = fileStream?.Length ?? 0
};
@ -116,9 +116,8 @@ namespace AsbCloudInfrastructure.Services
using var newfileStream = new FileStream(filePath, FileMode.Create);
await fileStream.CopyToAsync(newfileStream, token).ConfigureAwait(false);
var dto = entry.Entity.Adapt<FileInfoDto>();
return dto;
return await GetInfoAsync(entry.Entity.Id, token);
}
private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId)
@ -136,7 +135,7 @@ namespace AsbCloudInfrastructure.Services
.ToListAsync(token)
.ConfigureAwait(false);
var dtos = entities.Adapt<FileInfoDto>();
var dtos = entities.Select(e => Convert(e));
return dtos;
}
@ -157,11 +156,28 @@ namespace AsbCloudInfrastructure.Services
if (!string.IsNullOrEmpty(fileName))
query = query.Where(e => e.Name.ToLower().Contains(fileName.ToLower()));
var firstFile = await query.FirstOrDefaultAsync(token);
if (firstFile is null)
return new PaginationContainer<FileInfoDto>()
{
Skip = skip,
Take = take,
Count = 0,
};
var timezoneOffset = firstFile.Well.Timezone?.Hours ?? 5;
if (begin != default)
query = query.Where(e => e.UploadDate >= begin);
{
var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset);
query = query.Where(e => e.UploadDate >= beginUtc);
}
if (end != default)
query = query.Where(e => e.UploadDate <= end);
{
var endUtc = end.ToUtcDateTimeOffset(timezoneOffset);
query = query.Where(e => e.UploadDate <= endUtc);
}
var count = await query.CountAsync(token).ConfigureAwait(false);
@ -185,8 +201,7 @@ namespace AsbCloudInfrastructure.Services
.Take(take).AsNoTracking().ToListAsync(token)
.ConfigureAwait(false);
var dtos = entities.Adapt<FileInfoDto>();
var dtos = entities.Select(e => Convert(e, timezoneOffset));
result.Items.AddRange(dtos);
return result;
}
@ -202,7 +217,7 @@ namespace AsbCloudInfrastructure.Services
if (entity is null)
return null;
var dto = entity.Adapt<FileInfoDto>();
var dto = Convert(entity);
return dto;
}
@ -259,10 +274,29 @@ namespace AsbCloudInfrastructure.Services
var entity = await dbSetConfigured
.FirstOrDefaultAsync(f => f.FileMarks.Any(m => m.Id == idMark), token)
.ConfigureAwait(false);
var dto = entity.Adapt<FileInfoDto>();
FileInfoDto dto = Convert(entity);
return dto;
}
private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity)
{
var timezoneOffset = entity.Well.Timezone?.Hours ?? 5;
return Convert(entity, timezoneOffset);
}
private static FileInfoDto Convert(AsbCloudDb.Model.FileInfo entity, double timezoneOffset)
{
var dto = entity.Adapt<FileInfoDto>();
dto.UploadDate = entity.UploadDate.ToRemoteDateTime(timezoneOffset);
dto.FileMarks = entity.FileMarks.Select(m =>
{
var mark = m.Adapt<FileMarkDto>();
mark.DateCreated = m.DateCreated.ToRemoteDateTime(timezoneOffset);
return mark;
});
return dto;
}
public async Task<int> CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token)
{
var fileMark = await db.FileMarks
@ -278,7 +312,7 @@ namespace AsbCloudInfrastructure.Services
var newFileMark = fileMarkDto.Adapt<FileMark>();
newFileMark.Id = default;
newFileMark.DateCreated = DateTime.Now;
newFileMark.DateCreated = DateTime.UtcNow;
newFileMark.IdUser = idUser;
db.FileMarks.Add(newFileMark);
@ -303,7 +337,7 @@ namespace AsbCloudInfrastructure.Services
fileInfo.PublishInfo = new FilePublishInfo()
{
IdPublisher = idUser,
Date = DateTime.Now,
Date = DateTime.UtcNow,
WebStorageFileUrl = weblink
};

View File

@ -15,11 +15,13 @@ namespace AsbCloudInfrastructure.Services
public class MeasureService : IMeasureService
{
private readonly IAsbCloudDbContext db;
private readonly IWellService wellService;
private readonly CacheTable<MeasureCategory> cacheCategories;
public MeasureService(IAsbCloudDbContext db, Cache.CacheDb cacheDb)
public MeasureService(IAsbCloudDbContext db, Cache.CacheDb cacheDb, IWellService wellService)
{
this.db = db;
this.wellService = wellService;
cacheCategories = cacheDb.GetCachedTable<MeasureCategory>((DbContext)db);
}
@ -43,8 +45,12 @@ namespace AsbCloudInfrastructure.Services
.FirstOrDefaultAsync(token)
.ConfigureAwait(false);
var dtos = entity?.Adapt<MeasureDto, Measure>((d, s) => d.CategoryName = s.Category?.Name);
return dtos;
var timezone = wellService.GetTimezone(idWell);
var dto = entity?.Adapt<MeasureDto, Measure>((d, s) => {
d.CategoryName = s.Category?.Name;
d.Timestamp = s.Timestamp.ToRemoteDateTime(timezone.Hours);
});
return dto;
}
public async Task<IEnumerable<MeasureDto>> GetHisoryAsync(int idWell, int? idCategory = null, CancellationToken token = default)
@ -61,41 +67,50 @@ namespace AsbCloudInfrastructure.Services
.ToListAsync(token)
.ConfigureAwait(false);
var dtos = entities.Adapt<MeasureDto, Measure>((d, s) => d.CategoryName = s.Category?.Name);
var timezone = wellService.GetTimezone(idWell);
var dtos = entities.Adapt<MeasureDto, Measure>((d, s) => {
d.CategoryName = s.Category?.Name;
d.Timestamp = s.Timestamp.ToRemoteDateTime(timezone.Hours);
});
return dtos;
}
public Task<int> InsertAsync(int idWell, MeasureDto data, CancellationToken token)
public Task<int> InsertAsync(int idWell, MeasureDto dto, CancellationToken token)
{
if (data.IdCategory < 1)
throw new ArgumentException("wrong idCategory", nameof(data));
if (data.Data is null)
throw new ArgumentException("data.data is not optional", nameof(data));
var entity = data.Adapt<Measure>();
if (dto.IdCategory < 1)
throw new ArgumentException("wrong idCategory", nameof(dto));
if (dto.Data is null)
throw new ArgumentException("data.data is not optional", nameof(dto));
var timezone = wellService.GetTimezone(idWell);
var entity = dto.Adapt<Measure>();
entity.IdWell = idWell;
entity.Timestamp = dto.Timestamp.ToUtcDateTimeOffset(timezone.Hours);
db.Measures.Add(entity);
return db.SaveChangesAsync(token);
}
public async Task<int> UpdateAsync(int idWell, MeasureDto data, CancellationToken token)
public async Task<int> UpdateAsync(int idWell, MeasureDto dto, CancellationToken token)
{
if (data.Id < 1)
throw new ArgumentException("wrong id", nameof(data));
if (data.IdCategory < 1)
throw new ArgumentException("wrong idCategory", nameof(data));
if (data.Data is null)
throw new ArgumentException("data.data is not optional", nameof(data));
if (dto.Id < 1)
throw new ArgumentException("wrong id", nameof(dto));
if (dto.IdCategory < 1)
throw new ArgumentException("wrong idCategory", nameof(dto));
if (dto.Data is null)
throw new ArgumentException("data.data is not optional", nameof(dto));
var entity = await db.Measures
.Where(m => m.Id == data.Id && !m.IsDeleted)
.Where(m => m.Id == dto.Id && !m.IsDeleted)
.FirstOrDefaultAsync(token)
.ConfigureAwait(false);
if (entity is null)
throw new ArgumentException("id doesn't exist", nameof(data));
throw new ArgumentException("id doesn't exist", nameof(dto));
var timezone = wellService.GetTimezone(idWell);
entity.IdWell = idWell;
entity.Timestamp = data.Timestamp;
entity.Data = (RawData)data.Data;
entity.Timestamp = dto.Timestamp.ToUtcDateTimeOffset(timezone.Hours);
entity.Data = (RawData)dto.Data;
return await db.SaveChangesAsync(token).ConfigureAwait(false);
}

View File

@ -35,7 +35,6 @@ namespace AsbCloudInfrastructure.Services
string searchString = default,
int skip = 0,
int take = 32,
bool isUtc = true,
CancellationToken token = default)
{
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
@ -68,18 +67,17 @@ namespace AsbCloudInfrastructure.Services
query = query.OrderByDescending(m => m.Date);
var timeZoneOffset = (await telemetryService.GetTimeZoneOffsetAsync(idTelemetry??default, token)
.ConfigureAwait(false)) ?? 0;
var timezone = telemetryService.GetTimezone(idTelemetry??default);
if (begin != default)
{
var beginUtc = telemetryService.TimeZoneService.DateToUtc(begin, timeZoneOffset);
var beginUtc = begin.ToUtcDateTimeOffset(timezone.Hours);
query = query.Where(m => m.Date >= beginUtc);
}
if (end != default)
{
var endUtc = telemetryService.TimeZoneService.DateToUtc(end, timeZoneOffset);
var endUtc = end.ToUtcDateTimeOffset(timezone.Hours);
query = query.Where(m => m.Date <= endUtc);
}
@ -109,9 +107,7 @@ namespace AsbCloudInfrastructure.Services
WellDepth = message.WellDepth
};
messageDto.Date = isUtc
? message.Date.UtcDateTime
: telemetryService.TimeZoneService.DateToTimeZone(message.Date, timeZoneOffset);
messageDto.Date = message.Date.ToRemoteDateTime(timezone.Hours);
if (message.IdTelemetryUser is not null)
{
@ -137,11 +133,6 @@ namespace AsbCloudInfrastructure.Services
return result;
}
[Obsolete("Use telemetryService.GetDatesRangeAsync instead", false)]
public Task<DatesRangeDto> GetMessagesDatesRangeAsync(int idWell, bool isUtc,
CancellationToken token = default)
=> telemetryService.GetDatesRangeAsync(idWell, isUtc, token);
public Task InsertAsync(string uid, IEnumerable<TelemetryMessageDto> dtos,
CancellationToken token = default)
{
@ -149,10 +140,10 @@ namespace AsbCloudInfrastructure.Services
return null;
var telemetryId = telemetryService.GetOrCreateTelemetryIdByUid(uid);
var timeZoneOffset = telemetryService.GetTimezoneOffset(telemetryId);
var timezone = telemetryService.GetTimezone(telemetryId);
var maxDateDto = dtos.Max(m => m.Date);
var maxDateUtc = maxDateDto.ToUtcDateTimeOffset(timeZoneOffset);
var maxDateUtc = maxDateDto.ToUtcDateTimeOffset(timezone.Hours);
telemetryService.SaveRequestDate(uid, maxDateDto);
foreach (var dto in dtos)
@ -160,7 +151,7 @@ namespace AsbCloudInfrastructure.Services
var entity = dto.Adapt<TelemetryMessage>();
entity.Id = 0;
entity.IdTelemetry = telemetryId;
entity.Date = dto.Date.ToUtcDateTimeOffset(timeZoneOffset);
entity.Date = dto.Date.ToUtcDateTimeOffset(timezone.Hours);
db.TelemetryMessages.Add(entity);
}

View File

@ -19,17 +19,17 @@ namespace AsbCloudInfrastructure.Services
private readonly IAsbCloudDbContext db;
private readonly string connectionString;
private readonly ITelemetryService telemetryService;
//private readonly IFileService fileService;
private readonly IReportsBackgroundQueue queue;
private readonly IWellService wellService;
public ReportService(IAsbCloudDbContext db, IConfiguration configuration,
ITelemetryService telemetryService,
IReportsBackgroundQueue queue)
IReportsBackgroundQueue queue, IWellService wellService)
{
this.db = db;
this.connectionString = configuration.GetConnectionString("DefaultConnection");
this.wellService = wellService;
this.telemetryService = telemetryService;
//this.fileService = fileService;
this.queue = queue;
ReportCategoryId = db.FileCategories.AsNoTracking()
.FirstOrDefault(c =>
@ -41,6 +41,12 @@ namespace AsbCloudInfrastructure.Services
public int CreateReport(int idWell, int idUser, int stepSeconds, int format, DateTime begin,
DateTime end, Action<object, int> progressHandler)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset);
var endUtc = end.ToUtcDateTimeOffset(timezoneOffset);
var beginRemote = begin.ToTimeZoneOffsetHours(timezoneOffset);
var endRemote = end.ToTimeZoneOffsetHours(timezoneOffset);
var newReportId = queue.EnqueueTask((id) =>
{
var optionsBuilder = new DbContextOptionsBuilder<AsbCloudDbContext>();
@ -49,7 +55,7 @@ namespace AsbCloudInfrastructure.Services
using var context = new AsbCloudDbContext(optionsBuilder.Options);
var generator = GetReportGenerator(idWell, begin, end, stepSeconds, format, context);
var generator = GetReportGenerator(idWell, beginRemote, endRemote, stepSeconds, format, context);
var reportFileName = Path.Combine(tempDir, generator.GetReportDefaultFileName());
var totalPages = generator.GetPagesCount();
@ -58,7 +64,7 @@ namespace AsbCloudInfrastructure.Services
progressHandler.Invoke(e.Adapt<ReportProgressDto>(), id);
};
generator.Make(reportFileName);
var fileService = new FileService(context);
var fileInfo = fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName).Result;
@ -75,8 +81,8 @@ namespace AsbCloudInfrastructure.Services
{
IdWell = idWell,
IdFile = fileInfo.Id,
Begin = begin,
End = end,
Begin = beginUtc,
End = endUtc,
Step = stepSeconds,
Format = format
};
@ -93,77 +99,56 @@ namespace AsbCloudInfrastructure.Services
public int GetReportPagesCount(int idWell, DateTime begin, DateTime end, int stepSeconds, int format)
{
var generator = GetReportGenerator(idWell, begin, end, stepSeconds, format, (AsbCloudDbContext)db);
return generator.GetPagesCount();
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var beginRemote = begin.ToTimeZoneOffsetHours(timezoneOffset);
var endRemote = end.ToTimeZoneOffsetHours(timezoneOffset);
var generator = GetReportGenerator(idWell, beginRemote, endRemote, stepSeconds, format, (AsbCloudDbContext)db);
var pagesCount = generator.GetPagesCount();
return pagesCount;
}
public async Task<DatesRangeDto> GetReportsDatesRangeAsync(int idWell, bool isUtc,
CancellationToken token = default)
public DatesRangeDto GetDatesRangeOrDefault(int idWell)
{
var telemetryId = telemetryService.GetIdTelemetryByIdWell(idWell);
if (telemetryId is null)
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
if(idTelemetry is null)
return null;
var datesRange = await (from d in db.TelemetryDataSaub
where d.IdTelemetry == telemetryId
select d.Date).Union(
from m in db.TelemetryMessages
where m.IdTelemetry == telemetryId
select m.Date).DefaultIfEmpty()
.GroupBy(g => true)
.AsNoTracking()
.Select(g => new
{
From = g.Min(),
To = g.Max()
}).OrderBy(gr => gr.From)
.FirstOrDefaultAsync(token)
.ConfigureAwait(false);
var result = new DatesRangeDto
{
From = datesRange.From,
To = datesRange.To.Year == 1 ? DateTime.MaxValue : datesRange.To
};
if (isUtc)
return result;
result = await telemetryService.DatesRangeToTelemetryTimeZoneAsync((int)telemetryId, result, token)
.ConfigureAwait(false);
return result;
var range = telemetryService.GetDatesRange((int)idTelemetry);
return range;
}
public Task<List<ReportPropertiesDto>> GetAllReportsByWellAsync(int idWell, CancellationToken token) =>
(from r in db.ReportProperties.Include(r => r.File)
where r.IdWell == idWell
select new ReportPropertiesDto
{
Id = r.Id,
Name = r.File.Name,
File = new FileInfoDto
{
Id = r.File.Id,
Author = null,
IdAuthor = r.File.IdAuthor ?? 0,
IdCategory = r.File.IdCategory,
IdWell = r.File.IdWell,
Name = r.File.Name,
Size = r.File.Size,
UploadDate = r.File.UploadDate,
},
IdWell = r.IdWell,
Date = r.File.UploadDate,
Begin = r.Begin,
End = r.End,
Step = r.Step,
Format = r.Format == 0 ? ".pdf" : ".las"
})
.OrderBy(o => o.Date)
public async Task<IEnumerable<ReportPropertiesDto>> GetAllReportsByWellAsync(int idWell, CancellationToken token)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var propertiesQuery = db.ReportProperties.Include(r => r.File)
.Where(p => p.IdWell == idWell)
.OrderBy(o => o.File.UploadDate)
.AsNoTracking()
.Take(1024).ToListAsync(token);
.Take(1024);
var properties = await propertiesQuery.ToListAsync(token);
return properties.Select(p => new ReportPropertiesDto
{
Id = p.Id,
Name = p.File.Name,
File = new FileInfoDto
{
Id = p.File.Id,
Author = null,
IdAuthor = p.File.IdAuthor ?? 0,
IdCategory = p.File.IdCategory,
IdWell = p.File.IdWell,
Name = p.File.Name,
Size = p.File.Size,
UploadDate = p.File.UploadDate.ToRemoteDateTime(timezoneOffset),
},
IdWell = p.IdWell,
Date = p.File.UploadDate.ToRemoteDateTime(timezoneOffset),
Begin = p.Begin.ToRemoteDateTime(timezoneOffset),
End = p.End.ToRemoteDateTime(timezoneOffset),
Step = p.Step,
Format = p.Format == 0 ? ".pdf" : ".las"
});
}
private static IReportGenerator GetReportGenerator(int idWell, DateTime begin,
DateTime end, int stepSeconds, int format, AsbCloudDbContext context)

View File

@ -13,7 +13,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services
{
public abstract class TelemetryDataBaseService<TDto, TModel> : ITelemetryDataService<TDto>, IConverter<TDto, TModel>
public abstract class TelemetryDataBaseService<TDto, TModel> : ITelemetryDataService<TDto>
where TDto : AsbCloudApp.Data.ITelemetryData
where TModel : class, AsbCloudDb.Model.ITelemetryData
{
@ -41,7 +41,6 @@ namespace AsbCloudInfrastructure.Services
return 0;
var idTelemetry = telemetryService.GetOrCreateTelemetryIdByUid(uid);
var lastTelemetryDate = telemetryService.GetLastTelemetryDate(uid);
var dtosList = dtos.OrderBy(d => d.Date).ToList();
var dtoMinDate = dtosList.First().Date;
@ -57,11 +56,10 @@ namespace AsbCloudInfrastructure.Services
dtosList.Remove(duplicate);
}
var timeZoneOffset = (await telemetryService.GetTimeZoneOffsetAsync(idTelemetry, token)) ?? 0;
var timezone = telemetryService.GetTimezone(idTelemetry);
var entities = dtosList.Select(dto => {
var entity = Convert(dto);
entity.Date = dto.Date.ToUtcDateTimeOffset(timeZoneOffset);
var entity = Convert(dto, timezone.Hours);
entity.IdTelemetry = idTelemetry;
return entity;
});
@ -91,7 +89,7 @@ namespace AsbCloudInfrastructure.Services
public virtual async Task<IEnumerable<TDto>> GetAsync(int idWell,
DateTime dateBegin = default, double intervalSec = 600d,
int approxPointsCount = 1024, bool isUtc = false, CancellationToken token = default)
int approxPointsCount = 1024, CancellationToken token = default)
{
var well = cacheWells.FirstOrDefault(w => w.Id == idWell);
if (well?.IdTelemetry is null)
@ -99,20 +97,19 @@ namespace AsbCloudInfrastructure.Services
var idTelemetry = well?.IdTelemetry ?? default;
var timeZoneOffset = (await telemetryService.GetTimeZoneOffsetAsync(idTelemetry, token)) ?? 0d;
var timezone = telemetryService.GetTimezone(idTelemetry);
var filterByDateEnd = dateBegin != default;
DateTimeOffset dateBeginUtc;
if (dateBegin == default)
{
dateBeginUtc = telemetryService.GetLastTelemetryDate(idTelemetry)
.UtcDateTime;
dateBeginUtc = telemetryService.GetLastTelemetryDate(idTelemetry, true);
if (dateBeginUtc != default)
dateBeginUtc = dateBeginUtc.AddSeconds(-intervalSec);
}
else
{
dateBeginUtc = dateBegin.ToUtcDateTimeOffset(timeZoneOffset);
dateBeginUtc = dateBegin.ToUtcDateTimeOffset(timezone.Hours);
}
if (dateBeginUtc == default)
@ -126,7 +123,7 @@ namespace AsbCloudInfrastructure.Services
&& d.Date >= dateBeginUtc);
if (filterByDateEnd)
query = query.Where(d => d.Date < dateEnd);
query = query.Where(d => d.Date <= dateEnd);
var fullDataCount = await query.CountAsync(token)
.ConfigureAwait(false);
@ -166,27 +163,13 @@ namespace AsbCloudInfrastructure.Services
.ToListAsync(token)
.ConfigureAwait(false);
var dtos = entities.Select(e => Convert(e));
if (isUtc)
return dtos;
dtos = dtos.Select(d =>
{
d.Date = d.Date.ToTimeZoneOffsetHours(timeZoneOffset);
return d;
});
var dtos = entities.Select(e => Convert(e, timezone.Hours));
return dtos;
}
[Obsolete("Use telemetryService.GetDatesRangeAsync instead", false)]
public virtual Task<DatesRangeDto> GetDataDatesRangeAsync(int idWell, bool isUtc,
CancellationToken token = default)
=> telemetryService.GetDatesRangeAsync(idWell, isUtc, token);
public abstract TDto Convert(TModel src, double timezoneOffset);
public abstract TDto Convert(TModel src);
public abstract TModel Convert(TDto src);
public abstract TModel Convert(TDto src, double timezoneOffset);
}
}

View File

@ -15,21 +15,23 @@ namespace AsbCloudInfrastructure.Services
:base(db, telemetryService, cacheDb)
{}
public override TelemetryDataSaub Convert(TelemetryDataSaubDto src)
public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset)
{
var entity = src.Adapt<TelemetryDataSaub>();
var telemetryUser = cacheTelemetryUsers?
.FirstOrDefault(u => u.IdTelemetry == src.IdTelemetry && (u.Name == src.User || u.Surname == src.User));
entity.IdUser = telemetryUser?.IdUser;
entity.Date = src.Date.ToUtcDateTimeOffset(timezoneOffset);
return entity;
}
public override TelemetryDataSaubDto Convert(TelemetryDataSaub src)
public override TelemetryDataSaubDto Convert(TelemetryDataSaub src, double timezoneOffset)
{
var dto = src.Adapt<TelemetryDataSaubDto>();
var telemetryUser = cacheTelemetryUsers?
.FirstOrDefault(u => u.IdTelemetry == src.IdTelemetry && u.IdUser == src.IdUser);
dto.User = telemetryUser?.MakeDisplayName();
dto.Date = src.Date.ToRemoteDateTime(timezoneOffset);
return dto;
}
}

View File

@ -15,15 +15,17 @@ namespace AsbCloudInfrastructure.Services
: base(db, telemetryService, cacheDb)
{ }
public override TelemetryDataSpin Convert(TelemetryDataSpinDto src)
public override TelemetryDataSpin Convert(TelemetryDataSpinDto src, double timezoneOffset)
{
var entity = src.Adapt<TelemetryDataSpin>();
entity.Date = src.Date.ToUtcDateTimeOffset(timezoneOffset);
return entity;
}
public override TelemetryDataSpinDto Convert(TelemetryDataSpin src)
public override TelemetryDataSpinDto Convert(TelemetryDataSpin src, double timezoneOffset)
{
var dto = src.Adapt<TelemetryDataSpinDto>();
dto.Date = src.Date.ToRemoteDateTime(timezoneOffset);
return dto;
}
}

View File

@ -19,15 +19,15 @@ namespace AsbCloudInfrastructure.Services
private readonly CacheTable<Well> cacheWells;//TODO: use wellService instead of this
private readonly IAsbCloudDbContext db;
private readonly ITelemetryTracker telemetryTracker;
private readonly ITimeZoneService timeZoneService;
private readonly ITimezoneService timezoneService;
public ITimeZoneService TimeZoneService => timeZoneService;
public ITimezoneService TimeZoneService => timezoneService;
public ITelemetryTracker TelemetryTracker => telemetryTracker;
public TelemetryService(
IAsbCloudDbContext db,
ITelemetryTracker telemetryTracker,
ITimeZoneService timeZoneService,
ITimezoneService timezoneService,
CacheDb cacheDb)
{
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
@ -39,7 +39,7 @@ namespace AsbCloudInfrastructure.Services
nameof(Well.WellType));
this.db = db;
this.telemetryTracker = telemetryTracker;
this.timeZoneService = timeZoneService;
this.timezoneService = timezoneService;
}
public IEnumerable<TelemetryDto> GetTransmittingTelemetries()
@ -58,45 +58,40 @@ namespace AsbCloudInfrastructure.Services
public void SaveRequestDate(string uid, DateTimeOffset remoteDate) =>
telemetryTracker.SaveRequestDate(uid, remoteDate);
public DateTimeOffset GetLastTelemetryDate(string telemetryUid) =>
telemetryTracker.GetLastTelemetryDateByUid(telemetryUid);
public DateTimeOffset GetLastTelemetryDate(int telemetryId)
public DateTime GetLastTelemetryDate(int idTelemetry, bool useUtc = false)
{
var lastTelemetryDate = DateTimeOffset.MinValue;
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == telemetryId);
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry);
if (telemetry is null)
return lastTelemetryDate;
throw new Exception($"Telemetry id:{idTelemetry} does not exist");
var uid = telemetry.RemoteUid;
var timzone = GetTimezone(idTelemetry);
lastTelemetryDate = GetLastTelemetryDate(uid);
return lastTelemetryDate;
lastTelemetryDate = telemetryTracker.GetLastTelemetryDateByUid(uid);
if (useUtc)
return lastTelemetryDate.UtcDateTime;
return lastTelemetryDate.ToRemoteDateTime(timzone.Hours);
}
public virtual async Task<DatesRangeDto> GetDatesRangeAsync(
int idWell,
bool isUtc,
CancellationToken token = default)
public DatesRangeDto GetDatesRange(int idTelemetry)
{
var telemetryId = GetIdTelemetryByIdWell(idWell);
if (telemetryId is null)
return null;
var telemetry = await cacheTelemetry.FirstOrDefaultAsync(t => t.Id == telemetryId, token)
.ConfigureAwait(false);
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry);
if (telemetry is null)
throw new Exception($"Telemetry id:{idTelemetry} does not exist");
var dto = TelemetryTracker.GetTelemetryDateRangeByUid(telemetry.RemoteUid);
if (dto is null)
throw new Exception($"Telemetry id:{idTelemetry} has no data");
if (isUtc)
return dto;
dto = await DatesRangeToTelemetryTimeZoneAsync((int)telemetryId, dto, token)
.ConfigureAwait(false);
var timezone = GetTimezone((int)idTelemetry);
dto.From = dto.From.ToTimeZoneOffsetHours(timezone.Hours);
dto.To = dto.To.ToTimeZoneOffsetHours(timezone.Hours);
return dto;
}
public int GetOrCreateTelemetryIdByUid(string uid)
@ -113,7 +108,7 @@ namespace AsbCloudInfrastructure.Services
if (!string.IsNullOrEmpty(info.TimeZoneId) &&
telemetry.TimeZone?.IsOverride != true)
telemetry.TimeZone = new TelemetryTimeZone()
telemetry.TimeZone = new SimpleTimezone()
{
Hours = info.TimeZoneOffsetTotalHours,
TimeZoneId = info.TimeZoneId
@ -123,73 +118,43 @@ namespace AsbCloudInfrastructure.Services
.ConfigureAwait(false);
}
public double GetTimezoneOffset(int idTelemetry) =>
cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry).Info?.TimeZoneOffsetTotalHours ?? 0d;
public async Task<double?> GetTimeZoneOffsetAsync(int idTelemetry, CancellationToken token)
public SimpleTimezoneDto GetTimezone(int idTelemetry)
{
var telemetry =
await cacheTelemetry.FirstOrDefaultAsync(t => t.Id == idTelemetry, token);
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry);
if (!string.IsNullOrEmpty(telemetry.TimeZone?.TimeZoneId))
return telemetry.TimeZone.Hours;
if (telemetry is null)
throw new Exception($"Telemetry id: {idTelemetry} does not exist.");
if (!string.IsNullOrEmpty(telemetry.Info?.TimeZoneId))
if (telemetry.TimeZone is not null)
return telemetry.TimeZone.Adapt<SimpleTimezoneDto>();
if (telemetry.Info is not null)
{
telemetry.TimeZone = new TelemetryTimeZone
telemetry.TimeZone = new SimpleTimezone
{
Hours = telemetry.Info.TimeZoneOffsetTotalHours,
IsOverride = false,
TimeZoneId = telemetry.Info.TimeZoneId,
};
}
else
{
var well = await cacheWells.FirstOrDefaultAsync(t => t.IdTelemetry == telemetry.Id, token)
.ConfigureAwait(false);
if (well is null)
return null;
var coordinates = await GetWellCoordinatesAsync(well.Id, token);
if (coordinates is null)
return null;
var requestedTimeZone = await timeZoneService.GetByCoordinatesAsync(coordinates.Value.latitude, coordinates.Value.longitude, token)
.ConfigureAwait(false);
if (requestedTimeZone is null)
return null;
telemetry.TimeZone = requestedTimeZone.Adapt<TelemetryTimeZone>();
cacheTelemetry.Upsert(telemetry);
return telemetry.TimeZone.Adapt<SimpleTimezoneDto>();
}
await cacheTelemetry.UpsertAsync(telemetry, token).ConfigureAwait(false);
return telemetry.TimeZone.Hours;
}
public async Task<DatesRangeDto> DatesRangeToTelemetryTimeZoneAsync(int idTelemetry, DatesRangeDto range,
CancellationToken token)
{
var offset = await GetTimeZoneOffsetAsync(idTelemetry, token);
if (offset is null)
return range;
return new DatesRangeDto()
if (telemetry.Well?.Timezone is not null)
{
From = range.From.ToTimeZoneOffsetHours(offset ?? default),
To = range.To.ToTimeZoneOffsetHours(offset ?? default),
};
telemetry.TimeZone = telemetry.Well.Timezone;
cacheTelemetry.Upsert(telemetry);
return telemetry.TimeZone.Adapt<SimpleTimezoneDto>();
}
throw new Exception($"Telemetry id: {idTelemetry} can't find timezone.");
}
public async Task UpdateTimeZoneAsync(string uid, TelemetryTimeZoneDto timeZoneInfo,
public async Task UpdateTimezoneAsync(string uid, SimpleTimezoneDto timeone,
CancellationToken token)
{
var telemetry = GetOrCreateTelemetryByUid(uid);
var newTelemetryTimeZone = timeZoneInfo.Adapt<TelemetryTimeZone>();
var newTelemetryTimeZone = timeone.Adapt<SimpleTimezone>();
if (newTelemetryTimeZone?.Equals(telemetry.TimeZone) == true)
return;
await cacheTelemetry.UpsertAsync(telemetry, token)
@ -202,29 +167,6 @@ namespace AsbCloudInfrastructure.Services
return well?.IdTelemetry;
}
private async Task<(double latitude, double longitude)?> GetWellCoordinatesAsync(int idWell,
CancellationToken token)
{
var well = await cacheWells.FirstOrDefaultAsync(w => w.Id == idWell, token)
.ConfigureAwait(false);
if (well is null)
return null;
var latitude = well.Latitude ??
well.Cluster?.Latitude ??
well.Cluster?.Deposit?.Latitude;
var longitude = well.Longitude ??
well.Cluster?.Longitude ??
well.Cluster?.Deposit?.Longitude;
if (latitude is not null && longitude is not null)
return ((double)latitude, (double)longitude);
return null;
}
private Well GetWellByTelemetryUid(string uid)
{
var tele = cacheTelemetry.FirstOrDefault(t => t.RemoteUid == uid);

View File

@ -28,12 +28,12 @@ namespace AsbCloudInfrastructure.Services
/// <summary>
/// Дата первых данных в БД
/// </summary>
public DateTimeOffset TelemetryDateMin { get; set; }
public DateTimeOffset TelemetryDateUtcMin { get; set; }
/// <summary>
/// Дата последних данных в БД
/// </summary>
public DateTimeOffset TelemetryDateMax { get; set; }
public DateTimeOffset TelemetryDateUtcMax { get; set; }
}
@ -56,8 +56,8 @@ namespace AsbCloudInfrastructure.Services
keyValuePairs[telemetry.RemoteUid] = new TrackerStat
{
RemoteUid = telemetry.RemoteUid,
TelemetryDateMin = date,
TelemetryDateMax = date,
TelemetryDateUtcMin = date,
TelemetryDateUtcMax = date,
LastTimeServer = date,
};
}
@ -88,8 +88,8 @@ namespace AsbCloudInfrastructure.Services
foreach (var oldReq in oldRequests)
{
var telemetryStat = telemetriesStats.GetOrAdd(oldReq.Uid, (uid) => new TrackerStat { RemoteUid = uid });
telemetryStat.TelemetryDateMin = oldReq.DateMin;
telemetryStat.TelemetryDateMax = oldReq.DateMax;
telemetryStat.TelemetryDateUtcMin = oldReq.DateMin;
telemetryStat.TelemetryDateUtcMax = oldReq.DateMax;
telemetryStat.LastTimeServer = oldReq.DateMax;
}
}).ContinueWith((t) =>
@ -118,25 +118,25 @@ namespace AsbCloudInfrastructure.Services
{
var stat = telemetriesStats.GetOrAdd(uid, _ => new TrackerStat {
RemoteUid = uid,
TelemetryDateMin = remoteDate}
TelemetryDateUtcMin = remoteDate}
);
stat.LastTimeServer = DateTime.Now;
if(stat.TelemetryDateMax.ToUniversalTime() < remoteDate.ToUniversalTime())
stat.TelemetryDateMax = remoteDate;
if(stat.TelemetryDateUtcMax.ToUniversalTime() < remoteDate.ToUniversalTime())
stat.TelemetryDateUtcMax = remoteDate;
}
public DateTimeOffset GetLastTelemetryDateByUid(string uid) =>
telemetriesStats.GetValueOrDefault(uid)?.TelemetryDateMax ?? default;
telemetriesStats.GetValueOrDefault(uid)?.TelemetryDateUtcMax ?? default;
public DatesRangeDto GetTelemetryDateRangeByUid(string uid)
{
var stat = telemetriesStats.GetValueOrDefault(uid);
var range = new DatesRangeDto
{
From = stat?.TelemetryDateMin.UtcDateTime ?? default,
To = stat?.TelemetryDateMax.UtcDateTime ?? default,
From = stat?.TelemetryDateUtcMin.UtcDateTime ?? default,
To = stat?.TelemetryDateUtcMax.UtcDateTime ?? default,
};
return range;
}

View File

@ -8,7 +8,7 @@ using System;
namespace AsbCloudInfrastructure.Services
{
public class TimeZoneService : ITimeZoneService
public class TimezoneService : ITimezoneService
{
private class TimeZoneInfo
{
@ -25,16 +25,19 @@ namespace AsbCloudInfrastructure.Services
public string Time { get; set; }
}
private const string timeZoneApiUrl = "http://api.geonames.org/timezoneJSON";
private const string timezoneApiUrl = "http://api.geonames.org/timezoneJSON";
private const string timezoneApiUserName = "asbautodrilling";
public async Task<TelemetryTimeZoneDto> GetByCoordinatesAsync(double latitude, double longitude, CancellationToken token)
public SimpleTimezoneDto GetByCoordinates(double latitude, double longitude)
=> GetByCoordinatesAsync(latitude, longitude, default).Result;
public async Task<SimpleTimezoneDto> GetByCoordinatesAsync(double latitude, double longitude, CancellationToken token)
{
var lat = latitude.ToString(System.Globalization.CultureInfo.InvariantCulture);
var lng = longitude.ToString(System.Globalization.CultureInfo.InvariantCulture);
var url =
$"{timeZoneApiUrl}?lat={lat}&lng={lng}&username={timezoneApiUserName}";
$"{timezoneApiUrl}?lat={lat}&lng={lng}&username={timezoneApiUserName}";
using var client = new HttpClient();
@ -51,13 +54,13 @@ namespace AsbCloudInfrastructure.Services
{
PropertyNameCaseInsensitive = true
};
var timeZoneInfo = JsonSerializer.Deserialize<TimeZoneInfo>(responseJson, options);
var timezoneInfo = JsonSerializer.Deserialize<TimeZoneInfo>(responseJson, options);
return new TelemetryTimeZoneDto
return new SimpleTimezoneDto
{
Hours = timeZoneInfo.DstOffset,
Hours = timezoneInfo.DstOffset,
IsOverride = false,
TimeZoneId = timeZoneInfo.TimezoneId,
TimezoneId = timezoneInfo.TimezoneId,
};
}

View File

@ -143,7 +143,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
var statsList = clusterWellsIds.Select(clusterWellId =>
{
var currentWellOps = operations.Where(o => o.IdWell == clusterWellId);
var stat = CalcStat(currentWellOps);
var timezoneOffsetH = wellService.GetTimezone(clusterWellId).Hours;
var stat = CalcStat(currentWellOps, timezoneOffsetH);
return stat;
}).Where(c => c is not null);
@ -161,8 +162,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
private async Task<StatWellDto> CalcStatWellAsync(Well well, CancellationToken token = default)
{
var wellType = await cacheWellType.FirstOrDefaultAsync(t => t.Id == well.IdWellType, token);
var wellType = await cacheWellType.FirstOrDefaultAsync(t => t.Id == well.IdWellType, token);
var statWellDto = new StatWellDto()
{
Id = well.Id,
@ -170,7 +170,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
WellType = wellType?.Caption ?? "",
IdState = well.IdState,
State = wellService.GetStateText(well.IdState),
LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id),
LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id).DateTime,
};
statWellDto.Companies = await wellService.GetCompaniesAsync(well.Id, token);
@ -185,13 +185,14 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
if (!wellOperations.Any())
return statWellDto;
statWellDto.Sections = CalcSectionsStats(wellOperations);
statWellDto.Total = GetStatTotal(wellOperations, well.IdState);
var timezoneOffsetH = wellService.GetTimezone(well.Id).Hours;
statWellDto.Sections = CalcSectionsStats(wellOperations, timezoneOffsetH);
statWellDto.Total = GetStatTotal(wellOperations, well.IdState, timezoneOffsetH);
return statWellDto;
}
private IEnumerable<StatSectionDto> CalcSectionsStats(IEnumerable<WellOperation> operations)
private IEnumerable<StatSectionDto> CalcSectionsStats(IEnumerable<WellOperation> operations, double timezoneOffsetH)
{
var sectionTypeIds = operations
.Select(o => o.IdWellSectionType)
@ -211,8 +212,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
{
Id = id,
Caption = sectionType.Caption,
Plan = CalcSectionStat(operationsPlan, id),
Fact = CalcSectionStat(operationsFact, id),
Plan = CalcSectionStat(operationsPlan, id, timezoneOffsetH),
Fact = CalcSectionStat(operationsFact, id, timezoneOffsetH),
};
sections.Add(section);
}
@ -220,42 +221,42 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
}
private static PlanFactBase<StatOperationsDto> GetStatTotal(IEnumerable<WellOperation> operations,
int idWellState)
int idWellState, double timezoneOffsetH)
{
var operationsPlan = operations.Where(o => o.IdType == idOperationTypePlan);
var operationsFact = operations.Where(o => o.IdType == idOperationTypeFact);
var factEnd = CalcStat(operationsFact);
var factEnd = CalcStat(operationsFact, timezoneOffsetH);
if (idWellState != 2)
factEnd.End = null;
var section = new PlanFactBase<StatOperationsDto>
{
Plan = CalcStat(operationsPlan),
Plan = CalcStat(operationsPlan, timezoneOffsetH),
Fact = factEnd,
};
return section;
}
private static StatOperationsDto CalcSectionStat(IEnumerable<WellOperation> operations, int idSectionType)
private static StatOperationsDto CalcSectionStat(IEnumerable<WellOperation> operations, int idSectionType, double timezoneOffsetH)
{
var sectionOperations = operations
.Where(o => o.IdWellSectionType == idSectionType)
.OrderBy(o => o.DateStart)
.ThenBy(o => o.DepthStart);
return CalcStat(sectionOperations);
return CalcStat(sectionOperations, timezoneOffsetH);
}
private static StatOperationsDto CalcStat(IEnumerable<WellOperation> operations)
private static StatOperationsDto CalcStat(IEnumerable<WellOperation> operations, double timezoneOffsetH)
{
if (!operations.Any())
return null;
var races = GetCompleteRaces(operations);
var races = GetCompleteRaces(operations, timezoneOffsetH);
var section = new StatOperationsDto
{
Start = operations.FirstOrDefault()?.DateStart,
End = operations.Max(o => o.DateStart.AddHours(o.DurationHours)),
Start = operations.FirstOrDefault()?.DateStart.ToRemoteDateTime(timezoneOffsetH),
End = operations.Max(o => o.DateStart.ToRemoteDateTime(timezoneOffsetH).AddHours(o.DurationHours)),
WellDepthStart = operations.Min(o => o.DepthStart),
WellDepthEnd = operations.Max(o => o.DepthStart),
Rop = CalcROP(operations),
@ -297,7 +298,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return depth / (dHours + double.Epsilon);
}
private static IEnumerable<Race> GetCompleteRaces(IEnumerable<WellOperation> operations)
private static IEnumerable<Race> GetCompleteRaces(IEnumerable<WellOperation> operations, double timezoneOffsetH)
{
var races = new List<Race>();
var iterator = operations
@ -309,7 +310,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
{
var race = new Race
{
StartDate = iterator.Current.DateStart.AddHours(iterator.Current.DurationHours),
StartDate = iterator.Current.DateStart.ToRemoteDateTime(timezoneOffsetH).AddHours(iterator.Current.DurationHours),
StartWellDepth = iterator.Current.DepthStart,
Operations = new List<WellOperation>(10),
};
@ -321,7 +322,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
}
if (iterator.Current.IdCategory == idOperationBhaDisassembly)
{
race.EndDate = iterator.Current.DateStart;
race.EndDate = iterator.Current.DateStart.ToRemoteDateTime(timezoneOffsetH);
race.EndWellDepth = iterator.Current.DepthStart;
races.Add(race);
break;

View File

@ -35,7 +35,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
private static readonly TimeSpan drillingDurationLimitMax = TimeSpan.FromDays(366);
private readonly IAsbCloudDbContext db;
private readonly IWellService wellService;
private List<WellOperationCategory> categories = null;
public List<WellOperationCategory> Categories
{
@ -65,9 +65,10 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
}
}
public WellOperationImportService(IAsbCloudDbContext db)
public WellOperationImportService(IAsbCloudDbContext db, IWellService wellService)
{
this.db = db;
this.wellService = wellService;
}
public void Import(int idWell, Stream stream, bool deleteWellOperationsBeforeImport = false)
@ -93,7 +94,9 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
if (!operations.Any())
return null;
return MakeExelFileStream(operations);
var timezone = wellService.GetTimezone(idWell);
return MakeExelFileStream(operations, timezone.Hours);
}
public Stream GetExcelTemplateStream() {
@ -102,12 +105,12 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return stream;
}
private Stream MakeExelFileStream(IEnumerable<WellOperation> operations)
private Stream MakeExelFileStream(IEnumerable<WellOperation> operations, double timezoneOffset)
{
using Stream ecxelTemplateStream = GetExcelTemplateStream();
using var workbook = new XLWorkbook(ecxelTemplateStream, XLEventTracking.Disabled);
AddOperationsToWorkbook(workbook, operations);
AddOperationsToWorkbook(workbook, operations, timezoneOffset);
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
@ -115,53 +118,61 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return memoryStream;
}
private static void AddOperationsToWorkbook(XLWorkbook workbook, IEnumerable<WellOperation> operations)
private static void AddOperationsToWorkbook(XLWorkbook workbook, IEnumerable<WellOperation> operations, double timezoneOffset)
{
var planOperations = operations.Where(o => o.IdType == 0);
if (planOperations.Any())
{
var sheetPlan = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlan);
AddOperationsToSheet(sheetPlan, planOperations);
AddOperationsToSheet(sheetPlan, planOperations, timezoneOffset);
}
var factOperations = operations.Where(o => o.IdType == 1);
if (factOperations.Any())
{
var sheetFact = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNameFact);
AddOperationsToSheet(sheetFact, factOperations);
AddOperationsToSheet(sheetFact, factOperations, timezoneOffset);
}
}
private static void AddOperationsToSheet(IXLWorksheet sheet, IEnumerable<WellOperation> operations)
private static void AddOperationsToSheet(IXLWorksheet sheet, IEnumerable<WellOperation> operations, double timezoneOffset)
{
var operationsList = operations.ToList();
for (int i = 0; i < operationsList.Count; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
AddOperationToRow(row, operationsList[i]);
AddOperationToRow(row, operationsList[i], timezoneOffset);
}
}
private static void AddOperationToRow(IXLRow row, WellOperation operation)
private static void AddOperationToRow(IXLRow row, WellOperation operation, double timezoneOffset)
{
row.Cell(columnSection).Value = operation.WellSectionType?.Caption;
row.Cell(columnCategory).Value = operation.OperationCategory?.Name;
row.Cell(columnCategoryInfo).Value = operation.CategoryInfo;
row.Cell(columnDepthStart).Value = operation.DepthStart;
row.Cell(columnDepthEnd).Value = operation.DepthEnd;
row.Cell(columnDate).Value = operation.DateStart;
row.Cell(columnDate).Value = operation.DateStart.ToRemoteDateTime(timezoneOffset);
row.Cell(columnDuration).Value = operation.DurationHours;
row.Cell(columnComment).Value = operation.Comment;
}
private void SaveOperations(int idWell, IEnumerable<WellOperationDto> operations, bool deleteWellOperationsBeforeImport = false)
{
var timezone = wellService.GetTimezone(idWell);
var transaction = db.Database.BeginTransaction();
try
{
if (deleteWellOperationsBeforeImport)
db.WellOperations.RemoveRange(db.WellOperations.Where(o => o.IdWell == idWell));
db.WellOperations.AddRange(operations.Adapt<WellOperation>());
var entities = operations.Select(o => {
var entity = o.Adapt<WellOperation>();
entity.IdWell = idWell;
entity.DateStart = o.DateStart.ToUtcDateTimeOffset(timezone.Hours);
return entity;
});
db.WellOperations.AddRange(entities);
db.SaveChanges();
transaction.Commit();
}
@ -204,7 +215,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
{
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 7)
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцев.");
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
var count = sheet.RowsUsed().Count() - headerRowsCount;

View File

@ -52,13 +52,13 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
int take = 32,
CancellationToken token = default)
{
var timezone = wellService.GetTimezone(idWell);
var query = db.WellOperations
.Include(s => s.WellSectionType)
.Include(s => s.OperationCategory)
.Where(s => s.IdWell == idWell);
var timeZoneOffset = await wellService.GetTimeZoneOffsetAsync(idWell,token);
if (operationType != default)
query = query.Where(e => e.IdType == (int)operationType);
@ -76,12 +76,15 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
if (begin != default)
{
query = query.Where(e => e.DateStart >= begin);
var beginOffset = begin.ToUtcDateTimeOffset(timezone.Hours);
query = query.Where(e => e.DateStart >= beginOffset);
}
if (end != default)
{
query = query.Where(e => e.DateStart <= end);
var endOffset = end.ToUtcDateTimeOffset(timezone.Hours);
query = query.Where(e => e.DateStart <= endOffset);
}
var result = new PaginationContainer<WellOperationDto>
@ -102,11 +105,12 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
var entities = await query.Take(take).AsNoTracking()
.ToListAsync(token).ConfigureAwait(false);
foreach (var item in entities)
foreach (var entity in entities)
{
var dto = item.Adapt<WellOperationDto>();
dto.WellSectionTypeName = item.WellSectionType.Caption;
dto.CategoryName = item.OperationCategory.Name;
var dto = entity.Adapt<WellOperationDto>();
dto.WellSectionTypeName = entity.WellSectionType.Caption;
dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours);
dto.CategoryName = entity.OperationCategory.Name;
result.Items.Add(dto);
}
@ -116,6 +120,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
public async Task<WellOperationDto> GetAsync(int id,
CancellationToken token = default)
{
var entity = await db.WellOperations
.Include(s => s.WellSectionType)
.Include(s => s.OperationCategory)
@ -125,8 +130,11 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
if (entity is null)
return null;
var timezone = wellService.GetTimezone(entity.IdWell);
var dto = entity.Adapt<WellOperationDto>();
dto.WellSectionTypeName = entity.WellSectionType.Caption;
dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours);
dto.CategoryName = entity.OperationCategory.Name;
return dto;
}
@ -135,10 +143,12 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
IEnumerable<WellOperationDto> wellOperationDtos,
CancellationToken token = default)
{
foreach (var operationDto in wellOperationDtos)
var timezone = wellService.GetTimezone(idWell);
foreach (var dto in wellOperationDtos)
{
var entity = operationDto.Adapt<WellOperation>();
var entity = dto.Adapt<WellOperation>();
entity.Id = default;
entity.DateStart = dto.DateStart.ToUtcDateTimeOffset(timezone.Hours);
entity.IdWell = idWell;
db.WellOperations.Add(entity);
}
@ -148,11 +158,12 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
}
public async Task<int> UpdateAsync(int idWell, int idOperation,
WellOperationDto item, CancellationToken token = default)
WellOperationDto dto, CancellationToken token = default)
{
var entity = item.Adapt<WellOperation>();
var timezone = wellService.GetTimezone(idWell);
var entity = dto.Adapt<WellOperation>();
entity.Id = idOperation;
entity.IdWell = idWell;
entity.DateStart = dto.DateStart.ToUtcDateTimeOffset(timezone.Hours);
db.WellOperations.Update(entity);
return await db.SaveChangesAsync(token)
.ConfigureAwait(false);

View File

@ -5,7 +5,6 @@ using AsbCloudInfrastructure.Services.Cache;
using Mapster;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -28,13 +27,15 @@ namespace AsbCloudInfrastructure.Services
private readonly ITelemetryService telemetryService;
private readonly CacheTable<RelationCompanyWell> cacheRelationCompaniesWells;
private readonly CacheTable<CompanyType> cacheCompanyWellTypes;
private readonly ITimezoneService timezoneService;
public ITelemetryService TelemetryService => telemetryService;
public WellService(IAsbCloudDbContext db, CacheDb cacheDb, ITelemetryService telemetryService)
public WellService(IAsbCloudDbContext db, CacheDb cacheDb, ITelemetryService telemetryService, ITimezoneService timezoneService)
:base(db, cacheDb)
{
this.telemetryService = telemetryService;
this.timezoneService = timezoneService;
cacheRelationCompaniesWells = cacheDb.GetCachedTable<RelationCompanyWell>((AsbCloudDbContext)db, nameof(RelationCompanyWell.Company), nameof(RelationCompanyWell.Well));
cacheCompanyWellTypes = cacheDb.GetCachedTable<CompanyType>((AsbCloudDbContext)db);
Includes.Add($"{nameof(Well.Cluster)}.{nameof(Cluster.Deposit)}");
@ -60,7 +61,7 @@ namespace AsbCloudInfrastructure.Services
.WhereAsync(r => r.IdCompany == idCompany, token);
var wellsIds = relations.Select(r => r.IdWell);
var wells = await Cache.WhereAsync(w => wellsIds.Contains(w.Id));
var wells = await Cache.WhereAsync(w => wellsIds.Contains(w.Id), token);
var dtos = wells.Select(Convert);
return dtos;
@ -179,17 +180,21 @@ namespace AsbCloudInfrastructure.Services
protected override Well Convert(WellDto dto)
{
var entity = dto.Adapt<Well>(typeAdapterConfig);
//dto.WellType = entity.WellType?.Caption;
//dto.Cluster = entity.Cluster?.Caption;
//dto.Deposit = entity.Cluster?.Deposit?.Caption;
//dto.LastTelemetryDate = GetLastTelemetryDate(entity.Id);
//dto.Companies = GetCompanies(entity.Id);
if (dto.Timezone is null)
entity.Timezone = GetTimezone(dto.Id).Adapt<SimpleTimezone>();
return entity;
}
protected override WellDto Convert(Well entity)
{
if (entity is null)
return null;
var dto = base.Convert(entity);
if (entity.Timezone is null)
dto.Timezone = GetTimezone(entity);
dto.WellType = entity.WellType?.Caption;
dto.Cluster = entity.Cluster?.Caption;
dto.Deposit = entity.Cluster?.Deposit?.Caption;
@ -206,25 +211,105 @@ namespace AsbCloudInfrastructure.Services
return dto;
}
public DateTimeOffset DateToUtc(int idWell, DateTime date)
public void EnshureTimezonesIsSet()
{
var GetTimeZoneOffset(int idWell)
var wells = Cache.Where(w => w.Timezone is null).ToList();
foreach (var well in wells)
well.Timezone = GetTimezone(well).Adapt<SimpleTimezone>();
var wellsWithTz = wells.Where(w => w.Timezone is not null);
if (wellsWithTz.Any())
{
var adaptedWells = wellsWithTz.Adapt<WellDto>().Select(Convert);
Cache.Upsert(adaptedWells);
}
}
public DateTime DateToTimeZone(DateTimeOffset date, double remoteTimezoneOffsetHours);
public double? GetTimeZoneOffset(int idWell)
public SimpleTimezoneDto GetTimezone(int idWell)
{
// TODO: Add timeZoneOffset into Db.Well.
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
if (idTelemetry is not null)
var well = Cache.FirstOrDefault(c => c.Id == idWell);
if (well == null)
throw new ArgumentException($"idWell: {idWell} does not exist.", nameof(idWell));
return GetTimezone(well);
}
private SimpleTimezoneDto GetTimezone(Well well)
{
if (well == null)
throw new ArgumentNullException(nameof(well));
if (well.Timezone is not null)
return well.Timezone.Adapt<SimpleTimezoneDto>();
if (well.Telemetry is not null)
{
var timeZoneOffset = telemetryService.GetTimeZoneOffset((int)idTelemetry);
if (timeZoneOffset is not null)
return timeZoneOffset;
var timezone = telemetryService.GetTimezone(well.Telemetry.Id);
if (timezone is not null)
{
well.Timezone = timezone.Adapt<SimpleTimezone>();
return timezone;
}
}
Trace.WriteLine("No timeZoneOffset");
return null;
var point = GetCoordinates(well);
if (point is not null)
{
if (point.Timezone is not null)
{
well.Timezone = point.Timezone;
return point.Timezone.Adapt<SimpleTimezoneDto>();
}
if (point.Latitude is not null & point.Longitude is not null)
{
var timezone = timezoneService.GetByCoordinates((double)point.Latitude, (double)point.Longitude);
if (timezone is not null)
{
well.Timezone = timezone.Adapt<SimpleTimezone>();
return timezone;
}
}
}
throw new Exception($"Can't find timezone for well {well.Caption} id: {well.Id}");
}
private static AsbCloudDb.Model.IMapPoint GetCoordinates(Well well)
{
if(well is null)
throw new ArgumentNullException(nameof(well));
if (well.Latitude is not null & well.Longitude is not null)
return well;
if (well.Cluster is null)
throw new Exception($"Can't find coordinates of well {well.Caption} id: {well.Id}");
var cluster = well.Cluster;
if (cluster.Latitude is not null & cluster.Longitude is not null)
return cluster;
if (cluster.Deposit is null)
throw new Exception($"Can't find coordinates of well by cluster {cluster.Caption} id: {cluster.Id}");
var deposit = cluster.Deposit;
if (deposit.Latitude is not null & deposit.Longitude is not null)
return deposit;
throw new Exception($"Can't find coordinates of well by deposit {deposit.Caption} id: {deposit.Id}");
}
public DatesRangeDto GetDatesRange(int idWell)
{
var well = Cache.FirstOrDefault(w => w.Id == idWell);
if (well is null)
throw new Exception($"Well id: {idWell} does not exist.");
if (well.IdTelemetry is null)
throw new Exception($"Well id: {idWell} does not contain telemetry.");
return telemetryService.GetDatesRange((int)well.IdTelemetry);
}
}
}

View File

@ -13,8 +13,14 @@ namespace AsbCloudWebApi.Controllers
public AdminWellController(IWellService service)
:base(service)
{
service.Includes.Add("Telemetry");
service.Includes.Add("Telemetry");
}
[HttpPost("EnshureTimezonesIsSet")]
public IActionResult EnsureTimestamps()
{
((IWellService)service).EnshureTimezonesIsSet();
return Ok();
}
}
}

View File

@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Authorization;
namespace AsbCloudWebApi.Controllers
{
/// <summary>
/// Контроллер для корридоров бурения на панели
/// Контроллер для коридоров бурения на панели
/// </summary>
[ApiController]
[Authorize]
@ -29,12 +29,12 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Возвращает все значения для корридоров бурения по id скважины
/// Возвращает все значения для коридоров бурения по id скважины
/// </summary>
/// <param name="idWell"> id скважины </param>
/// <param name="updateFrom"> Дата, с которой следует искать новые параметры </param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns> Список параметров для корридоров бурения </returns>
/// <returns> Список параметров для коридоров бурения </returns>
[HttpGet]
[Route("api/well/{idWell}/drillFlowChart")]
[ProducesResponseType(typeof(IEnumerable<DrillFlowChartDto>), (int) System.Net.HttpStatusCode.OK)]
@ -54,12 +54,12 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Возвращает все значения для корридоров бурения по uid панели
/// Возвращает все значения для коридоров бурения по uid панели
/// </summary>
/// <param name="uid"> uid панели </param>
/// <param name="updateFrom"> Дата, с которой следует искать новые параметры </param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns> Список параметров для корридоров бурения </returns>
/// <returns> Список параметров для коридоров бурения </returns>
[HttpGet]
[Route("api/telemetry/{uid}/drillFlowChart")]
[AllowAnonymous]
@ -77,10 +77,10 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Сохраняет значения для корридоров бурения
/// Сохраняет значения для коридоров бурения
/// </summary>
/// <param name="idWell"> id скважины </param>
/// <param name="drillFlowChartDto"> Параметры корридоров бурения</param>
/// <param name="drillFlowChartDto"> Параметры коридоров бурения</param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns></returns>
[HttpPost]
@ -101,10 +101,10 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Добавляет массив объектов корридоров бурения
/// Добавляет массив объектов коридоров бурения
/// </summary>
/// <param name="idWell"> id скважины </param>
/// <param name="drillFlowChartParams"> Массив объектов параметров корридоров бурения</param>
/// <param name="drillFlowChartParams"> Массив объектов параметров коридоров бурения</param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns></returns>
[HttpPost]
@ -126,10 +126,10 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Изменяет значения выбранного корридора бурения
/// Изменяет значения выбранного коридора бурения
/// </summary>
/// <param name="idWell"> id скважины </param>
/// <param name="drillFlowChart"> Параметры корридоров бурения</param>
/// <param name="drillFlowChart"> Параметры коридоров бурения</param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns></returns>
[HttpPut]
@ -151,10 +151,10 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Удаляет значения выбранного корридора бурения
/// Удаляет значения выбранного коридора бурения
/// </summary>
/// <param name="idWell"> id скважины </param>
/// <param name="drillFlowChartParamsId"> Id объекта корридоров бурения</param>
/// <param name="drillFlowChartParamsId"> Id объекта коридоров бурения</param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns></returns>
[HttpDelete]

View File

@ -25,7 +25,7 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Возвращает автоматически расчитанные значения для режимов бурения
/// Возвращает автоматически рассчитанные значения для режимов бурения
/// </summary>
/// <param name="idWell"> id скважины </param>
/// <param name="startDepth"> Стартовая глубина </param>

View File

@ -84,7 +84,7 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Создает метку для файла входящего в проргамму бурения
/// Создает метку для файла входящего в программу бурения
/// </summary>
/// <param name="idWell"> id скважины </param>
/// <param name="markDto">метка файла</param>
@ -109,7 +109,7 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Помечает метку у файла входящего, в проргамму бурения, как удаленную
/// Помечает метку у файла входящего, в программу бурения, как удаленную
/// </summary>
/// <param name="idWell"> id скважины </param>
/// <param name="idMark"> id метки </param>

View File

@ -31,7 +31,6 @@ namespace AsbCloudWebApi.Controllers
/// <param name="skip">для пагинации кол-во записей пропустить</param>
/// <param name="take">для пагинации кол-во записей </param>
/// <param name="searchString"> Строка поиска </param>
/// <param name="isUtc">Даты в формате UTC или часового пояса скважины</param>
/// <param name="token">Токен для отмены задачи</param>
/// <returns>список сообщений по скважине</returns>
[HttpGet]
@ -40,7 +39,6 @@ namespace AsbCloudWebApi.Controllers
[FromQuery] IEnumerable<int> categoryids = default,
DateTime begin = default, DateTime end = default,
string searchString = default,
bool isUtc = true,
CancellationToken token = default)
{
if (take > 1024)
@ -48,7 +46,7 @@ namespace AsbCloudWebApi.Controllers
var result = await messageService.GetMessagesAsync(idWell,
categoryids, begin, end, searchString,
skip, take, isUtc, token).ConfigureAwait(false);
skip, take, token).ConfigureAwait(false);
if (result is null || result.Count == 0)
return NoContent();
@ -61,13 +59,11 @@ namespace AsbCloudWebApi.Controllers
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="token">Токен для отмены задачи</param>
/// <param name="isUtc">Смена дат с UTC формата на часовой пояс скважины</param>
/// <returns>список сообщений по скважине</returns>
[HttpGet]
[Route("datesRange")]
[ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetMessagesDateRangeAsync(int idWell, bool isUtc = true,
CancellationToken token = default)
public async Task<IActionResult> GetMessagesDateRangeAsync(int idWell, CancellationToken token = default)
{
int? idCompany = User.GetCompanyId();
@ -79,9 +75,8 @@ namespace AsbCloudWebApi.Controllers
if (!isCompanyOwnsWell)
return Forbid();
var wellMessagesDatesRange = await messageService.GetMessagesDatesRangeAsync(idWell,
isUtc, token);
var wellMessagesDatesRange = wellService.GetDatesRange(idWell);
return Ok(wellMessagesDatesRange);
}

View File

@ -29,7 +29,7 @@ namespace AsbCloudWebApi.Controllers
/// <summary>
/// Формирует данные по среднему и максимальному МСП на кусту по id скважины
/// </summary>
/// <param name="idWell">id скважины с данного куста (через нее будут полуены данные)</param>
/// <param name="idWell">id скважины с данного куста (через нее будут получены данные)</param>
/// <param name="token"></param>
/// <returns>Возвращает данные по среднему и максимальному МСП на кусту</returns>
[HttpGet("well/{idWell}/ropStat")]
@ -65,13 +65,13 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Получает статстику по скважинам куста
/// Получает статистику по скважинам куста
/// </summary>
/// <param name="idCluster">id куста</param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet]
[Route("cluster/{idCluster}/stat")] // TODO: Это статистика клатера, перенести в ClusterOperationStatController
[Route("cluster/{idCluster}/stat")] // TODO: Это статистика кластера, перенести в ClusterOperationStatController
[ProducesResponseType(typeof(StatClusterDto), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetStatClusterAsync(int idCluster,
CancellationToken token = default)
@ -91,7 +91,7 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Получает статстику по списку скважин
/// Получает статистику по списку скважин
/// </summary>
/// <param name="idWells">список скважин</param>
/// <param name="token"></param>
@ -128,7 +128,7 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Получает данные для графика глубина-днь
/// Получает данные для графика глубина-день
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>

View File

@ -134,13 +134,11 @@ namespace AsbCloudWebApi.Controllers
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="token">Токен для отмены задачи</param>
/// <param name="isUtc">Смена дат с UTC формата на часовой пояс скважины</param>
/// <returns>Даты самого старого и самого свежего отчетов в БД</returns>
[HttpGet]
[Route("datesRange")]
[ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetReportsDateRangeAsync(int idWell, bool isUtc = true,
CancellationToken token = default)
public async Task<IActionResult> GetReportsDateRangeAsync(int idWell, CancellationToken token = default)
{
int? idCompany = User.GetCompanyId();
@ -150,9 +148,8 @@ namespace AsbCloudWebApi.Controllers
if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false))
return Forbid();
var wellReportsDatesRange = await reportService.GetReportsDatesRangeAsync(idWell, isUtc,
token).ConfigureAwait(false);
var wellReportsDatesRange = reportService.GetDatesRangeOrDefault(idWell);
return Ok(wellReportsDatesRange);
}

View File

@ -71,7 +71,7 @@ namespace AsbCloudWebApi.Controllers
return BadRequest("Wrong ObsolescenceSec");
if (!setpoints.Setpoints.Any())
return BadRequest("Wrong Setpoints count");
return BadRequest("Wrong setpoints count");
var result = await setpointsService.InsertAsync(setpoints, token)
.ConfigureAwait(false);
@ -107,7 +107,7 @@ namespace AsbCloudWebApi.Controllers
/// </summary>
/// <param name="uid"></param>
/// <param name="id"></param>
/// <param name="setpointsRequestDto">можно передать только новый state eg.: {state:3} - принято</param>
/// <param name="setpointsRequestDto">можно передать только новый state ex.: {state:3} - принято</param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPut("api/telemetry/{uid}/setpoints/{id}")]

View File

@ -176,13 +176,11 @@ namespace AsbCloudWebApi.Controllers
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="token">Токен для отмены задачи</param>
/// <param name="isUtc">Смена дат с UTC формата на часовой пояс скважины</param>
/// <returns>Даты самой первой и самой последней операций на скважине</returns>
[HttpGet]
[Route("datesRange")]
[ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetOperationsDateRangeAsync(int idWell, bool isUtc = true,
CancellationToken token = default)
public async Task<IActionResult> GetOperationsDateRangeAsync(int idWell, CancellationToken token = default)
{
int? idCompany = User.GetCompanyId();
@ -193,8 +191,7 @@ namespace AsbCloudWebApi.Controllers
idWell, token).ConfigureAwait(false))
return Forbid();
var wellOperationsDatesRange = await analyticsService.GetOperationsDateRangeAsync(idWell,
isUtc, token).ConfigureAwait(false);
var wellOperationsDatesRange = await analyticsService.GetOperationsDateRangeAsync(idWell, token).ConfigureAwait(false);
return Ok(wellOperationsDatesRange);
}

View File

@ -58,15 +58,15 @@ namespace AsbCloudWebApi.Controllers
/// Обновляет часовой пояс скважины
/// </summary>
/// <param name="uid">Уникальный идентификатор отправителя</param>
/// <param name="timeZoneInfo">Информация о часовом поясе</param>
/// <param name="timezone">Информация о часовом поясе</param>
/// <param name="token">Токен отмены задачи</param>
/// <returns></returns>
[HttpPost]
[Route("{uid}/timeZone")]
public async Task<IActionResult> UpdateTimeZoneAsync(string uid, TelemetryTimeZoneDto timeZoneInfo,
[Route("{uid}/timezone")]
public async Task<IActionResult> UpdateTimeZoneAsync(string uid, SimpleTimezoneDto timezone,
CancellationToken token = default)
{
await telemetryService.UpdateTimeZoneAsync(uid, timeZoneInfo, token)
await telemetryService.UpdateTimezoneAsync(uid, timezone, token)
.ConfigureAwait(false);
return Ok();
}

View File

@ -68,12 +68,11 @@ namespace AsbCloudWebApi.Controllers
/// <param name="begin">дата начала выборки. По умолчанию: текущее время - intervalSec</param>
/// <param name="intervalSec">интервал времени даты начала выборки, секунды</param>
/// <param name="approxPointsCount">желаемое количество точек. Если в выборке точек будет больше, то выборка будет прорежена.</param>
/// <param name="isUtc">Даты в формате UTC или часового пояса скважины</param>
/// <param name="token">Токен завершения задачи</param>
/// <returns></returns>
[HttpGet("{idWell}")]
public virtual async Task<ActionResult<TDto>> GetDataAsync(int idWell, DateTime begin = default,
int intervalSec = 600, int approxPointsCount = 1024, bool isUtc = false, CancellationToken token = default)
int intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default)
{
int? idCompany = User.GetCompanyId();
@ -87,7 +86,7 @@ namespace AsbCloudWebApi.Controllers
return Forbid();
var content = await telemetryDataService.GetAsync(idWell, begin,
intervalSec, approxPointsCount, isUtc, token).ConfigureAwait(false);
intervalSec, approxPointsCount, token).ConfigureAwait(false);
return Ok(content);
}
@ -96,13 +95,12 @@ namespace AsbCloudWebApi.Controllers
/// Возвращает диапазон дат сохраненных данных.
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="isUtc">Смена дат с UTC формата на часовой пояс скважины</param>
/// <param name="token">Токен завершения задачи</param>
/// <returns></returns>
[HttpGet]
[Route("{idWell}/datesRange")]
[ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)]
public virtual async Task<IActionResult> GetDataDatesRangeAsync(int idWell, bool isUtc = false,
public virtual async Task<IActionResult> GetDataDatesRangeAsync(int idWell,
CancellationToken token = default)
{
int? idCompany = User.GetCompanyId();
@ -116,8 +114,7 @@ namespace AsbCloudWebApi.Controllers
if (!isCompanyOwnsWell)
return Forbid();
var dataDatesRange = await telemetryDataService.GetDataDatesRangeAsync(idWell, isUtc,
token).ConfigureAwait(false);
var dataDatesRange = wellService.GetDatesRange(idWell);
return Ok(dataDatesRange);
}

View File

@ -52,7 +52,7 @@ namespace AsbCloudWebApi.Controllers
/// <param name="idWell"> Id требуемой скважины </param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns>Информация о требуемой скважине </returns>
[HttpGet("getWell")]
[HttpGet("{idWell}")]
[ProducesResponseType(typeof(WellDto), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetAsync(int idWell, CancellationToken token = default)
{
@ -76,7 +76,7 @@ namespace AsbCloudWebApi.Controllers
/// State: 0 - Неизвестно, 1 - В работе, 2 - Завершена.</param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns></returns>
[HttpPut]
[HttpPut("{idWell}")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> UpdateWellAsync(int idWell, WellDto dto,
CancellationToken token = default)

View File

@ -2,7 +2,7 @@
https://www.geonames.org/commercial-webservices.html
# учетная запись для аутентификации на сайте
Имя пользователя: asbautodrilling
Имя пользователя: asbautodrilling
Пароль: asbautodrilling1!
# имя пользователя для запросов

View File

@ -2,33 +2,15 @@
Скважины и пользователи ЕЦП расположены на различных часовых поясах.
В БД время хранится только в UTC.
На страницах ЕЦП время везде должно отображаться в часовом поясе скважины.
Web Api должен понимать при обращении время как в UTC `2021-12-29T07:00:00Z`, так и с указанием часового пояса `2021-12-29T12:00:00Z5`.
Web Api должен понимать при обращении время как в UTC `2021-12-29T07:00:00Z`, так и с указанием часового пояса `2021-12-29T12:00:00+05`.
## Решение
В БД уже хранится часовой пояс скважины в таблице телеметрии.
На стороне backEnd публичные методы контроллеров и методы сервисов, которые вызываются из контроллеров должны понимать параметры времени как тип DateTime, затем приводить его к UTC.
Если DateTime.Kind == unspecified, то считается что это время указанное в часовом поясе скважины.
На стороне backEnd публичные методы контроллеров и методы сервисов,
которые вызываются из контроллеров должны понимать параметры времени как тип DateTime, затем приводить его к UTC.
Если DateTime.Kind == unspecified, то считается что *это время указанное в часовом поясе скважины*.
При переходе на DateTimeOffset флаги isUTC не нужны
Даты в Model - используют DateTimeOffset.
Даты в Dto - используют DateTime без указания часового пояса во времени скважины.
При получении Dto от фронта с kind == unspecified дата приводится к UTC как будто она в часовом поясе скважины.
Перед отправкой клиенту в Dto все даты приводятся к часовому поясу скважины и kind устанавливается как unspecified.
## Affected
ReportController
.CreateReportAsync
.GetReportSizeAsync
.GetReportsDateRangeAsync
TelemetryDataBaseController
.GetDataAsync
.GetDataDatesRangeAsync
MessageController
.GetMessagesAsync
.GetMessagesDateRangeAsync
WellOperationController
.GetOperationsAsync
.InsertRangeAsync
.UpdateAsync

View File

@ -1,3 +1,4 @@
using AsbCloudApp.Services;
using AsbCloudInfrastructure;
using AsbCloudWebApi.Middlewares;
using AsbCloudWebApi.SignalR;
@ -11,13 +12,12 @@ namespace AsbCloudWebApi
{
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
@ -61,6 +61,7 @@ namespace AsbCloudWebApi
.AllowCredentials();
});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

View File

@ -9,7 +9,7 @@
- мониторинг активно передающих скважин
- доделать секционирование.
- редуцирование архива телеметрии по принципу второй производной. Если вторая производная ~0, то промежуточные значения можно удалить.
- редуцирование выборки в контроллере. слишком большую выборку попробовать уменьшать оконными функиями, сохранять экстремумы и ближайшие к ним значения.
- редуцирование выборки в контроллере. слишком большую выборку попробовать уменьшать оконными функциями, сохранять экстремумы и ближайшие к ним значения.
* Выполненные задачи *

View File

@ -1,40 +1,40 @@
{
"files": {
"main.css": "/static/css/main.dd1fcee2.chunk.css",
"main.js": "/static/js/main.b9f2543d.chunk.js",
"main.js.map": "/static/js/main.b9f2543d.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.e4d23dc4.js",
"runtime-main.js.map": "/static/js/runtime-main.e4d23dc4.js.map",
"static/js/2.c978f7e7.chunk.js": "/static/js/2.c978f7e7.chunk.js",
"static/js/2.c978f7e7.chunk.js.map": "/static/js/2.c978f7e7.chunk.js.map",
"static/js/3.6446ff6d.chunk.js": "/static/js/3.6446ff6d.chunk.js",
"static/js/3.6446ff6d.chunk.js.map": "/static/js/3.6446ff6d.chunk.js.map",
"static/js/4.eb6dbaeb.chunk.js": "/static/js/4.eb6dbaeb.chunk.js",
"static/js/4.eb6dbaeb.chunk.js.map": "/static/js/4.eb6dbaeb.chunk.js.map",
"static/js/5.7a9fb752.chunk.js": "/static/js/5.7a9fb752.chunk.js",
"static/js/5.7a9fb752.chunk.js.map": "/static/js/5.7a9fb752.chunk.js.map",
"static/js/6.61991758.chunk.js": "/static/js/6.61991758.chunk.js",
"static/js/6.61991758.chunk.js.map": "/static/js/6.61991758.chunk.js.map",
"static/js/7.a1c2547f.chunk.js": "/static/js/7.a1c2547f.chunk.js",
"static/js/7.a1c2547f.chunk.js.map": "/static/js/7.a1c2547f.chunk.js.map",
"static/js/8.2a766587.chunk.js": "/static/js/8.2a766587.chunk.js",
"static/js/8.2a766587.chunk.js.map": "/static/js/8.2a766587.chunk.js.map",
"static/js/9.6ba456d9.chunk.js": "/static/js/9.6ba456d9.chunk.js",
"static/js/9.6ba456d9.chunk.js.map": "/static/js/9.6ba456d9.chunk.js.map",
"static/js/10.f5187699.chunk.js": "/static/js/10.f5187699.chunk.js",
"static/js/10.f5187699.chunk.js.map": "/static/js/10.f5187699.chunk.js.map",
"static/js/11.37e8bbc7.chunk.js": "/static/js/11.37e8bbc7.chunk.js",
"static/js/11.37e8bbc7.chunk.js.map": "/static/js/11.37e8bbc7.chunk.js.map",
"main.css": "/static/css/main.9cfe6b31.chunk.css",
"main.js": "/static/js/main.6c26ed34.chunk.js",
"main.js.map": "/static/js/main.6c26ed34.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.33aef657.js",
"runtime-main.js.map": "/static/js/runtime-main.33aef657.js.map",
"static/js/2.968888d9.chunk.js": "/static/js/2.968888d9.chunk.js",
"static/js/2.968888d9.chunk.js.map": "/static/js/2.968888d9.chunk.js.map",
"static/js/3.d96a3708.chunk.js": "/static/js/3.d96a3708.chunk.js",
"static/js/3.d96a3708.chunk.js.map": "/static/js/3.d96a3708.chunk.js.map",
"static/js/4.a0d32a2c.chunk.js": "/static/js/4.a0d32a2c.chunk.js",
"static/js/4.a0d32a2c.chunk.js.map": "/static/js/4.a0d32a2c.chunk.js.map",
"static/js/5.8306e86d.chunk.js": "/static/js/5.8306e86d.chunk.js",
"static/js/5.8306e86d.chunk.js.map": "/static/js/5.8306e86d.chunk.js.map",
"static/js/6.642e7ca1.chunk.js": "/static/js/6.642e7ca1.chunk.js",
"static/js/6.642e7ca1.chunk.js.map": "/static/js/6.642e7ca1.chunk.js.map",
"static/js/7.d412fe5e.chunk.js": "/static/js/7.d412fe5e.chunk.js",
"static/js/7.d412fe5e.chunk.js.map": "/static/js/7.d412fe5e.chunk.js.map",
"static/js/8.0292b3ca.chunk.js": "/static/js/8.0292b3ca.chunk.js",
"static/js/8.0292b3ca.chunk.js.map": "/static/js/8.0292b3ca.chunk.js.map",
"static/js/9.35059bd2.chunk.js": "/static/js/9.35059bd2.chunk.js",
"static/js/9.35059bd2.chunk.js.map": "/static/js/9.35059bd2.chunk.js.map",
"static/js/10.de99360f.chunk.js": "/static/js/10.de99360f.chunk.js",
"static/js/10.de99360f.chunk.js.map": "/static/js/10.de99360f.chunk.js.map",
"static/js/11.8f392911.chunk.js": "/static/js/11.8f392911.chunk.js",
"static/js/11.8f392911.chunk.js.map": "/static/js/11.8f392911.chunk.js.map",
"index.html": "/index.html",
"static/css/main.dd1fcee2.chunk.css.map": "/static/css/main.dd1fcee2.chunk.css.map",
"static/js/2.c978f7e7.chunk.js.LICENSE.txt": "/static/js/2.c978f7e7.chunk.js.LICENSE.txt",
"static/css/main.9cfe6b31.chunk.css.map": "/static/css/main.9cfe6b31.chunk.css.map",
"static/js/2.968888d9.chunk.js.LICENSE.txt": "/static/js/2.968888d9.chunk.js.LICENSE.txt",
"static/media/ClusterIcon.a395f860.svg": "/static/media/ClusterIcon.a395f860.svg",
"static/media/DepositIcon.6de7c7ae.svg": "/static/media/DepositIcon.6de7c7ae.svg"
},
"entrypoints": [
"static/js/runtime-main.e4d23dc4.js",
"static/js/2.c978f7e7.chunk.js",
"static/css/main.dd1fcee2.chunk.css",
"static/js/main.b9f2543d.chunk.js"
"static/js/runtime-main.33aef657.js",
"static/js/2.968888d9.chunk.js",
"static/css/main.9cfe6b31.chunk.css",
"static/js/main.6c26ed34.chunk.js"
]
}

View File

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="manifest" href="/manifest.json"/><title>АСБ Vision</title><link href="/static/css/main.dd1fcee2.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,u,i=r[0],c=r[1],f=r[2],s=0,p=[];s<i.length;s++)u=i[s],Object.prototype.hasOwnProperty.call(o,u)&&o[u]&&p.push(o[u][0]),o[u]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);p.length;)p.shift()();return a.push.apply(a,f||[]),t()}function t(){for(var e,r=0;r<a.length;r++){for(var t=a[r],n=!0,i=1;i<t.length;i++){var c=t[i];0!==o[c]&&(n=!1)}n&&(a.splice(r--,1),e=u(u.s=t[0]))}return e}var n={},o={1:0},a=[];function u(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,u),t.l=!0,t.exports}u.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var a,i=document.createElement("script");i.charset="utf-8",i.timeout=120,u.nc&&i.setAttribute("nonce",u.nc),i.src=function(e){return u.p+"static/js/"+({}[e]||e)+"."+{3:"6446ff6d",4:"eb6dbaeb",5:"7a9fb752",6:"61991758",7:"a1c2547f",8:"2a766587",9:"6ba456d9",10:"f5187699",11:"37e8bbc7"}[e]+".chunk.js"}(e);var c=new Error;a=function(r){i.onerror=i.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),a=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+a+")",c.name="ChunkLoadError",c.type=n,c.request=a,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){a({type:"timeout",target:i})}),12e4);i.onerror=i.onload=a,document.head.appendChild(i)}return Promise.all(r)},u.m=e,u.c=n,u.d=function(e,r,t){u.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},u.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,r){if(1&r&&(e=u(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(u.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)u.d(t,n,function(r){return e[r]}.bind(null,n));return t},u.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(r,"a",r),r},u.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},u.p="/",u.oe=function(e){throw console.error(e),e};var i=this.webpackJsonpasb_cloud_front_react=this.webpackJsonpasb_cloud_front_react||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var f=0;f<i.length;f++)r(i[f]);var l=c;t()}([])</script><script src="/static/js/2.c978f7e7.chunk.js"></script><script src="/static/js/main.b9f2543d.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="онлайн мониторинг процесса бурения в реальном времени в офисе заказчика"/><link rel="manifest" href="/manifest.json"/><title>АСБ Vision</title><link href="/static/css/main.9cfe6b31.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,u,c=r[0],i=r[1],f=r[2],s=0,p=[];s<c.length;s++)u=c[s],Object.prototype.hasOwnProperty.call(o,u)&&o[u]&&p.push(o[u][0]),o[u]=0;for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n]);for(l&&l(r);p.length;)p.shift()();return a.push.apply(a,f||[]),t()}function t(){for(var e,r=0;r<a.length;r++){for(var t=a[r],n=!0,c=1;c<t.length;c++){var i=t[c];0!==o[i]&&(n=!1)}n&&(a.splice(r--,1),e=u(u.s=t[0]))}return e}var n={},o={1:0},a=[];function u(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,u),t.l=!0,t.exports}u.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var a,c=document.createElement("script");c.charset="utf-8",c.timeout=120,u.nc&&c.setAttribute("nonce",u.nc),c.src=function(e){return u.p+"static/js/"+({}[e]||e)+"."+{3:"d96a3708",4:"a0d32a2c",5:"8306e86d",6:"642e7ca1",7:"d412fe5e",8:"0292b3ca",9:"35059bd2",10:"de99360f",11:"8f392911"}[e]+".chunk.js"}(e);var i=new Error;a=function(r){c.onerror=c.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),a=r&&r.target&&r.target.src;i.message="Loading chunk "+e+" failed.\n("+n+": "+a+")",i.name="ChunkLoadError",i.type=n,i.request=a,t[1](i)}o[e]=void 0}};var f=setTimeout((function(){a({type:"timeout",target:c})}),12e4);c.onerror=c.onload=a,document.head.appendChild(c)}return Promise.all(r)},u.m=e,u.c=n,u.d=function(e,r,t){u.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},u.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,r){if(1&r&&(e=u(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(u.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)u.d(t,n,function(r){return e[r]}.bind(null,n));return t},u.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(r,"a",r),r},u.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},u.p="/",u.oe=function(e){throw console.error(e),e};var c=this.webpackJsonpasb_cloud_front_react=this.webpackJsonpasb_cloud_front_react||[],i=c.push.bind(c);c.push=r,c=c.slice();for(var f=0;f<c.length;f++)r(c[f]);var l=i;t()}([])</script><script src="/static/js/2.968888d9.chunk.js"></script><script src="/static/js/main.6c26ed34.chunk.js"></script></body></html>ц

View File

@ -4,4 +4,4 @@
Есть t_telemetry для которой нет t_well | Кто-то начал новое бурение или исправил название старого
2 t_telemetry с не уникальными uid
Провалы в непрерывной t_data.
Сопоставление сущетсвующих на диске файлов-рапортов с теми, что хранятся в БД
Сопоставление существующих на диске файлов-рапортов с теми, что хранятся в БД