101 lines
5.1 KiB
C#
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();
|
|
}
|
|
} |