Merge branch 'Feature/program-manager/test-upload'
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
using System.Linq;
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AutoUpdateDeployStatus;
|
||||
|
||||
public record AutoUpdateDeployStatusCommand : IBaseCommand;
|
||||
|
||||
public class AutoUpdateDeployStatusCommandHandler : IBaseCommandHandler<AutoUpdateDeployStatusCommand>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _dbContext;
|
||||
|
||||
public AutoUpdateDeployStatusCommandHandler(IProgramManagerDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(AutoUpdateDeployStatusCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// Fetch all sections whose phase is still marked as not completed
|
||||
var sections = await _dbContext.TaskSections
|
||||
.Include(ts => ts.Task)
|
||||
.ThenInclude(t => t.Phase)
|
||||
.Where(ts => ts.Task.Phase.DeployStatus == ProjectDeployStatus.NotCompleted)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (sections.Count == 0)
|
||||
return OperationResult.Success();
|
||||
|
||||
var phasesToUpdate = sections
|
||||
.GroupBy(ts => ts.Task.PhaseId)
|
||||
.Where(g => g.All(s => s.Status == TaskSectionStatus.Completed))
|
||||
.Select(g => g.First().Task.Phase)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
if (phasesToUpdate.Count == 0)
|
||||
return OperationResult.Success();
|
||||
|
||||
foreach (var phase in phasesToUpdate)
|
||||
{
|
||||
phase.UpdateDeployStatus(ProjectDeployStatus.PendingDevDeploy);
|
||||
}
|
||||
|
||||
await _dbContext.SaveChangesAsync(cancellationToken);
|
||||
return OperationResult.Success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeDeployStatusProject;
|
||||
|
||||
public record ChangeDeployStatusProjectCommand(Guid PhaseId, ProjectDeployStatus Status):IBaseCommand;
|
||||
|
||||
public class ChangeDeployStatusProjectCommandHandler : IBaseCommandHandler<ChangeDeployStatusProjectCommand>
|
||||
{
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly IProjectPhaseRepository _projectPhaseRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public ChangeDeployStatusProjectCommandHandler(IProjectRepository projectRepository, IUnitOfWork unitOfWork, IProjectPhaseRepository projectPhaseRepository)
|
||||
{
|
||||
_projectRepository = projectRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_projectPhaseRepository = projectPhaseRepository;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(ChangeDeployStatusProjectCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var project = await _projectPhaseRepository.GetByIdAsync(request.PhaseId, cancellationToken);
|
||||
if (project == null)
|
||||
return OperationResult.NotFound("بخش مورد نظر یافت نشد");
|
||||
|
||||
if (project.DeployStatus == ProjectDeployStatus.NotCompleted)
|
||||
{
|
||||
return OperationResult.Failure("وضعیت استقرار نمیتواند از حالت 'تایید نشده' تغییر کند.");
|
||||
}
|
||||
|
||||
if (request.Status == ProjectDeployStatus.NotCompleted)
|
||||
{
|
||||
return OperationResult.Failure("وضعیت استقرار نمیتواند به حالت 'تایید نشده' تغییر کند.");
|
||||
}
|
||||
project.UpdateDeployStatus(request.Status);
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
return OperationResult.Success();
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,9 @@ public class ProjectBoardListQueryHandler : IBaseQueryHandler<ProjectBoardListQu
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var currentUserId = _authHelper.GetCurrentUserId();
|
||||
|
||||
var queryable = _programManagerDbContext.TaskSections.AsNoTracking()
|
||||
.Where(x => x.InitialEstimatedHours > TimeSpan.Zero)
|
||||
.Where(x => x.InitialEstimatedHours > TimeSpan.Zero && x.Status != TaskSectionStatus.Completed)
|
||||
.Include(x => x.Task)
|
||||
.ThenInclude(x => x.Phase)
|
||||
.ThenInclude(x => x.Project)
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
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<ProjectDeployBoardDetailTaskItem> Tasks);
|
||||
|
||||
public record ProjectDeployBoardDetailPhaseItem(
|
||||
string Name,
|
||||
TimeSpan TotalTimeSpan,
|
||||
TimeSpan DoneTimeSpan);
|
||||
|
||||
public record ProjectDeployBoardDetailTaskItem(
|
||||
string Name,
|
||||
TimeSpan TotalTimeSpan,
|
||||
TimeSpan DoneTimeSpan,
|
||||
List<ProjectDeployBoardDetailItemSkill> Skills)
|
||||
: ProjectDeployBoardDetailPhaseItem(Name, TotalTimeSpan, DoneTimeSpan);
|
||||
|
||||
public record ProjectDeployBoardDetailItemSkill(string OriginalUserFullName, string SkillName, int TimePercentage);
|
||||
|
||||
public record ProjectDeployBoardDetailsQuery(Guid PhaseId) : IBaseQuery<ProjectDeployBoardDetailsResponse>;
|
||||
|
||||
public class
|
||||
ProjectDeployBoardDetailsQueryHandler : IBaseQueryHandler<ProjectDeployBoardDetailsQuery,
|
||||
ProjectDeployBoardDetailsResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _dbContext;
|
||||
|
||||
public ProjectDeployBoardDetailsQueryHandler(IProgramManagerDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<ProjectDeployBoardDetailsResponse>> 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<ProjectDeployBoardDetailsResponse>.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 totalTimeSpent = s.GetTotalTimeSpent();
|
||||
|
||||
var timePercentage = s.FinalEstimatedHours.Ticks > 0
|
||||
? (int)((totalTimeSpent.Ticks / (double)s.FinalEstimatedHours.Ticks) * 100)
|
||||
: 0;
|
||||
|
||||
return new ProjectDeployBoardDetailItemSkill(
|
||||
originalUserFullName,
|
||||
skillName,
|
||||
timePercentage);
|
||||
}).ToList();
|
||||
|
||||
return new ProjectDeployBoardDetailTaskItem(
|
||||
t.Name,
|
||||
totalTime,
|
||||
doneTime,
|
||||
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 phaseRes = new ProjectDeployBoardDetailPhaseItem(phase.Name, totalTimeSpan, doneTimeSpan);
|
||||
|
||||
var res = new ProjectDeployBoardDetailsResponse(phaseRes, tasksRes);
|
||||
|
||||
return OperationResult<ProjectDeployBoardDetailsResponse>.Success(res);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectDeployBoardDetail;
|
||||
|
||||
public class ProjectDeployBoardDetailsQueryValidator:AbstractValidator<ProjectDeployBoardDetailsQuery>
|
||||
{
|
||||
public ProjectDeployBoardDetailsQueryValidator()
|
||||
{
|
||||
RuleFor(x=>x.PhaseId).NotNull().WithMessage("شناسه بخش اصلی نمیتواند خالی باشد");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Xml.Schema;
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectDeployBoardList;
|
||||
|
||||
public record ProjectDeployBoardListItem()
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string ProjectName { get; set; }
|
||||
public string PhaseName { get; set; }
|
||||
public int TotalTasks { get; set; }
|
||||
public int DoneTasks { get; set; }
|
||||
public TimeSpan TotalTimeSpan { get; set; }
|
||||
public TimeSpan DoneTimeSpan { get; set; }
|
||||
public ProjectDeployStatus DeployStatus { get; set; }
|
||||
}
|
||||
public record GetProjectsDeployBoardListResponse(List<ProjectDeployBoardListItem> Items);
|
||||
|
||||
|
||||
public record GetProjectDeployBoardListQuery():IBaseQuery<GetProjectsDeployBoardListResponse>;
|
||||
|
||||
public class ProjectDeployBoardListQueryHandler:IBaseQueryHandler<GetProjectDeployBoardListQuery, GetProjectsDeployBoardListResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _dbContext;
|
||||
private readonly IAuthHelper _authHelper;
|
||||
|
||||
|
||||
public ProjectDeployBoardListQueryHandler(IProgramManagerDbContext dbContext, IAuthHelper authHelper)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_authHelper = authHelper;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetProjectsDeployBoardListResponse>> Handle(GetProjectDeployBoardListQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var userId = _authHelper.GetCurrentUserId();
|
||||
if (userId == null)
|
||||
{
|
||||
return OperationResult<GetProjectsDeployBoardListResponse>.NotFound("کاربر یافت نشد");
|
||||
}
|
||||
|
||||
var query =await _dbContext.TaskSections
|
||||
.Include(x=>x.Activities)
|
||||
.Include(x=>x.Task)
|
||||
.ThenInclude(x => x.Phase)
|
||||
.ThenInclude(x => x.Project)
|
||||
.AsNoTracking()
|
||||
.Where(x => x.Status == TaskSectionStatus.Completed
|
||||
|| x.Status == TaskSectionStatus.PendingForCompletion
|
||||
|| (x.Task.Phase.DeployStatus != ProjectDeployStatus.NotCompleted
|
||||
&& x.InitialEstimatedHours>TimeSpan.Zero))
|
||||
.GroupBy(x=>x.Task.PhaseId).ToListAsync(cancellationToken: cancellationToken);
|
||||
|
||||
var list = query.Select(g => new ProjectDeployBoardListItem
|
||||
{
|
||||
Id = g.Key,
|
||||
ProjectName = g.First().Task.Phase.Project.Name,
|
||||
PhaseName = g.First().Task.Phase.Name,
|
||||
TotalTasks = g.Select(x => x.TaskId).Distinct().Count(),
|
||||
DoneTasks = g.Where(x => x.Status == TaskSectionStatus.Completed)
|
||||
.Select(x => x.TaskId).Distinct().Count(),
|
||||
TotalTimeSpan = TimeSpan.FromTicks(g.Sum(x => x.InitialEstimatedHours.Ticks)),
|
||||
DoneTimeSpan = TimeSpan.FromTicks(g.Sum(x=>x.GetTotalTimeSpent().Ticks)),
|
||||
DeployStatus = g.First().Task.Phase.DeployStatus
|
||||
}).ToList();
|
||||
var response = new GetProjectsDeployBoardListResponse(list);
|
||||
return OperationResult<GetProjectsDeployBoardListResponse>.Success(response);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user