forked from ddrilling/AsbCloudServer
Merge dev to well_operations_import
This commit is contained in:
commit
cb862c9ef3
@ -13,7 +13,6 @@ public class AutoGeneratedDailyReportDto : AutoGeneratedDailyReportInfoDto
|
||||
/// </summary>
|
||||
public HeadBlockDto Head { get; set; } = null!;
|
||||
|
||||
//TODO: поля не должны быть массивами
|
||||
/// <summary>
|
||||
/// Блок подсистем
|
||||
/// </summary>
|
||||
|
33
AsbCloudApp/Data/Manuals/ManualDirectoryDto.cs
Normal file
33
AsbCloudApp/Data/Manuals/ManualDirectoryDto.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AsbCloudApp.Data.Manuals;
|
||||
|
||||
/// <summary>
|
||||
/// Директория для хранения инструкций
|
||||
/// </summary>
|
||||
public class ManualDirectoryDto : IId
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Название
|
||||
/// </summary>
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Id родительской директории
|
||||
/// </summary>
|
||||
public int? IdParent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Вложенные директории
|
||||
/// </summary>
|
||||
public IEnumerable<ManualDirectoryDto> Children { get; set; } = Enumerable.Empty<ManualDirectoryDto>();
|
||||
|
||||
/// <summary>
|
||||
/// Хранимые инструкции
|
||||
/// </summary>
|
||||
public IEnumerable<ManualDto> Manuals { get; set; } = Enumerable.Empty<ManualDto>();
|
||||
}
|
37
AsbCloudApp/Data/Manuals/ManualDto.cs
Normal file
37
AsbCloudApp/Data/Manuals/ManualDto.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace AsbCloudApp.Data.Manuals;
|
||||
|
||||
/// <summary>
|
||||
/// Инструкция
|
||||
/// </summary>
|
||||
public class ManualDto : IId
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Название
|
||||
/// </summary>
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Дата загрузки
|
||||
/// </summary>
|
||||
public DateTime DateDownload { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id автора
|
||||
/// </summary>
|
||||
public int IdAuthor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id директории
|
||||
/// </summary>
|
||||
public int IdDirectory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id категории файла
|
||||
/// </summary>
|
||||
public int IdCategory { get; set; }
|
||||
}
|
@ -16,7 +16,7 @@ public class NotificationDto : IId
|
||||
/// Id получателя уведомления
|
||||
/// </summary>
|
||||
public int IdUser { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Id категории уведомления
|
||||
/// </summary>
|
||||
@ -32,6 +32,11 @@ public class NotificationDto : IId
|
||||
/// </summary>
|
||||
public string Message { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Дата регистрации уведомления
|
||||
/// </summary>
|
||||
public DateTime RegistrationDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата отправки уведомления
|
||||
/// </summary>
|
||||
@ -41,7 +46,7 @@ public class NotificationDto : IId
|
||||
/// Дата прочтения уведомления
|
||||
/// </summary>
|
||||
public DateTime? ReadDate { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Состояние уведомления
|
||||
/// 0 - Зарегистрировано,
|
||||
@ -60,11 +65,30 @@ public class NotificationDto : IId
|
||||
|
||||
return 0;
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
SentDate = null;
|
||||
ReadDate = null;
|
||||
break;
|
||||
case 1:
|
||||
SentDate = DateTime.UtcNow;
|
||||
ReadDate = null;
|
||||
break;
|
||||
case 2:
|
||||
SentDate = DateTime.UtcNow;
|
||||
ReadDate = DateTime.UtcNow;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Id типа доставки уведомления
|
||||
/// 0 - SignalR
|
||||
/// 1 - Email
|
||||
/// </summary>
|
||||
public int IdTransportType { get; set; }
|
||||
|
||||
|
@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AsbCloudApp.Data.ProcessMap;
|
||||
|
||||
/// <summary>
|
||||
/// РТК план проработка скважины
|
||||
/// </summary>
|
||||
public class ProcessMapWellboreDevelopmentDto : IId, IWellRelated
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int IdWell { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id пользователя
|
||||
/// </summary>
|
||||
public int IdUser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата последнего изменения
|
||||
/// </summary>
|
||||
public DateTimeOffset LastUpdate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Стартовая глубина, м
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Значение стартовой глубины должно быть в пределах от 0 до 99999.9")]
|
||||
public double DepthStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Окончательная глубина, м
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Значение окончательной глубины должно быть в пределах от 0 до 99999.9")]
|
||||
public double DepthEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Количество повторений
|
||||
/// </summary>
|
||||
[Range(0, 100, ErrorMessage = "Значение количества повторений должно быть в пределах от 0 до 100")]
|
||||
public double Repeats { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Вращение при движении вверх, об/мин
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Значение количества вращений вверх должно быть в пределах от 0 до 99999.9")]
|
||||
public double SpinUpward { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Вращение при движении вниз, об/мин
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Значение количества вращений вниз должно быть в пределах от 0 до 99999.9")]
|
||||
public double SpinDownward { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Скорость подъёма, м/ч
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Значение скорости подъёма должно быть в пределах от 0 до 99999.9")]
|
||||
public double SpeedUpward { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Скорость спуска, м/ч
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Значение скорости спуска должно быть в пределах от 0 до 99999.9")]
|
||||
public double SpeedDownward { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Уставка зятяжки, т
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Значение затяжек уставки должно быть в пределах от 0 до 99999.9")]
|
||||
public double SetpointDrag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Уставка посадки, т
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Значение посадки уставки должно быть в пределах от 0 до 99999.9")]
|
||||
public double SetpointTight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Давление, атм
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Значение давления должно быть в пределах от 0 до 99999.9")]
|
||||
public double Pressure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Момент, кН*м
|
||||
/// </summary>
|
||||
[Range(0, 99999.9, ErrorMessage = "Значение крутящего момента должно быть в пределах от 0 до 99999.9")]
|
||||
public double Torque { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Комментарий
|
||||
/// </summary>
|
||||
public string? Comment { get; set; }
|
||||
}
|
@ -12,15 +12,6 @@ namespace AsbCloudApp.Data.SAUB
|
||||
/// </summary>
|
||||
public DateTime DateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// метка времени данных (legacy)
|
||||
/// </summary>
|
||||
public DateTime Date // TODO: remove this legacy after all panels updated (> 3.2.0407)
|
||||
{
|
||||
get { return DateTime; }
|
||||
set { DateTime = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Режим работы САУБ:
|
||||
/// 0 - "РУЧНОЙ"
|
||||
|
@ -53,8 +53,13 @@ namespace AsbCloudApp.Data
|
||||
public IEnumerable<CompanyDto> Companies { get; set; } = Enumerable.Empty<CompanyDto>();
|
||||
|
||||
/// <summary>
|
||||
/// Отставание от ГГД, проценты
|
||||
/// Отставание от ГГД, дни
|
||||
/// </summary>
|
||||
public double? TvdLagPercent { get; set; }
|
||||
public double? TvdLagDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Кол-во дней бурения по ГГД
|
||||
/// </summary>
|
||||
public double? TvdDrillingDays { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -33,16 +33,6 @@ public abstract class TrajectoryGeoDto
|
||||
/// Глубина вертикальная
|
||||
/// </summary>
|
||||
public double? VerticalDepth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Север отн- но устья
|
||||
/// </summary>
|
||||
public double? NorthOrifice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Восток отн- но устья
|
||||
/// </summary>
|
||||
public double? EastOrifice { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -20,42 +20,7 @@ namespace AsbCloudApp.Data
|
||||
/// ИД пользователя
|
||||
/// </summary>
|
||||
public int IdUser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Абсолютная отметка
|
||||
/// </summary>
|
||||
public double AbsoluteMark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Восток картографический
|
||||
/// </summary>
|
||||
public double EastCartographic { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Север картографический
|
||||
/// </summary>
|
||||
public double NorthCartographic { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Пространственная интенсивность
|
||||
/// </summary>
|
||||
public double SpatialIntensity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Интенсивность по углу
|
||||
/// </summary>
|
||||
public double AngleIntensity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Интенсивность по азимуту
|
||||
/// </summary>
|
||||
public double AzimuthIntensity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Смещение от устья
|
||||
/// </summary>
|
||||
public double OrificeOffset { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Радиус цели
|
||||
/// </summary>
|
||||
|
@ -50,6 +50,11 @@ namespace AsbCloudApp.Data
|
||||
/// 2 - завершена
|
||||
/// </summary>
|
||||
public int IdState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Название текущей секции
|
||||
/// </summary>
|
||||
public string? Section { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Коэф-т использования автоподачи долота (суммарный ротор + слайд)
|
||||
@ -89,14 +94,44 @@ namespace AsbCloudApp.Data
|
||||
/// </summary>
|
||||
public PlanFactDto<double?> ROP { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Нагрузка на долота, Т
|
||||
/// </summary>
|
||||
public PlanFactDto<double?> AxialLoad { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Обороты ротора
|
||||
/// </summary>
|
||||
public PlanFactDto<double?> TopDriveSpeed { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Момент ротора кн/м
|
||||
/// </summary>
|
||||
public PlanFactDto<double?> TopDriveTorque { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Перепад давления
|
||||
/// </summary>
|
||||
public PlanFactDto<double?> Pressure { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Действующее задание давления, атм
|
||||
/// </summary>
|
||||
public double? PressureSp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Плановая и текущая глубина
|
||||
/// </summary>
|
||||
public PlanFactDto<double?> WellDepth { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Отставание от ГГД, проценты
|
||||
/// Отставание от ГГД, дни
|
||||
/// </summary>
|
||||
public double TvdLagPercent { get; set; }
|
||||
public double? TvdLagDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Кол-во дней бурения по ГГД
|
||||
/// </summary>
|
||||
public double? TvdDrillingDays { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
namespace AsbCloudApp.IntegrationEvents.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Интерфейс маркер для доменных событий
|
||||
/// </summary>
|
||||
public interface IIntegrationEvent { }
|
@ -0,0 +1,19 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.IntegrationEvents.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Обработчик событий
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public interface IIntegrationEventHandler<in T> where T: IIntegrationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод обработки события
|
||||
/// </summary>
|
||||
/// <param name="integrationEvent"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task HandleAsync(T integrationEvent, CancellationToken cancellationToken);
|
||||
}
|
9
AsbCloudApp/IntegrationEvents/UpdateWellInfoEvent.cs
Normal file
9
AsbCloudApp/IntegrationEvents/UpdateWellInfoEvent.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using AsbCloudApp.IntegrationEvents.Interfaces;
|
||||
|
||||
namespace AsbCloudApp.IntegrationEvents;
|
||||
|
||||
/// <summary>
|
||||
/// Обновление показателей бурения
|
||||
/// </summary>
|
||||
/// <param name="IdWell"></param>
|
||||
public record UpdateWellInfoEvent(int IdWell) : IIntegrationEvent;
|
@ -47,6 +47,13 @@ namespace AsbCloudApp.Repositories
|
||||
/// <param name="fileName"></param>
|
||||
void DeleteFile(string fileName);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление директории
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="isRecursive"></param>
|
||||
void DeleteDirectory(string path, bool isRecursive);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление всех файлов с диска о которых нет информации в базе
|
||||
/// </summary>
|
||||
|
37
AsbCloudApp/Repositories/IManualDirectoryRepository.cs
Normal file
37
AsbCloudApp/Repositories/IManualDirectoryRepository.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.Manuals;
|
||||
using AsbCloudApp.Services;
|
||||
|
||||
namespace AsbCloudApp.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Репозиторий для работы с директориямиы хранящими инструкциями
|
||||
/// </summary>
|
||||
public interface IManualDirectoryRepository : ICrudRepository<ManualDirectoryDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// Получение дерева директорий
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<ManualDirectoryDto>> GetTreeAsync(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Получение одной директории по параметрам
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="idParent"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<ManualDirectoryDto?> GetOrDefaultAsync(string name, int? idParent, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Проверка директории на существование
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> IsExistsAsync(int id, CancellationToken cancellationToken);
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Repositories;
|
||||
|
||||
@ -12,15 +12,6 @@ namespace AsbCloudApp.Repositories;
|
||||
/// </summary>
|
||||
public interface INotificationRepository : ICrudRepository<NotificationDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// Обновление изменённых уведомлений
|
||||
/// </summary>
|
||||
/// <param name="notifications"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> UpdateRangeAsync(IEnumerable<NotificationDto> notifications,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Получение уведомлений по параметрам
|
||||
/// </summary>
|
||||
@ -31,4 +22,41 @@ public interface INotificationRepository : ICrudRepository<NotificationDto>
|
||||
Task<PaginationContainer<NotificationDto>> GetNotificationsAsync(int idUser,
|
||||
NotificationRequest request,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Получение всех уведомлений
|
||||
/// </summary>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="isSent"></param>
|
||||
/// <param name="idTransportType"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<NotificationDto>> GetAllAsync(int? idUser, bool? isSent, int? idTransportType,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Обновление уведомлений
|
||||
/// </summary>
|
||||
/// <param name="notifications"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> UpdateRangeAsync(IEnumerable<NotificationDto> notifications, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление уведомлений по параметрам
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> DeleteAsync(NotificationDeleteRequest request,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Получение количества непрочтенных уведомлений
|
||||
/// </summary>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="idTransportType"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> GetUnreadCountAsync(int idUser, int idTransportType, CancellationToken cancellationToken);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.ProcessMap;
|
||||
using AsbCloudApp.Services;
|
||||
|
||||
namespace AsbCloudApp.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Репозиторий для проработки скважины
|
||||
/// </summary>
|
||||
public interface IProcessMapWellboreDevelopmentRepository : IRepositoryWellRelated<ProcessMapWellboreDevelopmentDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// Получить проработку начиная с даты
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="updateFrom"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<ProcessMapWellboreDevelopmentDto>> GetAllAsync(int idWell, DateTime? updateFrom, CancellationToken cancellationToken);
|
||||
}
|
24
AsbCloudApp/Requests/NotificationDeleteRequest.cs
Normal file
24
AsbCloudApp/Requests/NotificationDeleteRequest.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace AsbCloudApp.Requests;
|
||||
|
||||
/// <summary>
|
||||
/// Запрос для удаления уведомлений
|
||||
/// </summary>
|
||||
public class NotificationDeleteRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Идентификатор категории
|
||||
/// </summary>
|
||||
public int? IdCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Меньше или равно дате отправки
|
||||
/// </summary>
|
||||
public DateTime? LtSentDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Меньше или равно дате прочтения
|
||||
/// </summary>
|
||||
public DateTime? LtReadDate { get; set; }
|
||||
}
|
40
AsbCloudApp/Requests/NotifyRequest.cs
Normal file
40
AsbCloudApp/Requests/NotifyRequest.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AsbCloudApp.Requests;
|
||||
|
||||
/// <summary>
|
||||
/// Параметры запроса для отправки уведомления
|
||||
/// </summary>
|
||||
public class NotifyRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Id получателя уведомления
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int IdUser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id категории уведомления. Допустимое значение параметра: 1
|
||||
/// </summary>
|
||||
[Required]
|
||||
[Range(minimum: 1, maximum: 1, ErrorMessage = "Id категории уведомления недоступно. Допустимые: 1")]
|
||||
public int IdNotificationCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Заголовок уведомления
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Title { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Сообщение уведомления
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Message { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Id типа доставки уведомления. Допустимое значение: 0, 1
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int IdTransportType { get; set; }
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using AsbCloudApp.ValidationAttributes;
|
||||
using System;
|
||||
|
||||
namespace AsbCloudApp.Requests;
|
||||
@ -20,10 +21,12 @@ public class ReportParametersRequest
|
||||
/// <summary>
|
||||
/// Дата начала интервала
|
||||
/// </summary>
|
||||
[DateValidation(GtDate ="2000-01-01")]
|
||||
public DateTime Begin { get; set; } = default;
|
||||
|
||||
/// <summary>
|
||||
/// Дата окончания интервала
|
||||
/// </summary>
|
||||
public DateTime End { get; set; } = default;
|
||||
/// <summary>
|
||||
/// Дата окончания интервала
|
||||
/// </summary>
|
||||
[DateValidation(GtDate ="2000-01-01")]
|
||||
public DateTime End { get; set; } = default;
|
||||
}
|
59
AsbCloudApp/Requests/TelemetryRequest.cs
Normal file
59
AsbCloudApp/Requests/TelemetryRequest.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AsbCloudApp.Requests;
|
||||
|
||||
/// <summary>
|
||||
/// Параметры запроса телеметрии
|
||||
/// </summary>
|
||||
public class TelemetryDataRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Максимально допустимое кол-во строк данных
|
||||
/// </summary>
|
||||
public const int MaxTake = 3072;
|
||||
|
||||
/// <summary>
|
||||
/// greater or equal then Date
|
||||
/// </summary>
|
||||
public DateTimeOffset? GeDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// less or equal then Date
|
||||
/// </summary>
|
||||
public DateTimeOffset? LeDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Делитель для прореживания выборки.
|
||||
/// <list type="bullet">
|
||||
/// <item>1 - без прореживания (default); </item>
|
||||
/// <item>2 - каждое 2-е значение; </item>
|
||||
/// <item>10 - каждое 10-е значение; </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[Range(0, 300)]
|
||||
public int Divider { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// сортировка/выравнивание данных в запросе по дате
|
||||
/// <list type="bullet">
|
||||
/// <item>0 - более ранние данные вперед; </item>
|
||||
/// <item>1 - более поздние данные вперед; </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[Range(0, 1)]
|
||||
public int Order { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Пропустить с начала
|
||||
/// </summary>
|
||||
[Range(0, int.MaxValue)]
|
||||
public int Skip { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Кол-во возвращаемых, но не больше MaxTake
|
||||
/// </summary>
|
||||
[Range(1, MaxTake)]
|
||||
public int Take { get; set; } = 1024;
|
||||
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AsbCloudApp.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Сервис отправки сообщений
|
||||
/// </summary>
|
||||
public interface IEmailService
|
||||
{
|
||||
/// <summary>
|
||||
/// добавить сообщение на отправку нескольким пользователям
|
||||
/// </summary>
|
||||
/// <param name="addresses"></param>
|
||||
/// <param name="subject"></param>
|
||||
/// <param name="htmlBody"></param>
|
||||
void EnqueueSend(IEnumerable<string> addresses, string subject, string htmlBody);
|
||||
|
||||
/// <summary>
|
||||
/// добавить сообщение на отправку одному пользователю
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="subject"></param>
|
||||
/// <param name="htmlBody"></param>
|
||||
void EnqueueSend(string address, string subject, string htmlBody);
|
||||
}
|
||||
}
|
64
AsbCloudApp/Services/IManualCatalogService.cs
Normal file
64
AsbCloudApp/Services/IManualCatalogService.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Сервис для работы c каталогом инструкций
|
||||
/// </summary>
|
||||
public interface IManualCatalogService
|
||||
{
|
||||
/// <summary>
|
||||
/// Сохранение файла
|
||||
/// </summary>
|
||||
/// <param name="idDirectory"></param>
|
||||
/// <param name="idAuthor"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> SaveFileAsync(int idDirectory, int idAuthor, string name, Stream stream, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Добавление директории
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="idParent"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> AddDirectoryAsync(string name, int? idParent, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Обновление директории
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateDirectoryAsync(int id, string name, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление директории
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> DeleteDirectoryAsync(int id, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление файла
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> DeleteFileAsync(int id, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Получение файла
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<(Stream stream, string fileName)?> GetFileAsync(int id, CancellationToken cancellationToken);
|
||||
}
|
@ -6,9 +6,9 @@ using System.Threading.Tasks;
|
||||
namespace AsbCloudApp.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Сервис формирования РТК
|
||||
/// Сервис РТК
|
||||
/// </summary>
|
||||
public interface IProcessMapReportService
|
||||
public interface IProcessMapService
|
||||
{
|
||||
/// <summary>
|
||||
/// Получение моделей РТК
|
||||
|
@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.ProcessMap;
|
||||
|
||||
namespace AsbCloudApp.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Сервис для проработок скважины
|
||||
/// </summary>
|
||||
public interface IProcessMapWellboreDevelopmentService
|
||||
{
|
||||
/// <summary>
|
||||
/// Добавить запись проработки
|
||||
/// </summary>
|
||||
/// <param name="processMapWellboreDevelopment"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> InsertAsync(ProcessMapWellboreDevelopmentDto processMapWellboreDevelopment, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Обновить запись проработки
|
||||
/// </summary>
|
||||
/// <param name="processMapWellboreDevelopment"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> UpdateAsync(ProcessMapWellboreDevelopmentDto processMapWellboreDevelopment, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Получить записи проработок по уникальному ключу телеметрии
|
||||
/// </summary>
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="updateFrom"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<ProcessMapWellboreDevelopmentDto>> GetByTelemetryAsync(string uid, DateTime updateFrom,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Requests;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
@ -25,6 +26,7 @@ namespace AsbCloudApp.Services
|
||||
Task<IEnumerable<TDto>> GetAsync(int idWell,
|
||||
DateTime dateBegin = default, double intervalSec = 600d,
|
||||
int approxPointsCount = 1024, CancellationToken token = default);
|
||||
Task<IEnumerable<TDto>> GetAsync(int idWell, TelemetryDataRequest request, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получение статистики за период
|
||||
|
@ -16,7 +16,7 @@ public interface INotificationTransportService
|
||||
int IdTransportType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Отправка одного уведомлений
|
||||
/// Отправка одного уведомления
|
||||
/// </summary>
|
||||
/// <param name="notification"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
|
@ -33,48 +33,34 @@ public class NotificationService
|
||||
this.notificationRepository = notificationRepository;
|
||||
this.notificationTransportServices = notificationTransportServices;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Отправка нового уведомления
|
||||
/// </summary>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="idNotificationCategory"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="idTransportType"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task NotifyAsync(int idUser,
|
||||
int idNotificationCategory,
|
||||
string title,
|
||||
string message,
|
||||
int idTransportType,
|
||||
public async Task NotifyAsync(NotifyRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var notificationCategory = await notificationCategoryRepository
|
||||
.GetOrDefaultAsync(idNotificationCategory, cancellationToken)
|
||||
?? throw new ArgumentInvalidException("Категория уведомления не найдена", nameof(idNotificationCategory));
|
||||
var notificationCategory = await notificationCategoryRepository.GetOrDefaultAsync(request.IdNotificationCategory, cancellationToken)
|
||||
?? throw new ArgumentInvalidException("Категория уведомления не найдена", nameof(request.IdNotificationCategory));
|
||||
|
||||
var notification = new NotificationDto()
|
||||
var notification = new NotificationDto
|
||||
{
|
||||
IdUser = idUser,
|
||||
IdNotificationCategory = idNotificationCategory,
|
||||
Title = title,
|
||||
Message = message,
|
||||
IdTransportType = idTransportType
|
||||
IdUser = request.IdUser,
|
||||
RegistrationDate = DateTime.UtcNow,
|
||||
IdNotificationCategory = notificationCategory.Id,
|
||||
Title = request.Title,
|
||||
Message = request.Message,
|
||||
IdTransportType = request.IdTransportType,
|
||||
};
|
||||
|
||||
notification.Id = await notificationRepository.InsertAsync(notification,
|
||||
cancellationToken);
|
||||
|
||||
notification.Id = await notificationRepository.InsertAsync(notification, cancellationToken);
|
||||
notification.NotificationCategory = notificationCategory;
|
||||
|
||||
var notificationTransportService = GetNotificationTransportService(idTransportType);
|
||||
var notificationTransportService = GetTransportService(request.IdTransportType);
|
||||
|
||||
await notificationTransportService.SendAsync(notification, cancellationToken);
|
||||
|
||||
await notificationRepository.UpdateAsync(notification,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -84,21 +70,17 @@ public class NotificationService
|
||||
/// <param name="isRead"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task UpdateNotificationAsync(int idNotification,
|
||||
public async Task UpdateAsync(int idNotification,
|
||||
bool isRead,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var notification = await notificationRepository.GetOrDefaultAsync(idNotification,
|
||||
cancellationToken)
|
||||
var notification = await notificationRepository.GetOrDefaultAsync(idNotification, cancellationToken)
|
||||
?? throw new ArgumentInvalidException("Уведомление не найдено", nameof(idNotification));
|
||||
|
||||
if (isRead)
|
||||
{
|
||||
if (notification.SentDate == null)
|
||||
throw new ArgumentInvalidException("Уведомление не может быть прочитано", nameof(isRead));
|
||||
|
||||
notification.SentDate = DateTime.UtcNow;
|
||||
}
|
||||
if(isRead && !notification.SentDate.HasValue)
|
||||
throw new ArgumentInvalidException("Уведомление не может быть прочитано", nameof(isRead));
|
||||
|
||||
notification.ReadDate = isRead ? DateTime.UtcNow : null;
|
||||
|
||||
await notificationRepository.UpdateAsync(notification,
|
||||
cancellationToken);
|
||||
@ -111,28 +93,21 @@ public class NotificationService
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task ResendNotificationAsync(int idUser,
|
||||
NotificationRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
public async Task RenotifyAsync(int idUser, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!request.IdTransportType.HasValue)
|
||||
throw new ArgumentInvalidException("Id типа доставки уведомления должен иметь значение",
|
||||
nameof(request.IdTransportType));
|
||||
|
||||
var result = await notificationRepository.GetNotificationsAsync(idUser,
|
||||
request,
|
||||
const int idTransportType = 0;
|
||||
|
||||
var notifications = await notificationRepository.GetAllAsync(idUser, false,
|
||||
idTransportType,
|
||||
cancellationToken);
|
||||
|
||||
var notificationTransportService = GetNotificationTransportService(request.IdTransportType.Value);
|
||||
var notificationTransportService = GetTransportService(idTransportType);
|
||||
|
||||
await notificationTransportService.SendRangeAsync(result.Items,
|
||||
cancellationToken);
|
||||
|
||||
await notificationRepository.UpdateRangeAsync(result.Items,
|
||||
await notificationTransportService.SendRangeAsync(notifications,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private INotificationTransportService GetNotificationTransportService(int idTransportType)
|
||||
private INotificationTransportService GetTransportService(int idTransportType)
|
||||
{
|
||||
var notificationTransportService = notificationTransportServices
|
||||
.FirstOrDefault(s => s.IdTransportType == idTransportType)
|
||||
|
@ -63,6 +63,6 @@ namespace AsbCloudApp.Services.Subsystems
|
||||
/// <param name="wellIds"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatByActiveWells(IEnumerable<int> wellIds, CancellationToken token);
|
||||
Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatByActiveWells(IEnumerable<int> wellIds, CancellationToken token);
|
||||
}
|
||||
}
|
||||
|
8385
AsbCloudDb/Migrations/20230725082154_Add_Registration_Date_Notification.Designer.cs
generated
Normal file
8385
AsbCloudDb/Migrations/20230725082154_Add_Registration_Date_Notification.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Add_Registration_Date_Notification : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "registration_date",
|
||||
table: "t_notification",
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
|
||||
comment: "Дата регистрации уведомления");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "registration_date",
|
||||
table: "t_notification");
|
||||
}
|
||||
}
|
||||
}
|
8346
AsbCloudDb/Migrations/20230821110455_Update_PlannedTrajectory.Designer.cs
generated
Normal file
8346
AsbCloudDb/Migrations/20230821110455_Update_PlannedTrajectory.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
123
AsbCloudDb/Migrations/20230821110455_Update_PlannedTrajectory.cs
Normal file
123
AsbCloudDb/Migrations/20230821110455_Update_PlannedTrajectory.cs
Normal file
@ -0,0 +1,123 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Update_PlannedTrajectory : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "absolute_mark",
|
||||
table: "t_planned_trajectory");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "angle_intensity",
|
||||
table: "t_planned_trajectory");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "azimuth_intensity",
|
||||
table: "t_planned_trajectory");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "east_cartographic",
|
||||
table: "t_planned_trajectory");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "east_orifice",
|
||||
table: "t_planned_trajectory");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "north_cartographic",
|
||||
table: "t_planned_trajectory");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "north_orifice",
|
||||
table: "t_planned_trajectory");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "orifice_offset",
|
||||
table: "t_planned_trajectory");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "spatial_intensity",
|
||||
table: "t_planned_trajectory");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "absolute_mark",
|
||||
table: "t_planned_trajectory",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "Абсолютная отметка");
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "angle_intensity",
|
||||
table: "t_planned_trajectory",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "Интенсивность по углу");
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "azimuth_intensity",
|
||||
table: "t_planned_trajectory",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "Интенсивность по азимуту");
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "east_cartographic",
|
||||
table: "t_planned_trajectory",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "Восток картографический");
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "east_orifice",
|
||||
table: "t_planned_trajectory",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "Восток отн-но устья");
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "north_cartographic",
|
||||
table: "t_planned_trajectory",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "Север картографический");
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "north_orifice",
|
||||
table: "t_planned_trajectory",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "Север отн-но устья");
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "orifice_offset",
|
||||
table: "t_planned_trajectory",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "Смещение от устья");
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "spatial_intensity",
|
||||
table: "t_planned_trajectory",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "Пространственная интенсивность");
|
||||
}
|
||||
}
|
||||
}
|
8403
AsbCloudDb/Migrations/20230906090612_Add_separated_subsystems.Designer.cs
generated
Normal file
8403
AsbCloudDb/Migrations/20230906090612_Add_separated_subsystems.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,34 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Add_separated_subsystems : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.InsertData(
|
||||
table: "t_subsystem",
|
||||
columns: new[] { "id", "description", "name" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ 11, "Режим работы \"Бурение в роторе\"", "АПД ротор" },
|
||||
{ 12, "Режим работы \"Бурение в слайде\"", "АПД слайд" }
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_subsystem",
|
||||
keyColumn: "id",
|
||||
keyValue: 11);
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_subsystem",
|
||||
keyColumn: "id",
|
||||
keyValue: 12);
|
||||
}
|
||||
}
|
||||
}
|
8539
AsbCloudDb/Migrations/20230907070954_Add_Manuals.Designer.cs
generated
Normal file
8539
AsbCloudDb/Migrations/20230907070954_Add_Manuals.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
148
AsbCloudDb/Migrations/20230907070954_Add_Manuals.cs
Normal file
148
AsbCloudDb/Migrations/20230907070954_Add_Manuals.cs
Normal file
@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Add_Manuals : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "t_manual_directory",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
name = table.Column<string>(type: "text", nullable: false, comment: "Название"),
|
||||
id_parent = table.Column<int>(type: "integer", nullable: true, comment: "Id родительской директории")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_t_manual_directory", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_manual_directory_t_manual_directory_id_parent",
|
||||
column: x => x.id_parent,
|
||||
principalTable: "t_manual_directory",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
},
|
||||
comment: "Директория для инструкций");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "t_manual",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
name = table.Column<string>(type: "text", nullable: false, comment: "Название"),
|
||||
date_download = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, comment: "Дата загрузки"),
|
||||
id_directory = table.Column<int>(type: "integer", nullable: false, comment: "Id директории"),
|
||||
id_category = table.Column<int>(type: "integer", nullable: false, comment: "Id категории файла"),
|
||||
id_author = table.Column<int>(type: "integer", nullable: false, comment: "Id автора")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_t_manual", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_manual_t_file_category_id_category",
|
||||
column: x => x.id_category,
|
||||
principalTable: "t_file_category",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_manual_t_manual_directory_id_directory",
|
||||
column: x => x.id_directory,
|
||||
principalTable: "t_manual_directory",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_manual_t_user_id_author",
|
||||
column: x => x.id_author,
|
||||
principalTable: "t_user",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
},
|
||||
comment: "Инструкции");
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "t_file_category",
|
||||
columns: new[] { "id", "name", "short_name" },
|
||||
values: new object[] { 30000, "Инструкции", null });
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "t_permission",
|
||||
columns: new[] { "id", "description", "name" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ 523, "Разрешить редактирование инструкций", "Manual.edit" },
|
||||
{ 524, "Разрешить получение инструкций", "Manual.get" }
|
||||
});
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "t_relation_user_role_permission",
|
||||
columns: new[] { "id_permission", "id_user_role" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ 523, 1 },
|
||||
{ 524, 1 }
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_manual_id_author",
|
||||
table: "t_manual",
|
||||
column: "id_author");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_manual_id_category",
|
||||
table: "t_manual",
|
||||
column: "id_category");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_manual_id_directory",
|
||||
table: "t_manual",
|
||||
column: "id_directory");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_manual_directory_id_parent",
|
||||
table: "t_manual_directory",
|
||||
column: "id_parent");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "t_manual");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "t_manual_directory");
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_file_category",
|
||||
keyColumn: "id",
|
||||
keyValue: 30000);
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_relation_user_role_permission",
|
||||
keyColumns: new[] { "id_permission", "id_user_role" },
|
||||
keyValues: new object[] { 523, 1 });
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_relation_user_role_permission",
|
||||
keyColumns: new[] { "id_permission", "id_user_role" },
|
||||
keyValues: new object[] { 524, 1 });
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_permission",
|
||||
keyColumn: "id",
|
||||
keyValue: 523);
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_permission",
|
||||
keyColumn: "id",
|
||||
keyValue: 524);
|
||||
}
|
||||
}
|
||||
}
|
8413
AsbCloudDb/Migrations/20230913063219_Add_New_Permissions.Designer.cs
generated
Normal file
8413
AsbCloudDb/Migrations/20230913063219_Add_New_Permissions.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
53
AsbCloudDb/Migrations/20230913063219_Add_New_Permissions.cs
Normal file
53
AsbCloudDb/Migrations/20230913063219_Add_New_Permissions.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Add_New_Permissions : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.InsertData(
|
||||
table: "t_permission",
|
||||
columns: new[] { "id", "description", "name" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ 525, "Разрешение на редактирование РТК у завершенной скважины", "ProcessMap.editCompletedWell" },
|
||||
{ 526, "Разрешение на редактирование операций у завершенной скважины", "WellOperation.editCompletedWell" }
|
||||
});
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "t_relation_user_role_permission",
|
||||
columns: new[] { "id_permission", "id_user_role" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ 525, 1 },
|
||||
{ 526, 1 }
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_relation_user_role_permission",
|
||||
keyColumns: new[] { "id_permission", "id_user_role" },
|
||||
keyValues: new object[] { 525, 1 });
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_relation_user_role_permission",
|
||||
keyColumns: new[] { "id_permission", "id_user_role" },
|
||||
keyValues: new object[] { 526, 1 });
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_permission",
|
||||
keyColumn: "id",
|
||||
keyValue: 525);
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_permission",
|
||||
keyColumn: "id",
|
||||
keyValue: 526);
|
||||
}
|
||||
}
|
||||
}
|
8632
AsbCloudDb/Migrations/20230925052808_Add_ProcessMapWellboreDevelopment.Designer.cs
generated
Normal file
8632
AsbCloudDb/Migrations/20230925052808_Add_ProcessMapWellboreDevelopment.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Add_ProcessMapWellboreDevelopment : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "t_process_map_wellbore_development",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
id_well = table.Column<int>(type: "integer", nullable: false, comment: "Id скважины"),
|
||||
last_update = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Дата последнего изменения"),
|
||||
depth_start = table.Column<double>(type: "double precision", nullable: false, comment: "Стартовая глубина"),
|
||||
depth_end = table.Column<double>(type: "double precision", nullable: false, comment: "Окончательная глубина"),
|
||||
repeats = table.Column<double>(type: "double precision", nullable: false, comment: "Количество повторений"),
|
||||
spin_upward = table.Column<double>(type: "double precision", nullable: false, comment: "Вращение при движении вверх, об/мин"),
|
||||
spin_downward = table.Column<double>(type: "double precision", nullable: false, comment: "Вращение при движении вниз, об/мин"),
|
||||
speed_upward = table.Column<double>(type: "double precision", nullable: false, comment: "Скорость подъёма, м/ч"),
|
||||
speed_downward = table.Column<double>(type: "double precision", nullable: false, comment: "Скорость спуска, м/ч"),
|
||||
setpoint_drags = table.Column<double>(type: "double precision", nullable: false, comment: "Уставка зятяжки, т"),
|
||||
setpoint_tights = table.Column<double>(type: "double precision", nullable: false, comment: "Уставка посадки, т"),
|
||||
pressure = table.Column<double>(type: "double precision", nullable: false, comment: "Давление"),
|
||||
torque = table.Column<double>(type: "double precision", nullable: false, comment: "Момент, кН м"),
|
||||
comment = table.Column<string>(type: "text", nullable: true, comment: "Комментарий")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_t_process_map_wellbore_development", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK_t_process_map_wellbore_development_t_well_id_well",
|
||||
column: x => x.id_well,
|
||||
principalTable: "t_well",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
},
|
||||
comment: "Проработка скважины");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_process_map_wellbore_development_id_well",
|
||||
table: "t_process_map_wellbore_development",
|
||||
column: "id_well");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "t_process_map_wellbore_development");
|
||||
}
|
||||
}
|
||||
}
|
8544
AsbCloudDb/Migrations/20230925081405_Add_New_Permission_For_Manuals.Designer.cs
generated
Normal file
8544
AsbCloudDb/Migrations/20230925081405_Add_New_Permission_For_Manuals.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,35 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Add_New_Permission_For_Manuals : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.InsertData(
|
||||
table: "t_permission",
|
||||
columns: new[] { "id", "description", "name" },
|
||||
values: new object[] { 527, "Разрешение на удаление инструкций", "Manual.delete" });
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "t_relation_user_role_permission",
|
||||
columns: new[] { "id_permission", "id_user_role" },
|
||||
values: new object[] { 527, 1 });
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_relation_user_role_permission",
|
||||
keyColumns: new[] { "id_permission", "id_user_role" },
|
||||
keyValues: new object[] { 527, 1 });
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "t_permission",
|
||||
keyColumn: "id",
|
||||
keyValue: 527);
|
||||
}
|
||||
}
|
||||
}
|
8647
AsbCloudDb/Migrations/20230925132919_Update_ProcessMapWellboreDevelopment.Designer.cs
generated
Normal file
8647
AsbCloudDb/Migrations/20230925132919_Update_ProcessMapWellboreDevelopment.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,158 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AsbCloudDb.Migrations
|
||||
{
|
||||
public partial class Update_ProcessMapWellboreDevelopment : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "setpoint_tights",
|
||||
table: "t_process_map_wellbore_development",
|
||||
newName: "setpoint_tight");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "setpoint_drags",
|
||||
table: "t_process_map_wellbore_development",
|
||||
newName: "setpoint_drag");
|
||||
|
||||
migrationBuilder.AlterTable(
|
||||
name: "t_process_map_wellbore_development",
|
||||
comment: "РТК план проработка скважины",
|
||||
oldComment: "Проработка скважины");
|
||||
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "torque",
|
||||
table: "t_process_map_wellbore_development",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
comment: "Момент, кН*м",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double precision",
|
||||
oldComment: "Момент, кН м");
|
||||
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "pressure",
|
||||
table: "t_process_map_wellbore_development",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
comment: "Давление, атм",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double precision",
|
||||
oldComment: "Давление");
|
||||
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "depth_start",
|
||||
table: "t_process_map_wellbore_development",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
comment: "Стартовая глубина, м",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double precision",
|
||||
oldComment: "Стартовая глубина");
|
||||
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "depth_end",
|
||||
table: "t_process_map_wellbore_development",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
comment: "Окончательная глубина, м",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double precision",
|
||||
oldComment: "Окончательная глубина");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "id_user",
|
||||
table: "t_process_map_wellbore_development",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
comment: "Id пользователя");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_t_process_map_wellbore_development_id_user",
|
||||
table: "t_process_map_wellbore_development",
|
||||
column: "id_user");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_t_process_map_wellbore_development_t_user_id_user",
|
||||
table: "t_process_map_wellbore_development",
|
||||
column: "id_user",
|
||||
principalTable: "t_user",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_t_process_map_wellbore_development_t_user_id_user",
|
||||
table: "t_process_map_wellbore_development");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_t_process_map_wellbore_development_id_user",
|
||||
table: "t_process_map_wellbore_development");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "id_user",
|
||||
table: "t_process_map_wellbore_development");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "setpoint_tight",
|
||||
table: "t_process_map_wellbore_development",
|
||||
newName: "setpoint_tights");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "setpoint_drag",
|
||||
table: "t_process_map_wellbore_development",
|
||||
newName: "setpoint_drags");
|
||||
|
||||
migrationBuilder.AlterTable(
|
||||
name: "t_process_map_wellbore_development",
|
||||
comment: "Проработка скважины",
|
||||
oldComment: "РТК план проработка скважины");
|
||||
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "torque",
|
||||
table: "t_process_map_wellbore_development",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
comment: "Момент, кН м",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double precision",
|
||||
oldComment: "Момент, кН*м");
|
||||
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "pressure",
|
||||
table: "t_process_map_wellbore_development",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
comment: "Давление",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double precision",
|
||||
oldComment: "Давление, атм");
|
||||
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "depth_start",
|
||||
table: "t_process_map_wellbore_development",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
comment: "Стартовая глубина",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double precision",
|
||||
oldComment: "Стартовая глубина, м");
|
||||
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "depth_end",
|
||||
table: "t_process_map_wellbore_development",
|
||||
type: "double precision",
|
||||
nullable: false,
|
||||
comment: "Окончательная глубина",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double precision",
|
||||
oldComment: "Окончательная глубина, м");
|
||||
}
|
||||
}
|
||||
}
|
@ -785,6 +785,11 @@ namespace AsbCloudDb.Migrations
|
||||
{
|
||||
Id = 20000,
|
||||
Name = "Справки по страницам"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 30000,
|
||||
Name = "Инструкции"
|
||||
});
|
||||
});
|
||||
|
||||
@ -1066,6 +1071,83 @@ namespace AsbCloudDb.Migrations
|
||||
b.HasComment("Ограничения по параметрам телеметрии");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.Manuals.Manual", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("DateDownload")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("date_download")
|
||||
.HasComment("Дата загрузки");
|
||||
|
||||
b.Property<int>("IdAuthor")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_author")
|
||||
.HasComment("Id автора");
|
||||
|
||||
b.Property<int>("IdCategory")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_category")
|
||||
.HasComment("Id категории файла");
|
||||
|
||||
b.Property<int>("IdDirectory")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_directory")
|
||||
.HasComment("Id директории");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name")
|
||||
.HasComment("Название");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("IdAuthor");
|
||||
|
||||
b.HasIndex("IdCategory");
|
||||
|
||||
b.HasIndex("IdDirectory");
|
||||
|
||||
b.ToTable("t_manual");
|
||||
|
||||
b.HasComment("Инструкции");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.Manuals.ManualDirectory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int?>("IdParent")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_parent")
|
||||
.HasComment("Id родительской директории");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name")
|
||||
.HasComment("Название");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("IdParent");
|
||||
|
||||
b.ToTable("t_manual_directory");
|
||||
|
||||
b.HasComment("Директория для инструкций");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.Measure", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@ -1194,6 +1276,11 @@ namespace AsbCloudDb.Migrations
|
||||
.HasColumnName("read_date")
|
||||
.HasComment("Дата прочтения уведомления");
|
||||
|
||||
b.Property<DateTime>("RegistrationDate")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("registration_date")
|
||||
.HasComment("Дата регистрации уведомления");
|
||||
|
||||
b.Property<DateTime?>("SentDate")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("sent_date")
|
||||
@ -2163,6 +2250,36 @@ namespace AsbCloudDb.Migrations
|
||||
Id = 522,
|
||||
Description = "Разрешить удаление всех настроек пользователя",
|
||||
Name = "UserSettings.delete"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 523,
|
||||
Description = "Разрешить редактирование инструкций",
|
||||
Name = "Manual.edit"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 524,
|
||||
Description = "Разрешить получение инструкций",
|
||||
Name = "Manual.get"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 525,
|
||||
Description = "Разрешение на редактирование РТК у завершенной скважины",
|
||||
Name = "ProcessMap.editCompletedWell"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 526,
|
||||
Description = "Разрешение на редактирование операций у завершенной скважины",
|
||||
Name = "WellOperation.editCompletedWell"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 527,
|
||||
Description = "Разрешение на удаление инструкций",
|
||||
Name = "Manual.delete"
|
||||
});
|
||||
});
|
||||
|
||||
@ -2175,26 +2292,11 @@ namespace AsbCloudDb.Migrations
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<double>("AbsoluteMark")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("absolute_mark")
|
||||
.HasComment("Абсолютная отметка");
|
||||
|
||||
b.Property<double>("AngleIntensity")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("angle_intensity")
|
||||
.HasComment("Интенсивность по углу");
|
||||
|
||||
b.Property<double>("AzimuthGeo")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("azimuth_geo")
|
||||
.HasComment("Азимут Географ.");
|
||||
|
||||
b.Property<double>("AzimuthIntensity")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("azimuth_intensity")
|
||||
.HasComment("Интенсивность по азимуту");
|
||||
|
||||
b.Property<double>("AzimuthMagnetic")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("azimuth_magnetic")
|
||||
@ -2205,16 +2307,6 @@ namespace AsbCloudDb.Migrations
|
||||
.HasColumnName("comment")
|
||||
.HasComment("Комментарии");
|
||||
|
||||
b.Property<double>("EastCartographic")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("east_cartographic")
|
||||
.HasComment("Восток картографический");
|
||||
|
||||
b.Property<double>("EastOrifice")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("east_orifice")
|
||||
.HasComment("Восток отн-но устья");
|
||||
|
||||
b.Property<int>("IdUser")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_user")
|
||||
@ -2225,31 +2317,11 @@ namespace AsbCloudDb.Migrations
|
||||
.HasColumnName("id_well")
|
||||
.HasComment("ID скважины");
|
||||
|
||||
b.Property<double>("NorthCartographic")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("north_cartographic")
|
||||
.HasComment("Север картографический");
|
||||
|
||||
b.Property<double>("NorthOrifice")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("north_orifice")
|
||||
.HasComment("Север отн-но устья");
|
||||
|
||||
b.Property<double>("OrificeOffset")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("orifice_offset")
|
||||
.HasComment("Смещение от устья");
|
||||
|
||||
b.Property<double?>("Radius")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("radius")
|
||||
.HasComment("Радиус цели");
|
||||
|
||||
b.Property<double>("SpatialIntensity")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("spatial_intensity")
|
||||
.HasComment("Пространственная интенсивность");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdateDate")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("update_date")
|
||||
@ -2401,6 +2473,101 @@ namespace AsbCloudDb.Migrations
|
||||
b.HasComment("Операции по скважине – РТК");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.ProcessMapWellboreDevelopment", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Comment")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("comment")
|
||||
.HasComment("Комментарий");
|
||||
|
||||
b.Property<double>("DepthEnd")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("depth_end")
|
||||
.HasComment("Окончательная глубина, м");
|
||||
|
||||
b.Property<double>("DepthStart")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("depth_start")
|
||||
.HasComment("Стартовая глубина, м");
|
||||
|
||||
b.Property<int>("IdUser")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_user")
|
||||
.HasComment("Id пользователя");
|
||||
|
||||
b.Property<int>("IdWell")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id_well")
|
||||
.HasComment("Id скважины");
|
||||
|
||||
b.Property<DateTimeOffset>("LastUpdate")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("last_update")
|
||||
.HasComment("Дата последнего изменения");
|
||||
|
||||
b.Property<double>("Pressure")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("pressure")
|
||||
.HasComment("Давление, атм");
|
||||
|
||||
b.Property<double>("Repeats")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("repeats")
|
||||
.HasComment("Количество повторений");
|
||||
|
||||
b.Property<double>("SetpointDrag")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("setpoint_drag")
|
||||
.HasComment("Уставка зятяжки, т");
|
||||
|
||||
b.Property<double>("SetpointTight")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("setpoint_tight")
|
||||
.HasComment("Уставка посадки, т");
|
||||
|
||||
b.Property<double>("SpeedDownward")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("speed_downward")
|
||||
.HasComment("Скорость спуска, м/ч");
|
||||
|
||||
b.Property<double>("SpeedUpward")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("speed_upward")
|
||||
.HasComment("Скорость подъёма, м/ч");
|
||||
|
||||
b.Property<double>("SpinDownward")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("spin_downward")
|
||||
.HasComment("Вращение при движении вниз, об/мин");
|
||||
|
||||
b.Property<double>("SpinUpward")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("spin_upward")
|
||||
.HasComment("Вращение при движении вверх, об/мин");
|
||||
|
||||
b.Property<double>("Torque")
|
||||
.HasColumnType("double precision")
|
||||
.HasColumnName("torque")
|
||||
.HasComment("Момент, кН*м");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("IdUser");
|
||||
|
||||
b.HasIndex("IdWell");
|
||||
|
||||
b.ToTable("t_process_map_wellbore_development");
|
||||
|
||||
b.HasComment("РТК план проработка скважины");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.RelationCompanyWell", b =>
|
||||
{
|
||||
b.Property<int>("IdCompany")
|
||||
@ -3750,6 +3917,31 @@ namespace AsbCloudDb.Migrations
|
||||
{
|
||||
IdUserRole = 1,
|
||||
IdPermission = 522
|
||||
},
|
||||
new
|
||||
{
|
||||
IdUserRole = 1,
|
||||
IdPermission = 523
|
||||
},
|
||||
new
|
||||
{
|
||||
IdUserRole = 1,
|
||||
IdPermission = 524
|
||||
},
|
||||
new
|
||||
{
|
||||
IdUserRole = 1,
|
||||
IdPermission = 525
|
||||
},
|
||||
new
|
||||
{
|
||||
IdUserRole = 1,
|
||||
IdPermission = 526
|
||||
},
|
||||
new
|
||||
{
|
||||
IdUserRole = 1,
|
||||
IdPermission = 527
|
||||
});
|
||||
});
|
||||
|
||||
@ -4260,6 +4452,18 @@ namespace AsbCloudDb.Migrations
|
||||
Name = "АКБ"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 11,
|
||||
Description = "Режим работы \"Бурение в роторе\"",
|
||||
Name = "АПД ротор"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 12,
|
||||
Description = "Режим работы \"Бурение в слайде\"",
|
||||
Name = "АПД слайд"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 2,
|
||||
Description = "Алгоритм поиска оптимальных параметров бурения САУБ",
|
||||
@ -7682,6 +7886,43 @@ namespace AsbCloudDb.Migrations
|
||||
b.Navigation("Telemetry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.Manuals.Manual", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.User", "Author")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdAuthor")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("AsbCloudDb.Model.FileCategory", "Category")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdCategory")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("AsbCloudDb.Model.Manuals.ManualDirectory", "Directory")
|
||||
.WithMany("Manuals")
|
||||
.HasForeignKey("IdDirectory")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Author");
|
||||
|
||||
b.Navigation("Category");
|
||||
|
||||
b.Navigation("Directory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.Manuals.ManualDirectory", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.Manuals.ManualDirectory", "Parent")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("IdParent")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.Navigation("Parent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.Measure", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.MeasureCategory", "Category")
|
||||
@ -7777,6 +8018,25 @@ namespace AsbCloudDb.Migrations
|
||||
b.Navigation("WellSectionType");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.ProcessMapWellboreDevelopment", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdUser")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("AsbCloudDb.Model.Well", "Well")
|
||||
.WithMany()
|
||||
.HasForeignKey("IdWell")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
|
||||
b.Navigation("Well");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.RelationCompanyWell", b =>
|
||||
{
|
||||
b.HasOne("AsbCloudDb.Model.Company", "Company")
|
||||
@ -8307,6 +8567,13 @@ namespace AsbCloudDb.Migrations
|
||||
b.Navigation("FileMarks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.Manuals.ManualDirectory", b =>
|
||||
{
|
||||
b.Navigation("Children");
|
||||
|
||||
b.Navigation("Manuals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AsbCloudDb.Model.MeasureCategory", b =>
|
||||
{
|
||||
b.Navigation("Measures");
|
||||
|
@ -3,6 +3,7 @@ using AsbCloudDb.Model.Subsystems;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudDb.Model.Manuals;
|
||||
|
||||
namespace AsbCloudDb.Model
|
||||
{
|
||||
@ -16,6 +17,7 @@ namespace AsbCloudDb.Model
|
||||
public virtual DbSet<DetectedOperation> DetectedOperations => Set<DetectedOperation>();
|
||||
public virtual DbSet<PlannedTrajectory> PlannedTrajectories => Set<PlannedTrajectory>();
|
||||
public virtual DbSet<ProcessMap> ProcessMap => Set<ProcessMap>();
|
||||
public virtual DbSet<ProcessMapWellboreDevelopment> ProcessMapWellboreDevelopments => Set<ProcessMapWellboreDevelopment>();
|
||||
public virtual DbSet<DrillingProgramPart> DrillingProgramParts => Set<DrillingProgramPart>();
|
||||
public virtual DbSet<FileCategory> FileCategories => Set<FileCategory>();
|
||||
public virtual DbSet<FileInfo> Files => Set<FileInfo>();
|
||||
@ -77,6 +79,9 @@ namespace AsbCloudDb.Model
|
||||
public DbSet<HelpPage> HelpPages => Set<HelpPage>();
|
||||
public DbSet<Notification> Notifications => Set<Notification>();
|
||||
public DbSet<NotificationCategory> NotificationCategories => Set<NotificationCategory>();
|
||||
public DbSet<Manual> Manuals => Set<Manual>();
|
||||
public DbSet<ManualDirectory> ManualDirectories => Set<ManualDirectory>();
|
||||
|
||||
|
||||
public AsbCloudDbContext() : base()
|
||||
{
|
||||
@ -388,6 +393,18 @@ namespace AsbCloudDb.Model
|
||||
entity.HasKey(x => new { x.IdWell, x.IdUser });
|
||||
});
|
||||
|
||||
modelBuilder.Entity<ManualDirectory>()
|
||||
.HasOne(mf => mf.Parent)
|
||||
.WithMany(mf => mf.Children)
|
||||
.HasForeignKey(mf => mf.IdParent)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<Manual>()
|
||||
.HasOne(m => m.Directory)
|
||||
.WithMany(f => f.Manuals)
|
||||
.HasForeignKey(m => m.IdDirectory)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
DefaultData.DefaultContextData.Fill(modelBuilder);
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,9 @@
|
||||
new () {Id = 10042, Name = "Паспорт скважины (заполняется геологами)"},
|
||||
new () {Id = 10043, Name = "Фактические данные бурения (вставляются в паспорт скважины)"},
|
||||
|
||||
new () {Id = 20000, Name = "Справки по страницам"}
|
||||
new () {Id = 20000, Name = "Справки по страницам"},
|
||||
|
||||
new() { Id = 30000, Name = "Инструкции"},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -156,6 +156,14 @@
|
||||
new() { Id = 521, Name = "HelpPage.edit", Description = "Разрешить создание справок по страницам"},
|
||||
|
||||
new() { Id = 522, Name = "UserSettings.delete", Description = "Разрешить удаление всех настроек пользователя"},
|
||||
|
||||
new() { Id = 523, Name = "Manual.edit", Description = "Разрешить редактирование инструкций" },
|
||||
new() { Id = 524, Name = "Manual.get", Description = "Разрешить получение инструкций"},
|
||||
|
||||
new (){ Id = 525, Name = "ProcessMap.editCompletedWell", Description = "Разрешение на редактирование РТК у завершенной скважины"},
|
||||
new (){ Id = 526, Name = "WellOperation.editCompletedWell", Description = "Разрешение на редактирование операций у завершенной скважины"},
|
||||
|
||||
new() { Id = 527, Name = "Manual.delete", Description = "Разрешение на удаление инструкций"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,6 @@ namespace AsbCloudDb.Model.DefaultData
|
||||
new (){ IdUserRole = 2005, IdPermission = 247}, new (){ IdUserRole = 2005, IdPermission = 205}, new (){ IdUserRole = 2005, IdPermission = 204},
|
||||
new (){ IdUserRole = 2006, IdPermission = 243}, new (){ IdUserRole = 2006, IdPermission = 205}, new (){ IdUserRole = 2006, IdPermission = 204},
|
||||
new (){ IdUserRole = 2007, IdPermission = 241}, new (){ IdUserRole = 2007, IdPermission = 205}, new (){ IdUserRole = 2007, IdPermission = 204},
|
||||
//new (){ IdUserRole = 1, IdPermission = 500}, new (){ IdUserRole = 1, IdPermission = 501}, new (){ IdUserRole = 1, IdPermission = 502}, new (){ IdUserRole = 1, IdPermission = 503}, new (){ IdUserRole = 1, IdPermission = 504}, new (){ IdUserRole = 1, IdPermission = 505}, new (){ IdUserRole = 1, IdPermission = 506}, new (){ IdUserRole = 1, IdPermission = 510}, new (){ IdUserRole = 1, IdPermission = 511}, new (){ IdUserRole = 1, IdPermission = 512}, new (){ IdUserRole = 1, IdPermission = 513}, new (){ IdUserRole = 1, IdPermission = 514}, new (){ IdUserRole = 1, IdPermission = 515},
|
||||
};
|
||||
var allPermissions = (new EntityFillerPermission()).GetData();
|
||||
foreach ( var permission in allPermissions)
|
||||
|
@ -6,6 +6,8 @@ namespace AsbCloudDb.Model.DefaultData
|
||||
public override Subsystem[] GetData() => new Subsystem[]{
|
||||
// САУБ - ид подсистем с 1 до 65_535
|
||||
new () {Id = 1, Name = "АКБ", Description = "Совместная работа режимов \"Бурение в роторе\" и \"Бурение в слайде\""},
|
||||
new () {Id = 11, Name = "АПД ротор", Description = "Режим работы \"Бурение в роторе\""},
|
||||
new () {Id = 12, Name = "АПД слайд", Description = "Режим работы \"Бурение в слайде\""},
|
||||
new () {Id = 2, Name = "MSE", Description = "Алгоритм поиска оптимальных параметров бурения САУБ"},
|
||||
//Spin master - id подсистем с 65_536 до 131_071
|
||||
new () {Id = 65536, Name = "Spin master", Description = "Spin master"},
|
||||
|
@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudDb.Model.Manuals;
|
||||
|
||||
namespace AsbCloudDb.Model
|
||||
{
|
||||
@ -20,6 +21,7 @@ namespace AsbCloudDb.Model
|
||||
DbSet<DetectedOperation> DetectedOperations { get; }
|
||||
DbSet<PlannedTrajectory> PlannedTrajectories { get; }
|
||||
DbSet<ProcessMap> ProcessMap { get; }
|
||||
DbSet<ProcessMapWellboreDevelopment> ProcessMapWellboreDevelopments { get; }
|
||||
DbSet<DrillingProgramPart> DrillingProgramParts { get; }
|
||||
DbSet<FileCategory> FileCategories { get; }
|
||||
DbSet<FileInfo> Files { get; }
|
||||
@ -70,6 +72,8 @@ namespace AsbCloudDb.Model
|
||||
DbSet<HelpPage> HelpPages { get; }
|
||||
DbSet<Notification> Notifications { get; }
|
||||
DbSet<NotificationCategory> NotificationCategories { get; }
|
||||
DbSet<Manual> Manuals { get; }
|
||||
DbSet<ManualDirectory> ManualDirectories { get; }
|
||||
DatabaseFacade Database { get; }
|
||||
|
||||
Task<int> RefreshMaterializedViewAsync(string mwName, CancellationToken token);
|
||||
|
38
AsbCloudDb/Model/Manuals/Manual.cs
Normal file
38
AsbCloudDb/Model/Manuals/Manual.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AsbCloudDb.Model.Manuals;
|
||||
|
||||
[Table("t_manual"), Comment("Инструкции")]
|
||||
public class Manual : IId
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("name"), Comment("Название")]
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
[Column("date_download"), Comment("Дата загрузки")]
|
||||
public DateTime DateDownload { get; set; }
|
||||
|
||||
[Column("id_directory"), Comment("Id директории")]
|
||||
public int IdDirectory { get; set; }
|
||||
|
||||
[Column("id_category"), Comment("Id категории файла")]
|
||||
public int IdCategory { get; set; }
|
||||
|
||||
[Column("id_author"), Comment("Id автора")]
|
||||
public int IdAuthor { get; set; }
|
||||
|
||||
[ForeignKey(nameof(IdDirectory))]
|
||||
public virtual ManualDirectory Directory { get; set; } = null!;
|
||||
|
||||
[ForeignKey(nameof(IdCategory))]
|
||||
public virtual FileCategory Category { get; set; } = null!;
|
||||
|
||||
[ForeignKey(nameof(IdAuthor))]
|
||||
public virtual User Author { get; set; } = null!;
|
||||
}
|
27
AsbCloudDb/Model/Manuals/ManualDirectory.cs
Normal file
27
AsbCloudDb/Model/Manuals/ManualDirectory.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AsbCloudDb.Model.Manuals;
|
||||
|
||||
[Table("t_manual_directory"), Comment("Директория для инструкций")]
|
||||
public class ManualDirectory : IId
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("name"), Comment("Название")]
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
[Column("id_parent"), Comment("Id родительской директории")]
|
||||
public int? IdParent { get; set; }
|
||||
|
||||
[ForeignKey(nameof(IdParent))]
|
||||
public virtual ManualDirectory? Parent { get; set; }
|
||||
|
||||
public virtual ICollection<ManualDirectory>? Children { get; set; }
|
||||
|
||||
public virtual ICollection<Manual>? Manuals { get; set; }
|
||||
}
|
@ -24,6 +24,9 @@ public class Notification : IId
|
||||
[Column("message"), Comment("Сообщение уведомления")]
|
||||
public string Message { get; set; } = null!;
|
||||
|
||||
[Column("registration_date"), Comment("Дата регистрации уведомления")]
|
||||
public DateTime RegistrationDate { get; set; }
|
||||
|
||||
[Column("sent_date"), Comment("Дата отправки уведомления")]
|
||||
public DateTime? SentDate { get; set; }
|
||||
|
||||
|
@ -35,33 +35,6 @@ namespace AsbCloudDb.Model
|
||||
[Column("vertical_depth"), Comment("Глубина вертикальная")]
|
||||
public double VerticalDepth { get; set; }
|
||||
|
||||
[Column("absolute_mark"), Comment("Абсолютная отметка")]
|
||||
public double AbsoluteMark { get; set; }
|
||||
|
||||
[Column("north_orifice"), Comment("Север отн-но устья")]
|
||||
public double NorthOrifice { get; set; }
|
||||
|
||||
[Column("east_orifice"), Comment("Восток отн-но устья")]
|
||||
public double EastOrifice { get; set; }
|
||||
|
||||
[Column("east_cartographic"), Comment("Восток картографический")]
|
||||
public double EastCartographic { get; set; }
|
||||
|
||||
[Column("north_cartographic"), Comment("Север картографический")]
|
||||
public double NorthCartographic { get; set; }
|
||||
|
||||
[Column("spatial_intensity"), Comment("Пространственная интенсивность")]
|
||||
public double SpatialIntensity { get; set; }
|
||||
|
||||
[Column("angle_intensity"), Comment("Интенсивность по углу")]
|
||||
public double AngleIntensity { get; set; }
|
||||
|
||||
[Column("azimuth_intensity"), Comment("Интенсивность по азимуту")]
|
||||
public double AzimuthIntensity { get; set; }
|
||||
|
||||
[Column("orifice_offset"), Comment("Смещение от устья")]
|
||||
public double OrificeOffset { get; set; }
|
||||
|
||||
[Column("comment"), Comment("Комментарии")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
|
65
AsbCloudDb/Model/ProcessMapWellboreDevelopment.cs
Normal file
65
AsbCloudDb/Model/ProcessMapWellboreDevelopment.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AsbCloudDb.Model;
|
||||
|
||||
[Table("t_process_map_wellbore_development"), Comment("РТК план проработка скважины")]
|
||||
public class ProcessMapWellboreDevelopment : IId, IWellRelated
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("id_well"), Comment("Id скважины")]
|
||||
public int IdWell { get; set; }
|
||||
|
||||
[Column("id_user"), Comment("Id пользователя")]
|
||||
public int IdUser { get; set; }
|
||||
|
||||
[Column("last_update", TypeName = "timestamp with time zone"), Comment("Дата последнего изменения")]
|
||||
public DateTimeOffset LastUpdate { get; set; }
|
||||
|
||||
[Column("depth_start"), Comment("Стартовая глубина, м")]
|
||||
public double DepthStart { get; set; }
|
||||
|
||||
[Column("depth_end"), Comment("Окончательная глубина, м")]
|
||||
public double DepthEnd { get; set; }
|
||||
|
||||
[Column("repeats"), Comment("Количество повторений")]
|
||||
public double Repeats { get; set; }
|
||||
|
||||
[Column("spin_upward"), Comment("Вращение при движении вверх, об/мин")]
|
||||
public double SpinUpward { get; set; }
|
||||
|
||||
[Column("spin_downward"), Comment("Вращение при движении вниз, об/мин")]
|
||||
public double SpinDownward { get; set; }
|
||||
|
||||
[Column("speed_upward"), Comment("Скорость подъёма, м/ч")]
|
||||
public double SpeedUpward { get; set; }
|
||||
|
||||
[Column("speed_downward"), Comment("Скорость спуска, м/ч")]
|
||||
public double SpeedDownward { get; set; }
|
||||
|
||||
[Column("setpoint_drag"), Comment("Уставка зятяжки, т")]
|
||||
public double SetpointDrag { get; set; }
|
||||
|
||||
[Column("setpoint_tight"), Comment("Уставка посадки, т")]
|
||||
public double SetpointTight { get; set; }
|
||||
|
||||
[Column("pressure"), Comment("Давление, атм")]
|
||||
public double Pressure { get; set; }
|
||||
|
||||
[Column("torque"), Comment("Момент, кН*м")]
|
||||
public double Torque { get; set; }
|
||||
|
||||
[Column("comment"), Comment("Комментарий")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
[ForeignKey(nameof(IdWell))]
|
||||
public virtual Well Well { get; set; } = null!;
|
||||
|
||||
[ForeignKey(nameof(IdUser))]
|
||||
public virtual User User { get; set; } = null!;
|
||||
}
|
@ -43,6 +43,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsbSaubReport" Version="3.2.1" />
|
||||
<PackageReference Include="AsbSaubReportLas" Version="3.2.1" />
|
||||
<PackageReference Include="AsbSaubReportPdf" Version="3.2.1" />
|
||||
<PackageReference Include="CliWrap" Version="3.6.0" />
|
||||
<PackageReference Include="ClosedXML" Version="0.96.0" />
|
||||
<PackageReference Include="itext7" Version="7.2.3" />
|
||||
@ -62,15 +65,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="AsbSaubReport">
|
||||
<HintPath>CommonLibs\AsbSaubReport.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AsbSaubReportLas">
|
||||
<HintPath>CommonLibs\AsbSaubReportLas.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AsbSaubReportPdf">
|
||||
<HintPath>CommonLibs\AsbSaubReportPdf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AsbWitsInfo">
|
||||
<HintPath>CommonLibs\AsbWitsInfo.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -7,7 +7,6 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Background
|
||||
{
|
||||
# nullable enable
|
||||
/// <summary>
|
||||
/// Сервис для фонового выполнения работы
|
||||
/// </summary>
|
||||
@ -94,5 +93,4 @@ namespace AsbCloudInfrastructure.Background
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace AsbCloudInfrastructure.Background;
|
||||
|
||||
public class NotificationBackgroundWorker : BackgroundWorker
|
||||
{
|
||||
public NotificationBackgroundWorker(IServiceProvider serviceProvider) : base(serviceProvider)
|
||||
{
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -23,12 +23,15 @@ using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using AsbCloudApp.Data.Manuals;
|
||||
using AsbCloudApp.Services.AutoGeneratedDailyReports;
|
||||
using AsbCloudApp.Services.Notifications;
|
||||
using AsbCloudApp.Services.WellOperationImport;
|
||||
using AsbCloudDb.Model.Manuals;
|
||||
using AsbCloudInfrastructure.Services.AutoGeneratedDailyReports;
|
||||
using AsbCloudInfrastructure.Services.WellOperationImport;
|
||||
using AsbCloudInfrastructure.Services.WellOperationImport.FileParser;
|
||||
using AsbCloudInfrastructure.Services.ProcessMap.ProcessMapWellboreDevelopment;
|
||||
|
||||
namespace AsbCloudInfrastructure
|
||||
{
|
||||
@ -108,18 +111,19 @@ namespace AsbCloudInfrastructure
|
||||
|
||||
services.AddMemoryCache();
|
||||
services.AddScoped<IAsbCloudDbContext>(provider => provider.GetRequiredService<AsbCloudDbContext>());
|
||||
services.AddScoped<IEmailService, EmailService>();
|
||||
|
||||
services.AddSingleton(new WitsInfoService());
|
||||
services.AddSingleton(provider => TelemetryDataCache<TelemetryDataSaubDto>.GetInstance<TelemetryDataSaub>(provider));
|
||||
services.AddSingleton(provider => TelemetryDataCache<TelemetryDataSpinDto>.GetInstance<TelemetryDataSpin>(provider));
|
||||
services.AddSingleton<IRequerstTrackerService, RequestTrackerService>();
|
||||
services.AddSingleton<BackgroundWorker>();
|
||||
services.AddSingleton<NotificationBackgroundWorker>();
|
||||
services.AddSingleton<IReduceSamplingService>(provider => ReduceSamplingService.GetInstance(configuration));
|
||||
|
||||
services.AddTransient<IAuthService, AuthService>();
|
||||
services.AddTransient<IDepositRepository, DepositRepository>();
|
||||
services.AddTransient<IProcessMapPlanRepository, ProcessMapRepository>();
|
||||
services.AddTransient<IProcessMapWellboreDevelopmentRepository, ProcessMapWellboreDevelopmentRepository>();
|
||||
services.AddTransient<IDrillingProgramService, DrillingProgramService>();
|
||||
services.AddTransient<IEventService, EventService>();
|
||||
services.AddTransient<FileService>();
|
||||
@ -146,7 +150,8 @@ namespace AsbCloudInfrastructure
|
||||
services.AddTransient<IFileCategoryService, FileCategoryService>();
|
||||
services.AddTransient<ILimitingParameterService, LimitingParameterService>();
|
||||
services.AddTransient<IProcessMapReportMakerService, ProcessMapReportMakerService>();
|
||||
services.AddTransient<IProcessMapReportService, ProcessMapReportService>();
|
||||
services.AddTransient<IProcessMapService, ProcessMapService>();
|
||||
services.AddTransient<IProcessMapWellboreDevelopmentService, ProcessMapWellboreDevelopmentService>();
|
||||
services.AddTransient<WellInfoService>();
|
||||
services.AddTransient<IHelpPageService, HelpPageService>();
|
||||
|
||||
@ -223,6 +228,10 @@ namespace AsbCloudInfrastructure
|
||||
|
||||
services.AddTransient<IAutoGeneratedDailyReportService, AutoGeneratedDailyReportService>();
|
||||
services.AddTransient<IAutoGeneratedDailyReportMakerService, AutoGeneratedDailyReportMakerService>();
|
||||
|
||||
services.AddTransient<IManualDirectoryRepository, ManualDirectoryRepository>();
|
||||
services.AddTransient<IManualCatalogService, ManualCatalogService>();
|
||||
services.AddTransient<ICrudRepository<ManualDto>, CrudRepositoryBase<ManualDto, Manual>>();
|
||||
|
||||
services.AddTransient<IWellboreService, WellboreService>();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbSaubReport.Model;
|
||||
using iText.Forms.Xfdf;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using AsbCloudApp.Data;
|
||||
using System;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Repositories;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@ -33,6 +34,23 @@ public class FileStorageRepository : IFileStorageRepository
|
||||
DeleteFile(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteDirectory(string path, bool isRecursive)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
return;
|
||||
|
||||
if (!isRecursive)
|
||||
{
|
||||
var files = Directory.GetFiles(path);
|
||||
var directories = Directory.GetDirectories(path);
|
||||
|
||||
if (files.Length != 0 || directories.Length != 0)
|
||||
throw new InvalidOperationException("Директория не пуста и не может быть удалена");
|
||||
}
|
||||
|
||||
Directory.Delete(path, isRecursive);
|
||||
}
|
||||
|
||||
public void DeleteFile(string fileName)
|
||||
{
|
||||
|
@ -1,12 +1,14 @@
|
||||
using AsbCloudApp.Data.GTR;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudDb.Model.GTR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -149,6 +151,10 @@ namespace AsbCloudInfrastructure.Repository
|
||||
|
||||
var cacheTelemetryItems = cache.GetValueOrDefault(idTelemetry);
|
||||
|
||||
var strings = new List<WitsItemString>(4);
|
||||
var floats = new List<WitsItemFloat>(4);
|
||||
var ints = new List<WitsItemInt>(4);
|
||||
|
||||
foreach (var record in dtos)
|
||||
{
|
||||
var dateTime = record.Date.ToUtcDateTimeOffset(timezoneHours);
|
||||
@ -161,30 +167,35 @@ namespace AsbCloudInfrastructure.Repository
|
||||
if (item.Value.Value is string valueString)
|
||||
{
|
||||
var entity = MakeEntity<WitsItemString, string>(record.Id, item.Key, idTelemetry, dateTime, valueString);
|
||||
db.WitsItemString.Add(entity);
|
||||
strings.Add(entity);
|
||||
}
|
||||
if (item.Value.Value is float valueFloat)
|
||||
{
|
||||
var entity = MakeEntity<WitsItemFloat, float>(record.Id, item.Key, idTelemetry, dateTime, valueFloat);
|
||||
db.WitsItemFloat.Add(entity);
|
||||
floats.Add(entity);
|
||||
}
|
||||
if (item.Value.Value is int valueInt)
|
||||
{
|
||||
var entity = MakeEntity<WitsItemInt, int>(record.Id, item.Key, idTelemetry, dateTime, valueInt);
|
||||
db.WitsItemInt.Add(entity);
|
||||
ints.Add(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await db.SaveChangesAsync(token);
|
||||
if (strings.Any())
|
||||
await db.Database.ExecInsertOrIgnoreAsync(db.Set<WitsItemString>(), strings, token);
|
||||
|
||||
if (floats.Any())
|
||||
await db.Database.ExecInsertOrIgnoreAsync(db.Set<WitsItemFloat>(), floats, token);
|
||||
|
||||
if (ints.Any())
|
||||
await db.Database.ExecInsertOrIgnoreAsync(db.Set<WitsItemInt>(), ints, token);
|
||||
}
|
||||
catch(DbUpdateException ex)
|
||||
catch(Exception ex)
|
||||
{
|
||||
var isRelational = ex.Source == "Microsoft.EntityFrameworkCore.Relational" && ex.Entries.Any();
|
||||
if (!isRelational)
|
||||
throw;
|
||||
Trace.TraceError("Exception while saving GTR Wits data", ex);
|
||||
}
|
||||
|
||||
cache.AddOrUpdate(idTelemetry,
|
||||
|
@ -0,0 +1,62 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.Manuals;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudDb.Model.Manuals;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AsbCloudInfrastructure.Repository;
|
||||
|
||||
public class ManualDirectoryRepository : CrudRepositoryBase<ManualDirectoryDto, ManualDirectory>, IManualDirectoryRepository
|
||||
{
|
||||
public ManualDirectoryRepository(IAsbCloudDbContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ManualDirectoryDto>> GetTreeAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var directories = await dbContext.ManualDirectories
|
||||
.Include(m => m.Manuals)
|
||||
.Include(m => m.Parent)
|
||||
.AsNoTracking()
|
||||
.ToArrayAsync(cancellationToken);
|
||||
|
||||
return BuildTree(directories).Select(x => x.Adapt<ManualDirectoryDto>());
|
||||
}
|
||||
|
||||
public async Task<ManualDirectoryDto?> GetOrDefaultAsync(string name, int? idParent, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await dbContext.ManualDirectories
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(m => m.Name == name &&
|
||||
m.IdParent == idParent, cancellationToken);
|
||||
|
||||
if (entity is null)
|
||||
return null;
|
||||
|
||||
return Convert(entity);
|
||||
}
|
||||
|
||||
public Task<bool> IsExistsAsync(int id, CancellationToken cancellationToken) =>
|
||||
dbContext.ManualDirectories.AnyAsync(d => d.Id == id, cancellationToken);
|
||||
|
||||
private static IEnumerable<ManualDirectory> BuildTree(IEnumerable<ManualDirectory> directories)
|
||||
{
|
||||
var directoryDict = directories.ToDictionary(f => f.Id);
|
||||
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
if (directory.IdParent.HasValue && directoryDict.TryGetValue(directory.IdParent.Value, out var parent))
|
||||
{
|
||||
parent.Children ??= new List<ManualDirectory>();
|
||||
parent.Children.Add(directory);
|
||||
}
|
||||
}
|
||||
|
||||
return directories.Where(f => f.IdParent == null);
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -12,45 +11,21 @@ using AsbCloudDb;
|
||||
using AsbCloudDb.Model;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace AsbCloudInfrastructure.Repository;
|
||||
|
||||
public class NotificationRepository : CrudCacheRepositoryBase<NotificationDto, Notification>, INotificationRepository
|
||||
public class NotificationRepository : CrudRepositoryBase<NotificationDto, Notification>, INotificationRepository
|
||||
{
|
||||
private static IQueryable<Notification> MakeQueryNotification(DbSet<Notification> dbSet)
|
||||
=> dbSet.Include(n => n.NotificationCategory)
|
||||
.Include(n => n.User)
|
||||
.AsNoTracking();
|
||||
|
||||
public NotificationRepository(IAsbCloudDbContext dbContext, IMemoryCache memoryCache)
|
||||
: base(dbContext, memoryCache, MakeQueryNotification)
|
||||
public NotificationRepository(IAsbCloudDbContext context)
|
||||
: base(context, MakeQueryNotification)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<int> UpdateRangeAsync(IEnumerable<NotificationDto> notifications, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!notifications.Any())
|
||||
return 0;
|
||||
|
||||
var ids = notifications.Select(d => d.Id).ToArray();
|
||||
|
||||
var existingEntities = await dbSet
|
||||
.Where(d => ids.Contains(d.Id))
|
||||
.AsNoTracking()
|
||||
.Select(d => d.Id)
|
||||
.ToArrayAsync(cancellationToken);
|
||||
|
||||
if (ids.Length > existingEntities.Length)
|
||||
return ICrudRepository<SetpointsRequestDto>.ErrorIdNotFound;
|
||||
|
||||
var entities = notifications.Select(Convert);
|
||||
|
||||
dbContext.Notifications.UpdateRange(entities);
|
||||
|
||||
var result = await dbContext.SaveChangesAsync(cancellationToken);
|
||||
DropCache();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public async Task<PaginationContainer<NotificationDto>> GetNotificationsAsync(int idUser,
|
||||
NotificationRequest request,
|
||||
@ -61,7 +36,7 @@ public class NotificationRepository : CrudCacheRepositoryBase<NotificationDto, N
|
||||
|
||||
var query = BuildQuery(idUser, request);
|
||||
|
||||
var result = new PaginationContainer<NotificationDto>()
|
||||
var result = new PaginationContainer<NotificationDto>
|
||||
{
|
||||
Skip = skip,
|
||||
Take = take,
|
||||
@ -82,20 +57,92 @@ public class NotificationRepository : CrudCacheRepositoryBase<NotificationDto, N
|
||||
return result;
|
||||
}
|
||||
|
||||
private IQueryable<Notification> BuildQuery(int idUser,
|
||||
public async Task<IEnumerable<NotificationDto>> GetAllAsync(int? idUser, bool? isSent, int? idTransportType,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = dbContext.Notifications.AsQueryable();
|
||||
|
||||
if (idUser.HasValue)
|
||||
query = query.Where(n => n.IdUser == idUser);
|
||||
|
||||
if(isSent.HasValue)
|
||||
query = isSent.Value ?
|
||||
query.Where(n => n.SentDate != null)
|
||||
: query.Where(n => n.SentDate == null);
|
||||
|
||||
if (idTransportType.HasValue)
|
||||
query = query.Where(n => n.IdTransportType == idTransportType);
|
||||
|
||||
return await query.AsNoTracking().Select(n => n.Adapt<NotificationDto>())
|
||||
.ToArrayAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<int> UpdateRangeAsync(IEnumerable<NotificationDto> notifications, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!notifications.Any())
|
||||
return 0;
|
||||
|
||||
var ids = notifications.Select(d => d.Id);
|
||||
|
||||
var existingEntities = await dbSet
|
||||
.Where(d => ids.Contains(d.Id))
|
||||
.AsNoTracking()
|
||||
.Select(d => d.Id)
|
||||
.ToArrayAsync(cancellationToken);
|
||||
|
||||
if (ids.Count() > existingEntities.Length)
|
||||
return ICrudRepository<SetpointsRequestDto>.ErrorIdNotFound;
|
||||
|
||||
var entities = notifications.Select(Convert);
|
||||
|
||||
dbContext.Notifications.UpdateRange(entities);
|
||||
|
||||
return await dbContext.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public Task<int> DeleteAsync(NotificationDeleteRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = dbContext.Notifications
|
||||
.Include(n => n.NotificationCategory)
|
||||
.AsQueryable();
|
||||
|
||||
if (request.IdCategory.HasValue)
|
||||
query = query.Where(n => n.IdNotificationCategory == request.IdCategory.Value);
|
||||
|
||||
if (request.LtSentDate.HasValue)
|
||||
query = query.Where(n => n.SentDate <= request.LtSentDate.Value);
|
||||
|
||||
if (request.LtReadDate.HasValue)
|
||||
query = query.Where(n => n.ReadDate <= request.LtReadDate.Value);
|
||||
|
||||
dbContext.Notifications.RemoveRange(query);
|
||||
|
||||
return dbContext.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public Task<int> GetUnreadCountAsync(int idUser, int idTransportType, CancellationToken cancellationToken)
|
||||
{
|
||||
return dbContext.Notifications
|
||||
.Where(n => !n.ReadDate.HasValue &&
|
||||
n.SentDate.HasValue &&
|
||||
n.IdUser == idUser &&
|
||||
n.IdTransportType == idTransportType)
|
||||
.CountAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private IQueryable<Notification> BuildQuery(int idUser,
|
||||
NotificationRequest request)
|
||||
{
|
||||
var query = dbContext.Notifications
|
||||
.Include(x => x.NotificationCategory)
|
||||
.Where(n => n.IdUser == idUser);
|
||||
|
||||
if (request.IsSent.HasValue)
|
||||
if (request.IsSent.HasValue)
|
||||
{
|
||||
if(request.IsSent.Value)
|
||||
query = query.Where(n => n.SentDate != null);
|
||||
else
|
||||
query = query.Where(n => n.SentDate == null);
|
||||
}
|
||||
query = request.IsSent.Value ?
|
||||
query.Where(n => n.SentDate != null)
|
||||
: query.Where(n => n.SentDate == null);
|
||||
}
|
||||
|
||||
if (request.IdTransportType.HasValue)
|
||||
query = query.Where(n => n.IdTransportType == request.IdTransportType);
|
||||
|
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.ProcessMap;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AsbCloudInfrastructure.Repository;
|
||||
|
||||
public class ProcessMapWellboreDevelopmentRepository :
|
||||
CrudWellRelatedRepositoryBase<ProcessMapWellboreDevelopmentDto, ProcessMapWellboreDevelopment>,
|
||||
IProcessMapWellboreDevelopmentRepository
|
||||
{
|
||||
private readonly IWellService wellService;
|
||||
|
||||
public ProcessMapWellboreDevelopmentRepository(IAsbCloudDbContext context, IWellService wellService) : base(context)
|
||||
{
|
||||
this.wellService = wellService;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ProcessMapWellboreDevelopmentDto>> GetAllAsync(int idWell, DateTime? updateFrom,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = dbContext.ProcessMapWellboreDevelopments
|
||||
.Where(p => p.IdWell == idWell);
|
||||
|
||||
if (updateFrom.HasValue)
|
||||
{
|
||||
var timezone = wellService.GetTimezone(idWell);
|
||||
var updateFromUtc = updateFrom.Value.ToUtcDateTimeOffset(timezone.Hours);
|
||||
query = query.Where(p => p.LastUpdate >= updateFromUtc);
|
||||
}
|
||||
|
||||
var entities = await query
|
||||
.OrderBy(p => p.DepthStart)
|
||||
.ThenBy(p => p.Id)
|
||||
.AsNoTracking()
|
||||
.ToArrayAsync(cancellationToken);
|
||||
|
||||
return entities.Select(Convert);
|
||||
}
|
||||
}
|
@ -41,8 +41,6 @@ namespace AsbCloudInfrastructure.Repository
|
||||
IdWell = idWell,
|
||||
AzimuthMagnetic = coord.Svymtf,
|
||||
VerticalDepth = coord.Deptsvyv,
|
||||
NorthOrifice = coord.Svyns,
|
||||
EastOrifice = coord.Svyew,
|
||||
WellboreDepth = coord.Deptsvym!.Value,
|
||||
ZenithAngle = coord.Svyinc!.Value,
|
||||
AzimuthGeo = coord.Svyazc!.Value
|
||||
|
@ -16,6 +16,9 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services.Notifications;
|
||||
using AsbCloudInfrastructure.Services.Email;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
{
|
||||
@ -23,15 +26,18 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
public class DrillingProgramService : IDrillingProgramService
|
||||
{
|
||||
private static readonly Dictionary<string, DrillingProgramCreateError> drillingProgramCreateErrors = new Dictionary<string, DrillingProgramCreateError>();
|
||||
|
||||
|
||||
private readonly IAsbCloudDbContext context;
|
||||
private readonly FileService fileService;
|
||||
private readonly IUserRepository userRepository;
|
||||
private readonly IWellService wellService;
|
||||
private readonly IConfiguration configuration;
|
||||
private readonly BackgroundWorker backgroundWorker;
|
||||
private readonly IEmailService emailService;
|
||||
|
||||
private readonly NotificationService notificationService;
|
||||
|
||||
private const int idNotificationCategory = 20000;
|
||||
private const int idTransportType = 1;
|
||||
|
||||
private const int idFileCategoryDrillingProgram = 1000;
|
||||
private const int idFileCategoryDrillingProgramPartsStart = 1001;
|
||||
private const int idFileCategoryDrillingProgramPartsEnd = 1100;
|
||||
@ -61,7 +67,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
IWellService wellService,
|
||||
IConfiguration configuration,
|
||||
BackgroundWorker backgroundWorker,
|
||||
IEmailService emailService)
|
||||
NotificationService notificationService)
|
||||
{
|
||||
this.context = context;
|
||||
this.fileService = fileService;
|
||||
@ -69,7 +75,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
this.wellService = wellService;
|
||||
this.configuration = configuration;
|
||||
this.backgroundWorker = backgroundWorker;
|
||||
this.emailService = emailService;
|
||||
this.notificationService = notificationService;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<UserDto>> GetAvailableUsers(int idWell, CancellationToken token = default)
|
||||
@ -378,7 +384,14 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
var subject = factory.MakeSubject(well, "Загруженный вами документ полностью согласован");
|
||||
var body = factory.MakeMailBodyForPublisherOnFullAccept(well, user.Name ?? string.Empty, file.Id, file.Name);
|
||||
|
||||
emailService.EnqueueSend(user.Email, subject, body);
|
||||
await notificationService.NotifyAsync(new NotifyRequest
|
||||
{
|
||||
IdUser = user.Id,
|
||||
IdNotificationCategory = idNotificationCategory,
|
||||
Title = subject,
|
||||
Message = body,
|
||||
IdTransportType = idTransportType
|
||||
}, token);
|
||||
}
|
||||
|
||||
private async Task NotifyPublisherOnRejectAsync(FileMarkDto fileMark, CancellationToken token)
|
||||
@ -393,7 +406,14 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
var subject = factory.MakeSubject(well, "Загруженный вами документ отклонен");
|
||||
var body = factory.MakeMailBodyForPublisherOnReject(well, user.Name ?? string.Empty, file.Id, file.Name, fileMark);
|
||||
|
||||
emailService.EnqueueSend(user.Email, subject, body);
|
||||
await notificationService.NotifyAsync(new NotifyRequest
|
||||
{
|
||||
IdUser = user.Id,
|
||||
IdNotificationCategory = idNotificationCategory,
|
||||
Title = subject,
|
||||
Message = body,
|
||||
IdTransportType = idTransportType
|
||||
}, token);
|
||||
}
|
||||
|
||||
private async Task NotifyApproversAsync(DrillingProgramPart part, int idFile, string fileName, CancellationToken token)
|
||||
@ -411,7 +431,14 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
foreach (var user in users)
|
||||
{
|
||||
var body = factory.MakeMailBodyForApproverNewFile(well, user.Name ?? string.Empty, idFile, fileName);
|
||||
emailService.EnqueueSend(user.Email, subject, body);
|
||||
await notificationService.NotifyAsync(new NotifyRequest
|
||||
{
|
||||
IdUser = user.Id,
|
||||
IdNotificationCategory = idNotificationCategory,
|
||||
Title = subject,
|
||||
Message = body,
|
||||
IdTransportType = idTransportType
|
||||
}, token);
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,7 +451,15 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
var factory = new DrillingMailBodyFactory(configuration);
|
||||
var subject = factory.MakeSubject(well, $"От вас ожидается загрузка на портал документа «{documentCategory}»");
|
||||
var body = factory.MakeMailBodyForNewPublisher(well, user.Name ?? string.Empty, documentCategory);
|
||||
emailService.EnqueueSend(user.Email, subject, body);
|
||||
|
||||
await notificationService.NotifyAsync(new NotifyRequest
|
||||
{
|
||||
IdUser = user.Id,
|
||||
IdNotificationCategory = idNotificationCategory,
|
||||
Title = subject,
|
||||
Message = body,
|
||||
IdTransportType = idTransportType
|
||||
}, token);
|
||||
}
|
||||
|
||||
private static DrillingProgramPartDto ConvertPart(int idUser, List<FileCategory> fileCategories, List<AsbCloudDb.Model.FileInfo> files, DrillingProgramPart partEntity, double timezoneOffset)
|
||||
|
@ -1,10 +1,7 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudInfrastructure.Services.Email;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace AsbCloudInfrastructure
|
||||
namespace AsbCloudInfrastructure.Services.Email
|
||||
{
|
||||
|
||||
class DrillingMailBodyFactory : BaseFactory
|
||||
|
@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.Mail;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Services.Notifications;
|
||||
using AsbCloudInfrastructure.Background;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.Email
|
||||
{
|
||||
|
||||
public class EmailNotificationTransportService : INotificationTransportService
|
||||
{
|
||||
private readonly BackgroundWorker backgroundWorker;
|
||||
private readonly bool IsConfigured;
|
||||
private readonly string sender;
|
||||
private readonly string smtpServer;
|
||||
private readonly string smtpPassword;
|
||||
|
||||
public EmailNotificationTransportService(BackgroundWorker backgroundWorker,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
sender = configuration.GetValue("email:sender", string.Empty);
|
||||
smtpPassword = configuration.GetValue("email:password", string.Empty);
|
||||
smtpServer = configuration.GetValue("email:smtpServer", string.Empty);
|
||||
|
||||
var configError = string.IsNullOrEmpty(sender) ||
|
||||
string.IsNullOrEmpty(smtpPassword) ||
|
||||
string.IsNullOrEmpty(smtpServer);
|
||||
|
||||
IsConfigured = !configError;
|
||||
|
||||
this.backgroundWorker = backgroundWorker;
|
||||
}
|
||||
|
||||
public int IdTransportType => 1;
|
||||
|
||||
public Task SendAsync(NotificationDto notification, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!IsConfigured)
|
||||
{
|
||||
Trace.TraceWarning("smtp is not configured");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var workId = MakeWorkId(notification.IdUser, notification.Title, notification.Message);
|
||||
if (!backgroundWorker.Contains(workId))
|
||||
{
|
||||
var workAction = MakeEmailSendWorkAction(notification);
|
||||
|
||||
var work = new WorkBase(workId, workAction);
|
||||
backgroundWorker.Push(work);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task SendRangeAsync(IEnumerable<NotificationDto> notifications, CancellationToken cancellationToken)
|
||||
{
|
||||
var tasks = notifications
|
||||
.Select(notification => SendAsync(notification, cancellationToken));
|
||||
|
||||
return Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
|
||||
private Func<string, IServiceProvider, CancellationToken, Task> MakeEmailSendWorkAction(NotificationDto notification)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(notification.Title))
|
||||
throw new ArgumentInvalidException($"{nameof(notification.Title)} should be set", nameof(notification.Title));
|
||||
|
||||
return async (_, serviceProvider, token) =>
|
||||
{
|
||||
var notificationRepository = serviceProvider.GetRequiredService<INotificationRepository>();
|
||||
var userRepository = serviceProvider.GetRequiredService<IUserRepository>();
|
||||
|
||||
var user = await userRepository.GetOrDefaultAsync(notification.IdUser, token)
|
||||
?? throw new ArgumentInvalidException("Пользователь не найден" , nameof(notification.IdUser));
|
||||
|
||||
if(!MailAddress.TryCreate(user.Email, out var mailAddress))
|
||||
Trace.TraceWarning($"Mail {user.Email} is not correct.");
|
||||
|
||||
if (mailAddress is null)
|
||||
throw new ArgumentInvalidException($"Mail {user.Email} is not null.", nameof(user.Email));
|
||||
|
||||
var from = new MailAddress(sender);
|
||||
var message = new MailMessage
|
||||
{
|
||||
From = from
|
||||
};
|
||||
|
||||
message.To.Add(mailAddress.Address);
|
||||
message.BodyEncoding = System.Text.Encoding.UTF8;
|
||||
message.Body = notification.Message;
|
||||
message.Subject = notification.Title;
|
||||
message.IsBodyHtml = true;
|
||||
|
||||
using var client = new SmtpClient(smtpServer);
|
||||
client.EnableSsl = true;
|
||||
client.UseDefaultCredentials = false;
|
||||
client.Credentials = new System.Net.NetworkCredential(sender, smtpPassword);
|
||||
|
||||
await client.SendMailAsync(message, token);
|
||||
|
||||
notification.SentDate = DateTime.UtcNow;
|
||||
|
||||
await notificationRepository.UpdateAsync(notification, token);
|
||||
|
||||
Trace.TraceInformation($"Send email to {user.Email} subj:{notification.Title} html body count {notification.Message.Length}");
|
||||
};
|
||||
}
|
||||
|
||||
private static string MakeWorkId(int idUser, string subject, string content)
|
||||
{
|
||||
var hash = idUser.GetHashCode();
|
||||
hash ^= subject.GetHashCode();
|
||||
hash ^= content.GetHashCode();
|
||||
return hash.ToString("x");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.Mail;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudInfrastructure.Background;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
|
||||
public class EmailService : IEmailService
|
||||
{
|
||||
private readonly BackgroundWorker backgroundWorker;
|
||||
private readonly bool IsConfigured;
|
||||
private readonly string sender;
|
||||
private readonly string smtpServer;
|
||||
private readonly string smtpPassword;
|
||||
|
||||
public EmailService(BackgroundWorker backgroundWorker, IConfiguration configuration)
|
||||
{
|
||||
sender = configuration.GetValue("email:sender", string.Empty);
|
||||
smtpPassword = configuration.GetValue("email:password", string.Empty);
|
||||
smtpServer = configuration.GetValue("email:smtpServer", string.Empty);
|
||||
|
||||
var configError = string.IsNullOrEmpty(sender) ||
|
||||
string.IsNullOrEmpty(smtpPassword) ||
|
||||
string.IsNullOrEmpty(smtpServer);
|
||||
|
||||
IsConfigured = !configError;
|
||||
|
||||
this.backgroundWorker = backgroundWorker;
|
||||
}
|
||||
|
||||
public void EnqueueSend(string address, string subject, string htmlBody)
|
||||
=> EnqueueSend(new List<string> { address }, subject, htmlBody);
|
||||
|
||||
public void EnqueueSend(IEnumerable<string> addresses, string subject, string htmlBody)
|
||||
{
|
||||
if (!IsConfigured)
|
||||
{
|
||||
Trace.TraceWarning("smtp is not configured");
|
||||
return;
|
||||
}
|
||||
var workId = MakeWorkId(addresses, subject, htmlBody);
|
||||
if (!backgroundWorker.Contains(workId))
|
||||
{
|
||||
var workAction = MakeEmailSendWorkAction(addresses, subject, htmlBody);
|
||||
var work = new WorkBase(workId, workAction);
|
||||
backgroundWorker.Push(work);
|
||||
}
|
||||
}
|
||||
|
||||
private Func<string, IServiceProvider, CancellationToken, Task> MakeEmailSendWorkAction(IEnumerable<string> addresses, string subject, string htmlBody)
|
||||
{
|
||||
var mailAddresses = new List<MailAddress>();
|
||||
foreach (var address in addresses)
|
||||
{
|
||||
if (MailAddress.TryCreate(address, out MailAddress? mailAddress))
|
||||
mailAddresses.Add(mailAddress);
|
||||
else
|
||||
Trace.TraceWarning($"Mail {address} is not correct.");
|
||||
}
|
||||
|
||||
if (!mailAddresses.Any())
|
||||
throw new ArgumentException($"No valid email found. List:[{string.Join(',', addresses)}]", nameof(addresses));
|
||||
|
||||
if (string.IsNullOrEmpty(subject))
|
||||
throw new ArgumentInvalidException($"{nameof(subject)} should be set", nameof(subject));
|
||||
|
||||
var workAction = async (string id, IServiceProvider serviceProvider, CancellationToken token) =>
|
||||
{
|
||||
var from = new MailAddress(sender);
|
||||
var message = new MailMessage
|
||||
{
|
||||
From = from
|
||||
};
|
||||
|
||||
foreach (var mailAddress in mailAddresses)
|
||||
message.To.Add(mailAddress);
|
||||
|
||||
message.BodyEncoding = System.Text.Encoding.UTF8;
|
||||
message.Body = htmlBody;
|
||||
message.Subject = subject;
|
||||
message.IsBodyHtml = true;
|
||||
|
||||
using var client = new SmtpClient(smtpServer);
|
||||
client.EnableSsl = true;
|
||||
client.UseDefaultCredentials = false;
|
||||
client.Credentials = new System.Net.NetworkCredential(sender, smtpPassword);
|
||||
|
||||
await client.SendMailAsync(message, token);
|
||||
Trace.TraceInformation($"Send email to {string.Join(',', addresses)} subj:{subject} html body count {htmlBody.Length}");
|
||||
};
|
||||
return workAction;
|
||||
}
|
||||
|
||||
private static string MakeWorkId(IEnumerable<string> addresses, string subject, string content)
|
||||
{
|
||||
var hash = GetHashCode(addresses);
|
||||
hash ^= subject.GetHashCode();
|
||||
hash ^= content.GetHashCode();
|
||||
return hash.ToString("x");
|
||||
}
|
||||
|
||||
private static int GetHashCode(IEnumerable<string> strings)
|
||||
{
|
||||
int hash = -1397075115;
|
||||
var enumerator = strings.GetEnumerator();
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
hash ^= enumerator.Current.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
180
AsbCloudInfrastructure/Services/ManualCatalogService.cs
Normal file
180
AsbCloudInfrastructure/Services/ManualCatalogService.cs
Normal file
@ -0,0 +1,180 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.Manuals;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services;
|
||||
|
||||
public class ManualCatalogService : IManualCatalogService
|
||||
{
|
||||
private const int IdFileCategory = 30000;
|
||||
|
||||
private readonly IEnumerable<string> validExtensions = new[]
|
||||
{
|
||||
".pdf",
|
||||
".mp4"
|
||||
};
|
||||
|
||||
private readonly string directoryFiles;
|
||||
private readonly IFileStorageRepository fileStorageRepository;
|
||||
private readonly IManualDirectoryRepository manualDirectoryRepository;
|
||||
private readonly ICrudRepository<ManualDto> manualRepository;
|
||||
|
||||
public ManualCatalogService(IFileStorageRepository fileStorageRepository,
|
||||
IManualDirectoryRepository manualDirectoryRepository,
|
||||
ICrudRepository<ManualDto> manualRepository,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
this.fileStorageRepository = fileStorageRepository;
|
||||
this.manualDirectoryRepository = manualDirectoryRepository;
|
||||
this.manualRepository = manualRepository;
|
||||
directoryFiles = configuration.GetValue<string>("DirectoryManualFiles");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(directoryFiles))
|
||||
directoryFiles = "manuals";
|
||||
}
|
||||
|
||||
public async Task<int> SaveFileAsync(int idDirectory, int idAuthor, string name, Stream stream, CancellationToken cancellationToken)
|
||||
{
|
||||
var extension = Path.GetExtension(name);
|
||||
|
||||
if (!validExtensions.Contains(extension))
|
||||
throw new ArgumentInvalidException(
|
||||
$"Невозможно загрузить файл с расширением '{extension}'. Допустимые форматы файлов: {string.Join(", ", validExtensions)}",
|
||||
extension);
|
||||
|
||||
var path = await BuildFilePathAsync(idDirectory, name, cancellationToken);
|
||||
|
||||
await fileStorageRepository.SaveFileAsync(path, stream, cancellationToken);
|
||||
|
||||
var manual = new ManualDto
|
||||
{
|
||||
Name = name,
|
||||
DateDownload = DateTime.UtcNow,
|
||||
IdDirectory = idDirectory,
|
||||
IdCategory = IdFileCategory,
|
||||
IdAuthor = idAuthor
|
||||
};
|
||||
|
||||
return await manualRepository.InsertAsync(manual, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<int> AddDirectoryAsync(string name, int? idParent, CancellationToken cancellationToken)
|
||||
{
|
||||
if (idParent.HasValue && !await manualDirectoryRepository.IsExistsAsync(idParent.Value, cancellationToken))
|
||||
throw new ArgumentInvalidException("Родительской директории не существует", nameof(idParent));
|
||||
|
||||
var directory = new ManualDirectoryDto
|
||||
{
|
||||
Name = name,
|
||||
IdParent = idParent,
|
||||
};
|
||||
|
||||
if (await IsExistDirectoryAsync(directory, cancellationToken))
|
||||
throw new ArgumentInvalidException("Директория с таким названием уже существует", name);
|
||||
|
||||
return await manualDirectoryRepository.InsertAsync(directory, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task UpdateDirectoryAsync(int id, string name, CancellationToken cancellationToken)
|
||||
{
|
||||
var directory = await manualDirectoryRepository.GetOrDefaultAsync(id, cancellationToken)
|
||||
?? throw new ArgumentInvalidException($"Директории с Id: {id} не существует", nameof(id));
|
||||
|
||||
directory.Name = name;
|
||||
|
||||
if (await IsExistDirectoryAsync(directory, cancellationToken))
|
||||
throw new ArgumentInvalidException("Директория с таким названием уже существует", name);
|
||||
|
||||
await manualDirectoryRepository.UpdateAsync(directory, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<int> DeleteDirectoryAsync(int id, CancellationToken cancellationToken)
|
||||
{
|
||||
var directory = await manualDirectoryRepository.GetOrDefaultAsync(id, cancellationToken);
|
||||
|
||||
if (directory is null)
|
||||
return 0;
|
||||
|
||||
var path = fileStorageRepository.MakeFilePath(directoryFiles, IdFileCategory.ToString(),
|
||||
await BuildDirectoryPathAsync(id, cancellationToken));
|
||||
|
||||
try
|
||||
{
|
||||
fileStorageRepository.DeleteDirectory(path, true);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
throw new ArgumentInvalidException(ex.Message, nameof(id));
|
||||
}
|
||||
|
||||
return await manualDirectoryRepository.DeleteAsync(directory.Id, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<int> DeleteFileAsync(int id, CancellationToken cancellationToken)
|
||||
{
|
||||
var manual = await manualRepository.GetOrDefaultAsync(id, cancellationToken);
|
||||
|
||||
if (manual is null)
|
||||
return 0;
|
||||
|
||||
var filePath = await BuildFilePathAsync(manual.IdDirectory, manual.Name, cancellationToken);
|
||||
|
||||
fileStorageRepository.DeleteFile(filePath);
|
||||
|
||||
return await manualRepository.DeleteAsync(manual.Id, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<(Stream stream, string fileName)?> GetFileAsync(int id, CancellationToken cancellationToken)
|
||||
{
|
||||
var manual = await manualRepository.GetOrDefaultAsync(id, cancellationToken);
|
||||
|
||||
if (manual is null)
|
||||
return null;
|
||||
|
||||
var path = await BuildFilePathAsync(manual.IdDirectory, manual.Name, cancellationToken);
|
||||
var fileStream = new FileStream(path, FileMode.Open);
|
||||
return (fileStream, manual.Name);
|
||||
}
|
||||
|
||||
private async Task<bool> IsExistDirectoryAsync(ManualDirectoryDto directory, CancellationToken cancellationToken)
|
||||
{
|
||||
var existingDirectory = await manualDirectoryRepository.GetOrDefaultAsync(directory.Name, directory.IdParent,
|
||||
cancellationToken);
|
||||
|
||||
return existingDirectory is not null && directory.Id != existingDirectory.Id;
|
||||
}
|
||||
|
||||
private async Task<string> BuildDirectoryPathAsync(int idDirectory, CancellationToken cancellationToken)
|
||||
{
|
||||
var directiories = await manualDirectoryRepository.GetAllAsync(cancellationToken);
|
||||
|
||||
var directory = directiories.FirstOrDefault(d => d.Id == idDirectory)
|
||||
?? throw new ArgumentInvalidException($"Директории с Id: {idDirectory} не существует", nameof(idDirectory));
|
||||
|
||||
var pathSegments = new List<int> { directory.Id };
|
||||
|
||||
while (directory.IdParent.HasValue)
|
||||
{
|
||||
directory = directiories.FirstOrDefault(d => d.Id == directory.IdParent.Value);
|
||||
|
||||
pathSegments.Insert(0, directory.Id);
|
||||
}
|
||||
|
||||
return string.Join("/", pathSegments);
|
||||
}
|
||||
|
||||
private async Task<string> BuildFilePathAsync(int idDirectory, string name, CancellationToken cancellationToken)
|
||||
{
|
||||
var directoryPath = await BuildDirectoryPathAsync(idDirectory, cancellationToken);
|
||||
|
||||
return fileStorageRepository.MakeFilePath(directoryFiles, IdFileCategory.ToString(), Path.Combine(directoryPath, name));
|
||||
}
|
||||
}
|
@ -13,13 +13,13 @@ namespace AsbCloudInfrastructure.Services.ProcessMap
|
||||
public class ProcessMapReportMakerService : IProcessMapReportMakerService
|
||||
{
|
||||
const int firstColumn = 2;
|
||||
const int lastColumn = 49;
|
||||
const int lastColumn = 42;
|
||||
|
||||
const int headerRowsCount = 5;
|
||||
|
||||
private readonly IProcessMapReportService processMapService;
|
||||
private readonly IProcessMapService processMapService;
|
||||
|
||||
public ProcessMapReportMakerService(IProcessMapReportService processMapService)
|
||||
public ProcessMapReportMakerService(IProcessMapService processMapService)
|
||||
{
|
||||
this.processMapService = processMapService;
|
||||
}
|
||||
|
Binary file not shown.
@ -12,14 +12,14 @@ using System.Threading.Tasks;
|
||||
namespace AsbCloudInfrastructure.Services.ProcessMap
|
||||
{
|
||||
|
||||
public partial class ProcessMapReportService : IProcessMapReportService
|
||||
public partial class ProcessMapService : IProcessMapService
|
||||
{
|
||||
private readonly IWellService wellService;
|
||||
private readonly IWellOperationRepository wellOperationRepository;
|
||||
private readonly IProcessMapPlanRepository processMapPlanRepository;
|
||||
private readonly ITelemetryDataSaubService telemetryDataSaubService;
|
||||
|
||||
public ProcessMapReportService(
|
||||
public ProcessMapService(
|
||||
IWellService wellService,
|
||||
IWellOperationRepository wellOperationRepository,
|
||||
IProcessMapPlanRepository processMapPlanRepository,
|
@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.ProcessMap;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Services;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.ProcessMap.ProcessMapWellboreDevelopment;
|
||||
|
||||
public class ProcessMapWellboreDevelopmentService : IProcessMapWellboreDevelopmentService
|
||||
{
|
||||
private readonly ITelemetryService telemetryService;
|
||||
private readonly IWellService wellService;
|
||||
private readonly IProcessMapWellboreDevelopmentRepository processMapWellboreDevelopmentRepository;
|
||||
|
||||
public ProcessMapWellboreDevelopmentService(ITelemetryService telemetryService,
|
||||
IWellService wellService,
|
||||
IProcessMapWellboreDevelopmentRepository processMapWellboreDevelopmentRepository)
|
||||
{
|
||||
this.telemetryService = telemetryService;
|
||||
this.wellService = wellService;
|
||||
this.processMapWellboreDevelopmentRepository = processMapWellboreDevelopmentRepository;
|
||||
}
|
||||
|
||||
public async Task<int> InsertAsync(ProcessMapWellboreDevelopmentDto processMapWellboreDevelopment, CancellationToken cancellationToken)
|
||||
{
|
||||
var well = await wellService.GetOrDefaultAsync(processMapWellboreDevelopment.IdWell, cancellationToken);
|
||||
|
||||
if (well is null)
|
||||
throw new ArgumentInvalidException($"Скважины с Id: {processMapWellboreDevelopment.IdWell} не существует",
|
||||
nameof(processMapWellboreDevelopment.IdWell));
|
||||
|
||||
if (processMapWellboreDevelopment.DepthStart > processMapWellboreDevelopment.DepthEnd)
|
||||
throw new ArgumentInvalidException("Значение стартовой глубины должно быть не больше значения конечной глубины",
|
||||
nameof(processMapWellboreDevelopment.DepthStart));
|
||||
|
||||
processMapWellboreDevelopment.LastUpdate = DateTimeOffset.UtcNow;
|
||||
|
||||
return await processMapWellboreDevelopmentRepository.InsertAsync(processMapWellboreDevelopment, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<int> UpdateAsync(ProcessMapWellboreDevelopmentDto processMapWellboreDevelopment, CancellationToken cancellationToken)
|
||||
{
|
||||
var well = await wellService.GetOrDefaultAsync(processMapWellboreDevelopment.IdWell, cancellationToken);
|
||||
|
||||
if (well is null)
|
||||
throw new ArgumentInvalidException($"Скважины с Id: {processMapWellboreDevelopment.IdWell} не существует",
|
||||
nameof(processMapWellboreDevelopment.IdWell));
|
||||
|
||||
if (processMapWellboreDevelopment.DepthStart > processMapWellboreDevelopment.DepthEnd)
|
||||
throw new ArgumentInvalidException("Значение стартовой глубины должно быть не больше значения конечной глубины",
|
||||
nameof(processMapWellboreDevelopment.DepthStart));
|
||||
|
||||
processMapWellboreDevelopment.LastUpdate = DateTimeOffset.UtcNow;
|
||||
|
||||
var result = await processMapWellboreDevelopmentRepository.UpdateAsync(processMapWellboreDevelopment, cancellationToken);
|
||||
|
||||
if (result == ICrudRepository<ProcessMapWellboreDevelopmentDto>.ErrorIdNotFound)
|
||||
throw new ArgumentInvalidException($"Проработки с Id: {processMapWellboreDevelopment.Id} не существует",
|
||||
nameof(processMapWellboreDevelopment.Id));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ProcessMapWellboreDevelopmentDto>> GetByTelemetryAsync(string uid, DateTime updateFrom,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var idWell = telemetryService.GetIdWellByTelemetryUid(uid);
|
||||
|
||||
if (!idWell.HasValue)
|
||||
throw new ArgumentInvalidException($"Неправильный телеметрии. Uid: {uid}", nameof(uid));
|
||||
|
||||
return await processMapWellboreDevelopmentRepository.GetAllAsync(idWell.Value, updateFrom, cancellationToken);
|
||||
}
|
||||
}
|
@ -168,6 +168,14 @@ namespace AsbCloudInfrastructure.Services
|
||||
//PDF
|
||||
_ => new AsbSaubReportPdf.ReprotGeneratorPdf(dataSource),
|
||||
};
|
||||
|
||||
if(begin == default || end == default)
|
||||
{
|
||||
var analyzeResult = dataSource.Analyze();
|
||||
begin = begin == default ? analyzeResult.MinDate : begin;
|
||||
end = end == default ? begin.AddDays(1) : end;
|
||||
}
|
||||
|
||||
generator.Begin = begin;
|
||||
generator.End = end;
|
||||
generator.Step = TimeSpan.FromSeconds(stepSeconds);
|
||||
|
@ -63,10 +63,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
return entity;
|
||||
});
|
||||
|
||||
var entityMaxDate = entities.Max(e => e.DateTime);
|
||||
|
||||
var dbset = db.Set<TEntity>();
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var dbset = db.Set<TEntity>();
|
||||
try
|
||||
{
|
||||
return await db.Database.ExecInsertOrUpdateAsync(dbset, entities, token).ConfigureAwait(false);
|
||||
@ -137,10 +135,67 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
}
|
||||
|
||||
var entities = await query
|
||||
.OrderBy(d => d.DateTime)
|
||||
.AsNoTracking()
|
||||
.ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
.ToArrayAsync(token);
|
||||
|
||||
var dtos = entities.Select(e => Convert(e, timezone.Hours));
|
||||
|
||||
return dtos;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual async Task<IEnumerable<TDto>> GetAsync(int idWell, AsbCloudApp.Requests.TelemetryDataRequest request, CancellationToken token)
|
||||
{
|
||||
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
|
||||
if (telemetry is null)
|
||||
return Enumerable.Empty<TDto>();
|
||||
|
||||
var timezone = telemetryService.GetTimezone(telemetry.Id);
|
||||
|
||||
var cache = telemetryDataCache.GetOrDefault(telemetry.Id, request);
|
||||
if(cache is not null)
|
||||
return cache;
|
||||
|
||||
var dbSet = db.Set<TEntity>();
|
||||
|
||||
var query = dbSet
|
||||
.Where(d => d.IdTelemetry == telemetry.Id)
|
||||
.AsNoTracking();
|
||||
|
||||
if (request.GeDate.HasValue)
|
||||
{
|
||||
var geDate = request.GeDate.Value.UtcDateTime;
|
||||
query = query.Where(d => d.DateTime >= geDate);
|
||||
}
|
||||
|
||||
if (request.LeDate.HasValue)
|
||||
{
|
||||
var leDate = request.LeDate.Value.UtcDateTime;
|
||||
query = query.Where(d => d.DateTime <= leDate);
|
||||
}
|
||||
|
||||
if (request.Divider > 1)
|
||||
query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % request.Divider == 0);
|
||||
|
||||
switch (request.Order)
|
||||
{
|
||||
case 1:// Поздние вперед
|
||||
query = query
|
||||
.OrderByDescending(d => d.DateTime)
|
||||
.Skip(request.Skip)
|
||||
.Take(request.Take)
|
||||
.OrderBy(d => d.DateTime);
|
||||
break;
|
||||
default:// Ранние вперед
|
||||
query = query
|
||||
.OrderBy(d => d.DateTime)
|
||||
.Skip(request.Skip)
|
||||
.Take(request.Take);
|
||||
break;
|
||||
}
|
||||
|
||||
var entities = await query
|
||||
.ToArrayAsync(token);
|
||||
|
||||
var dtos = entities.Select(e => Convert(e, timezone.Hours));
|
||||
|
||||
|
@ -11,6 +11,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using AsbCloudInfrastructure.Background;
|
||||
using System.Threading;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Requests;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.SAUB
|
||||
{
|
||||
@ -21,6 +22,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
{
|
||||
public TDto? FirstByDate { get; init; }
|
||||
public CyclycArray<TDto> LastData { get; init; } = null!;
|
||||
public double TimezoneHours { get; init; } = 5;
|
||||
}
|
||||
|
||||
private IServiceProvider provider = null!;
|
||||
@ -155,9 +157,12 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
throw new Exception("Multiple cache loading detected.");
|
||||
|
||||
isLoading = true;
|
||||
Well[] wells = Array.Empty<Well>();
|
||||
|
||||
wells = await db.Set<Well>()
|
||||
var defaultTimeout = db.Database.GetCommandTimeout();
|
||||
System.Diagnostics.Trace.TraceInformation($"cache loading starting. Setting CommandTimeout 90s ({defaultTimeout})");
|
||||
db.Database.SetCommandTimeout(TimeSpan.FromSeconds(90));
|
||||
|
||||
Well[] wells = await db.Set<Well>()
|
||||
.Include(well => well.Telemetry)
|
||||
.Include(well => well.Cluster)
|
||||
.Where(well => well.IdTelemetry != null)
|
||||
@ -172,6 +177,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
var idTelemetry = well.IdTelemetry!.Value;
|
||||
var hoursOffset = well.Timezone.Hours;
|
||||
|
||||
System.Diagnostics.Trace.TraceInformation($"cache<{typeof(TDto).Name}>: Loading for well: {well.Cluster?.Caption}/{well.Caption} (capacity:{capacity}) idTelemetry:{idTelemetry}");
|
||||
var cacheItem = await GetOrDefaultCacheDataFromDbAsync<TEntity>(db, idTelemetry, capacity, hoursOffset, token);
|
||||
if(cacheItem is not null)
|
||||
{
|
||||
@ -186,6 +192,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
|
||||
System.Diagnostics.Trace.TraceInformation($"cache<{typeof(TDto).Name}> load complete");
|
||||
isLoading = false;
|
||||
db.Database.SetCommandTimeout(defaultTimeout);
|
||||
}
|
||||
|
||||
private static async Task<TelemetryDataCacheItem?> GetOrDefaultCacheDataFromDbAsync<TEntity>(IAsbCloudDbContext db, int idTelemetry, int capacity, double hoursOffset, CancellationToken token)
|
||||
@ -225,8 +232,62 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
{
|
||||
FirstByDate = first,
|
||||
LastData = cacheItem,
|
||||
TimezoneHours = hoursOffset,
|
||||
};
|
||||
return item;
|
||||
}
|
||||
|
||||
public IEnumerable<TDto>? GetOrDefault(int idTelemetry, TelemetryDataRequest request)
|
||||
{
|
||||
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
|
||||
return null;
|
||||
|
||||
IEnumerable<TDto> data = cacheItem.LastData;
|
||||
|
||||
if (!data.Any())
|
||||
return null;
|
||||
|
||||
if (request.GeDate.HasValue)
|
||||
{
|
||||
var geDate = request.GeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
|
||||
if (data.First().DateTime > geDate)
|
||||
return null;
|
||||
|
||||
data = data.Where(d => d.DateTime >= geDate);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request.Order == 0)
|
||||
return null;
|
||||
}
|
||||
|
||||
if (request.LeDate.HasValue)
|
||||
{
|
||||
var leDate = request.LeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
|
||||
data = data.Where(d => d.DateTime >= request.LeDate);
|
||||
}
|
||||
|
||||
if (request.Divider > 1)
|
||||
data = data.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % request.Divider == 0);
|
||||
|
||||
switch (request.Order)
|
||||
{
|
||||
case 1: // Поздние вперед
|
||||
data = data
|
||||
.OrderByDescending(d => d.DateTime)
|
||||
.Skip(request.Skip)
|
||||
.Take(request.Take)
|
||||
.OrderBy(d => d.DateTime);
|
||||
break;
|
||||
default: // Ранние вперед
|
||||
data = data
|
||||
.OrderBy(d => d.DateTime)
|
||||
.Skip(request.Skip)
|
||||
.Take(request.Take);
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
{
|
||||
|
||||
internal static class SubsystemOperationTimeCalcWorkFactory
|
||||
{
|
||||
private const string workId = "Subsystem operation time calc";
|
||||
@ -23,7 +22,8 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
|
||||
private const int idSubsytemTorqueMaster = 65537;
|
||||
private const int idSubsytemSpinMaster = 65536;
|
||||
private const int idSubsytemAkb = 1;
|
||||
private const int idSubsystemAPDRotor = 11;
|
||||
private const int idSubsystemAPDSlide = 12;
|
||||
private const int idSubsytemMse = 2;
|
||||
|
||||
public static WorkPeriodic MakeWork()
|
||||
@ -85,8 +85,8 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
{
|
||||
var connection = db.Database.GetDbConnection();
|
||||
if (
|
||||
connection?.State is null ||
|
||||
connection.State == ConnectionState.Broken ||
|
||||
connection?.State is null ||
|
||||
connection.State == ConnectionState.Broken ||
|
||||
connection.State == ConnectionState.Closed)
|
||||
{
|
||||
await db.Database.OpenConnectionAsync(token);
|
||||
@ -101,23 +101,11 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
|
||||
private static async Task<IEnumerable<SubsystemOperationTime>> OperationTimeSaubAsync(int idTelemetry, DateTimeOffset begin, IAsbCloudDbContext db, CancellationToken token)
|
||||
{
|
||||
static bool isSubsytemAkb(short? mode)
|
||||
{
|
||||
if (mode is null)
|
||||
return false;
|
||||
if (mode == 1 | mode == 3)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
static bool isSubsytemAkbRotor(short? mode) => mode == 1;
|
||||
|
||||
static bool IsSubsystemMse(short? state)
|
||||
{
|
||||
if (state is null)
|
||||
return false;
|
||||
if ((state & 1) > 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
static bool isSubsytemAkbSlide(short? mode) => mode == 3;
|
||||
|
||||
static bool IsSubsystemMse(short? state) => (state & 1) > 0;
|
||||
|
||||
var query =
|
||||
$"select tt.date, tt.mode, tt.well_depth, tt.mse_state " +
|
||||
@ -138,62 +126,31 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
using var result = await ExecuteReaderAsync(db, query, token);
|
||||
|
||||
var subsystemsOperationTimes = new List<SubsystemOperationTime>();
|
||||
|
||||
(bool isEnable, DateTimeOffset date, float depth) akbPre = default;
|
||||
(bool isEnable, DateTimeOffset date, float depth) msePre = default;
|
||||
var detectorRotor = new SubsystemDetector(idTelemetry, idSubsystemAPDRotor, isSubsytemAkbRotor, IsValid);
|
||||
var detectorSlide = new SubsystemDetector(idTelemetry, idSubsystemAPDSlide, isSubsytemAkbSlide, IsValid);
|
||||
var detectorMse = new SubsystemDetector(idTelemetry, idSubsytemMse, IsSubsystemMse, IsValid);
|
||||
|
||||
while (result.Read())
|
||||
{
|
||||
var mode = result.GetFieldValue<short?>(1);
|
||||
var state = result.GetFieldValue<short?>(3);
|
||||
|
||||
var isAkbEnable = isSubsytemAkb(mode);
|
||||
var isAkbRotorEnable = isSubsytemAkbRotor(mode);
|
||||
var isAkbSlideEnable = isSubsytemAkbSlide(mode);
|
||||
var isMseEnable = IsSubsystemMse(state);
|
||||
var date = result.GetFieldValue<DateTimeOffset>(0);
|
||||
var depth = result.GetFieldValue<float>(2);
|
||||
var depth = result.GetFieldValue<float>(2);
|
||||
|
||||
if (!akbPre.isEnable && isAkbEnable)
|
||||
{
|
||||
akbPre = (true, date, depth);
|
||||
}
|
||||
else if (akbPre.isEnable && !isAkbEnable)
|
||||
{
|
||||
var subsystemOperationTime = new SubsystemOperationTime
|
||||
{
|
||||
IdTelemetry = idTelemetry,
|
||||
IdSubsystem = idSubsytemAkb,
|
||||
DateStart = akbPre.date,
|
||||
DateEnd = date,
|
||||
DepthStart = akbPre.depth,
|
||||
DepthEnd = depth,
|
||||
};
|
||||
if (IsValid(subsystemOperationTime))
|
||||
subsystemsOperationTimes.Add(subsystemOperationTime);
|
||||
akbPre.isEnable = false;
|
||||
}
|
||||
if (detectorRotor.TryDetect(mode, date, depth, out var detectedRotor))
|
||||
subsystemsOperationTimes.Add(detectedRotor!);
|
||||
|
||||
if (!msePre.isEnable && isMseEnable)
|
||||
{
|
||||
msePre = (true, date, depth);
|
||||
}
|
||||
else if (msePre.isEnable && !isMseEnable)
|
||||
{
|
||||
var subsystemOperationTime = new SubsystemOperationTime
|
||||
{
|
||||
IdTelemetry = idTelemetry,
|
||||
IdSubsystem = idSubsytemMse,
|
||||
DateStart = akbPre.date,
|
||||
DateEnd = date,
|
||||
DepthStart = akbPre.depth,
|
||||
DepthEnd = depth,
|
||||
};
|
||||
if (IsValid(subsystemOperationTime))
|
||||
subsystemsOperationTimes.Add(subsystemOperationTime);
|
||||
|
||||
msePre.isEnable = false;
|
||||
}
|
||||
if (detectorSlide.TryDetect(mode, date, depth, out var detectedSlide))
|
||||
subsystemsOperationTimes.Add(detectedSlide!);
|
||||
|
||||
if (detectorMse.TryDetect(mode, date, depth, out var detectedMse))
|
||||
subsystemsOperationTimes.Add(detectedMse!);
|
||||
}
|
||||
|
||||
|
||||
return subsystemsOperationTimes;
|
||||
}
|
||||
|
||||
@ -215,7 +172,7 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
$"select " +
|
||||
$" tspin.date, " +
|
||||
$" tspin.mode, " +
|
||||
$" tspin.state " +
|
||||
$" tspin.state " +
|
||||
$"from ( " +
|
||||
$" select " +
|
||||
$" date, " +
|
||||
@ -226,28 +183,27 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
$" lag(state, 1) over (order by date) as state_lag " +
|
||||
$" from t_telemetry_data_spin " +
|
||||
$" where id_telemetry = {idTelemetry} and date >= '{begin:u}'" +
|
||||
$" order by date ) as tspin " +
|
||||
$" order by date ) as tspin " +
|
||||
$"where mode_lag is null or state_lag is null or (mode != mode_lag and mode_lead != mode_lag) or state != state_lag " +
|
||||
$"order by date;";
|
||||
|
||||
var rows = new List<(int? IdSubsystem, DateTimeOffset Date)>(32);
|
||||
|
||||
using var resultSpin = await ExecuteReaderAsync(db, querySpin, token);
|
||||
int? idSubsystemLast = null;
|
||||
while (resultSpin.Read())
|
||||
{
|
||||
using var resultSpin = await ExecuteReaderAsync(db, querySpin, token);
|
||||
int? idSubsystemLast = null;
|
||||
while (resultSpin.Read())
|
||||
var mode = resultSpin.GetFieldValue<short?>(1);
|
||||
var state = resultSpin.GetFieldValue<short?>(2);
|
||||
var idSubsystem = GetSubsytemId(mode, state);
|
||||
if (idSubsystemLast != idSubsystem)
|
||||
{
|
||||
var mode = resultSpin.GetFieldValue<short?>(1);
|
||||
var state = resultSpin.GetFieldValue<short?>(2);
|
||||
var idSubsystem = GetSubsytemId(mode, state);
|
||||
if(idSubsystemLast != idSubsystem)
|
||||
{
|
||||
idSubsystemLast = idSubsystem;
|
||||
var date = resultSpin.GetFieldValue<DateTimeOffset>(0);
|
||||
rows.Add((idSubsystem, date));
|
||||
}
|
||||
idSubsystemLast = idSubsystem;
|
||||
var date = resultSpin.GetFieldValue<DateTimeOffset>(0);
|
||||
rows.Add((idSubsystem, date));
|
||||
}
|
||||
await resultSpin.DisposeAsync();
|
||||
}
|
||||
await resultSpin.DisposeAsync();
|
||||
|
||||
if (rows.Count < 2)
|
||||
return Enumerable.Empty<SubsystemOperationTime>();
|
||||
@ -260,7 +216,7 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
return Enumerable.Empty<SubsystemOperationTime>();
|
||||
|
||||
var subsystemsOperationTimes = new List<SubsystemOperationTime>(32);
|
||||
|
||||
|
||||
for (int i = 1; i < rows.Count; i++)
|
||||
{
|
||||
var r0 = rows[i - 1];
|
||||
@ -276,12 +232,12 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
DepthStart = depthInterpolation.GetDepth(r0.Date),
|
||||
DepthEnd = depthInterpolation.GetDepth(r1.Date),
|
||||
};
|
||||
|
||||
|
||||
if (IsValid(subsystemOperationTime))
|
||||
subsystemsOperationTimes.Add(subsystemOperationTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return subsystemsOperationTimes;
|
||||
}
|
||||
|
||||
@ -336,7 +292,7 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
if (!dataDepthFromSaub.Any())
|
||||
return null;
|
||||
|
||||
var depthInterpolation = new DepthInterpolation(dataDepthFromSaub.Select(i=>(i.DateMin, i.DepthMin)));
|
||||
var depthInterpolation = new DepthInterpolation(dataDepthFromSaub.Select(i => (i.DateMin, i.DepthMin)));
|
||||
return depthInterpolation;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.DetectedOperation;
|
||||
using AsbCloudApp.Data.Subsystems;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudApp.Services.Subsystems;
|
||||
@ -17,15 +18,15 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
{
|
||||
|
||||
internal class SubsystemOperationTimeService : ISubsystemOperationTimeService
|
||||
{
|
||||
|
||||
private readonly IAsbCloudDbContext db;
|
||||
private readonly IWellService wellService;
|
||||
private readonly ICrudRepository<SubsystemDto> subsystemService;
|
||||
private readonly IDetectedOperationService detectedOperationService;
|
||||
public const int IdSubsystemAKB = 1;
|
||||
public const int IdSubsystemAKBRotor = 11;
|
||||
public const int IdSubsystemAKBSlide = 12;
|
||||
public const int IdSubsystemMSE = 2;
|
||||
public const int IdSubsystemSpin = 65536;
|
||||
public const int IdSubsystemTorque = 65537;
|
||||
@ -143,33 +144,54 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
return items;
|
||||
}
|
||||
|
||||
private IEnumerable<SubsystemStatDto> CalcStat(IEnumerable<SubsystemOperationTimeDto> dtos, (double depthIntervalRotor, double depthIntervalSlide) depthInterval)
|
||||
private IEnumerable<SubsystemStatDto> CalcStat(
|
||||
IEnumerable<SubsystemOperationTimeDto> dtos,
|
||||
(double depthIntervalRotor, double depthIntervalSlide) depthInterval)
|
||||
{
|
||||
var groupedDataSubsystems = dtos
|
||||
.OrderBy(o => o.Id)
|
||||
.GroupBy(o => o.IdSubsystem);
|
||||
var periodGroupTotal = dtos.Sum(o => (o.DateEnd - o.DateStart).TotalHours);
|
||||
|
||||
|
||||
var result = groupedDataSubsystems.Select(g =>
|
||||
{
|
||||
var depthIntervalSubsystem = GetDepthIntervalSubsystem(g.Key, depthInterval);
|
||||
var periodGroup = g.Sum(o => (o.DateEnd - o.DateStart).TotalHours);
|
||||
var periodGroupDepth = g.Sum(o => o.DepthEnd - o.DepthStart);
|
||||
var periodGroupDepth = g.Sum(o => o.DepthEnd - o.DepthStart);
|
||||
var subsystemStat = new SubsystemStatDto()
|
||||
{
|
||||
IdSubsystem = g.Key,
|
||||
SubsystemName = subsystemService.GetOrDefault(g.Key)?.Name ?? "unknown",
|
||||
UsedTimeHours = periodGroup,
|
||||
UsedTimeHours = periodGroup,
|
||||
//% использования = суммарная проходка АПД в слайде
|
||||
/// суммарную проходку автоопределенных операций в слайде.
|
||||
KUsage = periodGroupDepth / depthIntervalSubsystem,
|
||||
SumDepthInterval = periodGroupDepth,
|
||||
OperationCount = g.Count()
|
||||
OperationCount = g.Count(),
|
||||
};
|
||||
if(subsystemStat.KUsage > 1)
|
||||
if (subsystemStat.KUsage > 1)
|
||||
subsystemStat.KUsage = 1;
|
||||
return subsystemStat;
|
||||
});
|
||||
|
||||
var apdParts = result.Where(x => x.IdSubsystem == 11 || x.IdSubsystem == 12);
|
||||
if (apdParts.Any())
|
||||
{
|
||||
var apdSum = new SubsystemStatDto()
|
||||
{
|
||||
IdSubsystem = IdSubsystemAKB,
|
||||
SubsystemName = "АПД",
|
||||
UsedTimeHours = apdParts.Sum(part => part.UsedTimeHours),
|
||||
KUsage = apdParts.Sum(part => part.SumDepthInterval) / GetDepthIntervalSubsystem(IdSubsystemAKB, depthInterval),
|
||||
SumDepthInterval = apdParts.Sum(part => part.SumDepthInterval),
|
||||
OperationCount = apdParts.Sum(part => part.OperationCount),
|
||||
};
|
||||
result = result.Append(apdSum).OrderBy(m => m.IdSubsystem);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static (double depthIntervalRotor, double depthIntervalSlide) GetDepthInterval (IEnumerable<DetectedOperationDto> detectedOperations)
|
||||
{
|
||||
var depthIntervalRotor = detectedOperations.Where(o => o.IdCategory == WellOperationCategory.IdRotor)
|
||||
@ -180,6 +202,7 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
|
||||
return depthInterval;
|
||||
}
|
||||
|
||||
private static double GetDepthIntervalSubsystem(int idSubsystem, (double depthIntervalRotor, double depthIntervalSlide) depthInterval)
|
||||
{
|
||||
var depthIntervalSubsystem = 0d;
|
||||
@ -188,6 +211,16 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
{
|
||||
depthIntervalSubsystem = depthInterval.depthIntervalRotor + depthInterval.depthIntervalSlide;
|
||||
}
|
||||
//AKB - Rotor
|
||||
if (idSubsystem == IdSubsystemAKBRotor)
|
||||
{
|
||||
depthIntervalSubsystem = depthInterval.depthIntervalRotor;
|
||||
}
|
||||
//AKB - Slide
|
||||
if (idSubsystem == IdSubsystemAKBSlide)
|
||||
{
|
||||
depthIntervalSubsystem = depthInterval.depthIntervalSlide;
|
||||
}
|
||||
//Spin
|
||||
if (idSubsystem == IdSubsystemSpin)
|
||||
{
|
||||
@ -230,11 +263,15 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
|
||||
var beginUTC = gtDate.HasValue
|
||||
? gtDate.Value.ToUtcDateTimeOffset(hoursOffset)
|
||||
: DateTime.Today.AddDays(-1).ToUtcDateTimeOffset(hoursOffset);
|
||||
: db.SubsystemOperationTimes.Min(s => s.DateStart)
|
||||
.DateTime
|
||||
.ToUtcDateTimeOffset(hoursOffset);
|
||||
|
||||
var endUTC = ltDate.HasValue
|
||||
? ltDate.Value.ToUtcDateTimeOffset(hoursOffset)
|
||||
: DateTime.Today.ToUtcDateTimeOffset(hoursOffset);
|
||||
: db.SubsystemOperationTimes.Max(s => s.DateEnd)
|
||||
.DateTime
|
||||
.ToUtcDateTimeOffset(hoursOffset);
|
||||
|
||||
var telemetryIds = wells
|
||||
.Where(w => w.IdTelemetry is not null)
|
||||
@ -297,11 +334,11 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
return result;
|
||||
}
|
||||
|
||||
private IQueryable<SubsystemOperationTime>? BuildQuery(SubsystemOperationTimeRequest request)
|
||||
private IQueryable<SubsystemOperationTime> BuildQuery(SubsystemOperationTimeRequest request)
|
||||
{
|
||||
var well = wellService.GetOrDefault(request.IdWell);
|
||||
if (well?.IdTelemetry is null || well.Timezone is null)
|
||||
return null;
|
||||
throw new ArgumentInvalidException($"Not valid IdWell = {request.IdWell}", nameof(request.IdWell));
|
||||
|
||||
var query = db.SubsystemOperationTimes
|
||||
.Include(o => o.Subsystem)
|
||||
@ -348,8 +385,6 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
|
||||
if (request?.Take > 0)
|
||||
query = query.Take((int)request.Take);
|
||||
else
|
||||
query = query.Take(3000);
|
||||
|
||||
return query;
|
||||
}
|
||||
@ -361,9 +396,6 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
dto.DateStart = operationTime.DateStart.ToRemoteDateTime(hours);
|
||||
dto.DateEnd = operationTime.DateEnd.ToRemoteDateTime(hours);
|
||||
return dto;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,56 @@
|
||||
using AsbCloudDb.Model.Subsystems;
|
||||
using System;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
{
|
||||
public class SubsystemDetector
|
||||
{
|
||||
private readonly int idTelemetry;
|
||||
private readonly int idSubsystem;
|
||||
private readonly Func<short?, bool> isEnable;
|
||||
private readonly Func<SubsystemOperationTime, bool> isValid;
|
||||
(bool isEnable, DateTimeOffset date, float depth) pre = default;
|
||||
|
||||
public SubsystemDetector(
|
||||
int idTelemetry,
|
||||
int idSubsystem,
|
||||
Func<short?, bool> isEnable,
|
||||
Func<SubsystemOperationTime, bool> isValid)
|
||||
{
|
||||
this.idTelemetry = idTelemetry;
|
||||
this.idSubsystem = idSubsystem;
|
||||
this.isEnable = isEnable;
|
||||
this.isValid = isValid;
|
||||
}
|
||||
|
||||
public bool TryDetect(short? mode, DateTimeOffset date, float depth, out SubsystemOperationTime? subsystemOperationTime)
|
||||
{
|
||||
var isEnable = this.isEnable(mode);
|
||||
|
||||
if (!pre.isEnable && isEnable)
|
||||
{
|
||||
pre = (true, date, depth);
|
||||
}
|
||||
else if (pre.isEnable && !isEnable)
|
||||
{
|
||||
var detected = new SubsystemOperationTime
|
||||
{
|
||||
IdTelemetry = idTelemetry,
|
||||
IdSubsystem = idSubsystem,
|
||||
DateStart = pre.date,
|
||||
DateEnd = date,
|
||||
DepthStart = pre.depth,
|
||||
DepthEnd = depth,
|
||||
};
|
||||
pre.isEnable = false;
|
||||
if (isValid(detected))
|
||||
{
|
||||
subsystemOperationTime = detected;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
subsystemOperationTime = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -30,16 +30,8 @@ namespace AsbCloudInfrastructure.Services.Trajectory
|
||||
private const int ColumnAzimuthGeo = 3;
|
||||
private const int ColumnAzimuthMagnetic = 4;
|
||||
private const int ColumnVerticalDepth = 5;
|
||||
private const int ColumnAbsoluteMark = 6;
|
||||
private const int ColumnNorthOrifice = 7;
|
||||
private const int ColumnEastOrifice = 8;
|
||||
private const int ColumnEastCartographic = 9;
|
||||
private const int ColumnNorthCartographic = 10;
|
||||
private const int ColumnSpatialIntensity = 11;
|
||||
private const int ColumnAngleIntensity = 12;
|
||||
private const int ColumnAzimuthIntensity = 13;
|
||||
private const int ColumnOrificeOffset = 14;
|
||||
private const int ColumnComment = 15;
|
||||
private const int ColumnRadius = 6;
|
||||
private const int ColumnComment = 7;
|
||||
|
||||
public PlannedTrajectoryImportService(IWellService wellService, ITrajectoryPlanRepository plannedTrajectoryService)
|
||||
{
|
||||
@ -107,15 +99,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory
|
||||
row.Cell(ColumnAzimuthGeo).Value = trajectory.AzimuthGeo;
|
||||
row.Cell(ColumnAzimuthMagnetic).Value = trajectory.AzimuthMagnetic;
|
||||
row.Cell(ColumnVerticalDepth).Value = trajectory.VerticalDepth;
|
||||
row.Cell(ColumnAbsoluteMark).Value = trajectory.AbsoluteMark;
|
||||
row.Cell(ColumnNorthOrifice).Value = trajectory.NorthOrifice;
|
||||
row.Cell(ColumnEastOrifice).Value = trajectory.EastOrifice;
|
||||
row.Cell(ColumnEastCartographic).Value = trajectory.EastCartographic;
|
||||
row.Cell(ColumnNorthCartographic).Value = trajectory.NorthCartographic;
|
||||
row.Cell(ColumnSpatialIntensity).Value = trajectory.SpatialIntensity;
|
||||
row.Cell(ColumnAngleIntensity).Value = trajectory.AngleIntensity;
|
||||
row.Cell(ColumnAzimuthIntensity).Value = trajectory.AzimuthIntensity;
|
||||
row.Cell(ColumnOrificeOffset).Value = trajectory.OrificeOffset;
|
||||
row.Cell(ColumnRadius).Value = trajectory.Radius;
|
||||
row.Cell(ColumnComment).Value = trajectory.Comment;
|
||||
}
|
||||
|
||||
@ -158,7 +142,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory
|
||||
|
||||
private IEnumerable<TrajectoryGeoPlanDto> ParseSheet(IXLWorksheet sheet)
|
||||
{
|
||||
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 15)
|
||||
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 7)
|
||||
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
|
||||
|
||||
var count = sheet.RowsUsed().Count() - headerRowsCount;
|
||||
@ -183,7 +167,11 @@ namespace AsbCloudInfrastructure.Services.Trajectory
|
||||
{
|
||||
parseErrors.Add(ex.Message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (parseErrors.Any())
|
||||
throw new FileFormatException(string.Join("\r\n", parseErrors));
|
||||
|
||||
return trajectoryRows;
|
||||
}
|
||||
|
||||
@ -194,15 +182,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory
|
||||
var _azimuthGeo = row.Cell(ColumnAzimuthGeo).Value;
|
||||
var _azimuthMagnetic = row.Cell(ColumnAzimuthMagnetic).Value;
|
||||
var _verticalDepth = row.Cell(ColumnVerticalDepth).Value;
|
||||
var _absoluteMark = row.Cell(ColumnAbsoluteMark).Value;
|
||||
var _northOrifice = row.Cell(ColumnNorthOrifice).Value;
|
||||
var _eastOrifice = row.Cell(ColumnEastOrifice).Value;
|
||||
var _eastCartographic = row.Cell(ColumnEastCartographic).Value;
|
||||
var _northCartographic = row.Cell(ColumnNorthCartographic).Value;
|
||||
var _spatialIntensity = row.Cell(ColumnSpatialIntensity).Value;
|
||||
var _angleIntensity = row.Cell(ColumnAngleIntensity).Value;
|
||||
var _azimuthIntensity = row.Cell(ColumnAzimuthIntensity).Value;
|
||||
var _orificeOffset = row.Cell(ColumnOrificeOffset).Value;
|
||||
var _radius = row.Cell(ColumnRadius).Value;
|
||||
var _comment = row.Cell(ColumnComment).Value;
|
||||
|
||||
var trajectoryRow = new TrajectoryGeoPlanDto();
|
||||
@ -219,15 +199,8 @@ namespace AsbCloudInfrastructure.Services.Trajectory
|
||||
trajectoryRow.AzimuthGeo = getDoubleValue(_azimuthGeo, "Азимут географический", row);
|
||||
trajectoryRow.AzimuthMagnetic = getDoubleValue(_azimuthMagnetic, "Азимут магнитный", row);
|
||||
trajectoryRow.VerticalDepth = getDoubleValue(_verticalDepth, "Глубина вертикальная", row);
|
||||
trajectoryRow.AbsoluteMark = getDoubleValue(_absoluteMark, "Абсолютная отметка", row);
|
||||
trajectoryRow.NorthOrifice = getDoubleValue(_northOrifice, "Север относительно устья", row);
|
||||
trajectoryRow.EastOrifice = getDoubleValue(_eastOrifice, "Восток относительно устья", row);
|
||||
trajectoryRow.EastCartographic = getDoubleValue(_eastCartographic, "Восток картографический", row);
|
||||
trajectoryRow.NorthCartographic = getDoubleValue(_northCartographic, "Север картографический", row);
|
||||
trajectoryRow.SpatialIntensity = getDoubleValue(_spatialIntensity, "Простр. интенсивность", row);
|
||||
trajectoryRow.AngleIntensity = getDoubleValue(_angleIntensity, "Интенсивность по углу", row);
|
||||
trajectoryRow.AzimuthIntensity = getDoubleValue(_azimuthIntensity, "Интенсивность по азимуту", row);
|
||||
trajectoryRow.OrificeOffset = getDoubleValue(_orificeOffset, "Смещение от устья", row);
|
||||
trajectoryRow.Radius = getDoubleValue(_radius, "Радиус цели", row);
|
||||
|
||||
if (_comment is not null)
|
||||
trajectoryRow.Comment = _comment.ToString();
|
||||
return trajectoryRow;
|
||||
|
Binary file not shown.
@ -10,6 +10,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Services.Notifications;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
@ -23,9 +24,9 @@ namespace AsbCloudInfrastructure.Services
|
||||
private readonly IUserRepository userRepository;
|
||||
private readonly IWellService wellService;
|
||||
private readonly IConfiguration configuration;
|
||||
private readonly IEmailService emailService;
|
||||
private readonly IFileCategoryService fileCategoryService;
|
||||
private readonly IWellFinalDocumentsRepository wellFinalDocumentsRepository;
|
||||
private readonly NotificationService notificationService;
|
||||
|
||||
private const int FileServiceThrewException = -1;
|
||||
|
||||
@ -33,17 +34,17 @@ namespace AsbCloudInfrastructure.Services
|
||||
IUserRepository userRepository,
|
||||
IWellService wellService,
|
||||
IConfiguration configuration,
|
||||
IEmailService emailService,
|
||||
IFileCategoryService fileCategoryService,
|
||||
IWellFinalDocumentsRepository wellFinalDocumentsRepository)
|
||||
IWellFinalDocumentsRepository wellFinalDocumentsRepository,
|
||||
NotificationService notificationService)
|
||||
{
|
||||
this.fileService = fileService;
|
||||
this.userRepository = userRepository;
|
||||
this.wellService = wellService;
|
||||
this.configuration = configuration;
|
||||
this.emailService = emailService;
|
||||
this.fileCategoryService = fileCategoryService;
|
||||
this.wellFinalDocumentsRepository = wellFinalDocumentsRepository;
|
||||
this.notificationService = notificationService;
|
||||
}
|
||||
|
||||
///<inheritdoc/>
|
||||
@ -129,27 +130,35 @@ namespace AsbCloudInfrastructure.Services
|
||||
if(well is null)
|
||||
throw new ArgumentInvalidException("idWell doesn`t exist", nameof(item.IdWell));
|
||||
|
||||
SendMessage(well, user, category?.Name ?? string.Empty, message);
|
||||
await SendMessageAsync(well, user, category?.Name ?? string.Empty, message,
|
||||
token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SendMessage(WellDto well, UserDto user, string documentCategory, string message)
|
||||
private async Task SendMessageAsync(WellDto well, UserDto user, string documentCategory, string message,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
const int idNotificationCategory = 20000;
|
||||
const int idTransportType = 1;
|
||||
|
||||
var factory = new WellFinalDocumentMailBodyFactory(configuration);
|
||||
var subject = factory.MakeSubject(well, documentCategory);
|
||||
|
||||
if(!string.IsNullOrEmpty(user.Email))
|
||||
{
|
||||
var body = factory.MakeMailBodyForWellFinalDocument(
|
||||
well,
|
||||
(user.Name ?? user.Surname ?? string.Empty),
|
||||
string.Format(message, documentCategory)
|
||||
);
|
||||
var body = factory.MakeMailBodyForWellFinalDocument(
|
||||
well,
|
||||
(user.Name ?? user.Surname ?? string.Empty),
|
||||
string.Format(message, documentCategory)
|
||||
);
|
||||
|
||||
emailService.EnqueueSend(user.Email, subject, body);
|
||||
}
|
||||
|
||||
await notificationService.NotifyAsync(new NotifyRequest
|
||||
{
|
||||
IdUser = user.Id,
|
||||
IdNotificationCategory = idNotificationCategory,
|
||||
Title = subject,
|
||||
Message = body,
|
||||
IdTransportType = idTransportType
|
||||
}, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudApp.Services.Subsystems;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Background;
|
||||
using AsbCloudInfrastructure.Services.SAUB;
|
||||
using Mapster;
|
||||
@ -16,6 +15,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.IntegrationEvents;
|
||||
using AsbCloudApp.IntegrationEvents.Interfaces;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
@ -36,7 +37,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
private readonly IWitsRecordRepository<Record1Dto> witsRecord1Repository;
|
||||
private readonly IGtrRepository gtrRepository;
|
||||
private static IEnumerable<WellMapInfoWithComanies> WellMapInfo = Enumerable.Empty<WellMapInfoWithComanies>();
|
||||
|
||||
|
||||
public WellInfoService(
|
||||
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache,
|
||||
TelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache,
|
||||
@ -63,23 +64,18 @@ namespace AsbCloudInfrastructure.Services
|
||||
|
||||
private static async Task WorkAction(string workName, IServiceProvider serviceProvider, CancellationToken token)
|
||||
{
|
||||
var db = serviceProvider.GetRequiredService<IAsbCloudDbContext>();
|
||||
var wellService = serviceProvider.GetRequiredService<IWellService>();
|
||||
var operationsStatService = serviceProvider.GetRequiredService<IOperationsStatService>();
|
||||
var processMapRepository = serviceProvider.GetRequiredService<IProcessMapPlanRepository>();
|
||||
var subsystemOperationTimeService = serviceProvider.GetRequiredService<ISubsystemOperationTimeService>();
|
||||
var telemetryDataSaubCache = serviceProvider.GetRequiredService<TelemetryDataCache<TelemetryDataSaubDto>>();
|
||||
var messageHub = serviceProvider.GetRequiredService<IIntegrationEventHandler<UpdateWellInfoEvent>>();
|
||||
|
||||
var activeWells = await wellService.GetAsync(new() {IdState = 1}, token);
|
||||
var wells = await wellService.GetAllAsync(token);
|
||||
|
||||
IEnumerable<int> activeWellsIds = activeWells
|
||||
.Select(w => w.Id);
|
||||
var wellsIds = wells.Select(w => w.Id);
|
||||
|
||||
var idTelemetries = activeWells
|
||||
.Where(w => w.IdTelemetry != null)
|
||||
.Select(t => t.IdTelemetry);
|
||||
|
||||
var processMapRequests = activeWellsIds.Select(id => new ProcessMapRequest { IdWell = id });
|
||||
var processMapRequests = wellsIds.Select(id => new ProcessMapRequest { IdWell = id });
|
||||
var processMaps = await processMapRepository.GetProcessMapAsync(processMapRequests, token);
|
||||
|
||||
var wellDepthByProcessMap = processMaps
|
||||
@ -90,20 +86,23 @@ namespace AsbCloudInfrastructure.Services
|
||||
DepthEnd = g.Max(p => p.DepthEnd)
|
||||
});
|
||||
|
||||
var operationsStat = await operationsStatService.GetWellsStatAsync(activeWellsIds, token);
|
||||
var operationsStat = await operationsStatService.GetWellsStatAsync(wellsIds, token);
|
||||
|
||||
var subsystemStat = await subsystemOperationTimeService.GetStatByActiveWells(activeWellsIds, token);
|
||||
var subsystemStat = await subsystemOperationTimeService
|
||||
.GetStatByActiveWells(wellsIds, token);
|
||||
|
||||
WellMapInfo = activeWells.Select(well => {
|
||||
WellMapInfo = wells.Select(well => {
|
||||
var wellMapInfo = well.Adapt<WellMapInfoWithComanies>();
|
||||
wellMapInfo.IdState = well.IdState;
|
||||
|
||||
double? currentDepth = null;
|
||||
|
||||
TelemetryDataSaubDto? lastSaubTelemetry = null;
|
||||
|
||||
if (well.IdTelemetry.HasValue)
|
||||
{
|
||||
wellMapInfo.IdTelemetry = well.IdTelemetry.Value;
|
||||
var lastSaubTelemetry = telemetryDataSaubCache.GetLastOrDefault(well.IdTelemetry.Value);
|
||||
lastSaubTelemetry = telemetryDataSaubCache.GetLastOrDefault(well.IdTelemetry.Value);
|
||||
if(lastSaubTelemetry is not null)
|
||||
{
|
||||
currentDepth = lastSaubTelemetry.WellDepth;
|
||||
@ -119,27 +118,54 @@ namespace AsbCloudInfrastructure.Services
|
||||
.OrderBy(p => p.DepthEnd);
|
||||
|
||||
int? idSection = wellLastFactSection?.Id;
|
||||
ProcessMapPlanDto? welllProcessMap = null;
|
||||
ProcessMapPlanDto? wellProcessMap = null;
|
||||
|
||||
if (idSection.HasValue)
|
||||
{
|
||||
welllProcessMap = wellProcessMaps.FirstOrDefault(p => p.IdWellSectionType == idSection);
|
||||
wellProcessMap = wellProcessMaps.FirstOrDefault(p => p.IdWellSectionType == idSection);
|
||||
}
|
||||
else if(currentDepth.HasValue)
|
||||
{
|
||||
welllProcessMap = wellProcessMaps.FirstOrDefault(p => p.DepthStart <= currentDepth.Value && p.DepthEnd >= currentDepth.Value);
|
||||
idSection ??= welllProcessMap?.IdWellSectionType;
|
||||
wellProcessMap = wellProcessMaps.FirstOrDefault(p => p.DepthStart <= currentDepth.Value && p.DepthEnd >= currentDepth.Value);
|
||||
}
|
||||
|
||||
double? planTotalDepth = null;
|
||||
planTotalDepth = wellDepthByProcessMap.FirstOrDefault(p => p.Id == well.Id)?.DepthEnd;
|
||||
planTotalDepth ??= wellOperationsStat?.Total.Plan?.WellDepthEnd;
|
||||
|
||||
wellMapInfo.Section = wellLastFactSection?.Caption;
|
||||
|
||||
wellMapInfo.FirstFactOperationDateStart = wellOperationsStat?.Total.Fact?.Start
|
||||
?? wellOperationsStat?.Total.Plan?.Start;
|
||||
|
||||
wellMapInfo.LastPredictOperationDateEnd = wellOperationsStat?.Total.Plan?.End;
|
||||
|
||||
wellMapInfo.AxialLoad = new()
|
||||
{
|
||||
Plan = wellProcessMap?.AxialLoad.Plan,
|
||||
Fact = lastSaubTelemetry?.AxialLoad
|
||||
};
|
||||
|
||||
wellMapInfo.TopDriveSpeed = new()
|
||||
{
|
||||
Plan = wellProcessMap?.TopDriveSpeed.Plan,
|
||||
Fact = lastSaubTelemetry?.RotorSpeed
|
||||
};
|
||||
|
||||
wellMapInfo.TopDriveTorque = new()
|
||||
{
|
||||
Plan = wellProcessMap?.TopDriveTorque.Plan,
|
||||
Fact = lastSaubTelemetry?.RotorTorque
|
||||
};
|
||||
|
||||
wellMapInfo.Pressure = new()
|
||||
{
|
||||
Plan = wellProcessMap?.Pressure.Plan,
|
||||
Fact = lastSaubTelemetry?.Pressure
|
||||
};
|
||||
|
||||
wellMapInfo.PressureSp = lastSaubTelemetry?.PressureSp;
|
||||
|
||||
wellMapInfo.WellDepth = new()
|
||||
{
|
||||
Plan = planTotalDepth,
|
||||
@ -148,7 +174,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
|
||||
wellMapInfo.ROP = new()
|
||||
{
|
||||
Plan = welllProcessMap?.RopPlan,
|
||||
Plan = wellProcessMap?.RopPlan,
|
||||
Fact = wellOperationsStat?.Total.Fact?.Rop,
|
||||
};
|
||||
|
||||
@ -162,11 +188,17 @@ namespace AsbCloudInfrastructure.Services
|
||||
wellMapInfo.SaubUsage = wellSubsystemStat?.SubsystemAKB?.KUsage ?? 0d;
|
||||
wellMapInfo.SpinUsage = wellSubsystemStat?.SubsystemSpinMaster?.KUsage ?? 0d;
|
||||
wellMapInfo.TorqueKUsage = wellSubsystemStat?.SubsystemTorqueMaster?.KUsage ?? 0d;
|
||||
wellMapInfo.TvdLagPercent = wellOperationsStat?.TvdLagPercent ?? 0d;
|
||||
wellMapInfo.TvdLagDays = wellOperationsStat?.TvdLagDays;
|
||||
wellMapInfo.TvdDrillingDays = wellOperationsStat?.TvdDrillingDays;
|
||||
wellMapInfo.IdsCompanies = well.Companies.Select(c => c.Id);
|
||||
|
||||
return wellMapInfo;
|
||||
}).ToArray();
|
||||
|
||||
var updateWellInfoEventTasks = wellsIds.Select(idWell =>
|
||||
messageHub.HandleAsync(new UpdateWellInfoEvent(idWell), token));
|
||||
|
||||
await Task.WhenAll(updateWellInfoEventTasks);
|
||||
}
|
||||
|
||||
private WellMapInfoWithTelemetryStat Convert(WellMapInfoWithComanies wellInfo)
|
||||
|
@ -172,81 +172,57 @@ public class OperationsStatService : IOperationsStatService
|
||||
var timezoneOffsetH = wellService.GetTimezone(well.Id).Hours;
|
||||
statWellDto.Sections = CalcSectionsStats(wellOperations, timezoneOffsetH);
|
||||
statWellDto.Total = GetStatTotal(wellOperations, well.IdState, timezoneOffsetH);
|
||||
statWellDto.TvdLagPercent = CalcTvdLagPercent(well.IdTelemetry, wellOperations);
|
||||
statWellDto.TvdLagDays = CalcTvdLagDays(wellOperations);
|
||||
statWellDto.TvdDrillingDays = CalcDrillingDays(wellOperations);
|
||||
|
||||
return statWellDto;
|
||||
}
|
||||
|
||||
private double? CalcTvdLagPercent(int? idTelemetry, IOrderedEnumerable<WellOperation> wellOperations)
|
||||
private static double? CalcDrillingDays(IEnumerable<WellOperation> wellOperations)
|
||||
{
|
||||
var currentDate = DateTimeOffset.UtcNow;
|
||||
var operationsOrdered = wellOperations
|
||||
.OrderBy(o => o.DateStart);
|
||||
|
||||
var wellDepth = wellOperations
|
||||
.LastOrDefault(o => o.IdType == WellOperation.IdOperationTypeFact)?.DepthEnd;
|
||||
var factOperations = operationsOrdered
|
||||
.Where(o => o.IdType == WellOperation.IdOperationTypeFact);
|
||||
|
||||
if (!factOperations.Any())
|
||||
return null;
|
||||
|
||||
if (idTelemetry.HasValue)
|
||||
wellDepth = telemetryDataCache.GetLastOrDefault(idTelemetry.Value)?.WellDepth;
|
||||
var operationFrom = factOperations.First();
|
||||
|
||||
if (wellDepth is null)
|
||||
return null;
|
||||
var operationTo = factOperations.Last();
|
||||
|
||||
var planOperations = wellOperations
|
||||
.Where(o => o.IdType == WellOperation.IdOperationTypePlan)
|
||||
.OrderBy(o => o.DateStart.AddHours(o.DurationHours));
|
||||
|
||||
if (!planOperations.Any())
|
||||
return null;
|
||||
|
||||
var planDepth = CalcPlanDepth(planOperations, currentDate);
|
||||
|
||||
if (planDepth is null)
|
||||
return null;
|
||||
|
||||
if (planDepth == 0d)
|
||||
return 0d;
|
||||
|
||||
return (1 - wellDepth / planDepth) * 100;
|
||||
return (operationTo.DateStart.AddHours(operationTo.DurationHours) - operationFrom.DateStart).TotalDays;
|
||||
}
|
||||
|
||||
private static double? CalcPlanDepth(IOrderedEnumerable<WellOperation> planOperations, DateTimeOffset currentDate)
|
||||
private static double? CalcTvdLagDays(IEnumerable<WellOperation> wellOperations)
|
||||
{
|
||||
var operationIn = planOperations
|
||||
.FirstOrDefault(o => o.DateStart <= currentDate && o.DateStart.AddHours(o.DurationHours) >= currentDate);
|
||||
|
||||
if (operationIn is not null)
|
||||
return Interpolate(
|
||||
operationIn.DepthStart,
|
||||
operationIn.DepthEnd,
|
||||
operationIn.DateStart,
|
||||
operationIn.DateStart.AddHours(operationIn.DurationHours),
|
||||
currentDate);
|
||||
var operationsOrdered = wellOperations
|
||||
.OrderBy(o => o.DateStart);
|
||||
|
||||
var operationFrom = planOperations
|
||||
.LastOrDefault(o => o.DateStart.AddHours(o.DurationHours) <= currentDate);
|
||||
var factOperations = operationsOrdered
|
||||
.Where(o => o.IdType == WellOperation.IdOperationTypeFact);
|
||||
|
||||
var operationTo = planOperations
|
||||
.FirstOrDefault(o => o.DateStart >= currentDate);
|
||||
var lastCorrespondingFactOperation = factOperations
|
||||
.LastOrDefault(o => o.IdPlan is not null);
|
||||
|
||||
if (lastCorrespondingFactOperation is null)
|
||||
return null;
|
||||
|
||||
var lastCorrespondingPlanOperation = wellOperations
|
||||
.FirstOrDefault(o => o.Id == lastCorrespondingFactOperation.IdPlan);
|
||||
|
||||
if (operationFrom is null && operationTo is not null)
|
||||
return 0d;
|
||||
else if (operationFrom is not null && operationTo is not null)
|
||||
{
|
||||
return Interpolate(
|
||||
operationFrom.DepthEnd,
|
||||
operationTo.DepthStart,
|
||||
operationFrom.DateStart.AddHours(operationTo.DurationHours),
|
||||
operationTo.DateStart,
|
||||
currentDate);
|
||||
}
|
||||
else if (operationFrom is not null && operationTo is null)
|
||||
return operationFrom.DepthEnd;
|
||||
if (lastCorrespondingPlanOperation is null)
|
||||
return null;
|
||||
|
||||
return null;
|
||||
var factEnd = lastCorrespondingFactOperation.DateStart.AddHours(lastCorrespondingFactOperation.DurationHours);
|
||||
var planEnd = lastCorrespondingPlanOperation.DateStart.AddHours(lastCorrespondingPlanOperation.DurationHours);
|
||||
var lagDays = (planEnd - factEnd).TotalDays;
|
||||
|
||||
return lagDays;
|
||||
}
|
||||
|
||||
private static double Interpolate(double y0, double y1, DateTimeOffset x0, DateTimeOffset x1, DateTimeOffset x)
|
||||
=> y0 + (y1 - y0) * (x - x0).TotalMinutes / (x1 - x0).TotalMinutes;
|
||||
|
||||
private IEnumerable<StatSectionDto> CalcSectionsStats(IEnumerable<WellOperation> operations, double timezoneOffsetH)
|
||||
{
|
||||
var sectionTypeIds = operations
|
||||
|
@ -92,7 +92,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
Longitude = gCluster.Key.Longitude ?? gDeposit.Key.Longitude,
|
||||
Wells = gCluster.Select(well =>
|
||||
{
|
||||
var dto = wellInfoService.FirstOrDefault(w => w.Id == well.Id);
|
||||
var dto = wellInfoService.FirstOrDefault(w => w.Id == well.Id && well.IdState == 1);
|
||||
dto ??= well.Adapt<WellMapInfoWithTelemetryStat>();
|
||||
dto.Latitude ??= gCluster.Key.Latitude ?? gDeposit.Key.Latitude;
|
||||
dto.Longitude ??= gCluster.Key.Longitude ?? gDeposit.Key.Longitude;
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@ -58,8 +59,8 @@ public class WellboreService : IWellboreService
|
||||
Id = group.Key,
|
||||
Name = sections[group.Key].Caption,
|
||||
Well = well.Adapt<WellWithTimezoneDto>(),
|
||||
DateStart = group.Min(operation => operation.DateStart),
|
||||
DateEnd = group.Max(operation => operation.DateStart.AddHours(operation.DurationHours)),
|
||||
DateStart = group.Min(operation => operation.DateStart).ToUtcDateTimeOffset(well.Timezone.Hours).ToOffset(TimeSpan.FromHours(well.Timezone.Hours)),
|
||||
DateEnd = group.Max(operation => operation.DateStart.AddHours(operation.DurationHours)).ToUtcDateTimeOffset(well.Timezone.Hours).ToOffset(TimeSpan.FromHours(well.Timezone.Hours)),
|
||||
DepthStart = group.Min(operation => operation.DepthStart),
|
||||
DepthEnd = group.Max(operation => operation.DepthEnd),
|
||||
});
|
||||
|
@ -38,8 +38,14 @@ namespace AsbCloudInfrastructure
|
||||
backgroundWorker.Push(LimitingParameterCalcWorkFactory.MakeWork());
|
||||
backgroundWorker.Push(MakeMemoryMonitoringWork());
|
||||
|
||||
var notificationBackgroundWorker = provider.GetRequiredService<NotificationBackgroundWorker>();
|
||||
|
||||
Task.Delay(1_000)
|
||||
.ContinueWith(async (_) => await backgroundWorker.StartAsync(CancellationToken.None));
|
||||
.ContinueWith(async (_) =>
|
||||
{
|
||||
await backgroundWorker.StartAsync(CancellationToken.None);
|
||||
await notificationBackgroundWorker.StartAsync(CancellationToken.None);
|
||||
});
|
||||
}
|
||||
|
||||
static WorkPeriodic MakeMemoryMonitoringWork()
|
||||
|
@ -13,6 +13,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Services.Notifications;
|
||||
using Xunit;
|
||||
|
||||
namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
@ -85,7 +86,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
private readonly Mock<IWellService> wellServiceMock;
|
||||
private readonly Mock<IConfiguration> configurationMock;
|
||||
private readonly Mock<BackgroundWorker> backgroundWorkerMock;
|
||||
private readonly Mock<IEmailService> emailServiceMock;
|
||||
private readonly Mock<NotificationService> notificationServiceMock;
|
||||
|
||||
public DrillingProgramServiceTest()
|
||||
{
|
||||
@ -104,7 +105,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock = new Mock<IWellService>();
|
||||
configurationMock = new Mock<IConfiguration>();
|
||||
backgroundWorkerMock = new Mock<BackgroundWorker>();
|
||||
emailServiceMock = new Mock<IEmailService>();
|
||||
notificationServiceMock = new Mock<NotificationService>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -117,7 +118,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
|
||||
var users = await service.GetAvailableUsers(idWell, CancellationToken.None);
|
||||
|
||||
@ -134,7 +135,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
|
||||
var result = await service.AddPartsAsync(idWell, new int[] { 1001, 1002 }, CancellationToken.None);
|
||||
|
||||
@ -153,7 +154,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
|
||||
var result = await service.RemovePartsAsync(idWell, new int[] { 1005 }, CancellationToken.None);
|
||||
|
||||
@ -176,7 +177,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
|
||||
var result = await service.AddUserAsync(idWell, 1001, publisher1.Id, 1, CancellationToken.None);
|
||||
|
||||
@ -211,7 +212,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
|
||||
var result = await service.RemoveUserAsync(idWell, idFileCategory, publisher1.Id, idUserRole, CancellationToken.None);
|
||||
|
||||
@ -237,7 +238,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
|
||||
var fileMark = new FileMarkDto
|
||||
{
|
||||
@ -268,7 +269,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
var fileMark = new FileMarkDto
|
||||
{
|
||||
IdFile = file1001.Id,
|
||||
@ -306,7 +307,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
|
||||
var fileMark = new FileMarkDto
|
||||
{
|
||||
@ -333,7 +334,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
|
||||
var state = await service.GetStateAsync(idWell, publisher1.Id, CancellationToken.None);
|
||||
|
||||
@ -360,7 +361,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
|
||||
var state = await service.GetStateAsync(idWell, publisher1.Id, CancellationToken.None);
|
||||
|
||||
@ -390,7 +391,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock.Object,
|
||||
configurationMock.Object,
|
||||
backgroundWorkerMock.Object,
|
||||
emailServiceMock.Object);
|
||||
notificationServiceMock.Object);
|
||||
|
||||
var state = await service.GetStateAsync(idWell, publisher1.Id, CancellationToken.None);
|
||||
|
||||
|
@ -10,6 +10,7 @@ using System.Linq;
|
||||
using AsbCloudApp.Repositories;
|
||||
using System.Collections.Generic;
|
||||
using AsbCloudApp.Data.User;
|
||||
using AsbCloudApp.Services.Notifications;
|
||||
|
||||
namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
{
|
||||
@ -21,8 +22,10 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
private readonly WellFinalDocumentsService service;
|
||||
private readonly Mock<IUserRepository> userRepositoryMock;
|
||||
private readonly Mock<IWellService> wellServiceMock;
|
||||
private readonly Mock<IEmailService> emailServiceMock;
|
||||
private readonly Mock<IFileCategoryService> fileCategoryService;
|
||||
private readonly NotificationService notificationService;
|
||||
private readonly Mock<ICrudRepository<NotificationCategoryDto>> notificationCategoryRepositoryMock;
|
||||
private readonly Mock<INotificationTransportService> notificationTransportServiceMock;
|
||||
|
||||
private static readonly UserExtendedDto[] users = new[]{
|
||||
new UserExtendedDto {
|
||||
@ -126,7 +129,25 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
Deposit = "deposit 1" });
|
||||
var configuration = new Microsoft.Extensions.Configuration.ConfigurationBuilder().Build();
|
||||
|
||||
emailServiceMock = new Mock<IEmailService>();
|
||||
notificationCategoryRepositoryMock = new Mock<ICrudRepository<NotificationCategoryDto>>();
|
||||
|
||||
notificationCategoryRepositoryMock.Setup(r => r.GetOrDefaultAsync(It.IsAny<int>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new NotificationCategoryDto
|
||||
{
|
||||
Id = 20000,
|
||||
Name = "Системные уведомления"
|
||||
});
|
||||
|
||||
notificationTransportServiceMock = new Mock<INotificationTransportService>();
|
||||
|
||||
notificationTransportServiceMock.SetupGet(x => x.IdTransportType)
|
||||
.Returns(1);
|
||||
|
||||
notificationService = new NotificationService(notificationCategoryRepositoryMock.Object,
|
||||
new Mock<INotificationRepository>().Object,
|
||||
new [] { notificationTransportServiceMock.Object });
|
||||
|
||||
fileCategoryService = new Mock<IFileCategoryService>();
|
||||
fileCategoryService.Setup(s => s.GetOrDefaultAsync(idWellFinalDocCategory, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync((int id, CancellationToken _) => new FileCategoryDto
|
||||
@ -140,7 +161,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
userRepository: userRepositoryMock.Object,
|
||||
wellService: wellServiceMock.Object,
|
||||
configuration: configuration,
|
||||
emailService: emailServiceMock.Object,
|
||||
notificationService: notificationService,
|
||||
fileCategoryService: fileCategoryService.Object,
|
||||
wellFinalDocumentsRepository: wellFinalDocumentsRepository.Object);
|
||||
}
|
||||
@ -187,13 +208,5 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
var data = await service.ReNotifyPublishersAsync(1, users[0].Id, idWellFinalDocCategory, CancellationToken.None);
|
||||
Assert.Equal(1, data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReNotifyPublishersAsync_returns_2()
|
||||
{
|
||||
var emailsCount = await service.ReNotifyPublishersAsync(1, users[0].Id, idWellFinalDocCategory, CancellationToken.None);
|
||||
Assert.Equal(1, emailsCount);
|
||||
emailServiceMock.Verify(s => s.EnqueueSend(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
87
AsbCloudWebApi/Controllers/ManualController.cs
Normal file
87
AsbCloudWebApi/Controllers/ManualController.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace AsbCloudWebApi.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[Authorize]
|
||||
public class ManualController : ControllerBase
|
||||
{
|
||||
private readonly IManualCatalogService manualCatalogService;
|
||||
|
||||
public ManualController(IManualCatalogService manualCatalogService)
|
||||
{
|
||||
this.manualCatalogService = manualCatalogService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сохранение файла
|
||||
/// </summary>
|
||||
/// <param name="idDirectory">Id директории</param>
|
||||
/// <param name="file">Загружаемый файл</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<IActionResult> SaveFileAsync(int idDirectory,
|
||||
[Required] IFormFile file,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var idUser = User.GetUserId();
|
||||
|
||||
if(!idUser.HasValue)
|
||||
throw new ForbidException("Не удается вас опознать");
|
||||
|
||||
using var fileStream = file.OpenReadStream();
|
||||
|
||||
var id = await manualCatalogService.SaveFileAsync(idDirectory, idUser.Value, file.FileName, fileStream, cancellationToken);
|
||||
|
||||
return Ok(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение файла
|
||||
/// </summary>
|
||||
/// <param name="id">Id инструкции</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{id:int}")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<IActionResult> GetFileAsync(int id, CancellationToken cancellationToken)
|
||||
{
|
||||
var file = await manualCatalogService.GetFileAsync(id, cancellationToken);
|
||||
|
||||
if (!file.HasValue)
|
||||
return NoContent();
|
||||
|
||||
return File(file.Value.stream, "application/octet-stream", file.Value.fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление файла
|
||||
/// </summary>
|
||||
/// <param name="id">Id инструкции</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<IActionResult> DeleteFileAsync(int id, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await manualCatalogService.DeleteFileAsync(id, cancellationToken));
|
||||
}
|
||||
}
|
90
AsbCloudWebApi/Controllers/ManualDirectoryController.cs
Normal file
90
AsbCloudWebApi/Controllers/ManualDirectoryController.cs
Normal file
@ -0,0 +1,90 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.Manuals;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
namespace AsbCloudWebApi.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[Authorize]
|
||||
public class ManualDirectoryController : ControllerBase
|
||||
{
|
||||
private readonly IManualDirectoryRepository manualDirectoryRepository;
|
||||
private readonly IManualCatalogService manualCatalogService;
|
||||
|
||||
public ManualDirectoryController(IManualDirectoryRepository manualDirectoryRepository,
|
||||
IManualCatalogService manualCatalogService)
|
||||
{
|
||||
this.manualDirectoryRepository = manualDirectoryRepository;
|
||||
this.manualCatalogService = manualCatalogService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создание директории
|
||||
/// </summary>
|
||||
/// <param name="name">Название</param>
|
||||
/// <param name="idParent">Необязательный параметр. Id родительской директории</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Permission("Manual.edit")]
|
||||
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<IActionResult> AddDirectoryAsync(string name, int? idParent, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await manualCatalogService.AddDirectoryAsync(name, idParent, cancellationToken));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обновление директории
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="name">Новое название директории</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPut]
|
||||
[Permission("Manual.edit")]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<IActionResult> UpdateDirectoryAsync(int id, string name, CancellationToken cancellationToken)
|
||||
{
|
||||
await manualCatalogService.UpdateDirectoryAsync(id, name, cancellationToken);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление директории
|
||||
/// </summary>
|
||||
/// <param name="id">Идентификатор директории</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
[Permission("Manual.delete")]
|
||||
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<IActionResult> DeleteDirectoryAsync(int id, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await manualCatalogService.DeleteDirectoryAsync(id, cancellationToken));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение дерева категорий
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
[Permission("Manual.get")]
|
||||
[ProducesResponseType(typeof(IEnumerable<ManualDirectoryDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<IActionResult> GetAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await manualDirectoryRepository.GetTreeAsync(cancellationToken));
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -6,6 +7,7 @@ using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services.Notifications;
|
||||
using AsbCloudWebApi.SignalR.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
@ -17,50 +19,36 @@ namespace AsbCloudWebApi.Controllers;
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("api/[controller]")]
|
||||
[Obsolete("Это тестовый контроллер, его нельзя использовать на фронте.")]
|
||||
public class NotificationController : ControllerBase
|
||||
{
|
||||
private readonly NotificationService notificationService;
|
||||
private readonly INotificationRepository notificationRepository;
|
||||
private readonly NotificationPublisher notificationPublisher;
|
||||
|
||||
public NotificationController(NotificationService notificationService,
|
||||
INotificationRepository notificationRepository)
|
||||
INotificationRepository notificationRepository,
|
||||
NotificationPublisher notificationPublisher)
|
||||
{
|
||||
this.notificationService = notificationService;
|
||||
this.notificationRepository = notificationRepository;
|
||||
this.notificationPublisher = notificationPublisher;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отправка уведомления
|
||||
/// </summary>
|
||||
/// <param name="idUser">Id пользователя</param>
|
||||
/// <param name="idNotificationCategory">Id категории уведомления. Допустимое значение параметра: 1</param>
|
||||
/// <param name="title">Заголовок уведомления</param>
|
||||
/// <param name="message">Сообщение уведомления</param>
|
||||
/// <param name="idNotificationTransport">Id типа доставки уведомления. Допустимое значение: 0</param>
|
||||
/// <param name="request">Параметры запроса</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> SendAsync([Required] int idUser,
|
||||
[Required]
|
||||
[Range(minimum: 1, maximum: 1, ErrorMessage = "Id категории уведомления недоступно. Допустимые: 1")]
|
||||
int idNotificationCategory,
|
||||
[Required] string title,
|
||||
[Required] string message,
|
||||
[Required]
|
||||
[Range(minimum: 0, maximum: 0, ErrorMessage = "Id способа отправки уведомления недоступно. Допустимые: 0")]
|
||||
int idNotificationTransport,
|
||||
CancellationToken cancellationToken)
|
||||
public async Task<IActionResult> SendAsync(NotifyRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
await notificationService.NotifyAsync(idUser,
|
||||
idNotificationCategory,
|
||||
title,
|
||||
message,
|
||||
idNotificationTransport,
|
||||
cancellationToken);
|
||||
|
||||
await notificationService.NotifyAsync(request, cancellationToken);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Обновление уведомления
|
||||
/// </summary>
|
||||
@ -73,13 +61,20 @@ public class NotificationController : ControllerBase
|
||||
[Required] bool isRead,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await notificationService.UpdateNotificationAsync(idNotification,
|
||||
var idUser = User.GetUserId();
|
||||
|
||||
if (!idUser.HasValue)
|
||||
return Forbid();
|
||||
|
||||
await notificationService.UpdateAsync(idNotification,
|
||||
isRead,
|
||||
cancellationToken);
|
||||
|
||||
await notificationPublisher.PublishCountUnreadAsync(idUser.Value, cancellationToken);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Получение уведомления по Id
|
||||
/// </summary>
|
||||
@ -96,12 +91,12 @@ public class NotificationController : ControllerBase
|
||||
if (notification is null)
|
||||
{
|
||||
return BadRequest(ArgumentInvalidException.MakeValidationError(nameof(idNotification),
|
||||
"Уведомление не найдено"));
|
||||
"Уведомление не найдено"));
|
||||
}
|
||||
|
||||
return Ok(notification);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Получение списка уведомлений
|
||||
/// </summary>
|
||||
@ -117,7 +112,7 @@ public class NotificationController : ControllerBase
|
||||
|
||||
if (!idUser.HasValue)
|
||||
return Forbid();
|
||||
|
||||
|
||||
var result = await notificationRepository.GetNotificationsAsync(idUser.Value,
|
||||
request,
|
||||
cancellationToken);
|
||||
@ -140,4 +135,19 @@ public class NotificationController : ControllerBase
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление уведомлений
|
||||
/// </summary>
|
||||
/// <param name="request">Параметры запроса</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
public async Task<IActionResult> DeleteAsync(NotificationDeleteRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await notificationRepository.DeleteAsync(request, cancellationToken);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user