using System.Security.AccessControl; using GozareshgirProgramManager.Application._Common.Interfaces; using GozareshgirProgramManager.Application._Common.Models; using Microsoft.EntityFrameworkCore; namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectDeployBoardDetail; public record ProjectDeployBoardDetailsResponse( ProjectDeployBoardDetailPhaseItem Phase, List Tasks); public record ProjectDeployBoardDetailPhaseItem( string Name, TimeSpan TotalTimeSpan, TimeSpan DoneTimeSpan, int Percentage); public record ProjectDeployBoardDetailTaskItem( string Name, TimeSpan TotalTimeSpan, TimeSpan DoneTimeSpan, int Percentage, List Skills) : ProjectDeployBoardDetailPhaseItem(Name, TotalTimeSpan, DoneTimeSpan,Percentage); public record ProjectDeployBoardDetailItemSkill(string OriginalUserFullName, string SkillName, int TimePercentage); public record ProjectDeployBoardDetailsQuery(Guid PhaseId) : IBaseQuery; public class ProjectDeployBoardDetailsQueryHandler : IBaseQueryHandler { private readonly IProgramManagerDbContext _dbContext; public ProjectDeployBoardDetailsQueryHandler(IProgramManagerDbContext dbContext) { _dbContext = dbContext; } public async Task> Handle(ProjectDeployBoardDetailsQuery request, CancellationToken cancellationToken) { var phase = await _dbContext.ProjectPhases .Include(x => x.Tasks) .ThenInclude(x => x.Sections) .ThenInclude(x => x.Activities) .Include(x => x.Tasks) .ThenInclude(x => x.Sections) .ThenInclude(x => x.AdditionalTimes) .Include(x => x.Tasks) .ThenInclude(x => x.Sections) .ThenInclude(x => x.Skill) .FirstOrDefaultAsync(x => x.Id == request.PhaseId, cancellationToken); if (phase == null) return OperationResult.NotFound("بخش اصلی مورد نظر یافت نشد"); var userIds = phase.Tasks .SelectMany(t => t.Sections) .Select(s => s.OriginalAssignedUserId) .Distinct() .ToList(); var usersDict = await _dbContext.Users .Where(x => userIds.Contains(x.Id)) .ToDictionaryAsync(x => x.Id, x => x.FullName, cancellationToken); var tasksRes = phase.Tasks.Select(t => { var totalTime = t.Sections.Select(s => s.FinalEstimatedHours) .Aggregate(TimeSpan.Zero, (sum, next) => sum.Add(next)); var doneTime = t.Sections.Aggregate(TimeSpan.Zero, (sum, next) => sum.Add(next.GetTotalTimeSpent())); var skills = t.Sections .Select(s => { var originalUserFullName = usersDict.GetValueOrDefault(s.OriginalAssignedUserId, "کاربر ناشناس"); var skillName = s.Skill?.Name ?? "بدون مهارت"; var timePercentage = (int)s.GetProgressPercentage(); return new ProjectDeployBoardDetailItemSkill( originalUserFullName, skillName, timePercentage); }).ToList(); var taskPercentage = (int)Math.Round(skills.Average(x => x.TimePercentage)); return new ProjectDeployBoardDetailTaskItem( t.Name, totalTime, doneTime, taskPercentage, skills); }).ToList(); var totalTimeSpan = tasksRes.Aggregate(TimeSpan.Zero, (sum, next) => sum.Add(next.TotalTimeSpan)); var doneTimeSpan = tasksRes.Aggregate(TimeSpan.Zero, (sum, next) => sum.Add(next.DoneTimeSpan)); var phasePercentage = tasksRes.Average(x => x.Percentage); var phaseRes = new ProjectDeployBoardDetailPhaseItem(phase.Name, totalTimeSpan, doneTimeSpan, (int)phasePercentage); var res = new ProjectDeployBoardDetailsResponse(phaseRes, tasksRes); return OperationResult.Success(res); } }