comand and query for bug section

This commit is contained in:
gozareshgir
2026-01-27 16:11:31 +03:30
parent 17f117726e
commit e5c96c8bcb
6 changed files with 231 additions and 6 deletions

View File

@@ -0,0 +1,146 @@
using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Application.Modules.TaskChat.DTOs;
using GozareshgirProgramManager.Application.Services.FileManagement;
using GozareshgirProgramManager.Domain._Common;
using GozareshgirProgramManager.Domain._Common.Exceptions;
using GozareshgirProgramManager.Domain.FileManagementAgg.Entities;
using GozareshgirProgramManager.Domain.FileManagementAgg.Enums;
using GozareshgirProgramManager.Domain.FileManagementAgg.Repositories;
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
using Microsoft.AspNetCore.Http;
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateBugSection;
public class CreateBugSectionCommandHandler : IBaseCommandHandler<CreateBugSectionCommand>
{
readonly IUnitOfWork _unitOfWork;
readonly IBugSectionRepository _bugSectionRepository;
readonly IUploadedFileRepository _uploadedFileRepository;
private readonly IFileStorageService _fileStorageService;
private readonly IThumbnailGeneratorService _thumbnailService;
private readonly IAuthHelper _authHelper;
public CreateBugSectionCommandHandler(IUnitOfWork unitOfWork, IBugSectionRepository bugSectionRepository, IUploadedFileRepository uploadedFileRepository, IAuthHelper authHelper, IFileStorageService fileStorageService, IThumbnailGeneratorService thumbnailService)
{
_unitOfWork = unitOfWork;
_bugSectionRepository = bugSectionRepository;
_uploadedFileRepository = uploadedFileRepository;
_authHelper = authHelper;
_fileStorageService = fileStorageService;
_thumbnailService = thumbnailService;
}
public async Task<OperationResult> Handle(CreateBugSectionCommand request, CancellationToken cancellationToken)
{
var currentUserId = _authHelper.GetCurrentUserId()
?? throw new UnAuthorizedException("کاربر احراز هویت نشده است");
#region Validation
if (_bugSectionRepository.Exists(x => x.TaskId == request.TaskId))
return OperationResult.Failure("برای این بخش قبلا تسک باگ ایجاد شده است");
if (string.IsNullOrWhiteSpace(request.InitialDescription))
return OperationResult.Failure("توضیحات باگ خالی است");
if (request.OriginalAssignedUserId == 0)
return OperationResult.Failure("کاربر انتخاب نشده است");
#endregion
var bug = new BugSection(request.TaskId, request.InitialDescription, request.OriginalAssignedUserId,
request.Priority);
await _bugSectionRepository.CreateAsync(bug);
if (request.Files.Any())
{
foreach (var file in request.Files)
{
const long maxFileSize = 100 * 1024 * 1024;
if (file.Length > maxFileSize)
return OperationResult.Failure("حجم فایل بیش از حد مجاز است (حداکثر 100MB)");
var fileType = DetectFileType(file.ContentType, Path.GetExtension(file.FileName));
var uploadedFile = new UploadedFile(
originalFileName: file.FileName,
fileSizeBytes: file.Length,
mimeType: file.ContentType,
fileType: fileType,
category: FileCategory.TaskChatMessage,
uploadedByUserId: currentUserId,
storageProvider: StorageProvider.LocalFileSystem
);
await _uploadedFileRepository.AddAsync(uploadedFile);
try
{
using var stream = file.OpenReadStream();
var uploadResult = await _fileStorageService.UploadAsync(
stream,
uploadedFile.UniqueFileName,
"TaskChatMessage"
);
uploadedFile.CompleteUpload(uploadResult.StoragePath, uploadResult.StorageUrl);
if (fileType == FileType.Image)
{
var dimensions = await _thumbnailService.GetImageDimensionsAsync(uploadResult.StoragePath);
if (dimensions.HasValue)
{
uploadedFile.SetImageDimensions(dimensions.Value.Width, dimensions.Value.Height);
}
var thumbnail = await _thumbnailService
.GenerateImageThumbnailAsync(uploadResult.StoragePath, category: "TaskChatMessage");
if (thumbnail.HasValue)
{
uploadedFile.SetThumbnail(thumbnail.Value.ThumbnailUrl);
}
}
await _uploadedFileRepository.UpdateAsync(uploadedFile);
}
catch (Exception ex)
{
await _uploadedFileRepository.DeleteAsync(uploadedFile);
return OperationResult<MessageDto>.ValidationError($"خطا در آپلود فایل: {ex.Message}");
}
bug.AddDocument(new BugDocument(uploadedFile.Id));
}
}
await _unitOfWork.SaveChangesAsync(cancellationToken);
return OperationResult.Success();
}
private FileType DetectFileType(string mimeType, string extension)
{
if (mimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
return FileType.Image;
if (mimeType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
return FileType.Video;
if (mimeType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase))
return FileType.Audio;
if (new[] { ".zip", ".rar", ".7z", ".tar", ".gz" }.Contains(extension.ToLower()))
return FileType.Archive;
return FileType.Document;
}
}
public record CreateBugSectionCommand(Guid TaskId, string InitialDescription, long OriginalAssignedUserId, ProjectTaskPriority Priority, List<IFormFile> Files) : IBaseCommand;

View File

@@ -0,0 +1,29 @@
using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using Microsoft.EntityFrameworkCore;
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetBugModalDetails;
public class GetBugModalDetailsQueryHandler : IBaseQueryHandler<GetBugModalDetailsQuery, GetBugModalDetailsResponse>
{
private readonly IProgramManagerDbContext _context;
public GetBugModalDetailsQueryHandler(IProgramManagerDbContext context)
{
_context = context;
}
public async Task<OperationResult<GetBugModalDetailsResponse>> Handle(GetBugModalDetailsQuery request, CancellationToken cancellationToken)
{
var projectTask =await _context.ProjectTasks.FirstOrDefaultAsync(x=>x.Id == request.TaskId);
if(projectTask == null)
return OperationResult<GetBugModalDetailsResponse>.NotFound("کاربر یافت نشد");
var response = new GetBugModalDetailsResponse(projectTask.Name);
return OperationResult<GetBugModalDetailsResponse>.Success(response);
}
}
public record GetBugModalDetailsQuery(Guid TaskId) : IBaseQuery<GetBugModalDetailsResponse>;
public record GetBugModalDetailsResponse(string Name);

View File

@@ -0,0 +1,9 @@
using GozareshgirProgramManager.Domain._Common;
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
namespace GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
public interface IBugSectionRepository : IRepository<Guid,BugSection>
{
}

View File

@@ -80,7 +80,8 @@ public static class DependencyInjection
services.AddScoped<ITaskSectionActivityRepository, TaskSectionActivityRepository>();
services.AddScoped<IPhaseSectionRepository, PhaseSectionRepository>();
services.AddScoped<IProjectSectionRepository, ProjectSectionRepository>();
services.AddScoped<IBugSectionRepository, BugSectionRepository>();
services.AddScoped<ISkillRepository, SkillRepository>();
services.AddScoped<IUserRefreshTokenRepository, UserRefreshTokenRepository>();

View File

@@ -0,0 +1,16 @@
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
using GozareshgirProgramManager.Infrastructure.Persistence._Common;
using GozareshgirProgramManager.Infrastructure.Persistence.Context;
using Microsoft.EntityFrameworkCore;
namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories;
public class BugSectionRepository : RepositoryBase<Guid,BugSection>, IBugSectionRepository
{
private readonly ProgramManagerDbContext _context;
public BugSectionRepository(ProgramManagerDbContext context) : base(context)
{
_context = context;
}
}

View File

@@ -1,29 +1,31 @@
using System.Runtime.InteropServices;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.ApproveTaskSectionCompletion;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.AssignProject;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.AutoPendingFullTimeTaskSections;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.AutoStopOverTimeTaskSections;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.AutoUpdateDeployStatus;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeDeployStatusProject;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeStatusSection;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeTaskPriority;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateBugSection;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.DeleteProject;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.EditProject;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectAssignDetails;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectHierarchySearch;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardDetail;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectDeployBoardDetail;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectDeployBoardList;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectHierarchySearch;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using ServiceHost.BaseControllers;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeTaskPriority;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.AutoPendingFullTimeTaskSections;
using System.Runtime.InteropServices;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetBugModalDetails;
namespace ServiceHost.Areas.Admin.Controllers.ProgramManager;
@@ -176,5 +178,27 @@ public class ProjectController : ProgramManagerBaseController
var res = await _mediator.Send(command);
return res;
}
[HttpGet("GetCreateBugModalDetails")]
public async Task<ActionResult<OperationResult<GetBugModalDetailsResponse>>> GetCreateBugModalDetails(
[FromQuery] GetBugModalDetailsQuery query)
{
var res = await _mediator.Send(query);
return res;
}
/// <summary>
/// ایجاد تسک باگ
/// </summary>
/// <param name="commnd"></param>
/// <returns></returns>
[HttpPost("CreateBugSection")]
public async Task<ActionResult<OperationResult>> CreateBugSection([FromBody] CreateBugSectionCommand commnd)
{
var res = await _mediator.Send(commnd);
return res;
}
}