diff --git a/PARR.API/Contracts/V1/ApiRoutes.cs b/PARR.API/Contracts/V1/ApiRoutes.cs
index 4c2a5934..fa684666 100644
--- a/PARR.API/Contracts/V1/ApiRoutes.cs
+++ b/PARR.API/Contracts/V1/ApiRoutes.cs
@@ -258,6 +258,7 @@
public static class StatRobotSnapshot
{
+ public const string GetAll = BaseStat + "/robot-snapshots/";
public const string Create = BaseStat + "/robot-snapshots/";
}
diff --git a/PARR.API/Contracts/V1/Requests/Queries/StatRobotSnapshotQuery.cs b/PARR.API/Contracts/V1/Requests/Queries/StatRobotSnapshotQuery.cs
new file mode 100644
index 00000000..df565d1a
--- /dev/null
+++ b/PARR.API/Contracts/V1/Requests/Queries/StatRobotSnapshotQuery.cs
@@ -0,0 +1,15 @@
+namespace PARR.API.Contracts.V1.Requests.Queries
+{
+ public record StatRobotSnapshotQuery
+ {
+ ///
+ /// IP робота
+ ///
+ public string? Ip { get; init; }
+
+ ///
+ /// Кол-во минут от текущего времени, по умолчнию 12 часов.
+ ///
+ public int Minutes { get; init; } = 12 * 60;
+ }
+}
diff --git a/PARR.API/Contracts/V1/Responses/Statistics/StatRobotSnapshotItemResponse.cs b/PARR.API/Contracts/V1/Responses/Statistics/StatRobotSnapshotItemResponse.cs
index 33731241..4893d44b 100644
--- a/PARR.API/Contracts/V1/Responses/Statistics/StatRobotSnapshotItemResponse.cs
+++ b/PARR.API/Contracts/V1/Responses/Statistics/StatRobotSnapshotItemResponse.cs
@@ -1,6 +1,13 @@
namespace PARR.API.Contracts.V1.Responses.Statistics
{
public record StatRobotSnapshotItemResponse
+ {
+ public required UserBaseResponse Robot { get; init; }
+
+ public List Snapshots { get; init; } = new();
+ }
+
+ public record StatRobotSnapshotResponse
{
public Guid Id { get; init; }
@@ -11,7 +18,5 @@
public int ScheduleRobotsCount { get; init; }
public int MaxRobots { get; init; }
-
- public required string Ip { get; init; }
}
}
diff --git a/PARR.API/Controllers/V1/Statistics/StatRobotSnapshotController.cs b/PARR.API/Controllers/V1/Statistics/StatRobotSnapshotController.cs
index 30baad32..7ef8d895 100644
--- a/PARR.API/Controllers/V1/Statistics/StatRobotSnapshotController.cs
+++ b/PARR.API/Controllers/V1/Statistics/StatRobotSnapshotController.cs
@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PARR.API.Contracts.V1;
using PARR.API.Contracts.V1.Requests;
+using PARR.API.Contracts.V1.Requests.Queries;
using PARR.API.Contracts.V1.Responses.Base;
using PARR.API.Contracts.V1.Responses.Statistics;
using PARR.API.Controllers.V1.Base;
@@ -13,7 +14,7 @@ using PARR.Domain.DTOs.RobotSnapshotDTO;
namespace PARR.API.Controllers.V1.Statistics
{
- [Authorize(Roles = ParrRoles.Administrator.Role)]
+ [Authorize]
public class StatRobotSnapshotController : BaseApiController
{
private readonly IRobotSnapshotService robotSnapshotService;
@@ -31,6 +32,28 @@ namespace PARR.API.Controllers.V1.Statistics
this.clientService = clientService;
}
+
+ ///
+ /// Получить снапшоты роботов.
+ ///
+ ///
+ [Authorize(Roles = ParrRoles.Administrator.Role)]
+ [HttpGet(ApiRoutes.StatRobotSnapshot.GetAll)]
+ public async Task GetAll([FromQuery] StatRobotSnapshotQuery query)
+ {
+ var queryDto = mapper.Map(query);
+
+ var snapshots = await robotSnapshotService.GetAsync(queryDto);
+
+ if (snapshots.Count == 0)
+ return NoContent();
+
+ var response = mapper.Map>(snapshots);
+
+ return Ok(new Response>(response, true));
+ }
+
+
///
/// Отправить снапшот роботов.
/// Доступ только с ролью "Робот ЕСПП"
diff --git a/PARR.API/MappingProfiles/DomainToResponseProfile.cs b/PARR.API/MappingProfiles/DomainToResponseProfile.cs
index 46672b21..73287145 100644
--- a/PARR.API/MappingProfiles/DomainToResponseProfile.cs
+++ b/PARR.API/MappingProfiles/DomainToResponseProfile.cs
@@ -9,6 +9,7 @@ using PARR.Domain.DTOs.RobotSnapshotDTO;
using PARR.Domain.DTOs.RobotTask;
using PARR.Domain.DTOs.Shortcode;
using PARR.Domain.DTOs.TaskDTO;
+using PARR.Domain.DTOs.User;
using PARR.Domain.DTOs.Workload;
using PARR.Domain.Entities;
using PARR.Domain.Entities.Base.History;
@@ -312,6 +313,8 @@ namespace PARR.API.MappingProfiles
CreateMap();
+ CreateMap();
+
#endregion
#region Order
@@ -486,8 +489,13 @@ namespace PARR.API.MappingProfiles
#endregion
+ #region RobotSnapshot
- CreateMap();
+ CreateMap();
+
+ CreateMap();
+
+ #endregion
}
}
diff --git a/PARR.API/MappingProfiles/RequestToDomainProfile.cs b/PARR.API/MappingProfiles/RequestToDomainProfile.cs
index 6a2c5b9b..1278a3ed 100644
--- a/PARR.API/MappingProfiles/RequestToDomainProfile.cs
+++ b/PARR.API/MappingProfiles/RequestToDomainProfile.cs
@@ -2,6 +2,7 @@
using PARR.API.Contracts.V1.Requests;
using PARR.API.Contracts.V1.Requests.Queries;
using PARR.Domain.Common.Pagination;
+using PARR.Domain.DTOs.RobotSnapshotDTO;
using PARR.Domain.Entities.Job;
namespace PARR.API.MappingProfiles
@@ -45,6 +46,8 @@ namespace PARR.API.MappingProfiles
CreateMap();
#endregion
+
+ CreateMap();
}
}
}
diff --git a/PARR.Core/Infrastructure/Mapping/RobotSnapshot/RobotSnapshotMappingProfile.cs b/PARR.Core/Infrastructure/Mapping/RobotSnapshot/RobotSnapshotMappingProfile.cs
index 56ebf523..81e547c6 100644
--- a/PARR.Core/Infrastructure/Mapping/RobotSnapshot/RobotSnapshotMappingProfile.cs
+++ b/PARR.Core/Infrastructure/Mapping/RobotSnapshot/RobotSnapshotMappingProfile.cs
@@ -7,7 +7,7 @@ namespace PARR.Core.Infrastructure.Mapping.RobotSnapshot
{
public RobotSnapshotMappingProfile()
{
- CreateMap();
+ CreateMap();
}
}
}
diff --git a/PARR.Core/Services/RobotSnapshotServices/IRobotSnapshotService.cs b/PARR.Core/Services/RobotSnapshotServices/IRobotSnapshotService.cs
index 6582ed6a..6ac083f1 100644
--- a/PARR.Core/Services/RobotSnapshotServices/IRobotSnapshotService.cs
+++ b/PARR.Core/Services/RobotSnapshotServices/IRobotSnapshotService.cs
@@ -4,6 +4,8 @@ namespace PARR.Core.Services.RobotSnapshotServices
{
public interface IRobotSnapshotService
{
- Task CreateAsync(CreateRobotSnapshot robotSnapshot);
+ Task> GetAsync(RobotSnapshotQuery queryDto);
+
+ Task CreateAsync(CreateRobotSnapshot robotSnapshot);
}
}
diff --git a/PARR.Core/Services/RobotSnapshotServices/RobotSnapshotService.cs b/PARR.Core/Services/RobotSnapshotServices/RobotSnapshotService.cs
index c1ff0b9b..67738bc7 100644
--- a/PARR.Core/Services/RobotSnapshotServices/RobotSnapshotService.cs
+++ b/PARR.Core/Services/RobotSnapshotServices/RobotSnapshotService.cs
@@ -1,6 +1,9 @@
using AutoMapper;
+using Microsoft.EntityFrameworkCore;
+using PARR.Core.Repositories.Interfaces;
using PARR.Core.Repositories.Interfaces.RobotRepositories;
using PARR.Domain.DTOs.RobotSnapshotDTO;
+using PARR.Domain.DTOs.User;
using PARR.Domain.Entities.RobotEntities;
using PARR.Domain.Exceptions;
@@ -9,19 +12,63 @@ namespace PARR.Core.Services.RobotSnapshotServices
internal class RobotSnapshotService : IRobotSnapshotService
{
private readonly IRobotSnapshotRepository robotSnapshotRepository;
+ private readonly IUserRepository userRepository;
private readonly IMapper mapper;
public RobotSnapshotService(
IRobotSnapshotRepository robotSnapshotRepository,
+ IUserRepository userRepository,
IMapper mapper
)
{
this.robotSnapshotRepository = robotSnapshotRepository;
+ this.userRepository = userRepository;
this.mapper = mapper;
}
- public async Task CreateAsync(CreateRobotSnapshot robotSnapshot)
+ public async Task> GetAsync(RobotSnapshotQuery queryDto)
+ {
+ // Просто возвращаем данные из БД, не проверяем что есть промежутки между которыми не было данных
+ // Т.е это просто чтоб посмотреть что есть в БД
+
+ var minutes = queryDto.Minutes > 0 ? queryDto.Minutes : 60 * 12;
+
+ var dateEnd = DateTimeOffset.UtcNow;
+ var dateStart = dateEnd.AddMinutes(-minutes);
+
+ var query = robotSnapshotRepository.Get().AsNoTracking()
+ .Where(t => dateStart <= t.DateCreated && t.DateCreated <= dateEnd);
+
+ if (!string.IsNullOrEmpty(queryDto.Ip))
+ query = query.Where(t => t.Ip == queryDto.Ip);
+
+ var groupingSnapshots = (await query.ToListAsync()).GroupBy(t => t.Ip);
+
+
+ var robotIps = groupingSnapshots.Select(t => t.Key).ToHashSet();
+ var robotList = await userRepository.Get()
+ .AsNoTracking()
+ .Where(t => robotIps.Contains(t.Ip))
+ .ToDictionaryAsync(t => t.Ip);
+
+ var result = new List();
+
+ foreach (var item in groupingSnapshots)
+ {
+ robotList.TryGetValue(item.Key, out var robot);
+
+ var userDto = new UserBaseDto { Ip = item.Key, Description = robot?.Description ?? string.Empty, Name = robot?.Name ?? string.Empty };
+ var snapshots = mapper.Map>(item).OrderBy(t => t.DateCreated).ToList();
+
+ result.Add(new RobotSnapshotItemDto { Robot = userDto, Snapshots = snapshots });
+ }
+
+ return result.OrderBy(t => t.Robot.Ip).ThenBy(t => t.Robot.Name).ToList();
+ }
+
+
+ public async Task CreateAsync(CreateRobotSnapshot robotSnapshot)
{
var snapshot = new RobotSnapshot
{
@@ -38,7 +85,16 @@ namespace PARR.Core.Services.RobotSnapshotServices
if (!createdResult || !commitResult)
throw new DbErrorException("Ошибка сохранения в БД");
- return mapper.Map(snapshot);
+ var user = await userRepository.Get().AsNoTracking().FirstOrDefaultAsync(t => t.Ip == robotSnapshot.Ip);
+ var userDto = new UserBaseDto { Ip = robotSnapshot.Ip, Description = user?.Description ?? string.Empty, Name = user?.Name ?? string.Empty };
+
+ var result = new RobotSnapshotItemDto
+ {
+ Robot = userDto,
+ Snapshots = mapper.Map>(new List { snapshot })
+ };
+
+ return result;
}
diff --git a/PARR.Domain/DTOs/RobotSnapshotDTO/RobotSnapshotItem.cs b/PARR.Domain/DTOs/RobotSnapshotDTO/RobotSnapshotItem.cs
deleted file mode 100644
index 521d14c7..00000000
--- a/PARR.Domain/DTOs/RobotSnapshotDTO/RobotSnapshotItem.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace PARR.Domain.DTOs.RobotSnapshotDTO
-{
- public record RobotSnapshotItem
- {
- public Guid Id { get; init; }
-
- public DateTimeOffset DateCreated { get; init; }
-
- public int TemplateRobotsCount { get; init; }
-
- public int ScheduleRobotsCount { get; init; }
-
- public int MaxRobots { get; init; }
-
- public required string Ip { get; init; }
- }
-}
diff --git a/PARR.Domain/DTOs/RobotSnapshotDTO/RobotSnapshotItemDto.cs b/PARR.Domain/DTOs/RobotSnapshotDTO/RobotSnapshotItemDto.cs
new file mode 100644
index 00000000..8fc0c7f0
--- /dev/null
+++ b/PARR.Domain/DTOs/RobotSnapshotDTO/RobotSnapshotItemDto.cs
@@ -0,0 +1,26 @@
+
+
+using PARR.Domain.DTOs.User;
+
+namespace PARR.Domain.DTOs.RobotSnapshotDTO
+{
+ public record RobotSnapshotItemDto
+ {
+ public required UserBaseDto Robot { get; init; }
+
+ public List Snapshots { get; init; } = new();
+ }
+
+ public record RobotSnapshotDto
+ {
+ public Guid Id { get; init; }
+
+ public DateTimeOffset DateCreated { get; init; }
+
+ public int TemplateRobotsCount { get; init; }
+
+ public int ScheduleRobotsCount { get; init; }
+
+ public int MaxRobots { get; init; }
+ }
+}
diff --git a/PARR.Domain/DTOs/RobotSnapshotDTO/RobotSnapshotQuery.cs b/PARR.Domain/DTOs/RobotSnapshotDTO/RobotSnapshotQuery.cs
new file mode 100644
index 00000000..b45f0c0c
--- /dev/null
+++ b/PARR.Domain/DTOs/RobotSnapshotDTO/RobotSnapshotQuery.cs
@@ -0,0 +1,15 @@
+namespace PARR.Domain.DTOs.RobotSnapshotDTO
+{
+ public record RobotSnapshotQuery
+ {
+ ///
+ /// IP робота
+ ///
+ public string? Ip { get; init; }
+
+ ///
+ /// Кол-во минут от текущего времени
+ ///
+ public int Minutes { get; init; }
+ }
+}
diff --git a/PARR.Domain/DTOs/User/UserDto.cs b/PARR.Domain/DTOs/User/UserDto.cs
new file mode 100644
index 00000000..b8e03875
--- /dev/null
+++ b/PARR.Domain/DTOs/User/UserDto.cs
@@ -0,0 +1,25 @@
+namespace PARR.Domain.DTOs.User
+{
+ //todo: Не делал маппингов
+
+ public record UserDto : UserBaseDto
+ {
+ public Guid Id { get; set; }
+
+ public DateTimeOffset DateCreated { get; set; }
+
+ public DateTimeOffset? LastLogon { get; set; }
+
+ //todo:
+ //public List? Roles { get; set; }
+ }
+
+ public record UserBaseDto
+ {
+ public required string Ip { get; set; }
+
+ public string Name { get; set; } = string.Empty;
+
+ public string Description { get; set; } = string.Empty;
+ }
+}