forked from ddrilling/AsbCloudServer
Merge branch 'dev' into SubsystemsOperationTime
This commit is contained in:
commit
24a1afb5a8
6
.gitignore
vendored
6
.gitignore
vendored
@ -174,13 +174,13 @@ publish/
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
# *.pubxml
|
||||
# *.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
# PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
|
@ -13,4 +13,16 @@
|
||||
<ItemGroup>
|
||||
<None Remove="Data\DailyReport\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EditorConfigFiles Remove="D:\Source\AsbCloudApp\Services\.editorconfig" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="D:\Source\AsbCloudApp\Services\.editorconfig" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AsbCloudDb\AsbCloudDb.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -1,5 +1,6 @@
|
||||
namespace AsbCloudApp.Data.DailyReport
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Блоки для формирования суточного рапорта
|
||||
/// </summary>
|
||||
@ -35,4 +36,5 @@
|
||||
/// </summary>
|
||||
public SignDto Sign { get; set; } = new();
|
||||
}
|
||||
#nullable disable
|
||||
}
|
||||
|
@ -13,14 +13,9 @@ namespace AsbCloudApp.Data
|
||||
public int IdWell { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ãëóáèíà íà÷àëà èíòåðâàëà äëÿ ýòèõ ïàðàìåòðîâ
|
||||
/// Ãëóáèíà èíòåðâàëà
|
||||
/// </summary>
|
||||
public double DepthStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ãëóáèíà îêîí÷àíèÿ èíòåðâàëà äëÿ ýòèõ ïàðàìåòðîâ
|
||||
/// </summary>
|
||||
public double DepthEnd { get; set; }
|
||||
public MinMaxDto<double> Depth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// id well section type.
|
||||
@ -28,78 +23,28 @@ namespace AsbCloudApp.Data
|
||||
public int IdWellSectionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// axial load min.
|
||||
/// axial load
|
||||
/// </summary>
|
||||
public double AxialLoadMin { get; set; }
|
||||
public MinMaxExtendedViewDto AxialLoad { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// axial load avg.
|
||||
/// pressure
|
||||
/// </summary>
|
||||
public double AxialLoadAvg { get; set; }
|
||||
public MinMaxExtendedViewDto Pressure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// axial load max.
|
||||
/// rotor torque
|
||||
/// </summary>
|
||||
public double AxialLoadMax { get; set; }
|
||||
public MinMaxExtendedViewDto RotorTorque { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// pressure min.
|
||||
/// rotor speed
|
||||
/// </summary>
|
||||
public double PressureMin { get; set; }
|
||||
public MinMaxExtendedViewDto RotorSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// pressure avg.
|
||||
/// flow
|
||||
/// </summary>
|
||||
public double PressureAvg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// pressure max.
|
||||
/// </summary>
|
||||
public double PressureMax { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// rotor torque min.
|
||||
/// </summary>
|
||||
public double RotorTorqueMin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// rotor torque avg.
|
||||
/// </summary>
|
||||
public double RotorTorqueAvg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// rotor torque max.
|
||||
/// </summary>
|
||||
public double RotorTorqueMax { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// rotor speed min.
|
||||
/// </summary>
|
||||
public double RotorSpeedMin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// rotor speed avg.
|
||||
/// </summary>
|
||||
public double RotorSpeedAvg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// rotor speed max.
|
||||
/// </summary>
|
||||
public double RotorSpeedMax { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// flow min.
|
||||
/// </summary>
|
||||
public double FlowMin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// flow avg.
|
||||
/// </summary>
|
||||
public double FlowAvg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// flow max.
|
||||
/// </summary>
|
||||
public double FlowMax { get; set; }
|
||||
public MinMaxExtendedViewDto Flow { get; set; }
|
||||
}
|
||||
}
|
@ -39,6 +39,11 @@ namespace AsbCloudApp.Data
|
||||
/// </summary>
|
||||
public long Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Помечен как удаленный
|
||||
/// </summary>
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DTO автора
|
||||
/// </summary>
|
||||
|
56
AsbCloudApp/Data/JobDto.cs
Normal file
56
AsbCloudApp/Data/JobDto.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace AsbCloudApp.Data
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Состояние фоновой задачи
|
||||
/// </summary>
|
||||
public enum JobState
|
||||
{
|
||||
/// <summary>
|
||||
/// Ожидает в очереди на выполнение
|
||||
/// </summary>
|
||||
Waiting,
|
||||
/// <summary>
|
||||
/// выполняется
|
||||
/// </summary>
|
||||
Working,
|
||||
/// <summary>
|
||||
/// успешно выполнена
|
||||
/// </summary>
|
||||
Done,
|
||||
/// <summary>
|
||||
/// завершена с ошибкой
|
||||
/// </summary>
|
||||
Fail
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// работа фоновой задачи
|
||||
/// </summary>
|
||||
public class JobDto
|
||||
{
|
||||
/// <summary>
|
||||
/// идентификатор
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Состояние
|
||||
/// </summary>
|
||||
public JobState State { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// результат выполнения
|
||||
/// </summary>
|
||||
public Hashtable? Results { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Исключение, если возникла ошибка
|
||||
/// </summary>
|
||||
public string? Error { get; set; }
|
||||
}
|
||||
#nullable disable
|
||||
}
|
26
AsbCloudApp/Data/MinMaxDto.cs
Normal file
26
AsbCloudApp/Data/MinMaxDto.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Data
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Минимальное и максимальное значение
|
||||
/// </summary>
|
||||
public class MinMaxDto<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Минимальное значение
|
||||
/// </summary>
|
||||
public T? Min { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Максимальное значение
|
||||
/// </summary>
|
||||
public T? Max { get; set; }
|
||||
}
|
||||
#nullable disable
|
||||
}
|
31
AsbCloudApp/Data/MinMaxExtendedViewDto.cs
Normal file
31
AsbCloudApp/Data/MinMaxExtendedViewDto.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Data
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Расширение для класса MinMaxDto
|
||||
/// </summary>
|
||||
public class MinMaxExtendedViewDto : MinMaxDto<double>
|
||||
{
|
||||
/// <summary>
|
||||
/// Среднее значение
|
||||
/// </summary>
|
||||
public double Avg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Является максимальным
|
||||
/// </summary>
|
||||
public bool IsMax { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Является минимальным
|
||||
/// </summary>
|
||||
public bool IsMin { get; set; }
|
||||
}
|
||||
#nullable disable
|
||||
}
|
@ -2,80 +2,77 @@
|
||||
|
||||
namespace AsbCloudApp.Data.SAUB
|
||||
{
|
||||
#pragma warning disable CS1591 // Отсутствует комментарий XML для открытого видимого типа или члена
|
||||
#nullable enable
|
||||
public class TelemetryDataSpinDto : ITelemetryData
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
/// <summary>
|
||||
/// Идентификатор телеметрии
|
||||
/// </summary>
|
||||
public int IdTelemetry { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата
|
||||
/// </summary>
|
||||
public DateTime DateTime { get; set; }
|
||||
public DateTime Date // TODO: remove this legacy after all panels updated
|
||||
|
||||
/// <summary>
|
||||
/// Дата
|
||||
/// </summary>
|
||||
public DateTime Date
|
||||
{
|
||||
get { return DateTime; }
|
||||
set { DateTime = value; }
|
||||
}
|
||||
public float? TopDriveSpeed { get; set; }
|
||||
public float? TopDriveSpeedMin { get; set; }
|
||||
public float? TopDriveSpeedMax { get; set; }
|
||||
public float? TopDriveSpeedOffset { get; set; }
|
||||
public short? TopDriveSpeedErr { get; set; }
|
||||
public float? TopDriveTorque { get; set; }
|
||||
public float? TopDriveTorqueMin { get; set; }
|
||||
public float? TopDriveTorqueMax { get; set; }
|
||||
public float? TopDriveTorqueOffset { get; set; }
|
||||
public short? TopDriveTorqueErr { get; set; }
|
||||
public float? TopDriveSpeedSpFrom { get; set; }
|
||||
public float? TopDriveSpeedSpFromMin { get; set; }
|
||||
public float? TopDriveSpeedSpFromMax { get; set; }
|
||||
public float? TopDriveSpeedSpFromOffset { get; set; }
|
||||
public short? TopDriveSpeedSpFromErr { get; set; }
|
||||
public float? TopDriveTorqueSpFrom { get; set; }
|
||||
public float? TopDriveTorqueSpFromMin { get; set; }
|
||||
public float? TopDriveTorqueSpFromMax { get; set; }
|
||||
public float? TopDriveTorqueSpFromOffset { get; set; }
|
||||
public short? TopDriveTorqueSpFromErr { get; set; }
|
||||
public float? TopDriveSpeedSpTo { get; set; }
|
||||
public float? TopDriveSpeedSpToMin { get; set; }
|
||||
public float? TopDriveSpeedSpToMax { get; set; }
|
||||
public float? TopDriveSpeedSpToOffset { get; set; }
|
||||
public short? TopDriveSpeedSpToErr { get; set; }
|
||||
public float? TopDriveTorqueSpTo { get; set; }
|
||||
public float? TopDriveTorqueSpToMin { get; set; }
|
||||
public float? TopDriveTorqueSpToMax { get; set; }
|
||||
public float? TopDriveTorqueSpToOffset { get; set; }
|
||||
public short? TopDriveTorqueSpToErr { get; set; }
|
||||
public short? W2800 { get; set; }
|
||||
public short? W2810 { get; set; }
|
||||
public short? Mode { get; set; }
|
||||
public short? W2808 { get; set; }
|
||||
public float? TorqueStarting { get; set; }
|
||||
public float? RotorTorqueAvg { get; set; }
|
||||
public float? EncoderResolution { get; set; }
|
||||
public float? Ratio { get; set; }
|
||||
public float? TorqueRightLimit { get; set; }
|
||||
public float? TorqueLeftLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ограничение числа оборотов вправо
|
||||
/// </summary>
|
||||
public float? RevolsRightLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ограничение числа оборотов влево
|
||||
/// </summary>
|
||||
public float? RevolsLeftLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Заданная скорость вращения вправо
|
||||
/// </summary>
|
||||
public float? SpeedRightSp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Заданная скорость вращения влево
|
||||
/// </summary>
|
||||
public float? SpeedLeftSp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Суммарное количество оборотов вправо
|
||||
/// </summary>
|
||||
public float? RevolsRightTotal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Суммарное количество оборотов влево
|
||||
/// </summary>
|
||||
public float? RevolsLeftTotal { get; set; }
|
||||
public float? TurnRightOnceByTorque { get; set; }
|
||||
public float? TurnLeftOnceByTorque { get; set; }
|
||||
public float? TurnRightOnceByAngle { get; set; }
|
||||
public float? TurnLeftOnceByAngle { get; set; }
|
||||
public float? TurnRightOnceByRevols { get; set; }
|
||||
public float? TurnLeftOnceByRevols { get; set; }
|
||||
public float? BreakAngleK { get; set; }
|
||||
public float? ReverseKTorque { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Нулевая позиция осцилляции
|
||||
/// </summary>
|
||||
public float? PositionZero { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Крайний правый угол осцилляции
|
||||
/// </summary>
|
||||
public float? PositionRight { get; set; }
|
||||
public float? TorqueRampTime { get; set; }
|
||||
public float? Ver { get; set; }
|
||||
public short? ReverseSpeedSpZeroTime { get; set; }
|
||||
public float? UnlockBySectorOut { get; set; }
|
||||
public float? PidMuxTorqueLeftLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Выбранный режим управления
|
||||
/// </summary>
|
||||
public short? Mode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Переменная этапа
|
||||
/// </summary>
|
||||
public short? State { get; set; }
|
||||
public float? BreakAngleLeft { get; set; }
|
||||
}
|
||||
#pragma warning restore CS1591 // Отсутствует комментарий XML для открытого видимого типа или члена
|
||||
#nullable disable
|
||||
}
|
||||
|
83
AsbCloudApp/Repositories/IFileRepository.cs
Normal file
83
AsbCloudApp/Repositories/IFileRepository.cs
Normal file
@ -0,0 +1,83 @@
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Services;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Repositories
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Сервис доступа к файлам
|
||||
/// </summary>
|
||||
public interface IFileRepository : ICrudService<FileInfoDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// Получение файлов по скважине
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<FileInfoDto>> GetInfosAsync(FileRequest request, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получить список файлов в контейнере
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<PaginationContainer<FileInfoDto>> GetInfosPaginatedAsync(FileRequest request, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// Пометить файл как удаленный
|
||||
/// </summary>
|
||||
/// <param name="idFile"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> MarkAsDeletedAsync(int idFile, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// удалить файлы
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<FileInfoDto>> DeleteAsync(IEnumerable<int> ids, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// получить инфо о файле по метке
|
||||
/// </summary>
|
||||
/// <param name="idMark"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<FileInfoDto> GetByMarkId(int idMark, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// добавить метку на файл
|
||||
/// </summary>
|
||||
/// <param name="fileMarkDto"></param>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Инфо о файлах
|
||||
/// </summary>
|
||||
/// <param name="idsFile"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<FileInfoDto>> GetInfoByIdsAsync(IEnumerable<int> idsFile, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// пометить метки файлов как удаленные
|
||||
/// </summary>
|
||||
/// <param name="idsMarks"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> MarkFileMarkAsDeletedAsync(IEnumerable<int> idsMarks, CancellationToken token);
|
||||
|
||||
}
|
||||
#nullable disable
|
||||
}
|
80
AsbCloudApp/Repositories/IFileStorageRepository.cs
Normal file
80
AsbCloudApp/Repositories/IFileStorageRepository.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using AsbCloudApp.Data;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Repositories
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Репозиторий хранения фалов
|
||||
/// </summary>
|
||||
public interface IFileStorageRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Получение длинны фала и проверка его наличия, если отсутствует падает исключение
|
||||
/// </summary>
|
||||
/// <param name="srcFilePath"></param>
|
||||
/// <returns></returns>
|
||||
long GetFileLength(string srcFilePath);
|
||||
|
||||
/// <summary>
|
||||
/// Перемещение файла
|
||||
/// </summary>
|
||||
/// <param name="srcFilePath"></param>
|
||||
/// <param name="filePath"></param>
|
||||
void MoveFile(string srcFilePath, string filePath);
|
||||
|
||||
/// <summary>
|
||||
/// Копирование файла
|
||||
/// </summary>
|
||||
/// <param name="filePathRec"></param>
|
||||
/// <param name="fileStreamSrc"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task SaveFileAsync(string filePathRec, Stream fileStreamSrc, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление файла
|
||||
/// </summary>
|
||||
/// <param name="filesName"></param>
|
||||
void DeleteFile(IEnumerable<string> filesName);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление всех файлов с диска о которых нет информации в базе
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idsFiles"></param>
|
||||
int DeleteFilesNotInList(int idWell, IEnumerable<int> idsFiles);
|
||||
|
||||
/// <summary>
|
||||
/// Вывод списка всех файлов из базы, для которых нет файла на диске
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="files"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<FileInfoDto> GetListFilesNotDisc(IEnumerable<FileInfoDto> files);
|
||||
|
||||
/// <summary>
|
||||
/// Получение пути к файлу
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idCategory"></param>
|
||||
/// <param name="fileFullName"></param>
|
||||
/// <param name="fileId"></param>
|
||||
/// <returns></returns>
|
||||
string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId);
|
||||
|
||||
/// <summary>
|
||||
/// Получить путь для скачивания
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idCategory"></param>
|
||||
/// <param name="idFile"></param>
|
||||
/// <param name="dotExtention"></param>
|
||||
/// <returns></returns>
|
||||
string GetUrl(int idWell, int idCategory, int idFile, string dotExtention);
|
||||
}
|
||||
#nullable disable
|
||||
}
|
50
AsbCloudApp/Requests/FileRequest.cs
Normal file
50
AsbCloudApp/Requests/FileRequest.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AsbCloudApp.Requests
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Параметры запроса для файлового сервиса
|
||||
/// </summary>
|
||||
public class FileRequest : RequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Идентификатор скважины
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int IdWell { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор категории файла
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int? IdCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Наименование компании
|
||||
/// </summary>
|
||||
public string? CompanyNamePart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Имя файла
|
||||
/// </summary>
|
||||
public string? FileNamePart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата начала периода
|
||||
/// </summary>
|
||||
public DateTime? Begin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата окончания периода
|
||||
/// </summary>
|
||||
public DateTime? End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Признак удаления
|
||||
/// </summary>
|
||||
public bool? IsDeleted { get; set; }
|
||||
}
|
||||
#nullable disable
|
||||
}
|
312
AsbCloudApp/Services/FileService.cs
Normal file
312
AsbCloudApp/Services/FileService.cs
Normal file
@ -0,0 +1,312 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Services
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Сервис доступа к файлам
|
||||
/// </summary>
|
||||
public class FileService
|
||||
{
|
||||
private readonly IFileRepository fileRepository;
|
||||
private readonly IFileStorageRepository fileStorageRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Сервис доступа к файлам
|
||||
/// </summary>
|
||||
/// <param name="fileRepository"></param>
|
||||
/// <param name="fileStorageRepository"></param>
|
||||
public FileService(IFileRepository fileRepository, IFileStorageRepository fileStorageRepository)
|
||||
{
|
||||
this.fileRepository = fileRepository;
|
||||
this.fileStorageRepository = fileStorageRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// переместить файл
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="idCategory"></param>
|
||||
/// <param name="destinationFileName"></param>
|
||||
/// <param name="srcFilePath"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<FileInfoDto?> MoveAsync(int idWell, int? idUser, int idCategory,
|
||||
string destinationFileName, string srcFilePath, CancellationToken token = default)
|
||||
{
|
||||
destinationFileName = Path.GetFileName(destinationFileName);
|
||||
srcFilePath = Path.GetFullPath(srcFilePath);
|
||||
var fileSize = fileStorageRepository.GetFileLength(srcFilePath);
|
||||
|
||||
//save info to db
|
||||
var dto = new FileInfoDto {
|
||||
IdWell = idWell,
|
||||
IdAuthor = idUser,
|
||||
IdCategory = idCategory,
|
||||
Name = destinationFileName,
|
||||
Size = fileSize
|
||||
};
|
||||
var fileId = await fileRepository.InsertAsync(dto, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, destinationFileName, fileId);
|
||||
fileStorageRepository.MoveFile(srcFilePath, filePath);
|
||||
|
||||
return await GetOrDefaultAsync(fileId, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сохранить файл
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="idCategory"></param>
|
||||
/// <param name="fileFullName"></param>
|
||||
/// <param name="fileStream"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<FileInfoDto?> SaveAsync(int idWell, int? idUser, int idCategory,
|
||||
string fileFullName, Stream fileStream, CancellationToken token)
|
||||
{
|
||||
//save info to db
|
||||
var dto = new FileInfoDto
|
||||
{
|
||||
IdWell = idWell,
|
||||
IdAuthor = idUser,
|
||||
IdCategory = idCategory,
|
||||
Name = Path.GetFileName(fileFullName),
|
||||
Size = fileStream.Length
|
||||
};
|
||||
|
||||
var fileId = await fileRepository.InsertAsync(dto, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
//save stream to disk
|
||||
string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, fileFullName, fileId);
|
||||
await fileStorageRepository.SaveFileAsync(filePath, fileStream, token);
|
||||
|
||||
return await GetOrDefaultAsync(fileId, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// удалить файл
|
||||
/// </summary>
|
||||
/// <param name="idFile"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> DeleteAsync(int idFile, CancellationToken token)
|
||||
=> DeleteAsync(new int[] { idFile }, token);
|
||||
|
||||
/// <summary>
|
||||
/// удалить файлы
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token)
|
||||
{
|
||||
if (ids is null || !ids.Any())
|
||||
return 0;
|
||||
|
||||
var files = await fileRepository.DeleteAsync(ids, token).ConfigureAwait(false);
|
||||
|
||||
if (files is null || !files.Any())
|
||||
return 0;
|
||||
|
||||
var filesName = files.Select(x => GetUrl(x.IdWell, x.IdCategory, x.Id, Path.GetExtension(x.Name)));
|
||||
fileStorageRepository.DeleteFile(filesName);
|
||||
|
||||
return files.Any() ? 1 : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// получить путь для скачивания
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <returns></returns>
|
||||
public string GetUrl(FileInfoDto fileInfo) =>
|
||||
GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name));
|
||||
|
||||
/// <summary>
|
||||
/// получить путь для скачивания
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idCategory"></param>
|
||||
/// <param name="idFile"></param>
|
||||
/// <param name="dotExtention"></param>
|
||||
/// <returns></returns>
|
||||
public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) =>
|
||||
fileStorageRepository.GetUrl(idWell, idCategory, idFile, dotExtention);
|
||||
|
||||
/// <summary>
|
||||
/// пометить метку файла как удаленную
|
||||
/// </summary>
|
||||
/// <param name="idMark"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> MarkFileMarkAsDeletedAsync(int idMark,
|
||||
CancellationToken token)
|
||||
=> fileRepository.MarkFileMarkAsDeletedAsync(new int[] { idMark }, token);
|
||||
|
||||
/// <summary>
|
||||
/// Инфо о файле
|
||||
/// </summary>
|
||||
/// <param name="idsFile"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IEnumerable<FileInfoDto>> GetInfoByIdsAsync(IEnumerable<int> idsFile, CancellationToken token)
|
||||
{
|
||||
var result = await fileRepository.GetInfoByIdsAsync(idsFile, token).ConfigureAwait(false);
|
||||
|
||||
foreach (var entity in result)
|
||||
{
|
||||
|
||||
var ext = Path.GetExtension(entity.Name);
|
||||
var relativePath = GetUrl(entity.IdWell, entity.IdCategory, entity.Id, ext);
|
||||
var fullPath = Path.GetFullPath(relativePath);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получить файлы определенной категории
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public Task<IEnumerable<FileInfoDto>> GetInfosAsync(FileRequest request, CancellationToken token)
|
||||
=> fileRepository.GetInfosAsync(request, token);
|
||||
|
||||
/// <summary>
|
||||
/// Получить список файлов в контейнере
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public Task<PaginationContainer<FileInfoDto>> GetInfosPaginatedAsync(FileRequest request, CancellationToken token)
|
||||
=> fileRepository.GetInfosPaginatedAsync(request, token);
|
||||
|
||||
/// <summary>
|
||||
/// Пометить файл как удаленный
|
||||
/// </summary>
|
||||
/// <param name="idFile"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> MarkAsDeletedAsync(int idFile, CancellationToken token = default)
|
||||
=> fileRepository.MarkAsDeletedAsync(idFile, token);
|
||||
|
||||
/// <summary>
|
||||
/// добавить метку на файл
|
||||
/// </summary>
|
||||
/// <param name="fileMarkDto"></param>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token)
|
||||
=> fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token);
|
||||
|
||||
/// <summary>
|
||||
/// Получить запись по id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public Task<FileInfoDto?> GetOrDefaultAsync(int id, CancellationToken token)
|
||||
=> fileRepository.GetOrDefaultAsync(id, token);
|
||||
|
||||
/// <summary>
|
||||
/// получить инфо о файле по метке
|
||||
/// </summary>
|
||||
/// <param name="idMark"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public Task<FileInfoDto> GetByMarkId(int idMark, CancellationToken token)
|
||||
=> fileRepository.GetByMarkId(idMark, token);
|
||||
|
||||
/// <summary>
|
||||
/// получить инфо о файле по метке
|
||||
/// </summary>
|
||||
/// <param name="idsMarks"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> MarkFileMarkAsDeletedAsync(IEnumerable<int> idsMarks, CancellationToken token)
|
||||
=> fileRepository.MarkFileMarkAsDeletedAsync(idsMarks, token);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление всех файлов по скважине помеченных как удаленные
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<int> DeleteFilesFromDbMarkedDeletionByIdWell(int idWell, CancellationToken token)
|
||||
{
|
||||
var files = await fileRepository.GetInfosAsync(
|
||||
new FileRequest
|
||||
{
|
||||
IdWell = idWell,
|
||||
IsDeleted = true
|
||||
},
|
||||
token);
|
||||
var result = await DeleteAsync(files.Select(x => x.Id), token);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление всех файлов с диска о которых нет информации в базе
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="token"></param>
|
||||
public async Task<int> DeleteFilesNotExistStorage(int idWell, CancellationToken token)
|
||||
{
|
||||
var files = await fileRepository.GetInfosAsync(
|
||||
new FileRequest
|
||||
{
|
||||
IdWell = idWell
|
||||
},
|
||||
token);
|
||||
var result = await Task.FromResult(fileStorageRepository.DeleteFilesNotInList(idWell, files.Select(x => x.Id)));
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вывод списка всех файлов из базы, для которых нет файла на диске
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IEnumerable<FileInfoDto>> GetListFilesNotDisc(int idWell, CancellationToken token)
|
||||
{
|
||||
var files = await fileRepository.GetInfosAsync(
|
||||
new FileRequest
|
||||
{
|
||||
IdWell = idWell
|
||||
},
|
||||
token);
|
||||
var result = fileStorageRepository.GetListFilesNotDisc(files);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получить файловый поток по идентификатору файла
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <returns></returns>
|
||||
public Stream GetFileStream(FileInfoDto fileInfo)
|
||||
{
|
||||
var relativePath = GetUrl(fileInfo);
|
||||
var fileStream = new FileStream(Path.GetFullPath(relativePath), FileMode.Open);
|
||||
|
||||
return fileStream;
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
using AsbCloudApp.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Services
|
||||
{
|
||||
//TODO: refactor IFileService
|
||||
|
||||
/// <summary>
|
||||
/// Сервис доступа к файлам
|
||||
/// </summary>
|
||||
public interface IFileService
|
||||
{
|
||||
/// <summary>
|
||||
/// Директория хранения файлов
|
||||
/// </summary>
|
||||
string RootPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Сохранить файл
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="idCategory"></param>
|
||||
/// <param name="fileFullName"></param>
|
||||
/// <param name="fileStream"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<FileInfoDto> SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// Получить список файлов в контейнере
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idCategory"></param>
|
||||
/// <param name="companyName"></param>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="begin"></param>
|
||||
/// <param name="end"></param>
|
||||
/// <param name="skip"></param>
|
||||
/// <param name="take"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<PaginationContainer<FileInfoDto>> GetInfosAsync(int idWell,
|
||||
int idCategory, string companyName = default, string fileName = default, DateTime begin = default, DateTime end = default,
|
||||
int skip = 0, int take = 32, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// Инфо о файле
|
||||
/// </summary>
|
||||
/// <param name="idFile"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<FileInfoDto> GetInfoAsync(int idFile,
|
||||
CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Пометить файл как удаленный
|
||||
/// </summary>
|
||||
/// <param name="idFile"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> MarkAsDeletedAsync(int idFile,
|
||||
CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// Получить файлы определенной категории
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idCategory"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<FileInfoDto>> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// удалить файл
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> DeleteAsync(int id, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// удалить файлы
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// получить путь для скачивания
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <returns></returns>
|
||||
string GetUrl(FileInfoDto fileInfo);
|
||||
|
||||
/// <summary>
|
||||
/// получить путь для скачивания
|
||||
/// </summary>
|
||||
/// <param name="idFile"></param>
|
||||
/// <returns></returns>
|
||||
string GetUrl(int idFile);
|
||||
|
||||
/// <summary>
|
||||
/// получить путь для скачивания
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idCategory"></param>
|
||||
/// <param name="idFile"></param>
|
||||
/// <param name="dotExtention"></param>
|
||||
/// <returns></returns>
|
||||
string GetUrl(int idWell, int idCategory, int idFile, string dotExtention);
|
||||
|
||||
/// <summary>
|
||||
/// добавить метку на файл
|
||||
/// </summary>
|
||||
/// <param name="fileMarkDto"></param>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// пометить метку файла как удаленную
|
||||
/// </summary>
|
||||
/// <param name="idMark"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// переместить файл
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="idCategory"></param>
|
||||
/// <param name="destinationFileName"></param>
|
||||
/// <param name="srcFileFullName"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<FileInfoDto> MoveAsync(int idWell, int? idUser, int idCategory, string destinationFileName, string srcFileFullName, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// получить инфо о файле по метке
|
||||
/// </summary>
|
||||
/// <param name="idMark"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<FileInfoDto> GetByMarkId(int idMark, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// пометить метки файлов как удаленные
|
||||
/// </summary>
|
||||
/// <param name="idsMarks"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> MarkFileMarkAsDeletedAsync(IEnumerable<int> idsMarks, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Инфо о файле
|
||||
/// </summary>
|
||||
/// <param name="idsFile"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<FileInfoDto>> GetInfoByIdsAsync(List<int> idsFile, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получение файлов по скважине
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<FileInfoDto>> GetInfosByWellIdAsync(int idWell, CancellationToken token);
|
||||
}
|
||||
}
|
43
AsbCloudApp/Services/IReduceSamplingService.cs
Normal file
43
AsbCloudApp/Services/IReduceSamplingService.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using AsbCloudApp.Data;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AsbCloudApp.Services
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Делегат обновления состояния задачи
|
||||
/// </summary>
|
||||
/// <param name="job"></param>
|
||||
public delegate void OnJobProgressDelagate(JobDto job);
|
||||
|
||||
/// <summary>
|
||||
/// Сервис прореживания архива БД.
|
||||
/// Удаляет часть телеметрии.
|
||||
/// Понижает частоту записей в БД с 1 запись за 1 сек до 1 запись за N сек.
|
||||
/// </summary>
|
||||
public interface IReduceSamplingService
|
||||
{
|
||||
/// <summary>
|
||||
/// Получить все задания. Задания удаляются минимум через 10 сек после выполнения, возможно позднее.
|
||||
/// </summary>
|
||||
/// <returns>Enumerable of JobDto or empty</returns>
|
||||
IEnumerable<JobDto> GetJobs();
|
||||
|
||||
/// <summary>
|
||||
/// Получить состояние определенной задачи
|
||||
/// </summary>
|
||||
/// <param name="idTelemetry"></param>
|
||||
/// <returns></returns>
|
||||
JobDto? GetOrDefaultState(int idTelemetry);
|
||||
|
||||
/// <summary>
|
||||
/// Создать задачу прореживанию архива и добавить её в очередь на выполнение
|
||||
/// </summary>
|
||||
/// <param name="idTelemetry">телеметрия для прореживания</param>
|
||||
/// <param name="onProgress">колбек процесса выполнения</param>
|
||||
/// <param name="jobDto">созданная задача или задача из очереди</param>
|
||||
/// <returns>задача добавлена == true</returns>
|
||||
bool TryEnqueueRediceSamplingJob(int idTelemetry, OnJobProgressDelagate onProgress, out JobDto jobDto);
|
||||
}
|
||||
#nullable disable
|
||||
}
|
@ -69,6 +69,15 @@ namespace AsbCloudDb
|
||||
return database.ExecuteSqlRawAsync(query, token);
|
||||
}
|
||||
|
||||
public static Task<int> ExecInsertAsync<T>(this Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade database, DbSet<T> dbSet, IEnumerable<T> items, CancellationToken token)
|
||||
where T : class
|
||||
{
|
||||
var factory = GetQueryStringFactory(dbSet);
|
||||
var query = factory.MakeInsertSql(items);
|
||||
|
||||
return database.ExecuteSqlRawAsync(query, token);
|
||||
}
|
||||
|
||||
public static string GetTableName<T>(this DbSet<T> dbSet)
|
||||
where T : class
|
||||
{
|
||||
@ -108,6 +117,17 @@ namespace AsbCloudDb
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
public static IQueryable<T> SkipTake<T>(this IQueryable<T> query, int? skip, int? take)
|
||||
{
|
||||
if (skip > 0)
|
||||
query = query.Skip((int)skip);
|
||||
|
||||
if (take > 0)
|
||||
query = query.Take((int)take);
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
interface IQueryStringFactory { }
|
||||
@ -154,6 +174,14 @@ namespace AsbCloudDb
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public string MakeInsertSql(IEnumerable<T> items)
|
||||
{
|
||||
var builder = new StringBuilder(insertHeader, 7);
|
||||
BuildRows(builder, items);
|
||||
builder.Append(';');
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private StringBuilder BuildRows(StringBuilder builder, IEnumerable<T> items)
|
||||
{
|
||||
var list = items.ToList();
|
||||
|
6543
AsbCloudDb/Migrations/20221013040242_Delete_colums_table_t_telemetry_data_spin.Designer.cs
generated
Normal file
6543
AsbCloudDb/Migrations/20221013040242_Delete_colums_table_t_telemetry_data_spin.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,577 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Delete_colums_table_t_telemetry_data_spin : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "break_angle_k",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "break_angle_left",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "encoder_resolution",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "pid_mux_torque_left_limit",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ratio",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "reverse_k_torque",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "reverse_speed_sp_zero_time",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "rotor_torque_avg",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_err",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_max",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_min",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_offset",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_sp_from",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_sp_from_err",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_sp_from_max",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_sp_from_min",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_sp_from_offset",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_sp_to",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_sp_to_err",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_sp_to_max",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_sp_to_min",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_speed_sp_to_offset",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_err",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_max",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_min",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_offset",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_sp_from",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_sp_from_err",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_sp_from_max",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_sp_from_min",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_sp_from_offset",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_sp_to",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_sp_to_err",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_sp_to_max",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_sp_to_min",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "top_drive_torque_sp_to_offset",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "torque_left_limit",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "torque_ramp_time",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "torque_right_limit",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "torque_starting",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "turn_left_once_by_angle",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "turn_left_once_by_revols",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "turn_left_once_by_torque",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "turn_right_once_by_angle",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "turn_right_once_by_revols",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "turn_right_once_by_torque",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "unlock_by_sector_out",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ver",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "w2800",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "w2808",
|
||||
table: "t_telemetry_data_spin");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "w2810",
|
||||
table: "t_telemetry_data_spin");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "break_angle_k",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Коэффициент для расчёта за какой угол нужно тормозить");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "break_angle_left",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Угол торможения влево при работе по моменту");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "encoder_resolution",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Разрешение энкодера");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "pid_mux_torque_left_limit",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: " Момент при котором определяется ехать назад по моменту или по скорости");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "ratio",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: " Коэффициент редукции редуктора");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "reverse_k_torque",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Коэффициент на который умножается момент, для того чтобы система поняла что мы движемся в обратную сторону");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "reverse_speed_sp_zero_time",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "smallint",
|
||||
nullable: true,
|
||||
comment: "Время выдачи сигнала нулевой скорости на при смене направления");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "rotor_torque_avg",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Момент в роторе средний");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Скорость СВП");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "top_drive_speed_err",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_max",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "верхний предел");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_min",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "нижний предел");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_offset",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "смещение");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_sp_from",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Заданная скорость c СВП");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "top_drive_speed_sp_from_err",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_sp_from_max",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_sp_from_min",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_sp_from_offset",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_sp_to",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Задание скорости на СВП");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "top_drive_speed_sp_to_err",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_sp_to_max",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_sp_to_min",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_speed_sp_to_offset",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Момент СВП");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "top_drive_torque_err",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_max",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_min",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_offset",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_sp_from",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Заданный момент c СВП");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "top_drive_torque_sp_from_err",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_sp_from_max",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_sp_from_min",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_sp_from_offset",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_sp_to",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Задание момента на СВП");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "top_drive_torque_sp_to_err",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_sp_to_max",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_sp_to_min",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "top_drive_torque_sp_to_offset",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "torque_left_limit",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Ограничение крутящего момента влево");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "torque_ramp_time",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Время нарастания момента");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "torque_right_limit",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Ограничение крутящего момента вправо");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "torque_starting",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Страгивающий момент");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "turn_left_once_by_angle",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Доворот по градусам единожды влево");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "turn_left_once_by_revols",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Доворот по оборотам единожды влево");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "turn_left_once_by_torque",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Доворот по моменту единожды влево");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "turn_right_once_by_angle",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Доворот по градусам единожды вправо");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "turn_right_once_by_revols",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Доворот по оборотам единожды вправо");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "turn_right_once_by_torque",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Доворот по моменту единожды вправо");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "unlock_by_sector_out",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: " Градус отклонения от сектора для автоматического сброса блокировки");
|
||||
|
||||
migrationBuilder.AddColumn<float>(
|
||||
name: "ver",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "real",
|
||||
nullable: true,
|
||||
comment: "Версия ПО ПЛК");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "w2800",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "smallint",
|
||||
nullable: true,
|
||||
comment: "Установка нуля энкодера");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "w2808",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "smallint",
|
||||
nullable: true,
|
||||
comment: "Неисправность энкодера");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "w2810",
|
||||
table: "t_telemetry_data_spin",
|
||||
type: "smallint",
|
||||
nullable: true,
|
||||
comment: " автоматический сброс блокировки");
|
||||
}
|
||||
}
|
||||
}
|
@ -3435,31 +3435,11 @@ namespace AsbCloudDb.Migrations
|
||||
.HasColumnName("date")
|
||||
.HasComment("'2021-10-19 18:23:54+05'");
|
||||
|
||||
b.Property<float?>("BreakAngleK")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("break_angle_k")
|
||||
.HasComment("Коэффициент для расчёта за какой угол нужно тормозить");
|
||||
|
||||
b.Property<float?>("BreakAngleLeft")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("break_angle_left")
|
||||
.HasComment("Угол торможения влево при работе по моменту");
|
||||
|
||||
b.Property<float?>("EncoderResolution")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("encoder_resolution")
|
||||
.HasComment("Разрешение энкодера");
|
||||
|
||||
b.Property<short?>("Mode")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("mode")
|
||||
.HasComment("Выбранный режим управления");
|
||||
|
||||
b.Property<float?>("PidMuxTorqueLeftLimit")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("pid_mux_torque_left_limit")
|
||||
.HasComment(" Момент при котором определяется ехать назад по моменту или по скорости");
|
||||
|
||||
b.Property<float?>("PositionRight")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("position_right")
|
||||
@ -3470,21 +3450,6 @@ namespace AsbCloudDb.Migrations
|
||||
.HasColumnName("position_zero")
|
||||
.HasComment("Нулевая позиция осцилляции");
|
||||
|
||||
b.Property<float?>("Ratio")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("ratio")
|
||||
.HasComment(" Коэффициент редукции редуктора");
|
||||
|
||||
b.Property<float?>("ReverseKTorque")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("reverse_k_torque")
|
||||
.HasComment("Коэффициент на который умножается момент, для того чтобы система поняла что мы движемся в обратную сторону");
|
||||
|
||||
b.Property<short?>("ReverseSpeedSpZeroTime")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("reverse_speed_sp_zero_time")
|
||||
.HasComment("Время выдачи сигнала нулевой скорости на при смене направления");
|
||||
|
||||
b.Property<float?>("RevolsLeftLimit")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("revols_left_limit")
|
||||
@ -3505,11 +3470,6 @@ namespace AsbCloudDb.Migrations
|
||||
.HasColumnName("revols_right_total")
|
||||
.HasComment("Суммарное количество оборотов вправо");
|
||||
|
||||
b.Property<float?>("RotorTorqueAvg")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("rotor_torque_avg")
|
||||
.HasComment("Момент в роторе средний");
|
||||
|
||||
b.Property<float?>("SpeedLeftSp")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("speed_left_sp")
|
||||
@ -3525,210 +3485,6 @@ namespace AsbCloudDb.Migrations
|
||||
.HasColumnName("state")
|
||||
.HasComment("Переменная этапа");
|
||||
|
||||
b.Property<float?>("TopDriveSpeed")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed")
|
||||
.HasComment("Скорость СВП");
|
||||
|
||||
b.Property<short?>("TopDriveSpeedErr")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("top_drive_speed_err");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedMax")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_max")
|
||||
.HasComment("верхний предел");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedMin")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_min")
|
||||
.HasComment("нижний предел");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedOffset")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_offset")
|
||||
.HasComment("смещение");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedSpFrom")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_sp_from")
|
||||
.HasComment("Заданная скорость c СВП");
|
||||
|
||||
b.Property<short?>("TopDriveSpeedSpFromErr")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("top_drive_speed_sp_from_err");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedSpFromMax")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_sp_from_max");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedSpFromMin")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_sp_from_min");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedSpFromOffset")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_sp_from_offset");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedSpTo")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_sp_to")
|
||||
.HasComment("Задание скорости на СВП");
|
||||
|
||||
b.Property<short?>("TopDriveSpeedSpToErr")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("top_drive_speed_sp_to_err");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedSpToMax")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_sp_to_max");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedSpToMin")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_sp_to_min");
|
||||
|
||||
b.Property<float?>("TopDriveSpeedSpToOffset")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_speed_sp_to_offset");
|
||||
|
||||
b.Property<float?>("TopDriveTorque")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque")
|
||||
.HasComment("Момент СВП");
|
||||
|
||||
b.Property<short?>("TopDriveTorqueErr")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("top_drive_torque_err");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueMax")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_max");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueMin")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_min");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueOffset")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_offset");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueSpFrom")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_sp_from")
|
||||
.HasComment("Заданный момент c СВП");
|
||||
|
||||
b.Property<short?>("TopDriveTorqueSpFromErr")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("top_drive_torque_sp_from_err");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueSpFromMax")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_sp_from_max");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueSpFromMin")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_sp_from_min");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueSpFromOffset")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_sp_from_offset");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueSpTo")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_sp_to")
|
||||
.HasComment("Задание момента на СВП");
|
||||
|
||||
b.Property<short?>("TopDriveTorqueSpToErr")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("top_drive_torque_sp_to_err");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueSpToMax")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_sp_to_max");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueSpToMin")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_sp_to_min");
|
||||
|
||||
b.Property<float?>("TopDriveTorqueSpToOffset")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("top_drive_torque_sp_to_offset");
|
||||
|
||||
b.Property<float?>("TorqueLeftLimit")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("torque_left_limit")
|
||||
.HasComment("Ограничение крутящего момента влево");
|
||||
|
||||
b.Property<float?>("TorqueRampTime")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("torque_ramp_time")
|
||||
.HasComment("Время нарастания момента");
|
||||
|
||||
b.Property<float?>("TorqueRightLimit")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("torque_right_limit")
|
||||
.HasComment("Ограничение крутящего момента вправо");
|
||||
|
||||
b.Property<float?>("TorqueStarting")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("torque_starting")
|
||||
.HasComment("Страгивающий момент");
|
||||
|
||||
b.Property<float?>("TurnLeftOnceByAngle")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("turn_left_once_by_angle")
|
||||
.HasComment("Доворот по градусам единожды влево");
|
||||
|
||||
b.Property<float?>("TurnLeftOnceByRevols")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("turn_left_once_by_revols")
|
||||
.HasComment("Доворот по оборотам единожды влево");
|
||||
|
||||
b.Property<float?>("TurnLeftOnceByTorque")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("turn_left_once_by_torque")
|
||||
.HasComment("Доворот по моменту единожды влево");
|
||||
|
||||
b.Property<float?>("TurnRightOnceByAngle")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("turn_right_once_by_angle")
|
||||
.HasComment("Доворот по градусам единожды вправо");
|
||||
|
||||
b.Property<float?>("TurnRightOnceByRevols")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("turn_right_once_by_revols")
|
||||
.HasComment("Доворот по оборотам единожды вправо");
|
||||
|
||||
b.Property<float?>("TurnRightOnceByTorque")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("turn_right_once_by_torque")
|
||||
.HasComment("Доворот по моменту единожды вправо");
|
||||
|
||||
b.Property<float?>("UnlockBySectorOut")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("unlock_by_sector_out")
|
||||
.HasComment(" Градус отклонения от сектора для автоматического сброса блокировки");
|
||||
|
||||
b.Property<float?>("Ver")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("ver")
|
||||
.HasComment("Версия ПО ПЛК");
|
||||
|
||||
b.Property<short?>("W2800")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("w2800")
|
||||
.HasComment("Установка нуля энкодера");
|
||||
|
||||
b.Property<short?>("W2808")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("w2808")
|
||||
.HasComment("Неисправность энкодера");
|
||||
|
||||
b.Property<short?>("W2810")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("w2810")
|
||||
.HasComment(" автоматический сброс блокировки");
|
||||
|
||||
b.HasKey("IdTelemetry", "DateTime");
|
||||
|
||||
b.ToTable("t_telemetry_data_spin");
|
||||
|
@ -11,135 +11,37 @@ namespace AsbCloudDb.Model
|
||||
{
|
||||
[Column("id_telemetry")]
|
||||
public int IdTelemetry { get; set; }
|
||||
|
||||
[Column("date", TypeName = "timestamp with time zone"), Comment("'2021-10-19 18:23:54+05'")]
|
||||
public DateTimeOffset DateTime { get; set; }
|
||||
|
||||
[Column("top_drive_speed"), Comment("Скорость СВП")]
|
||||
public float? TopDriveSpeed { get; set; }
|
||||
[Column("top_drive_speed_min"), Comment("нижний предел")]
|
||||
public float? TopDriveSpeedMin { get; set; }
|
||||
[Column("top_drive_speed_max"), Comment("верхний предел")]
|
||||
public float? TopDriveSpeedMax { get; set; }
|
||||
[Column("top_drive_speed_offset"), Comment("смещение")]
|
||||
public float? TopDriveSpeedOffset { get; set; }
|
||||
[Column("top_drive_torque"), Comment("Момент СВП")]
|
||||
public float? TopDriveTorque { get; set; }
|
||||
[Column("top_drive_torque_min")]
|
||||
public float? TopDriveTorqueMin { get; set; }
|
||||
[Column("top_drive_torque_max")]
|
||||
public float? TopDriveTorqueMax { get; set; }
|
||||
[Column("top_drive_torque_offset")]
|
||||
public float? TopDriveTorqueOffset { get; set; }
|
||||
[Column("top_drive_speed_sp_from"), Comment("Заданная скорость c СВП")]
|
||||
public float? TopDriveSpeedSpFrom { get; set; }
|
||||
[Column("top_drive_speed_sp_from_min")]
|
||||
public float? TopDriveSpeedSpFromMin { get; set; }
|
||||
[Column("top_drive_speed_sp_from_max")]
|
||||
public float? TopDriveSpeedSpFromMax { get; set; }
|
||||
[Column("top_drive_speed_sp_from_offset")]
|
||||
public float? TopDriveSpeedSpFromOffset { get; set; }
|
||||
[Column("top_drive_torque_sp_from"), Comment("Заданный момент c СВП")]
|
||||
public float? TopDriveTorqueSpFrom { get; set; }
|
||||
[Column("top_drive_torque_sp_from_min")]
|
||||
public float? TopDriveTorqueSpFromMin { get; set; }
|
||||
[Column("top_drive_torque_sp_from_max")]
|
||||
public float? TopDriveTorqueSpFromMax { get; set; }
|
||||
[Column("top_drive_torque_sp_from_offset")]
|
||||
public float? TopDriveTorqueSpFromOffset { get; set; }
|
||||
[Column("top_drive_speed_sp_to"), Comment("Задание скорости на СВП")]
|
||||
public float? TopDriveSpeedSpTo { get; set; }
|
||||
[Column("top_drive_speed_sp_to_min")]
|
||||
public float? TopDriveSpeedSpToMin { get; set; }
|
||||
[Column("top_drive_speed_sp_to_max")]
|
||||
public float? TopDriveSpeedSpToMax { get; set; }
|
||||
[Column("top_drive_speed_sp_to_offset")]
|
||||
public float? TopDriveSpeedSpToOffset { get; set; }
|
||||
[Column("top_drive_torque_sp_to"), Comment("Задание момента на СВП")]
|
||||
public float? TopDriveTorqueSpTo { get; set; }
|
||||
[Column("top_drive_torque_sp_to_min")]
|
||||
public float? TopDriveTorqueSpToMin { get; set; }
|
||||
[Column("top_drive_torque_sp_to_max")]
|
||||
public float? TopDriveTorqueSpToMax { get; set; }
|
||||
[Column("top_drive_torque_sp_to_offset")]
|
||||
public float? TopDriveTorqueSpToOffset { get; set; }
|
||||
[Column("torque_starting"), Comment("Страгивающий момент")]
|
||||
public float? TorqueStarting { get; set; }
|
||||
[Column("rotor_torque_avg"), Comment("Момент в роторе средний")]
|
||||
public float? RotorTorqueAvg { get; set; }
|
||||
[Column("encoder_resolution"), Comment("Разрешение энкодера")]
|
||||
public float? EncoderResolution { get; set; }
|
||||
[Column("ratio"), Comment(" Коэффициент редукции редуктора")]
|
||||
public float? Ratio { get; set; }
|
||||
[Column("torque_right_limit"), Comment("Ограничение крутящего момента вправо")]
|
||||
public float? TorqueRightLimit { get; set; }
|
||||
[Column("torque_left_limit"), Comment("Ограничение крутящего момента влево")]
|
||||
public float? TorqueLeftLimit { get; set; }
|
||||
[Column("revols_right_limit"), Comment("Ограничение числа оборотов вправо")]
|
||||
public float? RevolsRightLimit { get; set; }
|
||||
|
||||
[Column("revols_left_limit"), Comment("Ограничение числа оборотов влево")]
|
||||
public float? RevolsLeftLimit { get; set; }
|
||||
|
||||
[Column("speed_right_sp"), Comment("Заданная скорость вращения вправо")]
|
||||
public float? SpeedRightSp { get; set; }
|
||||
|
||||
[Column("speed_left_sp"), Comment("Заданная скорость вращения влево")]
|
||||
public float? SpeedLeftSp { get; set; }
|
||||
|
||||
[Column("revols_right_total"), Comment("Суммарное количество оборотов вправо")]
|
||||
public float? RevolsRightTotal { get; set; }
|
||||
|
||||
[Column("revols_left_total"), Comment("Суммарное количество оборотов влево")]
|
||||
public float? RevolsLeftTotal { get; set; }
|
||||
[Column("turn_right_once_by_torque"), Comment("Доворот по моменту единожды вправо")]
|
||||
public float? TurnRightOnceByTorque { get; set; }
|
||||
[Column("turn_left_once_by_torque"), Comment("Доворот по моменту единожды влево")]
|
||||
public float? TurnLeftOnceByTorque { get; set; }
|
||||
[Column("turn_right_once_by_angle"), Comment("Доворот по градусам единожды вправо")]
|
||||
public float? TurnRightOnceByAngle { get; set; }
|
||||
[Column("turn_left_once_by_angle"), Comment("Доворот по градусам единожды влево")]
|
||||
public float? TurnLeftOnceByAngle { get; set; }
|
||||
[Column("turn_right_once_by_revols"), Comment("Доворот по оборотам единожды вправо")]
|
||||
public float? TurnRightOnceByRevols { get; set; }
|
||||
[Column("turn_left_once_by_revols"), Comment("Доворот по оборотам единожды влево")]
|
||||
public float? TurnLeftOnceByRevols { get; set; }
|
||||
[Column("break_angle_k"), Comment("Коэффициент для расчёта за какой угол нужно тормозить")]
|
||||
public float? BreakAngleK { get; set; }
|
||||
[Column("reverse_k_torque"), Comment("Коэффициент на который умножается момент, для того чтобы система поняла что мы движемся в обратную сторону")]
|
||||
public float? ReverseKTorque { get; set; }
|
||||
|
||||
[Column("position_zero"), Comment("Нулевая позиция осцилляции")]
|
||||
public float? PositionZero { get; set; }
|
||||
|
||||
[Column("position_right"), Comment("Крайний правый угол осцилляции")]
|
||||
public float? PositionRight { get; set; }
|
||||
[Column("torque_ramp_time"), Comment("Время нарастания момента")]
|
||||
public float? TorqueRampTime { get; set; }
|
||||
[Column("ver"), Comment("Версия ПО ПЛК")]
|
||||
public float? Ver { get; set; }
|
||||
[Column("unlock_by_sector_out"), Comment(" Градус отклонения от сектора для автоматического сброса блокировки")]
|
||||
public float? UnlockBySectorOut { get; set; }
|
||||
[Column("pid_mux_torque_left_limit"), Comment(" Момент при котором определяется ехать назад по моменту или по скорости")]
|
||||
public float? PidMuxTorqueLeftLimit { get; set; }
|
||||
|
||||
[Column("break_angle_left"), Comment("Угол торможения влево при работе по моменту")]
|
||||
public float? BreakAngleLeft { get; set; }
|
||||
|
||||
[Column("top_drive_speed_err")]
|
||||
public short? TopDriveSpeedErr { get; set; }
|
||||
[Column("top_drive_torque_err")]
|
||||
public short? TopDriveTorqueErr { get; set; }
|
||||
[Column("top_drive_speed_sp_from_err")]
|
||||
public short? TopDriveSpeedSpFromErr { get; set; }
|
||||
[Column("top_drive_torque_sp_from_err")]
|
||||
public short? TopDriveTorqueSpFromErr { get; set; }
|
||||
[Column("top_drive_speed_sp_to_err")]
|
||||
public short? TopDriveSpeedSpToErr { get; set; }
|
||||
[Column("top_drive_torque_sp_to_err")]
|
||||
public short? TopDriveTorqueSpToErr { get; set; }
|
||||
[Column("w2800"), Comment("Установка нуля энкодера")]
|
||||
public short? W2800 { get; set; }
|
||||
[Column("w2810"), Comment(" автоматический сброс блокировки")]
|
||||
public short? W2810 { get; set; }
|
||||
[Column("mode"), Comment("Выбранный режим управления")]
|
||||
public short? Mode { get; set; }
|
||||
[Column("w2808"), Comment("Неисправность энкодера")]
|
||||
public short? W2808 { get; set; }
|
||||
[Column("reverse_speed_sp_zero_time"), Comment("Время выдачи сигнала нулевой скорости на при смене направления")]
|
||||
public short? ReverseSpeedSpZeroTime { get; set; }
|
||||
|
||||
[Column("state"), Comment("Переменная этапа")]
|
||||
public short? State { get; set; }
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.SAUB;
|
||||
using AsbCloudApp.Data.Subsystems;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudApp.Services.Subsystems;
|
||||
using AsbCloudDb.Model;
|
||||
@ -82,8 +83,12 @@ namespace AsbCloudInfrastructure
|
||||
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
MapsterSetup();
|
||||
var connectionStringName = "DefaultConnection";
|
||||
#if DEBUG
|
||||
connectionStringName = "DebugConnection";
|
||||
#endif
|
||||
services.AddDbContext<AsbCloudDbContext>(options =>
|
||||
options.UseNpgsql(configuration.GetConnectionString("DefaultConnection")));
|
||||
options.UseNpgsql(configuration.GetConnectionString(connectionStringName)));
|
||||
|
||||
services.AddFluentValidation();
|
||||
|
||||
@ -98,6 +103,7 @@ namespace AsbCloudInfrastructure
|
||||
services.AddSingleton<ITelemetryTracker, TelemetryTracker>();
|
||||
services.AddSingleton<IRequerstTrackerService, RequestTrackerService>();
|
||||
services.AddSingleton<IBackgroundWorkerService, BackgroundWorkerService>();
|
||||
services.AddSingleton<IReduceSamplingService>(provider => ReduceSamplingService.GetInstance(configuration));
|
||||
|
||||
services.AddTransient<IAuthService, AuthService>();
|
||||
services.AddTransient<IClusterService, ClusterService>();
|
||||
@ -105,7 +111,7 @@ namespace AsbCloudInfrastructure
|
||||
services.AddTransient<IDrillingProgramService, DrillingProgramService>();
|
||||
services.AddTransient<IDrillParamsService, DrillParamsService>();
|
||||
services.AddTransient<IEventService, EventService>();
|
||||
services.AddTransient<IFileService, FileService>();
|
||||
services.AddTransient<FileService>();
|
||||
services.AddTransient<IMeasureService, MeasureService>();
|
||||
services.AddTransient<IMessageService, MessageService>();
|
||||
services.AddTransient<IOperationsStatService, OperationsStatService>();
|
||||
@ -154,6 +160,8 @@ namespace AsbCloudInfrastructure
|
||||
dbSet => dbSet
|
||||
.Include(c => c.Wells)
|
||||
.Include(c => c.Deposit))); // может быть включен в сервис ClusterService
|
||||
services.AddTransient<IFileRepository, FileRepository>();
|
||||
services.AddTransient<IFileStorageRepository, FileStorageRepository>();
|
||||
// Subsystem service
|
||||
services.AddTransient<ICrudService<SubsystemDto>, CrudCacheServiceBase<SubsystemDto, Subsystem>>();
|
||||
services.AddTransient<ISubsystemService, SubsystemService>();
|
||||
|
297
AsbCloudInfrastructure/Repository/FileRepository.cs
Normal file
297
AsbCloudInfrastructure/Repository/FileRepository.cs
Normal file
@ -0,0 +1,297 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Services;
|
||||
using DocumentFormat.OpenXml.Drawing.Charts;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Org.BouncyCastle.Asn1.Ocsp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Repository
|
||||
{
|
||||
#nullable enable
|
||||
public class FileRepository : IFileRepository
|
||||
{
|
||||
private readonly IQueryable<FileInfo> dbSetConfigured;
|
||||
private readonly IAsbCloudDbContext db;
|
||||
|
||||
public FileRepository(IAsbCloudDbContext db)
|
||||
{
|
||||
this.db = db;
|
||||
this.dbSetConfigured = db.Files
|
||||
.Include(f => f.Author)
|
||||
.ThenInclude(u => u.Company)
|
||||
.ThenInclude(c => c.CompanyType)
|
||||
.Include(f => f.FileMarks)
|
||||
.ThenInclude(m => m.User)
|
||||
.Include(f => f.Well);
|
||||
}
|
||||
|
||||
private IQueryable<FileInfo> BuildQuery(FileRequest request)
|
||||
{
|
||||
var query = dbSetConfigured
|
||||
.Where(e => e.IdWell == request.IdWell);
|
||||
|
||||
double timezoneOffsetHours = query.FirstOrDefault()
|
||||
?.Well.Timezone.Hours ?? 5d;
|
||||
|
||||
if (request.IdCategory is not null)
|
||||
query = query.Where(x => x.IdCategory == request.IdCategory);
|
||||
|
||||
if (request.IsDeleted is not null)
|
||||
query = query.Where(x => x.IsDeleted == request.IsDeleted);
|
||||
|
||||
if (request.CompanyNamePart is not null)
|
||||
query = query.Where(e => e.Author.Company.Caption.ToLower().Contains(request.CompanyNamePart.ToLower()));
|
||||
|
||||
if (request.FileNamePart is not null)
|
||||
query = query.Where(e => e.Name.ToLower().Contains(request.FileNamePart.ToLower()));
|
||||
|
||||
if (request.Begin is not null)
|
||||
{
|
||||
var beginUtc = request.Begin.Value.ToUtcDateTimeOffset(timezoneOffsetHours);
|
||||
query = query.Where(e => e.UploadDate >= beginUtc);
|
||||
}
|
||||
|
||||
if (request.End is not null)
|
||||
{
|
||||
var endUtc = request.End.Value.ToUtcDateTimeOffset(timezoneOffsetHours);
|
||||
query = query.Where(e => e.UploadDate <= endUtc);
|
||||
}
|
||||
|
||||
if (request?.SortFields?.Any() == true)
|
||||
{
|
||||
query = query.SortBy(request.SortFields);
|
||||
}
|
||||
else
|
||||
query = query
|
||||
.OrderBy(o => o.UploadDate);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<FileInfoDto>> GetInfosAsync(FileRequest request, CancellationToken token)
|
||||
{
|
||||
var query = BuildQuery(request);
|
||||
|
||||
var entities = await query
|
||||
.SkipTake(request.Skip, request.Take)
|
||||
.AsNoTracking()
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var dtos = entities.Select(e => Convert(e));
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public async Task<PaginationContainer<FileInfoDto>> GetInfosPaginatedAsync(FileRequest request, CancellationToken token = default)
|
||||
{
|
||||
var skip = request.Skip ?? 0;
|
||||
var take = request.Take ?? 32;
|
||||
|
||||
var query = BuildQuery(request);
|
||||
|
||||
var result = new PaginationContainer<FileInfoDto>()
|
||||
{
|
||||
Skip = skip,
|
||||
Take = take,
|
||||
Count = await query.CountAsync(token),
|
||||
};
|
||||
|
||||
if (result.Count == 0)
|
||||
return result;
|
||||
|
||||
var entities = await query
|
||||
.SkipTake(skip, take)
|
||||
.AsNoTracking()
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
result.Items = entities.Select(e => Convert(e)).ToList();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<FileInfoDto>> GetInfoByIdsAsync(IEnumerable<int> idsFile, CancellationToken token)
|
||||
{
|
||||
var result = Enumerable.Empty<FileInfoDto>();
|
||||
|
||||
var entities = await dbSetConfigured
|
||||
.AsNoTracking()
|
||||
.Where(f => idsFile.Contains(f.Id))
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (entities is not null)
|
||||
result = entities.Select(entity => Convert(entity));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<int> MarkAsDeletedAsync(int idFile, CancellationToken token = default)
|
||||
{
|
||||
var fileInfo = await db.Files.FirstOrDefaultAsync(f => f.Id == idFile, token).ConfigureAwait(false);
|
||||
|
||||
if (fileInfo is null)
|
||||
return 0;
|
||||
|
||||
fileInfo.IsDeleted = true;
|
||||
|
||||
return await db.SaveChangesAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<FileInfoDto>> DeleteAsync(IEnumerable<int> ids, CancellationToken token)
|
||||
{
|
||||
var query = dbSetConfigured
|
||||
.Where(f => ids.Contains(f.Id) && f.IsDeleted);
|
||||
|
||||
var files = await query.ToListAsync(token);
|
||||
|
||||
var filesDtos = files.Select(x => Convert(x));
|
||||
|
||||
db.Files.RemoveRange(query);
|
||||
await db.SaveChangesAsync(token).ConfigureAwait(false);
|
||||
|
||||
return filesDtos;
|
||||
}
|
||||
|
||||
public async Task<FileInfoDto> GetByMarkId(int idMark, CancellationToken token)
|
||||
{
|
||||
var entity = await dbSetConfigured
|
||||
.FirstOrDefaultAsync(f => f.FileMarks.Any(m => m.Id == idMark), token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FileInfoDto dto = Convert(entity!);
|
||||
return dto;
|
||||
}
|
||||
|
||||
public async Task<int> CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token)
|
||||
{
|
||||
var fileMark = await db.FileMarks
|
||||
.FirstOrDefaultAsync(m => m.IdFile == fileMarkDto.IdFile &&
|
||||
m.IdMarkType == fileMarkDto.IdMarkType &&
|
||||
m.IdUser == idUser &&
|
||||
m.IsDeleted == false,
|
||||
token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (fileMark is not null)
|
||||
return 0;
|
||||
|
||||
var newFileMark = fileMarkDto.Adapt<FileMark>();
|
||||
newFileMark.Id = default;
|
||||
newFileMark.DateCreated = DateTime.UtcNow;
|
||||
newFileMark.IdUser = idUser;
|
||||
newFileMark.User = null;
|
||||
|
||||
db.FileMarks.Add(newFileMark);
|
||||
return await db.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
public async Task<int> MarkFileMarkAsDeletedAsync(IEnumerable<int> idsMarks, CancellationToken token)
|
||||
{
|
||||
var fileMarkQuery = db.FileMarks
|
||||
.Where(m => idsMarks.Contains(m.Id));
|
||||
|
||||
foreach (var fileMark in fileMarkQuery)
|
||||
fileMark.IsDeleted = true;
|
||||
|
||||
return await db.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<FileInfoDto>> GetAllAsync(CancellationToken token)
|
||||
=> await dbSetConfigured.AsNoTracking()
|
||||
.Select(x => Convert(x))
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
public async Task<FileInfoDto?> GetOrDefaultAsync(int id, CancellationToken token)
|
||||
{
|
||||
var entity = await dbSetConfigured
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(f => f.Id == id, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (entity is null)
|
||||
return null;
|
||||
|
||||
var dto = Convert(entity);
|
||||
return dto;
|
||||
}
|
||||
|
||||
public FileInfoDto? GetOrDefault(int id)
|
||||
{
|
||||
var entity = dbSetConfigured
|
||||
.AsNoTracking()
|
||||
.FirstOrDefault(f => f.Id == id);
|
||||
|
||||
if (entity is null)
|
||||
return null;
|
||||
|
||||
var dto = Convert(entity);
|
||||
return dto;
|
||||
}
|
||||
|
||||
public async Task<int> InsertAsync(FileInfoDto newItem, CancellationToken token)
|
||||
{
|
||||
var fileInfo = new FileInfo()
|
||||
{
|
||||
IdWell = newItem.IdWell,
|
||||
IdAuthor = newItem.IdAuthor,
|
||||
IdCategory = newItem.IdCategory,
|
||||
Name = newItem.Name,
|
||||
UploadDate = DateTime.UtcNow,
|
||||
IsDeleted = false,
|
||||
Size = newItem.Size,
|
||||
};
|
||||
|
||||
var entry = db.Files.Add(fileInfo);
|
||||
await db.SaveChangesAsync(token).ConfigureAwait(false);
|
||||
return entry.Entity.Id;
|
||||
}
|
||||
|
||||
public Task<int> InsertRangeAsync(IEnumerable<FileInfoDto> newItems, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<int> UpdateAsync(FileInfoDto item, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<int> DeleteAsync(int id, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static FileInfoDto Convert(FileInfo entity)
|
||||
{
|
||||
var timezoneOffset = entity.Well.Timezone?.Hours ?? 5;
|
||||
return Convert(entity, timezoneOffset);
|
||||
}
|
||||
|
||||
private static FileInfoDto Convert(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;
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
}
|
121
AsbCloudInfrastructure/Repository/FileStorageRepository.cs
Normal file
121
AsbCloudInfrastructure/Repository/FileStorageRepository.cs
Normal file
@ -0,0 +1,121 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Repositories;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Repository
|
||||
{
|
||||
#nullable enable
|
||||
public class FileStorageRepository : IFileStorageRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Директория хранения файлов
|
||||
/// </summary>
|
||||
private readonly string RootPath = "files";
|
||||
|
||||
public FileStorageRepository()
|
||||
{
|
||||
}
|
||||
|
||||
public async Task SaveFileAsync(string filePathRec, Stream fileStreamSrc, CancellationToken token)
|
||||
{
|
||||
CreateDirectory(filePathRec);
|
||||
using var newfileStream = new FileStream(filePathRec, FileMode.Create);
|
||||
await fileStreamSrc.CopyToAsync(newfileStream, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public void DeleteFile(IEnumerable<string> filesName)
|
||||
{
|
||||
foreach (var fileName in filesName)
|
||||
{
|
||||
if (File.Exists(fileName))
|
||||
File.Delete(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
public long GetFileLength(string srcFilePath)
|
||||
{
|
||||
var sysFileInfo = new FileInfo(srcFilePath);
|
||||
return sysFileInfo.Length;
|
||||
}
|
||||
|
||||
public void MoveFile(string srcFilePath, string filePath)
|
||||
{
|
||||
CreateDirectory(filePath);
|
||||
File.Move(srcFilePath, filePath);
|
||||
}
|
||||
|
||||
public string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId)
|
||||
{
|
||||
return Path.Combine(RootPath, $"{idWell}",
|
||||
$"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}");
|
||||
}
|
||||
|
||||
public int DeleteFilesNotInList(int idWell, IEnumerable<int> idsFilesList)
|
||||
{
|
||||
var allFilesPath = GetFilesPath(idWell);
|
||||
var result = 0;
|
||||
|
||||
foreach (var filePath in allFilesPath)
|
||||
{
|
||||
if (int.TryParse(Path.GetFileNameWithoutExtension(filePath), out int idFile)
|
||||
|| !idsFilesList.Any(x => x == idFile))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public IEnumerable<FileInfoDto> GetListFilesNotDisc(IEnumerable<FileInfoDto> files)
|
||||
{
|
||||
var resutl = new List<FileInfoDto>();
|
||||
var groupFiles = files.GroupBy(x => x.IdWell);
|
||||
|
||||
foreach (var itemGroupFiles in groupFiles)
|
||||
{
|
||||
var idsFilesStorage = GetIdsFiles(itemGroupFiles.Key);
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (!idsFilesStorage.Any(x => x == file.Id))
|
||||
resutl.Add(file);
|
||||
}
|
||||
}
|
||||
|
||||
return resutl;
|
||||
}
|
||||
|
||||
public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) =>
|
||||
Path.Combine(RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}");
|
||||
|
||||
private IEnumerable<int> GetIdsFiles(int idWell)
|
||||
{
|
||||
var result = new List<int>();
|
||||
var allFilesPath = GetFilesPath(idWell);
|
||||
|
||||
foreach (var filePath in allFilesPath)
|
||||
if(int.TryParse(Path.GetFileNameWithoutExtension(filePath), out int idFile))
|
||||
result.Add(idFile);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetFilesPath(int idWell)
|
||||
{
|
||||
var path = Path.Combine(RootPath, $"{idWell}");
|
||||
return Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
|
||||
}
|
||||
|
||||
private static void CreateDirectory(string filePath)
|
||||
{
|
||||
var directoryName = Path.GetDirectoryName(filePath)!;
|
||||
Directory.CreateDirectory(directoryName);
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
}
|
@ -66,17 +66,33 @@ namespace AsbCloudInfrastructure.Repository
|
||||
return new TDto[] { Convert(data, timezoneHours) };
|
||||
}
|
||||
|
||||
public Task SaveDataAsync(int idTelemetry, IEnumerable<TDto> dtos, CancellationToken token)
|
||||
public async Task SaveDataAsync(int idTelemetry, IEnumerable<TDto> dtos, CancellationToken token)
|
||||
{
|
||||
if (dtos?.Any() != true)
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
|
||||
var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours;
|
||||
var entities = dtos
|
||||
.DistinctBy(d => d.DateTime)
|
||||
.Select(dto => Convert(dto, idTelemetry, timezoneHours));
|
||||
dbset.AddRange(entities);
|
||||
return db.SaveChangesAsync(token);
|
||||
|
||||
var dateMin = entities.Min(e => e.DateTime);
|
||||
var dateMax = entities.Max(e => e.DateTime);
|
||||
var existingEntities = await dbset
|
||||
.Where(e => e.IdTelemetry == idTelemetry)
|
||||
.Where(e => e.DateTime >= dateMin && e.DateTime <= dateMax)
|
||||
.Select(e => new { e.DateTime, e.IdTelemetry})
|
||||
.ToArrayAsync(token);
|
||||
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
if (existingEntities.Any(e=>e.IdTelemetry == entity.IdTelemetry && e.DateTime == entity.DateTime))
|
||||
dbset.Update(entity);
|
||||
else
|
||||
dbset.Add(entity);
|
||||
}
|
||||
|
||||
await db.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
private static TEntity Convert(TDto dto, int idTelemetry, double timezoneHours)
|
||||
|
@ -162,7 +162,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
||||
sheet.Cell(AddressWatchData[1])
|
||||
._SetValue($"{blockDto.WorkTimeSpinMaster}");
|
||||
sheet.Cell(AddressMetreData[1])
|
||||
._SetValue($"{blockDto.PenetrationTorkMaster}");
|
||||
._SetValue($"{blockDto.PenetrationSpinMaster}");
|
||||
sheet._Range(AddressWorkSaubData[2], AddressWorkSaubData[2] + (0, 2))
|
||||
._SetValue("Торк Мастер (демпфирование), ч/:");
|
||||
sheet.Cell(AddressWatchData[2])
|
||||
|
@ -44,7 +44,9 @@ namespace AsbCloudInfrastructure.Services.DailyReport
|
||||
timeBalance.Draw(sheet);
|
||||
blockDimensionless.Draw(sheet);
|
||||
blockSaub.Draw(sheet);
|
||||
blockSign.Draw(sheet);
|
||||
blockSign.Draw(sheet);
|
||||
//sheet.Columns().AdjustToContents(); // Adjust column width
|
||||
sheet.Rows().AdjustToContents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,9 +48,10 @@ namespace AsbCloudInfrastructure.Services.DailyReport
|
||||
|
||||
public async Task<DailyReportDto> GetOrGenerateAsync(int idWell, DateTime date, CancellationToken token)
|
||||
{
|
||||
var dailyReportDto = await GetAsync(idWell, date, token);
|
||||
var dateOnly = DateTime.SpecifyKind(date.Date, DateTimeKind.Utc);
|
||||
var dailyReportDto = await GetAsync(idWell, dateOnly, token);
|
||||
if (dailyReportDto is null)
|
||||
dailyReportDto = await MakeDefaultDailyReportAsync(idWell, date, token);
|
||||
dailyReportDto = await MakeDefaultDailyReportAsync(idWell, dateOnly, token);
|
||||
return dailyReportDto;
|
||||
}
|
||||
|
||||
@ -124,10 +125,27 @@ namespace AsbCloudInfrastructure.Services.DailyReport
|
||||
ClusterName = well?.Cluster ?? "",
|
||||
},
|
||||
TimeBalance = await MakeTimeBalanceAsync(idWell, date, token),
|
||||
Bha = await GetPrevOrNewBhaAsync(idWell, date, token)
|
||||
};
|
||||
return dto;
|
||||
}
|
||||
|
||||
private async Task<BhaDto> GetPrevOrNewBhaAsync(int idWell, DateTime date, CancellationToken token)
|
||||
{
|
||||
var dateOffset = date.Date;
|
||||
var entity = await db.DailyReports
|
||||
.Where(x => x.IdWell == idWell)
|
||||
.OrderByDescending(x => x.StartDate)
|
||||
.FirstOrDefaultAsync(r => r.StartDate.Year <= dateOffset.Year &&
|
||||
r.StartDate.DayOfYear <= dateOffset.DayOfYear, token);
|
||||
|
||||
if (entity is null)
|
||||
return new BhaDto();
|
||||
|
||||
var dto = Convert(entity);
|
||||
return dto.Bha;
|
||||
}
|
||||
|
||||
private async Task<TimeBalanceDto> MakeTimeBalanceAsync(int idWell, DateTime date, CancellationToken token)
|
||||
{
|
||||
var stat = await detectedOperationService.GetOperationsStatAsync(new DetectedOperationRequest
|
||||
|
@ -10,12 +10,12 @@ namespace AsbCloudInfrastructure.Services.DailyReport
|
||||
var mergedRange = range.Merge();
|
||||
mergedRange.FirstCell()._SetValue(value);
|
||||
var colWidth = mergedRange.FirstCell().WorksheetColumn().Width;
|
||||
var maxCharsToWrap = colWidth / (0.05d * mergedRange.FirstCell().Style.Font.FontSize);
|
||||
var maxCharsToWrap = colWidth / (0.1d * mergedRange.FirstCell().Style.Font.FontSize);
|
||||
if (value is string valueString && valueString.Length > maxCharsToWrap)
|
||||
{
|
||||
var row = mergedRange.FirstCell().WorksheetRow();
|
||||
var baseHeight = row.Height;
|
||||
row.Height = 0.45d * baseHeight * Math.Ceiling(1d + valueString.Length / maxCharsToWrap);
|
||||
row.Height = 0.5d * baseHeight * Math.Ceiling(1d + valueString.Length / maxCharsToWrap);
|
||||
}
|
||||
mergedRange.Style.SetAllBorders()
|
||||
.Alignment.SetWrapText(true);
|
||||
@ -59,7 +59,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport
|
||||
{
|
||||
var row = cell.WorksheetRow();
|
||||
var baseHeight = row.Height;
|
||||
row.Height = 0.52d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap);
|
||||
row.Height = 0.5d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport
|
||||
{
|
||||
var row = cell.WorksheetRow();
|
||||
var baseHeight = row.Height;
|
||||
row.Height = 0.52d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap);
|
||||
row.Height = 0.5d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
#nullable enable
|
||||
public class DrillParamsService : CrudServiceBase<DrillParamsDto, DrillParams>, IDrillParamsService
|
||||
{
|
||||
private readonly IAsbCloudDbContext db;
|
||||
@ -23,7 +24,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
this.telemetryService = telemetryService;
|
||||
}
|
||||
|
||||
public async Task<DrillParamsDto> GetDefaultDrillParamsAsync(int idWell,
|
||||
public async Task<DrillParamsDto?> GetDefaultDrillParamsAsync(int idWell,
|
||||
double startDepth, double endDepth, CancellationToken token = default)
|
||||
{
|
||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
||||
@ -39,28 +40,46 @@ namespace AsbCloudInfrastructure.Services
|
||||
select new DrillParamsDto()
|
||||
{
|
||||
IdWell = idWell,
|
||||
DepthStart = startDepth,
|
||||
DepthEnd = endDepth,
|
||||
Depth = new MinMaxDto<double>
|
||||
{
|
||||
Min = endDepth,
|
||||
Max = startDepth
|
||||
},
|
||||
IdWellSectionType = 0,
|
||||
AxialLoadMin = g.Min(t => t.AxialLoad) ?? double.NaN,
|
||||
AxialLoadAvg = g.Average(t => t.AxialLoad) ?? double.NaN,
|
||||
AxialLoadMax = g.Max(t => t.AxialLoad) ?? double.NaN,
|
||||
PressureMin = g.Min(t => t.Pressure) ?? double.NaN,
|
||||
PressureAvg = g.Average(t => t.Pressure) ?? double.NaN,
|
||||
PressureMax = g.Max(t => t.Pressure) ?? double.NaN,
|
||||
RotorTorqueMin = g.Min(t => t.RotorTorque) ?? double.NaN,
|
||||
RotorTorqueAvg = g.Average(t => t.RotorTorque) ?? double.NaN,
|
||||
RotorTorqueMax = g.Max(t => t.RotorTorque) ?? double.NaN,
|
||||
RotorSpeedMin = g.Min(t => t.RotorSpeed) ?? double.NaN,
|
||||
RotorSpeedAvg = g.Average(t => t.RotorSpeed) ?? double.NaN,
|
||||
RotorSpeedMax = g.Max(t => t.RotorSpeed) ?? double.NaN,
|
||||
FlowMin = g.Min(t => t.Flow) ?? double.NaN,
|
||||
FlowAvg = g.Min(t => t.Flow) ?? double.NaN,
|
||||
FlowMax = g.Min(t => t.Flow) ?? double.NaN
|
||||
AxialLoad = new MinMaxExtendedViewDto
|
||||
{
|
||||
Min = g.Min(t => t.AxialLoad) ?? double.NaN,
|
||||
Avg = g.Average(t => t.AxialLoad) ?? double.NaN,
|
||||
Max = g.Max(t => t.AxialLoad) ?? double.NaN
|
||||
},
|
||||
Pressure = new MinMaxExtendedViewDto
|
||||
{
|
||||
Min = g.Min(t => t.Pressure) ?? double.NaN,
|
||||
Avg = g.Average(t => t.Pressure) ?? double.NaN,
|
||||
Max = g.Max(t => t.Pressure) ?? double.NaN
|
||||
},
|
||||
RotorTorque = new MinMaxExtendedViewDto
|
||||
{
|
||||
Min = g.Min(t => t.RotorTorque) ?? double.NaN,
|
||||
Avg = g.Average(t => t.RotorTorque) ?? double.NaN,
|
||||
Max = g.Max(t => t.RotorTorque) ?? double.NaN
|
||||
},
|
||||
RotorSpeed = new MinMaxExtendedViewDto
|
||||
{
|
||||
Min = g.Min(t => t.RotorSpeed) ?? double.NaN,
|
||||
Avg = g.Average(t => t.RotorSpeed) ?? double.NaN,
|
||||
Max = g.Max(t => t.RotorSpeed) ?? double.NaN
|
||||
},
|
||||
Flow = new MinMaxExtendedViewDto
|
||||
{
|
||||
Min = g.Min(t => t.Flow) ?? double.NaN,
|
||||
Avg = g.Min(t => t.Flow) ?? double.NaN,
|
||||
Max = g.Min(t => t.Flow) ?? double.NaN
|
||||
}
|
||||
})
|
||||
.AsNoTracking()
|
||||
.DefaultIfEmpty()
|
||||
.OrderBy(t => t.AxialLoadMin)
|
||||
.OrderBy(t => t.AxialLoad.Min)
|
||||
.FirstOrDefaultAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@ -70,35 +89,62 @@ namespace AsbCloudInfrastructure.Services
|
||||
public async Task<IEnumerable<DrillParamsDto>> GetAllAsync(int idWell,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var entities = await (from p in db.DrillParams
|
||||
where p.IdWell == idWell
|
||||
orderby p.Id
|
||||
select p)
|
||||
.AsNoTracking()
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
var entities = await db.DrillParams
|
||||
.Where(p => p.IdWell == idWell)
|
||||
.OrderBy(p=> p.Id)
|
||||
.AsNoTracking()
|
||||
.ToArrayAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var dto = entities.Adapt<IEnumerable<DrillParamsDto>>();
|
||||
return dto;
|
||||
var dtos = entities.Select(p =>
|
||||
{
|
||||
var dto = new DrillParamsDto
|
||||
{
|
||||
IdWell = p.IdWell,
|
||||
Id = p.Id,
|
||||
IdWellSectionType = p.IdWellSectionType,
|
||||
Depth = new MinMaxDto<double> { Max = p.PressureMax, Min = p.PressureMin },
|
||||
Pressure = MakeMinMaxExtended(p.PressureAvg, p.PressureMax, p.PressureMin),
|
||||
AxialLoad = MakeMinMaxExtended(p.AxialLoadAvg, p.AxialLoadMax, p.AxialLoadMin),
|
||||
Flow = MakeMinMaxExtended(p.FlowAvg, p.FlowMax, p.FlowMin),
|
||||
RotorSpeed = MakeMinMaxExtended(p.RotorSpeedAvg, p.RotorSpeedMax, p.RotorSpeedMin),
|
||||
RotorTorque = MakeMinMaxExtended(p.RotorTorqueAvg, p.RotorTorqueMax, p.RotorTorqueMin)
|
||||
};
|
||||
return dto;
|
||||
});
|
||||
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<DrillParamsDto>> GetCompositeAllAsync(int idWell,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var compositeWellDrillParams =
|
||||
await (from p in db.DrillParams
|
||||
from c in db.WellComposites
|
||||
where c.IdWell == idWell &&
|
||||
p.IdWell == c.IdWellSrc &&
|
||||
p.IdWellSectionType == c.IdWellSectionType
|
||||
select p)
|
||||
.AsNoTracking()
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
var allDrillParamsQuery = db.WellComposites
|
||||
.Where(c => c.IdWell == idWell)
|
||||
.Join(db.DrillParams,
|
||||
c => c.IdWellSrc,
|
||||
p => p.IdWell,
|
||||
(c, p) => p);
|
||||
|
||||
var compositeDrillParamsDtos = compositeWellDrillParams.Adapt<IEnumerable<DrillParamsDto>>();
|
||||
var allDrillParams = await allDrillParamsQuery
|
||||
.AsNoTracking()
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return compositeDrillParamsDtos;
|
||||
var compositeWellDrillParamsQuery = db.WellComposites
|
||||
.Where(c => c.IdWell == idWell)
|
||||
.Join(db.DrillParams,
|
||||
c => new { IdWell = c.IdWellSrc, IdSection = c.IdWellSectionType },
|
||||
p => new { IdWell = p.IdWell, IdSection = p.IdWellSectionType },
|
||||
(c, p) => p);
|
||||
|
||||
var compositeWellDrillParams = await compositeWellDrillParamsQuery
|
||||
.AsNoTracking()
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var result = compositeWellDrillParams.Select(x => Convert(x, allDrillParams));
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<int> InsertAsync(int idWell, DrillParamsDto dto,
|
||||
@ -143,5 +189,34 @@ namespace AsbCloudInfrastructure.Services
|
||||
var result = await base.UpdateAsync(dto, token).ConfigureAwait(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static DrillParamsDto Convert(DrillParams entity, IEnumerable<DrillParams> drillParams)
|
||||
{
|
||||
return new DrillParamsDto
|
||||
{
|
||||
Id = entity.Id,
|
||||
IdWellSectionType = entity.IdWellSectionType,
|
||||
AxialLoad = MakeMinMaxExtended(entity.AxialLoadAvg, entity.AxialLoadMax, entity.AxialLoadMin, drillParams.Select(x => (x.AxialLoadMin, x.AxialLoadMax))),
|
||||
Depth = new MinMaxDto<double> {
|
||||
Min = entity.DepthEnd,
|
||||
Max = entity.DepthStart
|
||||
},
|
||||
Flow = MakeMinMaxExtended(entity.FlowAvg, entity.FlowMax, entity.FlowMin, drillParams.Select(x => (x.FlowMin, x.FlowMax))),
|
||||
IdWell = entity.IdWell,
|
||||
Pressure = MakeMinMaxExtended(entity.PressureAvg, entity.PressureMax, entity.PressureMin, drillParams.Select(x => (x.PressureMin, x.PressureMax))),
|
||||
RotorSpeed = MakeMinMaxExtended(entity.RotorSpeedAvg, entity.RotorSpeedMax, entity.RotorSpeedMin, drillParams.Select(x => (x.RotorSpeedMin, x.RotorSpeedMax))),
|
||||
RotorTorque = MakeMinMaxExtended(entity.RotorTorqueAvg, entity.RotorTorqueMax, entity.RotorTorqueMin, drillParams.Select(x => (x.RotorTorqueMin, x.RotorTorqueMax)))
|
||||
};
|
||||
}
|
||||
|
||||
private static MinMaxExtendedViewDto MakeMinMaxExtended(double avg, double max, double min, IEnumerable<(double min, double max)>? allDrillParams = null)
|
||||
=> new MinMaxExtendedViewDto {
|
||||
Avg = avg,
|
||||
Max = max,
|
||||
Min = min,
|
||||
IsMax = (! allDrillParams?.Any (mx => mx.max > max)) ?? false,
|
||||
IsMin = (! allDrillParams?.Any (mn => mn.min < min)) ?? false
|
||||
};
|
||||
}
|
||||
#nullable disable
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Repository;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -19,7 +20,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
private static readonly Dictionary<string, DrillingProgramCreateError> drillingProgramCreateErrors = new Dictionary<string, DrillingProgramCreateError>();
|
||||
|
||||
private readonly IAsbCloudDbContext context;
|
||||
private readonly IFileService fileService;
|
||||
private readonly FileService fileService;
|
||||
private readonly IUserService userService;
|
||||
private readonly IWellService wellService;
|
||||
private readonly IConfiguration configuration;
|
||||
@ -49,7 +50,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
|
||||
public DrillingProgramService(
|
||||
IAsbCloudDbContext context,
|
||||
IFileService fileService,
|
||||
FileService fileService,
|
||||
IUserService userService,
|
||||
IWellService wellService,
|
||||
IConfiguration configuration,
|
||||
@ -281,7 +282,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
fileMarkDto.IdMarkType != idMarkTypeReject)
|
||||
throw new ArgumentInvalidException($"В этом методе допустимы только отметки о принятии или отклонении.", nameof(fileMarkDto));
|
||||
|
||||
var fileInfo = await fileService.GetInfoAsync(fileMarkDto.IdFile, token)
|
||||
var fileInfo = await fileService.GetOrDefaultAsync(fileMarkDto.IdFile, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (fileInfo is null)
|
||||
@ -356,7 +357,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
|
||||
private async Task NotifyPublisherOnFullAccepAsync(FileMarkDto fileMark, CancellationToken token)
|
||||
{
|
||||
var file = await fileService.GetInfoAsync(fileMark.IdFile, token);
|
||||
var file = await fileService.GetOrDefaultAsync(fileMark.IdFile, token);
|
||||
var well = await wellService.GetOrDefaultAsync(file.IdWell, token);
|
||||
var user = file.Author;
|
||||
var factory = new DrillingMailBodyFactory(configuration);
|
||||
@ -368,7 +369,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
|
||||
private async Task NotifyPublisherOnRejectAsync(FileMarkDto fileMark, CancellationToken token)
|
||||
{
|
||||
var file = await fileService.GetInfoAsync(fileMark.IdFile, token);
|
||||
var file = await fileService.GetOrDefaultAsync(fileMark.IdFile, token);
|
||||
var well = await wellService.GetOrDefaultAsync(file.IdWell, token);
|
||||
var user = file.Author;
|
||||
var factory = new DrillingMailBodyFactory(configuration);
|
||||
@ -472,14 +473,15 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
var well = await wellService.GetOrDefaultAsync(idWell, token);
|
||||
var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.xlsx";
|
||||
var tempResultFilePath = Path.Combine(Path.GetTempPath(), "drillingProgram", resultFileName);
|
||||
var mailService = new EmailService(backgroundWorker, configuration);
|
||||
async Task funcProgramMake(string id, CancellationToken token)
|
||||
{
|
||||
var contextOptions = new DbContextOptionsBuilder<AsbCloudDbContext>()
|
||||
.UseNpgsql(connectionString)
|
||||
.Options;
|
||||
using var context = new AsbCloudDbContext(contextOptions);
|
||||
var fileService = new FileService(context);
|
||||
var fileRepository = new FileRepository(context);
|
||||
var fileStorageRepository = new FileStorageRepository();
|
||||
var fileService = new FileService(fileRepository, fileStorageRepository);
|
||||
var files = state.Parts.Select(p => fileService.GetUrl(p.File));
|
||||
DrillingProgramMaker.UniteExcelFiles(files, tempResultFilePath, state.Parts, well);
|
||||
await fileService.MoveAsync(idWell, null, idFileCategoryDrillingProgram, resultFileName, tempResultFilePath, token);
|
||||
|
@ -1,379 +0,0 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
public class FileService : IFileService
|
||||
{
|
||||
public string RootPath { get; private set; }
|
||||
|
||||
private readonly IQueryable<AsbCloudDb.Model.FileInfo> dbSetConfigured;
|
||||
private readonly IAsbCloudDbContext db;
|
||||
|
||||
public FileService(IAsbCloudDbContext db)
|
||||
{
|
||||
RootPath = "files";
|
||||
this.db = db;
|
||||
dbSetConfigured = db.Files
|
||||
.Include(f => f.Author)
|
||||
.ThenInclude(u => u.Company)
|
||||
.ThenInclude(c => c.CompanyType)
|
||||
.Include(f => f.FileMarks)
|
||||
.ThenInclude(m => m.User)
|
||||
.Include(f => f.Well);
|
||||
}
|
||||
|
||||
public async Task<FileInfoDto> MoveAsync(int idWell, int? idUser, int idCategory,
|
||||
string destinationFileName, string srcFilePath, CancellationToken token = default)
|
||||
{
|
||||
destinationFileName = Path.GetFileName(destinationFileName);
|
||||
srcFilePath = Path.GetFullPath(srcFilePath);
|
||||
if (!File.Exists(srcFilePath))
|
||||
throw new ArgumentInvalidException($"file {srcFilePath} doesn't exist", nameof(srcFilePath));
|
||||
|
||||
var sysFileInfo = new System.IO.FileInfo(srcFilePath);
|
||||
|
||||
//save info to db
|
||||
var fileInfo = new AsbCloudDb.Model.FileInfo()
|
||||
{
|
||||
IdWell = idWell,
|
||||
IdAuthor = idUser,
|
||||
IdCategory = idCategory,
|
||||
Name = destinationFileName,
|
||||
UploadDate = DateTime.UtcNow,
|
||||
IsDeleted = false,
|
||||
Size = sysFileInfo.Length,
|
||||
};
|
||||
|
||||
var entry = db.Files.Add(fileInfo);
|
||||
await db.SaveChangesAsync(token).ConfigureAwait(false);
|
||||
var fileId = entry.Entity.Id;
|
||||
string filePath = MakeFilePath(idWell, idCategory, destinationFileName, fileId);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
||||
File.Move(srcFilePath, filePath);
|
||||
|
||||
return await GetInfoAsync(entry.Entity.Id, token);
|
||||
}
|
||||
|
||||
public async Task<FileInfoDto> SaveAsync(int idWell, int? idUser, int idCategory,
|
||||
string fileFullName, Stream fileStream, CancellationToken token)
|
||||
{
|
||||
//save info to db
|
||||
var fileInfo = new AsbCloudDb.Model.FileInfo()
|
||||
{
|
||||
IdWell = idWell,
|
||||
IdAuthor = idUser,
|
||||
IdCategory = idCategory,
|
||||
Name = Path.GetFileName(fileFullName),
|
||||
UploadDate = DateTime.UtcNow,
|
||||
IsDeleted = false,
|
||||
Size = fileStream?.Length ?? 0
|
||||
};
|
||||
|
||||
var entry = db.Files.Add(fileInfo);
|
||||
await db.SaveChangesAsync(token).ConfigureAwait(false);
|
||||
var fileId = entry.Entity.Id;
|
||||
//save stream to disk
|
||||
string filePath = MakeFilePath(idWell, idCategory, fileFullName, fileId);
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
||||
|
||||
using var newfileStream = new FileStream(filePath, FileMode.Create);
|
||||
await fileStream.CopyToAsync(newfileStream, token).ConfigureAwait(false);
|
||||
|
||||
return await GetInfoAsync(entry.Entity.Id, token);
|
||||
}
|
||||
|
||||
private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId)
|
||||
{
|
||||
return Path.Combine(RootPath, $"{idWell}",
|
||||
$"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}");
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<FileInfoDto>> GetInfosByCategoryAsync(int idWell,
|
||||
int idCategory, CancellationToken token)
|
||||
{
|
||||
var entities = await dbSetConfigured
|
||||
.Where(e => e.IdWell == idWell && e.IdCategory == idCategory && e.IsDeleted == false)
|
||||
.AsNoTracking()
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var dtos = entities.Select(e => Convert(e));
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public async Task<PaginationContainer<FileInfoDto>> GetInfosAsync(int idWell,
|
||||
int idCategory, string companyName = default, string fileName = default, DateTime begin = default,
|
||||
DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default)
|
||||
{
|
||||
var query = dbSetConfigured
|
||||
.Where(e => e.IdWell == idWell &&
|
||||
e.IdCategory == idCategory &&
|
||||
!e.IsDeleted);
|
||||
|
||||
if (!string.IsNullOrEmpty(companyName))
|
||||
query = query.Where(e => (e.Author == null) ||
|
||||
(e.Author.Company == null) ||
|
||||
e.Author.Company.Caption.Contains(companyName));
|
||||
|
||||
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)
|
||||
{
|
||||
var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset);
|
||||
query = query.Where(e => e.UploadDate >= beginUtc);
|
||||
}
|
||||
|
||||
if (end != default)
|
||||
{
|
||||
var endUtc = end.ToUtcDateTimeOffset(timezoneOffset);
|
||||
query = query.Where(e => e.UploadDate <= endUtc);
|
||||
}
|
||||
|
||||
var count = await query.CountAsync(token).ConfigureAwait(false);
|
||||
|
||||
var result = new PaginationContainer<FileInfoDto>(count)
|
||||
{
|
||||
Skip = skip,
|
||||
Take = take,
|
||||
Count = count,
|
||||
};
|
||||
|
||||
if (count <= skip)
|
||||
return result;
|
||||
|
||||
query = query.OrderBy(e => e.UploadDate);
|
||||
|
||||
if (skip > 0)
|
||||
query = query.Skip(skip);
|
||||
query = query.Take(take);
|
||||
|
||||
var entities = await query
|
||||
.Take(take).AsNoTracking().ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var dtos = entities.Select(e => Convert(e, timezoneOffset));
|
||||
result.Items.AddRange(dtos);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<FileInfoDto> GetInfoAsync(int idFile,
|
||||
CancellationToken token)
|
||||
{
|
||||
var entity = await dbSetConfigured
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(f => f.Id == idFile, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (entity is null)
|
||||
{
|
||||
throw new FileNotFoundException($"fileId:{idFile} not found");
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(entity.Name);
|
||||
|
||||
var relativePath = GetUrl(entity.IdWell, entity.IdCategory, entity.Id, ext);
|
||||
var fullPath = Path.GetFullPath(relativePath);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
throw new FileNotFoundException("not found", relativePath);
|
||||
}
|
||||
|
||||
var dto = Convert(entity);
|
||||
return dto;
|
||||
}
|
||||
|
||||
public async Task<int> MarkAsDeletedAsync(int idFile,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var fileInfo = await db.Files.FirstOrDefaultAsync(f => f.Id == idFile, token).ConfigureAwait(false);
|
||||
|
||||
if (fileInfo is null)
|
||||
return 0;
|
||||
|
||||
fileInfo.IsDeleted = true;
|
||||
|
||||
return await db.SaveChangesAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Task<int> DeleteAsync(int idFile, CancellationToken token)
|
||||
=> DeleteAsync(new int[] { idFile }, token);
|
||||
|
||||
public async Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token)
|
||||
{
|
||||
if (ids is null || !ids.Any())
|
||||
return 0;
|
||||
|
||||
var filesQuery = db.Files
|
||||
.Where(f => ids.Contains(f.Id));
|
||||
|
||||
var files = await filesQuery.ToListAsync(token);
|
||||
|
||||
if (files is null || !files.Any())
|
||||
return 0;
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
var fileName = GetUrl(file.IdWell, file.IdCategory, file.Id, Path.GetExtension(file.Name));
|
||||
if (File.Exists(fileName))
|
||||
File.Delete(fileName);
|
||||
}
|
||||
|
||||
db.Files.RemoveRange(filesQuery);
|
||||
|
||||
return await db.SaveChangesAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public string GetUrl(int idFile)
|
||||
{
|
||||
var fileInfo = db.Files
|
||||
.FirstOrDefault(f => f.Id == idFile);
|
||||
|
||||
if (fileInfo is null)
|
||||
return null;
|
||||
|
||||
return GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name));
|
||||
}
|
||||
|
||||
public string GetUrl(FileInfoDto fileInfo) =>
|
||||
GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name));
|
||||
|
||||
public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) =>
|
||||
Path.Combine(RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}");
|
||||
|
||||
public async Task<FileInfoDto> GetByMarkId(int idMark,
|
||||
CancellationToken token)
|
||||
{
|
||||
var entity = await dbSetConfigured
|
||||
.FirstOrDefaultAsync(f => f.FileMarks.Any(m => m.Id == idMark), token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
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
|
||||
.FirstOrDefaultAsync(m => m.IdFile == fileMarkDto.IdFile &&
|
||||
m.IdMarkType == fileMarkDto.IdMarkType &&
|
||||
m.IdUser == idUser &&
|
||||
m.IsDeleted == false,
|
||||
token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (fileMark is not null)
|
||||
return 0;
|
||||
|
||||
var newFileMark = fileMarkDto.Adapt<FileMark>();
|
||||
newFileMark.Id = default;
|
||||
newFileMark.DateCreated = DateTime.UtcNow;
|
||||
newFileMark.IdUser = idUser;
|
||||
newFileMark.User = null;
|
||||
|
||||
db.FileMarks.Add(newFileMark);
|
||||
return await db.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
public Task<int> MarkFileMarkAsDeletedAsync(int idMark,
|
||||
CancellationToken token)
|
||||
=> MarkFileMarkAsDeletedAsync(new int[] { idMark }, token);
|
||||
|
||||
public async Task<int> MarkFileMarkAsDeletedAsync(IEnumerable<int> idsMarks,
|
||||
CancellationToken token)
|
||||
{
|
||||
var fileMarkQuery = db.FileMarks
|
||||
.Where(m => idsMarks.Contains(m.Id));
|
||||
|
||||
foreach (var fileMark in fileMarkQuery)
|
||||
fileMark.IsDeleted = true;
|
||||
|
||||
return await db.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
public async Task<List<FileInfoDto>> GetInfoByIdsAsync(List<int> idsFile, CancellationToken token)
|
||||
{
|
||||
var result = new List<FileInfoDto>();
|
||||
|
||||
var entities = await dbSetConfigured
|
||||
.AsNoTracking()
|
||||
.Where(f => idsFile.Contains(f.Id))
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
if (entity is null)
|
||||
{
|
||||
throw new FileNotFoundException($"fileId:{entity.Id} not found");
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(entity.Name);
|
||||
|
||||
var relativePath = GetUrl(entity.IdWell, entity.IdCategory, entity.Id, ext);
|
||||
var fullPath = Path.GetFullPath(relativePath);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
throw new FileNotFoundException("not found", relativePath);
|
||||
}
|
||||
|
||||
result.Add(Convert(entity));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<FileInfoDto>> GetInfosByWellIdAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var entities = await dbSetConfigured
|
||||
.Where(e => e.IdWell == idWell && e.IsDeleted == false)
|
||||
.AsNoTracking()
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var dtos = entities.Select(e => Convert(e));
|
||||
return dtos;
|
||||
}
|
||||
}
|
||||
}
|
335
AsbCloudInfrastructure/Services/ReduceSamplingService.cs
Normal file
335
AsbCloudInfrastructure/Services/ReduceSamplingService.cs
Normal file
@ -0,0 +1,335 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb;
|
||||
using AsbCloudDb.Model;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
#nullable enable
|
||||
class JobHandle
|
||||
{
|
||||
public int Id => Job.Id;
|
||||
public JobDto Job { get; set; } = null!;
|
||||
public DateTime DateCreate { get; set; } = DateTime.Now;
|
||||
public OnJobProgressDelagate? OnProgress { get; set; }
|
||||
}
|
||||
|
||||
public class ReduceSamplingService : IReduceSamplingService
|
||||
{
|
||||
private const string jobResultKeyDeleted = "deleted";
|
||||
private const string jobResultKeyTotal = "total";
|
||||
private static ReduceSamplingService? instance;
|
||||
private readonly string connectionString;
|
||||
private const int ratio = 5;
|
||||
private readonly List<JobHandle> jobHandlers = new(5);
|
||||
private bool isHandling;
|
||||
private CancellationTokenSource? cancellationTokenSource;
|
||||
private Task? task;
|
||||
|
||||
private ReduceSamplingService(IConfiguration configuration)
|
||||
{
|
||||
connectionString = configuration.GetConnectionString("DefaultConnection");
|
||||
}
|
||||
|
||||
~ReduceSamplingService()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get singleton Instance
|
||||
/// </summary>
|
||||
/// <param name="configuration"></param>
|
||||
/// <returns></returns>
|
||||
public static ReduceSamplingService GetInstance(IConfiguration configuration)
|
||||
{
|
||||
instance ??= new(configuration);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryEnqueueRediceSamplingJob(int idTelemetry, OnJobProgressDelagate? onProgress, out JobDto jobDto)
|
||||
{
|
||||
lock (jobHandlers)
|
||||
{
|
||||
var oldJob = jobHandlers.FirstOrDefault(j => j.Id == idTelemetry);
|
||||
if (oldJob is not null)
|
||||
{
|
||||
jobDto = oldJob.Job;
|
||||
return false;
|
||||
}
|
||||
|
||||
jobDto = new JobDto
|
||||
{
|
||||
Id = idTelemetry,
|
||||
State = JobState.Waiting,
|
||||
Results = new(),
|
||||
};
|
||||
var jobHandler = new JobHandle
|
||||
{
|
||||
Job = jobDto,
|
||||
OnProgress = onProgress,
|
||||
};
|
||||
|
||||
jobHandlers.Add(jobHandler);
|
||||
}
|
||||
EnsureHandleQueueStarted();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public JobDto? GetOrDefaultState(int idTelemetry)
|
||||
{
|
||||
JobHandle? jobHandler;
|
||||
lock (jobHandlers)
|
||||
{
|
||||
jobHandler = jobHandlers.FirstOrDefault(j => j.Id == idTelemetry);
|
||||
}
|
||||
return jobHandler?.Job;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<JobDto> GetJobs() => jobHandlers.Select(j=>j.Job);
|
||||
|
||||
private bool TryTakeWaitingJob(out JobHandle? job)
|
||||
{
|
||||
lock (jobHandlers)
|
||||
{
|
||||
job = jobHandlers.FirstOrDefault(j => j.Job.State == JobState.Waiting);
|
||||
}
|
||||
return job is not null;
|
||||
}
|
||||
|
||||
private void EnsureHandleQueueStarted()
|
||||
{
|
||||
if (isHandling)
|
||||
return;
|
||||
isHandling = true;
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
var token = cancellationTokenSource.Token;
|
||||
task = Task.Run(async () => await HandleJobs(token))
|
||||
.ContinueWith(_ => isHandling = false);
|
||||
}
|
||||
|
||||
private async Task HandleJobs(CancellationToken token)
|
||||
{
|
||||
while (TryTakeWaitingJob(out JobHandle? jobHandler))
|
||||
{
|
||||
jobHandler!.Job.State = JobState.Working;
|
||||
try
|
||||
{
|
||||
await RediceSamplingSaubAsync(jobHandler, token);
|
||||
await RediceSamplingSpinAsync(jobHandler, token);
|
||||
jobHandler.Job.State = JobState.Done;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
jobHandler.Job.State = JobState.Fail;
|
||||
jobHandler.Job.Results = null;
|
||||
jobHandler.Job.Error = exception.Message;
|
||||
jobHandler.OnProgress?.Invoke(jobHandler.Job);
|
||||
}
|
||||
|
||||
if (!jobHandlers.Any(j => j.Job.State == JobState.Waiting))
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
await VacuumAsync(token);
|
||||
sw.Stop();
|
||||
if (sw.ElapsedMilliseconds < 10_000)
|
||||
{
|
||||
var delayMs = 10_000 - (int)sw.ElapsedMilliseconds;
|
||||
await Task.Delay(delayMs, token);
|
||||
}
|
||||
CleanJobs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CleanJobs()
|
||||
{
|
||||
lock (jobHandlers)
|
||||
{
|
||||
jobHandlers.RemoveAll(j => j.Job.State == JobState.Done || j.Job.State == JobState.Fail);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task VacuumAsync(CancellationToken token)
|
||||
{
|
||||
using var db = MakeContext();
|
||||
var sqlVacuum = "vacuum (SKIP_LOCKED);";
|
||||
await db.Database.ExecuteSqlRawAsync(sqlVacuum, token);
|
||||
}
|
||||
|
||||
private void Stop()
|
||||
{
|
||||
cancellationTokenSource?.Cancel();
|
||||
task?.Wait(1_000);
|
||||
task = null;
|
||||
cancellationTokenSource?.Dispose();
|
||||
cancellationTokenSource = null;
|
||||
}
|
||||
|
||||
private Task RediceSamplingSaubAsync(JobHandle job, CancellationToken token)
|
||||
{
|
||||
const int ramLimit = 10 * 1024 * 1024;
|
||||
const int dataItemSize = 345; // by profiler
|
||||
const int chankSize = ramLimit / dataItemSize; // ~ 90_000
|
||||
const double maxWellDepthGap = 0.1;
|
||||
|
||||
var maxDateGapSec = ratio;
|
||||
|
||||
var sqlSelectTemplate =
|
||||
"select " +
|
||||
" * " +
|
||||
"from " +
|
||||
" (select " +
|
||||
" *, " +
|
||||
" rank() over win1 as row_num, " +
|
||||
" lag(\"date\", 1) over win1 as lag_date, " +
|
||||
" lag(\"mode\", 1) over win1 as lag_mode, " +
|
||||
" lag(mse_state, 1) over win1 as lag_mse_state, " +
|
||||
" lag(well_depth, 1) over win1 as lag_well_depth, " +
|
||||
" lag(id_feed_regulator, 1) over win1 as lag_id_feed_regulator " +
|
||||
" from t_telemetry_data_saub " +
|
||||
$" where id_telemetry = {job.Id} and \"date\" > {{0}}" +
|
||||
" window win1 as (order by \"date\") " +
|
||||
" ) as t_1 " +
|
||||
"where " +
|
||||
$" (row_num % {ratio}) = 0 " +
|
||||
" or \"mode\" != lag_mode " +
|
||||
$" or(\"date\" - lag_date) >= interval '{maxDateGapSec} second' " +
|
||||
$" or well_depth - lag_well_depth > {maxWellDepthGap:#0,0#} " +
|
||||
" or mse_state != lag_mse_state " +
|
||||
" or id_feed_regulator != lag_id_feed_regulator " +
|
||||
"order by \"date\" ";
|
||||
|
||||
var sqlDeleteTemplate = "delete " +
|
||||
"from t_telemetry_data_saub " +
|
||||
$"where id_telemetry = {job.Id} and \"date\" between {{0}} and {{1}};";
|
||||
|
||||
return RediceSamplingAsync<TelemetryDataSaub>(
|
||||
job,
|
||||
chankSize,
|
||||
sqlSelectTemplate,
|
||||
sqlDeleteTemplate,
|
||||
token);
|
||||
}
|
||||
|
||||
private Task RediceSamplingSpinAsync(JobHandle job, CancellationToken token)
|
||||
{
|
||||
const int ramLimit = 10 * 1024 * 1024;
|
||||
const int dataItemSize = 345; // by profiler
|
||||
const int chankSize = ramLimit / dataItemSize; // ~ 90_000
|
||||
var maxDateGapSec = ratio;
|
||||
|
||||
var sqlSelectTemplate =
|
||||
"select " +
|
||||
" * " +
|
||||
"from " +
|
||||
" (select " +
|
||||
" *, " +
|
||||
" rank() over win1 as row_num, " +
|
||||
" lag(\"date\", 1) over win1 as lag_date, " +
|
||||
" lag(\"mode\", 1) over win1 as lag_mode, " +
|
||||
" lag(state, 1) over win1 as lag_state " +
|
||||
" from t_telemetry_data_spin " +
|
||||
$" where id_telemetry = {job.Id} and \"date\" > {{0}}" +
|
||||
" window win1 as (order by \"date\") " +
|
||||
" ) as t_1 " +
|
||||
"where " +
|
||||
$" (row_num % {ratio}) = 0 " +
|
||||
" or \"mode\" != lag_mode " +
|
||||
$" or(\"date\" - lag_date) >= interval '{maxDateGapSec} second' " +
|
||||
" or state != lag_state " +
|
||||
"order by \"date\" ";
|
||||
|
||||
var sqlDeleteTemplate = "delete " +
|
||||
"from t_telemetry_data_spin " +
|
||||
$"where id_telemetry = {job.Id} and \"date\" between {{0}} and {{1}};";
|
||||
|
||||
return RediceSamplingAsync<TelemetryDataSpin>(
|
||||
job,
|
||||
chankSize,
|
||||
sqlSelectTemplate,
|
||||
sqlDeleteTemplate,
|
||||
token);
|
||||
}
|
||||
|
||||
private async Task RediceSamplingAsync<TEntity>(
|
||||
JobHandle jobHandle,
|
||||
int chankSize,
|
||||
string sqlSelectTemplate,
|
||||
string sqlDeleteTemplate,
|
||||
CancellationToken token)
|
||||
where TEntity : class, AsbCloudDb.Model.ITelemetryData
|
||||
{
|
||||
using var db = MakeContext();
|
||||
var dbset = db.Set<TEntity>();
|
||||
|
||||
var deleted = 0;
|
||||
var totalCount = await dbset.Where(t => t.IdTelemetry == jobHandle.Id).CountAsync(token);
|
||||
|
||||
var result = jobHandle.Job.Results!;
|
||||
if (result[jobResultKeyDeleted] is int previousDeleted)
|
||||
deleted += previousDeleted;
|
||||
|
||||
if (result[jobResultKeyTotal] is int previousCount)
|
||||
totalCount += previousCount;
|
||||
|
||||
result[jobResultKeyDeleted] = deleted;
|
||||
result[jobResultKeyTotal] = totalCount;
|
||||
|
||||
jobHandle.OnProgress?.Invoke(jobHandle.Job);
|
||||
var startDate = DateTimeOffset.MinValue;
|
||||
|
||||
do
|
||||
{
|
||||
var query = dbset
|
||||
.FromSqlRaw(sqlSelectTemplate, startDate)
|
||||
.AsNoTracking();
|
||||
|
||||
var data = await query
|
||||
.Take(chankSize)
|
||||
.ToArrayAsync(token);
|
||||
|
||||
var currentDataCount = data.Length;
|
||||
if (currentDataCount == 0)
|
||||
break;
|
||||
|
||||
var lastDate = data.Last().DateTime;
|
||||
|
||||
var currentDeleted = await db.Database.ExecuteSqlRawAsync(sqlDeleteTemplate, new object[] { startDate, lastDate }.AsEnumerable(), token);
|
||||
if (currentDeleted == 0)
|
||||
break;
|
||||
|
||||
await db.Database.ExecInsertAsync(dbset, data, token);
|
||||
|
||||
startDate = lastDate;
|
||||
deleted += currentDeleted;
|
||||
result[jobResultKeyDeleted] = deleted;
|
||||
result[jobResultKeyTotal] = totalCount;
|
||||
jobHandle.OnProgress?.Invoke(jobHandle.Job);
|
||||
} while (true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private AsbCloudDbContext MakeContext()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
|
||||
.UseNpgsql(connectionString)
|
||||
.Options;
|
||||
|
||||
return new AsbCloudDbContext(options);
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Repository;
|
||||
using AsbSaubReport;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -65,7 +66,9 @@ namespace AsbCloudInfrastructure.Services
|
||||
};
|
||||
generator.Make(reportFileName);
|
||||
|
||||
var fileService = new FileService(context);
|
||||
var fileRepository = new FileRepository(context);
|
||||
var fileStorageRepository = new FileStorageRepository();
|
||||
var fileService = new FileService(fileRepository, fileStorageRepository);
|
||||
var fileInfo = await fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName, token);
|
||||
|
||||
progressHandler.Invoke(new
|
||||
|
@ -16,7 +16,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
where TDto : AsbCloudApp.Data.ITelemetryData
|
||||
where TModel : class, AsbCloudDb.Model.ITelemetryData
|
||||
{
|
||||
private readonly IAsbCloudDbContext db;
|
||||
protected readonly IAsbCloudDbContext db;
|
||||
private readonly ITelemetryService telemetryService;
|
||||
protected readonly CacheTable<Telemetry> cacheTelemetry;
|
||||
protected readonly CacheTable<TelemetryUser> cacheTelemetryUsers;
|
||||
@ -134,25 +134,6 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
if (fullDataCount > 1.75 * approxPointsCount)
|
||||
{
|
||||
var m = (int)Math.Round(1d * fullDataCount / approxPointsCount);
|
||||
|
||||
switch (m)
|
||||
{
|
||||
//case var i when i <= 1: // тут для полноты, но никогда не сработает из-за условия выше
|
||||
// break;
|
||||
case var i when i < 10:
|
||||
query = query.Where((d) => d.DateTime.Second % m == 0);
|
||||
break;
|
||||
case var i when i < 30:
|
||||
query = query.Where((d) => (d.DateTime.Minute * 60 + d.DateTime.Second) % m == 0);
|
||||
break;
|
||||
case var i when i < 600:
|
||||
query = query.Where((d) => ((d.DateTime.Hour * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0);
|
||||
break;
|
||||
default:
|
||||
query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (m > 1)
|
||||
query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0);
|
||||
}
|
||||
@ -189,5 +170,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,12 @@
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Services.Cache;
|
||||
using DocumentFormat.OpenXml.Drawing.Charts;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.SAUB
|
||||
{
|
||||
|
@ -3,6 +3,8 @@ using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Services.Cache;
|
||||
using Mapster;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.SAUB
|
||||
{
|
||||
|
@ -145,8 +145,8 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
SumDepthInterval = periodGroupDepth,
|
||||
OperationCount = g.Count()
|
||||
};
|
||||
if(subsystemStat.KUsage > 100)
|
||||
subsystemStat.KUsage = 100;
|
||||
if(subsystemStat.KUsage > 1)
|
||||
subsystemStat.KUsage = 1;
|
||||
return subsystemStat;
|
||||
});
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Repository;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -21,7 +23,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
public class WellFinalDocumentsService : IWellFinalDocumentsService
|
||||
{
|
||||
private readonly IAsbCloudDbContext context;
|
||||
private readonly IFileService fileService;
|
||||
private readonly FileService fileService;
|
||||
private readonly IUserService userService;
|
||||
private readonly IWellService wellService;
|
||||
private readonly IConfiguration configuration;
|
||||
@ -31,7 +33,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
private const int FileServiceThrewException = -1;
|
||||
|
||||
public WellFinalDocumentsService(IAsbCloudDbContext context,
|
||||
IFileService fileService,
|
||||
FileService fileService,
|
||||
IUserService userService,
|
||||
IWellService wellService,
|
||||
IConfiguration configuration,
|
||||
@ -95,7 +97,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
.Select(g => g.Key);
|
||||
|
||||
var files = (await fileService
|
||||
.GetInfosByWellIdAsync(idWell, token)
|
||||
.GetInfosAsync(new FileRequest { IdWell = idWell}, token)
|
||||
.ConfigureAwait(false))
|
||||
.Where(f => categoriesIds.Contains(f.IdCategory))
|
||||
.ToArray();
|
||||
@ -161,7 +163,12 @@ namespace AsbCloudInfrastructure.Services
|
||||
|
||||
public async Task<WellFinalDocumentsHistoryDto> GetFilesHistoryByIdCategory(int idWell, int idCategory, CancellationToken token)
|
||||
{
|
||||
var files = await fileService.GetInfosByCategoryAsync(idWell, idCategory, token).ConfigureAwait(false);
|
||||
var request = new FileRequest
|
||||
{
|
||||
IdWell = idWell,
|
||||
IdCategory = idCategory,
|
||||
};
|
||||
var files = await fileService.GetInfosAsync(request, token).ConfigureAwait(false);
|
||||
|
||||
return new WellFinalDocumentsHistoryDto {
|
||||
IdWell = idWell,
|
||||
|
9
AsbCloudInfrastructure/Services/_Readme.md
Normal file
9
AsbCloudInfrastructure/Services/_Readme.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Создание репозитория для сервися
|
||||
|
||||
1. Создать интерфейс репозитория в AsbCloudApp.Services
|
||||
2. Создать репозиторий в AsbCloudInfrastructure.Repository, наследоваться от созданного интерфейса, в нем добавить работу с БД
|
||||
3. Добавить репозиторий в AsbCloudInfrastructure.DependencyInjection
|
||||
4. Добавить в конструктор сервиса новый репозиторий и использовать его методы
|
||||
5. Перенести сервис из AsbCloudInfrastructure.Services в AsbCloudApp.Services
|
||||
6. Добавить или поправить тесты на изменяемый сервис используя AsbCloudWebApi.Tests.RepositoryFactory
|
||||
7. В тестах сделать мок данных для репозитория
|
@ -5,6 +5,7 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace AsbCloudInfrastructure
|
||||
{
|
||||
|
@ -4,6 +4,8 @@
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
17
AsbCloudWebApi.Tests/IRepositoryFactory.cs
Normal file
17
AsbCloudWebApi.Tests/IRepositoryFactory.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudWebApi.Tests
|
||||
{
|
||||
public interface IRepositoryFactory<TDto>
|
||||
{
|
||||
Task<int> DeleteAsync(int id, CancellationToken token);
|
||||
Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token);
|
||||
TDto? GetOrDefault(int id);
|
||||
Task<TDto?> GetOrDefaultAsync(int id, CancellationToken token);
|
||||
Task<int> InsertAsync(TDto newItem, CancellationToken token);
|
||||
Task<int> InsertRangeAsync(IEnumerable<TDto> newItems, CancellationToken token);
|
||||
Task<int> UpdateAsync(TDto item, CancellationToken token);
|
||||
}
|
||||
}
|
42
AsbCloudWebApi.Tests/RepositoryFactory.cs
Normal file
42
AsbCloudWebApi.Tests/RepositoryFactory.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using AsbCloudApp.Services;
|
||||
using Moq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudWebApi.Tests
|
||||
{
|
||||
public class RepositoryFactory
|
||||
{
|
||||
public static Mock<TRepository> Make<TRepository, TDto>(ICollection<TDto> data)
|
||||
where TDto : AsbCloudApp.Data.IId
|
||||
where TRepository : class, ICrudService<TDto>
|
||||
{
|
||||
var repositoryMock = new Mock<TRepository>();
|
||||
|
||||
repositoryMock.Setup(x => x.InsertAsync(It.IsAny<TDto>(), It.IsAny<CancellationToken>()))
|
||||
.Returns((TDto dto, CancellationToken token) => {
|
||||
var id = data.Max(x => x.Id);
|
||||
dto.Id = ++id;
|
||||
data.Add(dto);
|
||||
return Task.FromResult(dto.Id);
|
||||
});
|
||||
repositoryMock.Setup(x => x.DeleteAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.Returns((int idFile, CancellationToken token) => {
|
||||
var cnt = data.Count;
|
||||
var dto = data.FirstOrDefault(x => x.Id == idFile);
|
||||
data.Remove(dto);
|
||||
return Task.FromResult(cnt - data.Count);
|
||||
});
|
||||
|
||||
repositoryMock.Setup(x => x.GetAllAsync(It.IsAny<CancellationToken>())).ReturnsAsync(data);
|
||||
repositoryMock.Setup(x => x.GetOrDefaultAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.Returns((int idFile, CancellationToken token) => {
|
||||
return Task.FromResult(data.FirstOrDefault(x => x.Id == idFile));
|
||||
});
|
||||
|
||||
return repositoryMock;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Repository;
|
||||
using AsbCloudInfrastructure.Services.DrillingProgram;
|
||||
using Mapster;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -77,7 +78,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
new RelationCompanyWell { IdCompany = 3003, IdWell = 3002, },
|
||||
};
|
||||
|
||||
private readonly Mock<IFileService> fileServiceMock;
|
||||
private readonly Mock<FileService> fileServiceMock;
|
||||
private readonly Mock<IUserService> userServiceMock;
|
||||
private readonly Mock<IWellService> wellServiceMock;
|
||||
private readonly Mock<IConfiguration> configurationMock;
|
||||
@ -96,7 +97,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
db.RelationCompaniesWells.AddRange(relationsCompanyWell);
|
||||
db.SaveChanges();
|
||||
|
||||
fileServiceMock = new Mock<IFileService>();
|
||||
fileServiceMock = new Mock<FileService>();
|
||||
userServiceMock = new Mock<IUserService>();
|
||||
wellServiceMock = new Mock<IWellService>();
|
||||
configurationMock = new Mock<IConfiguration>();
|
||||
@ -219,7 +220,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
{
|
||||
ConfigureNotApproved();
|
||||
fileServiceMock
|
||||
.Setup(s => s.GetInfoAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.Setup(s => s.GetOrDefaultAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(file1002.Adapt<FileInfoDto>()));
|
||||
|
||||
fileServiceMock
|
||||
@ -250,7 +251,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
{
|
||||
ConfigureNotApproved();
|
||||
fileServiceMock
|
||||
.Setup(s => s.GetInfoAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.Setup(s => s.GetOrDefaultAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(file1002.Adapt<FileInfoDto>()));
|
||||
|
||||
fileServiceMock
|
||||
|
200
AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs
Normal file
200
AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs
Normal file
@ -0,0 +1,200 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using Moq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
{
|
||||
public class FileServiceTest
|
||||
{
|
||||
private FileService fileService;
|
||||
|
||||
private static UserDto Author = new UserDto {
|
||||
Id = 1,
|
||||
IdCompany = 1
|
||||
};
|
||||
|
||||
private static List<FileMarkDto> FileMarks = new List<FileMarkDto> {
|
||||
new FileMarkDto
|
||||
{
|
||||
Id = 132,
|
||||
IdFile = 1742,
|
||||
User = Author,
|
||||
Comment = "qqq",
|
||||
IdMarkType = 1,
|
||||
DateCreated = DateTime.Now,
|
||||
IsDeleted = false
|
||||
},
|
||||
new FileMarkDto
|
||||
{
|
||||
Id = 133,
|
||||
IdFile = 1742,
|
||||
User = Author,
|
||||
Comment = "qqq3",
|
||||
IdMarkType = 1,
|
||||
DateCreated = DateTime.Now,
|
||||
IsDeleted = false
|
||||
}
|
||||
};
|
||||
|
||||
private static List<FileInfoDto> Files = new List<FileInfoDto> {
|
||||
new FileInfoDto {
|
||||
Id = 1742,
|
||||
IdAuthor = 1,
|
||||
Author = Author,
|
||||
IdWell = 90,
|
||||
IdCategory = 10040,
|
||||
Name = "test.txt",
|
||||
Size = 0,
|
||||
UploadDate = DateTime.Now,
|
||||
FileMarks = FileMarks
|
||||
},
|
||||
new FileInfoDto
|
||||
{
|
||||
Id = 1743,
|
||||
IdAuthor = 1,
|
||||
Author = Author,
|
||||
IdWell = 90,
|
||||
IdCategory = 10021,
|
||||
Name = "test1.txt",
|
||||
Size = 0,
|
||||
UploadDate = DateTime.Now
|
||||
}
|
||||
};
|
||||
|
||||
public FileServiceTest()
|
||||
{
|
||||
var repositoryMock = RepositoryFactory.Make<IFileRepository, FileInfoDto>(Files);
|
||||
|
||||
repositoryMock.Setup(x => x.GetByMarkId(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.Returns((int idMark, CancellationToken token) => {
|
||||
var data = Files.FirstOrDefault(x => x.FileMarks.Any(m => m.Id == idMark));
|
||||
return Task.FromResult(data);
|
||||
});
|
||||
repositoryMock.Setup(x => x.GetInfoByIdsAsync(It.IsAny<IEnumerable<int>>(), It.IsAny<CancellationToken>()))
|
||||
.Returns((int[] idsFile, CancellationToken token) => {
|
||||
var data = Files.Where(x => idsFile.Contains(x.Id));
|
||||
return Task.FromResult(data);
|
||||
});
|
||||
|
||||
repositoryMock.Setup(x => x.DeleteAsync(It.IsAny<IEnumerable<int>>(), It.IsAny<CancellationToken>()))
|
||||
.Returns((int[] idsFile, CancellationToken token) => {
|
||||
var dtos = Files.Where(x => idsFile.Contains(x.Id)).ToArray();
|
||||
Files.RemoveAll(x => dtos.Select(d => d.Id).Contains(x.Id));
|
||||
return Task.FromResult(dtos.AsEnumerable());
|
||||
});
|
||||
|
||||
repositoryMock.Setup(x => x.MarkFileMarkAsDeletedAsync(It.IsAny<IEnumerable<int>>(), It.IsAny<CancellationToken>()))
|
||||
.Returns((int[] idsMarks, CancellationToken token) => {
|
||||
var data = FileMarks.Where(m => idsMarks.Contains(m.Id));
|
||||
|
||||
foreach (var fileMark in data)
|
||||
fileMark.IsDeleted = true;
|
||||
|
||||
var result = data.All(x => x.IsDeleted) ? 1 : 0;
|
||||
return Task.FromResult(result);
|
||||
});
|
||||
|
||||
repositoryMock.Setup(x => x.MarkAsDeletedAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.Returns((int idFile, CancellationToken token) => {
|
||||
var result = Files.Where(x => x.Id == idFile).Any() ? 1 : 0;
|
||||
return Task.FromResult(result);
|
||||
});
|
||||
|
||||
repositoryMock.Setup(x => x.GetInfosAsync(It.IsAny<FileRequest>(), It.IsAny<CancellationToken>()))
|
||||
.Returns((FileRequest request, CancellationToken token) => {
|
||||
var data = Files.Where(x => x.IdWell == request.IdWell);
|
||||
return Task.FromResult(data);
|
||||
});
|
||||
|
||||
repositoryMock.Setup(x => x.CreateFileMarkAsync(It.IsAny<FileMarkDto>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.Returns((FileMarkDto dto, int idUser, CancellationToken token) => {
|
||||
dto.Id = FileMarks.Max(x => x.Id) + 1;
|
||||
dto.DateCreated = DateTime.UtcNow;
|
||||
dto.User = null;
|
||||
FileMarks.Add(dto);
|
||||
|
||||
var result = FileMarks.Any(x => x.Id == dto.Id) ? 1 : 0;
|
||||
return Task.FromResult(result);
|
||||
});
|
||||
|
||||
var storageRepositoryMock = new Mock<IFileStorageRepository>();
|
||||
storageRepositoryMock.Setup(x => x.GetUrl(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>()))
|
||||
.Returns((int idWell, int idCategory, int idFile, string dotExtention) => {
|
||||
return Path.Combine("files", idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}");
|
||||
});
|
||||
|
||||
fileService = new FileService(repositoryMock.Object, storageRepositoryMock.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetByMarkId_returns_FileInfo_by_idMark()
|
||||
{
|
||||
var data = await fileService.GetByMarkId(133, CancellationToken.None);
|
||||
Assert.NotNull(data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetOrDefaultAsync_returns_FileInfo()
|
||||
{
|
||||
var data = await fileService.GetOrDefaultAsync(1742, CancellationToken.None);
|
||||
Assert.NotNull(data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetInfoByIdsAsync_returns_FileInfo()
|
||||
{
|
||||
var data = await fileService.GetInfoByIdsAsync(new int[] { 1742, 1743 }, CancellationToken.None);
|
||||
Assert.NotNull(data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SaveAsync_returns_FileInfo()
|
||||
{
|
||||
using var stream = new MemoryStream(Array.Empty<byte>());
|
||||
var data = await fileService.SaveAsync(90, 1, 10040, "test.txt", stream, CancellationToken.None);
|
||||
Assert.NotNull(data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAsync()
|
||||
{
|
||||
var result = await fileService.DeleteAsync(new int[] { 1743 }, CancellationToken.None);
|
||||
Assert.True(result > 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MarkFileMarkAsDeletedAsync()
|
||||
{
|
||||
var result = await fileService.MarkFileMarkAsDeletedAsync(new int[] { 132, 133 }, CancellationToken.None);
|
||||
Assert.True(result > 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MarkAsDeletedAsync()
|
||||
{
|
||||
var result = await fileService.MarkAsDeletedAsync(1742, CancellationToken.None);
|
||||
Assert.True(result > 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateFileMarkAsync()
|
||||
{
|
||||
var dto = new FileMarkDto {
|
||||
Comment = "test",
|
||||
IdFile = 1742,
|
||||
IdMarkType = 1
|
||||
};
|
||||
var result = await fileService.CreateFileMarkAsync(dto, 1, CancellationToken.None);
|
||||
Assert.True(result > 0);
|
||||
}
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
{
|
||||
private readonly AsbCloudDbContext context;
|
||||
private WellFinalDocumentsService service;
|
||||
private readonly Mock<IFileService> fileServiceMock;
|
||||
private readonly Mock<FileService> fileServiceMock;
|
||||
private readonly Mock<IUserService> userServiceMock;
|
||||
private readonly Mock<IWellService> wellServiceMock;
|
||||
private readonly Mock<IConfiguration> configurationMock;
|
||||
@ -44,7 +44,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
context = TestHelpter.MakeTestContext();
|
||||
context.SaveChanges();
|
||||
|
||||
fileServiceMock = new Mock<IFileService>();
|
||||
fileServiceMock = new Mock<FileService>();
|
||||
userServiceMock = new Mock<IUserService>();
|
||||
userServiceMock.Setup(x => x.GetAllAsync(CancellationToken.None)).Returns(Task.Run(() => users.Select(x => (UserExtendedDto)x)));
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
|
||||
|
@ -1,15 +1,17 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudWebApi.Controllers
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Хранение файлов
|
||||
/// </summary>
|
||||
@ -18,10 +20,10 @@ namespace AsbCloudWebApi.Controllers
|
||||
[Authorize]
|
||||
public class FileController : ControllerBase
|
||||
{
|
||||
private readonly IFileService fileService;
|
||||
private readonly FileService fileService;
|
||||
private readonly IWellService wellService;
|
||||
|
||||
public FileController(IFileService fileService, IWellService wellService)
|
||||
public FileController(FileService fileService, IWellService wellService)
|
||||
{
|
||||
this.fileService = fileService;
|
||||
this.wellService = wellService;
|
||||
@ -68,38 +70,27 @@ namespace AsbCloudWebApi.Controllers
|
||||
/// <summary>
|
||||
/// Возвращает информацию о файлах для скважины в выбраной категории
|
||||
/// </summary>
|
||||
/// <param name="idWell">id скважины</param>
|
||||
/// <param name="idCategory">id категории файла</param>
|
||||
/// <param name="companyName">id компаний для фильтрации возвращаемых файлов</param>
|
||||
/// <param name="fileName">часть имени файла для поиска</param>
|
||||
/// <param name="begin">дата начала</param>
|
||||
/// <param name="end">дата окончания</param>
|
||||
/// <param name="skip">для пагинации кол-во записей пропустить</param>
|
||||
/// <param name="take">для пагинации кол-во записей взять </param>
|
||||
/// <param name="request"> </param>
|
||||
/// <param name="token"> Токен отмены задачи </param>
|
||||
/// <returns>Список информации о файлах в этой категории</returns>
|
||||
[HttpGet]
|
||||
[Route("/api/files")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(PaginationContainer<FileInfoDto>), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> GetFilesInfoAsync(
|
||||
[FromRoute] int idWell,
|
||||
int idCategory = default,
|
||||
string companyName = default,
|
||||
string fileName = default,
|
||||
DateTime begin = default,
|
||||
DateTime end = default,
|
||||
int skip = 0,
|
||||
int take = 32,
|
||||
[FromQuery] FileRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
int? idCompany = User.GetCompanyId();
|
||||
|
||||
if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
idWell, token).ConfigureAwait(false))
|
||||
if (request.IdCategory is null || idCompany is null)
|
||||
return Forbid();
|
||||
|
||||
var filesInfo = await fileService.GetInfosAsync(idWell, idCategory,
|
||||
companyName, fileName, begin, end, skip, take, token).ConfigureAwait(false);
|
||||
if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value,
|
||||
request.IdWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
var filesInfo = await fileService.GetInfosPaginatedAsync(request, token).ConfigureAwait(false);
|
||||
|
||||
return Ok(filesInfo);
|
||||
}
|
||||
@ -108,36 +99,33 @@ namespace AsbCloudWebApi.Controllers
|
||||
/// Возвращает файл с диска на сервере
|
||||
/// </summary>
|
||||
/// <param name="idWell">id скважины</param>
|
||||
/// <param name="fileId">id запрашиваемого файла</param>
|
||||
/// <param name="idFile">id запрашиваемого файла</param>
|
||||
/// <param name="token"> Токен отмены задачи </param>
|
||||
/// <returns>Запрашиваемый файл</returns>
|
||||
[HttpGet]
|
||||
[Route("{fileId}")]
|
||||
[Route("{idFile}")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> GetFileAsync([FromRoute] int idWell,
|
||||
int fileId, CancellationToken token = default)
|
||||
int idFile, CancellationToken token = default)
|
||||
{
|
||||
int? idCompany = User.GetCompanyId();
|
||||
|
||||
if (idCompany is null)
|
||||
return Forbid();
|
||||
|
||||
var fileInfo = await fileService.GetOrDefaultAsync(idFile, token);
|
||||
|
||||
if (fileInfo is null)
|
||||
return NotFound(idFile);
|
||||
|
||||
if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
idWell, token).ConfigureAwait(false))
|
||||
fileInfo.IdWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
try
|
||||
{
|
||||
var fileInfo = await fileService.GetInfoAsync(fileId, token);
|
||||
var fileStream = fileService.GetFileStream(fileInfo);
|
||||
|
||||
var relativePath = fileService.GetUrl(fileInfo);
|
||||
return PhysicalFile(Path.GetFullPath(relativePath), "application/octet-stream", fileInfo.Name);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
return NotFound(ex.FileName);
|
||||
}
|
||||
return File(fileStream, "application/octet-stream", fileInfo.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -159,13 +147,16 @@ namespace AsbCloudWebApi.Controllers
|
||||
|
||||
int? idCompany = User.GetCompanyId();
|
||||
|
||||
if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
if (idUser is null || idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||
idWell, token).ConfigureAwait(false))
|
||||
return Forbid();
|
||||
|
||||
var file = await fileService.GetInfoAsync((int)idFile, token);
|
||||
var fileInfo = await fileService.GetOrDefaultAsync(idFile, token);
|
||||
|
||||
if (!userService.HasPermission((int)idUser, $"File.edit{file.IdCategory}"))
|
||||
if (fileInfo is null)
|
||||
return NotFound(idFile);
|
||||
|
||||
if (!userService.HasPermission((int)idUser, $"File.edit{fileInfo?.IdCategory}"))
|
||||
return Forbid();
|
||||
|
||||
var result = await fileService.MarkAsDeletedAsync(idFile, token);
|
||||
@ -223,5 +214,34 @@ namespace AsbCloudWebApi.Controllers
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает информацию о файле
|
||||
/// </summary>
|
||||
/// <param name="idFile">id запрашиваемого файла</param>
|
||||
/// <param name="token"> Токен отмены задачи </param>
|
||||
/// <returns>Запрашиваемый файл</returns>
|
||||
[HttpGet]
|
||||
[Route("/api/files/{idFile}")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(FileInfoDto), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> GetFileInfoAsync([FromRoute] int idFile, CancellationToken token = default)
|
||||
{
|
||||
int? idCompany = User.GetCompanyId();
|
||||
|
||||
if (idCompany is null)
|
||||
return Forbid();
|
||||
|
||||
try
|
||||
{
|
||||
var fileInfo = await fileService.GetOrDefaultAsync(idFile, token).ConfigureAwait(false);
|
||||
return Ok(fileInfo);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
return NotFound(ex.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
}
|
||||
|
78
AsbCloudWebApi/Controllers/ReduceSamplingController.cs
Normal file
78
AsbCloudWebApi/Controllers/ReduceSamplingController.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using AsbCloudApp.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data;
|
||||
using System.Linq;
|
||||
using AsbCloudWebApi.SignalR;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace AsbCloudWebApi.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// Редактор кустов для админки
|
||||
/// </summary>
|
||||
[Route("api/admin/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class ReduceSamplingController: ControllerBase
|
||||
{
|
||||
private readonly IReduceSamplingService service;
|
||||
private readonly IHubContext<TelemetryHub> telemetryHubContext;
|
||||
private const string sirnalRGroupName = "ReduceSampling";
|
||||
private const string sirnalRMethodOnProgress = "OnProgress";
|
||||
|
||||
public ReduceSamplingController(
|
||||
IReduceSamplingService service,
|
||||
IHubContext<TelemetryHub> telemetryHubContext )
|
||||
{
|
||||
this.service = service;
|
||||
this.telemetryHubContext = telemetryHubContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получить все задания. Задания удаляются минимум через 10 сек после выполнения, возможно позднее.
|
||||
/// </summary>
|
||||
/// <param name="idTelemetry"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public virtual ActionResult<IEnumerable<JobDto>> GetAll(int idTelemetry)
|
||||
{
|
||||
var result = service.GetJobs();
|
||||
if (result.Any())
|
||||
return Ok(result);
|
||||
else
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получить состояние определенной задачи
|
||||
/// </summary>
|
||||
/// <param name="idTelemetry"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{idTelemetry}")]
|
||||
public virtual ActionResult<JobDto> GetOrDefault(int idTelemetry)
|
||||
{
|
||||
var result = service.GetOrDefaultState(idTelemetry);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создать задачу прореживанию архива и добавить её в очередь на выполнение.
|
||||
/// Если задача есть в очереди, она же и возвращается, но подписка не происходит.
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Permission]
|
||||
public virtual ActionResult<JobDto> Enqueue(int idTelemetry)
|
||||
{
|
||||
void onProgress(JobDto job) =>
|
||||
Task.Run(async () =>
|
||||
await telemetryHubContext.Clients.Group(sirnalRGroupName)
|
||||
.SendAsync(sirnalRMethodOnProgress, job));
|
||||
|
||||
service.TryEnqueueRediceSamplingJob(idTelemetry, onProgress, out JobDto job);
|
||||
return Ok(job);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,12 +18,12 @@ namespace AsbCloudWebApi.Controllers
|
||||
public class ReportController : ControllerBase
|
||||
{
|
||||
private readonly IReportService reportService;
|
||||
private readonly IFileService fileService;
|
||||
private readonly FileService fileService;
|
||||
private readonly IWellService wellService;
|
||||
private readonly IHubContext<ReportsHub> reportsHubContext;
|
||||
|
||||
public ReportController(IReportService reportService, IWellService wellService,
|
||||
IFileService fileService, IHubContext<ReportsHub> reportsHubContext)
|
||||
FileService fileService, IHubContext<ReportsHub> reportsHubContext)
|
||||
{
|
||||
this.reportService = reportService;
|
||||
this.fileService = fileService;
|
||||
|
@ -1,3 +1,4 @@
|
||||
using DocumentFormat.OpenXml.InkML;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -25,7 +26,10 @@ namespace AsbCloudWebApi
|
||||
{
|
||||
var connectionStringName = "DefaultConnection";
|
||||
|
||||
AsbCloudInfrastructure.DependencyInjection.MakeContext(configuration.GetConnectionString(connectionStringName));
|
||||
var context = AsbCloudInfrastructure.DependencyInjection.MakeContext(configuration.GetConnectionString(connectionStringName));
|
||||
context.Database.SetCommandTimeout(TimeSpan.FromSeconds(5 * 60));
|
||||
context.Database.Migrate();
|
||||
|
||||
Console.WriteLine("Óñïåøíî âûïîëíåíî.");
|
||||
return;
|
||||
}
|
||||
|
21
AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml
Normal file
21
AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<DeleteExistingFiles>true</DeleteExistingFiles>
|
||||
<ExcludeApp_Data>false</ExcludeApp_Data>
|
||||
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
|
||||
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||
<PublishProvider>FileSystem</PublishProvider>
|
||||
<PublishUrl>bin\publishLinux\</PublishUrl>
|
||||
<WebPublishMethod>FileSystem</WebPublishMethod>
|
||||
<SiteUrlToLaunchAfterPublish />
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ProjectGuid>a2768702-47cb-4127-941c-e339d5efcffe</ProjectGuid>
|
||||
<SelfContained>true</SelfContained>
|
||||
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -296,69 +296,16 @@ namespace AsbCloudWebApi
|
||||
RuntimeTypeModel.Default.Add(type, false)
|
||||
.Add(1, nameof(TelemetryDataSpinDto.IdTelemetry))
|
||||
.Add(2, nameof(TelemetryDataSpinDto.DateTime))
|
||||
.Add(3, nameof(TelemetryDataSpinDto.TopDriveSpeed))
|
||||
.Add(4, nameof(TelemetryDataSpinDto.TopDriveSpeedMin))
|
||||
.Add(5, nameof(TelemetryDataSpinDto.TopDriveSpeedMax))
|
||||
.Add(6, nameof(TelemetryDataSpinDto.TopDriveSpeedOffset))
|
||||
.Add(7, nameof(TelemetryDataSpinDto.TopDriveSpeedErr))
|
||||
.Add(8, nameof(TelemetryDataSpinDto.TopDriveTorque))
|
||||
.Add(9, nameof(TelemetryDataSpinDto.TopDriveTorqueMin))
|
||||
.Add(10, nameof(TelemetryDataSpinDto.TopDriveTorqueMax))
|
||||
.Add(11, nameof(TelemetryDataSpinDto.TopDriveTorqueOffset))
|
||||
.Add(12, nameof(TelemetryDataSpinDto.TopDriveTorqueErr))
|
||||
.Add(13, nameof(TelemetryDataSpinDto.TopDriveSpeedSpFrom))
|
||||
.Add(14, nameof(TelemetryDataSpinDto.TopDriveSpeedSpFromMin))
|
||||
.Add(15, nameof(TelemetryDataSpinDto.TopDriveSpeedSpFromMax))
|
||||
.Add(16, nameof(TelemetryDataSpinDto.TopDriveSpeedSpFromOffset))
|
||||
.Add(17, nameof(TelemetryDataSpinDto.TopDriveSpeedSpFromErr))
|
||||
.Add(18, nameof(TelemetryDataSpinDto.TopDriveTorqueSpFrom))
|
||||
.Add(19, nameof(TelemetryDataSpinDto.TopDriveTorqueSpFromMin))
|
||||
.Add(20, nameof(TelemetryDataSpinDto.TopDriveTorqueSpFromMax))
|
||||
.Add(21, nameof(TelemetryDataSpinDto.TopDriveTorqueSpFromOffset))
|
||||
.Add(22, nameof(TelemetryDataSpinDto.TopDriveTorqueSpFromErr))
|
||||
.Add(23, nameof(TelemetryDataSpinDto.TopDriveSpeedSpTo))
|
||||
.Add(24, nameof(TelemetryDataSpinDto.TopDriveSpeedSpToMin))
|
||||
.Add(25, nameof(TelemetryDataSpinDto.TopDriveSpeedSpToMax))
|
||||
.Add(26, nameof(TelemetryDataSpinDto.TopDriveSpeedSpToOffset))
|
||||
.Add(27, nameof(TelemetryDataSpinDto.TopDriveSpeedSpToErr))
|
||||
.Add(28, nameof(TelemetryDataSpinDto.TopDriveTorqueSpTo))
|
||||
.Add(29, nameof(TelemetryDataSpinDto.TopDriveTorqueSpToMin))
|
||||
.Add(30, nameof(TelemetryDataSpinDto.TopDriveTorqueSpToMax))
|
||||
.Add(31, nameof(TelemetryDataSpinDto.TopDriveTorqueSpToOffset))
|
||||
.Add(32, nameof(TelemetryDataSpinDto.TopDriveTorqueSpToErr))
|
||||
.Add(33, nameof(TelemetryDataSpinDto.W2800))
|
||||
.Add(34, nameof(TelemetryDataSpinDto.W2810))
|
||||
.Add(35, nameof(TelemetryDataSpinDto.Mode))
|
||||
.Add(36, nameof(TelemetryDataSpinDto.W2808))
|
||||
.Add(37, nameof(TelemetryDataSpinDto.TorqueStarting))
|
||||
.Add(38, nameof(TelemetryDataSpinDto.RotorTorqueAvg))
|
||||
.Add(39, nameof(TelemetryDataSpinDto.EncoderResolution))
|
||||
.Add(40, nameof(TelemetryDataSpinDto.Ratio))
|
||||
.Add(41, nameof(TelemetryDataSpinDto.TorqueRightLimit))
|
||||
.Add(42, nameof(TelemetryDataSpinDto.TorqueLeftLimit))
|
||||
.Add(43, nameof(TelemetryDataSpinDto.RevolsRightLimit))
|
||||
.Add(44, nameof(TelemetryDataSpinDto.RevolsLeftLimit))
|
||||
.Add(45, nameof(TelemetryDataSpinDto.SpeedRightSp))
|
||||
.Add(46, nameof(TelemetryDataSpinDto.SpeedLeftSp))
|
||||
.Add(47, nameof(TelemetryDataSpinDto.RevolsRightTotal))
|
||||
.Add(48, nameof(TelemetryDataSpinDto.RevolsLeftTotal))
|
||||
.Add(49, nameof(TelemetryDataSpinDto.TurnRightOnceByTorque))
|
||||
.Add(50, nameof(TelemetryDataSpinDto.TurnLeftOnceByTorque))
|
||||
.Add(51, nameof(TelemetryDataSpinDto.TurnRightOnceByAngle))
|
||||
.Add(52, nameof(TelemetryDataSpinDto.TurnLeftOnceByAngle))
|
||||
.Add(53, nameof(TelemetryDataSpinDto.TurnRightOnceByRevols))
|
||||
.Add(54, nameof(TelemetryDataSpinDto.TurnLeftOnceByRevols))
|
||||
.Add(55, nameof(TelemetryDataSpinDto.BreakAngleK))
|
||||
.Add(56, nameof(TelemetryDataSpinDto.ReverseKTorque))
|
||||
.Add(57, nameof(TelemetryDataSpinDto.PositionZero))
|
||||
.Add(58, nameof(TelemetryDataSpinDto.PositionRight))
|
||||
.Add(59, nameof(TelemetryDataSpinDto.TorqueRampTime))
|
||||
.Add(60, nameof(TelemetryDataSpinDto.Ver))
|
||||
.Add(61, nameof(TelemetryDataSpinDto.ReverseSpeedSpZeroTime))
|
||||
.Add(62, nameof(TelemetryDataSpinDto.UnlockBySectorOut))
|
||||
.Add(63, nameof(TelemetryDataSpinDto.PidMuxTorqueLeftLimit))
|
||||
.Add(64, nameof(TelemetryDataSpinDto.State))
|
||||
.Add(65, nameof(TelemetryDataSpinDto.BreakAngleLeft));
|
||||
.Add(64, nameof(TelemetryDataSpinDto.State));
|
||||
}
|
||||
|
||||
static void EnshureRegisteredDataSaub()
|
||||
|
@ -1,50 +0,0 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.c2a82e71.chunk.css",
|
||||
"main.js": "/static/js/main.01e9ada9.chunk.js",
|
||||
"main.js.map": "/static/js/main.01e9ada9.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.8da12c69.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.8da12c69.js.map",
|
||||
"static/js/2.f196b75b.chunk.js": "/static/js/2.f196b75b.chunk.js",
|
||||
"static/js/2.f196b75b.chunk.js.map": "/static/js/2.f196b75b.chunk.js.map",
|
||||
"static/css/3.f8ac3883.chunk.css": "/static/css/3.f8ac3883.chunk.css",
|
||||
"static/js/3.31b66021.chunk.js": "/static/js/3.31b66021.chunk.js",
|
||||
"static/js/3.31b66021.chunk.js.map": "/static/js/3.31b66021.chunk.js.map",
|
||||
"static/css/4.f8ac3883.chunk.css": "/static/css/4.f8ac3883.chunk.css",
|
||||
"static/js/4.1f09e89e.chunk.js": "/static/js/4.1f09e89e.chunk.js",
|
||||
"static/js/4.1f09e89e.chunk.js.map": "/static/js/4.1f09e89e.chunk.js.map",
|
||||
"static/js/5.ef929bfe.chunk.js": "/static/js/5.ef929bfe.chunk.js",
|
||||
"static/js/5.ef929bfe.chunk.js.map": "/static/js/5.ef929bfe.chunk.js.map",
|
||||
"static/js/6.88051835.chunk.js": "/static/js/6.88051835.chunk.js",
|
||||
"static/js/6.88051835.chunk.js.map": "/static/js/6.88051835.chunk.js.map",
|
||||
"static/js/7.4f3c315a.chunk.js": "/static/js/7.4f3c315a.chunk.js",
|
||||
"static/js/7.4f3c315a.chunk.js.map": "/static/js/7.4f3c315a.chunk.js.map",
|
||||
"static/js/8.8e9a1dc7.chunk.js": "/static/js/8.8e9a1dc7.chunk.js",
|
||||
"static/js/8.8e9a1dc7.chunk.js.map": "/static/js/8.8e9a1dc7.chunk.js.map",
|
||||
"static/js/9.71667cac.chunk.js": "/static/js/9.71667cac.chunk.js",
|
||||
"static/js/9.71667cac.chunk.js.map": "/static/js/9.71667cac.chunk.js.map",
|
||||
"static/js/10.e5247b1b.chunk.js": "/static/js/10.e5247b1b.chunk.js",
|
||||
"static/js/10.e5247b1b.chunk.js.map": "/static/js/10.e5247b1b.chunk.js.map",
|
||||
"static/js/11.70112c8f.chunk.js": "/static/js/11.70112c8f.chunk.js",
|
||||
"static/js/11.70112c8f.chunk.js.map": "/static/js/11.70112c8f.chunk.js.map",
|
||||
"static/js/12.2265b74f.chunk.js": "/static/js/12.2265b74f.chunk.js",
|
||||
"static/js/12.2265b74f.chunk.js.map": "/static/js/12.2265b74f.chunk.js.map",
|
||||
"static/js/13.063a16c9.chunk.js": "/static/js/13.063a16c9.chunk.js",
|
||||
"static/js/13.063a16c9.chunk.js.map": "/static/js/13.063a16c9.chunk.js.map",
|
||||
"static/js/14.50a284b1.chunk.js": "/static/js/14.50a284b1.chunk.js",
|
||||
"static/js/14.50a284b1.chunk.js.map": "/static/js/14.50a284b1.chunk.js.map",
|
||||
"index.html": "/index.html",
|
||||
"static/css/3.f8ac3883.chunk.css.map": "/static/css/3.f8ac3883.chunk.css.map",
|
||||
"static/css/4.f8ac3883.chunk.css.map": "/static/css/4.f8ac3883.chunk.css.map",
|
||||
"static/css/main.c2a82e71.chunk.css.map": "/static/css/main.c2a82e71.chunk.css.map",
|
||||
"static/js/2.f196b75b.chunk.js.LICENSE.txt": "/static/js/2.f196b75b.chunk.js.LICENSE.txt",
|
||||
"static/media/ClusterIcon.f85713df.svg": "/static/media/ClusterIcon.f85713df.svg",
|
||||
"static/media/DepositIcon.9688e406.svg": "/static/media/DepositIcon.9688e406.svg"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/js/runtime-main.8da12c69.js",
|
||||
"static/js/2.f196b75b.chunk.js",
|
||||
"static/css/main.c2a82e71.chunk.css",
|
||||
"static/js/main.01e9ada9.chunk.js"
|
||||
]
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 354 KiB |
@ -1 +1 @@
|
||||
<!doctype html><html lang="ru"><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="white"/><meta name="theme-color" media="(prefers-color-scheme: light)" content="white"/><meta name="theme-color" media="(prefers-color-scheme: dark)" content="black"/><meta name="description" content="Онлайн мониторинг процесса бурения в реальном времени в офисе заказчика"/><title>АСБ Vision</title><script defer="defer" src="/vendors.5c0d0b53.js"></script><script defer="defer" src="/main.05a81b59.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
<!doctype html><html lang="ru"><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="white"/><meta name="theme-color" media="(prefers-color-scheme: light)" content="white"/><meta name="theme-color" media="(prefers-color-scheme: dark)" content="black"/><meta name="description" content="Онлайн мониторинг процесса бурения в реальном времени в офисе заказчика"/><title>DDrilling</title><script defer="defer" src="/vendors.1920da1d.js"></script><script defer="defer" src="/main.101601f2.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
@ -1,15 +0,0 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
@ -4,6 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<StartupObject>ConsoleApp1.Program</StartupObject>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,72 +1,39 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.DailyReport;
|
||||
using AsbCloudDb;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Services.DailyReport;
|
||||
using ClosedXML.Excel;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Org.BouncyCastle.Utilities.Collections;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ConsoleApp1
|
||||
{
|
||||
|
||||
class Program
|
||||
{
|
||||
private static AsbCloudDbContext db = ServiceFactory.Context;
|
||||
|
||||
// use ServiceFactory to make services
|
||||
static void Main(/*string[] args*/)
|
||||
{
|
||||
|
||||
var h = new Hashtable();
|
||||
h.Add("name", 1);
|
||||
h.Add("name2", "66");
|
||||
var v = h["v"];
|
||||
|
||||
var block = new HeadDto()
|
||||
{
|
||||
AzimuthAngle = 12,
|
||||
WellName = "WellName",
|
||||
ClusterName = "clusterName",
|
||||
Customer = "customer",
|
||||
Contractor = "Contractor",
|
||||
ReportDate = DateTime.Now,
|
||||
WellDepthIntervalFinishDate = 27.5,
|
||||
WellDepthIntervalStartDate = 26.5,
|
||||
BottomholeDepth = 66.6
|
||||
};
|
||||
var block2 = new BhaDto()
|
||||
{
|
||||
BHADescription = "sadasdasdasdasdasdjlaskjdaksjdlasdlalskdklj"
|
||||
};
|
||||
var block3 = new SaubDto();
|
||||
var bloks = new DailyReportDto()
|
||||
{
|
||||
Head = block,
|
||||
Saub = block3
|
||||
};
|
||||
var s = System.Text.Json.JsonSerializer.Serialize(h);
|
||||
|
||||
|
||||
|
||||
var service = new DailyReportMakerExcel();
|
||||
var stream = service.MakeReportFromBlocks(bloks);
|
||||
var filename = "____.xlsx";
|
||||
if (File.Exists(filename))
|
||||
File.Delete(filename);
|
||||
using var fileStream = File.OpenWrite(filename);
|
||||
stream.CopyTo(fileStream);
|
||||
|
||||
return;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//var ms = MakeReportFromBlocks(block,block3);
|
||||
////File.Create("", MakeReportFromBlocks(block));
|
||||
//using var file = new FileStream("file.xlsx", FileMode.Create, System.IO.FileAccess.Write);
|
||||
//byte[] bytes = new byte[ms.Length];
|
||||
//ms.Read(bytes, 0, (int)ms.Length);
|
||||
//file.Write(bytes, 0, bytes.Length);
|
||||
//ms.Close();
|
||||
Console.WriteLine($"total time: ms");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user