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.DAL.Models; using PARR.DAL.Services.Interfaces; namespace PARR.API.Controllers.V1.Statistics { /// /// Статистика загрузки регламентными работами по Видам работ(ApplicationInWorks) /// public class StatWorkWorkLoadController : BaseApiController { private readonly ITemplateService templateService; private readonly IWorkLoadService workLoadService; private readonly IMapper mapper; private readonly ILogger logger; private readonly IWorkGroupService workGroupService; public StatWorkWorkLoadController( ITemplateService templateService, IWorkLoadService workLoadService, IMapper mapper, ILogger logger, IWorkGroupService workGroupService ) { this.templateService = templateService; this.workLoadService = workLoadService; this.mapper = mapper; this.logger = logger; this.workGroupService = workGroupService; } /// /// Статистика загрузки регламентными работами по Видам работ(ApplicationInWorks) /// /// /// /// [HttpGet(ApiRoutes.StatWorkWorkLoad.Get)] public async Task Get([FromRoute] Guid workGroupId, [FromQuery] WorkloadBaseQuery requestQuery) { var response = await GetStatisticsAsync(workGroupId, requestQuery); return Ok(new Response>(response, true)); } /// /// Статистика загрузки РР по списку РР /// /// /// [HttpPost(ApiRoutes.StatWorkWorkLoad.GetByApplicationInWork)] public async Task GetByApplicationInWork([FromBody] StatWorkWorkLoadRequest requestBody) { var response = await GetStatisticsAsync(null, requestBody.Filter, requestBody.JobsRequests); return Ok(new Response>(response, true)); } private async Task> GetStatisticsAsync(Guid? workGroupId, WorkloadBaseQuery requestQuery, List? jobsRequests = null) { //защита от дурака, чтоб не выгрузить всю БД if (workGroupId == null && (jobsRequests == null || jobsRequests.Count() == 0)) { logger.LogWarning($"Пытались выполнить запрос получения статситики с нулевыми параметрами {nameof(workGroupId)}, {nameof(jobsRequests)}. Controller {nameof(StatWorkWorkLoadController)}"); return new List(); } var daysList = workLoadService.GetDatesForPeriod(requestQuery); IQueryable query = templateService.Get() .Include(t => t.Host); query = workLoadService.FilterTemplatesQuery(query, requestQuery); if (workGroupId.HasValue) query = query.Where(t => t.Host!.WorkGroupId == workGroupId.Value); if (jobsRequests != null && jobsRequests.Count() > 0) //query = query.Where(t => jobsRequests.Any(x => x.JobId == t.ApplicationInWorkId && x.WorkGroupId == t.Host!.WorkGroupId.Value)); /*&& x.WorkGroupId == t.Host!.WorkGroupId.Value*/ query = query.Where(t => jobsRequests.Select(t => t.JobId).Any(x => x == t.ApplicationInWorkId) && jobsRequests.Select(t => t.WorkGroupId).Any(x => x == t.Host!.WorkGroupId.Value)); //var groupedQuery = query.GroupBy(t => new { t.NextRun.DateTime.Date, t.ApplicationInWorkId, t.Host.WorkGroupId }) var groupedQuery = query.GroupBy(t => new { t.NextRun.AddHours(requestQuery.TimeZoneOffsetHours).DateTime.Date, t.ApplicationInWorkId, t.Host.WorkGroupId }) .Select(t => new { ApplicationInWorkId = t.Key.ApplicationInWorkId, WorkGroupId = t.Key.WorkGroupId, Date = t.Key.Date, TemplateCount = t.Count() }); var queryResult = await groupedQuery.ToListAsync(); // получаем только работы по которым есть шаблоны (активированные/деакт) и за любой период IQueryable appInWorksQuery = templateService.Get() .Include(t => t.Host) .Include(t => t.ApplicationsInWork).ThenInclude(t => t.Application).ThenInclude(t => t.ApplicationType); IQueryable workGroupsQuery = workGroupService.Get() .Include(t => t.ResponseArea); if (workGroupId.HasValue) { appInWorksQuery = appInWorksQuery.Where(t => t.Host.WorkGroupId == workGroupId); workGroupsQuery = workGroupsQuery.Where(t => t.Id == workGroupId.Value); } if (jobsRequests != null && jobsRequests.Count() > 0) { //appInWorksQuery = appInWorksQuery.Where(t => jobsRequests.Any(x => x.JobId == t.ApplicationInWorkId)); appInWorksQuery = appInWorksQuery.Where(t => jobsRequests.Select(j => j.JobId).Any(x => x == t.ApplicationInWorkId)); workGroupsQuery = workGroupsQuery.Where(t => jobsRequests.Select(w => w.WorkGroupId).Any(x => x == t.Id)); } var appInWorks = await appInWorksQuery.Select(t => t.ApplicationsInWork) .Distinct() .ToListAsync(); var workGroups = await workGroupsQuery.Distinct().ToListAsync(); var response = new List(); appInWorks.ForEach(appInWork => { workGroups.ForEach(workGroup => { var workLoads = daysList.Select(t => new StatWorkLoadDataResponse { Date = t, TemplateCount = queryResult.FirstOrDefault(x => x.ApplicationInWorkId == appInWork.Id && DateOnly.FromDateTime(x.Date) == t && x.WorkGroupId == workGroup.Id)?.TemplateCount ?? 0 }).OrderBy(t => t.Date).ToList(); response.Add(new StatWorkWorkLoadResponse { Job = mapper.Map(appInWork), WorkGroup = mapper.Map(workGroup), WorkLoad = workLoads }); }); }); // убираем не нужные значения так как запрос в SQL (query) был с несколькими Any if (jobsRequests != null && jobsRequests.Count() > 0) response = response.Where(t => jobsRequests.Any(x => x.WorkGroupId == t.WorkGroup.Id && x.JobId == t.Job.Id)).ToList(); response = response.OrderBy(t => t.Job.ShortDescription).ThenBy(t => t.Job.Application?.Name).ThenBy(t => t.WorkGroup.Name).ToList(); return response; } } }