add task section revision command
This commit is contained in:
@@ -25,4 +25,8 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Modules\TaskSectionRevision\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
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.FileManagementAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.FileManagementAgg.Enums;
|
||||
using GozareshgirProgramManager.Domain.FileManagementAgg.Repositories;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities.Task.TaskSection;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateTaskSectionRevision;
|
||||
|
||||
public record CreateTaskSectionRevisionCommand(string Message, List<IFormFile> Files, Guid SectionId) : IBaseCommand;
|
||||
|
||||
public class CreateTaskSectionRevisionCommandHandler : IBaseCommandHandler<CreateTaskSectionRevisionCommand>
|
||||
{
|
||||
private readonly ITaskSectionRevisionRepository _revisionRepository;
|
||||
private readonly IFileStorageService _fileStorageService;
|
||||
private readonly IAuthHelper _authHelper;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IUploadedFileRepository _fileRepository;
|
||||
private readonly IThumbnailGeneratorService _thumbnailService;
|
||||
|
||||
public CreateTaskSectionRevisionCommandHandler(ITaskSectionRevisionRepository revisionRepository,
|
||||
IFileStorageService fileStorageService, IAuthHelper authHelper, IUnitOfWork unitOfWork, IUploadedFileRepository fileRepository, IThumbnailGeneratorService thumbnailService)
|
||||
{
|
||||
_revisionRepository = revisionRepository;
|
||||
_fileStorageService = fileStorageService;
|
||||
_authHelper = authHelper;
|
||||
_unitOfWork = unitOfWork;
|
||||
_fileRepository = fileRepository;
|
||||
_thumbnailService = thumbnailService;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(CreateTaskSectionRevisionCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var currentId = _authHelper.GetCurrentUserId();
|
||||
|
||||
var entity = new TaskSectionRevision(request.SectionId, request.Message, currentId!.Value);
|
||||
|
||||
foreach (var file in request.Files)
|
||||
{
|
||||
if (file.Length == 0)
|
||||
{
|
||||
return OperationResult.ValidationError("فایل خالی است");
|
||||
}
|
||||
|
||||
const long maxFileSize = 100 * 1024 * 1024;
|
||||
if (file.Length > maxFileSize)
|
||||
{
|
||||
return OperationResult.ValidationError("حجم فایل بیش از حد مجاز است (حداکثر 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.TaskSectionRevision,
|
||||
uploadedByUserId: currentId!.Value,
|
||||
storageProvider: StorageProvider.LocalFileSystem
|
||||
);
|
||||
|
||||
await _fileRepository.AddAsync(uploadedFile);
|
||||
await _fileRepository.SaveChangesAsync();
|
||||
|
||||
try
|
||||
{
|
||||
await using var stream = file.OpenReadStream();
|
||||
var uploadResult = await _fileStorageService.UploadAsync(
|
||||
stream,
|
||||
uploadedFile.UniqueFileName,
|
||||
"TaskSectionRevision"
|
||||
);
|
||||
|
||||
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: "TaskSectionRevision");
|
||||
if (thumbnail.HasValue)
|
||||
{
|
||||
uploadedFile.SetThumbnail(thumbnail.Value.ThumbnailUrl);
|
||||
}
|
||||
}
|
||||
|
||||
await _fileRepository.UpdateAsync(uploadedFile);
|
||||
await _fileRepository.SaveChangesAsync();
|
||||
|
||||
var taskRevisionFile = new TaskRevisionFile(uploadedFile.Id);
|
||||
entity.AddFile(taskRevisionFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await _fileRepository.DeleteAsync(uploadedFile);
|
||||
await _fileRepository.SaveChangesAsync();
|
||||
|
||||
return OperationResult<MessageDto>.ValidationError($"خطا در آپلود فایل: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
await _revisionRepository.CreateAsync(entity);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ public enum FileCategory
|
||||
ProjectDocument = 3, // مستندات پروژه
|
||||
UserProfilePhoto = 4, // عکس پروفایل کاربر
|
||||
Report = 5, // گزارش
|
||||
Other = 6 // سایر
|
||||
Other = 6, // سایر
|
||||
TaskSectionRevision
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,49 @@
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.FileManagementAgg.Entities;
|
||||
|
||||
namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities.Task.TaskSection;
|
||||
|
||||
public class TaskSectionRevision:EntityBase<Guid>
|
||||
public class TaskSectionRevision : EntityBase<Guid>
|
||||
{
|
||||
public TaskSectionRevision(Guid taskSectionId,
|
||||
string message, long createdByUserId)
|
||||
{
|
||||
TaskSectionId = taskSectionId;
|
||||
Status = RevisionReviewStatus.Pending;
|
||||
Message = message;
|
||||
CreatedByUserId = createdByUserId;
|
||||
}
|
||||
|
||||
public Guid TaskSectionId { get; private set; }
|
||||
|
||||
public TaskSectionRevisionStatus Status { get; private set; }
|
||||
public RevisionReviewStatus Status { get; private set; }
|
||||
|
||||
|
||||
public string Message { get; private set; }
|
||||
|
||||
public Guid CreatedByUserId { get; private set; }
|
||||
public DateTime CreatedAt { get; private set; }
|
||||
public long CreatedByUserId { get; private set; }
|
||||
|
||||
public IReadOnlyCollection<TaskRevisionFile> Files => _files;
|
||||
private readonly List<TaskRevisionFile> _files = new();
|
||||
|
||||
public void AddFile(TaskRevisionFile file)
|
||||
{
|
||||
_files.Add(file);
|
||||
}
|
||||
|
||||
}
|
||||
public class TaskRevisionFile: EntityBase<Guid>
|
||||
{
|
||||
public TaskRevisionFile(Guid fileId)
|
||||
{
|
||||
FileId = fileId;
|
||||
}
|
||||
|
||||
public Guid FileId { get; private set; }
|
||||
}
|
||||
|
||||
public enum RevisionReviewStatus : short
|
||||
{
|
||||
Pending = 1,
|
||||
Reviewed = 2
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities.Task.TaskSection;
|
||||
|
||||
namespace GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
|
||||
public interface ITaskSectionRevisionRepository:IRepository<Guid,TaskSectionRevision>
|
||||
{
|
||||
|
||||
}
|
||||
@@ -100,7 +100,12 @@ public static class DependencyInjection
|
||||
services.AddScoped<JwtTokenGenerator>();
|
||||
services.AddScoped<IAuthHelper, AuthHelper>();
|
||||
|
||||
|
||||
//TaskSection Time Request
|
||||
services.AddScoped<ITaskSectionTimeRequestRepository, TaskSectionTimeRequestRepository>();
|
||||
|
||||
//TaskSection Revision
|
||||
services.AddScoped<ITaskSectionRevisionRepository, TaskSectionRevisionRepository>();
|
||||
|
||||
#region ServicesInjection
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities.Task.TaskSection;
|
||||
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 TaskSectionRevisionRepository:RepositoryBase<Guid,TaskSectionRevision>,ITaskSectionRevisionRepository
|
||||
{
|
||||
private readonly ProgramManagerDbContext _programManagerDbContext;
|
||||
public TaskSectionRevisionRepository(ProgramManagerDbContext programManagerDbContext) : base(programManagerDbContext)
|
||||
{
|
||||
_programManagerDbContext = programManagerDbContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities.Task.TaskSection;
|
||||
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 TaskSectionTimeRequestRepository:RepositoryBase<Guid,TaskSectionTimeRequest>,ITaskSectionTimeRequestRepository
|
||||
{
|
||||
private readonly ProgramManagerDbContext _context;
|
||||
public TaskSectionTimeRequestRepository(ProgramManagerDbContext context) : base(context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateTaskSectionRevision;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ServiceHost.BaseControllers;
|
||||
|
||||
namespace ServiceHost.Areas.Admin.Controllers.ProgramManager;
|
||||
|
||||
public class TaskSectionRevisionController:ProgramManagerBaseController
|
||||
{
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
public TaskSectionRevisionController(IMediator mediator)
|
||||
{
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
public async Task<ActionResult<OperationResult>> CreateTaskRevision([FromForm]CreateTaskSectionRevisionCommand command)
|
||||
{
|
||||
var res =await _mediator.Send(command);
|
||||
return Ok(res);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user