Compare commits

...

18 commits

Author SHA1 Message Date
Suphonchai Phoonsawat
c65a4a04ac Merge branch 'develop' into working
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 1m44s
2026-04-23 19:12:24 +07:00
Suphonchai Phoonsawat
d58c7dc07e Logic การคำนวนวันลา แบบร่าง และ นะหว่างพิจาณา #1567 2026-04-23 19:11:54 +07:00
Suphonchai Phoonsawat
bb329f86de เพิ่ม DateSendLeave และปรับ Logic การดึงค่าวันที่ยื่นลา #1567 2026-04-23 15:48:20 +07:00
harid
b3298e88c6 fix path separator
All checks were successful
Build & Deploy Retirement Service / build (push) Successful in 1m49s
2026-04-21 10:34:21 +07:00
harid
04d0067ee8 ถ้ามีรักษาการแก้สิทธิ์ BROTHER
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 1m58s
2026-04-20 16:38:58 +07:00
harid
c035c13405 check runtime
All checks were successful
Build & Deploy Retirement Service / build (push) Successful in 1m47s
2026-04-20 14:31:28 +07:00
harid
2e9db2d42c รายงานประกาศเกษียณ #2262, #2261
All checks were successful
Build & Deploy Retirement Service / build (push) Successful in 1m50s
2026-04-20 12:37:06 +07:00
Suphonchai Phoonsawat
1389df0225 แก้ไข
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 1m54s
ถ้าไม่ได้ Add สิทธิ์มา จะข้ามตำแหน่งนั้นไป
แก้บั้กการแสดงข้อมูล กรณี "ROOT"

#2431
2026-04-20 11:42:41 +07:00
Suphonchai Phoonsawat
058027ea29 เปลี่ยน DEFAULT สิทธิ์เป็น "CHILD" กรณีไม่ตั้งค่ามา #2431
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 1m53s
2026-04-17 20:11:18 +07:00
Suphonchai Phoonsawat
ee2d16925a แก้ไข รักษาการ ถ้าไม่ได้ใส่ privilage มาจะให้ default = "PARENT" #2431
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 2m7s
2026-04-17 19:21:30 +07:00
Suphonchai Phoonsawat
42f3813a7a Merge branch 'develop' into working
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 2m2s
2026-04-17 15:42:36 +07:00
Suphonchai Phoonsawat
7bafbf5001 เพิ่มรายการรักษาการ #2431 2026-04-17 15:35:29 +07:00
harid
db99630e0d fix #2430
All checks were successful
Build & Deploy Placement Service / build (push) Successful in 1m59s
2026-04-17 15:18:30 +07:00
Suphonchai Phoonsawat
34ec9bb77c Remove Check Pending Status For Cancel Leave #2432
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 1m54s
2026-04-17 10:31:09 +07:00
Suphonchai Phoonsawat
5606e8b50a Change GetProfileByKeycloakIdNewAsync To GetProfileByKeycloakIdNew2Async 2026-04-17 09:41:52 +07:00
Suphonchai Phoonsawat
ee4e9c3699 แก้ leave/detail เป็น leave-reject/detail สำหรับรายการยกเลิก #2432
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 1m51s
2026-04-16 21:30:17 +07:00
Suphonchai Phoonsawat
6efeec3f1f เพิ่ม List ของการเจ้หน้าที่ ส่ง noti ขอยกเลิกการลา #2432
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 1m52s
2026-04-16 19:05:26 +07:00
harid
c34fe35506 API ยกเลิกการส่งตัวบรรจุผู้สอบผ่าน
All checks were successful
Build & Deploy Placement Service / build (push) Successful in 1m57s
2026-04-16 11:57:47 +07:00
27 changed files with 3225 additions and 92 deletions

View file

