refactor GetProjectsListQueryHandler to improve task and phase status aggregation logic
This commit is contained in:
@@ -228,28 +228,30 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler<GetProjectsListQuer
|
|||||||
// For projects: gather all phases, then tasks, then sections
|
// For projects: gather all phases, then tasks, then sections
|
||||||
var phases = await _context.ProjectPhases
|
var phases = await _context.ProjectPhases
|
||||||
.Where(ph => projectIds.Contains(ph.ProjectId))
|
.Where(ph => projectIds.Contains(ph.ProjectId))
|
||||||
.Select(ph => ph.Id)
|
.Select(ph => new { ph.Id, ph.ProjectId })
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
var phaseIds = phases.Select(ph => ph.Id).ToList();
|
||||||
var tasks = await _context.ProjectTasks
|
var tasks = await _context.ProjectTasks
|
||||||
.Where(t => phases.Contains(t.PhaseId))
|
.Where(t => phaseIds.Contains(t.PhaseId))
|
||||||
.Select(t => t.Id)
|
.Select(t => new { t.Id, t.PhaseId })
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
var taskIds = tasks.Select(t => t.Id).ToList();
|
||||||
var sections = await _context.TaskSections
|
var sections = await _context.TaskSections
|
||||||
.Include(s => s.Skill)
|
.Include(s => s.Skill)
|
||||||
.Where(s => tasks.Contains(s.TaskId))
|
.Where(s => taskIds.Contains(s.TaskId))
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
// Convert to tuple list for AggregatePhaseStatuses
|
||||||
|
var tasksList = tasks.Select(t => (t.Id, t.PhaseId)).ToList();
|
||||||
|
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
var relatedPhases = phases; // used for filtering tasks by project
|
var projectPhaseIds = phases.Where(ph => ph.ProjectId == item.Id).Select(ph => ph.Id).ToList();
|
||||||
var relatedTasks = await _context.ProjectTasks
|
|
||||||
.Where(t => t.PhaseId != Guid.Empty && relatedPhases.Contains(t.PhaseId))
|
// برای هر Skill، وضعیتهای تمام Phases را تجمیع کنیم
|
||||||
.Select(t => t.Id)
|
item.Backend = AggregatePhaseStatuses(projectPhaseIds, tasksList, sections, "Backend");
|
||||||
.ToListAsync(cancellationToken);
|
item.Front = AggregatePhaseStatuses(projectPhaseIds, tasksList, sections, "Frontend");
|
||||||
var itemSections = sections.Where(s => relatedTasks.Contains(s.TaskId));
|
item.Design = AggregatePhaseStatuses(projectPhaseIds, tasksList, sections, "UI/UX Design");
|
||||||
item.Backend = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "Backend"));
|
|
||||||
item.Front = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "Frontend"));
|
|
||||||
item.Design = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "UI/UX Design"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,24 +261,22 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler<GetProjectsListQuer
|
|||||||
// For phases: gather tasks, then sections
|
// For phases: gather tasks, then sections
|
||||||
var tasks = await _context.ProjectTasks
|
var tasks = await _context.ProjectTasks
|
||||||
.Where(t => phaseIds.Contains(t.PhaseId))
|
.Where(t => phaseIds.Contains(t.PhaseId))
|
||||||
.Select(t => t.Id)
|
.Select(t => new { t.Id, t.PhaseId })
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
var taskIds = tasks.Select(t => t.Id).ToList();
|
||||||
var sections = await _context.TaskSections
|
var sections = await _context.TaskSections
|
||||||
.Include(s => s.Skill)
|
.Include(s => s.Skill)
|
||||||
.Where(s => tasks.Contains(s.TaskId))
|
.Where(s => taskIds.Contains(s.TaskId))
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
// Filter tasks for this phase
|
var phaseTaskIds = tasks.Where(t => t.PhaseId == item.Id).Select(t => t.Id).ToList();
|
||||||
var phaseTaskIds = await _context.ProjectTasks
|
|
||||||
.Where(t => t.PhaseId == item.Id)
|
|
||||||
.Select(t => t.Id)
|
|
||||||
.ToListAsync(cancellationToken);
|
|
||||||
var itemSections = sections.Where(s => phaseTaskIds.Contains(s.TaskId));
|
var itemSections = sections.Where(s => phaseTaskIds.Contains(s.TaskId));
|
||||||
item.Backend = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "Backend"));
|
|
||||||
item.Front = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "Frontend"));
|
item.Backend = AggregateAssignmentStatus(itemSections.Where(x => x.Skill?.Name == "Backend"));
|
||||||
item.Design = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "UI/UX Design"));
|
item.Front = AggregateAssignmentStatus(itemSections.Where(x => x.Skill?.Name == "Frontend"));
|
||||||
|
item.Design = AggregateAssignmentStatus(itemSections.Where(x => x.Skill?.Name == "UI/UX Design"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,4 +380,57 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler<GetProjectsListQuer
|
|||||||
// تعیین تکلیف نشده: نه user دارد نه time
|
// تعیین تکلیف نشده: نه user دارد نه time
|
||||||
return AssignmentStatus.Unassigned;
|
return AssignmentStatus.Unassigned;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static AssignmentStatus AggregatePhaseStatuses(
|
||||||
|
List<Guid> phaseIds,
|
||||||
|
List<(Guid Id, Guid PhaseId)> tasks,
|
||||||
|
List<TaskSection> sections,
|
||||||
|
string skillName)
|
||||||
|
{
|
||||||
|
var phaseStatuses = new List<AssignmentStatus>();
|
||||||
|
|
||||||
|
foreach (var phaseId in phaseIds)
|
||||||
|
{
|
||||||
|
var phaseTaskIds = tasks.Where(t => t.PhaseId == phaseId).Select(t => t.Id).ToList();
|
||||||
|
var phaseSections = sections.Where(s => phaseTaskIds.Contains(s.TaskId) && s.Skill?.Name == skillName);
|
||||||
|
var phaseStatus = AggregateAssignmentStatus(phaseSections);
|
||||||
|
phaseStatuses.Add(phaseStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// الآن تجمیع وضعیتهای Phases
|
||||||
|
if (!phaseStatuses.Any())
|
||||||
|
return AssignmentStatus.Unassigned;
|
||||||
|
|
||||||
|
// اگر هر یکی Unassigned باشد → Unassigned
|
||||||
|
if (phaseStatuses.Any(s => s == AssignmentStatus.Unassigned))
|
||||||
|
return AssignmentStatus.Unassigned;
|
||||||
|
|
||||||
|
// اگر Unassigned نیست و هر یکی UserOnly باشد → UserOnly
|
||||||
|
if (phaseStatuses.Any(s => s == AssignmentStatus.UserOnly))
|
||||||
|
return AssignmentStatus.UserOnly;
|
||||||
|
|
||||||
|
// فقط اگر همه Assigned باشند → Assigned
|
||||||
|
return AssignmentStatus.Assigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AssignmentStatus AggregateAssignmentStatus(IEnumerable<TaskSection> sections)
|
||||||
|
{
|
||||||
|
var sectionList = sections.ToList();
|
||||||
|
if (!sectionList.Any())
|
||||||
|
return AssignmentStatus.Unassigned;
|
||||||
|
|
||||||
|
var statuses = sectionList.Select(GetAssignmentStatus).ToList();
|
||||||
|
|
||||||
|
// اگر هر یکی Unassigned باشد → Unassigned (بدترین وضعیت)
|
||||||
|
if (statuses.Any(s => s == AssignmentStatus.Unassigned))
|
||||||
|
return AssignmentStatus.Unassigned;
|
||||||
|
|
||||||
|
// اگر Unassigned نیست و هر یکی UserOnly باشد → UserOnly (وضعیت متوسط)
|
||||||
|
if (statuses.Any(s => s == AssignmentStatus.UserOnly))
|
||||||
|
return AssignmentStatus.UserOnly;
|
||||||
|
|
||||||
|
// فقط اگر همه Assigned باشند → Assigned (بهترین وضعیت)
|
||||||
|
return AssignmentStatus.Assigned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user