diff --git a/BMA.EHR.Application/ApplicationServicesRegistration.cs b/BMA.EHR.Application/ApplicationServicesRegistration.cs index b292256e..9a95c210 100644 --- a/BMA.EHR.Application/ApplicationServicesRegistration.cs +++ b/BMA.EHR.Application/ApplicationServicesRegistration.cs @@ -53,6 +53,8 @@ namespace BMA.EHR.Application services.AddTransient(); services.AddTransient(); + services.AddTransient(); + return services; } diff --git a/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveRequestRepository.cs b/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveRequestRepository.cs index a1b97c1d..02ab2096 100644 --- a/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveRequestRepository.cs +++ b/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveRequestRepository.cs @@ -68,12 +68,24 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests var data = await _dbContext.Set().AsQueryable() .Include(x => x.LeaveDocument) .Include(x => x.LeaveDraftDocument) + .Include(x => x.LeaveCancelDocument) .Include(x => x.Type) .FirstOrDefaultAsync(x => x.Id == id); return data; } + public override async Task UpdateAsync(LeaveRequest entity) + { + _dbContext.Attatch(entity.LeaveCancelDocument); + _dbContext.Attatch(entity.LeaveDraftDocument); + _dbContext.Attatch(entity.LeaveDocument); + _dbContext.Attatch(entity.Type); + + return await base.UpdateAsync(entity); + } + + #endregion public async Task> GetLeaveRequestByYearAsync(int year) @@ -182,18 +194,19 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests public async Task> GetCancelLeaveRequestForAdminAsync(int year, Guid type, string status) { - var rawData = _dbContext.Set().AsQueryable() + var rawData = _dbContext.Set() .Include(x => x.Type) - .Where(x => x.LeaveStatus == "DELETE"); + .Where(x => x.LeaveStatus == "DELETE") + .AsQueryable(); if (year != 0) - rawData = (IIncludableQueryable)rawData.Where(x => x.LeaveStartDate.Year == year); + rawData = rawData.Where(x => x.LeaveStartDate.Year == year); if (type != Guid.Empty) - rawData = (IIncludableQueryable)rawData.Where(x => x.Type.Id == type); + rawData = rawData.Where(x => x.Type.Id == type); if (status.Trim().ToUpper() != "ALL") - rawData = (IIncludableQueryable)rawData.Where(x => x.LeaveCancelStatus == status); + rawData = rawData.Where(x => x.LeaveCancelStatus == status); return await rawData.ToListAsync(); } diff --git a/BMA.EHR.Application/Repositories/MetaData/HolidayRepository.cs b/BMA.EHR.Application/Repositories/MetaData/HolidayRepository.cs index 1802c608..4575a8e2 100644 --- a/BMA.EHR.Application/Repositories/MetaData/HolidayRepository.cs +++ b/BMA.EHR.Application/Repositories/MetaData/HolidayRepository.cs @@ -26,15 +26,30 @@ namespace BMA.EHR.Application.Repositories.MetaData #region " Methods " - public async Task GetHolidayCountAsync(DateTime startDate,DateTime endDate, string category = "NORMAL") + public async Task GetHolidayCountAsync(DateTime startDate, DateTime endDate, string category = "NORMAL") { var data = await _dbContext.Set().AsQueryable() + .Where(x => x.Category == category) .Where(x => x.HolidayDate.Date >= startDate && x.HolidayDate.Date <= endDate) .CountAsync(); return data; } + public int GetWeekEndCount(DateTime startDate, DateTime endDate) + { + var dates = new List(); + + for (DateTime i = startDate; i < endDate; i = i.AddDays(1)) + { + dates.Add(i); + } + + var count = dates.Where(d => d.DayOfWeek == DayOfWeek.Saturday || d.DayOfWeek == DayOfWeek.Sunday).Count(); + + return count; + } + #endregion } } diff --git a/BMA.EHR.Application/Repositories/MinIOLeaveService.cs b/BMA.EHR.Application/Repositories/MinIOLeaveService.cs new file mode 100644 index 00000000..f2a30657 --- /dev/null +++ b/BMA.EHR.Application/Repositories/MinIOLeaveService.cs @@ -0,0 +1,446 @@ +using Amazon.S3.Model; +using Amazon.S3; +using BMA.EHR.Application.Common.Interfaces; +using BMA.EHR.Domain.Models.Organizations; +using BMA.EHR.Domain.Shared; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using MimeTypes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BMA.EHR.Domain.Models.Documents; +using Microsoft.EntityFrameworkCore; +using System.Net.Http.Headers; + +namespace BMA.EHR.Application.Repositories +{ + public class MinIOLeaveService + { + #region " Fields " + + private readonly ILeaveDbContext _dbContext; + private readonly IConfiguration _configuration; + private readonly AmazonS3Client _s3Client; + private readonly IWebHostEnvironment _hostingEnvironment; + private string _bucketName = string.Empty; + + #endregion + + #region " Constructors " + + public MinIOLeaveService(ILeaveDbContext dbContext, + IConfiguration configuration, + IWebHostEnvironment hostingEnvironment) + { + _dbContext = dbContext; + _configuration = configuration; + _hostingEnvironment = hostingEnvironment; + + var config = new AmazonS3Config + { + ServiceURL = _configuration["MinIO:Endpoint"], + ForcePathStyle = true + }; + + _s3Client = new AmazonS3Client(_configuration["MinIO:AccessKey"], _configuration["MinIO:SecretKey"], config); + this._bucketName = _configuration["MinIO:BucketName"] ?? "bma-recruit"; + } + + #endregion + + #region " Methods " + + public async Task UploadFileAsync(IFormFile file, string newFileName = "") + { + var fileName = ""; + var fileExt = Path.GetExtension(file.FileName); + if (newFileName != "") + fileName = $"{newFileName}"; + else + fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"'); + + + var tmpDir = Path.Combine("tmp"); + if (!Directory.Exists(tmpDir)) + Directory.CreateDirectory(tmpDir); + + var tmpFile = Path.Combine(tmpDir, $"tmp_{DateTime.Now.ToString("ddMMyyyyHHmmss")}{fileExt}"); + + try + { + using (var ms = new MemoryStream()) + { + var id = Guid.NewGuid(); + file.CopyTo(ms); + var fileBytes = ms.ToArray(); + System.IO.MemoryStream filestream = new System.IO.MemoryStream(fileBytes); + + var request = new PutObjectRequest + { + BucketName = _bucketName, + Key = id.ToString("D"), + InputStream = filestream, + ContentType = file.ContentType, + CannedACL = S3CannedACL.PublicRead + }; + + await _s3Client.PutObjectAsync(request); + + // create document object + var doc = new Document() + { + FileName = fileName, + FileType = file.ContentType, + FileSize = Convert.ToInt32(file.Length), + ObjectRefId = id, + CreatedDate = DateTime.Now + }; + await _dbContext.Set().AddAsync(doc); + await _dbContext.SaveChangesAsync(); + + return doc; + } + } + catch + { + throw; + } + finally + { + File.Delete(tmpFile); + } + } + + public async Task DownloadFileAsync(Guid fileId) + { + try + { + var doc = await _dbContext.Set().AsQueryable() + .FirstOrDefaultAsync(x => x.Id == fileId); + + if (doc == null) + throw new Exception(GlobalMessages.FileNotFoundOnServer); + + using (var memoryStream = new MemoryStream()) + { + GetObjectRequest request = new GetObjectRequest + { + BucketName = _bucketName, + Key = doc.ObjectRefId.ToString("D") + }; + + using (GetObjectResponse response = await _s3Client.GetObjectAsync(request)) + { + using (Stream responseStream = response.ResponseStream) + { + responseStream.CopyTo(memoryStream); + } + } + + var fileContent = memoryStream.ToArray(); + + return new FileDownloadResponse + { + FileName = doc.FileName, + FileType = doc.FileType, + FileContent = fileContent + }; + }; + } + catch + { + throw; + } + } + + public async Task DeleteFileAsync(Guid fileId) + { + try + { + var doc = await _dbContext.Set().AsQueryable() + .FirstOrDefaultAsync(x => x.Id == fileId); + + if (doc == null) + throw new Exception(GlobalMessages.FileNotFoundOnServer); + else + { + DeleteObjectRequest request = new DeleteObjectRequest + { + BucketName = _bucketName, + Key = doc?.ObjectRefId.ToString("D") + }; + + // delete from minio + await _s3Client.DeleteObjectAsync(request); + + _dbContext.Set().Remove(doc); + await _dbContext.SaveChangesAsync(); + } + } + catch + { + throw; + } + } + + public async Task ImagesPath(Guid? fileId) + { + if (fileId == null) + return ""; + + var doc = await _dbContext.Set().AsQueryable() + .FirstOrDefaultAsync(x => x.Id == fileId); + + if (doc == null) + throw new Exception(GlobalMessages.FileNotFoundOnServer); + var config = new AmazonS3Config + { + ServiceURL = _configuration["MinIO:Endpoint"], + ForcePathStyle = true + }; + + DateTime expires = DateTime.UtcNow.AddHours(6); + var _protocol = _configuration["Protocol"]; + GetPreSignedUrlRequest request = new GetPreSignedUrlRequest + { + BucketName = _bucketName, + Key = doc?.ObjectRefId.ToString("D"), + Expires = expires, + Protocol = _protocol == "HTTPS" ? Protocol.HTTPS : Protocol.HTTP + }; + string path = _s3Client.GetPreSignedURL(request); + + return path; + } + + public async Task ImagesPathByName(string fileName) + { + var config = new AmazonS3Config + { + ServiceURL = _configuration["MinIO:Endpoint"], + ForcePathStyle = true + }; + + DateTime expires = DateTime.UtcNow.AddHours(6); + var _protocol = _configuration["Protocol"]; + GetPreSignedUrlRequest request = new GetPreSignedUrlRequest + { + BucketName = _bucketName, + Key = fileName, + Expires = expires, + Protocol = _protocol == "HTTPS" ? Protocol.HTTPS : Protocol.HTTP + }; + string path = _s3Client.GetPreSignedURL(request); + + return path; + } + + #endregion + + private async Task IsExistBucketAsync(string bucketName) + { + try + { + var response = await _s3Client.ListObjectsV2Async(new ListObjectsV2Request + { + BucketName = bucketName + }); + + return true; + } + catch + { + return false; + } + } + + private async Task CreateBucketAsync(string bucketName) + { + try + { + var request = new PutBucketRequest + { + BucketName = bucketName, + UseClientRegion = true, + }; + + var response = await _s3Client.PutBucketAsync(request); + return response.HttpStatusCode == System.Net.HttpStatusCode.OK; + } + catch + { + return false; + } + } + + public List GetAllIdByRoot(Guid? id) + { + try + { + var ret = new List(); + if (id == null) + return ret; + + var oc = _dbContext.Set().FirstOrDefault(x => x.Id == id); + if (oc != null) + ret.Add(oc.Id); + + var child = _dbContext.Set().AsQueryable().Where(x => x.Parent != null && x.Parent.Id == id).ToList(); + if (child.Any()) + { + foreach (var item in child) + { + ret.AddRange(GetAllIdByRoot(item.Id)); + } + } + + return ret; + } + catch + { + throw; + } + } + + public async Task UploadFileAsyncTemp(string fileName, string subFolder) + { + try + { + var fileContents = File.ReadAllBytes(fileName); + System.IO.MemoryStream filestream = new System.IO.MemoryStream(fileContents); + //var fileNameWithoutExt = Path.GetFileNameWithoutExtension(fileName); + var fileExt = Path.GetExtension(fileName); + var fileType = MimeTypeMap.GetMimeType(fileExt); + var file_name = Path.GetFileName(fileName); + Console.WriteLine($"{_bucketName}{subFolder}"); + Console.WriteLine(fileName); + Console.WriteLine(file_name); + Console.WriteLine(filestream); + Console.WriteLine(fileType); + + var request = new PutObjectRequest + { + BucketName = $"{_bucketName}", + // BucketName = $"{_bucketName}{subFolder}", + Key = file_name, + InputStream = filestream, + ContentType = fileType, + CannedACL = S3CannedACL.PublicRead + }; + + await _s3Client.PutObjectAsync(request); + } + catch + { + throw; + } + } + + public async Task UploadFileAsync(string fileName, MemoryStream fileStream) + { + try + { + //var fileTransferUtility = new TransferUtility(_s3Client); + + var fileExt = Path.GetExtension(fileName); + var fileType = MimeTypeMap.GetMimeType(fileExt); + //var file_name = Path.GetFileName(fileName); + + var request = new PutObjectRequest + { + BucketName = _bucketName, + Key = fileName, + InputStream = fileStream, + ContentType = fileType, + CannedACL = S3CannedACL.BucketOwnerFullControl + }; + + await _s3Client.PutObjectAsync(request); + } + catch + { + throw; + } + } + + public async Task UploadFileAsync(string fileName, string subFolder) + { + try + { + var fileContents = File.ReadAllBytes(fileName); + System.IO.MemoryStream filestream = new System.IO.MemoryStream(fileContents); + //var fileNameWithoutExt = Path.GetFileNameWithoutExtension(fileName); + var fileExt = Path.GetExtension(fileName); + var fileType = MimeTypeMap.GetMimeType(fileExt); + var file_name = Path.GetFileName(fileName); + + var request = new PutObjectRequest + { + //BucketName = $"{_bucketName}", + BucketName = $"{_bucketName}{subFolder}", + Key = file_name, + InputStream = filestream, + ContentType = fileType, + CannedACL = S3CannedACL.PublicRead + }; + + await _s3Client.PutObjectAsync(request); + } + catch + { + throw; + } + } + + public async Task GenerateJsonFile(string json, string path, string fileName) + { + var tmpDir = Path.Combine("tmp"); + if (!Directory.Exists(tmpDir)) + Directory.CreateDirectory(tmpDir); + + var tmpFile = Path.Combine(tmpDir, $"{fileName}.json"); + + try + { + SaveToJsonFile(tmpFile, json); + await UploadFileAsyncTemp(tmpFile, path); + } + catch + { + throw; + } + finally + { + if (tmpFile != "") + { + if (System.IO.File.Exists(tmpFile)) + System.IO.File.Delete(tmpFile); + } + + } + } + + private void SaveToJsonFile(string fileName, string data) + { + TextWriter writer = null; + try + { + writer = new StreamWriter(fileName); + writer.Write(data); + } + catch + { + throw; + } + finally + { + if (writer != null) + writer.Close(); + } + } + } +} diff --git a/BMA.EHR.Application/Repositories/MinIOService.cs b/BMA.EHR.Application/Repositories/MinIOService.cs index 58a5542a..fd07807b 100644 --- a/BMA.EHR.Application/Repositories/MinIOService.cs +++ b/BMA.EHR.Application/Repositories/MinIOService.cs @@ -1,19 +1,16 @@ using Amazon.S3; using Amazon.S3.Model; +using BMA.EHR.Application.Common.Interfaces; using BMA.EHR.Domain.Models.Documents; +using BMA.EHR.Domain.Models.Organizations; using BMA.EHR.Domain.Shared; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; -using System.Net.Http.Headers; -using BMA.EHR.Application.Common.Interfaces; -using Amazon; -using BMA.EHR.Domain.Models.Organizations; using MimeTypes; +using System.Net.Http.Headers; using Profile = BMA.EHR.Domain.Models.HR.Profile; -using System.IO; -using Amazon.S3.Transfer; namespace BMA.EHR.Application.Repositories { diff --git a/BMA.EHR.Leave.Service/Controllers/LeaveRequestController.cs b/BMA.EHR.Leave.Service/Controllers/LeaveRequestController.cs index 357d0a97..8faa1aae 100644 --- a/BMA.EHR.Leave.Service/Controllers/LeaveRequestController.cs +++ b/BMA.EHR.Leave.Service/Controllers/LeaveRequestController.cs @@ -33,7 +33,7 @@ namespace BMA.EHR.Leave.Service.Controllers private readonly UserProfileRepository _userProfileRepository; private readonly LeaveTypeRepository _leaveTypeRepository; private readonly LeaveRequestRepository _leaveRequestRepository; - private readonly MinIOService _minIOService; + private readonly MinIOLeaveService _minIOService; private readonly HolidayRepository _holidayRepository; #endregion @@ -47,7 +47,7 @@ namespace BMA.EHR.Leave.Service.Controllers UserProfileRepository userProfileRepository, LeaveTypeRepository leaveTypeRepository, LeaveRequestRepository leaveRequestRepository, - MinIOService minIOService, + MinIOLeaveService minIOService, HolidayRepository holidayRepository) { _context = context; @@ -362,8 +362,8 @@ namespace BMA.EHR.Leave.Service.Controllers [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task> GetLeaveRequestCalendarAsync([FromBody] GetLeaveRequestCalendarDto req) { - var thisYear = DateTime.Now.Year; - var data = await _leaveRequestRepository.GetLeaveRequestByYearAsync(thisYear); + //var thisYear = DateTime.Now.Year; + var data = await _leaveRequestRepository.GetLeaveRequestByYearAsync(req.Year); var result = new List(); @@ -627,6 +627,8 @@ namespace BMA.EHR.Leave.Service.Controllers // save to database await _leaveRequestRepository.UpdateAsync(data); + // await _leaveRequestRepository.AddAsync(data); + return Success(); } @@ -708,14 +710,14 @@ namespace BMA.EHR.Leave.Service.Controllers Id = rawData.Id, LeaveTypeName = rawData.Type.Name, FullName = $"{profile.Prefix.Name}{profile.FirstName} {profile.LastName}", - Status = rawData.LeaveCancelStatus, + Status = rawData.LeaveCancelStatus ?? "", LeaveStartDate = rawData.LeaveStartDate, LeaveEndDate = rawData.LeaveEndDate, - LeaveWrote = rawData.LeaveWrote, + LeaveWrote = rawData.CancelLeaveWrote ?? rawData.LeaveWrote, LeaveAddress = rawData.LeaveAddress, LeaveNumber = rawData.LeaveNumber, LeaveDetail = rawData.LeaveDetail, - LeaveDocDelete = await _minIOService.ImagesPath(rawData.LeaveCancelDocument.Id), + LeaveDocDelete = rawData.LeaveCancelDocument == null ? "" : await _minIOService.ImagesPath(rawData.LeaveCancelDocument.Id), LeaveReasonDelete = rawData.LeaveCancelComment ?? "", LeaveTotal = rawData.LeaveTotal, };