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