diff --git a/PARR.API/Contracts/V1/Requests/Queries/StatWorkloadTemplateReqportQuery.cs b/PARR.API/Contracts/V1/Requests/Queries/StatWorkloadTemplateReqportQuery.cs
new file mode 100644
index 00000000..53273ac1
--- /dev/null
+++ b/PARR.API/Contracts/V1/Requests/Queries/StatWorkloadTemplateReqportQuery.cs
@@ -0,0 +1,17 @@
+using PARR.Domain.Enums.Workload;
+
+namespace PARR.API.Contracts.V1.Requests.Queries
+{
+ public record StatWorkloadTemplateReqportQuery
+ {
+ ///
+ /// Тип дополнительно фильтра для работы (ЗО, РГ)
+ ///
+ public WorkloadJobSubfliterType? JobSubfilterType { get; init; }
+
+ ///
+ /// Значение дополнительного фильтра для работы
+ ///
+ public string? JobSubfilterValue { get; init; }
+ }
+}
diff --git a/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadReportResponse.cs b/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadReportResponse.cs
index 6d266c49..c7dac959 100644
--- a/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadReportResponse.cs
+++ b/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadReportResponse.cs
@@ -72,6 +72,8 @@ namespace PARR.API.Contracts.V1.Responses.Statistics
{
public required string Title { get; init; }
+ public Guid? ObjId { get; init; }
+
public required WorkloadSummaryResponse Summary { get; init; }
public required List DailyMetrics { get; init; }
diff --git a/PARR.API/Controllers/V1/Statistics/StatWorkloadTemplateController.cs b/PARR.API/Controllers/V1/Statistics/StatWorkloadTemplateController.cs
index b5b33e9a..b443fa5e 100644
--- a/PARR.API/Controllers/V1/Statistics/StatWorkloadTemplateController.cs
+++ b/PARR.API/Controllers/V1/Statistics/StatWorkloadTemplateController.cs
@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PARR.API.Contracts.V1;
using PARR.API.Contracts.V1.Requests.BaseRequests;
+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;
@@ -45,7 +46,14 @@ namespace PARR.API.Controllers.V1.Statistics
///
///
[HttpGet(ApiRoutes.StatWorkloadTemplate.GetWorkloadTemplateReport)]
- public async Task GetWorkloadTemplateReport([FromRoute] WorkloadTemplateReportType reportType, [FromRoute] string filter, [FromRoute] WorkloadTemplateReportState state, [FromRoute] DateOnly date, [FromQuery] TimeZoneOffsetClient offset)
+ public async Task GetWorkloadTemplateReport(
+ [FromRoute] WorkloadTemplateReportType reportType,
+ [FromRoute] string filter,
+ [FromRoute] WorkloadTemplateReportState state,
+ [FromRoute] DateOnly date,
+ [FromQuery] TimeZoneOffsetClient offset,
+ [FromQuery] StatWorkloadTemplateReqportQuery query
+ )
{
if (string.IsNullOrWhiteSpace(filter))
{
@@ -53,7 +61,13 @@ namespace PARR.API.Controllers.V1.Statistics
throw new ArgumentException(nameof(filter), "Не передано значение фильтра.");
}
- var report = await workloadService.GetTemplateReportAsync(reportType, filter, state, date, offset.TimeZoneOffset);
+ if (query.JobSubfilterType.HasValue && string.IsNullOrWhiteSpace(query.JobSubfilterValue))
+ {
+ logger.LogWarning("Не передано значение дополнительного фильтра для работы");
+ throw new ArgumentException(nameof(filter), "Не передано значение дополнительного фильтра для работы.");
+ }
+
+ var report = await workloadService.GetTemplateReportAsync(reportType, filter, state, date, offset.TimeZoneOffset, query.JobSubfilterType, query.JobSubfilterValue);
var response = mapper.Map>(report);
diff --git a/PARR.Core/Services/Workload/Implementations/WorkloadService.cs b/PARR.Core/Services/Workload/Implementations/WorkloadService.cs
index 8f533012..07f98fe3 100644
--- a/PARR.Core/Services/Workload/Implementations/WorkloadService.cs
+++ b/PARR.Core/Services/Workload/Implementations/WorkloadService.cs
@@ -9,6 +9,7 @@ using PARR.Core.Services.TaskServices.Helpers;
using PARR.Core.Services.Workload.Interfaces;
using PARR.Core.Services.Workload.Models;
using PARR.Domain.DTOs.Workload;
+using PARR.Domain.Entities;
using PARR.Domain.Enums;
using PARR.Domain.Enums.Workload;
@@ -55,7 +56,6 @@ namespace PARR.Core.Services.Workload.Implementations
throw new ArgumentNullException(nameof(filterParam), $"Для отчета типа {reportType.ToString()} параметр является обязательным.");
}
-
// Если есть отчет в КЭШ, вернуть
var cacheReport = await workloadCacheService.GetWorkloadReportAsync(reportType, dateStart, durationDays, offset, filterParam);
if (cacheReport != null)
@@ -87,7 +87,7 @@ namespace PARR.Core.Services.Workload.Implementations
case WorkloadReportType.ResponseAreaAll:
displayName = "По зонам ответственности";
foreach (var group in templates.GroupBy(t => t.ResponseArea, StringComparer.OrdinalIgnoreCase))
- statistics.Add(BuildStatisticItem(group.Key, group, reportDays, offset));
+ statistics.Add(BuildStatisticItem(group.Key, null, group, reportDays, offset));
break;
case WorkloadReportType.ResponseAreaWorkGroups:
displayName = "По зоне ответственности";
@@ -95,13 +95,13 @@ namespace PARR.Core.Services.Workload.Implementations
var filteredRA = templates.Where(t => string.Equals(t.ResponseArea, filterParam, StringComparison.OrdinalIgnoreCase)).ToList();
// Группируем работы по РГ
foreach (var group in filteredRA.GroupBy(t => t.WorkGroup, StringComparer.OrdinalIgnoreCase))
- statistics.Add(BuildStatisticItem(group.Key, group, reportDays, offset));
+ statistics.Add(BuildStatisticItem(group.Key, null, group, reportDays, offset));
//statistics.Add(BuildStatisticItem(filterParam!, filteredRA, reportDays, offset));
break;
case WorkloadReportType.WorkGroupAll:
displayName = "По рабочим группам";
foreach (var group in templates.GroupBy(t => t.WorkGroup))
- statistics.Add(BuildStatisticItem(group.Key, group, reportDays, offset));
+ statistics.Add(BuildStatisticItem(group.Key, null, group, reportDays, offset));
break;
case WorkloadReportType.WorkGroupJob:
displayName = "По рабочей группе";
@@ -118,7 +118,7 @@ namespace PARR.Core.Services.Workload.Implementations
foreach (var group in filteredWG.GroupBy(t => t.JobId))
{
var jobName = jobs.GetValueOrDefault(group.Key) ?? "Работа";
- statistics.Add(BuildStatisticItem(jobName, group, reportDays, offset));
+ statistics.Add(BuildStatisticItem(jobName, group.Key, group, reportDays, offset));
}
break;
}
@@ -175,7 +175,15 @@ namespace PARR.Core.Services.Workload.Implementations
}
- public async Task> GetTemplateReportAsync(WorkloadTemplateReportType reportType, string filter, WorkloadTemplateReportState state, DateOnly date, TimeSpan offset)
+ public async Task> GetTemplateReportAsync(
+ WorkloadTemplateReportType reportType,
+ string filter,
+ WorkloadTemplateReportState state,
+ DateOnly date,
+ TimeSpan offset,
+ WorkloadJobSubfliterType? jobSubfilterType,
+ string? jobSubfilterValue
+ )
{
if (string.IsNullOrWhiteSpace(filter))
{
@@ -218,19 +226,16 @@ namespace PARR.Core.Services.Workload.Implementations
break;
}
- // Если тип - работы
+ // Если тип - работы, получим из бд сразу нужные работы
if (reportType == WorkloadTemplateReportType.Job)
{
if (!Guid.TryParse(trimmedFilter, out Guid jobId))
throw new ArgumentException("Значение фильтра не является Guid");
- return await query.Where(t => t.JobId == jobId)
- .OrderBy(t => t.Name)
- .Select(t => new WorkloadTemplateReport(t.Id, t.Name, t.NextRun, t.IsActiveTemplate, t.IsActiveSchedule))
- .ToListAsync();
+ query = query.Where(t => t.JobId == jobId);
}
- // Тип "не работы", загружаем шаблоны
+ // Загружаем шаблоны
var dbTemplates = await query.OrderBy(t => t.Name)
.Select(t => new WorkloadTemplateReport(t.Id, t.Name, t.NextRun, t.IsActiveTemplate, t.IsActiveSchedule))
.ToListAsync();
@@ -238,6 +243,13 @@ namespace PARR.Core.Services.Workload.Implementations
if (dbTemplates.Count == 0)
return new List();
+ // Если тип - работы, и нет дополнительных фильтров по ЗО или РГ, не полезем в кэш, вернем сразу
+ if (reportType == WorkloadTemplateReportType.Job && (!jobSubfilterType.HasValue || string.IsNullOrWhiteSpace(jobSubfilterValue)))
+ {
+ // Тут кэш не нужен, вернем сразу из бд (нет фильтров по РГ и ЗО, нужен список всех работ на дату)
+ return FilterWorkloadJobTemplateReport(dbTemplates, null);
+ }
+
// Получаем из кэша шаблоны (если их в кэше нет, догружаем в кэш)
var cacheData = await workloadCacheService.GetTemplateReportDataByIdsAsync(dbTemplates.Select(t => t.TemplateId).ToHashSet());
@@ -250,6 +262,30 @@ namespace PARR.Core.Services.Workload.Implementations
// Фильтр по типу
switch (reportType)
{
+ case WorkloadTemplateReportType.Job:
+ // Смотрим есть ли дополнительные фильтры
+ if (jobSubfilterType.HasValue && !string.IsNullOrWhiteSpace(jobSubfilterValue))
+ {
+ var cacheTemplatesJobs = new HashSet();
+ // Фильтруем из кэша
+ var trimmedJobSubfilterValue = jobSubfilterValue.Trim();
+ switch (jobSubfilterType)
+ {
+ case WorkloadJobSubfliterType.ResponseArea:
+ cacheTemplatesJobs = cacheData.Where(t => string.Equals(t.Data.ResponseArea, trimmedJobSubfilterValue, StringComparison.OrdinalIgnoreCase))
+ .Select(t => t.Data.TemplateId).ToHashSet();
+ break;
+ case WorkloadJobSubfliterType.WorkGroup:
+ cacheTemplatesJobs = cacheData.Where(t => string.Equals(t.Data.WorkGroup, trimmedJobSubfilterValue, StringComparison.OrdinalIgnoreCase))
+ .Select(t => t.Data.TemplateId).ToHashSet();
+ break;
+ default:
+ throw new ArgumentException("Неверный тип фильтра", nameof(jobSubfilterType));
+ }
+
+ return FilterWorkloadJobTemplateReport(dbTemplates, cacheTemplatesJobs);
+ }
+ return FilterWorkloadJobTemplateReport(dbTemplates, null);
case WorkloadTemplateReportType.WorkGroup:
var cacheTemplatesWg = cacheData.Where(t => string.Equals(t.Data.WorkGroup, trimmedFilter, StringComparison.OrdinalIgnoreCase))
.Select(t => t.Data.TemplateId).ToHashSet();
@@ -266,6 +302,16 @@ namespace PARR.Core.Services.Workload.Implementations
}
+ private List FilterWorkloadJobTemplateReport(List dbTemplates, HashSet? filteredCacheTemplates)
+ {
+ if (filteredCacheTemplates == null)
+ return dbTemplates;
+
+ // Отсекаем шаблоны которых нет в кэше
+ return dbTemplates.Where(t => filteredCacheTemplates.Contains(t.TemplateId)).ToList();
+ }
+
+
///
/// Получить список дней для отчета, с отметкой выходной/рабочий
///
@@ -347,12 +393,12 @@ namespace PARR.Core.Services.Workload.Implementations
///
///
///
- private WorkloadStatisticItem BuildStatisticItem(string title, IEnumerable groupTemplates, List reportDays, TimeSpan offset)
+ private WorkloadStatisticItem BuildStatisticItem(string title, Guid? objId, IEnumerable groupTemplates, List reportDays, TimeSpan offset)
{
var dailyMetrics = GetDailyMetrics(groupTemplates.ToList(), reportDays, offset);
var summary = GetSummary(dailyMetrics, reportDays.Count);
- return new WorkloadStatisticItem { DailyMetrics = dailyMetrics, Summary = summary, Title = title };
+ return new WorkloadStatisticItem { DailyMetrics = dailyMetrics, Summary = summary, Title = title, ObjId = objId };
}
}
}
diff --git a/PARR.Core/Services/Workload/Interfaces/IWorkloadService.cs b/PARR.Core/Services/Workload/Interfaces/IWorkloadService.cs
index f44595c4..12c905f3 100644
--- a/PARR.Core/Services/Workload/Interfaces/IWorkloadService.cs
+++ b/PARR.Core/Services/Workload/Interfaces/IWorkloadService.cs
@@ -33,8 +33,10 @@ namespace PARR.Core.Services.Workload.Interfaces
///
///
///
+ /// Дополнительный фильтр при отчете по шаблонам, тип
+ /// Дополнительный фильтр при отчете по шаблонам, значение
///
- Task> GetTemplateReportAsync(WorkloadTemplateReportType reportType, string filter, WorkloadTemplateReportState state, DateOnly date, TimeSpan offset);
+ Task> GetTemplateReportAsync(WorkloadTemplateReportType reportType, string filter, WorkloadTemplateReportState state, DateOnly date, TimeSpan offset, WorkloadJobSubfliterType? jobSubfilterType, string? jobSubfilterValue);
}
}
diff --git a/PARR.Domain/DTOs/Workload/WorkloadReport.cs b/PARR.Domain/DTOs/Workload/WorkloadReport.cs
index e3956864..862577ab 100644
--- a/PARR.Domain/DTOs/Workload/WorkloadReport.cs
+++ b/PARR.Domain/DTOs/Workload/WorkloadReport.cs
@@ -73,6 +73,12 @@ namespace PARR.Domain.DTOs.Workload
{
public required string Title { get; init; }
+ ///
+ /// ИД строки, если есть.
+ /// Например JobId
+ ///
+ public Guid? ObjId { get; init; }
+
public required WorkloadSummary Summary { get; init; }
public required List DailyMetrics { get; init; }
diff --git a/PARR.Domain/Enums/Workload/WorkloadJobSubfliterType.cs b/PARR.Domain/Enums/Workload/WorkloadJobSubfliterType.cs
new file mode 100644
index 00000000..0d0954f0
--- /dev/null
+++ b/PARR.Domain/Enums/Workload/WorkloadJobSubfliterType.cs
@@ -0,0 +1,22 @@
+using System.Text.Json.Serialization;
+
+namespace PARR.Domain.Enums.Workload
+{
+ ///
+ /// Дополнительный фильтр для работ.
+ /// Отчет Workload, шаблоны
+ ///
+ [JsonConverter(typeof(JsonStringEnumConverter))]
+ public enum WorkloadJobSubfliterType
+ {
+ ///
+ /// ЗО
+ ///
+ ResponseArea = 0,
+
+ ///
+ /// РГ
+ ///
+ WorkGroup=1
+ }
+}