@ -80,7 +80,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
public async Task UpdateLeaveUsageAsync(int year, Guid typeId, Guid userId, double day) public async Task UpdateLeaveUsageAsync(int year, Guid typeId, Guid userId, double day)
{ {
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); // var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (pf == null) if (pf == null)
{ {
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -102,7 +102,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
public async Task UpdateLeaveCountAsync(int year, Guid typeId, Guid userId, int count) public async Task UpdateLeaveCountAsync(int year, Guid typeId, Guid userId, int count)
{ {
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); // var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (pf == null) if (pf == null)
{ {
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -124,7 +124,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
public async Task<LeaveBeginning?> GetByYearAndTypeIdForUserAsync(int year, Guid typeId, Guid userId) public async Task<LeaveBeginning?> GetByYearAndTypeIdForUserAsync(int year, Guid typeId, Guid userId)
{ {
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); // var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (pf == null) if (pf == null)
{ {
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -263,7 +263,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
public async Task<LeaveBeginning?> GetByYearAndTypeIdForUser2Async(int year, Guid typeId, Guid userId) public async Task<LeaveBeginning?> GetByYearAndTypeIdForUser2Async(int year, Guid typeId, Guid userId)
{ {
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); // var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (pf == null) if (pf == null)
{ {
return null; return null;

View file

@ -254,7 +254,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
public async Task<List<LeaveRequest>> GetLeaveRequestByYearAsync(int year, Guid userId) public async Task<List<LeaveRequest>> GetLeaveRequestByYearAsync(int year, Guid userId)
{ {
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (profile == null) if (profile == null)
{ {
@ -354,7 +354,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
var rawData = _dbContext.Set<LeaveRequest>().AsNoTracking() var rawData = _dbContext.Set<LeaveRequest>().AsNoTracking()
.Include(x => x.Type) .Include(x => x.Type)
.Where(x => x.LeaveStatus != "DRAFT") .Where(x => x.LeaveStatus != "DRAFT")
.OrderByDescending(x => x.CreatedAt) .OrderByDescending(x => (x.DateSendLeave ?? x.CreatedAt))
.AsQueryable(); .AsQueryable();
if (year != 0) if (year != 0)
@ -380,7 +380,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
var rawData = _dbContext.Set<LeaveRequest>().AsNoTracking() var rawData = _dbContext.Set<LeaveRequest>().AsNoTracking()
.Include(x => x.Type) .Include(x => x.Type)
.Where(x => x.LeaveStatus != "DRAFT") .Where(x => x.LeaveStatus != "DRAFT")
.OrderByDescending(x => x.CreatedAt) .OrderByDescending(x => (x.DateSendLeave ?? x.CreatedAt))
.AsQueryable(); .AsQueryable();
// fix issue : 1830 // fix issue : 1830
if (year != 0) if (year != 0)
@ -447,7 +447,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
.Include(x => x.Type) .Include(x => x.Type)
.Where(x => keycloakIdList.Contains(x.KeycloakUserId)) .Where(x => keycloakIdList.Contains(x.KeycloakUserId))
.Where(x => x.LeaveStatus != "DRAFT") .Where(x => x.LeaveStatus != "DRAFT")
.OrderByDescending(x => x.CreatedAt) .OrderByDescending(x =>(x.DateSendLeave ?? x.CreatedAt))
.AsQueryable(); .AsQueryable();
if (year != 0) if (year != 0)
@ -497,7 +497,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
public async Task<double> GetSumLeaveByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId, int year) public async Task<double> GetSumLeaveByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId, int year)
{ {
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(keycloakUserId, AccessToken); // var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(keycloakUserId, AccessToken);
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(keycloakUserId, AccessToken); var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(keycloakUserId, AccessToken);
if (pf == null) if (pf == null)
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -574,12 +574,12 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking() var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking()
.Include(x => x.Type) .Include(x => x.Type)
//.Where(x => x.LeaveStartDate.Date < beforeDate.Date) //.Where(x => x.LeaveStartDate.Date < beforeDate.Date)
.Where(x => x.CreatedAt < beforeDate) .Where(x => (x.DateSendLeave ?? x.CreatedAt) < beforeDate)
.Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.KeycloakUserId == keycloakUserId)
.Where(x => x.Type.Id == leaveTypeId) .Where(x => x.Type.Id == leaveTypeId)
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING") .Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
//.Where(x => x.LeaveStatus != "REJECT" && x.LeaveStatus != "DELETE") //.Where(x => x.LeaveStatus != "REJECT" && x.LeaveStatus != "DELETE")
.OrderByDescending(x => x.CreatedAt) .OrderByDescending(x => (x.DateSendLeave ?? x.CreatedAt))
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
return data; return data;
@ -651,7 +651,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
try try
{ {
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(data.KeycloakUserId, AccessToken ?? ""); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(data.KeycloakUserId, AccessToken ?? "");
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(data.KeycloakUserId, AccessToken ?? ""); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(data.KeycloakUserId, AccessToken ?? "");
if (profile == null) if (profile == null)
{ {
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -728,7 +728,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
} }
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken ?? ""); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken ?? "");
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(rawData.KeycloakUserId, AccessToken ?? ""); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(rawData.KeycloakUserId, AccessToken ?? "");
if (profile == null) if (profile == null)
{ {
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -817,7 +817,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
} }
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken ?? ""); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken ?? "");
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(rawData.KeycloakUserId, AccessToken ?? ""); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(rawData.KeycloakUserId, AccessToken ?? "");
if (profile == null) if (profile == null)
{ {
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -904,6 +904,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
rawData.LeaveStatus = "NEW"; rawData.LeaveStatus = "NEW";
rawData.DateSendLeave = DateTime.Now; // Update วันที่ยื่นลาเป็นวันที่ปัจจุบัน
//rawData.ApproveStep = "st2"; //rawData.ApproveStep = "st2";
await UpdateAsync(rawData); await UpdateAsync(rawData);
@ -1242,7 +1243,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
else else
{ {
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(rawData.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(rawData.KeycloakUserId, AccessToken);
if (profile == null) if (profile == null)
{ {
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -1412,7 +1413,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
else else
{ {
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(rawData.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(rawData.KeycloakUserId, AccessToken);
if (profile == null) if (profile == null)
{ {
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -1876,7 +1877,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
.Include(x => x.Type) .Include(x => x.Type)
.Where(x => x.KeycloakUserId == keycloakUserId) .Where(x => x.KeycloakUserId == keycloakUserId)
.Where(x => x.Type.Id == leaveTypeId) .Where(x => x.Type.Id == leaveTypeId)
.Where(x => x.CreatedAt.Date >= startDate && x.CreatedAt < endDate) .Where(x => (x.DateSendLeave ?? x.CreatedAt).Date >= startDate && (x.DateSendLeave ??x.CreatedAt).Date < endDate)
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date) //.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING") .Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
.ToListAsync(); .ToListAsync();
@ -1887,6 +1888,57 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
return 0; return 0;
} }
/// <summary>
/// วันลาที่สร้างแบบร่างยังไม่ได้ยื่น
/// </summary>
/// <param name="keycloakUserId"></param>
/// <param name="leaveTypeId"></param>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <returns></returns>
public async Task<double> GetSumDraftLeaveTotalByTypeAndRangeForUser2(Guid keycloakUserId, Guid leaveTypeId, DateTime startDate, DateTime endDate)
{
var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking()
.Include(x => x.Type)
.Where(x => x.KeycloakUserId == keycloakUserId)
.Where(x => x.Type.Id == leaveTypeId)
.Where(x => (x.DateSendLeave ?? x.CreatedAt).Date >= startDate
&& (x.DateSendLeave ?? x.CreatedAt).Date < endDate)
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
.Where(x => x.LeaveStatus == "DRAFT")
.ToListAsync();
if (data.Count > 0)
return data.Sum(x => x.LeaveTotal);
else
return 0;
}
/// <summary>
/// วันลาที่ยื่นแล้วรอพิจารณา
/// </summary>
/// <param name="keycloakUserId"></param>
/// <param name="leaveTypeId"></param>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <returns></returns>
public async Task<double> GetSumNewLeaveTotalByTypeAndRangeForUser2(Guid keycloakUserId, Guid leaveTypeId, DateTime startDate, DateTime endDate)
{
var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking()
.Include(x => x.Type)
.Where(x => x.KeycloakUserId == keycloakUserId)
.Where(x => x.Type.Id == leaveTypeId)
.Where(x => (x.DateSendLeave ?? x.CreatedAt).Date >= startDate && (x.DateSendLeave ??x.CreatedAt).Date < endDate)
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
.Where(x => x.LeaveStatus == "NEW")
.ToListAsync();
if (data.Count > 0)
return data.Sum(x => x.LeaveTotal);
else
return 0;
}
public async Task<int> GetCountApproveLeaveByTypeAndRangeForUser(Guid keycloakUserId, Guid leaveTypeId, DateTime startDate, DateTime endDate) public async Task<int> GetCountApproveLeaveByTypeAndRangeForUser(Guid keycloakUserId, Guid leaveTypeId, DateTime startDate, DateTime endDate)
{ {
var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking() var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking()

View file

@ -10,6 +10,7 @@ using System.Net.Http.Headers;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System.Security.Claims; using System.Security.Claims;
using System.Net.Http.Json; using System.Net.Http.Json;
using BMA.EHR.Application.Responses.Leaves;
namespace BMA.EHR.Application.Repositories namespace BMA.EHR.Application.Repositories
{ {
@ -76,6 +77,39 @@ namespace BMA.EHR.Application.Repositories
} }
} }
public async Task<GetPermissionWithActingResultDto?> GetPermissionWithActingAPIAsync(string action, string system)
{
try
{
var apiPath = $"{_configuration["API"]}/org/permission/dotnet-acting/{action}/{system}";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", ""));
client.DefaultRequestHeaders.Add("api-key", _configuration["API_KEY"]);
var req = await client.GetAsync(apiPath);
if (!req.IsSuccessStatusCode)
{
throw new Exception("Error calling permission API");
}
var apiResult = await req.Content.ReadAsStringAsync();
//return res;
if (apiResult != null)
{
var raw = JsonConvert.DeserializeObject<GetPermissionWithActingResultDto>(apiResult);
return raw;
}
return null;
}
}
catch
{
throw;
}
}
public async Task<dynamic> GetPermissionOrgAPIAsync(string action, string system, string profileId) public async Task<dynamic> GetPermissionOrgAPIAsync(string action, string system, string profileId)
{ {
try try

View file

@ -192,7 +192,7 @@ namespace BMA.EHR.Application.Repositories.Reports
}).ToList(); }).ToList();
} }
string SignDate = retireHistorys.SignDate != null ? DateTime.Parse(retireHistorys.SignDate.ToString()).ToThaiFullDate().ToString().ToThaiNumber() : "-"; string SignDate = retireHistorys.SignDate != null ? DateTime.Parse(retireHistorys.SignDate.ToString()).ToThaiFullDate().ToString().ToThaiNumber() : "-";
return new { SignDate, retireHistorys.Detail, retireHistorys.Id, retireHistorys.CreatedAt, Year = retireHistorys.Year.ToThaiYear().ToString().ToThaiNumber(), retireHistorys.Round, retireHistorys.Type, retireHistorys.TypeReport, Total = retireHistorys.Total.ToString().ToThaiNumber(), profiles = mapProfiles }; return new { SignDate, Detail = retireHistorys.Detail.ToThaiNumber(), retireHistorys.Id, retireHistorys.CreatedAt, Year = retireHistorys.Year.ToThaiYear().ToString().ToThaiNumber(), retireHistorys.Round, retireHistorys.Type, retireHistorys.TypeReport, Total = retireHistorys.Total.ToString().ToThaiNumber(), profiles = mapProfiles };
} }
} }
else else
@ -312,7 +312,7 @@ namespace BMA.EHR.Application.Repositories.Reports
root = (isDuplicateRoot ? "" : profile.root + "\n") + root = (isDuplicateRoot ? "" : profile.root + "\n") +
(isDuplicateHospital || !hospital.ToObject<List<string>>().Contains(profile.child1) ? "" : profile.child1 + "\n") + (isDuplicateHospital || !hospital.ToObject<List<string>>().Contains(profile.child1) ? "" : profile.child1 + "\n") +
(isDuplicatePosType ? "" : $"ตำแหน่งประเภท{profile.posTypeName}" + "\n") + (isDuplicatePosType ? "" : $"ตำแหน่งประเภท{profile.posTypeName}" + "\n") +
(isDuplicatePosLevel ? "" : $"ระดับ{profile.posLevelName}"), (isDuplicatePosLevel ? "" : $"ระดับ{profile.posLevelName}").ToThaiNumber(),
child = (profile.posExecutiveName == null ? "" : profile.posExecutiveName + "\n") + child = (profile.posExecutiveName == null ? "" : profile.posExecutiveName + "\n") +
(profile.child4 == null ? "" : profile.child4 + "\n") + (profile.child4 == null ? "" : profile.child4 + "\n") +
(profile.child3 == null ? "" : profile.child3 + "\n") + (profile.child3 == null ? "" : profile.child3 + "\n") +
@ -326,7 +326,7 @@ namespace BMA.EHR.Application.Repositories.Reports
}).ToList(); }).ToList();
} }
string SignDate = retire.SignDate != null ? DateTime.Parse(retire.SignDate.ToString()).ToThaiFullDate().ToString().ToThaiNumber() : "-"; string SignDate = retire.SignDate != null ? DateTime.Parse(retire.SignDate.ToString()).ToThaiFullDate().ToString().ToThaiNumber() : "-";
return new { SignDate, retire.Detail, retire.Id, retire.CreatedAt, Year = retire.Year.ToThaiYear().ToString().ToThaiNumber(), retire.Round, retire.Type, retire.TypeReport, Total = profile_retire.Count.ToString().ToThaiNumber(), profiles = mapProfiles }; return new { SignDate, Detail = retire.Detail.ToThaiNumber(), retire.Id, retire.CreatedAt, Year = retire.Year.ToThaiYear().ToString().ToThaiNumber(), retire.Round, retire.Type, retire.TypeReport, Total = profile_retire.Count.ToString().ToThaiNumber(), profiles = mapProfiles };
} }
} }
#endregion #endregion

View file

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BMA.EHR.Domain.Shared;
using Newtonsoft.Json;
namespace BMA.EHR.Application.Responses.Leaves
{
public class GetPermissionWithActingDto
{
public string privilege {get; set;} = string.Empty;
public bool isAct {get; set;} = false;
public List<ActingPermission> posMasterActs {get; set;} = new();
}
public class ActingPermission
{
public string posNo {get; set;} = string.Empty;
//public string? privilege {get; set;} = "PARENT";
[JsonConverter(typeof(PrivilegeConverter))]
public string privilege {get; set;} = "CHILD";
public Guid? rootDnaId {get; set;}
public Guid? child1DnaId {get; set;}
public Guid? child2DnaId {get; set;}
public Guid? child3DnaId {get; set;}
public Guid? child4DnaId {get; set;}
}
public class GetPermissionWithActingResultDto
{
public int status {get; set;} = 0;
public string message {get; set;} = string.Empty;
public GetPermissionWithActingDto result {get; set;} = new();
}
}

View file

@ -210,5 +210,7 @@ namespace BMA.EHR.Domain.Models.Leave.Requests
public Guid? Child4DnaId { get; set; } = Guid.Empty; public Guid? Child4DnaId { get; set; } = Guid.Empty;
public DateTime? DateSendLeave { get; set; }
} }
} }

View file

@ -8,6 +8,8 @@
public static readonly string DataNotFound = "ไม่พบข้อมูลในระบบ"; public static readonly string DataNotFound = "ไม่พบข้อมูลในระบบ";
public static readonly string ProfileNotFound = "ไม่พบข้อมูลในระบบทะเบียนประวัติ";
public static readonly string NotAuthorized = "กรุณาเข้าสู่ระบบก่อนใช้งาน!"; public static readonly string NotAuthorized = "กรุณาเข้าสู่ระบบก่อนใช้งาน!";
public static readonly string ForbiddenAccess = "คุณไม่ได้รับอนุญาติให้เข้าใช้งาน!"; public static readonly string ForbiddenAccess = "คุณไม่ได้รับอนุญาติให้เข้าใช้งาน!";

View file

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace BMA.EHR.Domain.Shared
{
public class PrivilegeConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return "EMPTY";
}
return reader.Value;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
{
/// <inheritdoc />
public partial class AddDateSendLeave : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "DateSendLeave",
table: "LeaveRequests",
type: "datetime(6)",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DateSendLeave",
table: "LeaveRequests");
}
}
}

View file

@ -428,6 +428,9 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
b.Property<DateTime?>("DateAppoint") b.Property<DateTime?>("DateAppoint")
.HasColumnType("datetime(6)"); .HasColumnType("datetime(6)");
b.Property<DateTime?>("DateSendLeave")
.HasColumnType("datetime(6)");
b.Property<string>("Dear") b.Property<string>("Dear")
.HasColumnType("longtext") .HasColumnType("longtext")
.HasComment("เรียนใคร"); .HasComment("เรียนใคร");

View file

