feat(core): WorkloadService - реализация логики формирования отчета
This commit is contained in:
@@ -82,6 +82,7 @@ namespace PARR.Core
|
||||
#region Workload
|
||||
|
||||
services.AddScoped<WorkloadCacheService>();
|
||||
services.AddScoped<IWorkloadService, WorkloadService>();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NodaTime;
|
||||
using PARR.Core.Common.Interfaces;
|
||||
using PARR.Core.Repositories.Interfaces;
|
||||
using PARR.Core.Services.Shortcodes;
|
||||
using PARR.Core.Services.Workload.Models;
|
||||
using PARR.Domain.Cache.Models;
|
||||
using PARR.Domain.DTOs.Workload;
|
||||
using PARR.Domain.Entities;
|
||||
using PARR.Domain.Enums;
|
||||
|
||||
namespace PARR.Core.Services.Workload.Implementations
|
||||
{
|
||||
@@ -33,7 +36,7 @@ namespace PARR.Core.Services.Workload.Implementations
|
||||
}
|
||||
|
||||
|
||||
//----------- Настройки, вынести -----------
|
||||
//todo:----------- Настройки, вынести -----------
|
||||
/// <summary>
|
||||
/// Ключ КЭШ шаблонов
|
||||
/// </summary>
|
||||
@@ -56,7 +59,6 @@ namespace PARR.Core.Services.Workload.Implementations
|
||||
|
||||
/// <summary>
|
||||
/// Ключ КЭШ, отчет о загруженности, одна ЗО
|
||||
/// Формировать ключ, основа + Hash ЗО
|
||||
/// </summary>
|
||||
private readonly string[] cacheWorkloadResponseAreaItemKey = { "workload", "response area", "item" };
|
||||
|
||||
@@ -67,7 +69,6 @@ namespace PARR.Core.Services.Workload.Implementations
|
||||
|
||||
/// <summary>
|
||||
/// Ключ КЭШ, отчет о загруженности, одна РГ
|
||||
/// Формировать ключ, основа + Hash РГ
|
||||
/// </summary>
|
||||
private readonly string[] cacheWorkloadWorkGroupItemKey = { "workload", "work group", "item" };
|
||||
|
||||
@@ -161,19 +162,22 @@ namespace PARR.Core.Services.Workload.Implementations
|
||||
/// <summary>
|
||||
/// Получить кэш РГ и ЗО всех шаблонов, получить недостающие поля из БД.
|
||||
/// Сравнит кол-во записей в БД и в КЭШ, если не хватает до 1000 шаблонов, доформирует кэш,
|
||||
/// если больше 1000, вернет пустой список, так как считается кэш неактуальным.
|
||||
/// если больше 1000, вернет null, так как считается кэш неактуальным.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<Dictionary<Guid, TemplateReportData>> GetTemplateReportDataAsync()
|
||||
/// <param name="dateStart">Дата начала</param>
|
||||
/// <param name="durationDays">Продолжительность дней</param>
|
||||
/// <param name="offset">Смещение часового пояса</param>
|
||||
/// <returns>null - если нет кэша или он не актуальный. Иначе, список шаблонов.</returns>
|
||||
public async Task<List<TemplateReportData>?> GetTemplateReportDataAsync(DateOnly dateStart, int durationDays, TimeSpan offset)
|
||||
{
|
||||
logger.LogDebug("Получаю данные для формирования отчета.");
|
||||
logger.LogDebug("Получаю данные для формирования отчета. DateStart {DateStart}, DurationDays {DurationDays}, Offset {Offset}", dateStart, durationDays, offset);
|
||||
|
||||
// Получим кэш целиком
|
||||
var cacheData = await redisCacheService.GetAllHashFieldsAsync<TemplateCache>(redisCacheService.GetKey(cacheTemplateKey));
|
||||
if (cacheData.Count == 0)
|
||||
{
|
||||
logger.LogDebug("Записей в кэш 0. Конец.");
|
||||
return new Dictionary<Guid, TemplateReportData>();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Сравним кол-во записей в БД и в КЭШ, вдруг там разница больше допустимой
|
||||
@@ -182,16 +186,24 @@ namespace PARR.Core.Services.Workload.Implementations
|
||||
{
|
||||
logger.LogInformation("Разница в количестве шаблонов в БД ({TemplateCount}) и в КЭШ ({CacheCount}) больше допустимой {MaxCacheDiff}. Считаем КЭШ неактуальным. Требуется повторное формирование КЭШа.",
|
||||
templatesCount, cacheData.Count, maxCacheDiff);
|
||||
return new Dictionary<Guid, TemplateReportData>();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Получаем из БД только нужные данные для отчета
|
||||
// Получаем из БД только нужные данные для отчета, попадающие в интервал
|
||||
var dtStart = new DateTimeOffset(dateStart.Year, dateStart.Month, dateStart.Day, 0, 0, 0, offset);
|
||||
var dtEnd = dtStart.AddDays(durationDays);
|
||||
|
||||
logger.LogDebug("Фильтруем шаблоны в БД по интервалу: Start={DtStart:yyyy-MM-dd HH:mm:ss zzz}, End={DtEnd:yyyy-MM-dd HH:mm:ss zzz}", dtStart, dtEnd);
|
||||
|
||||
var templates = await templateRepository.Get()
|
||||
.AsNoTracking()
|
||||
.Where(t => dtStart <= t.NextRun && t.NextRun < dtEnd)
|
||||
.Select(t => new { Id = t.Id, IsActiveTemplate = t.IsActiveTemplate, IsActiveSchedule = t.IsActiveSchedule, Name = t.Name, NextRun = t.NextRun })
|
||||
.ToListAsync();
|
||||
|
||||
var reportData = new Dictionary<Guid, TemplateReportData>();
|
||||
logger.LogDebug("Загружено шаблонов из БД {Count}", templates.Count);
|
||||
|
||||
var reportData = new List<TemplateReportData>();
|
||||
|
||||
foreach (var template in templates)
|
||||
{
|
||||
@@ -220,7 +232,7 @@ namespace PARR.Core.Services.Workload.Implementations
|
||||
template.IsActiveTemplate,
|
||||
template.IsActiveSchedule,
|
||||
DateTimeOffset.UtcNow);
|
||||
reportData.Add(template.Id, data);
|
||||
reportData.Add(data);
|
||||
}
|
||||
|
||||
logger.LogDebug("Сформировано итоговых данных для отчета, строк: {Count}", reportData.Count);
|
||||
@@ -279,5 +291,93 @@ namespace PARR.Core.Services.Workload.Implementations
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Получить отчет Workload из кэша
|
||||
/// </summary>
|
||||
/// <param name="reportType"></param>
|
||||
/// <param name="dateStart"></param>
|
||||
/// <param name="durationDays"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="filterParam">Наименование ЗО или РГ или null</param>
|
||||
/// <returns></returns>
|
||||
public async Task<WorkloadReport?> GetWorkloadReportAsync(WorkloadReportType reportType, DateOnly dateStart, int durationDays, TimeSpan offset, string? filterParam)
|
||||
{
|
||||
var key = GetReportCacheKey(reportType, dateStart, durationDays, offset, filterParam);
|
||||
|
||||
return await redisCacheService.GetCachedDataAsync<WorkloadReport>(key);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Записать отчет Workload в кэш
|
||||
/// </summary>
|
||||
/// <param name="report"></param>
|
||||
/// <param name="reportType"></param>
|
||||
/// <param name="dateStart"></param>
|
||||
/// <param name="durationDays"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="filterParam">Наименование ЗО или РГ или null</param>
|
||||
/// <returns></returns>
|
||||
public async Task SetWorkloadReport(WorkloadReport report, WorkloadReportType reportType, DateOnly dateStart, int durationDays, TimeSpan offset, string? filterParam)
|
||||
{
|
||||
var key = GetReportCacheKey(reportType, dateStart, durationDays, offset, filterParam);
|
||||
await redisCacheService.SetCachedDataAsync(key, report, cacheWorkloadTtl);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Формирует ключ для отчета Workload
|
||||
/// </summary>
|
||||
/// <param name="reportType"></param>
|
||||
/// <param name="dateStart"></param>
|
||||
/// <param name="durationDays"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="filterParam"></param>
|
||||
/// <returns></returns>
|
||||
private string GetReportCacheKey(WorkloadReportType reportType, DateOnly dateStart, int durationDays, TimeSpan offset, string? filterParam = null)
|
||||
{
|
||||
// формируе ключ, вида: основа + дата начала + продолжительность + смещение
|
||||
// Если есть параметр (filterParam), добавляется параметр в виде Hash
|
||||
|
||||
var keyList = new List<string>();
|
||||
|
||||
switch (reportType)
|
||||
{
|
||||
case WorkloadReportType.ResponseAreaAll:
|
||||
keyList.AddRange(cacheWorkloadResponseAreaAllKey);
|
||||
break;
|
||||
case WorkloadReportType.ResponseAreaItem:
|
||||
keyList.AddRange(cacheWorkloadResponseAreaItemKey);
|
||||
break;
|
||||
case WorkloadReportType.WorkGroupAll:
|
||||
keyList.AddRange(cacheWorkloadWorkGroupAllKey);
|
||||
break;
|
||||
case WorkloadReportType.WorkGroupItem:
|
||||
keyList.AddRange(cacheWorkloadWorkGroupItemKey);
|
||||
break;
|
||||
default:
|
||||
logger.LogError("Недопустимое значение тип отчета '{ReportType}'", reportType);
|
||||
throw new ArgumentException("Недопустимое значение тип отчета", nameof(reportType));
|
||||
}
|
||||
|
||||
keyList.AddRange(new string[] { dateStart.ToString(), durationDays.ToString(), offset.ToString() });
|
||||
|
||||
var keyStr = string.Empty;
|
||||
|
||||
if (filterParam == null)
|
||||
keyStr = redisCacheService.GetKey(keyList.ToArray());
|
||||
else
|
||||
keyStr = redisCacheService.GetKey(keyList.ToArray(), new string[] { filterParam });
|
||||
|
||||
logger.LogDebug("Сформирован ключ для кэш '{Key}'", keyStr);
|
||||
|
||||
return keyStr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
197
PARR.Core/Services/Workload/Implementations/WorkloadService.cs
Normal file
197
PARR.Core/Services/Workload/Implementations/WorkloadService.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Services.NextRunServices;
|
||||
using PARR.Core.Services.Workload.Interfaces;
|
||||
using PARR.Core.Services.Workload.Models;
|
||||
using PARR.Domain.DTOs.Workload;
|
||||
using PARR.Domain.Enums;
|
||||
|
||||
namespace PARR.Core.Services.Workload.Implementations
|
||||
{
|
||||
internal class WorkloadService : IWorkloadService
|
||||
{
|
||||
private readonly ILogger<WorkloadService> logger;
|
||||
private readonly WorkloadCacheService workloadCacheService;
|
||||
private readonly INextRunService nextRunService;
|
||||
|
||||
public WorkloadService(
|
||||
ILogger<WorkloadService> logger,
|
||||
WorkloadCacheService workloadCacheService,
|
||||
INextRunService nextRunService
|
||||
)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.workloadCacheService = workloadCacheService;
|
||||
this.nextRunService = nextRunService;
|
||||
}
|
||||
|
||||
|
||||
public async Task<WorkloadReport?> GetWorkloadReport(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);
|
||||
|
||||
if ((reportType == WorkloadReportType.WorkGroupItem || reportType == WorkloadReportType.ResponseAreaItem) && string.IsNullOrEmpty(filterParam))
|
||||
{
|
||||
logger.LogError("Для типа отчета {ReportType} не передан параметр.", reportType.ToString());
|
||||
throw new ArgumentNullException(nameof(filterParam), $"Для отчета типа {reportType.ToString()} параметр является обязательным.");
|
||||
}
|
||||
|
||||
|
||||
// Если есть отчет в КЭШ, вернуть
|
||||
var cacheReport = await workloadCacheService.GetWorkloadReportAsync(reportType, dateStart, durationDays, offset, filterParam);
|
||||
if (cacheReport != null)
|
||||
{
|
||||
logger.LogDebug("Вернул отчет из кэша.");
|
||||
return cacheReport;
|
||||
}
|
||||
|
||||
// Если нет основного кэша, вернуть null, пусть пользователь нажимает кнопку сформировать отчет
|
||||
var templates = await workloadCacheService.GetTemplateReportDataAsync(dateStart, durationDays, offset);
|
||||
if (templates == null)
|
||||
{
|
||||
logger.LogDebug("Не могу рассчитать отчет Workload, так как нет основного кэш или он не актуальный.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Есть основной кэш, построить отчет и сохранить в кэш отчета
|
||||
logger.LogDebug("Основной кэш есть, начинаю строить отчет.");
|
||||
|
||||
// Список дней
|
||||
var reportDays = await GetReportDays(dateStart, durationDays);
|
||||
|
||||
var displayName = string.Empty;
|
||||
|
||||
// Формируем отчет в зависимости от типа
|
||||
var statistics = new List<WorkloadStatisticItem>();
|
||||
switch (reportType)
|
||||
{
|
||||
case WorkloadReportType.ResponseAreaAll:
|
||||
displayName = "По зонам ответственности";
|
||||
foreach (var group in templates.GroupBy(t => t.ResponseArea))
|
||||
statistics.Add(BuildStatisticItem(group.Key, group, reportDays, offset));
|
||||
break;
|
||||
case WorkloadReportType.ResponseAreaItem:
|
||||
displayName = "По зоне ответственности";
|
||||
var filteredRA = templates.Where(t => t.ResponseArea.Equals(filterParam, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
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));
|
||||
break;
|
||||
case WorkloadReportType.WorkGroupItem:
|
||||
displayName = "По рабочей группе";
|
||||
var filteredWG = templates.Where(t => t.WorkGroup.Equals(filterParam, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
statistics.Add(BuildStatisticItem(filterParam!, filteredWG, reportDays, offset));
|
||||
break;
|
||||
}
|
||||
|
||||
var report = new WorkloadReport
|
||||
{
|
||||
Type = reportType,
|
||||
DisplayName = displayName,
|
||||
SubfilterName = filterParam,
|
||||
ReportCacheCreatedAt = DateTimeOffset.UtcNow,
|
||||
TemplateCacheCreatedAt = templates.FirstOrDefault()?.CacheDate ?? DateTimeOffset.MinValue,
|
||||
Days = reportDays,
|
||||
Statistics = statistics
|
||||
};
|
||||
|
||||
// Сохраним в кэш
|
||||
await workloadCacheService.SetWorkloadReport(report, reportType, dateStart, durationDays, offset, filterParam);
|
||||
logger.LogDebug("Отчет построен и сохранен в кэш");
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получить список дней для отчета, с отметкой выходной/рабочий
|
||||
/// </summary>
|
||||
/// <param name="dateStart"></param>
|
||||
/// <param name="durationDays"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<List<WorkloadDayItem>> GetReportDays(DateOnly dateStart, int durationDays)
|
||||
{
|
||||
var dateEnd = dateStart.AddDays(durationDays);
|
||||
var days = await nextRunService.GetWorkDaysAsync(dateStart, dateEnd, false);
|
||||
var weekends = await nextRunService.GetWeekendsAsync(dateStart, dateEnd);
|
||||
|
||||
return days.Select(t => new WorkloadDayItem { Date = t, IsWeekend = weekends.Contains(t) })
|
||||
.OrderBy(t => t.Date)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Составить статистику по одному объекту за период
|
||||
/// </summary>
|
||||
/// <param name="templates"></param>
|
||||
/// <param name="reportDays"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
private List<WorkloadDailyItem> GetDailyMetrics(List<TemplateReportData> templates, List<WorkloadDayItem> reportDays, TimeSpan offset)
|
||||
{
|
||||
var result = new List<WorkloadDailyItem>();
|
||||
|
||||
foreach (var dayItem in reportDays)
|
||||
{
|
||||
var dateStart = new DateTimeOffset(dayItem.Date.Year, dayItem.Date.Month, dayItem.Date.Day, 0, 0, 0, offset);
|
||||
var dateEnd = dateStart.AddDays(1);
|
||||
|
||||
var filteredItems = templates.Where(t => dateStart <= t.NextRun && t.NextRun < dateEnd);
|
||||
|
||||
var dailyItem = new WorkloadDailyItem
|
||||
{
|
||||
Date = dayItem.Date,
|
||||
IsWeekend = dayItem.IsWeekend,
|
||||
Total = filteredItems.Count(),
|
||||
Activated = filteredItems.Count(t => t.IsActiveTemplate && t.IsActiveSchedule),
|
||||
Deactivated = filteredItems.Count(t => !t.IsActiveTemplate || !t.IsActiveSchedule)
|
||||
};
|
||||
|
||||
result.Add(dailyItem);
|
||||
}
|
||||
|
||||
return result.OrderBy(t => t.Date).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Заполнить Summary
|
||||
/// </summary>
|
||||
/// <param name="dailyMetrics"></param>
|
||||
/// <returns></returns>
|
||||
private WorkloadSummary GetSummary(List<WorkloadDailyItem> dailyMetrics, int allDays)
|
||||
{
|
||||
// Локальная функция для расчета одной метрики
|
||||
static WorkloadSummaryItem Calc(List<WorkloadDailyItem> dailyMetrics, int allDays, Func<WorkloadDailyItem, int> selector) => new()
|
||||
{
|
||||
Count = dailyMetrics.Sum(selector),
|
||||
Average = allDays > 0 ? Math.Round((double)dailyMetrics.Sum(selector) / allDays, 2) : 0
|
||||
};
|
||||
|
||||
return new WorkloadSummary
|
||||
{
|
||||
Total = Calc(dailyMetrics, allDays, t => t.Total),
|
||||
Activated = Calc(dailyMetrics, allDays, t => t.Activated),
|
||||
Deactivated = Calc(dailyMetrics, allDays, t => t.Deactivated)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Формирует статистику по одной группе
|
||||
/// </summary>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="groupTemplates"></param>
|
||||
/// <param name="reportDays"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
private WorkloadStatisticItem BuildStatisticItem(string title, IEnumerable<TemplateReportData> groupTemplates, List<WorkloadDayItem> 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 };
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace PARR.Core.Services.Workload.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Сервис формирования отчетности о загруженности
|
||||
/// </summary>
|
||||
public interface IWorkloadService
|
||||
{
|
||||
}
|
||||
}
|
||||
93
PARR.Domain/DTOs/Workload/WorkloadReport.cs
Normal file
93
PARR.Domain/DTOs/Workload/WorkloadReport.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using PARR.Domain.Enums;
|
||||
|
||||
namespace PARR.Domain.DTOs.Workload
|
||||
{
|
||||
/// <summary>
|
||||
/// Отчет о загруженности
|
||||
/// </summary>
|
||||
public record WorkloadReport
|
||||
{
|
||||
/// <summary>
|
||||
/// Тип отчета (все ЗО, все РГ, одна ЗО, одна РГ)
|
||||
/// </summary>
|
||||
public WorkloadReportType Type { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Название отчета (По всем ЗО, по одной ЗО)
|
||||
/// </summary>
|
||||
public required string DisplayName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Подзаголовок, наименование конкретной ЗО/РГ
|
||||
/// </summary>
|
||||
public string? SubfilterName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата формирования отчета
|
||||
/// </summary>
|
||||
public DateTimeOffset ReportCacheCreatedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата формирования кэша ЗО и РГ
|
||||
/// </summary>
|
||||
public DateTimeOffset TemplateCacheCreatedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Список дней
|
||||
/// </summary>
|
||||
public required List<WorkloadDayItem> Days { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Нагруженность
|
||||
/// </summary>
|
||||
public required List<WorkloadStatisticItem> Statistics { get; init; }
|
||||
}
|
||||
|
||||
|
||||
public record WorkloadSummary
|
||||
{
|
||||
public required WorkloadSummaryItem Total { get; init; }
|
||||
|
||||
public required WorkloadSummaryItem Activated { get; init; }
|
||||
|
||||
public required WorkloadSummaryItem Deactivated { get; init; }
|
||||
}
|
||||
|
||||
public record WorkloadSummaryItem
|
||||
{
|
||||
public int Count { get; init; }
|
||||
|
||||
public double Average { get; init; }
|
||||
}
|
||||
|
||||
public record WorkloadDayItem
|
||||
{
|
||||
public DateOnly Date { get; init; }
|
||||
|
||||
public bool IsWeekend { get; init; }
|
||||
}
|
||||
|
||||
public record WorkloadStatisticItem
|
||||
{
|
||||
public required string Title { get; init; }
|
||||
|
||||
public required WorkloadSummary Summary { get; init; }
|
||||
|
||||
public required List<WorkloadDailyItem> DailyMetrics { get; init; }
|
||||
}
|
||||
|
||||
public record WorkloadDailyItem
|
||||
{
|
||||
public DateOnly Date { get; init; }
|
||||
|
||||
public bool IsWeekend { get; init; }
|
||||
|
||||
public int Total { get; init; }
|
||||
|
||||
public int Activated { get; init; }
|
||||
|
||||
public int Deactivated { get; init; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
31
PARR.Domain/Enums/WorkloadReportType.cs
Normal file
31
PARR.Domain/Enums/WorkloadReportType.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace PARR.Domain.Enums
|
||||
{
|
||||
/// <summary>
|
||||
/// Тип отчета о загруженности
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public enum WorkloadReportType
|
||||
{
|
||||
/// <summary>
|
||||
/// Отчет по всем ЗО
|
||||
/// </summary>
|
||||
ResponseAreaAll = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Отчет по одной ЗО
|
||||
/// </summary>
|
||||
ResponseAreaItem = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Отчет по всем РГ
|
||||
/// </summary>
|
||||
WorkGroupAll = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Отчет по одной РГ
|
||||
/// </summary>
|
||||
WorkGroupItem = 3
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user