diff --git a/PARR.API/Contracts/V1/ApiRoutes.cs b/PARR.API/Contracts/V1/ApiRoutes.cs
index ce4b5288..870afec2 100644
--- a/PARR.API/Contracts/V1/ApiRoutes.cs
+++ b/PARR.API/Contracts/V1/ApiRoutes.cs
@@ -22,6 +22,11 @@ namespace PARR.API.Contracts.V1
public const string Base = Root + "/" + Version;
+ ///
+ /// Статистика
+ ///
+ public const string BaseStat = Base + "/statistics";
+
public static class ApiStatus
{
public const string Version = Base + "/version";
@@ -160,6 +165,20 @@ namespace PARR.API.Contracts.V1
#endregion
+ #region Статистика
+
+ public static class StatRobotTask
+ {
+ public const string Get = BaseStat + "/robot-tasks/";
+ }
+
+ public static class StatRobotStatus
+ {
+ public const string Get = BaseStat + "/robot-statuses/";
+ }
+
+ #endregion
+
}
}
diff --git a/PARR.API/Contracts/V1/Responses/Statistics/StatRobotStatusResponse.cs b/PARR.API/Contracts/V1/Responses/Statistics/StatRobotStatusResponse.cs
new file mode 100644
index 00000000..ffab340b
--- /dev/null
+++ b/PARR.API/Contracts/V1/Responses/Statistics/StatRobotStatusResponse.cs
@@ -0,0 +1,14 @@
+namespace PARR.API.Contracts.V1.Responses.Statistics
+{
+ public class StatRobotStatusResponse
+ {
+ public RobotResponse? Robot { get; set; }
+ public List Statistics { get; set; } = new List();
+ }
+
+ public class StatRobotStatusItemResponse
+ {
+ public RobotStatusResponse? Status { get; set; }
+ public int Count { get; set; }
+ }
+}
diff --git a/PARR.API/Contracts/V1/Responses/Statistics/StatRobotTaskResponse.cs b/PARR.API/Contracts/V1/Responses/Statistics/StatRobotTaskResponse.cs
new file mode 100644
index 00000000..a3455675
--- /dev/null
+++ b/PARR.API/Contracts/V1/Responses/Statistics/StatRobotTaskResponse.cs
@@ -0,0 +1,14 @@
+namespace PARR.API.Contracts.V1.Responses.Statistics
+{
+ public class StatRobotTaskResponse
+ {
+ public RobotResponse? Robot { get; set; }
+ public List Statistics { get; set; } = new List();
+ }
+
+ public class StatRobotTasksResponse
+ {
+ public TaskStatusResponse? Status { get; set; }
+ public int Count { get; set; }
+ }
+}
diff --git a/PARR.API/Controllers/V1/Statistics/StatRobotStatusController.cs b/PARR.API/Controllers/V1/Statistics/StatRobotStatusController.cs
new file mode 100644
index 00000000..9d57f9f6
--- /dev/null
+++ b/PARR.API/Controllers/V1/Statistics/StatRobotStatusController.cs
@@ -0,0 +1,76 @@
+using AutoMapper;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using PARR.API.Contracts.V1;
+using PARR.API.Contracts.V1.Responses;
+using PARR.API.Contracts.V1.Responses.Base;
+using PARR.API.Contracts.V1.Responses.Statistics;
+using PARR.API.Controllers.V1.Base;
+using PARR.Constants;
+using PARR.DAL.Services.Interfaces;
+
+namespace PARR.API.Controllers.V1.Statistics
+{
+ ///
+ /// Статистика выполняения заданий роботами, по полю RobotConfigurations.RobotStatusCode
+ ///
+ [Authorize(Roles = ParrRoles.Administrator.Role)]
+ public class StatRobotStatusController : BaseApiController
+ {
+ private readonly IRobotService robotService;
+ private readonly IRobotConfigurationService robotConfigurationService;
+ private readonly IRobotStatusService robotStatusService;
+ private readonly IMapper mapper;
+
+ public StatRobotStatusController(
+ IRobotService robotService,
+ IRobotConfigurationService robotConfigurationService,
+ IRobotStatusService robotStatusService,
+ IMapper mapper
+ )
+ {
+ this.robotService = robotService;
+ this.robotConfigurationService = robotConfigurationService;
+ this.robotStatusService = robotStatusService;
+ this.mapper = mapper;
+ }
+
+ ///
+ /// Статистика работы роботов
+ ///
+ ///
+ [HttpGet(ApiRoutes.StatRobotStatus.Get)]
+ public async Task Get()
+ {
+ var confStat = await robotConfigurationService.Get()
+ .GroupBy(t => new { t.RobotCode, t.RobotStatusCode })
+ .Select(t => new { RobotCode = t.Key.RobotCode, RobotStatusCode = t.Key.RobotStatusCode, Count = t.Count() })
+ .ToListAsync();
+
+ var robots = await robotService.Get().ToListAsync();
+ var robotStatuses = await robotStatusService.Get().ToListAsync();
+
+ var response = new List();
+
+ foreach (var robot in robots)
+ {
+ var item = new StatRobotStatusResponse { Robot = mapper.Map(robot) };
+ robotStatuses.ForEach(stat =>
+ {
+ item.Statistics.Add(new StatRobotStatusItemResponse
+ {
+ Status = mapper.Map(stat),
+ Count = confStat.FirstOrDefault(t => t.RobotStatusCode == stat.Code && t.RobotCode == robot.Code)?.Count ?? 0
+ });
+ });
+ item.Statistics = item.Statistics.OrderByDescending(t => t.Status?.Code).ToList();
+ response.Add(item);
+ }
+
+ response = response.OrderBy(t => t.Robot?.Code).ToList();
+
+ return Ok(new Response>(response, true));
+ }
+ }
+}
diff --git a/PARR.API/Controllers/V1/Statistics/StatRobotTaskController.cs b/PARR.API/Controllers/V1/Statistics/StatRobotTaskController.cs
new file mode 100644
index 00000000..4bd26c13
--- /dev/null
+++ b/PARR.API/Controllers/V1/Statistics/StatRobotTaskController.cs
@@ -0,0 +1,76 @@
+using AutoMapper;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using PARR.API.Contracts.V1;
+using PARR.API.Contracts.V1.Responses;
+using PARR.API.Contracts.V1.Responses.Base;
+using PARR.API.Contracts.V1.Responses.Statistics;
+using PARR.API.Controllers.V1.Base;
+using PARR.Constants;
+using PARR.DAL.Services.Interfaces;
+
+namespace PARR.API.Controllers.V1.Statistics
+{
+ ///
+ /// Статистика по заданиям для робота, по полю RobotConfigurations.TaskStatusCode
+ ///
+ [Authorize(Roles = ParrRoles.Administrator.Role)]
+ public class StatRobotTaskController : BaseApiController
+ {
+ private readonly IRobotService robotService;
+ private readonly IRobotConfigurationService robotConfigurationService;
+ private readonly ITaskStatusService taskStatusService;
+ private readonly IMapper mapper;
+
+ public StatRobotTaskController(
+ IRobotService robotService,
+ IRobotConfigurationService robotConfigurationService,
+ ITaskStatusService taskStatusService,
+ IMapper mapper
+ )
+ {
+ this.robotService = robotService;
+ this.robotConfigurationService = robotConfigurationService;
+ this.taskStatusService = taskStatusService;
+ this.mapper = mapper;
+ }
+
+ ///
+ /// Статистика по заданиям для роботов
+ ///
+ ///
+ [HttpGet(ApiRoutes.StatRobotTask.Get)]
+ public async Task Get()
+ {
+ var confStat = await robotConfigurationService.Get()
+ .GroupBy(t => new { t.RobotCode, t.TaskStatusCode })
+ .Select(t => new { RobotCode = t.Key.RobotCode, TaskStatusCode = t.Key.TaskStatusCode, Count = t.Count() })
+ .ToListAsync();
+
+ var robots = await robotService.Get().ToListAsync();
+ var statuses = await taskStatusService.Get().ToListAsync();
+
+ var response = new List();
+
+ foreach (var robot in robots)
+ {
+ var item = new StatRobotTaskResponse { Robot = mapper.Map(robot) };
+ statuses.ForEach(stat =>
+ {
+ item.Statistics.Add(new StatRobotTasksResponse
+ {
+ Status = mapper.Map(stat),
+ Count = confStat.FirstOrDefault(t => t.TaskStatusCode == stat.Code && t.RobotCode == robot.Code)?.Count ?? 0
+ });
+ });
+ item.Statistics = item.Statistics.OrderBy(t => t.Status?.Code).ToList();
+ response.Add(item);
+ }
+
+ response = response.OrderBy(t => t.Robot?.Code).ToList();
+
+ return Ok(new Response>(response, true));
+ }
+ }
+}
diff --git a/PARR.DAL/ParrDalInstaller.cs b/PARR.DAL/ParrDalInstaller.cs
index 851fd9cc..8ef0c90c 100644
--- a/PARR.DAL/ParrDalInstaller.cs
+++ b/PARR.DAL/ParrDalInstaller.cs
@@ -64,6 +64,7 @@ namespace PARR.DAL
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
// TransformServices
services.AddTransient();
diff --git a/PARR.DAL/Services/Implementations/TaskStatusService.cs b/PARR.DAL/Services/Implementations/TaskStatusService.cs
new file mode 100644
index 00000000..21f10faf
--- /dev/null
+++ b/PARR.DAL/Services/Implementations/TaskStatusService.cs
@@ -0,0 +1,20 @@
+using PARR.DAL.Context;
+using PARR.DAL.Services.Interfaces;
+
+namespace PARR.DAL.Services.Implementations
+{
+ internal class TaskStatusService : ITaskStatusService
+ {
+ private readonly DataContext dataContext;
+
+ public TaskStatusService(DataContext dataContext)
+ {
+ this.dataContext = dataContext;
+ }
+
+ public IQueryable Get()
+ {
+ return dataContext.TaskStatuses;
+ }
+ }
+}
diff --git a/PARR.DAL/Services/Interfaces/ITaskStatusService.cs b/PARR.DAL/Services/Interfaces/ITaskStatusService.cs
new file mode 100644
index 00000000..bb4d330d
--- /dev/null
+++ b/PARR.DAL/Services/Interfaces/ITaskStatusService.cs
@@ -0,0 +1,7 @@
+namespace PARR.DAL.Services.Interfaces
+{
+ public interface ITaskStatusService
+ {
+ IQueryable Get();
+ }
+}