Compare commits
48 commits
insignia-d
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0365fad723 | ||
|
|
20e8dfddd6 | ||
|
|
91c479ef9e | ||
|
|
80fcda61cf | ||
|
|
f02413f2b2 | ||
|
|
1739aa8057 | ||
|
|
bc3bba547f | ||
|
|
4161fcc1cf | ||
|
|
6d0921a76a | ||
|
|
df7bebe0ba | ||
|
|
82a45b6811 | ||
|
|
63d983f831 | ||
|
|
e326e43ae6 | ||
|
|
4dab3c5cd9 | ||
|
|
4bd46d13e5 | ||
|
|
132a59b946 | ||
|
|
740a9984c9 | ||
|
|
5b0fcd0680 | ||
|
|
2bdb8bb733 | ||
|
|
aed1e8a58d | ||
|
|
fb3cb2aa94 | ||
|
|
b5025c382f | ||
|
|
4e2113eef2 | ||
|
|
ffcf95c210 | ||
|
|
e4bcfee80c | ||
|
|
a173a7dc3c | ||
|
|
361ded2078 | ||
|
|
1379dab556 | ||
|
|
d8039379ad | ||
|
|
2d4116d79a | ||
|
|
c65a4a04ac | ||
|
|
d58c7dc07e | ||
|
|
bb329f86de | ||
|
|
b3298e88c6 | ||
|
|
04d0067ee8 | ||
|
|
c035c13405 | ||
|
|
2e9db2d42c | ||
|
|
1389df0225 | ||
|
|
058027ea29 | ||
|
|
ee2d16925a | ||
|
|
42f3813a7a | ||
|
|
7bafbf5001 | ||
|
|
db99630e0d | ||
|
|
34ec9bb77c | ||
|
|
5606e8b50a | ||
|
|
ee4e9c3699 | ||
|
|
6efeec3f1f | ||
|
|
c34fe35506 |
58 changed files with 29241 additions and 367 deletions
|
|
@ -80,7 +80,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
public async Task UpdateLeaveUsageAsync(int year, Guid typeId, Guid userId, double day)
|
||||
{
|
||||
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
if (pf == null)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
if (pf == null)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
if (pf == null)
|
||||
{
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
|
|
@ -149,7 +149,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var prevRemain = 0.0;
|
||||
if (prev != null)
|
||||
{
|
||||
prevRemain = prev.LeaveDays - prev.LeaveDaysUsed;
|
||||
prevRemain = prev.LeaveDays - (prev.LeaveDaysUsed ?? 0.0);
|
||||
}
|
||||
|
||||
if (govAge >= 180)
|
||||
|
|
@ -215,7 +215,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var prevRemain = 0.0;
|
||||
if (prev != null)
|
||||
{
|
||||
prevRemain = prev.LeaveDays - prev.LeaveDaysUsed;
|
||||
prevRemain = prev.LeaveDays - (prev.LeaveDaysUsed ?? 0.0);
|
||||
}
|
||||
|
||||
if (govAge >= 180)
|
||||
|
|
@ -263,7 +263,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
public async Task<LeaveBeginning?> GetByYearAndTypeIdForUser2Async(int year, Guid typeId, Guid userId)
|
||||
{
|
||||
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
if (pf == null)
|
||||
{
|
||||
return null;
|
||||
|
|
@ -288,7 +288,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var prevRemain = 0.0;
|
||||
if (prev != null)
|
||||
{
|
||||
prevRemain = prev.LeaveDays - prev.LeaveDaysUsed;
|
||||
prevRemain = prev.LeaveDays - (prev.LeaveDaysUsed ?? 0.0);
|
||||
}
|
||||
|
||||
if (govAge >= 180)
|
||||
|
|
@ -376,7 +376,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var prevRemain = 0.0;
|
||||
if (prev != null)
|
||||
{
|
||||
prevRemain = prev.LeaveDays - prev.LeaveDaysUsed;
|
||||
prevRemain = prev.LeaveDays - (prev.LeaveDaysUsed ?? 0.0);
|
||||
}
|
||||
|
||||
if (govAge >= 180)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ using Microsoft.Extensions.Configuration;
|
|||
using System.IO.Compression;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Json;
|
||||
using BMA.EHR.Application.Repositories.Leaves.TimeAttendants;
|
||||
using BMA.EHR.Domain.Models.Leave.TimeAttendants;
|
||||
|
||||
namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
||||
{
|
||||
|
|
@ -29,6 +31,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
private readonly MinIOLeaveService _minIOService;
|
||||
|
||||
private readonly LeaveBeginningRepository _leaveBeginningRepository;
|
||||
private readonly ProcessUserTimeStampRepository _processUserTimeStampRepository;
|
||||
|
||||
private readonly string URL = string.Empty;
|
||||
|
||||
|
|
@ -44,7 +47,8 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
EmailSenderService emailSenderService,
|
||||
IApplicationDBContext appDbContext,
|
||||
MinIOLeaveService minIOService,
|
||||
LeaveBeginningRepository leaveBeginningRepository) : base(dbContext, httpContextAccessor)
|
||||
LeaveBeginningRepository leaveBeginningRepository,
|
||||
ProcessUserTimeStampRepository processUserTimeStampRepository) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
|
|
@ -58,6 +62,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
Console.WriteLine($"URL : {URL}");
|
||||
_minIOService = minIOService;
|
||||
_leaveBeginningRepository = leaveBeginningRepository;
|
||||
_processUserTimeStampRepository = processUserTimeStampRepository;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
@ -254,7 +259,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
public async Task<List<LeaveRequest>> GetLeaveRequestByYearAsync(int year, Guid userId)
|
||||
{
|
||||
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
|
||||
if (profile == null)
|
||||
{
|
||||
|
|
@ -354,7 +359,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var rawData = _dbContext.Set<LeaveRequest>().AsNoTracking()
|
||||
.Include(x => x.Type)
|
||||
.Where(x => x.LeaveStatus != "DRAFT")
|
||||
.OrderByDescending(x => x.CreatedAt)
|
||||
.OrderByDescending(x => (x.DateSendLeave ?? x.CreatedAt))
|
||||
.AsQueryable();
|
||||
|
||||
if (year != 0)
|
||||
|
|
@ -380,7 +385,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var rawData = _dbContext.Set<LeaveRequest>().AsNoTracking()
|
||||
.Include(x => x.Type)
|
||||
.Where(x => x.LeaveStatus != "DRAFT")
|
||||
.OrderByDescending(x => x.CreatedAt)
|
||||
.OrderByDescending(x => (x.DateSendLeave ?? x.CreatedAt))
|
||||
.AsQueryable();
|
||||
// fix issue : 1830
|
||||
if (year != 0)
|
||||
|
|
@ -447,7 +452,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
.Include(x => x.Type)
|
||||
.Where(x => keycloakIdList.Contains(x.KeycloakUserId))
|
||||
.Where(x => x.LeaveStatus != "DRAFT")
|
||||
.OrderByDescending(x => x.CreatedAt)
|
||||
.OrderByDescending(x =>(x.DateSendLeave ?? x.CreatedAt))
|
||||
.AsQueryable();
|
||||
|
||||
if (year != 0)
|
||||
|
|
@ -497,7 +502,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
public async Task<double> GetSumLeaveByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId, int year)
|
||||
{
|
||||
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(keycloakUserId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(keycloakUserId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(keycloakUserId, AccessToken);
|
||||
if (pf == null)
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
|
||||
|
|
@ -522,7 +527,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
//.Where(x => x.LeaveStatus != "REJECT" && x.LeaveStatus != "DELETE")
|
||||
.ToListAsync();
|
||||
|
||||
return data.Sum(x => x.LeaveTotal) + (beginningLeave == null ? 0 : beginningLeave.LeaveDaysUsed);
|
||||
return data.Sum(x => x.LeaveTotal) + (beginningLeave == null ? 0 : (beginningLeave.LeaveDaysUsed ?? 0.0));
|
||||
}
|
||||
|
||||
//public async Task<double> GetSumApproveLeaveByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId, int year)
|
||||
|
|
@ -574,12 +579,12 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking()
|
||||
.Include(x => x.Type)
|
||||
//.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.Type.Id == leaveTypeId)
|
||||
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
|
||||
//.Where(x => x.LeaveStatus != "REJECT" && x.LeaveStatus != "DELETE")
|
||||
.OrderByDescending(x => x.CreatedAt)
|
||||
.OrderByDescending(x => (x.DateSendLeave ?? x.CreatedAt))
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
return data;
|
||||
|
|
@ -651,7 +656,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
try
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
|
|
@ -728,7 +733,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
|
|
@ -817,7 +822,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
|
|
@ -904,6 +909,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
|
||||
|
||||
rawData.LeaveStatus = "NEW";
|
||||
rawData.DateSendLeave = DateTime.Now; // Update วันที่ยื่นลาเป็นวันที่ปัจจุบัน
|
||||
//rawData.ApproveStep = "st2";
|
||||
|
||||
await UpdateAsync(rawData);
|
||||
|
|
@ -1242,7 +1248,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
else
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
|
|
@ -1324,9 +1330,68 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
}
|
||||
await _appDbContext.SaveChangesAsync();
|
||||
|
||||
// insert to process timestamp
|
||||
|
||||
|
||||
// ปรับสถานะการลงเวลา
|
||||
if (rawData.LeaveStartDate.Date == rawData.LeaveEndDate.Date)
|
||||
{
|
||||
var processCheckIn = await _dbContext.Set<ProcessUserTimeStamp>()
|
||||
.Where(x => x.KeycloakUserId == rawData.KeycloakUserId)
|
||||
.Where(x => x.CheckIn.Date == rawData.LeaveStartDate.Date)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
|
||||
if (processCheckIn is not null)
|
||||
{
|
||||
switch (rawData.LeaveRange.Trim().ToUpper())
|
||||
{
|
||||
case "MORNING":
|
||||
processCheckIn.CheckInStatus = "NORMAL";
|
||||
break;
|
||||
case "AFTERNOON":
|
||||
processCheckIn.CheckOutStatus = "NORMAL";
|
||||
break;
|
||||
case "ALL":
|
||||
processCheckIn.CheckInStatus = "NORMAL";
|
||||
processCheckIn.CheckOutStatus = "NORMAL";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
var from = rawData.LeaveStartDate.Date;
|
||||
var to = rawData.LeaveEndDate.Date;
|
||||
for (var day = from.Date; day <= to.Date; day = day.AddDays(1))
|
||||
{
|
||||
var processCheckIn = await _dbContext.Set<ProcessUserTimeStamp>()
|
||||
.Where(x => x.KeycloakUserId == rawData.KeycloakUserId)
|
||||
.Where(x => x.CheckIn.Date == day.Date)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (processCheckIn is not null)
|
||||
{
|
||||
switch (rawData.LeaveRange.Trim().ToUpper())
|
||||
{
|
||||
case "MORNING":
|
||||
processCheckIn.CheckInStatus = "NORMAL";
|
||||
break;
|
||||
case "AFTERNOON":
|
||||
processCheckIn.CheckOutStatus = "NORMAL";
|
||||
break;
|
||||
case "ALL":
|
||||
processCheckIn.CheckInStatus = "NORMAL";
|
||||
processCheckIn.CheckOutStatus = "NORMAL";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// Send Noti
|
||||
var noti = new Notification
|
||||
{
|
||||
|
|
@ -1412,7 +1477,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
else
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
|
|
@ -1485,7 +1550,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
KeycloakUserId = pf.Keycloak == null ? Guid.Empty : pf.Keycloak.Value,
|
||||
LeaveTypeId = b.LeaveTypeId,
|
||||
LeaveTypeCode = b.LeaveType!.Code,
|
||||
SumLeaveDay = b.LeaveDaysUsed
|
||||
SumLeaveDay = b.LeaveDaysUsed ?? 0.0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1876,7 +1941,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
.Include(x => x.Type)
|
||||
.Where(x => x.KeycloakUserId == keycloakUserId)
|
||||
.Where(x => x.Type.Id == leaveTypeId)
|
||||
.Where(x => x.CreatedAt.Date >= startDate && x.CreatedAt < endDate)
|
||||
.Where(x => ((x.DateSendLeave ?? x.CreatedAt) >= startDate && (x.DateSendLeave ??x.CreatedAt) <= endDate))
|
||||
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
|
||||
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
|
||||
.ToListAsync();
|
||||
|
|
@ -1886,6 +1951,102 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
public async Task<double> GetSumApproveLeaveTotalByTypeAndRangeForUserByProfile(Guid profileId, Guid leaveTypeId, DateTime startDate, DateTime endDate)
|
||||
{
|
||||
var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking()
|
||||
.Include(x => x.Type)
|
||||
.Where(x => x.ProfileId == profileId)
|
||||
.Where(x => x.Type.Id == leaveTypeId)
|
||||
.Where(x => ((x.DateSendLeave ?? x.CreatedAt) >= startDate && (x.DateSendLeave ??x.CreatedAt) <= endDate))
|
||||
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
|
||||
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
|
||||
.ToListAsync();
|
||||
|
||||
if (data.Count > 0)
|
||||
return data.Sum(x => x.LeaveTotal);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
public async Task<int> GetSumApproveLeaveCountByTypeAndRangeForUserByProfile(Guid profileId, Guid leaveTypeId, DateTime startDate, DateTime endDate)
|
||||
{
|
||||
var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking()
|
||||
.Include(x => x.Type)
|
||||
.Where(x => x.ProfileId == profileId)
|
||||
.Where(x => x.Type.Id == leaveTypeId)
|
||||
.Where(x => ((x.DateSendLeave ?? x.CreatedAt) >= startDate && (x.DateSendLeave ??x.CreatedAt) <= endDate))
|
||||
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
|
||||
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
|
||||
.ToListAsync();
|
||||
|
||||
return data.Count;
|
||||
}
|
||||
|
||||
public async Task<int> GetSumApproveLeaveCountByTypeAndRangeForUser2(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) >= startDate && (x.DateSendLeave ??x.CreatedAt) <= endDate))
|
||||
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
|
||||
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
|
||||
.ToListAsync();
|
||||
|
||||
return data.Count;
|
||||
}
|
||||
|
||||
/// <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) >= startDate && (x.DateSendLeave ??x.CreatedAt) < endDate))
|
||||
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
|
||||
.Where(x => (x.LeaveStatus == "NEW" || x.LeaveStatus == "PENDING"))
|
||||
.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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -213,6 +213,79 @@ namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<List<AdditionalCheckRequest>> GetAdditionalCheckRequestsByAdminRole2(DateTime startDate, DateTime endDate, string role, string nodeId, int? node, string? keyword, string? status)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = await _dbContext.Set<AdditionalCheckRequest>().AsQueryable()
|
||||
.Where(x => (x.CheckDate.Date >= startDate.Date && x.CheckDate.Date <= endDate.Date))
|
||||
.OrderByDescending(x => x.CreatedAt.Date)
|
||||
.ToListAsync();
|
||||
|
||||
if(!string.IsNullOrEmpty(status))
|
||||
data = data.Where(x => x.Status == status).ToList();
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(keyword))
|
||||
{
|
||||
data = data.Where(x =>
|
||||
(
|
||||
(x.Prefix ?? "") + (x.FirstName ?? "") + " " + (x.LastName ?? "")).Contains(keyword)
|
||||
|| x.Description.Contains(keyword)
|
||||
|
||||
).ToList();
|
||||
}
|
||||
|
||||
if (role == "OWNER")
|
||||
{
|
||||
node = null;
|
||||
}
|
||||
if (role == "OWNER" || role == "CHILD")
|
||||
{
|
||||
data = data
|
||||
.Where(x => node == 4 ? x.Child4DnaId == Guid.Parse(nodeId!) : (node == 3 ? x.Child3DnaId == Guid.Parse(nodeId!) : (node == 2 ? x.Child2DnaId == Guid.Parse(nodeId!) : (node == 1 ? x.Child1DnaId == Guid.Parse(nodeId!) : (node == 0 ? x.RootDnaId == Guid.Parse(nodeId!) : (node == null ? true : true))))))
|
||||
.ToList();
|
||||
}
|
||||
else if (role == "BROTHER")
|
||||
{
|
||||
data = data
|
||||
.Where(x => node == 4 ? x.Child3DnaId == Guid.Parse(nodeId!) : (node == 3 ? x.Child2DnaId == Guid.Parse(nodeId!) : (node == 2 ? x.Child1DnaId == Guid.Parse(nodeId!) : (node == 1 || node == 0 ? x.RootDnaId == Guid.Parse(nodeId!) : (node == null ? true : true)))))
|
||||
.ToList();
|
||||
}
|
||||
else if (role == "ROOT")
|
||||
{
|
||||
data = data
|
||||
.Where(x => x.RootDnaId == Guid.Parse(nodeId!)).ToList();
|
||||
}
|
||||
// else if (role == "PARENT")
|
||||
// {
|
||||
// data = data
|
||||
// .Where(x => x.RootDnaId == Guid.Parse(nodeId!) && x.Child1DnaId != null && x.Child1DnaId != Guid.Empty).ToList();
|
||||
// }
|
||||
else if (role == "NORMAL")
|
||||
{
|
||||
data = data.Where(x =>
|
||||
node == 0 ? x.RootDnaId == Guid.Parse(nodeId!) &&
|
||||
(x.Child1DnaId == Guid.Empty || x.Child1DnaId == null) :
|
||||
node == 1 ? x.Child1DnaId == Guid.Parse(nodeId!) &&
|
||||
(x.Child2DnaId == Guid.Empty || x.Child2DnaId == null) :
|
||||
node == 2 ? x.Child2DnaId == Guid.Parse(nodeId!) &&
|
||||
(x.Child3DnaId == Guid.Empty || x.Child3DnaId == null) :
|
||||
node == 3 ? x.Child3DnaId == Guid.Parse(nodeId!) &&
|
||||
(x.Child4DnaId == Guid.Empty || x.Child4DnaId == null) :
|
||||
node == 4 ? x.Child4DnaId == Guid.Parse(nodeId!) :
|
||||
true
|
||||
).ToList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,12 +49,16 @@ namespace BMA.EHR.Application.Repositories.MetaData
|
|||
|
||||
public async Task<int> GetHolidayCountAsync(DateTime startDate, DateTime endDate, string category = "NORMAL")
|
||||
{
|
||||
var data = await _dbContext.Set<Holiday>().AsQueryable()
|
||||
var query = _dbContext.Set<Holiday>().AsQueryable()
|
||||
.Where(x => x.Category == category)
|
||||
.Where(x => x.HolidayDate.Date >= startDate && x.HolidayDate.Date <= endDate)
|
||||
.CountAsync();
|
||||
.Where(x => x.HolidayDate.Date >= startDate && x.HolidayDate.Date <= endDate);
|
||||
|
||||
return data;
|
||||
if (category == "NORMAL")
|
||||
query = query.Where(x => x.HolidayDate.DayOfWeek != DayOfWeek.Saturday && x.HolidayDate.DayOfWeek != DayOfWeek.Sunday);
|
||||
else
|
||||
query = query.Where(x => x.HolidayDate.DayOfWeek != DayOfWeek.Sunday);
|
||||
|
||||
return await query.CountAsync();
|
||||
}
|
||||
|
||||
public List<DateTime> GetWeekEnd(DateTime startDate, DateTime endDate, string category = "NORMAL")
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using System.Net.Http.Headers;
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using System.Security.Claims;
|
||||
using System.Net.Http.Json;
|
||||
using BMA.EHR.Application.Responses.Leaves;
|
||||
|
||||
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)
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ namespace BMA.EHR.Application.Repositories.Reports
|
|||
}).ToList();
|
||||
}
|
||||
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
|
||||
|
|
@ -312,7 +312,7 @@ namespace BMA.EHR.Application.Repositories.Reports
|
|||
root = (isDuplicateRoot ? "" : profile.root + "\n") +
|
||||
(isDuplicateHospital || !hospital.ToObject<List<string>>().Contains(profile.child1) ? "" : profile.child1 + "\n") +
|
||||
(isDuplicatePosType ? "" : $"ตำแหน่งประเภท{profile.posTypeName}" + "\n") +
|
||||
(isDuplicatePosLevel ? "" : $"ระดับ{profile.posLevelName}"),
|
||||
(isDuplicatePosLevel ? "" : $"ระดับ{profile.posLevelName}").ToThaiNumber(),
|
||||
child = (profile.posExecutiveName == null ? "" : profile.posExecutiveName + "\n") +
|
||||
(profile.child4 == null ? "" : profile.child4 + "\n") +
|
||||
(profile.child3 == null ? "" : profile.child3 + "\n") +
|
||||
|
|
@ -326,7 +326,7 @@ namespace BMA.EHR.Application.Repositories.Reports
|
|||
}).ToList();
|
||||
}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using RabbitMQ.Client;
|
||||
using RabbitMQ.Client.Events;
|
||||
using System.Text;
|
||||
|
|
@ -21,77 +21,101 @@ var queue = configuration["Rabbit:Queue"] ?? "basic-queue";
|
|||
// create connection
|
||||
var factory = new ConnectionFactory()
|
||||
{
|
||||
//Uri = new Uri("amqp://admin:P@ssw0rd@192.168.4.11:5672")
|
||||
HostName = host,// หรือ hostname ของ RabbitMQ Server ที่คุณใช้
|
||||
UserName = user, // ใส่ชื่อผู้ใช้ของคุณ
|
||||
Password = pass // ใส่รหัสผ่านของคุณ
|
||||
HostName = host,
|
||||
UserName = user,
|
||||
Password = pass,
|
||||
DispatchConsumersAsync = true
|
||||
};
|
||||
|
||||
using var connection = factory.CreateConnection();
|
||||
using var channel = connection.CreateModel();
|
||||
|
||||
//channel.QueueDeclare(queue: "bma-checkin-queue", durable: true, exclusive: false, autoDelete: false, arguments: null);
|
||||
channel.QueueDeclare(queue: queue, durable: true, exclusive: false, autoDelete: false, arguments: null);
|
||||
|
||||
var consumer = new EventingBasicConsumer(channel);
|
||||
// Create a SINGLE static HttpClient instance to prevent socket exhaustion
|
||||
using var httpClient = new HttpClient();
|
||||
httpClient.Timeout = TimeSpan.FromSeconds(300); // 5 นาที
|
||||
|
||||
var consumer = new AsyncEventingBasicConsumer(channel);
|
||||
|
||||
consumer.Received += async (model, ea) =>
|
||||
{
|
||||
var body = ea.Body.ToArray();
|
||||
var message = Encoding.UTF8.GetString(body);
|
||||
await CallRestApi(message);
|
||||
try
|
||||
{
|
||||
var body = ea.Body.ToArray();
|
||||
var message = Encoding.UTF8.GetString(body);
|
||||
|
||||
// convert string into object
|
||||
//var request = JsonConvert.DeserializeObject<CheckInRequest>(message);
|
||||
//using (var db = new ApplicationDbContext())
|
||||
//{
|
||||
// var item = new AttendantItem
|
||||
// {
|
||||
// Name = request.Name,
|
||||
// CheckInDateTime = request.CheckInDateTime,
|
||||
// };
|
||||
// db.AttendantItems.Add(item);
|
||||
// db.SaveChanges();
|
||||
WriteToConsole($"Received message: {message}");
|
||||
|
||||
// WriteToConsole($"ได้รับคำขอจาก Queue: {message}");
|
||||
// WriteToConsole($"ตอบกลับจาก REST API: {JsonConvert.SerializeObject(item)}");
|
||||
//}
|
||||
var success = await CallRestApi(message, httpClient, configuration);
|
||||
|
||||
WriteToConsole($"ได้รับคำขอจาก Queue: {message}");
|
||||
//WriteToConsole($"ตอบกลับจาก REST API: {JsonConvert.SerializeObject(item)}");
|
||||
if (success)
|
||||
{
|
||||
channel.BasicAck(ea.DeliveryTag, multiple: false);
|
||||
WriteToConsole("Message processed successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
channel.BasicNack(ea.DeliveryTag, multiple: false, requeue: false);
|
||||
WriteToConsole("Message processing failed - message rejected");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteToConsole($"Error processing message: {ex.Message}");
|
||||
channel.BasicNack(ea.DeliveryTag, multiple: false, requeue: false);
|
||||
}
|
||||
};
|
||||
|
||||
//channel.BasicConsume(queue: "bma-checkin-queue", autoAck: true, consumer: consumer);
|
||||
channel.BasicConsume(queue: queue, autoAck: true, consumer: consumer);
|
||||
channel.BasicConsume(queue: queue, autoAck: false, consumer: consumer);
|
||||
|
||||
//Console.WriteLine("\nPress 'Enter' to exit the process...");
|
||||
WriteToConsole("Consumer started. Waiting for messages...");
|
||||
|
||||
// Keep the application running
|
||||
await Task.Delay(-1);
|
||||
|
||||
static void WriteToConsole(string message)
|
||||
{
|
||||
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} : {message}");
|
||||
Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} : {message}");
|
||||
}
|
||||
|
||||
async Task CallRestApi(string requestData)
|
||||
static async Task<bool> CallRestApi(string requestData, HttpClient client, IConfiguration configuration)
|
||||
{
|
||||
using var client = new HttpClient();
|
||||
var apiPath = $"{configuration["API"]}/leave/process-check-in";
|
||||
|
||||
var content = new StringContent(requestData, Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await client.PostAsync(apiPath, content);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
try
|
||||
{
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
WriteToConsole(responseContent);
|
||||
var apiPath = $"{configuration["API"]}/leave/process-check-in";
|
||||
var content = new StringContent(requestData, Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await client.PostAsync(apiPath, content);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
WriteToConsole($"API Success: {responseContent}");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var errorMessage = await response.Content.ReadAsStringAsync();
|
||||
var res = JsonSerializer.Deserialize<ResponseObject>(errorMessage);
|
||||
WriteToConsole($"API Error ({response.StatusCode}): {res?.Message ?? errorMessage}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
var errorMessage = await response.Content.ReadAsStringAsync();
|
||||
var res = JsonSerializer.Deserialize<ResponseObject>(errorMessage);
|
||||
WriteToConsole($"Error: {res.Message}");
|
||||
WriteToConsole($"HTTP Error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
catch (TaskCanceledException ex)
|
||||
{
|
||||
WriteToConsole($"Timeout: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteToConsole($"Unexpected Error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -110,28 +134,14 @@ public class ResponseObject
|
|||
public class CheckTimeDtoRB
|
||||
{
|
||||
public Guid? CheckInId { get; set; }
|
||||
|
||||
|
||||
public double Lat { get; set; } = 0;
|
||||
|
||||
|
||||
public double Lon { get; set; } = 0;
|
||||
|
||||
|
||||
public string POI { get; set; } = string.Empty;
|
||||
|
||||
|
||||
public bool IsLocation { get; set; } = true;
|
||||
|
||||
public string? LocationName { get; set; } = string.Empty;
|
||||
|
||||
public string? Remark { get; set; } = string.Empty;
|
||||
|
||||
public Guid? UserId { get; set; }
|
||||
|
||||
public DateTime? CurrentDate { get; set; }
|
||||
|
||||
public string? CheckInFileName { get; set; }
|
||||
|
||||
public byte[]? CheckInFileBytes { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1013,6 +1013,11 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
.Include(x => x.DisciplineDisciplinary)
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => { profile.Status = "REPORTED"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -1061,8 +1066,8 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
// คำสั่งไล่ออก หรือ ปลดออก Status หลังออกคำสั่งใช้ "REPORTED" เพื่อไม่ให้ส่งรายชื่อไปออกคำสั่งซ้ำได้
|
||||
data.ForEach(profile => { profile.Status = "REPORTED"; profile.CommandTypeId = null; });
|
||||
//// คำสั่งไล่ออก หรือ ปลดออก Status หลังออกคำสั่งใช้ "REPORTED" เพื่อไม่ให้ส่งรายชื่อไปออกคำสั่งซ้ำได้
|
||||
// data.ForEach(profile => { profile.Status = "REPORTED"; profile.CommandTypeId = null; });
|
||||
var _profile = new List<ProfileComplaintInvestigate>();
|
||||
DateTime _date = DateTime.Now;
|
||||
foreach (var item in data)
|
||||
|
|
@ -1150,6 +1155,11 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
.Include(x => x.DisciplineDisciplinary)
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => { profile.Status = "REPORTED"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -1198,8 +1208,8 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
// คำสั่งไล่ออก หรือ ปลดออก Status หลังออกคำสั่งใช้ "REPORTED" เพื่อไม่ให้ส่งรายชื่อไปออกคำสั่งซ้ำได้
|
||||
data.ForEach(profile => { profile.Status = "REPORTED"; profile.CommandTypeId = null; });
|
||||
//// คำสั่งไล่ออก หรือ ปลดออก Status หลังออกคำสั่งใช้ "REPORTED" เพื่อไม่ให้ส่งรายชื่อไปออกคำสั่งซ้ำได้
|
||||
// data.ForEach(profile => { profile.Status = "REPORTED"; profile.CommandTypeId = null; });
|
||||
var _profile = new List<ProfileComplaintInvestigate>();
|
||||
DateTime _date = DateTime.Now;
|
||||
foreach (var item in data)
|
||||
|
|
@ -1379,6 +1389,11 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
// .Where(x => x.Status == "REPORT")
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -1424,12 +1439,12 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => profile.Status = "DONE");
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -1518,6 +1533,11 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
// .Where(x => x.Status == "REPORT")
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -1563,12 +1583,12 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => profile.Status = "DONE");
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -1641,6 +1661,11 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
.Include(x => x.DisciplineDisciplinary)
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -1686,12 +1711,12 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -1764,6 +1789,11 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
.Include(x => x.DisciplineDisciplinary)
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -1809,12 +1839,12 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -1887,6 +1917,11 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
.Include(x => x.DisciplineDisciplinary)
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -1932,12 +1967,12 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -2010,6 +2045,11 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
.Include(x => x.DisciplineDisciplinary)
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -2055,12 +2095,12 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -2133,6 +2173,11 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
.Include(x => x.DisciplineDisciplinary)
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -2178,12 +2223,12 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => { profile.Status = "NEW"; profile.CommandTypeId = null; });
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -2272,6 +2317,11 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
// .Where(x => x.IsReport == "REPORT")
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.IsReport = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -2317,12 +2367,12 @@ namespace BMA.EHR.DisciplineResult.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.IsReport = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => profile.IsReport = "DONE");
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
|
||||
var data1 = await _context.DisciplineDisciplinary_ProfileComplaintInvestigates
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ namespace BMA.EHR.Domain.Common
|
|||
protected Guid? ProfileId => User.GetProfileId();
|
||||
protected string? Prefix => User.GetPrefix();
|
||||
protected string? FullNameFromClaim => User.GetName();
|
||||
|
||||
protected string? FirstName => User.GetFirstName();
|
||||
protected string? LastName => User.GetLastName();
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -26,5 +26,7 @@ namespace BMA.EHR.Domain.Extensions
|
|||
public static Guid? GetProfileId(this ClaimsPrincipal user) => user.GetGuidClaim(BmaClaimTypes.ProfileId);
|
||||
public static string? GetPrefix(this ClaimsPrincipal user) => user.GetClaimValue(BmaClaimTypes.Prefix);
|
||||
public static string? GetName(this ClaimsPrincipal user) => user.GetClaimValue(BmaClaimTypes.Name);
|
||||
public static string? GetFirstName(this ClaimsPrincipal user) => user.GetClaimValue(BmaClaimTypes.GivenName);
|
||||
public static string? GetLastName(this ClaimsPrincipal user) => user.GetClaimValue(BmaClaimTypes.FamilyName);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ namespace BMA.EHR.Domain.Models.Leave.Requests
|
|||
[Required, Comment("จำนวนวันลาทั้งหมด")]
|
||||
public double LeaveDays { get; set; } = 0.0;
|
||||
|
||||
[Required, Comment("จำนวนวันลาที่ใช้ไป")]
|
||||
public double LeaveDaysUsed { get; set; } = 0.0;
|
||||
[Comment("จำนวนวันลาที่ใช้ไป")]
|
||||
public double? LeaveDaysUsed { get; set; } = 0.0;
|
||||
|
||||
[Comment("จำนวนครั้งที่ลาสะสม")]
|
||||
public int LeaveCount { get; set; } = 0;
|
||||
public int? LeaveCount { get; set; } = 0;
|
||||
|
||||
public Guid? RootDnaId { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -210,5 +210,7 @@ namespace BMA.EHR.Domain.Models.Leave.Requests
|
|||
|
||||
public Guid? Child4DnaId { get; set; } = Guid.Empty;
|
||||
|
||||
public DateTime? DateSendLeave { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,5 +38,10 @@ namespace BMA.EHR.Domain.Models.Leave.Requests
|
|||
public string Comment { get; set; } = string.Empty;
|
||||
|
||||
public string? ApproveType { get; set; } = string.Empty; // ผู้บังคับบัญชา = commander, ผู้มีอำนาจอนุมัติ = Approver
|
||||
|
||||
|
||||
public bool IsAct { get; set; } = false;
|
||||
|
||||
public string KeyId { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,10 @@ namespace BMA.EHR.Domain.Models.Placement
|
|||
public string? profileId { get; set; }
|
||||
[Comment("คำนำหน้า")]
|
||||
public string? prefix { get; set; }
|
||||
|
||||
[Comment("ยศ")]
|
||||
public string? rank { get; set; }
|
||||
|
||||
[Comment("ชื่อ")]
|
||||
public string? firstName { get; set; }
|
||||
[Comment("นามสกุล")]
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
public static readonly string DataNotFound = "ไม่พบข้อมูลในระบบ";
|
||||
|
||||
public static readonly string ProfileNotFound = "ไม่พบข้อมูลในระบบทะเบียนประวัติ";
|
||||
|
||||
public static readonly string NotAuthorized = "กรุณาเข้าสู่ระบบก่อนใช้งาน!";
|
||||
|
||||
public static readonly string ForbiddenAccess = "คุณไม่ได้รับอนุญาติให้เข้าใช้งาน!";
|
||||
|
|
|
|||
30
BMA.EHR.Domain/Shared/PrivilegeConverter.cs
Normal file
30
BMA.EHR.Domain/Shared/PrivilegeConverter.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
21250
BMA.EHR.Infrastructure/Migrations/20260512073417_update_PlacementReceives_add_rank.Designer.cs
generated
Normal file
21250
BMA.EHR.Infrastructure/Migrations/20260512073417_update_PlacementReceives_add_rank.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,30 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BMA.EHR.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class update_PlacementReceives_add_rank : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "rank",
|
||||
table: "PlacementReceives",
|
||||
type: "longtext",
|
||||
nullable: true,
|
||||
comment: "ยศ")
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "rank",
|
||||
table: "PlacementReceives");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13693,6 +13693,10 @@ namespace BMA.EHR.Infrastructure.Migrations
|
|||
.HasColumnType("longtext")
|
||||
.HasComment("profile Id");
|
||||
|
||||
b.Property<string>("rank")
|
||||
.HasColumnType("longtext")
|
||||
.HasComment("ยศ");
|
||||
|
||||
b.Property<string>("root")
|
||||
.HasColumnType("longtext")
|
||||
.HasComment("ชื่อหน่วยงาน root");
|
||||
|
|
|
|||
1805
BMA.EHR.Infrastructure/Migrations/LeaveDb/20260423083625_Add DateSendLeave.Designer.cs
generated
Normal file
1805
BMA.EHR.Infrastructure/Migrations/LeaveDb/20260423083625_Add DateSendLeave.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
1805
BMA.EHR.Infrastructure/Migrations/LeaveDb/20260505035145_Change Field.Designer.cs
generated
Normal file
1805
BMA.EHR.Infrastructure/Migrations/LeaveDb/20260505035145_Change Field.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,62 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class ChangeField : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "LeaveDaysUsed",
|
||||
table: "LeaveBeginnings",
|
||||
type: "double",
|
||||
nullable: true,
|
||||
comment: "จำนวนวันลาที่ใช้ไป",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double",
|
||||
oldComment: "จำนวนวันลาที่ใช้ไป");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "LeaveCount",
|
||||
table: "LeaveBeginnings",
|
||||
type: "int",
|
||||
nullable: true,
|
||||
comment: "จำนวนครั้งที่ลาสะสม",
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldComment: "จำนวนครั้งที่ลาสะสม");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "LeaveDaysUsed",
|
||||
table: "LeaveBeginnings",
|
||||
type: "double",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "จำนวนวันลาที่ใช้ไป",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double",
|
||||
oldNullable: true,
|
||||
oldComment: "จำนวนวันลาที่ใช้ไป");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "LeaveCount",
|
||||
table: "LeaveBeginnings",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
comment: "จำนวนครั้งที่ลาสะสม",
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldNullable: true,
|
||||
oldComment: "จำนวนครั้งที่ลาสะสม");
|
||||
}
|
||||
}
|
||||
}
|
||||
1812
BMA.EHR.Infrastructure/Migrations/LeaveDb/20260511075931_Add Approver Field.Designer.cs
generated
Normal file
1812
BMA.EHR.Infrastructure/Migrations/LeaveDb/20260511075931_Add Approver Field.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,40 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddApproverField : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsAct",
|
||||
table: "LeaveRequestApprovers",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "KeyId",
|
||||
table: "LeaveRequestApprovers",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsAct",
|
||||
table: "LeaveRequestApprovers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "KeyId",
|
||||
table: "LeaveRequestApprovers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -192,7 +192,7 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
|||
.HasColumnOrder(102)
|
||||
.HasComment("แก้ไขข้อมูลล่าสุดเมื่อ");
|
||||
|
||||
b.Property<int>("LeaveCount")
|
||||
b.Property<int?>("LeaveCount")
|
||||
.HasColumnType("int")
|
||||
.HasComment("จำนวนครั้งที่ลาสะสม");
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
|||
.HasColumnType("double")
|
||||
.HasComment("จำนวนวันลาทั้งหมด");
|
||||
|
||||
b.Property<double>("LeaveDaysUsed")
|
||||
b.Property<double?>("LeaveDaysUsed")
|
||||
.HasColumnType("double")
|
||||
.HasComment("จำนวนวันลาที่ใช้ไป");
|
||||
|
||||
|
|
@ -428,6 +428,9 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
|||
b.Property<DateTime?>("DateAppoint")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<DateTime?>("DateSendLeave")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Dear")
|
||||
.HasColumnType("longtext")
|
||||
.HasComment("เรียนใคร");
|
||||
|
|
@ -710,6 +713,13 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
|||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsAct")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("KeyId")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<Guid>("KeycloakId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
private readonly IConfiguration _configuration;
|
||||
private readonly UserProfileRepository _userProfileRepository;
|
||||
private readonly PermissionRepository _permission;
|
||||
private readonly LeaveRequestRepository _leaveRequestRepository;
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
@ -44,7 +45,8 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
IWebHostEnvironment hostingEnvironment,
|
||||
IConfiguration configuration,
|
||||
UserProfileRepository userProfileRepository,
|
||||
PermissionRepository permission)
|
||||
PermissionRepository permission,
|
||||
LeaveRequestRepository leaveRequestRepository)
|
||||
{
|
||||
_leaveBeginningRepository = leaveBeginningRepository;
|
||||
_context = context;
|
||||
|
|
@ -53,6 +55,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
_configuration = configuration;
|
||||
_userProfileRepository = userProfileRepository;
|
||||
_permission = permission;
|
||||
_leaveRequestRepository = leaveRequestRepository;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
@ -375,6 +378,15 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
try
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
// var profileId = ProfileId ?? Guid.Empty;
|
||||
// var prefix = Prefix ?? "";
|
||||
// var firstName = FirstName ?? "";
|
||||
// var lastName = LastName ?? "";
|
||||
// var rootDnaId = OrgRootDnaId ?? Guid.Empty;
|
||||
// var child1DnaId = OrgChild1DnaId ?? Guid.Empty;
|
||||
// var child2DnaId = OrgChild2DnaId ?? Guid.Empty;
|
||||
// var child3DnaId = OrgChild3DnaId ?? Guid.Empty;
|
||||
// var child4DnaId = OrgChild4DnaId ?? Guid.Empty;
|
||||
|
||||
var getPermission = await _permission.GetPermissionAPIAsync("UPDATE", "SYS_LEAVE_HISTORY");
|
||||
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission);
|
||||
|
|
@ -386,20 +398,41 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
if (leaveBeginning == null)
|
||||
return Error("ไม่พบข้อมูลที่ต้องการแก้ไข", StatusCodes.Status404NotFound);
|
||||
|
||||
|
||||
var profile = await _userProfileRepository.GetProfileByProfileIdAsync(req.ProfileId, AccessToken);
|
||||
if (profile == null)
|
||||
{
|
||||
return Error("ไม่พบข้อมูลข้าราชการหรือลูกจ้าง", StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
var startFiscalDate = new DateTime(DateTime.Now.Year - 1, 10, 1);
|
||||
var endFiscalDate = new DateTime(DateTime.Now.Year, 9, 30);
|
||||
|
||||
|
||||
if (req.LeaveDaysUsed is null || req.LeaveCount is null)
|
||||
{
|
||||
var systemLeaveDays = await _leaveRequestRepository.GetSumApproveLeaveTotalByTypeAndRangeForUserByProfile(req.ProfileId, req.LeaveTypeId, startFiscalDate, endFiscalDate);
|
||||
var systemLeaveCount = await _leaveRequestRepository.GetSumApproveLeaveCountByTypeAndRangeForUserByProfile(req.ProfileId, req.LeaveTypeId, startFiscalDate, endFiscalDate);
|
||||
|
||||
leaveBeginning.LeaveDaysUsed = req.BeginningLeaveDays + systemLeaveDays;
|
||||
leaveBeginning.LeaveCount = req.BeginningLeaveCount + systemLeaveCount;
|
||||
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
leaveBeginning.LeaveDaysUsed = req.LeaveDaysUsed;
|
||||
leaveBeginning.LeaveCount = req.LeaveCount;
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
//var systemLeaveDays = await _leaveRequestRepository.GetSumApproveLeaveTotalByTypeAndRangeForUser2(profile.Keycloak ?? Guid.Empty, req.LeaveTypeId, startFiscalDate, endFiscalDate);
|
||||
//var systemLeaveCount = await _leaveRequestRepository.GetSumApproveLeaveCountByTypeAndRangeForUser2(profile.Keycloak ?? Guid.Empty, req.LeaveTypeId, startFiscalDate, endFiscalDate);
|
||||
}
|
||||
|
||||
leaveBeginning.LeaveTypeId = req.LeaveTypeId;
|
||||
leaveBeginning.LeaveYear = req.LeaveYear;
|
||||
leaveBeginning.LeaveDays = req.LeaveDays;
|
||||
leaveBeginning.LeaveDaysUsed = req.LeaveDaysUsed;
|
||||
leaveBeginning.LeaveCount = req.LeaveCount;
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
|
||||
|
||||
leaveBeginning.ProfileId = req.ProfileId;
|
||||
leaveBeginning.Prefix = profile.Prefix;
|
||||
|
|
@ -440,6 +473,17 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
try
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
|
||||
// var profileId = ProfileId ?? Guid.Empty;
|
||||
// var prefix = Prefix ?? "";
|
||||
// var firstName = FirstName ?? "";
|
||||
// var lastName = LastName ?? "";
|
||||
// var rootDnaId = OrgRootDnaId ?? Guid.Empty;
|
||||
// var child1DnaId = OrgChild1DnaId ?? Guid.Empty;
|
||||
// var child2DnaId = OrgChild2DnaId ?? Guid.Empty;
|
||||
// var child3DnaId = OrgChild3DnaId ?? Guid.Empty;
|
||||
// var child4DnaId = OrgChild4DnaId ?? Guid.Empty;
|
||||
|
||||
var getPermission = await _permission.GetPermissionAPIAsync("CREATE", "SYS_LEAVE_HISTORY");
|
||||
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission);
|
||||
if (jsonData["status"]?.ToString() != "200")
|
||||
|
|
@ -464,13 +508,26 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
}
|
||||
|
||||
var leaveBeginning = new LeaveBeginning();
|
||||
|
||||
if (req.LeaveDaysUsed is null || req.LeaveCount is null)
|
||||
{
|
||||
leaveBeginning.LeaveDaysUsed = req.BeginningLeaveDays;
|
||||
leaveBeginning.LeaveCount = req.BeginningLeaveCount;
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
leaveBeginning.LeaveDaysUsed = req.LeaveDaysUsed;
|
||||
leaveBeginning.LeaveCount = req.LeaveCount;
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
}
|
||||
|
||||
leaveBeginning.LeaveTypeId = req.LeaveTypeId;
|
||||
leaveBeginning.LeaveYear = req.LeaveYear;
|
||||
leaveBeginning.LeaveDays = req.LeaveDays;
|
||||
leaveBeginning.LeaveDaysUsed = req.LeaveDaysUsed;
|
||||
leaveBeginning.LeaveCount = req.LeaveCount;
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
|
||||
|
||||
leaveBeginning.ProfileId = req.ProfileId;
|
||||
leaveBeginning.Prefix = profile.Prefix;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ using BMA.EHR.Application.Repositories.Commands;
|
|||
using BMA.EHR.Application.Repositories.Leaves.LeaveRequests;
|
||||
using BMA.EHR.Application.Repositories.Leaves.TimeAttendants;
|
||||
using BMA.EHR.Application.Repositories.MessageQueue;
|
||||
using BMA.EHR.Application.Responses.Leaves;
|
||||
using BMA.EHR.Application.Responses.Profiles;
|
||||
using BMA.EHR.Domain.Common;
|
||||
using BMA.EHR.Domain.Extensions;
|
||||
using BMA.EHR.Domain.Models.Leave.TimeAttendants;
|
||||
using BMA.EHR.Domain.Models.Notifications;
|
||||
using BMA.EHR.Domain.Shared;
|
||||
|
|
@ -444,29 +446,30 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
public async Task<ActionResult<ResponseObject>> CheckTimeAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
var profileId = ProfileId ?? Guid.Empty;
|
||||
|
||||
// Get user's last check-in record and profile in parallel
|
||||
var dataTask = _userTimeStampRepository.GetLastRecord(userId);
|
||||
var profileTask = _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken);
|
||||
//var profileTask = _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
var defaultRoundTask = _dutyTimeRepository.GetDefaultAsync();
|
||||
|
||||
await Task.WhenAll(dataTask, profileTask, defaultRoundTask);
|
||||
await Task.WhenAll(dataTask, defaultRoundTask);
|
||||
|
||||
var data = await dataTask;
|
||||
var profile = await profileTask;
|
||||
//var profile = await profileTask;
|
||||
var getDefaultRound = await defaultRoundTask;
|
||||
|
||||
if (profile == null)
|
||||
{
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
}
|
||||
// if (profile == null)
|
||||
// {
|
||||
// throw new Exception(GlobalMessages.DataNotFound);
|
||||
// }
|
||||
|
||||
if (getDefaultRound == null)
|
||||
{
|
||||
return Error("ไม่พบรอบลงเวลา Default", StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
var effectiveDate = await _userDutyTimeRepository.GetLastEffectRound(profile.Id);
|
||||
var effectiveDate = await _userDutyTimeRepository.GetLastEffectRound(profileId);
|
||||
var roundId = effectiveDate != null ? effectiveDate.DutyTimeId : Guid.Empty;
|
||||
var userRound = await _dutyTimeRepository.GetByIdAsync(roundId);
|
||||
|
||||
|
|
@ -936,7 +939,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
await _checkInJobStatusRepository.UpdateToProcessingAsync(taskId);
|
||||
}
|
||||
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, data.Token);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, data.Token);
|
||||
|
||||
if (profile == null)
|
||||
{
|
||||
|
|
@ -1084,6 +1087,12 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
startTime1 = "13:00";
|
||||
endTime1 = "14:30";
|
||||
endTimeMorning1 = "12:00";
|
||||
}
|
||||
else if (!data.IsLocation && data.LocationName == "ปฏิบัติงานในจุดบริการด่วนมหานคร")
|
||||
{
|
||||
startTime1 = "13:00";
|
||||
endTime1 = "18:30";
|
||||
endTimeMorning1 = "12:00";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1250,6 +1259,12 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
var startTime = "";
|
||||
var endTime = "";
|
||||
if (!data.IsLocation && data.LocationName == "ไปประชุม / อบรม / สัมมนา")
|
||||
{
|
||||
//startTime = "09:30";
|
||||
startTime = "10:30";
|
||||
endTime = "12:00";
|
||||
}
|
||||
else if (!data.IsLocation && data.LocationName == "ปฏิบัติงานในจุดบริการด่วนมหานคร")
|
||||
{
|
||||
//startTime = "09:30";
|
||||
startTime = "10:30";
|
||||
|
|
@ -1401,6 +1416,12 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
startTime = "13:00";
|
||||
endTime = "14:30";
|
||||
endTimeMorning = "12:00";
|
||||
}
|
||||
else if (!data.IsLocation && data.LocationName == "ปฏิบัติงานในจุดบริการด่วนมหานคร")
|
||||
{
|
||||
startTime = "13:00";
|
||||
endTime = "18:30";
|
||||
endTimeMorning = "12:00";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1589,7 +1610,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
public async Task<ActionResult<ResponseObject>> CheckInOldAsync([FromForm] CheckTimeDto data)
|
||||
{
|
||||
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)
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
|
|
@ -1754,7 +1775,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
{
|
||||
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)
|
||||
{
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
|
|
@ -1884,7 +1905,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
? profileAdmin?.RootDnaId
|
||||
: "";
|
||||
}
|
||||
else if (role == "BROHTER")
|
||||
else if (role == "BROTHER")
|
||||
{
|
||||
nodeId = profileAdmin?.Node == 4
|
||||
? profileAdmin?.Child3DnaId
|
||||
|
|
@ -1914,7 +1935,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
ProfileType = d.ProfileType ?? "",
|
||||
|
||||
CheckInDate = d.CheckIn.Date,
|
||||
CheckInTime = d.CheckIn.ToString("HH:mm:ss"),
|
||||
CheckInTime = d.CheckIn.ToString("HH:mm"),
|
||||
CheckInLocation = d.CheckInPOI,
|
||||
CheckInLat = d.CheckInLat,
|
||||
CheckInLon = d.CheckInLon,
|
||||
|
|
@ -1925,7 +1946,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
CheckInLocationName = d.CheckInLocationName ?? "",
|
||||
|
||||
CheckOutDate = d.CheckOut?.Date,
|
||||
CheckOutTime = d.CheckOut == null ? "" : d.CheckOut.Value.ToString("HH:mm:ss"),
|
||||
CheckOutTime = d.CheckOut == null ? "" : d.CheckOut.Value.ToString("HH:mm"),
|
||||
CheckOutLocation = d.CheckOut == null ? "" : d.CheckOutPOI,
|
||||
CheckOutLat = d.CheckOut == null ? null : d.CheckOutLat,
|
||||
CheckOutLon = d.CheckOut == null ? null : d.CheckOutLon,
|
||||
|
|
@ -2043,7 +2064,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
}
|
||||
else
|
||||
{
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(d.KeycloakUserId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(d.KeycloakUserId, AccessToken);
|
||||
if (profile == null)
|
||||
{
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
|
|
@ -2990,10 +3011,12 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<ActionResult<ResponseObject>> CheckoutCheckAsync(string isSeminar = "N")
|
||||
{
|
||||
// "S" = Seminar, "N" = Normal, "O" = One Stop Service
|
||||
|
||||
var time = DateTime.Now;
|
||||
|
||||
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)
|
||||
{
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
|
|
@ -3021,9 +3044,11 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
|
||||
//var endTime = DateTimeOffset.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")}T{duty.EndTimeAfternoon}:00.0000000+07:00").ToLocalTime().DateTime;
|
||||
|
||||
//var endTime = DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")}T{duty.EndTimeAfternoon}:00.0000000+07:00");
|
||||
var endTime = isSeminar.Trim().ToUpper() == "Y"
|
||||
//var endTime = DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")}T{duty.EndTimeAfternoon}:00.0000000+07:00");
|
||||
var endTime = isSeminar.Trim().ToUpper() == "S"
|
||||
? DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")} 14:30")
|
||||
: isSeminar.Trim().ToUpper() == "O"
|
||||
? DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")} 18:30")
|
||||
: DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")} {duty.EndTimeAfternoon}");
|
||||
|
||||
var endTimeMorning = DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")} {duty.EndTimeMorning}");
|
||||
|
|
@ -3111,9 +3136,18 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
{
|
||||
return Error("ไม่สามารถขอลงเวลากรณีพิเศษในวันที่มากกว่าวันที่ปัจจุบันได้", StatusCodes.Status400BadRequest);
|
||||
}
|
||||
|
||||
|
||||
|
||||
var userId = UserId != null ? Guid.Parse(UserId) : Guid.Empty;
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken);
|
||||
|
||||
var checkin = await _userTimeStampRepository.GetTimestampByDateAsync(userId, req.CheckDate.Date);
|
||||
if (checkin != null && checkin.CheckOut == null)
|
||||
{
|
||||
return Error("ระบบพบรายการลงเวลาของวันที่ต้องการแก้ไข แต่ยังไม่มีข้อมูลการลงเวลาออก กรุณาลงเวลาออกให้เรียบร้อยก่อนดำเนินการ");
|
||||
}
|
||||
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
if (profile == null)
|
||||
{
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
|
|
@ -3160,15 +3194,16 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[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] DateTime startDate, [Required] DateTime endDate, [Required] int page = 1, [Required] int pageSize = 10, string keyword = "", string? sortBy = "", bool? descending = false,string? status = "")
|
||||
{
|
||||
var getPermission = await _permission.GetPermissionAPIAsync("LIST", "SYS_CHECKIN_SPECIAL");
|
||||
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission);
|
||||
if (jsonData["status"]?.ToString() != "200")
|
||||
var jsonData = await _permission.GetPermissionWithActingAPIAsync("LIST", "SYS_CHECKIN_SPECIAL");
|
||||
//var jsonData = JsonConvert.DeserializeObject<GetPermissionWithActingResultDto>(getPermission);
|
||||
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 profileAdmin = new GetUserOCAllDto();
|
||||
profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken);
|
||||
|
|
@ -3204,8 +3239,84 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
}
|
||||
|
||||
//var rawData = await _additionalCheckRequestRepository.GetAdditionalCheckRequests(year, month);
|
||||
var rawData = await _additionalCheckRequestRepository.GetAdditionalCheckRequestsByAdminRole(year, month, role, nodeId, profileAdmin?.Node, keyword);
|
||||
var rawData = await _additionalCheckRequestRepository.GetAdditionalCheckRequestsByAdminRole2(startDate, endDate, role, nodeId, profileAdmin?.Node, keyword,status);
|
||||
|
||||
// ถ้ามีการรักษาการ
|
||||
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.GetAdditionalCheckRequestsByAdminRole2(startDate, endDate, actRole, actNodeId, profileAdmin?.Node, keyword,status);
|
||||
if (rawDataAct != null)
|
||||
{
|
||||
if (rawData != null)
|
||||
rawData = rawData.Union(rawDataAct).DistinctBy(x => x.Id).ToList();
|
||||
else
|
||||
rawData = rawDataAct;
|
||||
}
|
||||
}
|
||||
}
|
||||
var total = rawData.Count;
|
||||
|
||||
var getDefaultRound = await _dutyTimeRepository.GetDefaultAsync();
|
||||
|
|
@ -3276,7 +3387,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
|
||||
foreach (var data in rawDataPaged)
|
||||
{
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(data.KeycloakUserId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(data.KeycloakUserId, AccessToken);
|
||||
UserDutyTime? effectiveDate = null;
|
||||
if (profile != null)
|
||||
{
|
||||
|
|
@ -3455,7 +3566,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
// change user timestamp
|
||||
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)
|
||||
{
|
||||
|
|
@ -3609,7 +3720,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
requestData.Comment = req.Reason;
|
||||
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 };
|
||||
await _notificationRepository.PushNotificationsAsync(recvId.ToArray(), "ลงเวลากรณีพิเศษ", "การขอลงเวลากรณีพิเศษของคุณไม่ได้รับการอนุมัติ", "", "", true, false);
|
||||
|
|
@ -3653,7 +3764,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
}
|
||||
else
|
||||
{
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(d.KeycloakUserId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(d.KeycloakUserId, AccessToken);
|
||||
if (profile == null)
|
||||
{
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
|
|
@ -3712,6 +3823,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
"ABSENT" :
|
||||
"NORMAL",
|
||||
CheckOutDescription = d.CheckOutRemark ?? "",
|
||||
IsLocationCheckIn = d.IsLocationCheckIn,
|
||||
IsLocationCheckOut = d.IsLocationCheckOut,
|
||||
CheckInLocationName = d.CheckInLocationName ?? "",
|
||||
CheckOutLocationName = d.CheckOutLocationName ?? ""
|
||||
};
|
||||
|
||||
return Success(result);
|
||||
|
|
@ -3747,7 +3862,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
|
||||
foreach (var data in rawData)
|
||||
{
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(data.KeycloakUserId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(data.KeycloakUserId, AccessToken);
|
||||
if (profile == null)
|
||||
{
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
|
|
@ -3776,6 +3891,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
{
|
||||
resultCheckInDate = checkInData == null ? null : checkInData.CheckIn;
|
||||
resultCheckInTime = checkInData == null ? "00:00" : checkInData.CheckIn.ToString("HH:mm");
|
||||
resultCheckInLocation = checkInData == null ? "" : checkInData!.CheckInPOI;
|
||||
}
|
||||
|
||||
if (data.CheckOutEdit)
|
||||
|
|
@ -3793,6 +3909,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
resultCheckOutTime = checkInData == null ? "00:00" :
|
||||
checkInData.CheckOut == null ? "00:00" :
|
||||
checkInData.CheckOut.Value.ToString("HH:mm");
|
||||
resultCheckOutLocation = checkInData == null ? "" : checkInData!.CheckOutPOI;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -4037,7 +4154,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
|
||||
//var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
// แก้เป็นมาใช้งาน KeycloakUserId แทน
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(data.KeycloakUserId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(data.KeycloakUserId, AccessToken);
|
||||
var defaultRound = await _dutyTimeRepository.GetDefaultAsync();
|
||||
if (defaultRound == null)
|
||||
{
|
||||
|
|
@ -4051,6 +4168,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
if (req.CheckInStatus == "NORMAL")
|
||||
{
|
||||
if(data.CheckInLocationName == "ไปประชุม / อบรม / สัมมนา")
|
||||
{
|
||||
data.CheckIn = DateTime.Parse($"{data.CheckIn.Date.ToString("yyyy-MM-dd")} 10:30");
|
||||
}
|
||||
else if (data.CheckInLocationName == "ปฏิบัติงานในจุดบริการด่วนมหานคร")
|
||||
{
|
||||
data.CheckIn = DateTime.Parse($"{data.CheckIn.Date.ToString("yyyy-MM-dd")} 10:30");
|
||||
}
|
||||
|
|
@ -4068,6 +4189,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
if(data.CheckOutLocationName == "ไปประชุม / อบรม / สัมมนา")
|
||||
{
|
||||
roundCheckOutTime = DateTime.Parse($"{checkOutTime.Date.ToString("yyyy-MM-dd")} 14:30");
|
||||
}
|
||||
else if (data.CheckInLocationName == "ปฏิบัติงานในจุดบริการด่วนมหานคร")
|
||||
{
|
||||
roundCheckOutTime = DateTime.Parse($"{checkOutTime.Date.ToString("yyyy-MM-dd")} 18:30");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -4107,7 +4232,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
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 startDate = req.StartDate;
|
||||
|
|
@ -4177,7 +4302,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
{
|
||||
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)
|
||||
{
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
|
|
|
|||
|
|
@ -156,8 +156,8 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
await _leaveRequestRepository.GetLastLeaveRequestByTypeForUserAsync2(data.KeycloakUserId,
|
||||
data.Type.Id, data.CreatedAt);
|
||||
|
||||
var startFiscalYear = new DateTime(data.LeaveStartDate.Year - 1, 10, 1);
|
||||
var endFiscalYear = data.CreatedAt;
|
||||
var startFiscalYear = (new DateTime(data.LeaveStartDate.Year - 1, 10, 1)).Date;
|
||||
var endFiscalYear = (data.DateSendLeave ?? data.CreatedAt);
|
||||
|
||||
var thisYear = data.LeaveStartDate.Year;
|
||||
var toDay = data.LeaveStartDate.Date;
|
||||
|
|
@ -182,7 +182,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
|
||||
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
|
||||
|
|
@ -272,7 +272,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
|
||||
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
|
||||
|
|
@ -366,7 +366,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
|
||||
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
|
||||
|
|
@ -461,7 +461,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
|
||||
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
|
||||
|
|
@ -515,7 +515,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
|
||||
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
|
||||
|
|
@ -602,7 +602,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
|
||||
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
|
||||
|
|
@ -683,7 +683,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
|
||||
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
|
||||
|
|
@ -786,7 +786,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
|
||||
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
|
||||
|
|
@ -905,7 +905,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
|
||||
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
|
||||
|
|
@ -1001,7 +1001,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
leaveSubTypeName = data.LeaveSubTypeName != null ? data.LeaveSubTypeName.ToThaiNumber() : "",
|
||||
dear = data.CommanderPosition == null ? data.Dear : data.CommanderPosition.ToThaiNumber(),
|
||||
|
|
@ -1227,7 +1227,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data = new
|
||||
{
|
||||
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,
|
||||
fullname = fullName,
|
||||
position = string.IsNullOrEmpty(profile.Position) ? "-" : profile.Position,
|
||||
|
|
@ -1533,17 +1533,21 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
coupleCount = coupleCount,
|
||||
therapyCount = therapyCount,
|
||||
|
||||
leaveTotal = sickCount +
|
||||
maternityCount +
|
||||
wifeCount +
|
||||
personalCount +
|
||||
restCount +
|
||||
ordainCount +
|
||||
absentCount +
|
||||
studyCount +
|
||||
agencyCount +
|
||||
coupleCount +
|
||||
therapyCount
|
||||
// ระบบนับจำนวนครั้ง วันลาพักผ่อนด้วย ซึ่งตามระเบียบไม่ให้นับจำนวนครั้งวันลาพักผ่อนครับ จำนวนครั้งนับเฉพาะ ป่วย กับ กิจ
|
||||
leaveTotal = sickCount +
|
||||
personalCount
|
||||
|
||||
// leaveTotal = sickCount +
|
||||
// maternityCount +
|
||||
// wifeCount +
|
||||
// personalCount +
|
||||
// restCount +
|
||||
// ordainCount +
|
||||
// absentCount +
|
||||
// studyCount +
|
||||
// agencyCount +
|
||||
// coupleCount +
|
||||
// therapyCount
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -175,6 +175,9 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
LastUpdateFullName = FullName ?? "",
|
||||
LastUpdateUserId = UserId!,
|
||||
LastUpdatedAt = DateTime.Now,
|
||||
|
||||
IsAct = r.isAct,
|
||||
KeyId = r.keyId
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +217,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
var thisYear = DateTime.Now.Year;
|
||||
|
||||
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
|
||||
if (profile == null)
|
||||
{
|
||||
|
|
@ -502,7 +505,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
foreach (var leave in leaves)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
leave.Prefix = profile.Prefix;
|
||||
|
|
@ -563,7 +566,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
// }
|
||||
|
||||
// var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
|
||||
if (profile == null)
|
||||
{
|
||||
|
|
@ -855,10 +858,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
{
|
||||
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 startFiscalDate = new DateTime(DateTime.Now.Year, 10, 1);
|
||||
var endFiscalDate = new DateTime(DateTime.Now.Year + 1, 9, 30);
|
||||
var startFiscalDate = new DateTime(DateTime.Now.Year - 1, 10, 1);
|
||||
var endFiscalDate = new DateTime(DateTime.Now.Year, 9, 30);
|
||||
|
||||
if (toDay >= startFiscalDate && toDay <= endFiscalDate)
|
||||
thisYear = thisYear + 1;
|
||||
|
|
@ -925,6 +928,9 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
|
||||
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
|
||||
{
|
||||
DateSendLeave = DateTime.Now.Date,
|
||||
|
|
@ -940,8 +946,8 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
OrganizationName = orgName, //profile.Oc ?? "",
|
||||
|
||||
LeaveLimit = leaveLimit, // จำนวนวันลาทั้งหมดในปีนั้นๆที่ลาได้ โดยรวมยอดที่เหลือจากปีก่อนมา (เอาค่ามาจากตาราง Beginning เลย)
|
||||
LeaveTotal = sumLeave, // จำนวนวันลาที่ลาไปแล้วในปีนั้นๆ โดยเมื่อมีการอนุมัติลา จะมาบวกค่านี้ไปเรื่อยๆ (เอาค่ามาจากตาราง Beginning เลย)
|
||||
LeaveRemain = leaveLimit - sumLeave,
|
||||
LeaveTotal = sumLeave ?? 0, // จำนวนวันลาที่ลาไปแล้วในปีนั้นๆ โดยเมื่อมีการอนุมัติลา จะมาบวกค่านี้ไปเรื่อยๆ (เอาค่ามาจากตาราง Beginning เลย)
|
||||
LeaveRemain = leaveLimit - (sumLeave ?? 0),
|
||||
RestDayTotalOld = restOldDay, // เอา leaveLimit มาลบ 10 (LV-005)
|
||||
RestDayTotalCurrent = restCurrentDay,// 10 วันเสมอ (LV-005)
|
||||
BirthDate = profile.BirthDate.Date,
|
||||
|
|
@ -960,7 +966,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
CurrentDistrict = profile.CurrentDistrict ?? "",
|
||||
CurrentProvince = profile.CurrentProvince ?? "",
|
||||
CurrentZipCode = profile.CurrentZipCode ?? "",
|
||||
GovAge = govAge
|
||||
GovAge = govAge,
|
||||
|
||||
LeaveDraftSummary = leaveDraftSummary,
|
||||
LeaveWaitingSummary = leaveWaitingSummary
|
||||
};
|
||||
|
||||
return Success(result);
|
||||
|
|
@ -1026,7 +1035,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
|
||||
// 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 startDate = profile?.DateStart?.Date ?? DateTime.Now.Date;
|
||||
// var date1Raw = profile?.DateStart?.Date ?? DateTime.Now.Date;
|
||||
|
|
@ -1324,7 +1333,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
Id = d.Id,
|
||||
LeaveTypeId = d.Type.Id,
|
||||
LeaveTypeName = d.Type.Name,
|
||||
DateSendLeave = d.CreatedAt.Date,
|
||||
DateSendLeave = d.DateSendLeave != null ? d.DateSendLeave.Value.Date : d.CreatedAt.Date,
|
||||
Status = d.LeaveStatus,
|
||||
FullName = $"{d.Prefix}{d.FirstName} {d.LastName}",
|
||||
LeaveEndDate = d.LeaveEndDate,
|
||||
|
|
@ -1352,14 +1361,14 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
public async Task<ActionResult<ResponseObject>> GetLeaveRequestCalendarAdminAsync(
|
||||
[FromBody] GetLeaveRequestCalendarDto req)
|
||||
{
|
||||
var getPermission = await _permission.GetPermissionAPIAsync("LIST", "SYS_LEAVE_LIST");
|
||||
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission);
|
||||
if (jsonData["status"]?.ToString() != "200")
|
||||
var jsonData = await _permission.GetPermissionWithActingAPIAsync("LIST", "SYS_LEAVE_LIST");
|
||||
//var jsonData = JsonConvert.DeserializeObject<GetPermissionWithActingResultDto>(getPermission);
|
||||
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 profileAdmin = new GetUserOCAllDto();
|
||||
profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken);
|
||||
|
|
@ -1395,6 +1404,87 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
}
|
||||
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
|
||||
//join p in profileList on d.KeycloakUserId equals p.Keycloak
|
||||
select new GetLeaveRequestCalendarResultDto
|
||||
|
|
@ -1402,7 +1492,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
Id = d.Id,
|
||||
LeaveTypeId = d.Type.Id,
|
||||
LeaveTypeName = d.Type.Name,
|
||||
DateSendLeave = d.CreatedAt.Date,
|
||||
DateSendLeave = d.DateSendLeave != null ? d.DateSendLeave.Value.Date : d.CreatedAt.Date,
|
||||
Status = d.LeaveStatus,
|
||||
FullName = $"{d.Prefix}{d.FirstName} {d.LastName}",
|
||||
LeaveEndDate = d.LeaveEndDate,
|
||||
|
|
@ -1455,7 +1545,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
LeaveTypeName = item.Type.Name,
|
||||
LeaveSubTypeName = item.LeaveSubTypeName ?? "",
|
||||
FullName = $"{item.Prefix}{item.FirstName} {item.LastName}",
|
||||
DateSendLeave = item.CreatedAt,
|
||||
DateSendLeave = item.DateSendLeave ?? item.CreatedAt,
|
||||
IsDelete = item.LeaveStatus == "DELETE",
|
||||
Status = item.LeaveStatus,
|
||||
LeaveStartDate = item.LeaveStartDate,
|
||||
|
|
@ -1577,7 +1667,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
|
@ -1630,7 +1720,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
LeaveSubTypeName = rawData.LeaveSubTypeName,
|
||||
LeaveTypeId = rawData.Type.Id,
|
||||
FullName = $"{rawData.Prefix}{rawData.FirstName} {rawData.LastName}",
|
||||
DateSendLeave = rawData.CreatedAt,
|
||||
DateSendLeave = rawData.DateSendLeave ?? rawData.CreatedAt,
|
||||
Status = rawData.LeaveStatus,
|
||||
LeaveStartDate = rawData.LeaveStartDate,
|
||||
LeaveEndDate = rawData.LeaveEndDate,
|
||||
|
|
@ -1750,14 +1840,14 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
public async Task<ActionResult<ResponseObject>> GetLeaveRequestForAdminAsync(
|
||||
[FromBody] GetLeaveRequestForAdminDto req)
|
||||
{
|
||||
var getPermission = await _permission.GetPermissionAPIAsync("LIST", "SYS_LEAVE_LIST");
|
||||
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission);
|
||||
if (jsonData["status"]?.ToString() != "200")
|
||||
var jsonData = await _permission.GetPermissionWithActingAPIAsync("LIST", "SYS_LEAVE_LIST");
|
||||
//var jsonData = JsonConvert.DeserializeObject<GetPermissionWithActingResultDto>(getPermission);
|
||||
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 profileAdmin = new GetUserOCAllDto();
|
||||
profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken);
|
||||
|
|
@ -1794,6 +1884,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);
|
||||
|
||||
|
||||
// ถ้ามีการรักษาการ
|
||||
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>();
|
||||
|
||||
foreach (var item in rawData)
|
||||
|
|
@ -1826,7 +1995,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
LeaveSubTypeName = item.LeaveSubTypeName,
|
||||
FullName = $"{item.Prefix}{item.FirstName} {item.LastName}",
|
||||
ProfileType = item.ProfileType ?? "-",
|
||||
DateSendLeave = item.CreatedAt,
|
||||
DateSendLeave = item.DateSendLeave ?? item.CreatedAt,
|
||||
Status = item.LeaveStatus,
|
||||
CitizenId = item.CitizenId ?? "",
|
||||
LeaveStartDate = item.LeaveStartDate,
|
||||
|
|
@ -1876,6 +2045,12 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
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
|
||||
// แก้จาก DELETE เป็น DELETING ไว้ก่อน รอ approve ค่อยเปลี่ยนเป็น DELETE
|
||||
// data.LeaveStatus = "DELETE";
|
||||
|
|
@ -1912,7 +2087,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
|
||||
// TODO: Send notification to all users who need to approve the cancel leave request
|
||||
var approvers = data.Approvers
|
||||
.Where(x => x.ApproveStatus!.ToUpper() == "PENDING")
|
||||
//.Where(x => x.ApproveStatus!.ToUpper() == "PENDING")
|
||||
.OrderBy(x => x.Seq)
|
||||
.ToList();
|
||||
|
||||
|
|
@ -1924,11 +2099,33 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
Body = $"คำร้องขอยกเลิกการลาของคุณ {data.FirstName} {data.LastName} รอรับการอนุมัติจากคุณ",
|
||||
ReceiverUserId = approver!.ProfileId,
|
||||
Type = "",
|
||||
Payload = $"{URL}/leave/detail/{id}",
|
||||
Payload = $"{URL}/leave-reject/detail/{id}",
|
||||
};
|
||||
_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();
|
||||
}
|
||||
|
|
@ -1948,14 +2145,14 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
public async Task<ActionResult<ResponseObject>> GetCancelLeaveRequestForAdminAsync(
|
||||
[FromBody] GetLeaveRequestForAdminDto req)
|
||||
{
|
||||
var getPermission = await _permission.GetPermissionAPIAsync("LIST", "SYS_LEAVE_LIST");
|
||||
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission);
|
||||
if (jsonData["status"]?.ToString() != "200")
|
||||
var jsonData = await _permission.GetPermissionWithActingAPIAsync("LIST", "SYS_LEAVE_LIST");
|
||||
//var jsonData = JsonConvert.DeserializeObject<GetPermissionWithActingResultDto>(getPermission);
|
||||
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 profileAdmin = new GetUserOCAllDto();
|
||||
profileAdmin = await _userProfileRepository.GetUserOCAll(Guid.Parse(UserId!), AccessToken);
|
||||
|
|
@ -1993,6 +2190,84 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
var rawData =
|
||||
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;
|
||||
|
||||
if (req.Keyword != "")
|
||||
|
|
@ -2015,7 +2290,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
LeaveSubTypeName = item.LeaveSubTypeName,
|
||||
ProfileType = item.ProfileType ?? "-",
|
||||
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 ?? ""
|
||||
};
|
||||
result.Add(res);
|
||||
|
|
@ -2112,7 +2387,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
|
@ -2563,8 +2838,15 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
var leaveData = await _leaveBeginningRepository.GetByYearAndTypeIdForUser2Async(thisYear, rawData.Type.Id, rawData.KeycloakUserId);
|
||||
|
||||
var startFiscalYear = new DateTime(rawData.LeaveStartDate.Year - 1, 10, 1);
|
||||
var endFiscalYear = rawData.CreatedAt;
|
||||
var endFiscalYear = rawData.DateSendLeave ?? rawData.CreatedAt;
|
||||
var endFiscalYear2 = new DateTime(rawData.LeaveStartDate.Year, 9, 30);
|
||||
//var endFiscalYear3 = rawData.DateSendLeave ?? rawData.CreatedAt;
|
||||
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;
|
||||
if (leaveData != null)
|
||||
leaveSummary += leaveData.BeginningLeaveDays;
|
||||
|
|
@ -2588,7 +2870,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
LeaveSubTypeName = rawData.LeaveSubTypeName,
|
||||
LeaveTypeId = rawData.Type.Id,
|
||||
FullName = $"{rawData.Prefix}{rawData.FirstName} {rawData.LastName}",
|
||||
DateSendLeave = rawData.CreatedAt,
|
||||
DateSendLeave = rawData.DateSendLeave ?? rawData.CreatedAt,
|
||||
Status = rawData.LeaveStatus,
|
||||
LeaveStartDate = rawData.LeaveStartDate,
|
||||
LeaveEndDate = rawData.LeaveEndDate,
|
||||
|
|
@ -2678,7 +2960,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
|
||||
LeaveLimit = rawData.Type.Limit + extendLeave,
|
||||
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)
|
||||
|
|
@ -2706,7 +2991,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
ApproveStatus = x.ApproveStatus,
|
||||
Comment = x.Comment,
|
||||
ProfileId = x.ProfileId,
|
||||
KeycloakId = x.KeycloakId
|
||||
KeycloakId = x.KeycloakId,
|
||||
isAct = x.IsAct,
|
||||
keyId = x.KeyId
|
||||
|
||||
}).ToList();
|
||||
|
||||
var approvers = rawData.Approvers.Where(x => x.ApproveType.ToUpper() == "APPROVER")
|
||||
|
|
@ -2721,7 +3009,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
ApproveStatus = x.ApproveStatus,
|
||||
Comment = x.Comment,
|
||||
ProfileId = x.ProfileId,
|
||||
KeycloakId = x.KeycloakId
|
||||
KeycloakId = x.KeycloakId,
|
||||
|
||||
isAct = x.IsAct,
|
||||
keyId = x.KeyId
|
||||
}).ToList();
|
||||
|
||||
result.Approvers.AddRange(approvers);
|
||||
|
|
@ -2757,7 +3048,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
var rejectList = await _leaveRequestRepository.GetSumRejectLeaveAsync(thisYear);
|
||||
var deleteList = await _leaveRequestRepository.GetSumDeleteLeaveAsync(thisYear);
|
||||
// var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNewAsync(userId, AccessToken);
|
||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
|
||||
if (pf == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,16 +17,16 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveBeginnings
|
|||
[Required, Comment("จำนวนวันลายกมา")]
|
||||
public double LeaveDays { get; set; } = 0.0;
|
||||
|
||||
[Required, Comment("จำนวนวันลาที่ใช้ไป")]
|
||||
public double LeaveDaysUsed { get; set; } = 0.0;
|
||||
[Comment("จำนวนวันลาที่ใช้ไป")]
|
||||
public double? LeaveDaysUsed { get; set; }
|
||||
|
||||
[Required, Comment("จำนวนครั้งที่ลาสะสม")]
|
||||
public int LeaveCount { get; set; } = 0;
|
||||
[Comment("จำนวนครั้งที่ลาสะสม")]
|
||||
public int? LeaveCount { get; set; }
|
||||
|
||||
[Required, Comment("จำนวนวันลายกมา")]
|
||||
[Required, Comment("จำนวนวันลายกมาก่อนใช้ระบบ")]
|
||||
public double BeginningLeaveDays { get; set; } = 0.0;
|
||||
|
||||
[Comment("จำนวนครั้งที่ลายกมา")]
|
||||
[Comment("จำนวนครั้งที่ลายกมาก่อนใช้ระบบ")]
|
||||
public int BeginningLeaveCount { get; set; } = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,6 +147,10 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
|
|||
public List<GetLeaveApproverDto> Approvers { get; set; } = new();
|
||||
|
||||
public Guid? KeycloakUserId { get; set; } = Guid.Empty;
|
||||
|
||||
|
||||
public double LeaveDraftSummary { get; set; } = 0;
|
||||
public double LeaveWaitingSummary { get; set; } = 0;
|
||||
}
|
||||
|
||||
public class GetLeaveApproverDto
|
||||
|
|
@ -170,5 +174,8 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
|
|||
public string ApproveStatus { get; set; } = string.Empty;
|
||||
|
||||
public string Comment { get; set; } = string.Empty;
|
||||
|
||||
public bool isAct { get; set; } = false;
|
||||
public string keyId { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,5 +53,8 @@
|
|||
public string? CurrentZipCode { get; set; }
|
||||
|
||||
public int GovAge { get; set; } = 0;
|
||||
|
||||
public double LeaveDraftSummary { get; set; } = 0;
|
||||
public double LeaveWaitingSummary { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,5 +37,11 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
|
|||
[JsonProperty("organizationName")]
|
||||
public string OrganizationName { get; set; } = string.Empty;
|
||||
|
||||
[JsonProperty("isAct")]
|
||||
public bool isAct { get; set; } = false;
|
||||
|
||||
[JsonProperty("keyId")]
|
||||
public string keyId { get; set; } = string.Empty;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@
|
|||
"ExamConnection": "Server=192.168.1.63;User ID=root;Password=12345678;Port=3306;Database=hrms_exam;Allow User Variables=True;Convert Zero Datetime=True;Pooling=True;",
|
||||
"LeaveConnection": "Server=192.168.1.63;User ID=root;Password=12345678;Port=3306;Database=hrms_leave;Allow User Variables=True;Convert Zero Datetime=True;Pooling=True;"
|
||||
|
||||
// "DefaultConnection": "server=172.27.17.68;user=root;password=ey2qVVyyqGYw8CyA7h8X72559r2Ad84K;port=3306;database=hrms;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;Connection Timeout=180;",
|
||||
// "ExamConnection": "server=172.27.17.68;user=root;password=ey2qVVyyqGYw8CyA7h8X72559r2Ad84K;port=3306;database=hrms_exam;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;Connection Timeout=180;",
|
||||
// "LeaveConnection": "server=172.27.17.68;user=root;password=ey2qVVyyqGYw8CyA7h8X72559r2Ad84K;port=3306;database=hrms_leave;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;Connection Timeout=180;"
|
||||
// "DefaultConnection": "server=127.0.0.1;user=root;password=ey2qVVyyqGYw8CyA7h8X72559r2Ad84K;port=3306;database=hrms;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;Connection Timeout=180;",
|
||||
// "ExamConnection": "server=127.0.0.1;user=root;password=ey2qVVyyqGYw8CyA7h8X72559r2Ad84K;port=3306;database=hrms_exam;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;Connection Timeout=180;",
|
||||
// "LeaveConnection": "server=127.0.0.1;user=root;password=ey2qVVyyqGYw8CyA7h8X72559r2Ad84K;port=3306;database=hrms_leave;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;Connection Timeout=180;"
|
||||
},
|
||||
"Jwt": {
|
||||
"Key": "j7C9RO_p4nRtuwCH4z9Db_A_6We42tkD_p4lZtDrezc",
|
||||
|
|
|
|||
|
|
@ -903,6 +903,49 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
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)}")]
|
||||
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 => x.PlacementStatus.ToUpper() == "REPORT")
|
||||
.ToListAsync();
|
||||
placementProfiles.ForEach(profile => profile.PlacementStatus = "PREPARE-CONTAI");
|
||||
placementProfiles.ForEach(profile => profile.PlacementStatus = "PREPARE-CONTAIN");
|
||||
await _context.SaveChangesAsync();
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -2498,6 +2541,11 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
var data = await _context.PlacementProfiles
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.PlacementStatus = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -2547,12 +2595,12 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.PlacementStatus = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => profile.PlacementStatus = "DONE");
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -2734,6 +2782,11 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
var data = await _context.PlacementProfiles
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.PlacementStatus = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -2783,12 +2836,12 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.PlacementStatus = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => profile.PlacementStatus = "DONE");
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -2955,6 +3008,11 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
var data = await _context.PlacementProfiles
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.PlacementStatus = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -3004,12 +3062,12 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.PlacementStatus = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// data.ForEach(profile => profile.PlacementStatus = "DONE");
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -758,6 +758,17 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
var data = await _context.PlacementOfficers
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
var firstRef = req.refIds.FirstOrDefault();
|
||||
var commandNoText = firstRef != null ? $"{firstRef.commandNo}/{firstRef.commandYear.ToThaiYear()}" : null;
|
||||
foreach (var profile in data)
|
||||
{
|
||||
profile.Status = "DONE";
|
||||
profile.commandNo = commandNoText;
|
||||
}
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -809,17 +820,16 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
//data.ForEach(profile => profile.Status = "DONE");
|
||||
foreach (var profile in data)
|
||||
{
|
||||
profile.Status = "DONE";
|
||||
profile.commandNo = resultData.Count > 0 ? $"{resultData[0].commandNo}/{resultData[0].commandYear.ToThaiYear()}" : null;
|
||||
}
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
//// var _result = await _res.Content.ReadAsStringAsync();
|
||||
//// if (_res.IsSuccessStatusCode)
|
||||
//// {
|
||||
//// foreach (var profile in data)
|
||||
//// {
|
||||
//// profile.Status = "DONE";
|
||||
//// profile.commandNo = resultData.Count > 0 ? $"{resultData[0].commandNo}/{resultData[0].commandYear.ToThaiYear()}" : null;
|
||||
//// }
|
||||
//// await _context.SaveChangesAsync();
|
||||
//// }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
{
|
||||
p.Id,
|
||||
p.prefix,
|
||||
p.rank,
|
||||
p.firstName,
|
||||
p.lastName,
|
||||
p.citizenId,
|
||||
|
|
@ -280,6 +281,7 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
// ProfileId = p.Profile.Id,
|
||||
p.citizenId,
|
||||
p.prefix,
|
||||
p.rank,
|
||||
p.firstName,
|
||||
p.lastName,
|
||||
p.DateOfBirth,
|
||||
|
|
@ -377,6 +379,7 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
// data.ProfileId,
|
||||
data.citizenId,
|
||||
data.prefix,
|
||||
data.rank,
|
||||
data.firstName,
|
||||
data.lastName,
|
||||
data.DateOfBirth,
|
||||
|
|
@ -484,6 +487,7 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
// Profile = profile,
|
||||
citizenId = req.citizenId,
|
||||
prefix = req.prefix,
|
||||
rank = req.rank,
|
||||
firstName = req.firstName,
|
||||
lastName = req.lastName,
|
||||
DateOfBirth = req.BirthDate,
|
||||
|
|
@ -852,6 +856,7 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
uppdated.Gender = req.Gender;
|
||||
uppdated.citizenId = req.citizenId;
|
||||
uppdated.prefix = req.prefix;
|
||||
uppdated.rank = req.rank;
|
||||
uppdated.firstName = req.firstName;
|
||||
uppdated.lastName = req.lastName;
|
||||
uppdated.DateOfBirth = req.DateOfBirth;
|
||||
|
|
@ -1124,6 +1129,10 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
.Include(x => x.Avatar)
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -1223,12 +1232,12 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
// // var _result = await _res.Content.ReadAsStringAsync();
|
||||
// // if (_res.IsSuccessStatusCode)
|
||||
// // {
|
||||
// // data.ForEach(profile => profile.Status = "DONE");
|
||||
// // await _context.SaveChangesAsync();
|
||||
// // }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -623,6 +623,10 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
var data = await _context.PlacementRepatriations
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -675,12 +679,12 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
// // var _result = await _res.Content.ReadAsStringAsync();
|
||||
// // if (_res.IsSuccessStatusCode)
|
||||
// // {
|
||||
// // data.ForEach(profile => profile.Status = "DONE");
|
||||
// // await _context.SaveChangesAsync();
|
||||
// // }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1094,6 +1094,10 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
var data = await _context.PlacementTransfers
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -1146,12 +1150,12 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
// // var _result = await _res.Content.ReadAsStringAsync();
|
||||
// // if (_res.IsSuccessStatusCode)
|
||||
// // {
|
||||
// // data.ForEach(profile => profile.Status = "DONE");
|
||||
// // await _context.SaveChangesAsync();
|
||||
// // }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ namespace BMA.EHR.Placement.Service.Requests
|
|||
public class PlacementReceiveEditRequest
|
||||
{
|
||||
public string citizenId { get; set; }
|
||||
public string prefix { get; set; }
|
||||
public string? prefix { get; set; }
|
||||
public string? rank { get; set; }
|
||||
public string firstName { get; set; }
|
||||
public string lastName { get; set; }
|
||||
public DateTime DateOfBirth { get; set; }
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ namespace BMA.EHR.Placement.Service.Requests
|
|||
public class PlacementReceiveRequest
|
||||
{
|
||||
public string citizenId { get; set; }
|
||||
public string prefix { get; set; }
|
||||
|
||||
public string? prefix { get; set; }
|
||||
public string? rank { get; set; }
|
||||
public string firstName { get; set; }
|
||||
public string lastName { get; set; }
|
||||
public DateTime BirthDate { get; set; }
|
||||
|
|
|
|||
|
|
@ -40,10 +40,17 @@
|
|||
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="9.0.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="DocumentFormat.OpenXml" Version="2.20.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BMA.EHR.Infrastructure\BMA.EHR.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Templates\**\*.docx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using BMA.EHR.Domain.Models.Retirement;
|
|||
using BMA.EHR.Domain.Shared;
|
||||
using BMA.EHR.Infrastructure.Persistence;
|
||||
using BMA.EHR.Retirement.Service.Requests;
|
||||
using BMA.EHR.Retirement.Service.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
|
@ -37,6 +38,7 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
private readonly PermissionRepository _permission;
|
||||
private readonly DisciplineDbContext _contextDiscipline;
|
||||
private readonly RetireReportRepository _service;
|
||||
private readonly RetirementReportService _reportService;
|
||||
public RetirementController(RetirementRepository repository,
|
||||
NotificationRepository repositoryNoti,
|
||||
ApplicationDBContext context,
|
||||
|
|
@ -46,7 +48,8 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
IHttpContextAccessor httpContextAccessor,
|
||||
PermissionRepository permission,
|
||||
DisciplineDbContext contextDiscipline,
|
||||
RetireReportRepository service)
|
||||
RetireReportRepository service,
|
||||
RetirementReportService reportService)
|
||||
{
|
||||
_repository = repository;
|
||||
_repositoryNoti = repositoryNoti;
|
||||
|
|
@ -58,6 +61,7 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
_permission = permission;
|
||||
_contextDiscipline = contextDiscipline;
|
||||
_service = service;
|
||||
_reportService = reportService;
|
||||
}
|
||||
|
||||
#region " Properties "
|
||||
|
|
@ -2213,5 +2217,83 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
}
|
||||
}
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -845,6 +845,10 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
var data = await _context.RetirementOthers
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -914,12 +918,12 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
// // var _result = await _res.Content.ReadAsStringAsync();
|
||||
// // if (_res.IsSuccessStatusCode)
|
||||
// // {
|
||||
// // data.ForEach(profile => profile.Status = "DONE");
|
||||
// // await _context.SaveChangesAsync();
|
||||
// // }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -1090,6 +1094,10 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
var data = await _context.RetirementOthers
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -1159,12 +1167,12 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
// // var _result = await _res.Content.ReadAsStringAsync();
|
||||
// // if (_res.IsSuccessStatusCode)
|
||||
// // {
|
||||
// // data.ForEach(profile => profile.Status = "DONE");
|
||||
// // await _context.SaveChangesAsync();
|
||||
// // }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -642,6 +642,10 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
var data = await _context.RetirementOuts
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -701,12 +705,12 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
// // var _result = await _res.Content.ReadAsStringAsync();
|
||||
// // if (_res.IsSuccessStatusCode)
|
||||
// // {
|
||||
// // data.ForEach(profile => profile.Status = "DONE");
|
||||
// // await _context.SaveChangesAsync();
|
||||
// // }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2861,6 +2861,10 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
var data = await _context.RetirementResigns
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -2915,12 +2919,12 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
// // var _result = await _res.Content.ReadAsStringAsync();
|
||||
// // if (_res.IsSuccessStatusCode)
|
||||
// // {
|
||||
// // data.ForEach(profile => profile.Status = "DONE");
|
||||
// // await _context.SaveChangesAsync();
|
||||
// // }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -3060,6 +3064,11 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
.Include(x => x.RetirementResign)
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
data.ForEach(profile => profile.RetirementResign.Status = "CANCEL");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -3120,13 +3129,13 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
data.ForEach(profile => profile.RetirementResign.Status = "CANCEL");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
// // var _result = await _res.Content.ReadAsStringAsync();
|
||||
// // if (_res.IsSuccessStatusCode)
|
||||
// // {
|
||||
// // data.ForEach(profile => profile.Status = "DONE");
|
||||
// // data.ForEach(profile => profile.RetirementResign.Status = "CANCEL");
|
||||
// // await _context.SaveChangesAsync();
|
||||
// // }
|
||||
}
|
||||
//}
|
||||
//else
|
||||
|
|
|
|||
|
|
@ -2361,6 +2361,10 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
var data = await _context.RetirementResignEmployees
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
on p.Id.ToString() equals r.refId
|
||||
|
|
@ -2413,12 +2417,12 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
// // var _result = await _res.Content.ReadAsStringAsync();
|
||||
// // if (_res.IsSuccessStatusCode)
|
||||
// // {
|
||||
// // data.ForEach(profile => profile.Status = "DONE");
|
||||
// // await _context.SaveChangesAsync();
|
||||
// // }
|
||||
}
|
||||
return Success();
|
||||
}
|
||||
|
|
@ -2556,6 +2560,11 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
.Include(x => x.RetirementResignEmployee)
|
||||
.Where(x => req.refIds.Select(x => x.refId).Contains(x.Id.ToString()))
|
||||
.ToListAsync();
|
||||
// Task #224 ปรับให้เป็น process ที่ควรบันทึกตามลำดับ
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
data.ForEach(profile => profile.RetirementResignEmployee.Status = "CANCEL");
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string? _null = null;
|
||||
var resultData = (from p in data
|
||||
join r in req.refIds
|
||||
|
|
@ -2615,13 +2624,13 @@ namespace BMA.EHR.Retirement.Service.Controllers
|
|||
{
|
||||
data = resultData,
|
||||
});
|
||||
var _result = await _res.Content.ReadAsStringAsync();
|
||||
if (_res.IsSuccessStatusCode)
|
||||
{
|
||||
data.ForEach(profile => profile.Status = "DONE");
|
||||
data.ForEach(profile => profile.RetirementResignEmployee.Status = "CANCEL");
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
// // var _result = await _res.Content.ReadAsStringAsync();
|
||||
// // if (_res.IsSuccessStatusCode)
|
||||
// // {
|
||||
// // data.ForEach(profile => profile.Status = "DONE");
|
||||
// // data.ForEach(profile => profile.RetirementResignEmployee.Status = "CANCEL");
|
||||
// // await _context.SaveChangesAsync();
|
||||
// // }
|
||||
}
|
||||
//}
|
||||
//else
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using BMA.EHR.Domain.Middlewares;
|
|||
using BMA.EHR.Infrastructure;
|
||||
using BMA.EHR.Infrastructure.Persistence;
|
||||
using BMA.EHR.Retirement.Service;
|
||||
using BMA.EHR.Retirement.Service.Services;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
|
|
@ -86,6 +87,7 @@ var builder = WebApplication.CreateBuilder(args);
|
|||
builder.Services.AddApplication();
|
||||
builder.Services.AddLeaveApplication();
|
||||
builder.Services.AddPersistence(builder.Configuration);
|
||||
builder.Services.AddScoped<RetirementReportService>();
|
||||
builder.Services.AddLeavePersistence(builder.Configuration);
|
||||
|
||||
builder.Services.AddHttpClient();
|
||||
|
|
|
|||
698
BMA.EHR.Retirement.Service/Services/RetirementReportService.cs
Normal file
698
BMA.EHR.Retirement.Service/Services/RetirementReportService.cs
Normal file
|
|
@ -0,0 +1,698 @@
|
|||
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-1 format: 2 rows, 3 columns (root row + data row per profile)
|
||||
if (IsTwoRowPerProfileFormat(rows))
|
||||
return new TwoRowPerProfileTableStrategy();
|
||||
|
||||
// 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;
|
||||
|
||||
private static bool IsTwoRowPerProfileFormat(List<TableRow> rows) =>
|
||||
rows.Count == 2 &&
|
||||
rows[0].Elements<TableCell>().Count() == 3 &&
|
||||
rows[1].Elements<TableCell>().Count() == 3;
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class TwoRowPerProfileTableStrategy : ITableStrategy
|
||||
{
|
||||
public void Process(Table table, List<TableRow> rows, System.Collections.IEnumerable profiles)
|
||||
{
|
||||
// retire-1 format: 2 rows per profile (root row + data row)
|
||||
var rootRow = rows[0];
|
||||
var dataRow = rows[1];
|
||||
|
||||
// Remove template rows from table
|
||||
rootRow.Remove();
|
||||
dataRow.Remove();
|
||||
|
||||
var profileList = profiles.Cast<object>().ToList();
|
||||
|
||||
foreach (var profile in profileList)
|
||||
{
|
||||
var props = profile.GetType()
|
||||
.GetProperties()
|
||||
.Where(p => p.GetIndexParameters().Length == 0)
|
||||
.ToList();
|
||||
|
||||
// Check root value - skip root row if empty or null
|
||||
var rootValue = props.FirstOrDefault(p => p.Name.Equals("root", StringComparison.OrdinalIgnoreCase))
|
||||
?.GetValue(profile)?.ToString() ?? string.Empty;
|
||||
|
||||
// Clone root row and fill with placeholders (only if root has value)
|
||||
if (!string.IsNullOrWhiteSpace(rootValue))
|
||||
{
|
||||
var newRootRow = (TableRow)rootRow.CloneNode(true);
|
||||
foreach (var prop in props)
|
||||
{
|
||||
var value = prop.GetValue(profile)?.ToString() ?? string.Empty;
|
||||
var placeholder = $"{{{{{prop.Name}}}}}";
|
||||
TextReplacer.ReplaceInRow(newRootRow, placeholder, value);
|
||||
}
|
||||
table.AppendChild(newRootRow);
|
||||
}
|
||||
|
||||
// Clone data row and fill with placeholders (always show)
|
||||
var newDataRow = (TableRow)dataRow.CloneNode(true);
|
||||
foreach (var prop in props)
|
||||
{
|
||||
var value = prop.GetValue(profile)?.ToString() ?? string.Empty;
|
||||
var placeholder = $"{{{{{prop.Name}}}}}";
|
||||
TextReplacer.ReplaceInRow(newDataRow, placeholder, value);
|
||||
}
|
||||
table.AppendChild(newDataRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
BIN
BMA.EHR.Retirement.Service/Templates/retire-1.docx
Normal file
BIN
BMA.EHR.Retirement.Service/Templates/retire-1.docx
Normal file
Binary file not shown.
BIN
BMA.EHR.Retirement.Service/Templates/retire-2.docx
Normal file
BIN
BMA.EHR.Retirement.Service/Templates/retire-2.docx
Normal file
Binary file not shown.
BIN
BMA.EHR.Retirement.Service/Templates/retire-3.docx
Normal file
BIN
BMA.EHR.Retirement.Service/Templates/retire-3.docx
Normal file
Binary file not shown.
BIN
BMA.EHR.Retirement.Service/Templates/retire-emp-1.docx
Normal file
BIN
BMA.EHR.Retirement.Service/Templates/retire-emp-1.docx
Normal file
Binary file not shown.
BIN
BMA.EHR.Retirement.Service/Templates/retire-emp-2.docx
Normal file
BIN
BMA.EHR.Retirement.Service/Templates/retire-emp-2.docx
Normal file
Binary file not shown.
BIN
BMA.EHR.Retirement.Service/Templates/retire-emp-3.docx
Normal file
BIN
BMA.EHR.Retirement.Service/Templates/retire-emp-3.docx
Normal file
Binary file not shown.
210
README.md
Normal file
210
README.md
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
# BMA.EHR - HRMS API Backend
|
||||
|
||||
ระบบบริหารจัดการทรัพยากรบุคคล (Human Resource Management System) พัฒนาด้วยสถาปัตยกรรม Microservices บน .NET
|
||||
|
||||
---
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Category | Technology |
|
||||
| ----------------- | ----------------------------- |
|
||||
| Framework | .NET 6.0 / 7.0 / 8.0 |
|
||||
| Architecture | Clean Architecture, DDD, CQRS |
|
||||
| Database | MySQL (Entity Framework Core) |
|
||||
| Authentication | JWT + Keycloak |
|
||||
| Message Queue | RabbitMQ |
|
||||
| Object Storage | MinIO |
|
||||
| Background Jobs | Hangfire |
|
||||
| Logging | Serilog + Elasticsearch |
|
||||
| Error Tracking | Sentry |
|
||||
| API Documentation | Swagger / OpenAPI |
|
||||
| Containerization | Docker |
|
||||
| Testing | xUnit, k6 (Load Testing) |
|
||||
|
||||
---
|
||||
|
||||
## โครงสร้างโปรเจกต์ (Project Structure)
|
||||
|
||||
```
|
||||
BMA.EHR.Solution.sln
|
||||
├── src/ # Core Libraries
|
||||
│ ├── BMA.EHR.Domain/ # Domain layer (Entities, Business Rules)
|
||||
│ ├── BMA.EHR.Application/ # Application layer (Use Cases, Interfaces)
|
||||
│ └── BMA.EHR.Infrastructure/ # Infrastructure layer (Data Access, External Services)
|
||||
│
|
||||
└── Service/ # Microservices
|
||||
├── BMA.EHR.Command.Service/ # Command/CQRS API Gateway
|
||||
├── BMA.EHR.MetaData.Service/ # ข้อมูลอ้างอิง (คำนำหน้า, หมู่เลือด, ศาสนา ฯลฯ)
|
||||
├── BMA.EHR.Placement.Service/ # การบริจาค/สั่งย้าย/แต่งตั้ง
|
||||
├── BMA.EHR.OrganizationEmployee.Service/ # โครงสร้างองค์กรและบุคลากร
|
||||
├── BMA.EHR.Discipline.Service/ # การ discipline บุคลากร
|
||||
├── BMA.EHR.Retirement.Service/ # การเกษียณอายุราชการ
|
||||
├── BMA.EHR.Report.Service/ # รายงาน
|
||||
├── BMA.EHR.Insignia/ # เครื่องราชอิสริยาภรณ์
|
||||
├── BMA.EHR.Leave/ # ระบบลา
|
||||
└── BMA.EHR.CheckInConsumer/ # ลงเวลาปฏิบัติงาน
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## โมดูลหลัก (Key Modules)
|
||||
|
||||
### การบริหารทรัพยากรบุคคล
|
||||
|
||||
- **Placement Service** - สั่งย้าย, แต่งตั้ง, เลื่อนตำแหน่ง, โอนย้ายบุคลากร
|
||||
- **Organization Employee Service** - จัดการโครงสร้างองค์กร, ตำแหน่ง, ข้อมูลบุคลากร
|
||||
- **Leave Service** - การลางาน, การอนุมัติ, วันหยุดนักขัตฤกษ์, ยอดวันลาคงเหลือ
|
||||
- **Discipline Service** - การดำเนินการ discipline, การสืบสวน, เอกสารที่เกี่ยวข้อง
|
||||
- **Retirement Service** - การเกษียณอายุ, เอกสาร, สิทธิประโยชน์
|
||||
- **Insignia Service** - เครื่องราชอิสริยาภรณ์และรางวัล
|
||||
- **CheckIn Consumer** - ติดตามการลงเวลาปฏิบัติงาน
|
||||
|
||||
### ระบบสนับสนุน
|
||||
|
||||
- **Metadata Service** - ข้อมูลอ้างอิง (คำนำหน้าชื่อ, หมู่เลือด, ศาสนา, ระดับการศึกษา ฯลฯ)
|
||||
- **Report Service** - สร้างรายงาน PDF/Excel
|
||||
- **Command Service** - API Gateway สำหรับ CQRS command operations
|
||||
|
||||
### ฟีเจอร์เด่น
|
||||
|
||||
- **Real-time Notifications** - แจ้งเตือนผ่าน WebSocket
|
||||
- **Background Processing** - งานที่กำหนดเวลาผ่าน Hangfire
|
||||
- **Event-Driven Communication** - สื่อสารระหว่าง services ผ่าน RabbitMQ
|
||||
- **Document Generation** - สร้างเอกสาร PDF/Excel
|
||||
- **Audit Trail** - บันทึกประวัติการเปลี่ยนแปลงข้อมูลทั้งหมด
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints
|
||||
|
||||
API ใช้ versioning และสามารถดูรายละเอียดได้ผ่าน Swagger UI:
|
||||
|
||||
```
|
||||
/api/v1/placement # การบริจาค/สั่งย้าย/แต่งตั้ง
|
||||
/api/v1/leave # ระบบลา
|
||||
/api/v1/discipline # การ discipline
|
||||
/api/v1/organization # โครงสร้างองค์กร
|
||||
/api/v1/metadata # ข้อมูลอ้างอิง
|
||||
/api/v1/retirement # การเกษียณอายุ
|
||||
/api/v1/insignia # เครื่องราชอิสริยาภรณ์
|
||||
/api/v1/reports # รายงาน
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- .NET SDK 6.0 / 7.0 / 8.0
|
||||
- MySQL Server
|
||||
- Keycloak (Authentication Server)
|
||||
- RabbitMQ
|
||||
- MinIO (Object Storage)
|
||||
- Docker (สำหรับ deployment)
|
||||
|
||||
### Configuration
|
||||
|
||||
แต่ละ service มีไฟล์ `appsettings.json` สำหรับ config ดังนี้:
|
||||
|
||||
- **JWT Authentication** - เชื่อมต่อกับ Keycloak
|
||||
- **Database Connection** - MySQL connection string
|
||||
- **RabbitMQ** - Message queue connection
|
||||
- **MinIO** - File storage endpoint
|
||||
- **Elasticsearch** - Logging endpoint
|
||||
- **Mail Server** - สำหรับส่งอีเมล
|
||||
|
||||
### Build & Run
|
||||
|
||||
```bash
|
||||
# Restore dependencies
|
||||
dotnet restore
|
||||
|
||||
# Build solution
|
||||
dotnet build
|
||||
|
||||
# Run specific service
|
||||
dotnet run --project Service/BMA.EHR.Command.Service
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
# Build Docker image
|
||||
docker build -t bma-ehr-service .
|
||||
|
||||
# Run container
|
||||
docker run -d -p 5000:80 bma-ehr-service
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ Swagger │ │ Client │ │ WebSocket │
|
||||
│ UI │ │ Apps │ │ Clients │
|
||||
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
|
||||
│ │ │
|
||||
└────────────────────┼────────────────────┘
|
||||
│
|
||||
┌────────▼────────┐
|
||||
│ API Gateway │
|
||||
│ (Keycloak JWT) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌────────────────────┼────────────────────┐
|
||||
│ │ │
|
||||
┌──────▼──────┐ ┌────────▼──────┐ ┌────────▼──────┐
|
||||
│ Placement │ │ Leave │ │ Discipline │
|
||||
│ Service │ │ Service │ │ Service │
|
||||
└──────┬──────┘ └────────┬──────┘ └────────┬──────┘
|
||||
│ │ │
|
||||
└────────────────────┼────────────────────┘
|
||||
│
|
||||
┌─────────────▼──────────────┐
|
||||
│ MySQL Database │
|
||||
│ (Entity Framework) │
|
||||
└────────────────────────────┘
|
||||
|
||||
┌────────────────────────────┐
|
||||
│ RabbitMQ / MinIO / │
|
||||
│ Elasticsearch / Hangfire │
|
||||
└────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencies ที่สำคัญ
|
||||
|
||||
| Package | หน้าที่ |
|
||||
| --------------------- | ------------------------- |
|
||||
| Entity Framework Core | ORM สำหรับ MySQL |
|
||||
| Serilog | Structured Logging |
|
||||
| Swashbuckle | API Documentation |
|
||||
| Hangfire | Background Job Processing |
|
||||
| EPPlus | สร้าง/อ่านไฟล์ Excel |
|
||||
| iTextSharp | สร้างไฟล์ PDF |
|
||||
| RabbitMQ.Client | Message Queue |
|
||||
| NEST | Elasticsearch Client |
|
||||
| ThaiBahtText | แปลงตัวเลขเป็นหน่วยบาทไทย |
|
||||
| NodaTime | Date/Time Handling |
|
||||
| Sentry | Error Tracking |
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Run unit tests
|
||||
dotnet test
|
||||
|
||||
# Run with coverage
|
||||
dotnet test --collect:"XPlat Code Coverage"
|
||||
|
||||
# Run load tests (k6)
|
||||
k6 run tests/load/*.js
|
||||
```
|
||||
|
||||
---
|
||||
Loading…
Add table
Add a link
Reference in a new issue