diff --git a/AsbCloudApp/Data/SAUB/TelemetryEventDto.cs b/AsbCloudApp/Data/SAUB/TelemetryEventDto.cs
new file mode 100644
index 00000000..e9a8a90e
--- /dev/null
+++ b/AsbCloudApp/Data/SAUB/TelemetryEventDto.cs
@@ -0,0 +1,29 @@
+namespace AsbCloudApp.Data.SAUB;
+
+///
+/// dto для события телеметрии
+///
+public class TelemetryEventDto
+{
+ ///
+ /// ключ события
+ ///
+ public object Id { get; set; }
+
+ ///
+ /// ключ категории
+ ///
+ public int IdCategory { get; set; }
+
+ ///
+ /// шаблон сообщения
+ ///
+ public string MessageTemplate { get; set; } = null!;
+
+ ///
+ /// метод формирования текста сообщения по шаблону
+ ///
+ /// аргументы, которые подставляются в шаблон сообщения
+ ///
+ public string MakeMessageText(string?[] args) => string.Format(MessageTemplate, args);
+}
diff --git a/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs b/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs
index 05562034..b34d1289 100644
--- a/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs
+++ b/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs
@@ -51,4 +51,9 @@ public class TelemetryMessageDto : IId
/// аргумент №3 для подстановки в шаблон сообщения
///
public string? Arg3 { get; set; }
+
+ ///
+ /// ключ телеметрии
+ ///
+ public int IdTelemetry { get; set; }
}
diff --git a/AsbCloudApp/Data/StatCriticalMessageDto.cs b/AsbCloudApp/Data/StatCriticalMessageDto.cs
new file mode 100644
index 00000000..8595934a
--- /dev/null
+++ b/AsbCloudApp/Data/StatCriticalMessageDto.cs
@@ -0,0 +1,28 @@
+
+namespace AsbCloudApp.Data;
+
+///
+/// dto для отображения статистики сообщений
+///
+public class StatCriticalMessageDto
+{
+ ///
+ /// ключ скважины
+ ///
+ public int IdWell { get; set; }
+
+ ///
+ /// ключ категории
+ ///
+ public int? IdCategory { get; set; }
+
+ ///
+ /// шаблон сообщения
+ ///
+ public string? MessageTemplate { get; set; }
+
+ ///
+ /// количество сообщений
+ ///
+ public int MessagesCount { get; set; }
+}
diff --git a/AsbCloudApp/Repositories/IEventRepository.cs b/AsbCloudApp/Repositories/IEventRepository.cs
new file mode 100644
index 00000000..90aa9687
--- /dev/null
+++ b/AsbCloudApp/Repositories/IEventRepository.cs
@@ -0,0 +1,30 @@
+using AsbCloudApp.Data.SAUB;
+using AsbCloudApp.Requests;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.Repositories;
+
+///
+/// Репозиторий по работе с событиями
+///
+public interface IEventRepository
+{
+ ///
+ /// получение списка событий по параметрам запроса
+ ///
+ /// параметры запроса
+ ///
+ ///
+ Task> GetAsync(TelemetryEventRequest request, CancellationToken token);
+
+ ///
+ /// Сохранить. Добавить или заменить.
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task UpsertAsync(string uid, IEnumerable dtos, CancellationToken token);
+}
diff --git a/AsbCloudApp/Repositories/IMessageRepository.cs b/AsbCloudApp/Repositories/IMessageRepository.cs
new file mode 100644
index 00000000..ac794a46
--- /dev/null
+++ b/AsbCloudApp/Repositories/IMessageRepository.cs
@@ -0,0 +1,41 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Data.SAUB;
+using AsbCloudApp.Requests;
+using AsbCloudApp.Services;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.Repositories;
+
+///
+/// Репозиторий по работе с сообщениями панели оператора
+///
+public interface IMessageRepository : ITelemetryDataEditorService
+{
+ ///
+ /// Получить сообщения по параметрам
+ ///
+ ///
+ ///
+ ///
+ Task> GetPaginatedMessagesAsync(MessageTelemetryRequest request, CancellationToken token);
+
+ ///
+ /// Получить сообщения по параметрам
+ ///
+ ///
+ ///
+ ///
+ Task> GetMessagesAsync(MessageTelemetryRequest request, CancellationToken token);
+
+ ///
+ /// Метод для сохранения сообщения от панели
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task InsertAsync(string uid, IEnumerable dtos,
+ CancellationToken token);
+}
\ No newline at end of file
diff --git a/AsbCloudApp/Requests/MessageRequest.cs b/AsbCloudApp/Requests/MessageRequest.cs
index 1e755231..f11f6290 100644
--- a/AsbCloudApp/Requests/MessageRequest.cs
+++ b/AsbCloudApp/Requests/MessageRequest.cs
@@ -1,5 +1,8 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Data.SAUB;
using System;
using System.Collections.Generic;
+using System.Linq;
namespace AsbCloudApp.Requests;
@@ -11,7 +14,7 @@ public class MessageRequestBase : RequestBase
///
/// категория
///
- public IEnumerable? Categoryids { get; set; }
+ public IEnumerable? IdsCategories { get; set; }
///
@@ -29,29 +32,21 @@ public class MessageRequestBase : RequestBase
///
public string? SearchString { get; set; }
-}
-
-///
-/// параметры для запроса списка сообщений (с id скважины)
-///
-public class MessageRequest : MessageRequestBase
-{
-
///
- /// id скважины
+ ///
///
- public int IdWell { get; set; }
+ public MessageRequestBase()
+ {
+
+ }
///
- /// параметры для запроса списка сообщений (с id скважины)
+ /// копирующий конструктор
///
///
- ///
- public MessageRequest(MessageRequestBase request, int idWell)
+ public MessageRequestBase(MessageRequestBase request)
{
- this.IdWell = idWell;
-
- this.Categoryids = request.Categoryids;
+ this.IdsCategories = request.IdsCategories;
this.Begin = request.Begin;
this.End = request.End;
this.SearchString = request.SearchString;
@@ -62,3 +57,55 @@ public class MessageRequest : MessageRequestBase
}
}
+
+///
+/// параметры для запроса списка сообщений (с ids скважин)
+///
+public class MessageRequest : MessageRequestBase
+{
+ ///
+ /// ids скважин
+ ///
+ public IEnumerable IdsWell { get; set; } = null!;
+
+ ///
+ /// параметры для запроса списка сообщений (с ids скважин)
+ ///
+ ///
+ ///
+ public MessageRequest(MessageRequestBase request, IEnumerable idsWell) : base(request)
+ {
+ this.IdsWell = idsWell;
+ }
+}
+
+///
+/// параметры запроса для получения списка сообщений телеметрии
+///
+public class MessageTelemetryRequest : MessageRequestBase
+{
+ ///
+ /// события
+ ///
+ public IEnumerable Events { get; set; }= Enumerable.Empty();
+
+ ///
+ /// телеметрии
+ ///
+ public IEnumerable Telemetries { get; set; } = Enumerable.Empty();
+
+ ///
+ public MessageTelemetryRequest(
+ MessageRequestBase request,
+ IEnumerable events,
+ IEnumerable telemetries) : base(request)
+ {
+ Events = events;
+ Telemetries = telemetries;
+ }
+
+ ///
+ public MessageTelemetryRequest(MessageRequestBase request)
+ : base(request) { }
+}
+
diff --git a/AsbCloudApp/Requests/TelemetryEventRequest.cs b/AsbCloudApp/Requests/TelemetryEventRequest.cs
new file mode 100644
index 00000000..a9018f9b
--- /dev/null
+++ b/AsbCloudApp/Requests/TelemetryEventRequest.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.Requests;
+
+///
+/// параметры запроса для получения событий телеметрии
+///
+public class TelemetryEventRequest
+{
+ ///
+ /// ключи телеметрии
+ ///
+ public IEnumerable IdsTelemetries { get; set; } = null!;
+
+ ///
+ /// ключи категорий
+ ///
+ public IEnumerable? IdsCategories { get; set; }
+
+ ///
+ /// строка поиска
+ ///
+ public string? SearchString { get; set; }
+}
diff --git a/AsbCloudApp/Services/IEventService.cs b/AsbCloudApp/Services/IEventService.cs
deleted file mode 100644
index a376b649..00000000
--- a/AsbCloudApp/Services/IEventService.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using AsbCloudApp.Data.SAUB;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace AsbCloudApp.Services;
-
-///
-/// Сервис сохранения списка сообщений от панелей
-///
-public interface IEventService
-{
- ///
- /// Сохранить. Добавить или заменить.
- ///
- ///
- ///
- ///
- ///
- Task UpsertAsync(string uid, IEnumerable dtos,
- CancellationToken token = default);
-}
diff --git a/AsbCloudApp/Services/IMessageService.cs b/AsbCloudApp/Services/IMessageService.cs
index 5a5f4d17..319d2faa 100644
--- a/AsbCloudApp/Services/IMessageService.cs
+++ b/AsbCloudApp/Services/IMessageService.cs
@@ -1,5 +1,4 @@
using AsbCloudApp.Data;
-using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Requests;
using System.Collections.Generic;
using System.Threading;
@@ -8,25 +7,24 @@ using System.Threading.Tasks;
namespace AsbCloudApp.Services;
///
-/// Сервис сообщений панели оператора
+/// Сервис сообщений
///
-public interface IMessageService : ITelemetryDataEditorService
+public interface IMessageService
{
///
- /// Получить сообщения по параметрам
+ /// Получить статистику сообщений по параметрам запроса
///
///
///
///
- Task> GetMessagesAsync(MessageRequest request, CancellationToken token);
+ Task> GetStatAsync(MessageRequest request, CancellationToken token);
///
- /// Метод для сохранения сообщения от панели
+ /// Получить PaginationContainer с сообщениями по параметрам
///
- ///
- ///
+ ///
///
///
- Task InsertAsync(string uid, IEnumerable dtos,
- CancellationToken token);
+ Task> GetPaginatedMessagesAsync(MessageRequest request, CancellationToken token);
+
}
\ No newline at end of file
diff --git a/AsbCloudApp/Services/ITelemetryService.cs b/AsbCloudApp/Services/ITelemetryService.cs
index c1b4ba99..fa6c88f4 100644
--- a/AsbCloudApp/Services/ITelemetryService.cs
+++ b/AsbCloudApp/Services/ITelemetryService.cs
@@ -47,6 +47,12 @@ public interface ITelemetryService
///
TelemetryBaseDto? GetOrDefaultTelemetryByIdWell(int idWell);
+ ///
+ /// получить список телеметрии по ключам скважин
+ ///
+ /// ключи скважин
+ ///
+ IEnumerable GetOrDefaultTelemetriesByIdsWells(IEnumerable idsWells);
///
/// получить диапазон дат за которые есть данные
///
diff --git a/AsbCloudInfrastructure.Tests/Services/MessageServiceTest.cs b/AsbCloudInfrastructure.Tests/Services/MessageServiceTest.cs
new file mode 100644
index 00000000..ae7b6691
--- /dev/null
+++ b/AsbCloudInfrastructure.Tests/Services/MessageServiceTest.cs
@@ -0,0 +1,270 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Data.SAUB;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
+using AsbCloudApp.Services;
+using AsbCloudDb.Model;
+using AsbCloudInfrastructure.Services;
+using NSubstitute;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace AsbCloudInfrastructure.Tests.Services;
+
+public class MessageServiceTest
+{
+ private static readonly List telemetries = new List()
+ {
+ new TelemetryDto()
+ {
+ Id = 1,
+ IdWell = 1,
+ TimeZone = new SimpleTimezoneDto()
+ {
+ Hours = 5
+ }
+ },
+ new TelemetryDto()
+ {
+ Id = 2,
+ IdWell = 2,
+ TimeZone = new SimpleTimezoneDto()
+ {
+ Hours = 5
+ }
+ }
+ };
+
+ private static readonly List events = new List()
+ {
+ new TelemetryEventDto()
+ {
+ Id = 1,
+ IdCategory = 1,
+ MessageTemplate = "Шаблон сообщения 1 категории 1"
+ },
+ new TelemetryEventDto()
+ {
+ Id = 2,
+ IdCategory = 1,
+ MessageTemplate = "Шаблон сообщения 2 категории 1"
+ },
+ new TelemetryEventDto()
+ {
+ Id = 3,
+ IdCategory = 1,
+ MessageTemplate = "Шаблон сообщения 3 категории 1"
+ },
+ new TelemetryEventDto()
+ {
+ Id = 4,
+ IdCategory = 2,
+ MessageTemplate = "Шаблон сообщения 1 категории 2"
+ },
+ new TelemetryEventDto()
+ {
+ Id = 5,
+ IdCategory = 2,
+ MessageTemplate = "Шаблон сообщения 2 категории 2"
+ },
+ new TelemetryEventDto()
+ {
+ Id = 6,
+ IdCategory = 3,
+ MessageTemplate = "Шаблон сообщения 1 категории 3"
+ }
+ };
+
+ ///
+ /// Структура:
+ /// Телеметрия 1:
+ /// Категория 1:
+ /// Событие 1:
+ /// Сообщение 1
+ /// Сообщение 2
+ /// Сообщение 3
+ /// Событие 2:
+ /// Сообщение 1
+ /// Сообщение 2
+ /// Сообщение 3
+ /// Событие 3:
+ /// Сообщение 1
+ /// Сообщение 2
+ /// Сообщение 3
+ /// Категория 2:
+ /// Событие 2:
+ /// Сообщение 1
+ /// Сообщение 2
+ /// Событие 3:
+ /// Сообщение 1
+ /// Сообщение 2
+ /// Телеметрия 2
+ /// Категория 3:
+ /// Событие 3:
+ /// Сообщение 1
+ /// Сообщение 2
+ /// Сообщение 3
+ ///
+ ///
+ private static readonly List messages = new List()
+ {
+ new TelemetryMessageDto()
+ {
+ Id = 1,
+ IdEvent = 1,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 2,
+ IdEvent = 1,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 3,
+ IdEvent = 1,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 4,
+ IdEvent = 2,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 5,
+ IdEvent = 2,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 6,
+ IdEvent = 2,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 7,
+ IdEvent = 3,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 8,
+ IdEvent = 3,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 9,
+ IdEvent = 3,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 10,
+ IdEvent = 4,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 11,
+ IdEvent = 4,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 12,
+ IdEvent = 5,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 13,
+ IdEvent = 5,
+ IdTelemetry = 1
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 14,
+ IdEvent = 6,
+ IdTelemetry = 2
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 15,
+ IdEvent = 6,
+ IdTelemetry = 2
+ },
+ new TelemetryMessageDto()
+ {
+ Id = 16,
+ IdEvent = 6,
+ IdTelemetry = 2
+ },
+ };
+
+
+
+ private readonly IMessageService messageServiceMock = Substitute.For();
+ private readonly IMessageRepository messageRepositoryMock = Substitute.For();
+ private readonly IEventRepository eventRepositoryMock = Substitute.For();
+ private readonly ITelemetryService telemetryServiceMock = Substitute.For();
+
+ public MessageServiceTest()
+ {
+ messageServiceMock = new MessageService(messageRepositoryMock, telemetryServiceMock, eventRepositoryMock);
+
+ telemetryServiceMock
+ .GetOrDefaultTelemetriesByIdsWells(Arg.Any>())
+ .Returns(telemetries);
+
+ eventRepositoryMock
+ .GetAsync(Arg.Any(), Arg.Any())
+ .Returns(events);
+
+ messageRepositoryMock
+ .GetMessagesAsync(Arg.Any(), Arg.Any())
+ .Returns(messages);
+ }
+
+
+ [Fact]
+ public async Task GetStatMessages_ShouldReturn_Success()
+ {
+ //act
+ var baseRequest = new MessageRequestBase() { };
+ var messageRequest = new MessageRequest(baseRequest, [1]);
+ var result = await messageServiceMock.GetStatAsync(messageRequest, CancellationToken.None);
+
+ Assert.Equal(6, result.Count());
+
+ AssertStatByEvent(result, 1, events[0], 3);
+ AssertStatByEvent(result, 1, events[1], 3);
+ AssertStatByEvent(result, 1, events[2], 3);
+ AssertStatByEvent(result, 1, events[3], 2);
+ AssertStatByEvent(result, 1, events[4], 2);
+ AssertStatByEvent(result, 2, events[5], 3);
+ }
+
+ private void AssertStatByEvent(IEnumerable result, int idWell, TelemetryEventDto eventDto, int count)
+ {
+ var eventStats = result
+ .Where(x => x.IdWell == idWell)
+ .Where(x => x.IdCategory == eventDto.IdCategory)
+ .Where(x => x.MessageTemplate == eventDto.MessageTemplate)
+ .ToArray();
+
+ Assert.Single(eventStats);
+ var eventStat = eventStats.First();
+ Assert.Equal(count, eventStat.MessagesCount);
+ }
+
+
+}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs
index ca66ebe8..37368596 100644
--- a/AsbCloudInfrastructure/DependencyInjection.cs
+++ b/AsbCloudInfrastructure/DependencyInjection.cs
@@ -293,9 +293,10 @@ public static class DependencyInjection
services.AddTransient();
services.AddTransient();
services.AddTransient();
- services.AddTransient();
+ services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient();
diff --git a/AsbCloudInfrastructure/Repository/EventRepository.cs b/AsbCloudInfrastructure/Repository/EventRepository.cs
new file mode 100644
index 00000000..680746f9
--- /dev/null
+++ b/AsbCloudInfrastructure/Repository/EventRepository.cs
@@ -0,0 +1,71 @@
+using AsbCloudApp.Data.SAUB;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
+using AsbCloudApp.Services;
+using AsbCloudDb;
+using AsbCloudDb.Model;
+using Microsoft.Extensions.Caching.Memory;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudInfrastructure.Repository;
+
+
+public class EventRepository : IEventRepository
+{
+ private readonly IAsbCloudDbContext db;
+ private readonly IMemoryCache memoryCache;
+ private readonly ITelemetryService telemetryService;
+
+ public EventRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService)
+ {
+ this.db = db;
+ this.memoryCache = memoryCache;
+ this.telemetryService = telemetryService;
+ }
+
+ public async Task> GetAsync(TelemetryEventRequest request, CancellationToken token)
+ {
+ var allEvents = await memoryCache.GetOrCreateBasicAsync(db.Set(), token);
+ var events = allEvents.Where(e => request.IdsTelemetries.Contains(e.IdTelemetry));
+
+ if (request.IdsCategories?.Any() == true)
+ events = events.Where(e => request.IdsCategories.Contains(e.IdCategory));
+
+ if (!string.IsNullOrEmpty(request.SearchString))
+ events = events.Where(e => e.MessageTemplate.Contains(request.SearchString, StringComparison.OrdinalIgnoreCase));
+
+ var dtos = events.Select(e =>
+ {
+ var dto = new TelemetryEventDto();
+ dto.Id = e.IdEvent;
+ dto.IdCategory = e.IdCategory;
+ dto.MessageTemplate = e.MessageTemplate;
+ return dto;
+ });
+
+ return dtos;
+ }
+
+ public async Task UpsertAsync(string uid, IEnumerable dtos,
+ CancellationToken token = default)
+ {
+ if (!dtos.Any())
+ return;
+
+ var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid);
+
+ var entities = dtos.Select(dto => new TelemetryEvent
+ {
+ IdEvent = dto.Id,
+ IdTelemetry = telemetry.Id,
+ IdCategory = dto.IdCategory,
+ MessageTemplate = dto.Message
+ });
+ await db.Database.ExecInsertOrUpdateAsync(db.TelemetryEvents, entities, token);
+ memoryCache.DropBasic();
+ }
+}
diff --git a/AsbCloudInfrastructure/Services/MessageService.cs b/AsbCloudInfrastructure/Services/MessageService.cs
new file mode 100644
index 00000000..e4a5b333
--- /dev/null
+++ b/AsbCloudInfrastructure/Services/MessageService.cs
@@ -0,0 +1,89 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
+using AsbCloudApp.Services;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudInfrastructure.Services;
+
+
+public class MessageService : IMessageService
+{
+ private readonly IMessageRepository messageRepository;
+ private readonly ITelemetryService telemetryService;
+ private readonly IEventRepository eventRepository;
+
+ public MessageService(
+ IMessageRepository messageRepository,
+ ITelemetryService telemetryService,
+ IEventRepository eventRepository)
+ {
+ this.messageRepository = messageRepository;
+ this.telemetryService = telemetryService;
+ this.eventRepository = eventRepository;
+ }
+
+ public async Task> GetPaginatedMessagesAsync(MessageRequest request, CancellationToken token)
+ {
+ var messageTelemetryRequest = await CreateMessageTelemetryRequest(request, token);
+
+ var result = await messageRepository.GetPaginatedMessagesAsync(messageTelemetryRequest, token);
+ return result;
+ }
+
+ public async Task> GetStatAsync(MessageRequest request, CancellationToken token)
+ {
+ var messageTelemetryRequest = await CreateMessageTelemetryRequest(request, token);
+
+ var telemetryMessages = await messageRepository.GetMessagesAsync(messageTelemetryRequest, token);
+
+ var groupedMessages = telemetryMessages.GroupBy(x => new { x.IdTelemetry, x.IdEvent });
+ var events = messageTelemetryRequest.Events.ToDictionary(e => e.Id);
+
+ var idsWellsDict = messageTelemetryRequest.Telemetries.ToDictionary(e => e.Id, e => e.IdWell);
+
+ var result = groupedMessages
+ .Select(m => new
+ {
+ IdWell = idsWellsDict.GetValueOrDefault(m.Key.IdTelemetry),
+ events.GetValueOrDefault(m.Key.IdEvent)?.IdCategory,
+ events.GetValueOrDefault(m.Key.IdEvent)?.MessageTemplate,
+ Count = m.Count(),
+ })
+ .Where(m => m.IdCategory != null)
+ .Where(m => m.IdWell != null)
+ .Where(m => m.MessageTemplate != null)
+ .GroupBy(m => new { m.IdWell, m.IdCategory, m.MessageTemplate })
+ .Select(m => new StatCriticalMessageDto()
+ {
+ IdWell = m.First().IdWell!.Value,
+ IdCategory = m.Key.IdCategory,
+ MessageTemplate = m.Key.MessageTemplate,
+ MessagesCount = m.Select(z => z.Count).Sum()
+ });
+
+ return result;
+ }
+
+ public async Task CreateMessageTelemetryRequest(MessageRequest request, CancellationToken token)
+ {
+ var telemetries = telemetryService.GetOrDefaultTelemetriesByIdsWells(request.IdsWell);
+
+ var telemetryEventRequest = new TelemetryEventRequest()
+ {
+ IdsTelemetries = telemetries.Select(t => t.Id),
+ IdsCategories = request.IdsCategories,
+ SearchString = request.SearchString,
+ };
+ var events = await eventRepository.GetAsync(telemetryEventRequest, token);
+
+ var messageTelemetryRequest = new MessageTelemetryRequest(request, events, telemetries);
+
+ return messageTelemetryRequest;
+ }
+}
diff --git a/AsbCloudInfrastructure/Services/SAUB/EventService.cs b/AsbCloudInfrastructure/Services/SAUB/EventService.cs
deleted file mode 100644
index d33dc502..00000000
--- a/AsbCloudInfrastructure/Services/SAUB/EventService.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using AsbCloudApp.Data.SAUB;
-using AsbCloudApp.Services;
-using AsbCloudDb;
-using AsbCloudDb.Model;
-using Microsoft.Extensions.Caching.Memory;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace AsbCloudInfrastructure.Services.SAUB;
-
-
-public class EventService : IEventService
-{
- private readonly IAsbCloudDbContext db;
- private readonly IMemoryCache memoryCache;
- private readonly ITelemetryService telemetryService;
-
- public EventService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService)
- {
- this.db = db;
- this.memoryCache = memoryCache;
- this.telemetryService = telemetryService;
- }
-
- public async Task UpsertAsync(string uid, IEnumerable dtos,
- CancellationToken token = default)
- {
- if (!dtos.Any())
- return;
-
- var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid);
-
- var entities = dtos.Select(dto => new TelemetryEvent
- {
- IdEvent = dto.Id,
- IdTelemetry = telemetry.Id,
- IdCategory = dto.IdCategory,
- MessageTemplate = dto.Message
- });
- var result = await db.Database.ExecInsertOrUpdateAsync(db.TelemetryEvents, entities, token);
- memoryCache.DropBasic();
- }
-}
diff --git a/AsbCloudInfrastructure/Services/SAUB/MessageService.cs b/AsbCloudInfrastructure/Services/SAUB/MessageRepository.cs
similarity index 63%
rename from AsbCloudInfrastructure/Services/SAUB/MessageService.cs
rename to AsbCloudInfrastructure/Services/SAUB/MessageRepository.cs
index 5d6555bc..4b9d36c4 100644
--- a/AsbCloudInfrastructure/Services/SAUB/MessageService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/MessageRepository.cs
@@ -1,12 +1,17 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.SAUB;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb;
using AsbCloudDb.Model;
+using DocumentFormat.OpenXml.Bibliography;
using Mapster;
using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.Extensions.Caching.Memory;
+using Microsoft.Extensions.Logging;
+using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -16,20 +21,31 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.SAUB;
-public class MessageService : IMessageService
+public class MessageRepository : IMessageRepository
{
private readonly IAsbCloudDbContext db;
private readonly IMemoryCache memoryCache;
private readonly ITelemetryService telemetryService;
- public MessageService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService)
+ public MessageRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService)
{
this.db = db;
this.memoryCache = memoryCache;
this.telemetryService = telemetryService;
}
- public async Task> GetMessagesAsync(MessageRequest request, CancellationToken token)
+ public async Task> GetMessagesAsync(MessageTelemetryRequest request, CancellationToken token)
+ {
+ var query = BuildQuery(request, token);
+
+ var entities = await query.ToArrayAsync(token);
+
+ var dtos = entities.Select(m => m.Adapt());
+
+ return dtos;
+ }
+
+ public async Task> GetPaginatedMessagesAsync(MessageTelemetryRequest request, CancellationToken token)
{
var result = new PaginationContainer
{
@@ -37,36 +53,86 @@ public class MessageService : IMessageService
Take = request.Take ?? 32,
};
- var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(request.IdWell);
- if (telemetry is null)
+ if (request.Telemetries.IsNullOrEmpty() || request.Events.IsNullOrEmpty())
return result;
- var allEvents = await memoryCache.GetOrCreateBasicAsync(db.Set(), token);
- var events = allEvents.Where(e => e.IdTelemetry == telemetry.Id);
+ var query = BuildQuery(request, token);
- if (!events.Any())
- return result;
-
- var query = db.TelemetryMessages.Where(m => m.IdTelemetry == telemetry.Id)
- .OrderBy(m => m.DateTime).AsNoTracking();
-
- if (request.Categoryids?.Any() == true || !string.IsNullOrEmpty(request.SearchString))
+ if (request.SortFields?.Any() == true)
{
- if (!string.IsNullOrEmpty(request.SearchString))
- events = events.Where(e => e.MessageTemplate.Contains(request.SearchString, StringComparison.OrdinalIgnoreCase));
-
- if (request.Categoryids?.Any() == true)
- events = events.Where(e => request.Categoryids.ToList().Contains(e.IdCategory));
-
- var eventIds = events.Select(e => e.IdEvent);
-
- if (!eventIds.Any())
- return result;
-
- query = query.Where(m => eventIds.Contains(m.IdEvent));
+ query = query.SortBy(request.SortFields);
}
- query = query.OrderByDescending(m => m.DateTime);
+ result.Count = query.Count();
+
+ var messagesList = await query
+ .Skip(result.Skip)
+ .Take(result.Take)
+ .AsNoTracking()
+ .ToArrayAsync(token);
+
+ if (messagesList.Count() == 0)
+ return result;
+
+ var allUsers = await memoryCache.GetOrCreateBasicAsync(db.Set(), token);
+ var users = allUsers.Where(u => request.Telemetries!.Select(t => t.Id).Contains(u.IdTelemetry));
+
+ if (!request.Events.Any())
+ return result;
+
+ var eventsDict = request.Events.ToDictionary(x => x.Id);
+ var usersDict = users.ToDictionary(x => x.IdUser, x => x);
+
+ var messagesDtoList = new List();
+
+ foreach (var message in messagesList)
+ {
+ var messageDto = new MessageDto
+ {
+ Id = message.Id,
+ WellDepth = message.WellDepth,
+ };
+
+ var telemetry = request.Telemetries.Where(t => t.Id == message.IdTelemetry).FirstOrDefault();
+
+ if(telemetry != null && telemetry.TimeZone != null)
+ messageDto.DateTime = message.DateTime.ToOffset(TimeSpan.FromHours(telemetry.TimeZone.Hours));
+
+ if (message.IdTelemetryUser is not null)
+ {
+ if (usersDict.TryGetValue((int)message.IdTelemetryUser, out TelemetryUser? user))
+ {
+ messageDto.User = user.MakeDisplayName();
+ }
+ else
+ messageDto.User = message.IdTelemetryUser.ToString();
+ }
+
+ if (eventsDict.TryGetValue(message.IdEvent, out TelemetryEventDto? e))
+ {
+ messageDto.CategoryId = e.IdCategory;
+ messageDto.Message = e.MakeMessageText([
+ message.Arg0,
+ message.Arg1,
+ message.Arg2,
+ message.Arg3
+ ]);
+ }
+ messagesDtoList.Add(messageDto);
+ }
+
+ result.Items = result.Items.Concat(messagesDtoList);
+
+ return result;
+ }
+ public IQueryable BuildQuery(MessageTelemetryRequest request, CancellationToken token)
+ {
+ var idsTelemetries = request.Telemetries.Select(t => t.Id);
+ var eventIds = request.Events.Select(e => e.Id);
+
+ var query = db.TelemetryMessages
+ .Where(m => idsTelemetries.Contains(m.IdTelemetry))
+ .Where(m => eventIds.Contains(m.IdEvent));
if (request.Begin is not null)
{
@@ -80,63 +146,13 @@ public class MessageService : IMessageService
query = query.Where(m => m.DateTime <= endUtc);
}
- result.Count = query.Count();
+ query = query.OrderByDescending(m => m.DateTime);
- if (request.SortFields?.Any() == true)
- {
- query = query.SortBy(request.SortFields);
- }
- var messagesList = await query.Skip(result.Skip)
- .Take(result.Take).AsNoTracking()
- .ToListAsync(token).ConfigureAwait(false);
-
- if (messagesList.Count == 0)
- return result;
-
- var allUsers = await memoryCache.GetOrCreateBasicAsync(db.Set(), token);
- var users = allUsers.Where(u => u.IdTelemetry == telemetry.Id);
-
- var eventsDict = events.ToDictionary(x => x.IdEvent, x => x);
- var usersDict = users.ToDictionary(x => x.IdUser, x => x);
-
- var messagesDtoList = new List();
- var timezone = telemetryService.GetTimezone(telemetry.Id);
-
- foreach (var message in messagesList)
- {
- var messageDto = new MessageDto
- {
- Id = message.Id,
- WellDepth = message.WellDepth
- };
-
- messageDto.DateTime = message.DateTime.ToOffset(TimeSpan.FromHours(timezone.Hours));
-
- if (message.IdTelemetryUser is not null)
- {
- if (usersDict.TryGetValue((int)message.IdTelemetryUser, out TelemetryUser? user))
- {
- messageDto.User = user.MakeDisplayName();
- }
- else
- messageDto.User = message.IdTelemetryUser.ToString();
- }
-
- if (eventsDict.TryGetValue(message.IdEvent, out TelemetryEvent? e))
- {
- messageDto.CategoryId = e.IdCategory;
- messageDto.Message = e.MakeMessageText(message);
- }
- messagesDtoList.Add(messageDto);
- }
-
- result.Items = result.Items.Concat(messagesDtoList);
-
- return result;
+ return query;
}
public Task InsertAsync(string uid, IEnumerable dtos,
- CancellationToken token = default)
+ CancellationToken token = default)
{
if (!dtos.Any())
return Task.CompletedTask;
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataEditorService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataEditorService.cs
index 207dc744..442a68f6 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataEditorService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataEditorService.cs
@@ -21,7 +21,7 @@ public class TelemetryDataEditorService : ITelemetryDataEditorService
///
///
///
- ///
+ ///
///
///
///
@@ -36,7 +36,7 @@ public class TelemetryDataEditorService : ITelemetryDataEditorService
ITelemetryDataSaubService dataSaubService,
ITelemetryDataService dataSpinService,
IDataSaubStatRepository dataSaubStatRepository,
- IMessageService messageService,
+ IMessageRepository messageRepository,
IDrillTestRepository drillTestRepository,
ILimitingParameterRepository limitingParameterRepository,
IDetectedOperationRepository detectedOperationRepository,
@@ -54,7 +54,7 @@ public class TelemetryDataEditorService : ITelemetryDataEditorService
dataSaubService,
dataSpinService,
dataSaubStatRepository,
- messageService,
+ messageRepository,
drillTestRepository,
limitingParameterRepository,
detectedOperationRepository,
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs
index 6de56bdc..a501f37c 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs
@@ -144,15 +144,32 @@ public class TelemetryService : ITelemetryService
public TelemetryBaseDto? GetOrDefaultTelemetryByIdWell(int idWell)
{
- var entity = GetTelemetryCache()
- .FirstOrDefault(t => t.Well?.Id == idWell);
+ var dto = GetOrDefaultTelemetriesByIdsWells([idWell])
+ .FirstOrDefault();
- if (entity?.Well?.Timezone is not null && entity.TimeZone.Hours != entity.Well.Timezone.Hours)
- {
- entity.TimeZone = entity.Well.Timezone;
- //TODO: выдаем предупреждение!
- }
- return entity?.Adapt();
+ return dto;
+ }
+
+ public IEnumerable GetOrDefaultTelemetriesByIdsWells(IEnumerable idsWells)
+ {
+ var entities = GetTelemetryCache()
+ .Where(t => t.Well != null)
+ .Where(t => idsWells.Contains(t.Well!.Id))
+ .Select(t => {
+ t.TimeZone = t.TimeZone.Hours != t.Well!.Timezone.Hours ? t.Well.Timezone : t.TimeZone;
+
+ return t;
+ });
+
+
+ var dtos = entities.Select(t => {
+ var dto = t.Adapt();
+ dto.IdWell = t.Well?.Id;
+
+ return dto;
+ });
+
+ return dtos;
}
public TelemetryDto GetOrCreateTelemetryByUid(string uid)
diff --git a/AsbCloudWebApi/Controllers/SAUB/MessageController.cs b/AsbCloudWebApi/Controllers/SAUB/MessageController.cs
index bc89b861..31bd4345 100644
--- a/AsbCloudWebApi/Controllers/SAUB/MessageController.cs
+++ b/AsbCloudWebApi/Controllers/SAUB/MessageController.cs
@@ -1,7 +1,10 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
+using AsbCloudDb.Model;
using Microsoft.AspNetCore.Mvc;
+using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -14,13 +17,18 @@ namespace AsbCloudWebApi.Controllers.SAUB;
[ApiController]
public class MessageController : ControllerBase
{
- private readonly IMessageService messageService;
+ private readonly IMessageRepository messageRepository;
private readonly IWellService wellService;
+ private readonly IMessageService messageService;
- public MessageController(IMessageService messageService, IWellService wellService)
+ public MessageController(
+ IMessageRepository messageRepository,
+ IWellService wellService,
+ IMessageService messageService)
{
- this.messageService = messageService;
+ this.messageRepository = messageRepository;
this.wellService = wellService;
+ this.messageService = messageService;
}
///
@@ -46,17 +54,22 @@ public class MessageController : ControllerBase
if (request.Take > 1024)
return this.ValidationBadRequest(nameof(request.Take), "limit mast be less then 1024");
- var requestToService = new MessageRequest(request, idWell);
-
- var result = await messageService.GetMessagesAsync(
- requestToService,
- token)
- .ConfigureAwait(false);
+ var messageRequest = new MessageRequest(request, new int[] { idWell });
+ var result = await messageService.GetPaginatedMessagesAsync(messageRequest, token);
if (result is null || result.Count == 0)
return NoContent();
return Ok(result);
+
+ }
+
+ [HttpGet("/api/serviceOperation/[controller]")]
+ [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)]
+ public async Task Get([FromQuery] MessageRequest request, CancellationToken token)
+ {
+ var result = await messageService.GetStatAsync(request, token);
+ return Ok(result);
}
///
diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs
index 0adbba81..c04b230c 100644
--- a/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs
+++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs
@@ -1,11 +1,11 @@
using AsbCloudApp.Data.SAUB;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudWebApi.SignalR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -20,21 +20,21 @@ namespace AsbCloudWebApi.Controllers.SAUB;
public class TelemetryController : ControllerBase
{
private readonly ITelemetryService telemetryService;
- private readonly IMessageService messageService;
- private readonly IEventService eventService;
+ private readonly IMessageRepository messageRepository;
+ private readonly IEventRepository eventRepository;
private readonly ITelemetryUserService telemetryUserService;
private readonly IHubContext telemetryHubContext;
public TelemetryController(
ITelemetryService telemetryService,
- IMessageService messageService,
- IEventService eventService,
+ IMessageRepository messageRepository,
+ IEventRepository eventRepository,
ITelemetryUserService telemetryUserService,
IHubContext telemetryHubContext)
{
this.telemetryService = telemetryService;
- this.messageService = messageService;
- this.eventService = eventService;
+ this.messageRepository = messageRepository;
+ this.eventRepository = eventRepository;
this.telemetryUserService = telemetryUserService;
this.telemetryHubContext = telemetryHubContext;
}
@@ -49,7 +49,7 @@ public class TelemetryController : ControllerBase
{
var from = DateTimeOffset.UtcNow.AddDays(-1);
var stream = await telemetryService.GetTelemetriesInfoByLastData(from, token);
- return File(stream, "text/csv", $"Software versions by active telemetries from {from :yy-MM-dd hh-mm}.csv");
+ return File(stream, "text/csv", $"Software versions by active telemetries from {from:yy-MM-dd hh-mm}.csv");
}
///
@@ -79,7 +79,7 @@ public class TelemetryController : ControllerBase
CancellationToken token)
{
var idWell = telemetryService.GetIdWellByTelemetryUid(uid);
- await messageService.InsertAsync(uid, dtos, token).ConfigureAwait(false);
+ await messageRepository.InsertAsync(uid, dtos, token).ConfigureAwait(false);
if (dtos.Any())
await Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}")
@@ -99,7 +99,7 @@ public class TelemetryController : ControllerBase
public async Task PostEventsAsync(string uid, [FromBody] List events,
CancellationToken token)
{
- await eventService.UpsertAsync(uid, events, token)
+ await eventRepository.UpsertAsync(uid, events, token)
.ConfigureAwait(false);
return Ok();
}