diff --git a/PARR.API/Contracts/V1/ApiRoutes.cs b/PARR.API/Contracts/V1/ApiRoutes.cs index f4b6d161..d75ef393 100644 --- a/PARR.API/Contracts/V1/ApiRoutes.cs +++ b/PARR.API/Contracts/V1/ApiRoutes.cs @@ -311,6 +311,11 @@ public const string ReportInfo = BaseStat + "/workload/report-info"; } + public static class StatWorkloadTemplate + { + public const string GetWorkloadTemplateReport = BaseStat + "/workload/templates/{reportType}/{filter}/{state}/{date}"; + } + #endregion #region Наряды diff --git a/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadReportResponse.cs b/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadReportResponse.cs index 560cf3e4..6d266c49 100644 --- a/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadReportResponse.cs +++ b/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadReportResponse.cs @@ -1,4 +1,4 @@ -using PARR.Domain.Enums; +using PARR.Domain.Enums.Workload; namespace PARR.API.Contracts.V1.Responses.Statistics { diff --git a/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadTemplateReportResponse.cs b/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadTemplateReportResponse.cs new file mode 100644 index 00000000..95acebbc --- /dev/null +++ b/PARR.API/Contracts/V1/Responses/Statistics/StatWorkloadTemplateReportResponse.cs @@ -0,0 +1,4 @@ +namespace PARR.API.Contracts.V1.Responses.Statistics +{ + public record StatWorkloadTemplateReportResponse(Guid TemplateId, string Name, DateTimeOffset NextRun, bool IsActiveTemplate, bool IsActiveSchedule); +} diff --git a/PARR.API/Controllers/V1/Statistics/StatWorkGroupWorkLoadController.cs b/PARR.API/Controllers/V1/Statistics/StatWorkGroupWorkLoadController.cs deleted file mode 100644 index 9fe2a151..00000000 --- a/PARR.API/Controllers/V1/Statistics/StatWorkGroupWorkLoadController.cs +++ /dev/null @@ -1,142 +0,0 @@ -using AutoMapper; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using PARR.API.Contracts.V1; -using PARR.API.Contracts.V1.Requests; -using PARR.API.Contracts.V1.Requests.Queries; -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.API.Services.Interfaces; -using PARR.Core.Repositories.Interfaces; - -namespace PARR.API.Controllers.V1.Statistics -{ - /// - /// Статистика загрузки регламентными работами по рабочим группам - /// - public class StatWorkGroupWorkLoadController : BaseApiController - { - private readonly ITemplateRepository templateService; - //private readonly IWorkLoadService workLoadService; - //private readonly IWorkGroupService workGroupService; - private readonly IMapper mapper; - private readonly ILogger logger; - - public StatWorkGroupWorkLoadController( - ITemplateRepository templateService, - //IWorkLoadService workLoadService, - //IWorkGroupService workGroupService, - IMapper mapper, - ILogger logger - ) - { - this.templateService = templateService; - //this.workLoadService = workLoadService; - //this.workGroupService = workGroupService; - this.mapper = mapper; - this.logger = logger; - } - - /* - /// - /// Статистика загрузки регламентными работами рабочих групп по ЗО - /// - /// - /// - /// - [HttpGet(ApiRoutes.StatWorkGroupWorkLoad.Get)] - public async Task Get([FromRoute] int responseAreaCode, [FromQuery] WorkloadBaseQuery requestQuery) - { - var response = await GetStatisticsAsync(responseAreaCode, requestQuery); - - return Ok(new Response>(response, true)); - } - - - /// - /// Статистика загрузки РГ по списку РГ - /// - /// - [HttpPost(ApiRoutes.StatWorkGroupWorkLoad.GetByWorkGroups)] - public async Task GetByWorkGroups([FromBody] StatWorkGroupsWorkLoadRequest request) - { - var response = await GetStatisticsAsync(null, request.Filter, request.WorkGroups); - - return Ok(new Response>(response, true)); - } - - - private async Task> GetStatisticsAsync(int? responseAreaCode, WorkloadBaseQuery requestQuery, List? workGroups = null) - { - //защита от дурака, чтоб не выгрузить всю БД - if (responseAreaCode == null && (workGroups == null || workGroups.Count() == 0)) - { - logger.LogWarning($"Пытались выполнить запрос получения статситики с нулевыми параметрами {nameof(responseAreaCode)}, {nameof(workGroups)}. Controller {nameof(StatWorkGroupWorkLoadController)}"); - return new List(); - } - - - var daysList = workLoadService.GetDatesForPeriod(requestQuery); - - IQueryable query = templateService.Get() - .Include(t => t.Host); - - query = workLoadService.FilterTemplatesQuery(query, requestQuery); - - if (responseAreaCode.HasValue) - query = query.Where(t => t.Host!.WorkGroup!.ResponseAreaCode == responseAreaCode.Value); - - if (workGroups != null && workGroups.Count() > 0) - query = query.Where(t => workGroups.Any(x => x == t.Host!.WorkGroupId.Value)); - - - // var groupedQuery = query.GroupBy(t => new { t.NextRun.DateTime.Date, t.Host!.WorkGroupId }) - var groupedQuery = query.GroupBy(t => new { t.NextRun.AddHours(requestQuery.TimeZoneOffsetHours).DateTime.Date, t.Host!.WorkGroupId }) - .Select(t => new - { - WorkGroupId = t.Key.WorkGroupId, - Date = t.Key.Date, - TemplateCount = t.Count() - }); - - var queryResult = await groupedQuery.ToListAsync(); - - - IQueryable workGroupsQuery = workGroupService.Get() - .Include(t => t.ResponseArea); - - if (responseAreaCode.HasValue) - workGroupsQuery = workGroupsQuery.Where(t => t.ResponseAreaCode == responseAreaCode); - - if (workGroups != null && workGroups.Count() > 0) - workGroupsQuery = workGroupsQuery.Where(t => workGroups.Any(x => x == t.Id)); - - - var allWorkGroups = await workGroupsQuery.ToListAsync(); - - var response = new List(); - - allWorkGroups.ForEach(wg => - { - var workLoads = daysList.Select(t => new StatWorkLoadDataResponse - { - Date = t, - TemplateCount = queryResult.FirstOrDefault(x => x.WorkGroupId == wg.Id && DateOnly.FromDateTime(x.Date) == t)?.TemplateCount ?? 0 - }).OrderBy(t => t.Date).ToList(); - - response.Add(new StatWorkGroupWorkLoadResponse - { - WorkGroup = mapper.Map(wg), - WorkLoad = workLoads - }); - }); - - response = response.OrderBy(t => t.WorkGroup.Name).ToList(); - - return response; - } - */ - } -} diff --git a/PARR.API/Controllers/V1/Statistics/StatWorkloadController.cs b/PARR.API/Controllers/V1/Statistics/StatWorkloadController.cs index fe83179c..ed47af74 100644 --- a/PARR.API/Controllers/V1/Statistics/StatWorkloadController.cs +++ b/PARR.API/Controllers/V1/Statistics/StatWorkloadController.cs @@ -14,8 +14,8 @@ using PARR.Core.Services.Workload.Interfaces; using PARR.Domain.Common.Roles; using PARR.Domain.Entities.Base.History; using PARR.Domain.Enums; +using PARR.Domain.Enums.Workload; using PARR.Domain.Exceptions; -using static PARR.API.Contracts.V1.ApiRoutes; namespace PARR.API.Controllers.V1.Statistics { @@ -153,7 +153,7 @@ namespace PARR.API.Controllers.V1.Statistics var localTime = utcNow.ToOffset(offset); var dateStart = DateOnly.FromDateTime(localTime.Date); - var report = await workloadService.GetWorkloadReport(reportType, dateStart, durationDays, offset, filter?.Trim()); + var report = await workloadService.GetWorkloadReportAsync(reportType, dateStart, durationDays, offset, filter?.Trim()); if (report == null) return BadRequest(new Response(null, false, new List { new ErrorModel { Message = "Необходимо сформировать отчетность." } }, "empty")); diff --git a/PARR.API/Controllers/V1/Statistics/StatWorkloadTemplateController.cs b/PARR.API/Controllers/V1/Statistics/StatWorkloadTemplateController.cs new file mode 100644 index 00000000..b5b33e9a --- /dev/null +++ b/PARR.API/Controllers/V1/Statistics/StatWorkloadTemplateController.cs @@ -0,0 +1,65 @@ +using AutoMapper; +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.Responses.Base; +using PARR.API.Contracts.V1.Responses.Statistics; +using PARR.API.Controllers.V1.Base; +using PARR.Core.Services.Workload.Interfaces; +using PARR.Domain.Common.Roles; +using PARR.Domain.Enums.Workload; + +namespace PARR.API.Controllers.V1.Statistics +{ + /// + /// Статситика загруженности - шаблоны + /// + [Authorize(Roles = ParrRoles.EsppRobot.RoleOrAdmin)] + public class StatWorkloadTemplateController : BaseApiController + { + private readonly IMapper mapper; + private readonly IWorkloadService workloadService; + private readonly ILogger logger; + + public StatWorkloadTemplateController( + IMapper mapper, + IWorkloadService workloadService, + ILogger logger + ) + { + this.mapper = mapper; + this.workloadService = workloadService; + this.logger = logger; + } + + + /// + /// Отчет о загруженности. Шаблоны + /// + /// + /// + /// + /// + /// + /// + /// + [HttpGet(ApiRoutes.StatWorkloadTemplate.GetWorkloadTemplateReport)] + public async Task GetWorkloadTemplateReport([FromRoute] WorkloadTemplateReportType reportType, [FromRoute] string filter, [FromRoute] WorkloadTemplateReportState state, [FromRoute] DateOnly date, [FromQuery] TimeZoneOffsetClient offset) + { + if (string.IsNullOrWhiteSpace(filter)) + { + logger.LogWarning("Не передано значение фильтра"); + throw new ArgumentException(nameof(filter), "Не передано значение фильтра."); + } + + var report = await workloadService.GetTemplateReportAsync(reportType, filter, state, date, offset.TimeZoneOffset); + + var response = mapper.Map>(report); + + return Ok(new Response>(response, true)); + } + + + } +} diff --git a/PARR.API/MappingProfiles/DomainToResponseProfile.cs b/PARR.API/MappingProfiles/DomainToResponseProfile.cs index 5735968c..f71c1276 100644 --- a/PARR.API/MappingProfiles/DomainToResponseProfile.cs +++ b/PARR.API/MappingProfiles/DomainToResponseProfile.cs @@ -460,6 +460,12 @@ namespace PARR.API.MappingProfiles #endregion + #region StatWorkloadTemplate + + CreateMap(); + + #endregion + #region Task diff --git a/PARR.Core/Services/Workload/Implementations/WorkloadCacheService.cs b/PARR.Core/Services/Workload/Implementations/WorkloadCacheService.cs index 7f384ae5..812d89db 100644 --- a/PARR.Core/Services/Workload/Implementations/WorkloadCacheService.cs +++ b/PARR.Core/Services/Workload/Implementations/WorkloadCacheService.cs @@ -6,9 +6,10 @@ using PARR.Core.Services.Shortcodes; using PARR.Core.Services.Workload.Models; using PARR.Domain.Cache; using PARR.Domain.Cache.Models; +using PARR.Domain.DTOs.UnitDto; using PARR.Domain.DTOs.Workload; using PARR.Domain.Entities; -using PARR.Domain.Enums; +using PARR.Domain.Enums.Workload; namespace PARR.Core.Services.Workload.Implementations { @@ -175,6 +176,47 @@ namespace PARR.Core.Services.Workload.Implementations await redisCacheService.DeleteKeysByPatternAsync(redisCacheService.GetKey(CacheKeys.Workload.WorkloadWorkGroupItem()) + "*"); } + + /// + /// Получить список шаблонов по ИД из кэш/бд. + /// Если каких то данных не хватает в кэше, дополнить кэш. + /// + /// + /// + public async Task?> GetTemplateReportDataByIdsAsync(IReadOnlySet templateIds) + { + if (templateIds == null || templateIds.Count == 0) + return null; + + // Формируем ключи + var keys = templateIds.Select(t => + { + var (hashKey, fieldKey) = (redisCacheService.GetKey(CacheKeys.Workload.TemplateHash()), redisCacheService.GetKey(CacheKeys.Workload.Template(t))); + return (HashKey: hashKey, FieldKey: fieldKey); + }).ToList(); + + // Получаем из кэш + var cacheData = await redisCacheService.GetHashFieldsAsync(keys); + + var resultDictionary = cacheData.ToDictionary(t => t.Data.TemplateId, t => t); + + if (resultDictionary.Count < templateIds.Count) + { + // Догружаем недостающие данные + // Находим id которых нет в кэше + var missingIds = templateIds.Where(id => !resultDictionary.ContainsKey(id)).ToHashSet(); + + foreach (var templateId in missingIds) + { + var newCacheItem = await GetTemplatePropsAsync(templateId); + resultDictionary[templateId] = newCacheItem; + } + } + + return resultDictionary.Select(t => t.Value).ToList(); + } + + /// /// Получить кэш РГ и ЗО всех шаблонов, получить недостающие поля из БД. /// Сравнит кол-во записей в БД и в КЭШ, если не хватает до 1000 шаблонов, доформирует кэш, @@ -196,14 +238,9 @@ namespace PARR.Core.Services.Workload.Implementations return null; } - // Сравним кол-во записей в БД и в КЭШ, вдруг там разница больше допустимой - var templatesCount = await templateRepository.Get().AsNoTracking().CountAsync(); - if (templatesCount - cacheData.Count > maxCacheDiff) - { - logger.LogInformation("Разница в количестве шаблонов в БД ({TemplateCount}) и в КЭШ ({CacheCount}) больше допустимой {MaxCacheDiff}. Считаем КЭШ неактуальным. Требуется повторное формирование КЭШа.", - templatesCount, cacheData.Count, maxCacheDiff); + // Кэш актуальный? + if (!await IsTemplateReportCacheActualAsync(cacheData.Count)) return null; - } // Получаем из БД только нужные данные для отчета, попадающие в интервал var dtStart = new DateTimeOffset(dateStart.Year, dateStart.Month, dateStart.Day, 0, 0, 0, offset); @@ -251,7 +288,11 @@ namespace PARR.Core.Services.Workload.Implementations } else { - (workGroup, responseArea, jobId) = await GetTemplatePropsAsync(template.Id); + //(workGroup, responseArea, jobId) = await GetTemplatePropsAsync(template.Id); + var newCacheItem = await GetTemplatePropsAsync(template.Id); + workGroup = newCacheItem.Data.WorkGroup; + responseArea = newCacheItem.Data.ResponseArea; + jobId = newCacheItem.Data.JobId; } var data = new TemplateReportData( @@ -272,12 +313,35 @@ namespace PARR.Core.Services.Workload.Implementations return reportData; } + + /// + /// Проверка кэша на акутальность. + /// + /// + public async Task IsTemplateReportCacheActualAsync(long? cacheCount = null) + { + long finalCacheCount = cacheCount ?? await redisCacheService.GetHashLengthAsync(redisCacheService.GetKey(CacheKeys.Workload.TemplateHash())); + + // Сравним кол-во записей в БД и в КЭШ, вдруг там разница больше допустимой + var templatesCount = await templateRepository.Get().AsNoTracking().CountAsync(); + if (Math.Abs(templatesCount - finalCacheCount) > maxCacheDiff) + { + logger.LogInformation("Разница в количестве шаблонов в БД ({TemplateCount}) и в КЭШ ({CacheCount}) больше допустимой {MaxCacheDiff}. Считаем КЭШ неактуальным. Требуется повторное формирование КЭШа.", + templatesCount, cacheCount, maxCacheDiff); + return false; + } + + return true; + } + + /// /// Получить РГ и ЗО из шорткода. Сохранить в КЭШ. /// /// /// - private async Task<(string WorkGroup, string ResponseArea, Guid jobId)> GetTemplatePropsAsync(Guid templateId) + //private async Task<(string WorkGroup, string ResponseArea, Guid jobId)> GetTemplatePropsAsync(Guid templateId) + private async Task GetTemplatePropsAsync(Guid templateId) { logger.LogDebug("Дозагружаю недостающие данные из БД для шаблона {TemplateId}", templateId); @@ -290,7 +354,20 @@ namespace PARR.Core.Services.Workload.Implementations if (template == null) { logger.LogWarning("Шаблон {TemplateId} не найден в БД", templateId); - return ($"РГ {templateId}", $"ЗО {templateId}", templateId); + //return ($"РГ {templateId}", $"ЗО {templateId}", templateId); + return new TemplateCache + { + Timestamp = DateTimeOffset.UtcNow, + Source = "", + Data = new TemplateCacheDto + { + JobGroupId = Guid.Empty, + JobId = Guid.Empty, + TemplateId = templateId, + ResponseArea = $"ЗО {templateId}", + WorkGroup = $"РГ {templateId}" + } + }; } var (workGroup, responseArea) = await ApplyShortcodesAsync(template); @@ -311,7 +388,8 @@ namespace PARR.Core.Services.Workload.Implementations ); logger.LogDebug("Добавлена недостающая запись в кэш. {TemplateId}, '{WorkGroup}', '{ResponseArea}'", templateId, workGroup, responseArea); - return (workGroup, responseArea, template.JobId); + //return (workGroup, responseArea, template.JobId); + return cacheItem; } /// diff --git a/PARR.Core/Services/Workload/Implementations/WorkloadService.cs b/PARR.Core/Services/Workload/Implementations/WorkloadService.cs index 2511396a..8f533012 100644 --- a/PARR.Core/Services/Workload/Implementations/WorkloadService.cs +++ b/PARR.Core/Services/Workload/Implementations/WorkloadService.cs @@ -1,6 +1,7 @@ using AutoMapper; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using PARR.Core.Repositories.Interfaces; using PARR.Core.Repositories.Interfaces.Job; using PARR.Core.Repositories.Interfaces.TaskRepositories; using PARR.Core.Services.NextRunServices; @@ -9,6 +10,7 @@ using PARR.Core.Services.Workload.Interfaces; using PARR.Core.Services.Workload.Models; using PARR.Domain.DTOs.Workload; using PARR.Domain.Enums; +using PARR.Domain.Enums.Workload; namespace PARR.Core.Services.Workload.Implementations { @@ -20,8 +22,7 @@ namespace PARR.Core.Services.Workload.Implementations private readonly ITaskRepository taskRepository; private readonly IMapper mapper; private readonly IJobRepository jobRepository; - - //private readonly ITaskManagementService taskManagementService; + private readonly ITemplateRepository templateRepository; public WorkloadService( ILogger logger, @@ -29,8 +30,8 @@ namespace PARR.Core.Services.Workload.Implementations INextRunService nextRunService, ITaskRepository taskRepository, IMapper mapper, - IJobRepository jobRepository - //ITaskManagementService taskManagementService + IJobRepository jobRepository, + ITemplateRepository templateRepository ) { this.logger = logger; @@ -39,11 +40,11 @@ namespace PARR.Core.Services.Workload.Implementations this.taskRepository = taskRepository; this.mapper = mapper; this.jobRepository = jobRepository; - //this.taskManagementService = taskManagementService; + this.templateRepository = templateRepository; } - public async Task GetWorkloadReport(WorkloadReportType reportType, DateOnly dateStart, int durationDays, TimeSpan offset, string? filterParam) + public async Task GetWorkloadReportAsync(WorkloadReportType reportType, DateOnly dateStart, int durationDays, TimeSpan offset, string? filterParam) { logger.LogDebug("Начинаю формировать отчет о загруженности по параметрам: reportType '{ReportType}', dateStart {DateStart}, durationDays {DurationDays}, offset {Offset}", reportType.ToString(), dateStart, durationDays, offset); @@ -174,6 +175,97 @@ namespace PARR.Core.Services.Workload.Implementations } + public async Task> GetTemplateReportAsync(WorkloadTemplateReportType reportType, string filter, WorkloadTemplateReportState state, DateOnly date, TimeSpan offset) + { + if (string.IsNullOrWhiteSpace(filter)) + { + logger.LogWarning("Не передано значение фильтра"); + throw new ArgumentException(nameof(filter), "Не передано значение фильтра."); + } + + // Template cache вообще есть, он актуальный? + if (!await workloadCacheService.IsTemplateReportCacheActualAsync()) + { + logger.LogDebug("Не могу рассчитать отчет Workload, так как нет основного кэш или он не актуальный."); + return new List(); + } + + var trimmedFilter = filter.Trim(); + + + // Формируем дату и время начала и конца + var dtStart = new DateTimeOffset(date.Year, date.Month, date.Day, 0, 0, 0, offset); + var dtEnd = dtStart.AddDays(1); + + // Конвертируем в UTC для совместимости с PostgreSQL timestamptz + var dtStartUtc = dtStart.ToUniversalTime(); + var dtEndUtc = dtEnd.ToUniversalTime(); + + // Запрос к БД + var query = templateRepository.Get().AsNoTracking() + .Where(t => dtStartUtc <= t.NextRun && t.NextRun < dtEndUtc); + + // Фильтруем по состоянию + switch (state) + { + case WorkloadTemplateReportState.All: + break; + case WorkloadTemplateReportState.Activated: + query = query.Where(t => t.IsActiveTemplate && t.IsActiveSchedule); + break; + case WorkloadTemplateReportState.Deactivated: + query = query.Where(t => !t.IsActiveTemplate || !t.IsActiveSchedule); + 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(); + } + + // Тип "не работы", загружаем шаблоны + var dbTemplates = await query.OrderBy(t => t.Name) + .Select(t => new WorkloadTemplateReport(t.Id, t.Name, t.NextRun, t.IsActiveTemplate, t.IsActiveSchedule)) + .ToListAsync(); + + if (dbTemplates.Count == 0) + return new List(); + + // Получаем из кэша шаблоны (если их в кэше нет, догружаем в кэш) + var cacheData = await workloadCacheService.GetTemplateReportDataByIdsAsync(dbTemplates.Select(t => t.TemplateId).ToHashSet()); + + if (cacheData == null) + throw new Exception("Из кэша не получили значения."); + + if (dbTemplates.Count != cacheData.Count) + logger.LogWarning("Количество шаблонов в БД {DbCount} не совпадает с количеством шаблонов полученных из кэша {CacheCount}", dbTemplates.Count, cacheData.Count); + + // Фильтр по типу + switch (reportType) + { + case WorkloadTemplateReportType.WorkGroup: + var cacheTemplatesWg = cacheData.Where(t => string.Equals(t.Data.WorkGroup, trimmedFilter, StringComparison.OrdinalIgnoreCase)) + .Select(t => t.Data.TemplateId).ToHashSet(); + return dbTemplates.Where(t => cacheTemplatesWg.Contains(t.TemplateId)).ToList(); + case WorkloadTemplateReportType.ResponseArea: + var cacheTemplatesRa = cacheData.Where(t => string.Equals(t.Data.ResponseArea, trimmedFilter, StringComparison.OrdinalIgnoreCase)) + .Select(t => t.Data.TemplateId).ToHashSet(); + return dbTemplates.Where(t => cacheTemplatesRa.Contains(t.TemplateId)).ToList(); + } + + logger.LogWarning("Не обработанный тип отчета {ReportType}", reportType); + + return new List(); + } + + /// /// Получить список дней для отчета, с отметкой выходной/рабочий /// @@ -262,6 +354,5 @@ namespace PARR.Core.Services.Workload.Implementations return new WorkloadStatisticItem { DailyMetrics = dailyMetrics, Summary = summary, Title = title }; } - } } diff --git a/PARR.Core/Services/Workload/Interfaces/IWorkloadService.cs b/PARR.Core/Services/Workload/Interfaces/IWorkloadService.cs index aae196c5..f44595c4 100644 --- a/PARR.Core/Services/Workload/Interfaces/IWorkloadService.cs +++ b/PARR.Core/Services/Workload/Interfaces/IWorkloadService.cs @@ -1,5 +1,5 @@ using PARR.Domain.DTOs.Workload; -using PARR.Domain.Enums; +using PARR.Domain.Enums.Workload; namespace PARR.Core.Services.Workload.Interfaces { @@ -23,6 +23,18 @@ namespace PARR.Core.Services.Workload.Interfaces /// /// /// - Task GetWorkloadReport(WorkloadReportType reportType, DateOnly dateStart, int durationDays, TimeSpan offset, string? filterParam); + Task GetWorkloadReportAsync(WorkloadReportType reportType, DateOnly dateStart, int durationDays, TimeSpan offset, string? filterParam); + + /// + /// Получить отчет - список шаблонов на дату согласно фильтрам + /// + /// + /// Фильтр, значение в зависимости от reportType + /// + /// + /// + /// + Task> GetTemplateReportAsync(WorkloadTemplateReportType reportType, string filter, WorkloadTemplateReportState state, DateOnly date, TimeSpan offset); + } } diff --git a/PARR.Domain/DTOs/Workload/WorkloadReport.cs b/PARR.Domain/DTOs/Workload/WorkloadReport.cs index ed312a08..e3956864 100644 --- a/PARR.Domain/DTOs/Workload/WorkloadReport.cs +++ b/PARR.Domain/DTOs/Workload/WorkloadReport.cs @@ -1,4 +1,4 @@ -using PARR.Domain.Enums; +using PARR.Domain.Enums.Workload; namespace PARR.Domain.DTOs.Workload { diff --git a/PARR.Domain/DTOs/Workload/WorkloadTemplateReport.cs b/PARR.Domain/DTOs/Workload/WorkloadTemplateReport.cs new file mode 100644 index 00000000..6753cb0b --- /dev/null +++ b/PARR.Domain/DTOs/Workload/WorkloadTemplateReport.cs @@ -0,0 +1,10 @@ +namespace PARR.Domain.DTOs.Workload +{ + /// + /// Отчет о шаблонах, для отчета о нагруженности + /// + /// + /// + /// + public record WorkloadTemplateReport(Guid TemplateId, string Name, DateTimeOffset NextRun, bool IsActiveTemplate, bool IsActiveSchedule); +} diff --git a/PARR.Domain/Enums/WorkloadReportType.cs b/PARR.Domain/Enums/Workload/WorkloadReportType.cs similarity index 95% rename from PARR.Domain/Enums/WorkloadReportType.cs rename to PARR.Domain/Enums/Workload/WorkloadReportType.cs index 57be84a9..bbc1c4eb 100644 --- a/PARR.Domain/Enums/WorkloadReportType.cs +++ b/PARR.Domain/Enums/Workload/WorkloadReportType.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace PARR.Domain.Enums +namespace PARR.Domain.Enums.Workload { /// /// Тип отчета о загруженности diff --git a/PARR.Domain/Enums/Workload/WorkloadTemplateReportState.cs b/PARR.Domain/Enums/Workload/WorkloadTemplateReportState.cs new file mode 100644 index 00000000..7b2c1a3d --- /dev/null +++ b/PARR.Domain/Enums/Workload/WorkloadTemplateReportState.cs @@ -0,0 +1,26 @@ +using System.Text.Json.Serialization; + +namespace PARR.Domain.Enums.Workload +{ + /// + /// Тип отчета о загруженности, состояние + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum WorkloadTemplateReportState + { + /// + /// Все + /// + All = 0, + + /// + /// Активированные + /// + Activated = 1, + + /// + /// Деактивированные + /// + Deactivated = 2 + } +} diff --git a/PARR.Domain/Enums/Workload/WorkloadTemplateReportType.cs b/PARR.Domain/Enums/Workload/WorkloadTemplateReportType.cs new file mode 100644 index 00000000..b8680aab --- /dev/null +++ b/PARR.Domain/Enums/Workload/WorkloadTemplateReportType.cs @@ -0,0 +1,26 @@ +using System.Text.Json.Serialization; + +namespace PARR.Domain.Enums.Workload +{ + /// + /// Тип отчета о загруженности, шаблоны + /// + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum WorkloadTemplateReportType + { + /// + /// Зона ответственности + /// + ResponseArea = 0, + + /// + /// Рабочая группа + /// + WorkGroup = 1, + + /// + /// Работа + /// + Job = 2 + } +}