Commit 8f8ad4cc authored by hasan khaddour's avatar hasan khaddour

add attchement load from file service

parent fb047242
......@@ -15,7 +15,7 @@ namespace PSManagement.Api
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Warning()
.WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
......
......@@ -11,6 +11,6 @@ namespace PSManagement.Application.Contracts.Storage
public interface IFileService
{
public Task<Result<String>> StoreFile(string fileName,IFormFile file);
public Task<Result<IFormFile>> RetreiveFile(string fileUrl);
}
}
using Microsoft.AspNetCore.Http;
namespace PSManagement.Application.Projects.Common
{
public record FileAttachmentDTO(
string AttachmentName,
string AttachmentDescription,
IFormFile File
);
}
......@@ -32,7 +32,7 @@ namespace PSManagement.Application.Projects.UseCases.Commands.ApproveProject
{
_specification.AddInclude(e => e.Steps);
Project project = await _projectsRepository.GetByIdAsync(request.ProjectId);
Project project = await _projectsRepository.GetByIdAsync(request.ProjectId,_specification);
if (project is null)
{
......
using Ardalis.Result;
using PSManagement.Application.Projects.Common;
using PSManagement.SharedKernel.CQRS.Query;
namespace PSManagement.Application.Projects.UseCases.Queries.GetFileByUrl
{
public record GetFileByUrlQuery(
string FileUrl,
int AttachmentId
) : IQuery<Result<FileAttachmentDTO>>;
}
using Ardalis.Result;
using AutoMapper;
using PSManagement.Application.Contracts.Storage;
using PSManagement.Application.Projects.Common;
using PSManagement.Domain.Projects.Entities;
using PSManagement.SharedKernel.CQRS.Query;
using PSManagement.SharedKernel.Repositories;
using System.Threading;
using System.Threading.Tasks;
namespace PSManagement.Application.Projects.UseCases.Queries.GetFileByUrl
{
public class GetFileByUrlQueryHandler : IQueryHandler<GetFileByUrlQuery, Result<FileAttachmentDTO>>
{
private readonly IRepository<Attachment> _attachmentRepository;
private readonly IFileService _fileService;
private readonly IMapper _mapper;
public GetFileByUrlQueryHandler(
IMapper mapper,
IRepository<Attachment> attachmentRepository,
IFileService fileService)
{
_mapper = mapper;
_attachmentRepository = attachmentRepository;
_fileService = fileService;
}
public async Task<Result<FileAttachmentDTO>> Handle(GetFileByUrlQuery request, CancellationToken cancellationToken)
{
var attachment = await _attachmentRepository.GetByIdAsync(request.AttachmentId);
if (attachment is null)
{
return Result.NotFound("Not found ");
}
var result = await _fileService.RetreiveFile(attachment.AttachmentUrl);
if (!result.IsSuccess)
{
return Result.NotFound("Not Found");
}
return Result.Success(new FileAttachmentDTO(attachment.AttachmentName, attachment.AttachmentDescription, result.Value));
}
}
}
......@@ -8,5 +8,4 @@ namespace PSManagement.Application.Projects.UseCases.Queries.GetParticipants
public record GetProjectParticipantsQuery(
int ProjectId
) : IQuery<Result<IEnumerable<EmployeeParticipateDTO>>>;
}
......@@ -30,6 +30,8 @@ namespace PSManagement.Application.Projects.UseCases.Queries.GetProject
public async Task<Result<ProjectDTO>> Handle(GetProjectByIdQuery request, CancellationToken cancellationToken)
{
_specification.Includes.Add(p=> p.EmployeeParticipates);
_specification.AddInclude("EmployeeParticipates.Employee");
_specification.Includes.Add(p => p.FinancialSpending);
_specification.Includes.Add(p => p.ProjectManager.Department);
_specification.Includes.Add(p => p.Attachments);
......
......@@ -56,7 +56,7 @@ namespace PSManagement.Application.Tracks.UseCaes.Commands.CompleteTrack
}
if (track.CheckEmployeeTrack()) {
if (!track.CheckEmployeeTrack()) {
return Result.Invalid(TracksErrors.InvailEmployeeTrack);
}
......
using Ardalis.Result;
using PSManagement.Domain.Steps.Repositories;
using PSManagement.Domain.Tracking;
using PSManagement.Domain.Tracking.Entities;
using PSManagement.Domain.Tracking.DomainErrors;
using PSManagement.Domain.Tracking.Specification;
using PSManagement.SharedKernel.CQRS.Command;
using PSManagement.SharedKernel.Interfaces;
using PSManagement.SharedKernel.Specification;
using PSManagement.SharedKernel.Repositories;
using System.Threading;
using System.Threading.Tasks;
......@@ -13,20 +20,31 @@ namespace PSManagement.Application.Tracks.UseCaes.Commands.RemoveTrack
{
private readonly ITracksRepository _tracksRepository;
private readonly IUnitOfWork _unitOfWork;
private readonly BaseSpecification<Track> _specification;
private readonly IRepository<StepTrack> _stepTracksRepository;
private readonly IRepository<EmployeeTrack> _employeeTracksRepository;
public RemoveTrackCommandHandler(
IUnitOfWork unitOfWork,
ITracksRepository tracksRepository
ITracksRepository tracksRepository,
IRepository<StepTrack> stepTracksRepository,
IRepository<EmployeeTrack> employeeTracksRepository
)
{
_employeeTracksRepository=employeeTracksRepository;
_stepTracksRepository = stepTracksRepository;
_specification = new TrackSpecification();
_unitOfWork = unitOfWork;
_tracksRepository = tracksRepository;
}
public async Task<Result> Handle(RemoveTrackCommand request, CancellationToken cancellationToken)
{
Track track = await _tracksRepository.GetByIdAsync(request.TrackId);
_specification.AddInclude(e => e.StepTracks);
_specification.AddInclude(e => e.EmployeeTracks);
Track track = await _tracksRepository.GetByIdAsync(request.TrackId,_specification);
if (track is null)
{
......@@ -35,6 +53,14 @@ namespace PSManagement.Application.Tracks.UseCaes.Commands.RemoveTrack
}
foreach(var emp in track.EmployeeTracks){
await _employeeTracksRepository.DeleteAsync(emp);
}
foreach(var emp in track.StepTracks){
await _stepTracksRepository.DeleteAsync(emp);
}
await _tracksRepository.DeleteAsync(track);
await _unitOfWork.SaveChangesAsync();
......
......@@ -56,6 +56,7 @@ namespace PSManagement.Application.Tracks.UseCaes.Commands.UpdateEmployeeWorkTra
employeeTrack.UpdateEmployeeWorkInfo(request.EmployeeWorkInfo);
employeeTrack.UpdateNotes(request.Notes);
System.Console.WriteLine(employeeTrack.EmployeeWork);
await _employeeTracksRepository.UpdateAsync(employeeTrack);
......
namespace PSManagement.Contracts.Projects.Requests
{
public record GetFileByUrlRequest(
string FileUrl,
int AttachmentId
);
}
using Microsoft.AspNetCore.Http;
namespace PSManagement.Contracts.Projects.Response
{
public record FileAttachmentResponse(
string AttachmentName,
string AttachmentDescription,
IFormFile File
);
}
......@@ -18,13 +18,13 @@ namespace PSManagement.Domain.Tracking
#region Encapsulation
public void UpdateEmployeeWork(EmployeeWork employeeWork)
{
EmployeeWork = employeeWork;
EmployeeWork = new(employeeWork.AssignedWorkingHours,employeeWork.WorkedHours,employeeWork.ContributingRatio);
}
public void UpdateEmployeeWorkInfo(EmployeeWorkInfo employeeWorkInfo)
{
EmployeeWorkInfo = employeeWorkInfo;
EmployeeWorkInfo = new (employeeWorkInfo.AssignedWork,employeeWorkInfo.PerformedWork,employeeWorkInfo.AssignedWorkEnd);
}
public void UpdateNotes(string notes)
......
......@@ -53,12 +53,15 @@ namespace PSManagement.Domain.Tracking
}
// this method check if the track is completed
public bool IsCompleted()
{
return TrackInfo.IsCompleted;
}
// this method check for the exitence of an employee in the track
//
public bool HasEmployee(int employeeId)
{
return EmployeeTracks.Any(e => e.EmployeeId == employeeId);
......@@ -80,13 +83,17 @@ namespace PSManagement.Domain.Tracking
public bool CheckEmployeeTrack()
{
//
int contributions = 0;
// calculate the total contribution of participatns in the tracks
foreach (EmployeeTrack employeeTrack in EmployeeTracks) {
contributions += employeeTrack.EmployeeWork.ContributingRatio;
}
// the track can be completed only if the contribution are equal to 100
return contributions == 100;
}
......
......@@ -41,5 +41,38 @@ namespace PSManagement.Infrastructure.Services.Storage
}
return Result.Success(fileName);
}
public async Task<Result<IFormFile>> RetreiveFile(string fileUrl)
{
if (string.IsNullOrWhiteSpace(fileUrl))
{
return Result.Invalid(new ValidationError("File URL couldn't be empty."));
}
var filePath = Path.Combine("wwwroot\\uploads", fileUrl);
if (!File.Exists(filePath))
{
return Result.Invalid(new ValidationError("File not found."));
}
var memoryStream = new MemoryStream();
using (var stream = new FileStream(filePath, FileMode.Open))
{
await stream.CopyToAsync(memoryStream);
}
memoryStream.Position = 0; // Reset the stream position to the beginning
// Create a new form file to return
IFormFile formFile = new FormFile(memoryStream, 0, memoryStream.Length, null, Path.GetFileName(filePath))
{
Headers = new HeaderDictionary(),
ContentType = "application/octet-stream"
};
return Result.Success(formFile);
}
}
}
......@@ -30,6 +30,7 @@ using PSManagement.Application.Projects.UseCases.Commands.RemoveAttachment;
using PSManagement.Application.Projects.UseCases.Queries.GetProjectCompletion;
using PSManagement.Domain.Identity.Constants;
using Microsoft.AspNetCore.Authorization;
using PSManagement.Application.Projects.UseCases.Queries.GetFileByUrl;
namespace PSManagement.Presentation.Controllers.Projects
{
......@@ -336,6 +337,15 @@ namespace PSManagement.Presentation.Controllers.Projects
return HandleResult(_mapper.Map<Result<IEnumerable<AttachmentReponse>>>(result));
}
[HttpGet("Attachment")]
public async Task<IActionResult> GetAttachments([FromQuery] GetFileByUrlRequest request)
{
var query = _mapper.Map<GetFileByUrlQuery>(request);
var result = await _sender.Send(query);
return HandleResult(_mapper.Map<Result<FileAttachmentResponse>>(result));
}
#endregion Attachments Management
}
......
......@@ -43,11 +43,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{A01E75A3
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ArchitectureTests", "ArchitectureTests", "{EECB1F9F-F97D-4A58-BC3D-62490B931836}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{9E74DD5B-202D-4DAD-9A08-3C7340CEF939}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IntegerationTests", "IntegerationTests", "{83FB2F8C-3B65-44D8-A4A7-8E87166233CD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PSManagement.ArchitectureTests", "PSManagement.ArchitectureTests\PSManagement.ArchitectureTests.csproj", "{394812BD-ECB4-4B7B-A6FF-4310E145450A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PSManagement.ArchitectureTests", "PSManagement.ArchitectureTests\PSManagement.ArchitectureTests.csproj", "{394812BD-ECB4-4B7B-A6FF-4310E145450A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
......@@ -114,8 +110,6 @@ Global
{E40CD9A8-20E3-4D39-992B-F7DA048E3B4C} = {7C209DBF-1DB8-4E86-BD78-F689B70D5BD1}
{2FF0133A-7AC6-4346-AEC2-CB5C36939AC7} = {7C209DBF-1DB8-4E86-BD78-F689B70D5BD1}
{EECB1F9F-F97D-4A58-BC3D-62490B931836} = {A01E75A3-EF06-4880-8EFE-2E2D8EC0FA9F}
{9E74DD5B-202D-4DAD-9A08-3C7340CEF939} = {A01E75A3-EF06-4880-8EFE-2E2D8EC0FA9F}
{83FB2F8C-3B65-44D8-A4A7-8E87166233CD} = {A01E75A3-EF06-4880-8EFE-2E2D8EC0FA9F}
{394812BD-ECB4-4B7B-A6FF-4310E145450A} = {EECB1F9F-F97D-4A58-BC3D-62490B931836}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment