using BMA.EHR.Application.Common.Interfaces; using BMA.EHR.Application.Messaging; using BMA.EHR.Domain.Models.Leave.Commons; using BMA.EHR.Domain.Models.Leave.Requests; using BMA.EHR.Domain.Models.Notifications; using BMA.EHR.Domain.Shared; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests { public class LeaveRequestRepository : GenericLeaveRepository { #region " Fields " private readonly ILeaveDbContext _dbContext; private readonly IHttpContextAccessor _httpContextAccessor; private readonly OrganizationCommonRepository _organizationCommonRepository; private readonly UserProfileRepository _userProfileRepository; private readonly IConfiguration _configuration; private readonly EmailSenderService _emailSenderService; private readonly IApplicationDBContext _appDbContext; #endregion #region " Constructor and Destuctor " public LeaveRequestRepository(ILeaveDbContext dbContext, IHttpContextAccessor httpContextAccessor, OrganizationCommonRepository organizationCommonRepository, UserProfileRepository userProfileRepository, IConfiguration configuration, EmailSenderService emailSenderService, IApplicationDBContext appDbContext) : base(dbContext, httpContextAccessor) { _dbContext = dbContext; _httpContextAccessor = httpContextAccessor; _organizationCommonRepository = organizationCommonRepository; _userProfileRepository = userProfileRepository; _configuration = configuration; _emailSenderService = emailSenderService; _appDbContext = appDbContext; } #endregion #region " Properties " protected Guid UserOrganizationId { get { if (UserId != null || UserId != "") return _userProfileRepository.GetUserOCId(Guid.Parse(UserId!)); else return Guid.Empty; } } #endregion #region " Methods " #region " Overrides " public override async Task GetByIdAsync(Guid id) { 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 AddAsync(LeaveRequest entity) { if (entity.LeaveCancelDocument != null) _dbContext.Attatch(entity.LeaveCancelDocument); if (entity.LeaveDraftDocument != null) _dbContext.Attatch(entity.LeaveDraftDocument); if (entity.LeaveDocument != null) _dbContext.Attatch(entity.LeaveDocument); if (entity.Type != null) _dbContext.Attatch(entity.Type); return await base.AddAsync(entity); } public override async Task UpdateAsync(LeaveRequest entity) { if (entity.LeaveCancelDocument != null) _dbContext.Attatch(entity.LeaveCancelDocument); if (entity.LeaveDraftDocument != null) _dbContext.Attatch(entity.LeaveDraftDocument); if (entity.LeaveDocument != null) _dbContext.Attatch(entity.LeaveDocument); if (entity.Type != null) _dbContext.Attatch(entity.Type); return await base.UpdateAsync(entity); } #endregion public async Task> GetLeaveRequestByYearAsync(int year) { var data = await _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.LeaveStartDate.Year == year) .Where(x => x.LeaveStatus != "REJECT" || x.LeaveStatus != "DELETE") .ToListAsync(); return data; } public async Task> GetLeaveRequestByUserIdAsync(Guid keycloakUserId, int year, Guid type, string status) { var rawData = _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId); if (year != 0) rawData = rawData.Where(x => x.LeaveStartDate.Year == year); if (type != Guid.Empty) rawData = rawData.Where(x => x.Type.Id == type); if (status.Trim().ToUpper() != "ALL") rawData = rawData.Where(x => x.LeaveStatus == status); return await rawData.ToListAsync(); } public async Task> GetLeaveRequestForAdminAsync(int year, Guid type, string status) { var rawData = _dbContext.Set() .Include(x => x.Type) .AsQueryable(); if (year != 0) rawData = rawData.Where(x => x.LeaveStartDate.Year == year); if (type != Guid.Empty) rawData = rawData.Where(x => x.Type.Id == type); if (status.Trim().ToUpper() != "ALL") rawData = rawData.Where(x => x.LeaveStatus == status); return await rawData.ToListAsync(); } public async Task GetRestDayTotalByYearForUserAsync(Guid keycloakUserId, int year) { var leaveType = await _dbContext.Set().AsQueryable().FirstOrDefaultAsync(l => l.Code.Trim().ToUpper() == "LV-005"); if (leaveType == null) { throw new Exception("ไม่พบข้อมูลประเภทการลาพักผ่อน โปรดติดต่อผู้ดูและระบบ"); } var data = _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.Type.Id == leaveType.Id) .Where(x => x.LeaveStartDate.Year == year) .Sum(x => x.LeaveTotal); return data; } public async Task GetSumLeaveByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId, int year) { var data = await _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.Type.Id == leaveTypeId) .Where(x => x.LeaveStartDate.Year == year) .Where(x => x.LeaveStatus != "REJECT" || x.LeaveStatus != "DELETE") .ToListAsync(); return data.Sum(x => x.LeaveTotal); } public async Task GetLeaveLastByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId) { var data = await _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.Type.Id == leaveTypeId) .Where(x => x.LeaveStatus != "REJECT" || x.LeaveStatus != "DELETE") .OrderByDescending(x => x.LeaveStartDate.Date) .Select(x => x.LeaveStartDate.Date) .FirstOrDefaultAsync(); return data; } public async Task GetLastLeaveRequestByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId) { var data = await _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.Type.Id == leaveTypeId) .Where(x => x.LeaveStatus != "REJECT" || x.LeaveStatus != "DELETE") .OrderByDescending(x => x.LeaveStartDate.Date) .FirstOrDefaultAsync(); return data; } public async Task> GetCancelLeaveRequestForAdminAsync(int year, Guid type, string status) { var rawData = _dbContext.Set() .Include(x => x.Type) .Where(x => x.LeaveStatus == "DELETE") .AsQueryable(); if (year != 0) rawData = rawData.Where(x => x.LeaveStartDate.Year == year); if (type != Guid.Empty) rawData = rawData.Where(x => x.Type.Id == type); if (status.Trim().ToUpper() != "ALL") rawData = rawData.Where(x => x.LeaveCancelStatus == status); return await rawData.ToListAsync(); } public async Task ApproveCancelLeaveRequestAsync(Guid id, string Reason) { var rawData = await GetByIdAsync(id); if (rawData == null) { throw new Exception(GlobalMessages.DataNotFound); } var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId); if (profile == null) { throw new Exception(GlobalMessages.DataNotFound); } rawData.LeaveCancelStatus = "APPROVE"; rawData.LeaveCancelComment = Reason; await UpdateAsync(rawData); // TODO: remove วันลา // Send Noti var noti = new Notification { Body = $"การขอยกเลิกใบลาของคุณได้รับการอนุมัติ", ReceiverUserId = profile.Id, Type = "", Payload = "", }; _appDbContext.Set().Add(noti); await _appDbContext.SaveChangesAsync(); } public async Task RejectCancelLeaveRequestAsync(Guid id, string Reason) { var rawData = await GetByIdAsync(id); if (rawData == null) { throw new Exception(GlobalMessages.DataNotFound); } var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId); if (profile == null) { throw new Exception(GlobalMessages.DataNotFound); } rawData.LeaveCancelStatus = "REJECT"; rawData.LeaveCancelComment = Reason; await UpdateAsync(rawData); // TODO: remove วันลา // Send Noti var noti = new Notification { Body = $"การขอยกเลิกใบลาของคุณไม่ได้รับการอนุมัติ \r\nเนืองจาก {Reason}", ReceiverUserId = profile.Id, Type = "", Payload = "", }; _appDbContext.Set().Add(noti); await _appDbContext.SaveChangesAsync(); } public async Task OfficerApproveLeaveRequest(Guid id) { var rawData = await GetByIdAsync(id); if (rawData == null) { throw new Exception(GlobalMessages.DataNotFound); } rawData.LeaveStatus = "PENDING"; rawData.ApproveStep = "st2"; await UpdateAsync(rawData); } public async Task CommanderApproveLeaveRequest(Guid id, string reason) { var rawData = await GetByIdAsync(id); if (rawData == null) { throw new Exception(GlobalMessages.DataNotFound); } if (rawData.ApproveStep != "st2") { throw new Exception("คำขอนี้ยังไม่ได้รับการอนุมัติจากเจ้าหน้าที่ ไม่สามารถทำรายการได้"); } rawData.LeaveStatus = "PENDING"; rawData.LeaveComment = reason; rawData.ApproveStep = "st3"; await UpdateAsync(rawData); } public async Task ApproveLeaveRequest(Guid id, string reason) { var rawData = await GetByIdAsync(id); if (rawData == null) { throw new Exception(GlobalMessages.DataNotFound); } if (rawData.ApproveStep != "st3") { throw new Exception("คำขอนี้ยังไม่ได้รับการอนุมัติจากผู้บังคับบัญชา ไม่สามารถทำรายการได้"); } var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId); if (profile == null) { throw new Exception(GlobalMessages.DataNotFound); } rawData.LeaveStatus = "APPROVE"; rawData.LeaveDirectorComment = reason; rawData.ApproveStep = "st4"; await UpdateAsync(rawData); // Send Noti var noti = new Notification { Body = $"การขอลาของคุณได้รับการอนุมัติ", ReceiverUserId = profile.Id, Type = "", Payload = "", }; _appDbContext.Set().Add(noti); await _appDbContext.SaveChangesAsync(); } public async Task RejectLeaveRequest(Guid id, string reason) { var rawData = await GetByIdAsync(id); if (rawData == null) { throw new Exception(GlobalMessages.DataNotFound); } if (rawData.ApproveStep != "st3") { throw new Exception("คำขอนี้ยังไม่ได้รับการอนุมัติจากผู้บังคับบัญชา ไม่สามารถทำรายการได้"); } var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId); if (profile == null) { throw new Exception(GlobalMessages.DataNotFound); } rawData.LeaveStatus = "REJECT"; rawData.LeaveDirectorComment = reason; rawData.ApproveStep = "st5"; await UpdateAsync(rawData); // Send Noti var noti = new Notification { Body = $"การขอลาของคุณไม่ได้รับการอนุมัติ \r\nเนื่องจาก{reason}", ReceiverUserId = profile.Id, Type = "", Payload = "", }; _appDbContext.Set().Add(noti); await _appDbContext.SaveChangesAsync(); } public async Task GetSumSendLeaveByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId, int year) { var data = await _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.Type.Id == leaveTypeId) .Where(x => x.LeaveStartDate.Year == year) .ToListAsync(); return data.Sum(x => x.LeaveTotal); } public async Task GetSumApproveLeaveByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId, int year) { var data = await _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.Type.Id == leaveTypeId) .Where(x => x.LeaveStartDate.Year == year) .Where(x => x.LeaveStatus == "APPROVE") .ToListAsync(); if (data.Count > 0) return data.Sum(x => x.LeaveTotal); else return 0.0; } public async Task GetSumApproveLeaveByTypeAndRangeForUser(Guid keycloakUserId, Guid leaveTypeId, DateTime startDate, DateTime endDate) { var data = await _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.Type.Id == leaveTypeId) .Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date) .Where(x => x.LeaveStatus == "APPROVE") .ToListAsync(); if (data.Count > 0) return data.Sum(x => x.LeaveTotal); else return 0; } public async Task GetCountApproveLeaveByTypeAndRangeForUser(Guid keycloakUserId, Guid leaveTypeId, DateTime startDate, DateTime endDate) { var data = await _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.Type.Id == leaveTypeId) .Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date) .Where(x => x.LeaveStatus == "APPROVE") .ToListAsync(); return data.Count; } public async Task GetSumRejectLeaveByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId, int year) { var data = await _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.Type.Id == leaveTypeId) .Where(x => x.LeaveStartDate.Year == year) .Where(x => x.LeaveStatus == "REJECT") .ToListAsync(); if (data.Count > 0) return data.Sum(x => x.LeaveTotal); else return 0; } public async Task GetSumDeleteLeaveByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId, int year) { var data = await _dbContext.Set().AsQueryable() .Include(x => x.Type) .Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.Type.Id == leaveTypeId) .Where(x => x.LeaveStartDate.Year == year) .Where(x => x.LeaveStatus == "DELETE") .ToListAsync(); if (data.Count > 0) return data.Sum(x => x.LeaveTotal); else return 0; } #endregion } }