Files
Backend-Api/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeStatusSection/ChangeStatusSectionCommandHandler.cs

101 lines
5.1 KiB
C#

using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Domain._Common;
using GozareshgirProgramManager.Domain._Common.Exceptions;
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeStatusSection;
public record ChangeStatusSectionCommand(Guid SectionId, TaskSectionStatus Status) : IBaseCommand;
public class ChangeStatusSectionCommandHandler : IBaseCommandHandler<ChangeStatusSectionCommand>
{
private readonly IUnitOfWork _unitOfWork;
private readonly ITaskSectionRepository _taskSectionRepository;
private readonly IAuthHelper _authHelper;
public ChangeStatusSectionCommandHandler(ITaskSectionRepository taskSectionRepository,
IUnitOfWork unitOfWork, IAuthHelper authHelper)
{
_taskSectionRepository = taskSectionRepository;
_unitOfWork = unitOfWork;
_authHelper = authHelper;
}
public async Task<OperationResult> Handle(ChangeStatusSectionCommand request, CancellationToken cancellationToken)
{
// استفاده از متد مخصوص که Activities رو load می‌کنه
var section = await _taskSectionRepository.GetByIdWithActivitiesAsync(request.SectionId, cancellationToken);
if (section == null)
return OperationResult.NotFound("بخش مورد نظر یافت نشد");
if (section.Status == request.Status)
return OperationResult.Success();
long currentUser = _authHelper.GetCurrentUserId()
?? throw new UnAuthorizedException("کاربر احراز هویت نشده است");
// Validate state transitions
var validationResult = ValidateStateTransition(section.Status, request.Status);
if (!validationResult.IsSuccess)
return validationResult;
// Handle state machine logic
if (section.Status == TaskSectionStatus.InProgress)
{
// Coming FROM InProgress: Stop the active activity
section.StopWork(currentUser, request.Status);
}
else if (request.Status == TaskSectionStatus.InProgress)
{
// Going TO InProgress: Start work and create activity
section.StartWork(currentUser);
}
else
{
// All other transitions: Just update status
section.UpdateStatus(request.Status);
}
await _unitOfWork.SaveChangesAsync(cancellationToken);
return OperationResult.Success();
}
/// <summary>
/// Validates state transitions based on business rules:
/// - ReadyToStart: شروع نشده - Initial state only, cannot return to it once left
/// - InProgress: درحال انجام - Can transition from ReadyToStart, can go to Incomplete or Completed
/// - Incomplete: نیمه کاره - Can come from InProgress or other states
/// - Completed: اتمام رسیده - Can come from InProgress or other states
/// </summary>
private OperationResult ValidateStateTransition(TaskSectionStatus currentStatus, TaskSectionStatus targetStatus)
{
// Cannot transition to ReadyToStart once the section has been started
if (targetStatus == TaskSectionStatus.ReadyToStart)
return OperationResult.ValidationError("بخش نمی‌تواند به وضعیت 'آماده برای شروع' تغییر کند");
// From ReadyToStart, can only go to InProgress
if (currentStatus == TaskSectionStatus.ReadyToStart && targetStatus != TaskSectionStatus.InProgress)
return OperationResult.ValidationError("از وضعیت 'آماده برای شروع' فقط می‌توان به 'درحال انجام' رفت");
// Valid transitions matrix
var validTransitions = new Dictionary<TaskSectionStatus, List<TaskSectionStatus>>
{
{ TaskSectionStatus.ReadyToStart, new List<TaskSectionStatus> { TaskSectionStatus.InProgress } },
{ TaskSectionStatus.InProgress, new List<TaskSectionStatus> { TaskSectionStatus.Incomplete, TaskSectionStatus.Completed } },
{ TaskSectionStatus.Incomplete, new List<TaskSectionStatus> { TaskSectionStatus.InProgress, TaskSectionStatus.Completed } },
{ TaskSectionStatus.Completed, new List<TaskSectionStatus> { TaskSectionStatus.InProgress, TaskSectionStatus.Incomplete } }, // Can return to InProgress or Incomplete
{ TaskSectionStatus.NotAssigned, new List<TaskSectionStatus> { TaskSectionStatus.InProgress, TaskSectionStatus.ReadyToStart } }
};
if (!validTransitions.TryGetValue(currentStatus, out var allowedTargets))
return OperationResult.ValidationError($"وضعیت فعلی '{currentStatus}' نامعتبر است");
if (!allowedTargets.Contains(targetStatus))
return OperationResult.ValidationError(
$"نمی‌توان از وضعیت '{currentStatus}' به '{targetStatus}' رفت");
return OperationResult.Success();
}
}