@ -3,8 +3,10 @@ using BMA.EHR.Application.Repositories.Commands;
using BMA.EHR.Application.Repositories.Leaves.LeaveRequests; using BMA.EHR.Application.Repositories.Leaves.LeaveRequests;
using BMA.EHR.Application.Repositories.Leaves.TimeAttendants; using BMA.EHR.Application.Repositories.Leaves.TimeAttendants;
using BMA.EHR.Application.Repositories.MessageQueue; using BMA.EHR.Application.Repositories.MessageQueue;
using BMA.EHR.Application.Responses.Leaves;
using BMA.EHR.Application.Responses.Profiles; using BMA.EHR.Application.Responses.Profiles;
using BMA.EHR.Domain.Common; using BMA.EHR.Domain.Common;
using BMA.EHR.Domain.Extensions;
using BMA.EHR.Domain.Models.Leave.TimeAttendants; using BMA.EHR.Domain.Models.Leave.TimeAttendants;
using BMA.EHR.Domain.Models.Notifications; using BMA.EHR.Domain.Models.Notifications;
using BMA.EHR.Domain.Shared; using BMA.EHR.Domain.Shared;
@ -447,7 +449,7 @@ namespace BMA.EHR.Leave.Service.Controllers
// Get user's last check-in record and profile in parallel // Get user's last check-in record and profile in parallel
var dataTask = _userTimeStampRepository.GetLastRecord(userId); var dataTask = _userTimeStampRepository.GetLastRecord(userId);
var profileTask = _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var profileTask = _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
var defaultRoundTask = _dutyTimeRepository.GetDefaultAsync(); var defaultRoundTask = _dutyTimeRepository.GetDefaultAsync();
await Task.WhenAll(dataTask, profileTask, defaultRoundTask); await Task.WhenAll(dataTask, profileTask, defaultRoundTask);
@ -936,7 +938,7 @@ namespace BMA.EHR.Leave.Service.Controllers
await _checkInJobStatusRepository.UpdateToProcessingAsync(taskId); await _checkInJobStatusRepository.UpdateToProcessingAsync(taskId);
} }
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, data.Token); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, data.Token);
if (profile == null) if (profile == null)
{ {
@ -1589,7 +1591,7 @@ namespace BMA.EHR.Leave.Service.Controllers
public async Task<ActionResult<ResponseObject>> CheckInOldAsync([FromForm] CheckTimeDto data) public async Task<ActionResult<ResponseObject>> CheckInOldAsync([FromForm] CheckTimeDto data)
{ {
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (profile == null) if (profile == null)
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
@ -1754,7 +1756,7 @@ namespace BMA.EHR.Leave.Service.Controllers
{ {
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (profile == null) if (profile == null)
{ {
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
@ -2043,7 +2045,7 @@ namespace BMA.EHR.Leave.Service.Controllers
} }
else else
{ {
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(d.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(d.KeycloakUserId, AccessToken);
if (profile == null) if (profile == null)
{ {
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
@ -2993,7 +2995,7 @@ namespace BMA.EHR.Leave.Service.Controllers
var time = DateTime.Now; var time = DateTime.Now;
var userId = UserId != null ? Guid.Parse(UserId) : Guid.Empty; var userId = UserId != null ? Guid.Parse(UserId) : Guid.Empty;
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (profile == null) if (profile == null)
{ {
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -3113,7 +3115,7 @@ namespace BMA.EHR.Leave.Service.Controllers
} }
var userId = UserId != null ? Guid.Parse(UserId) : Guid.Empty; var userId = UserId != null ? Guid.Parse(UserId) : Guid.Empty;
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (profile == null) if (profile == null)
{ {
throw new Exception(GlobalMessages.DataNotFound); throw new Exception(GlobalMessages.DataNotFound);
@ -3162,13 +3164,14 @@ namespace BMA.EHR.Leave.Service.Controllers
[ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ResponseObject>> GetAdditionalCheckRequestAsync([Required] int year, [Required] int month, [Required] int page = 1, [Required] int pageSize = 10, string keyword = "", string? sortBy = "", bool? descending = false) public async Task<ActionResult<ResponseObject>> GetAdditionalCheckRequestAsync([Required] int year, [Required] int month, [Required] int page = 1, [Required] int pageSize = 10, string keyword = "", string? sortBy = "", bool? descending = false)
{ {
var getPermission = await _permission.GetPermissionAPIAsync("LIST", "SYS_CHECKIN_SPECIAL"); var jsonData = await _permission.GetPermissionWithActingAPIAsync("LIST", "SYS_CHECKIN_SPECIAL");
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission); //var jsonData = JsonConvert.DeserializeObject<GetPermissionWithActingResultDto>(getPermission);
if (jsonData["status"]?.ToString() != "200") if (jsonData!.status != 200)
{ {
return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); return Error(jsonData.message, StatusCodes.Status403Forbidden);
} }
string role = jsonData["result"]?.ToString(); //string role = jsonData["result"]?.ToString();
string role = jsonData.result.privilege;
var nodeId = string.Empty; var nodeId = string.Empty;
var profileAdmin = new GetUserOCAllDto(); var profileAdmin = new GetUserOCAllDto();
profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken); profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken);
@ -3206,6 +3209,82 @@ namespace BMA.EHR.Leave.Service.Controllers
//var rawData = await _additionalCheckRequestRepository.GetAdditionalCheckRequests(year, month); //var rawData = await _additionalCheckRequestRepository.GetAdditionalCheckRequests(year, month);
var rawData = await _additionalCheckRequestRepository.GetAdditionalCheckRequestsByAdminRole(year, month, role, nodeId, profileAdmin?.Node, keyword); var rawData = await _additionalCheckRequestRepository.GetAdditionalCheckRequestsByAdminRole(year, month, role, nodeId, profileAdmin?.Node, keyword);
// ถ้ามีการรักษาการ
if (jsonData.result.isAct)
{
var posActs = jsonData.result.posMasterActs.Where(x => x.privilege != "EMPTY");
foreach(var act in posActs)
{
var actRole = act.privilege;
string actNodeId = string.Empty;
int? actNode;
if (actRole == "NORMAL" || actRole == "CHILD")
{
actNodeId = act.child4DnaId != null ?
act.child4DnaId.Value.ToString("D") :
act.child3DnaId != null ?
act.child3DnaId.Value.ToString("D") :
act.child2DnaId != null ?
act.child2DnaId.Value.ToString("D") :
act.child1DnaId != null ?
act.child1DnaId.Value.ToString("D") :
act.rootDnaId != null ?
act.rootDnaId.Value.ToString("D") :
"";
actNode = act.child4DnaId != null ?
4 :
act.child3DnaId != null ?
3 :
act.child2DnaId != null ?
2 :
act.child1DnaId != null ?
1 :
act.rootDnaId != null ?
0 :
null;
}
else if (actRole == "BROTHER")
{
actNodeId = act.child4DnaId != null ?
act.child3DnaId.Value.ToString("D") :
act.child3DnaId != null ?
act.child2DnaId.Value.ToString("D") :
act.child2DnaId != null ?
act.child1DnaId!.Value.ToString("D") :
act.child1DnaId != null ?
act.rootDnaId.Value.ToString("D") :
act.rootDnaId != null ?
act.rootDnaId.Value.ToString("D") :
"";
actNode = act.child4DnaId != null ?
4 :
act.child3DnaId != null ?
3 :
act.child2DnaId != null ?
2 :
act.child1DnaId != null ?
1 :
act.rootDnaId != null ?
0 :
null;
}
else if (actRole == "ROOT" /*|| role == "PARENT"*/)
{
actNodeId = act.rootDnaId!.Value.ToString("D");
actNode = 0;
}
var rawDataAct = await _additionalCheckRequestRepository.GetAdditionalCheckRequestsByAdminRole(year, month, actRole, actNodeId, profileAdmin?.Node, keyword);
if (rawDataAct != null)
{
if (rawData != null)
rawData = rawData.Union(rawDataAct).DistinctBy(x => x.Id).ToList();
else
rawData = rawDataAct;
}
}
}
var total = rawData.Count; var total = rawData.Count;
var getDefaultRound = await _dutyTimeRepository.GetDefaultAsync(); var getDefaultRound = await _dutyTimeRepository.GetDefaultAsync();
@ -3276,7 +3355,7 @@ namespace BMA.EHR.Leave.Service.Controllers
foreach (var data in rawDataPaged) foreach (var data in rawDataPaged)
{ {
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(data.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(data.KeycloakUserId, AccessToken);
UserDutyTime? effectiveDate = null; UserDutyTime? effectiveDate = null;
if (profile != null) if (profile != null)
{ {
@ -3455,7 +3534,7 @@ namespace BMA.EHR.Leave.Service.Controllers
// change user timestamp // change user timestamp
var processTimeStamp = await _processUserTimeStampRepository.GetTimestampByDateAsync(requestData.KeycloakUserId, requestData.CheckDate.Date); var processTimeStamp = await _processUserTimeStampRepository.GetTimestampByDateAsync(requestData.KeycloakUserId, requestData.CheckDate.Date);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(requestData.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(requestData.KeycloakUserId, AccessToken);
if (processTimeStamp == null) if (processTimeStamp == null)
{ {
@ -3609,7 +3688,7 @@ namespace BMA.EHR.Leave.Service.Controllers
requestData.Comment = req.Reason; requestData.Comment = req.Reason;
await _additionalCheckRequestRepository.UpdateAsync(requestData); await _additionalCheckRequestRepository.UpdateAsync(requestData);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(requestData.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(requestData.KeycloakUserId, AccessToken);
var recvId = new List<Guid> { profile.Id }; var recvId = new List<Guid> { profile.Id };
await _notificationRepository.PushNotificationsAsync(recvId.ToArray(), "ลงเวลากรณีพิเศษ", "การขอลงเวลากรณีพิเศษของคุณไม่ได้รับการอนุมัติ", "", "", true, false); await _notificationRepository.PushNotificationsAsync(recvId.ToArray(), "ลงเวลากรณีพิเศษ", "การขอลงเวลากรณีพิเศษของคุณไม่ได้รับการอนุมัติ", "", "", true, false);
@ -3653,7 +3732,7 @@ namespace BMA.EHR.Leave.Service.Controllers
} }
else else
{ {
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(d.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(d.KeycloakUserId, AccessToken);
if (profile == null) if (profile == null)
{ {
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
@ -3747,7 +3826,7 @@ namespace BMA.EHR.Leave.Service.Controllers
foreach (var data in rawData) foreach (var data in rawData)
{ {
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(data.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(data.KeycloakUserId, AccessToken);
if (profile == null) if (profile == null)
{ {
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
@ -4037,7 +4116,7 @@ namespace BMA.EHR.Leave.Service.Controllers
//var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); //var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
// แก้เป็นมาใช้งาน KeycloakUserId แทน // แก้เป็นมาใช้งาน KeycloakUserId แทน
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(data.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(data.KeycloakUserId, AccessToken);
var defaultRound = await _dutyTimeRepository.GetDefaultAsync(); var defaultRound = await _dutyTimeRepository.GetDefaultAsync();
if (defaultRound == null) if (defaultRound == null)
{ {
@ -4107,7 +4186,7 @@ namespace BMA.EHR.Leave.Service.Controllers
[ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ResponseObject>> GetLeaveSummaryByProfileAsync(Guid id, [FromBody] GetLeaveSummaryDto req) public async Task<ActionResult<ResponseObject>> GetLeaveSummaryByProfileAsync(Guid id, [FromBody] GetLeaveSummaryDto req)
{ {
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(id, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(id, AccessToken);
var thisYear = DateTime.Now.Year; var thisYear = DateTime.Now.Year;
var startDate = req.StartDate; var startDate = req.StartDate;
@ -4177,7 +4256,7 @@ namespace BMA.EHR.Leave.Service.Controllers
{ {
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (profile == null) if (profile == null)
{ {
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);

View file

@ -182,7 +182,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "", leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "", leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(), dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
@ -272,7 +272,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "", leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "", leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(), dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
@ -366,7 +366,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "", leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "", leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(), dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
@ -461,7 +461,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "", leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "", leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(), dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
@ -515,7 +515,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "", leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "", leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(), dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
@ -602,7 +602,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "", leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "", leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(), dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
@ -683,7 +683,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "", leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "", leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(), dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
@ -786,7 +786,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "", leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "", leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(), dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
@ -905,7 +905,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "", leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "", leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(), dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
@ -1001,7 +1001,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "", leaveWrote = data.LeaveWrote.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "", leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(), dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
@ -1227,7 +1227,7 @@ namespace BMA.EHR.Leave.Service.Controllers
data = new data = new
{ {
leaveWrote = data.CancelLeaveWrote!.ToThaiNumber() ?? "", leaveWrote = data.CancelLeaveWrote!.ToThaiNumber() ?? "",
dateSendLeave = data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(), dateSendLeave = data.DateSendLeave != null ? data.DateSendLeave.Value.Date.ToThaiShortDate().ToThaiNumber() : data.CreatedAt.Date.ToThaiShortDate().ToThaiNumber(),
leaveTypeName = data.Type.Name, leaveTypeName = data.Type.Name,
fullname = fullName, fullname = fullName,
position = string.IsNullOrEmpty(profile.Position) ? "-" : profile.Position, position = string.IsNullOrEmpty(profile.Position) ? "-" : profile.Position,

View file

@ -214,7 +214,7 @@ namespace BMA.EHR.Leave.Service.Controllers
var thisYear = DateTime.Now.Year; var thisYear = DateTime.Now.Year;
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (profile == null) if (profile == null)
{ {
@ -502,7 +502,7 @@ namespace BMA.EHR.Leave.Service.Controllers
foreach (var leave in leaves) foreach (var leave in leaves)
{ {
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(leave.KeycloakUserId, AccessToken); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(leave.KeycloakUserId, AccessToken);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(leave.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(leave.KeycloakUserId, AccessToken);
if (profile != null) if (profile != null)
{ {
leave.Prefix = profile.Prefix; leave.Prefix = profile.Prefix;
@ -563,7 +563,7 @@ namespace BMA.EHR.Leave.Service.Controllers
// } // }
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (profile == null) if (profile == null)
{ {
@ -855,10 +855,10 @@ namespace BMA.EHR.Leave.Service.Controllers
{ {
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
var thisYear = DateTime.Now.Year; var thisYear = DateTime.Now.Year - 1;
var toDay = DateTime.Now.Date; var toDay = DateTime.Now.Date;
var startFiscalDate = new DateTime(DateTime.Now.Year, 10, 1); var startFiscalDate = new DateTime(DateTime.Now.Year - 1, 10, 1);
var endFiscalDate = new DateTime(DateTime.Now.Year + 1, 9, 30); var endFiscalDate = new DateTime(DateTime.Now.Year, 9, 30);
if (toDay >= startFiscalDate && toDay <= endFiscalDate) if (toDay >= startFiscalDate && toDay <= endFiscalDate)
thisYear = thisYear + 1; thisYear = thisYear + 1;
@ -925,6 +925,9 @@ namespace BMA.EHR.Leave.Service.Controllers
var leaveLast = await _leaveRequestRepository.GetLeaveLastByTypeForUserAsync(userId, req.Type); var leaveLast = await _leaveRequestRepository.GetLeaveLastByTypeForUserAsync(userId, req.Type);
var leaveDraftSummary = await _leaveRequestRepository.GetSumDraftLeaveTotalByTypeAndRangeForUser2(userId, req.Type, startFiscalDate, endFiscalDate);
var leaveWaitingSummary = await _leaveRequestRepository.GetSumNewLeaveTotalByTypeAndRangeForUser2(userId, req.Type, startFiscalDate, endFiscalDate);
var result = new GetUserLeaveProfileResultDto var result = new GetUserLeaveProfileResultDto
{ {
DateSendLeave = DateTime.Now.Date, DateSendLeave = DateTime.Now.Date,
@ -960,7 +963,10 @@ namespace BMA.EHR.Leave.Service.Controllers
CurrentDistrict = profile.CurrentDistrict ?? "", CurrentDistrict = profile.CurrentDistrict ?? "",
CurrentProvince = profile.CurrentProvince ?? "", CurrentProvince = profile.CurrentProvince ?? "",
CurrentZipCode = profile.CurrentZipCode ?? "", CurrentZipCode = profile.CurrentZipCode ?? "",
GovAge = govAge GovAge = govAge,
LeaveDraftSummary = leaveDraftSummary,
LeaveWaitingSummary = leaveWaitingSummary
}; };
return Success(result); return Success(result);
@ -1026,7 +1032,7 @@ namespace BMA.EHR.Leave.Service.Controllers
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
var govAge = (profile?.DateStart?.Date ?? DateTime.Now.Date).DiffDay(DateTime.Now.Date); var govAge = (profile?.DateStart?.Date ?? DateTime.Now.Date).DiffDay(DateTime.Now.Date);
var startDate = profile?.DateStart?.Date ?? DateTime.Now.Date; var startDate = profile?.DateStart?.Date ?? DateTime.Now.Date;
// var date1Raw = profile?.DateStart?.Date ?? DateTime.Now.Date; // var date1Raw = profile?.DateStart?.Date ?? DateTime.Now.Date;
@ -1324,7 +1330,7 @@ namespace BMA.EHR.Leave.Service.Controllers
Id = d.Id, Id = d.Id,
LeaveTypeId = d.Type.Id, LeaveTypeId = d.Type.Id,
LeaveTypeName = d.Type.Name, LeaveTypeName = d.Type.Name,
DateSendLeave = d.CreatedAt.Date, DateSendLeave = d.DateSendLeave != null ? d.DateSendLeave.Value.Date : d.CreatedAt.Date,
Status = d.LeaveStatus, Status = d.LeaveStatus,
FullName = $"{d.Prefix}{d.FirstName} {d.LastName}", FullName = $"{d.Prefix}{d.FirstName} {d.LastName}",
LeaveEndDate = d.LeaveEndDate, LeaveEndDate = d.LeaveEndDate,
@ -1352,14 +1358,14 @@ namespace BMA.EHR.Leave.Service.Controllers
public async Task<ActionResult<ResponseObject>> GetLeaveRequestCalendarAdminAsync( public async Task<ActionResult<ResponseObject>> GetLeaveRequestCalendarAdminAsync(
[FromBody] GetLeaveRequestCalendarDto req) [FromBody] GetLeaveRequestCalendarDto req)
{ {
var getPermission = await _permission.GetPermissionAPIAsync("LIST", "SYS_LEAVE_LIST"); var jsonData = await _permission.GetPermissionWithActingAPIAsync("LIST", "SYS_LEAVE_LIST");
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission); //var jsonData = JsonConvert.DeserializeObject<GetPermissionWithActingResultDto>(getPermission);
if (jsonData["status"]?.ToString() != "200") if (jsonData!.status != 200)
{ {
return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); return Error(jsonData.message, StatusCodes.Status403Forbidden);
} }
//string role = jsonData["result"]?.ToString();
string role = jsonData["result"]?.ToString(); string role = jsonData.result.privilege;
var nodeId = string.Empty; var nodeId = string.Empty;
var profileAdmin = new GetUserOCAllDto(); var profileAdmin = new GetUserOCAllDto();
profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken); profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken);
@ -1395,6 +1401,87 @@ namespace BMA.EHR.Leave.Service.Controllers
} }
var data = await _leaveRequestRepository.GetLeaveRequestByYearForAdminAsync(req.Year, role, nodeId, profileAdmin.Node); var data = await _leaveRequestRepository.GetLeaveRequestByYearForAdminAsync(req.Year, role, nodeId, profileAdmin.Node);
// ถ้ามีการรักษาการ
if (jsonData.result.isAct)
{
var posActs = jsonData.result.posMasterActs.Where(x => x.privilege != "EMPTY");
foreach(var act in posActs)
{
var actRole = act.privilege;
string actNodeId = string.Empty;
int? actNode = null;
if (actRole == "NORMAL" || actRole == "CHILD")
{
actNodeId = act.child4DnaId != null ?
act.child4DnaId.Value.ToString("D") :
act.child3DnaId != null ?
act.child3DnaId.Value.ToString("D") :
act.child2DnaId != null ?
act.child2DnaId.Value.ToString("D") :
act.child1DnaId != null ?
act.child1DnaId.Value.ToString("D") :
act.rootDnaId != null ?
act.rootDnaId.Value.ToString("D") :
"";
actNode = act.child4DnaId != null ?
4 :
act.child3DnaId != null ?
3 :
act.child2DnaId != null ?
2 :
act.child1DnaId != null ?
1 :
act.rootDnaId != null ?
0 :
null;
}
else if (actRole == "BROTHER")
{
actNodeId = act.child4DnaId != null ?
act.child3DnaId.Value.ToString("D") :
act.child3DnaId != null ?
act.child2DnaId.Value.ToString("D") :
act.child2DnaId != null ?
act.child1DnaId!.Value.ToString("D") :
act.child1DnaId != null ?
act.rootDnaId.Value.ToString("D") :
act.rootDnaId != null ?
act.rootDnaId.Value.ToString("D") :
"";
actNode = act.child4DnaId != null ?
4 :
act.child3DnaId != null ?
3 :
act.child2DnaId != null ?
2 :
act.child1DnaId != null ?
1 :
act.rootDnaId != null ?
0 :
null;
}
else if (actRole == "ROOT" /*|| role == "PARENT"*/)
{
actNodeId = act.rootDnaId!.Value.ToString("D");
actNode = 0;
}
var rawDataAct = await _leaveRequestRepository.GetLeaveRequestByYearForAdminAsync(req.Year, actRole, actNodeId, actNode);
if (rawDataAct != null)
{
if (data != null)
data = data.Union(rawDataAct).DistinctBy(x => x.Id).ToList();
else
data = rawDataAct;
}
}
}
var resultData = (from d in data var resultData = (from d in data
//join p in profileList on d.KeycloakUserId equals p.Keycloak //join p in profileList on d.KeycloakUserId equals p.Keycloak
select new GetLeaveRequestCalendarResultDto select new GetLeaveRequestCalendarResultDto
@ -1402,7 +1489,7 @@ namespace BMA.EHR.Leave.Service.Controllers
Id = d.Id, Id = d.Id,
LeaveTypeId = d.Type.Id, LeaveTypeId = d.Type.Id,
LeaveTypeName = d.Type.Name, LeaveTypeName = d.Type.Name,
DateSendLeave = d.CreatedAt.Date, DateSendLeave = d.DateSendLeave != null ? d.DateSendLeave.Value.Date : d.CreatedAt.Date,
Status = d.LeaveStatus, Status = d.LeaveStatus,
FullName = $"{d.Prefix}{d.FirstName} {d.LastName}", FullName = $"{d.Prefix}{d.FirstName} {d.LastName}",
LeaveEndDate = d.LeaveEndDate, LeaveEndDate = d.LeaveEndDate,
@ -1455,7 +1542,7 @@ namespace BMA.EHR.Leave.Service.Controllers
LeaveTypeName = item.Type.Name, LeaveTypeName = item.Type.Name,
LeaveSubTypeName = item.LeaveSubTypeName ?? "", LeaveSubTypeName = item.LeaveSubTypeName ?? "",
FullName = $"{item.Prefix}{item.FirstName} {item.LastName}", FullName = $"{item.Prefix}{item.FirstName} {item.LastName}",
DateSendLeave = item.CreatedAt, DateSendLeave = item.DateSendLeave ?? item.CreatedAt,
IsDelete = item.LeaveStatus == "DELETE", IsDelete = item.LeaveStatus == "DELETE",
Status = item.LeaveStatus, Status = item.LeaveStatus,
LeaveStartDate = item.LeaveStartDate, LeaveStartDate = item.LeaveStartDate,
@ -1577,7 +1664,7 @@ namespace BMA.EHR.Leave.Service.Controllers
} }
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(rawData.KeycloakUserId, AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(rawData.KeycloakUserId, AccessToken);
if (profile == null) if (profile == null)
{ {
@ -1630,7 +1717,7 @@ namespace BMA.EHR.Leave.Service.Controllers
LeaveSubTypeName = rawData.LeaveSubTypeName, LeaveSubTypeName = rawData.LeaveSubTypeName,
LeaveTypeId = rawData.Type.Id, LeaveTypeId = rawData.Type.Id,
FullName = $"{rawData.Prefix}{rawData.FirstName} {rawData.LastName}", FullName = $"{rawData.Prefix}{rawData.FirstName} {rawData.LastName}",
DateSendLeave = rawData.CreatedAt, DateSendLeave = rawData.DateSendLeave ?? rawData.CreatedAt,
Status = rawData.LeaveStatus, Status = rawData.LeaveStatus,
LeaveStartDate = rawData.LeaveStartDate, LeaveStartDate = rawData.LeaveStartDate,
LeaveEndDate = rawData.LeaveEndDate, LeaveEndDate = rawData.LeaveEndDate,
@ -1750,14 +1837,14 @@ namespace BMA.EHR.Leave.Service.Controllers
public async Task<ActionResult<ResponseObject>> GetLeaveRequestForAdminAsync( public async Task<ActionResult<ResponseObject>> GetLeaveRequestForAdminAsync(
[FromBody] GetLeaveRequestForAdminDto req) [FromBody] GetLeaveRequestForAdminDto req)
{ {
var getPermission = await _permission.GetPermissionAPIAsync("LIST", "SYS_LEAVE_LIST"); var jsonData = await _permission.GetPermissionWithActingAPIAsync("LIST", "SYS_LEAVE_LIST");
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission); //var jsonData = JsonConvert.DeserializeObject<GetPermissionWithActingResultDto>(getPermission);
if (jsonData["status"]?.ToString() != "200") if (jsonData!.status != 200)
{ {
return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); return Error(jsonData.message, StatusCodes.Status403Forbidden);
} }
//string role = jsonData["result"]?.ToString();
string role = jsonData["result"]?.ToString(); string role = jsonData.result.privilege;
var nodeId = string.Empty; var nodeId = string.Empty;
var profileAdmin = new GetUserOCAllDto(); var profileAdmin = new GetUserOCAllDto();
profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken); profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken);
@ -1794,6 +1881,85 @@ namespace BMA.EHR.Leave.Service.Controllers
var rawData = await _leaveRequestRepository.GetListLeaveRequestForAdminAsync(req.Year, req.Type, req.Status, req.StartDate, req.EndDate, role, nodeId, profileAdmin?.Node); var rawData = await _leaveRequestRepository.GetListLeaveRequestForAdminAsync(req.Year, req.Type, req.Status, req.StartDate, req.EndDate, role, nodeId, profileAdmin?.Node);
// ถ้ามีการรักษาการ
if (jsonData.result.isAct)
{
var posActs = jsonData.result.posMasterActs.Where(x => x.privilege != "EMPTY");
foreach(var act in posActs)
{
var actRole = act.privilege;
string actNodeId = string.Empty;
int? actNode = null;
if (actRole == "NORMAL" || actRole == "CHILD")
{
actNodeId = act.child4DnaId != null ?
act.child4DnaId.Value.ToString("D") :
act.child3DnaId != null ?
act.child3DnaId.Value.ToString("D") :
act.child2DnaId != null ?
act.child2DnaId.Value.ToString("D") :
act.child1DnaId != null ?
act.child1DnaId.Value.ToString("D") :
act.rootDnaId != null ?
act.rootDnaId.Value.ToString("D") :
"";
actNode = act.child4DnaId != null ?
4 :
act.child3DnaId != null ?
3 :
act.child2DnaId != null ?
2 :
act.child1DnaId != null ?
1 :
act.rootDnaId != null ?
0 :
null;
}
else if (actRole == "BROTHER")
{
actNodeId = act.child4DnaId != null ?
act.child3DnaId.Value.ToString("D") :
act.child3DnaId != null ?
act.child2DnaId.Value.ToString("D") :
act.child2DnaId != null ?
act.child1DnaId!.Value.ToString("D") :
act.child1DnaId != null ?
act.rootDnaId.Value.ToString("D") :
act.rootDnaId != null ?
act.rootDnaId.Value.ToString("D") :
"";
actNode = act.child4DnaId != null ?
4 :
act.child3DnaId != null ?
3 :
act.child2DnaId != null ?
2 :
act.child1DnaId != null ?
1 :
act.rootDnaId != null ?
0 :
null;
}
else if (actRole == "ROOT" /*|| role == "PARENT"*/)
{
actNodeId = act.rootDnaId!.Value.ToString("D");
actNode = 0;
}
var rawDataAct = await _leaveRequestRepository.GetListLeaveRequestForAdminAsync(req.Year, req.Type, req.Status, req.StartDate, req.EndDate, actRole, actNodeId, actNode);
if (rawDataAct != null)
{
if (rawData != null)
rawData = rawData.Union(rawDataAct).DistinctBy(x => x.Id).ToList();
else
rawData = rawDataAct;
}
}
}
var result = new List<GetLeaveRequestForAdminResultDto>(); var result = new List<GetLeaveRequestForAdminResultDto>();
foreach (var item in rawData) foreach (var item in rawData)
@ -1826,7 +1992,7 @@ namespace BMA.EHR.Leave.Service.Controllers
LeaveSubTypeName = item.LeaveSubTypeName, LeaveSubTypeName = item.LeaveSubTypeName,
FullName = $"{item.Prefix}{item.FirstName} {item.LastName}", FullName = $"{item.Prefix}{item.FirstName} {item.LastName}",
ProfileType = item.ProfileType ?? "-", ProfileType = item.ProfileType ?? "-",
DateSendLeave = item.CreatedAt, DateSendLeave = item.DateSendLeave ?? item.CreatedAt,
Status = item.LeaveStatus, Status = item.LeaveStatus,
CitizenId = item.CitizenId ?? "", CitizenId = item.CitizenId ?? "",
LeaveStartDate = item.LeaveStartDate, LeaveStartDate = item.LeaveStartDate,
@ -1876,6 +2042,12 @@ namespace BMA.EHR.Leave.Service.Controllers
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
} }
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(data.KeycloakUserId, AccessToken);
if (profile == null)
{
return Error(GlobalMessages.ProfileNotFound, StatusCodes.Status404NotFound);
}
// change status to delete // change status to delete
// แก้จาก DELETE เป็น DELETING ไว้ก่อน รอ approve ค่อยเปลี่ยนเป็น DELETE // แก้จาก DELETE เป็น DELETING ไว้ก่อน รอ approve ค่อยเปลี่ยนเป็น DELETE
// data.LeaveStatus = "DELETE"; // data.LeaveStatus = "DELETE";
@ -1912,7 +2084,7 @@ namespace BMA.EHR.Leave.Service.Controllers
// TODO: Send notification to all users who need to approve the cancel leave request // TODO: Send notification to all users who need to approve the cancel leave request
var approvers = data.Approvers var approvers = data.Approvers
.Where(x => x.ApproveStatus!.ToUpper() == "PENDING") //.Where(x => x.ApproveStatus!.ToUpper() == "PENDING")
.OrderBy(x => x.Seq) .OrderBy(x => x.Seq)
.ToList(); .ToList();
@ -1924,11 +2096,33 @@ namespace BMA.EHR.Leave.Service.Controllers
Body = $"คำร้องขอยกเลิกการลาของคุณ {data.FirstName} {data.LastName} รอรับการอนุมัติจากคุณ", Body = $"คำร้องขอยกเลิกการลาของคุณ {data.FirstName} {data.LastName} รอรับการอนุมัติจากคุณ",
ReceiverUserId = approver!.ProfileId, ReceiverUserId = approver!.ProfileId,
Type = "", Type = "",
Payload = $"{URL}/leave/detail/{id}", Payload = $"{URL}/leave-reject/detail/{id}",
}; };
_appDbContext.Set<Notification>().Add(noti1); _appDbContext.Set<Notification>().Add(noti1);
} }
// Get Officer List
var officers = await _userProfileRepository.GetOCStaffAsync(profile.Id, AccessToken);
var approverProfileIdList = approvers.Select(x => x.ProfileId).ToList();
if(officers != null && officers.Count > 0)
{
officers = officers.Where(x => !approverProfileIdList.Contains(x.ProfileId)).ToList();
foreach (var officer in officers)
{
// Send Notification
var noti = new Notification
{
Body = $"คำร้องขอยกเลิกการลาของคุณ {data.FirstName} {data.LastName} รอรับการอนุมัติจากคุณ",
ReceiverUserId = officer.ProfileId,
Type = "",
Payload = $"{URL}/leave-reject/detail/{id}",
};
_appDbContext.Set<Notification>().Add(noti);
}
await _appDbContext.SaveChangesAsync();
}
return Success(); return Success();
} }
@ -1948,14 +2142,14 @@ namespace BMA.EHR.Leave.Service.Controllers
public async Task<ActionResult<ResponseObject>> GetCancelLeaveRequestForAdminAsync( public async Task<ActionResult<ResponseObject>> GetCancelLeaveRequestForAdminAsync(
[FromBody] GetLeaveRequestForAdminDto req) [FromBody] GetLeaveRequestForAdminDto req)
{ {
var getPermission = await _permission.GetPermissionAPIAsync("LIST", "SYS_LEAVE_LIST"); var jsonData = await _permission.GetPermissionWithActingAPIAsync("LIST", "SYS_LEAVE_LIST");
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission); //var jsonData = JsonConvert.DeserializeObject<GetPermissionWithActingResultDto>(getPermission);
if (jsonData["status"]?.ToString() != "200") if (jsonData!.status != 200)
{ {
return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); return Error(jsonData.message, StatusCodes.Status403Forbidden);
} }
//string role = jsonData["result"]?.ToString();
string role = jsonData["result"]?.ToString(); string role = jsonData.result.privilege;
var nodeId = string.Empty; var nodeId = string.Empty;
var profileAdmin = new GetUserOCAllDto(); var profileAdmin = new GetUserOCAllDto();
profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken); profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken);
@ -1993,6 +2187,84 @@ namespace BMA.EHR.Leave.Service.Controllers
var rawData = var rawData =
await _leaveRequestRepository.GetCancelLeaveRequestForAdminAsync(req.Year, req.Type, req.Status, role, nodeId, profileAdmin?.Node); await _leaveRequestRepository.GetCancelLeaveRequestForAdminAsync(req.Year, req.Type, req.Status, role, nodeId, profileAdmin?.Node);
// ถ้ามีการรักษาการ
if (jsonData.result.isAct)
{
var posActs = jsonData.result.posMasterActs.Where(x => x.privilege != "EMPTY");
foreach(var act in posActs)
{
var actRole = act.privilege;
string actNodeId = string.Empty;
int? actNode = null;
if (actRole == "NORMAL" || actRole == "CHILD")
{
actNodeId = act.child4DnaId != null ?
act.child4DnaId.Value.ToString("D") :
act.child3DnaId != null ?
act.child3DnaId.Value.ToString("D") :
act.child2DnaId != null ?
act.child2DnaId.Value.ToString("D") :
act.child1DnaId != null ?
act.child1DnaId.Value.ToString("D") :
act.rootDnaId != null ?
act.rootDnaId.Value.ToString("D") :
"";
actNode = act.child4DnaId != null ?
4 :
act.child3DnaId != null ?
3 :
act.child2DnaId != null ?
2 :
act.child1DnaId != null ?
1 :
act.rootDnaId != null ?
0 :
null;
}
else if (actRole == "BROTHER")
{
actNodeId = act.child4DnaId != null ?
act.child3DnaId.Value.ToString("D") :
act.child3DnaId != null ?
act.child2DnaId.Value.ToString("D") :
act.child2DnaId != null ?
act.child1DnaId!.Value.ToString("D") :
act.child1DnaId != null ?
act.rootDnaId.Value.ToString("D") :
act.rootDnaId != null ?
act.rootDnaId.Value.ToString("D") :
"";
actNode = act.child4DnaId != null ?
4 :
act.child3DnaId != null ?
3 :
act.child2DnaId != null ?
2 :
act.child1DnaId != null ?
1 :
act.rootDnaId != null ?
0 :
null;
}
else if (actRole == "ROOT" /*|| role == "PARENT"*/)
{
actNodeId = act.rootDnaId!.Value.ToString("D");
actNode = 0;
}
var rawDataAct = await _leaveRequestRepository.GetCancelLeaveRequestForAdminAsync(req.Year, req.Type, req.Status, actRole, actNodeId, actNode);
if (rawDataAct != null)
{
if (rawData != null)
rawData = rawData.Union(rawDataAct).DistinctBy(x => x.Id).ToList();
else
rawData = rawDataAct;
}
}
}
var recCount = rawData.Count; var recCount = rawData.Count;
if (req.Keyword != "") if (req.Keyword != "")
@ -2015,7 +2287,7 @@ namespace BMA.EHR.Leave.Service.Controllers
LeaveSubTypeName = item.LeaveSubTypeName, LeaveSubTypeName = item.LeaveSubTypeName,
ProfileType = item.ProfileType ?? "-", ProfileType = item.ProfileType ?? "-",
FullName = $"{item.Prefix}{item.FirstName} {item.LastName}", FullName = $"{item.Prefix}{item.FirstName} {item.LastName}",
DateSendLeave = item.CreatedAt.Date, DateSendLeave = item.DateSendLeave != null ? item.DateSendLeave.Value.Date : item.CreatedAt.Date,
Status = item.LeaveCancelStatus ?? "" Status = item.LeaveCancelStatus ?? ""
}; };
result.Add(res); result.Add(res);
@ -2112,7 +2384,7 @@ namespace BMA.EHR.Leave.Service.Controllers
} }
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(Guid.Parse(UserId!), AccessToken); // var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(Guid.Parse(UserId!), AccessToken);
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(Guid.Parse(UserId!), AccessToken); var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(Guid.Parse(UserId!), AccessToken);
if (profile == null) if (profile == null)
{ {
@ -2564,7 +2836,13 @@ namespace BMA.EHR.Leave.Service.Controllers
var startFiscalYear = new DateTime(rawData.LeaveStartDate.Year - 1, 10, 1); var startFiscalYear = new DateTime(rawData.LeaveStartDate.Year - 1, 10, 1);
var endFiscalYear = rawData.CreatedAt; var endFiscalYear = rawData.CreatedAt;
var endFiscalYear2 = new DateTime(rawData.LeaveStartDate.Year, 9, 30);
var leaveSummary = await _leaveRequestRepository.GetSumApproveLeaveTotalByTypeAndRangeForUser2(rawData.KeycloakUserId, rawData.Type.Id, startFiscalYear, endFiscalYear); var leaveSummary = await _leaveRequestRepository.GetSumApproveLeaveTotalByTypeAndRangeForUser2(rawData.KeycloakUserId, rawData.Type.Id, startFiscalYear, endFiscalYear);
// วันลาแบบร่างและที่ยื่นลาไปแล้ว
var leaveDraftSummary = await _leaveRequestRepository.GetSumDraftLeaveTotalByTypeAndRangeForUser2(rawData.KeycloakUserId, rawData.Type.Id, startFiscalYear, endFiscalYear2);
var leaveWaitingSummary = await _leaveRequestRepository.GetSumNewLeaveTotalByTypeAndRangeForUser2(rawData.KeycloakUserId, rawData.Type.Id, startFiscalYear, endFiscalYear2);
//var leaveSummary = leaveData == null ? 0.0 : leaveData.LeaveDaysUsed; //var leaveSummary = leaveData == null ? 0.0 : leaveData.LeaveDaysUsed;
if (leaveData != null) if (leaveData != null)
leaveSummary += leaveData.BeginningLeaveDays; leaveSummary += leaveData.BeginningLeaveDays;
@ -2588,7 +2866,7 @@ namespace BMA.EHR.Leave.Service.Controllers
LeaveSubTypeName = rawData.LeaveSubTypeName, LeaveSubTypeName = rawData.LeaveSubTypeName,
LeaveTypeId = rawData.Type.Id, LeaveTypeId = rawData.Type.Id,
FullName = $"{rawData.Prefix}{rawData.FirstName} {rawData.LastName}", FullName = $"{rawData.Prefix}{rawData.FirstName} {rawData.LastName}",
DateSendLeave = rawData.CreatedAt, DateSendLeave = rawData.DateSendLeave ?? rawData.CreatedAt,
Status = rawData.LeaveStatus, Status = rawData.LeaveStatus,
LeaveStartDate = rawData.LeaveStartDate, LeaveStartDate = rawData.LeaveStartDate,
LeaveEndDate = rawData.LeaveEndDate, LeaveEndDate = rawData.LeaveEndDate,
@ -2678,7 +2956,10 @@ namespace BMA.EHR.Leave.Service.Controllers
LeaveLimit = rawData.Type.Limit + extendLeave, LeaveLimit = rawData.Type.Limit + extendLeave,
LeaveSummary = leaveSummary, LeaveSummary = leaveSummary,
LeaveRemain = (rawData.Type.Limit + extendLeave) - leaveSummary LeaveRemain = (rawData.Type.Limit + extendLeave) - leaveSummary,
LeaveDraftSummary = leaveDraftSummary,
LeaveWaitingSummary = leaveWaitingSummary
}; };
if (rawData.LeaveDocument != null && rawData.LeaveDocument.Count > 0) if (rawData.LeaveDocument != null && rawData.LeaveDocument.Count > 0)
@ -2757,7 +3038,7 @@ namespace BMA.EHR.Leave.Service.Controllers
var rejectList = await _leaveRequestRepository.GetSumRejectLeaveAsync(thisYear); var rejectList = await _leaveRequestRepository.GetSumRejectLeaveAsync(thisYear);
var deleteList = await _leaveRequestRepository.GetSumDeleteLeaveAsync(thisYear); var deleteList = await _leaveRequestRepository.GetSumDeleteLeaveAsync(thisYear);
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); // var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken); var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
if (pf == null) if (pf == null)
{ {

View file

@ -147,6 +147,10 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
public List<GetLeaveApproverDto> Approvers { get; set; } = new(); public List<GetLeaveApproverDto> Approvers { get; set; } = new();
public Guid? KeycloakUserId { get; set; } = Guid.Empty; public Guid? KeycloakUserId { get; set; } = Guid.Empty;
public double LeaveDraftSummary { get; set; } = 0;
public double LeaveWaitingSummary { get; set; } = 0;
} }
public class GetLeaveApproverDto public class GetLeaveApproverDto

View file

@ -53,5 +53,8 @@
public string? CurrentZipCode { get; set; } public string? CurrentZipCode { get; set; }
public int GovAge { get; set; } = 0; public int GovAge { get; set; } = 0;
public double LeaveDraftSummary { get; set; } = 0;
public double LeaveWaitingSummary { get; set; } = 0;
} }
} }

View file

@ -903,6 +903,49 @@ namespace BMA.EHR.Placement.Service.Controllers
return Success(); return Success();
} }
/// <summary>
/// API สำหรับยกเลิกการส่งตัว
/// </summary>
/// <returns></returns>
/// <response code="200"></response>
/// <response code="400">ค่าตัวแปรที่ส่งมาไม่ถูกต้อง</response>
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
[HttpPost("update/draft-status")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ResponseObject>> PersonUpdateDraftStatus([FromBody] PersonUpdateStatusRequest req)
{
var getPermission = await _permission.GetPermissionAPIAsync("UPDATE", "SYS_PLACEMENT_PASS");
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission);
if (jsonData["status"]?.ToString() != "200")
return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden);
string role = jsonData["result"]?.ToString();
if (role != "OWNER")
return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden);
var person = await _context.PlacementProfiles
.FirstOrDefaultAsync(x => x.Id == req.PersonalId);
if (person == null)
return Error(GlobalMessages.DataNotFound, 404);
if (person.PlacementStatus == "REPORT")
return Error("ไม่สามารถยกเลิกการส่งตัวได้ เนื่องจากส่งไปออกคำสั่งแล้ว");
if (person.PlacementStatus == "DONE")
return Error("ไม่สามารถยกเลิกการส่งตัวได้ เนื่องจากบรรจุไปแล้ว");
person.Draft = false;
person.LastUpdateFullName = FullName ?? "System Administrator";
person.LastUpdateUserId = UserId ?? "";
person.LastUpdatedAt = DateTime.Now;
await _context.SaveChangesAsync();
return Success();
}
[HttpGet("pass/deferment/{personalId:length(36)}")] [HttpGet("pass/deferment/{personalId:length(36)}")]
public async Task<ActionResult<ResponseObject>> GetPersonDeferment(Guid personalId) public async Task<ActionResult<ResponseObject>> GetPersonDeferment(Guid personalId)
{ {
@ -2002,7 +2045,7 @@ namespace BMA.EHR.Placement.Service.Controllers
.Where(x => req.refIds.Contains(x.Id.ToString())) .Where(x => req.refIds.Contains(x.Id.ToString()))
// .Where(x => x.PlacementStatus.ToUpper() == "REPORT") // .Where(x => x.PlacementStatus.ToUpper() == "REPORT")
.ToListAsync(); .ToListAsync();
placementProfiles.ForEach(profile => profile.PlacementStatus = "PREPARE-CONTAI"); placementProfiles.ForEach(profile => profile.PlacementStatus = "PREPARE-CONTAIN");
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
return Success(); return Success();
} }

View file

@ -40,10 +40,17 @@
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="9.0.3" /> <PackageReference Include="Serilog.Sinks.Elasticsearch" Version="9.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" /> <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="DocumentFormat.OpenXml" Version="2.20.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\BMA.EHR.Infrastructure\BMA.EHR.Infrastructure.csproj" /> <ProjectReference Include="..\BMA.EHR.Infrastructure\BMA.EHR.Infrastructure.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="Templates\**\*.docx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project> </Project>

View file

@ -7,6 +7,7 @@ using BMA.EHR.Domain.Models.Retirement;
using BMA.EHR.Domain.Shared; using BMA.EHR.Domain.Shared;
using BMA.EHR.Infrastructure.Persistence; using BMA.EHR.Infrastructure.Persistence;
using BMA.EHR.Retirement.Service.Requests; using BMA.EHR.Retirement.Service.Requests;
using BMA.EHR.Retirement.Service.Services;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -37,6 +38,7 @@ namespace BMA.EHR.Retirement.Service.Controllers
private readonly PermissionRepository _permission; private readonly PermissionRepository _permission;
private readonly DisciplineDbContext _contextDiscipline; private readonly DisciplineDbContext _contextDiscipline;
private readonly RetireReportRepository _service; private readonly RetireReportRepository _service;
private readonly RetirementReportService _reportService;
public RetirementController(RetirementRepository repository, public RetirementController(RetirementRepository repository,
NotificationRepository repositoryNoti, NotificationRepository repositoryNoti,
ApplicationDBContext context, ApplicationDBContext context,
@ -46,7 +48,8 @@ namespace BMA.EHR.Retirement.Service.Controllers
IHttpContextAccessor httpContextAccessor, IHttpContextAccessor httpContextAccessor,
PermissionRepository permission, PermissionRepository permission,
DisciplineDbContext contextDiscipline, DisciplineDbContext contextDiscipline,
RetireReportRepository service) RetireReportRepository service,
RetirementReportService reportService)
{ {
_repository = repository; _repository = repository;
_repositoryNoti = repositoryNoti; _repositoryNoti = repositoryNoti;
@ -58,6 +61,7 @@ namespace BMA.EHR.Retirement.Service.Controllers
_permission = permission; _permission = permission;
_contextDiscipline = contextDiscipline; _contextDiscipline = contextDiscipline;
_service = service; _service = service;
_reportService = reportService;
} }
#region " Properties " #region " Properties "
@ -2213,5 +2217,83 @@ namespace BMA.EHR.Retirement.Service.Controllers
} }
} }
#endregion #endregion
#region &
/// <summary>
/// รายงานรายชื่อผู้เกษียณอายุราชการ ข้าราชการ & ลูกจ้างประจำ
/// </summary>
/// <param name="Id">Id ของรอบเกษียณ</param>
/// <param name="exportType">pdf, docx</param>
/// <returns></returns>
/// <response code="200">เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ</response>
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
[HttpGet("report/{exportType}/{Id}")]
public async Task<ActionResult<ResponseObject>> GetReportProfileRetirement([FromRoute] Guid Id, string exportType = "pdf")
{
var retire = await _service.GetProfileRetirementdAsync(Id, token);
if (retire != null)
{
var reportfile = string.Empty;
exportType = exportType.Trim();
switch (retire.GetType().GetProperty("Type").GetValue(retire))
{
case "OFFICER":
if (string.IsNullOrEmpty(retire.GetType().GetProperty("TypeReport").GetValue(retire)))
{
reportfile = $"retire-1";
}
else if (retire.GetType().GetProperty("TypeReport").GetValue(retire) == "ADD" || retire.GetType().GetProperty("TypeReport").GetValue(retire) == "EDIT")
{
reportfile = $"retire-2";
}
else if (retire.GetType().GetProperty("TypeReport").GetValue(retire) == "REMOVE")
{
reportfile = $"retire-3";
}
else
{
return Error(retire.GetType().GetProperty("TypeReport").GetValue(retire));
}
break;
case "EMPLOYEE":
if (string.IsNullOrEmpty(retire.GetType().GetProperty("TypeReport").GetValue(retire)))
{
reportfile = $"retire-emp-1";
}
else if (retire.GetType().GetProperty("TypeReport").GetValue(retire) == "ADD" || retire.GetType().GetProperty("TypeReport").GetValue(retire) == "EDIT")
{
reportfile = $"retire-emp-2";
}
else if (retire.GetType().GetProperty("TypeReport").GetValue(retire) == "REMOVE")
{
reportfile = $"retire-emp-3";
}
else
{
return Error(retire.GetType().GetProperty("TypeReport").GetValue(retire));
}
break;
default:
return Error(retire.GetType().GetProperty("Type").GetValue(retire));
}
var reportBytes = await _reportService.GenerateReportAsync(reportfile, retire, exportType);
var fileName = $"reportRetirement-{DateTime.Now:yyyyMMdd-HHmmss}.{exportType}";
var contentType = exportType.Trim().ToLower() == "pdf"
? "application/pdf"
: "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
return File(reportBytes, contentType, fileName);
}
else
{
return NotFound();
}
}
#endregion
} }
} }

View file

@ -3,6 +3,7 @@ using BMA.EHR.Domain.Middlewares;
using BMA.EHR.Infrastructure; using BMA.EHR.Infrastructure;
using BMA.EHR.Infrastructure.Persistence; using BMA.EHR.Infrastructure.Persistence;
using BMA.EHR.Retirement.Service; using BMA.EHR.Retirement.Service;
using BMA.EHR.Retirement.Service.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.ApiExplorer;
@ -86,6 +87,7 @@ var builder = WebApplication.CreateBuilder(args);
builder.Services.AddApplication(); builder.Services.AddApplication();
builder.Services.AddLeaveApplication(); builder.Services.AddLeaveApplication();
builder.Services.AddPersistence(builder.Configuration); builder.Services.AddPersistence(builder.Configuration);
builder.Services.AddScoped<RetirementReportService>();
builder.Services.AddLeavePersistence(builder.Configuration); builder.Services.AddLeavePersistence(builder.Configuration);
builder.Services.AddHttpClient(); builder.Services.AddHttpClient();

View file

@ -0,0 +1,638 @@
using BMA.EHR.Application.Responses;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
namespace BMA.EHR.Retirement.Service.Services
{
public class RetirementReportService
{
private readonly IWebHostEnvironment _environment;
private readonly ILogger<RetirementReportService> _logger;
private readonly IConfiguration _configuration;
/// <summary>
/// Initializes a new instance of the RetirementReportService class.
/// </summary>
public RetirementReportService(
IWebHostEnvironment environment,
ILogger<RetirementReportService> logger,
IConfiguration configuration)
{
_environment = environment;
_logger = logger;
_configuration = configuration;
}
#region Public Methods
/// <summary>
/// สร้างรายงานจาก Template (.docx)
/// </summary>
public async Task<byte[]> GenerateReportAsync(string templateName, dynamic data, string exportType)
{
try
{
var templatePath = GetTemplatePath(templateName);
var docxBytes = await ProcessTemplateAsync(templatePath, data);
return exportType.ToLower() == "pdf"
? await ConvertToPdfAsync(docxBytes)
: docxBytes;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error generating report");
throw;
}
}
#endregion
#region Template Processing
private string GetTemplatePath(string templateName)
{
var path = Path.Combine(_environment.ContentRootPath, "Templates", $"{templateName}.docx");
if (!File.Exists(path))
throw new FileNotFoundException($"Template not found: {templateName}");
return path;
}
private async Task<byte[]> ProcessTemplateAsync(string templatePath, dynamic data)
{
using var templateStream = File.OpenRead(templatePath);
using var outputStream = new MemoryStream();
await templateStream.CopyToAsync(outputStream);
outputStream.Position = 0;
using (var wordDoc = WordprocessingDocument.Open(outputStream, true))
{
var mainPart = wordDoc.MainDocumentPart;
if (mainPart == null) return Array.Empty<byte>();
ReplacePlaceholders(mainPart, data);
wordDoc.Save();
}
return outputStream.ToArray();
}
private void ReplacePlaceholders(MainDocumentPart mainPart, dynamic data)
{
var document = mainPart.Document;
if (document == null) return;
var processor = CreateDataProcessor(data);
processor.Process(document, new Action<Document, System.Collections.IEnumerable>(FillTableRows));
}
#endregion
#region Data Processing Strategy
private IDataProcessor CreateDataProcessor(dynamic data)
{
var dataType = data.GetType();
var isDictionary = dataType.IsGenericType &&
dataType.GetGenericTypeDefinition() == typeof(Dictionary<,>);
return isDictionary
? new DictionaryDataProcessor(data)
: new ObjectDataProcessor(data);
}
#endregion
#region Table Processing
private void FillTableRows(Document document, System.Collections.IEnumerable profiles)
{
var table = document.Descendants<Table>().FirstOrDefault();
if (table == null) return;
var rows = table.Elements<TableRow>().ToList();
if (rows.Count == 0) return;
var strategy = CreateTableStrategy(rows);
strategy.Process(table, rows, profiles);
}
private static ITableStrategy CreateTableStrategy(List<TableRow> rows)
{
// retire-1 format: 1 row, 1 cell, 1 paragraph
if (IsSingleParagraphFormat(rows))
return new SingleParagraphTableStrategy();
// retire-3 format: 2+ rows (header + template)
return new MultiRowTableStrategy();
}
private static bool IsSingleParagraphFormat(List<TableRow> rows) =>
rows.Count == 1 &&
rows[0].Elements<TableCell>().Count() == 1 &&
rows[0].Elements<TableCell>().First().Elements<Paragraph>().Count() == 1;
#endregion
#region PDF Conversion
private async Task<byte[]> ConvertToPdfAsync(byte[] docxBytes)
{
var tempDocx = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.docx");
var tempPdf = Path.ChangeExtension(tempDocx, ".pdf");
try
{
await File.WriteAllBytesAsync(tempDocx, docxBytes);
await ConvertToPdfInternalAsync(tempDocx, tempPdf);
return await File.ReadAllBytesAsync(tempPdf);
}
finally
{
if (File.Exists(tempDocx)) File.Delete(tempDocx);
if (File.Exists(tempPdf)) File.Delete(tempPdf);
}
}
private async Task ConvertToPdfInternalAsync(string docxPath, string pdfPath)
{
try
{
var useDocker = _configuration.GetValue<bool>("LibreOffice:UseDocker", false);
var timeout = _configuration.GetValue<int>("LibreOffice:Timeout", 180000);
if (useDocker)
{
await ConvertToPdfViaDockerAsync(docxPath, pdfPath, timeout);
}
else
{
// // PROD: Disabled local LibreOffice conversion
// await ConvertToPdfLocallyAsync(docxPath, pdfPath, timeout);
throw new NotSupportedException("LibreOffice conversion is disabled.");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error converting to PDF");
throw;
}
}
private async Task ConvertToPdfViaDockerAsync(string docxPath, string pdfPath, int timeout)
{
var inputDir = _configuration["LibreOffice:InputDirectory"] ?? "/app/libreoffice/input";
var outputDir = _configuration["LibreOffice:OutputDirectory"] ?? "/app/libreoffice/output";
var fileName = Path.GetFileName(docxPath);
var pdfName = Path.ChangeExtension(fileName, ".pdf");
// Ensure directories exist
Directory.CreateDirectory(inputDir);
Directory.CreateDirectory(outputDir);
// Copy file to input folder (LibreOffice watcher will pick it up)
var inputPath = Path.Combine(inputDir, fileName).Replace('\\', '/');
var outputPath = Path.Combine(outputDir, pdfName).Replace('\\', '/');
_logger.LogInformation("📤 Sending file to LibreOffice: {FileName}", fileName);
await File.WriteAllBytesAsync(inputPath, await File.ReadAllBytesAsync(docxPath));
// Wait for LibreOffice to convert (file watcher handles it)
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
var pollInterval = TimeSpan.FromMilliseconds(500);
while (stopwatch.ElapsedMilliseconds < timeout)
{
if (File.Exists(outputPath))
{
_logger.LogInformation("✅ PDF received: {PdfName} (took {ElapsedMs}ms)", pdfName, stopwatch.ElapsedMilliseconds);
await File.WriteAllBytesAsync(pdfPath, await File.ReadAllBytesAsync(outputPath));
// Cleanup
try
{
if (File.Exists(outputPath)) File.Delete(outputPath);
_logger.LogDebug("🗑️ Cleaned up output file: {PdfName}", pdfName);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to cleanup output file");
}
return;
}
await Task.Delay(pollInterval);
}
throw new TimeoutException($"LibreOffice conversion timed out after {timeout}ms. File not found: {outputPath}");
}
// // PROD: Disabled local LibreOffice conversion
// private async Task ConvertToPdfLocallyAsync(string docxPath, string pdfPath, int timeout)
// {
// var libreOfficePath = _configuration["LibreOffice:Path"] ?? GetDefaultLibreOfficePath();
// var arguments = _configuration["LibreOffice:Arguments"] ?? "--headless --convert-to pdf --nologo --norestore";
// var outputDir = Path.GetDirectoryName(pdfPath);
// if (string.IsNullOrEmpty(outputDir))
// {
// throw new DirectoryNotFoundException("Output directory cannot be determined");
// }
// var psi = new ProcessStartInfo
// {
// FileName = libreOfficePath,
// Arguments = $"{arguments} --outdir \"{outputDir}\" \"{docxPath}\"",
// UseShellExecute = false,
// RedirectStandardOutput = true,
// RedirectStandardError = true,
// CreateNoWindow = true
// };
// using var process = Process.Start(psi);
// var exited = process.WaitForExit(timeout);
// if (!exited)
// {
// process.Kill(entireProcessTree: true);
// throw new TimeoutException($"LibreOffice conversion timed out after {timeout}ms");
// }
// if (process.ExitCode != 0)
// {
// var error = await process.StandardError.ReadToEndAsync();
// throw new Exception($"LibreOffice conversion failed: {error}");
// }
// }
// // PROD: Disabled local LibreOffice path detection
// private static string GetDefaultLibreOfficePath()
// {
// if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
// {
// var possiblePaths = new[]
// {
// @"C:\Program Files\LibreOffice\program\soffice.exe",
// @"C:\Program Files (x86)\LibreOffice\program\soffice.exe",
// @"C:\Program Files\LibreOffice\program\soffice.com"
// };
// return possiblePaths.FirstOrDefault(File.Exists)
// ?? throw new FileNotFoundException("LibreOffice not found. Please install LibreOffice or configure the path in appsettings.json");
// }
// // Linux/Docker: use default path
// return "libreoffice";
// }
#endregion
}
#region Data Processor Interfaces & Implementations
internal interface IDataProcessor
{
void Process(Document document, Action<Document, System.Collections.IEnumerable> tableFiller);
}
internal class DictionaryDataProcessor : IDataProcessor
{
private readonly dynamic _data;
public DictionaryDataProcessor(dynamic data)
{
_data = data;
}
public void Process(Document document, Action<Document, System.Collections.IEnumerable> tableFiller)
{
var keys = _data.Keys as System.Collections.ICollection;
if (keys == null) return;
System.Collections.IEnumerable? profiles = null;
foreach (string key in keys)
{
if (key.Equals("profiles", StringComparison.OrdinalIgnoreCase))
{
profiles = _data[key] as System.Collections.IEnumerable;
continue;
}
var valueObj = _data[key];
if (valueObj != null && typeof(System.Collections.IEnumerable).IsAssignableFrom(valueObj.GetType()) &&
valueObj.GetType() != typeof(string))
{
continue;
}
var value = valueObj?.ToString() ?? string.Empty;
var placeholder = $"{{{{{key}}}}}";
TextReplacer.ReplaceAll(document, placeholder, value);
}
if (profiles != null)
{
tableFiller(document, profiles);
}
}
}
internal class ObjectDataProcessor : IDataProcessor
{
private readonly dynamic _data;
public ObjectDataProcessor(dynamic data)
{
_data = data;
}
public void Process(Document document, Action<Document, System.Collections.IEnumerable> tableFiller)
{
var dataType = _data.GetType();
var allProps = dataType.GetProperties();
var validProps = new List<PropertyInfo>();
foreach (var p in allProps)
{
if (p.GetIndexParameters().Length == 0)
{
validProps.Add(p);
}
}
System.Collections.IEnumerable? profiles = null;
foreach (var prop in validProps)
{
var propType = prop.PropertyType;
bool isEnumerable = typeof(System.Collections.IEnumerable).IsAssignableFrom(propType);
bool isString = propType == typeof(string);
if (isEnumerable && !isString)
{
if (prop.Name.Equals("profiles", StringComparison.OrdinalIgnoreCase))
{
profiles = prop.GetValue(_data) as System.Collections.IEnumerable;
}
continue;
}
var value = prop.GetValue(_data)?.ToString() ?? string.Empty;
var placeholder = $"{{{{{prop.Name}}}}}";
TextReplacer.ReplaceAll(document, placeholder, value);
}
if (profiles != null)
{
tableFiller(document, profiles);
}
}
}
#endregion
#region Text Replacer
internal static class TextReplacer
{
public static void ReplaceAll(Document document, string oldValue, string newValue)
{
bool found = false;
// Method 1: Check within single Run
foreach (var run in document.Descendants<Run>())
{
var textElements = run.Elements<Text>().ToList();
if (textElements.Count == 0) continue;
var combinedText = string.Concat(textElements.Select(t => t.Text));
if (combinedText.Contains(oldValue))
{
found = true;
var replacedText = combinedText.Replace(oldValue, newValue);
textElements[0].Text = replacedText;
for (int i = 1; i < textElements.Count; i++)
{
textElements[i].Text = string.Empty;
}
}
}
// Method 2: Check across all Runs in Paragraph
foreach (var para in document.Descendants<Paragraph>())
{
var allRuns = para.Elements<Run>().ToList();
if (allRuns.Count == 0) continue;
var combinedParaText = string.Concat(allRuns.SelectMany(r => r.Elements<Text>().Select(t => t.Text)));
if (combinedParaText.Contains(oldValue))
{
found = true;
var replacedText = combinedParaText.Replace(oldValue, newValue);
var firstRunTexts = allRuns[0].Elements<Text>().ToList();
if (firstRunTexts.Count > 0)
{
firstRunTexts[0].Text = replacedText;
for (int i = 1; i < firstRunTexts.Count; i++)
{
firstRunTexts[i].Text = string.Empty;
}
}
for (int i = 1; i < allRuns.Count; i++)
{
foreach (var t in allRuns[i].Elements<Text>())
{
t.Text = string.Empty;
}
}
}
}
// Fallback: Check individual Text elements
if (!found)
{
foreach (var text in document.Descendants<Text>())
{
if (!string.IsNullOrEmpty(text.Text) && text.Text.Contains(oldValue))
{
found = true;
text.Text = text.Text.Replace(oldValue, newValue);
}
}
}
}
public static void ReplaceInRow(TableRow row, string oldValue, string newValue)
{
bool found = false;
foreach (var cell in row.Descendants<TableCell>())
{
foreach (var para in cell.Elements<Paragraph>())
{
found = ReplaceInParagraph(para, oldValue, newValue) || found;
}
}
// Fallback: Check individual Text elements
if (!found)
{
foreach (var text in row.Descendants<Text>())
{
if (!string.IsNullOrEmpty(text.Text) && text.Text.Contains(oldValue))
{
found = true;
text.Text = text.Text.Replace(oldValue, newValue);
}
}
}
}
public static bool ReplaceInParagraph(Paragraph paragraph, string oldValue, string newValue)
{
bool found = false;
var allTexts = paragraph.Descendants<Text>().ToList();
if (allTexts.Count == 0) return false;
var combinedParaText = string.Concat(allTexts.Select(t => t.Text));
if (combinedParaText.Contains(oldValue))
{
found = true;
var replacedText = combinedParaText.Replace(oldValue, newValue);
allTexts[0].Text = replacedText;
for (int i = 1; i < allTexts.Count; i++)
{
allTexts[i].Text = string.Empty;
}
}
// Fallback: Check individual Text elements
if (!found)
{
foreach (var text in allTexts)
{
if (!string.IsNullOrEmpty(text.Text) && text.Text.Contains(oldValue))
{
found = true;
text.Text = text.Text.Replace(oldValue, newValue);
}
}
}
return found;
}
}
#endregion
#region Table Strategy Interfaces & Implementations
internal interface ITableStrategy
{
void Process(Table table, List<TableRow> rows, System.Collections.IEnumerable profiles);
}
internal class SingleParagraphTableStrategy : ITableStrategy
{
public void Process(Table table, List<TableRow> rows, System.Collections.IEnumerable profiles)
{
var cell = rows[0].Elements<TableCell>().First();
var templatePara = cell.Elements<Paragraph>().First();
var profileList = profiles.Cast<object>().ToList();
foreach (var profile in profileList)
{
var props = profile.GetType()
.GetProperties()
.Where(p => p.GetIndexParameters().Length == 0)
.ToList();
var newPara = (Paragraph)templatePara.CloneNode(true);
foreach (var prop in props)
{
var value = prop.GetValue(profile)?.ToString() ?? string.Empty;
var placeholder = $"{{{{{prop.Name}}}}}";
TextReplacer.ReplaceInParagraph(newPara, placeholder, value);
}
cell.Append(newPara);
}
templatePara.Remove();
}
}
internal class MultiRowTableStrategy : ITableStrategy
{
public void Process(Table table, List<TableRow> rows, System.Collections.IEnumerable profiles)
{
var templateRowIndex = rows.Count >= 2 ? 1 : 0;
var templateRow = rows[templateRowIndex];
templateRow.Remove();
var profileList = profiles.Cast<object>().ToList();
// Process header row if exists
if (rows.Count >= 2)
{
ProcessHeaderRow(rows[0], profileList);
}
// Process template rows
foreach (var profile in profileList)
{
var newRow = (TableRow)templateRow.CloneNode(true);
var props = profile.GetType()
.GetProperties()
.Where(p => p.GetIndexParameters().Length == 0)
.ToList();
foreach (var prop in props)
{
var value = prop.GetValue(profile)?.ToString() ?? string.Empty;
var placeholder = $"{{{{{prop.Name}}}}}";
TextReplacer.ReplaceInRow(newRow, placeholder, value);
}
table.AppendChild(newRow);
}
}
private static void ProcessHeaderRow(TableRow headerRow, List<object> profileList)
{
var firstProfile = profileList.FirstOrDefault();
if (firstProfile == null) return;
var props = firstProfile.GetType()
.GetProperties()
.Where(p => p.GetIndexParameters().Length == 0)
.ToList();
foreach (var prop in props)
{
var value = prop.GetValue(firstProfile)?.ToString() ?? string.Empty;
var placeholder = $"{{{{{prop.Name}}}}}";
if (!string.IsNullOrWhiteSpace(value))
{
TextReplacer.ReplaceInRow(headerRow, placeholder, value);
}
}
}
}
#endregion
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.