refactor code
This commit is contained in:
parent
8ba9d349db
commit
ed1bb838ce
5 changed files with 109 additions and 67 deletions
|
|
@ -720,7 +720,7 @@ namespace BMA.EHR.Application.Repositories
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<dynamic> SearchProfile(string? citizenId, string? firstName, string? lastName, string accessToken, int page, int pageSize, string? role, string? nodeId, int? node)
|
public async Task<GetProfileByKeycloakIdRootAddTotalDto> SearchProfile(string? citizenId, string? firstName, string? lastName, string accessToken, int page, int pageSize, string? role, string? nodeId, int? node)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -738,21 +738,21 @@ namespace BMA.EHR.Application.Repositories
|
||||||
pageSize = pageSize,
|
pageSize = pageSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
var profiles = new List<dynamic>();
|
var profiles = new List<GetProfileByKeycloakIdRootDto>();
|
||||||
var total = 0;
|
var total = 0;
|
||||||
|
|
||||||
var apiResult = await PostExternalAPIAsync(apiPath, accessToken, body, apiKey);
|
var apiResult = await PostExternalAPIAsync(apiPath, accessToken, body, apiKey);
|
||||||
if (apiResult != null)
|
if (apiResult != null)
|
||||||
{
|
{
|
||||||
var raw = JsonConvert.DeserializeObject<dynamic>(apiResult);
|
var raw = JsonConvert.DeserializeObject<GetListProfileByKeycloakIdRootResultAddTotalDto>(apiResult);
|
||||||
if (raw != null && raw.Result != null)
|
if (raw != null && raw.Result != null)
|
||||||
{
|
{
|
||||||
profiles.AddRange(raw.Result.data);
|
profiles.AddRange(raw.Result.Data);
|
||||||
total = raw.Result.total;
|
total = raw.Result.Total;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new { data = profiles, total = total };
|
return new GetProfileByKeycloakIdRootAddTotalDto { Data = profiles, Total = total };
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
@ -760,7 +760,7 @@ namespace BMA.EHR.Application.Repositories
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<dynamic> SearchProfileEmployee(string? citizenId, string? firstName, string? lastName, string accessToken, int page, int pageSize, string? role, string? nodeId, int? node)
|
public async Task<GetProfileByKeycloakIdRootAddTotalDto> SearchProfileEmployee(string? citizenId, string? firstName, string? lastName, string accessToken, int page, int pageSize, string? role, string? nodeId, int? node)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -778,21 +778,21 @@ namespace BMA.EHR.Application.Repositories
|
||||||
pageSize = pageSize,
|
pageSize = pageSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
var profiles = new List<dynamic>();
|
var profiles = new List<GetProfileByKeycloakIdRootDto>();
|
||||||
var total = 0;
|
var total = 0;
|
||||||
|
|
||||||
var apiResult = await PostExternalAPIAsync(apiPath, accessToken, body, apiKey);
|
var apiResult = await PostExternalAPIAsync(apiPath, accessToken, body, apiKey);
|
||||||
if (apiResult != null)
|
if (apiResult != null)
|
||||||
{
|
{
|
||||||
var raw = JsonConvert.DeserializeObject<dynamic>(apiResult);
|
var raw = JsonConvert.DeserializeObject<GetListProfileByKeycloakIdRootResultAddTotalDto>(apiResult);
|
||||||
if (raw != null && raw.Result != null)
|
if (raw != null && raw.Result != null)
|
||||||
{
|
{
|
||||||
profiles.AddRange(raw.Result.data);
|
profiles.AddRange(raw.Result.Data);
|
||||||
total = raw.Result.total;
|
total = raw.Result.Total;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new { data = profiles, total = total };
|
return new GetProfileByKeycloakIdRootAddTotalDto { Data = profiles, Total = total };
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,12 @@
|
||||||
|
|
||||||
public List<GetProfileByKeycloakIdRootDto> Result { get; set; } = new();
|
public List<GetProfileByKeycloakIdRootDto> Result { get; set; } = new();
|
||||||
}
|
}
|
||||||
|
public class GetListProfileByKeycloakIdRootResultAddTotalDto
|
||||||
|
{
|
||||||
|
public string Message { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public int Status { get; set; } = -1;
|
||||||
|
|
||||||
|
public GetProfileByKeycloakIdRootAddTotalDto Result { get; set; } = new();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,12 @@ namespace BMA.EHR.Application.Responses.Profiles
|
||||||
public DateTime? DateStart { get; set; }
|
public DateTime? DateStart { get; set; }
|
||||||
|
|
||||||
public DateTime? DateAppoint { get; set; }
|
public DateTime? DateAppoint { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetProfileByKeycloakIdRootAddTotalDto
|
||||||
|
{
|
||||||
|
public List<GetProfileByKeycloakIdRootDto> Data { get; set; } = new();
|
||||||
|
|
||||||
|
public int Total { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1839,18 +1839,41 @@ namespace BMA.EHR.Leave.Service.Controllers
|
||||||
}
|
}
|
||||||
var profile = await _userProfileRepository.SearchProfile(req.CitizenId, req.FirstName, req.LastName, AccessToken ?? "", req.Page, req.PageSize, role, nodeId, profileAdmin?.Node);
|
var profile = await _userProfileRepository.SearchProfile(req.CitizenId, req.FirstName, req.LastName, AccessToken ?? "", req.Page, req.PageSize, role, nodeId, profileAdmin?.Node);
|
||||||
|
|
||||||
|
// Get default round once
|
||||||
var getDefaultRound = await _dutyTimeRepository.GetDefaultAsync();
|
var getDefaultRound = await _dutyTimeRepository.GetDefaultAsync();
|
||||||
|
|
||||||
var resultSet = new List<SearchProfileResultDto>();
|
var resultSet = new List<SearchProfileResultDto>();
|
||||||
|
|
||||||
foreach (var p in profile.data)
|
// Create dictionaries to cache results and avoid duplicate queries
|
||||||
|
var effectiveDateCache = new Dictionary<Guid, UserDutyTime?>();
|
||||||
|
var dutyTimeCache = new Dictionary<Guid, DutyTime?>();
|
||||||
|
|
||||||
|
foreach (var p in profile.Data)
|
||||||
{
|
{
|
||||||
var effectiveDate = await _userDutyTimeRepository.GetLastEffectRound(p.Id);
|
// Use cache for effective date
|
||||||
|
if (!effectiveDateCache.ContainsKey(p.Id))
|
||||||
|
{
|
||||||
|
effectiveDateCache[p.Id] = await _userDutyTimeRepository.GetLastEffectRound(p.Id);
|
||||||
|
}
|
||||||
|
var effectiveDate = effectiveDateCache[p.Id];
|
||||||
|
|
||||||
var roundId = effectiveDate != null ? effectiveDate.DutyTimeId : Guid.Empty;
|
var roundId = effectiveDate != null ? effectiveDate.DutyTimeId : Guid.Empty;
|
||||||
var userRound = await _dutyTimeRepository.GetByIdAsync(roundId);
|
|
||||||
|
// Use cache for duty time
|
||||||
|
DutyTime? userRound = null;
|
||||||
|
if (roundId != Guid.Empty)
|
||||||
|
{
|
||||||
|
if (!dutyTimeCache.ContainsKey(roundId))
|
||||||
|
{
|
||||||
|
dutyTimeCache[roundId] = await _dutyTimeRepository.GetByIdAsync(roundId);
|
||||||
|
}
|
||||||
|
userRound = dutyTimeCache[roundId];
|
||||||
|
}
|
||||||
|
|
||||||
var duty = userRound ?? getDefaultRound;
|
var duty = userRound ?? getDefaultRound;
|
||||||
|
|
||||||
|
if (duty == null) continue; // Skip if no duty time found
|
||||||
|
|
||||||
var res = new SearchProfileResultDto
|
var res = new SearchProfileResultDto
|
||||||
{
|
{
|
||||||
ProfileId = p.Id,
|
ProfileId = p.Id,
|
||||||
|
|
@ -1858,44 +1881,12 @@ namespace BMA.EHR.Leave.Service.Controllers
|
||||||
FullName = $"{p.Prefix ?? ""}{p.FirstName ?? ""} {p.LastName ?? ""}",
|
FullName = $"{p.Prefix ?? ""}{p.FirstName ?? ""} {p.LastName ?? ""}",
|
||||||
StartTimeMorning = duty.StartTimeMorning,
|
StartTimeMorning = duty.StartTimeMorning,
|
||||||
LeaveTimeAfterNoon = duty.EndTimeAfternoon,
|
LeaveTimeAfterNoon = duty.EndTimeAfternoon,
|
||||||
EffectiveDate = effectiveDate == null ? null : effectiveDate.EffectiveDate.Value.Date
|
EffectiveDate = effectiveDate?.EffectiveDate?.Date
|
||||||
};
|
};
|
||||||
resultSet.Add(res);
|
resultSet.Add(res);
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrWhiteSpace(req.sortBy))
|
|
||||||
{
|
|
||||||
switch (req.sortBy.ToUpper())
|
|
||||||
{
|
|
||||||
case "CITIZENID":
|
|
||||||
if (req.descending == true)
|
|
||||||
resultSet = resultSet.OrderByDescending(x => x.CitizenId).ToList();
|
|
||||||
else
|
|
||||||
resultSet = resultSet.OrderBy(x => x.CitizenId).ToList();
|
|
||||||
break;
|
|
||||||
case "FULLNAME":
|
|
||||||
if (req.descending == true)
|
|
||||||
resultSet = resultSet.OrderByDescending(x => x.FullName).ToList();
|
|
||||||
else
|
|
||||||
resultSet = resultSet.OrderBy(x => x.FullName).ToList();
|
|
||||||
break;
|
|
||||||
case "STARTTIMEMORNING":
|
|
||||||
if (req.descending == true)
|
|
||||||
resultSet = resultSet.OrderByDescending(x => x.StartTimeMorning).ToList();
|
|
||||||
else
|
|
||||||
resultSet = resultSet.OrderBy(x => x.StartTimeMorning).ToList();
|
|
||||||
break;
|
|
||||||
case "EFFECTIVEDATE":
|
|
||||||
if (req.descending == true)
|
|
||||||
resultSet = resultSet.OrderByDescending(x => x.EffectiveDate).ToList();
|
|
||||||
else
|
|
||||||
resultSet = resultSet.OrderBy(x => x.EffectiveDate).ToList();
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var pageResult = resultSet.Skip((req.Page - 1) * req.PageSize).Take(req.PageSize).ToList();
|
|
||||||
|
|
||||||
return Success(new { data = resultSet, total = profile.total });
|
return Success(new { data = resultSet, total = profile.Total });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -2091,18 +2082,41 @@ namespace BMA.EHR.Leave.Service.Controllers
|
||||||
}
|
}
|
||||||
var profile = await _userProfileRepository.SearchProfileEmployee(req.CitizenId, req.FirstName, req.LastName, AccessToken ?? "", req.Page, req.PageSize, role, nodeId, profileAdmin?.Node);
|
var profile = await _userProfileRepository.SearchProfileEmployee(req.CitizenId, req.FirstName, req.LastName, AccessToken ?? "", req.Page, req.PageSize, role, nodeId, profileAdmin?.Node);
|
||||||
|
|
||||||
|
// Get default round once
|
||||||
var getDefaultRound = await _dutyTimeRepository.GetDefaultAsync();
|
var getDefaultRound = await _dutyTimeRepository.GetDefaultAsync();
|
||||||
|
|
||||||
var resultSet = new List<SearchProfileResultDto>();
|
var resultSet = new List<SearchProfileResultDto>();
|
||||||
|
|
||||||
foreach (var p in profile.data)
|
// Create dictionaries to cache results and avoid duplicate queries
|
||||||
|
var effectiveDateCache = new Dictionary<Guid, UserDutyTime?>();
|
||||||
|
var dutyTimeCache = new Dictionary<Guid, DutyTime?>();
|
||||||
|
|
||||||
|
foreach (var p in profile.Data)
|
||||||
{
|
{
|
||||||
var effectiveDate = await _userDutyTimeRepository.GetLastEffectRound(p.Id);
|
// Use cache for effective date
|
||||||
|
if (!effectiveDateCache.ContainsKey(p.Id))
|
||||||
|
{
|
||||||
|
effectiveDateCache[p.Id] = await _userDutyTimeRepository.GetLastEffectRound(p.Id);
|
||||||
|
}
|
||||||
|
var effectiveDate = effectiveDateCache[p.Id];
|
||||||
|
|
||||||
var roundId = effectiveDate != null ? effectiveDate.DutyTimeId : Guid.Empty;
|
var roundId = effectiveDate != null ? effectiveDate.DutyTimeId : Guid.Empty;
|
||||||
var userRound = await _dutyTimeRepository.GetByIdAsync(roundId);
|
|
||||||
|
// Use cache for duty time
|
||||||
|
DutyTime? userRound = null;
|
||||||
|
if (roundId != Guid.Empty)
|
||||||
|
{
|
||||||
|
if (!dutyTimeCache.ContainsKey(roundId))
|
||||||
|
{
|
||||||
|
dutyTimeCache[roundId] = await _dutyTimeRepository.GetByIdAsync(roundId);
|
||||||
|
}
|
||||||
|
userRound = dutyTimeCache[roundId];
|
||||||
|
}
|
||||||
|
|
||||||
var duty = userRound ?? getDefaultRound;
|
var duty = userRound ?? getDefaultRound;
|
||||||
|
|
||||||
|
if (duty == null) continue; // Skip if no duty time found
|
||||||
|
|
||||||
var res = new SearchProfileResultDto
|
var res = new SearchProfileResultDto
|
||||||
{
|
{
|
||||||
ProfileId = p.Id,
|
ProfileId = p.Id,
|
||||||
|
|
@ -2110,12 +2124,12 @@ namespace BMA.EHR.Leave.Service.Controllers
|
||||||
FullName = $"{p.Prefix ?? ""}{p.FirstName ?? ""} {p.LastName ?? ""}",
|
FullName = $"{p.Prefix ?? ""}{p.FirstName ?? ""} {p.LastName ?? ""}",
|
||||||
StartTimeMorning = duty.StartTimeMorning,
|
StartTimeMorning = duty.StartTimeMorning,
|
||||||
LeaveTimeAfterNoon = duty.EndTimeAfternoon,
|
LeaveTimeAfterNoon = duty.EndTimeAfternoon,
|
||||||
EffectiveDate = effectiveDate == null ? null : effectiveDate.EffectiveDate.Value.Date
|
EffectiveDate = effectiveDate?.EffectiveDate?.Date
|
||||||
};
|
};
|
||||||
resultSet.Add(res);
|
resultSet.Add(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Success(new { data = resultSet, total = profile.total });
|
return Success(new { data = resultSet, total = profile.Total });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -2481,44 +2481,58 @@ namespace BMA.EHR.Leave.Service.Controllers
|
||||||
public async Task<ActionResult<ResponseObject>> GetUserLeaveSummaryAsync()
|
public async Task<ActionResult<ResponseObject>> GetUserLeaveSummaryAsync()
|
||||||
{
|
{
|
||||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||||
var leaveTypes = await _leaveTypeRepository.GetAllAsync();
|
|
||||||
var thisYear = DateTime.Now.Year;
|
var thisYear = DateTime.Now.Year;
|
||||||
var toDay = DateTime.Now.Date;
|
var toDay = DateTime.Now.Date;
|
||||||
if (toDay >= new DateTime(toDay.Year, 10, 1) && toDay <= new DateTime(toDay.Year, 12, 31))
|
if (toDay >= new DateTime(toDay.Year, 10, 1) && toDay <= new DateTime(toDay.Year, 12, 31))
|
||||||
thisYear = thisYear + 1;
|
thisYear = thisYear + 1;
|
||||||
|
|
||||||
|
// Execute repository calls sequentially to avoid DbContext threading issues
|
||||||
|
var leaveTypes = await _leaveTypeRepository.GetAllAsync();
|
||||||
var sendList = await _leaveRequestRepository.GetSumSendLeaveAsync(thisYear);
|
var sendList = await _leaveRequestRepository.GetSumSendLeaveAsync(thisYear);
|
||||||
var rejectList = await _leaveRequestRepository.GetSumRejectLeaveAsync(thisYear);
|
var rejectList = await _leaveRequestRepository.GetSumRejectLeaveAsync(thisYear);
|
||||||
var deleteList = await _leaveRequestRepository.GetSumDeleteLeaveAsync(thisYear);
|
var deleteList = await _leaveRequestRepository.GetSumDeleteLeaveAsync(thisYear);
|
||||||
|
|
||||||
var result = new List<dynamic>();
|
|
||||||
var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
var pf = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
||||||
|
|
||||||
if (pf == null)
|
if (pf == null)
|
||||||
{
|
{
|
||||||
throw new Exception(GlobalMessages.DataNotFound);
|
throw new Exception(GlobalMessages.DataNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create dictionaries for fast lookup instead of FirstOrDefault searches
|
||||||
|
var sendDict = sendList.Where(x => x.KeycloakUserId == userId)
|
||||||
|
.ToDictionary(x => x.LeaveTypeId, x => x.SumLeaveDay);
|
||||||
|
var rejectDict = rejectList.Where(x => x.KeycloakUserId == userId)
|
||||||
|
.ToDictionary(x => x.LeaveTypeId, x => x.SumLeaveDay);
|
||||||
|
var deleteDict = deleteList.Where(x => x.KeycloakUserId == userId)
|
||||||
|
.ToDictionary(x => x.LeaveTypeId, x => x.SumLeaveDay);
|
||||||
|
|
||||||
|
// Pre-load all leave beginning data sequentially to avoid DbContext threading issues
|
||||||
|
var leaveBeginningDict = new Dictionary<Guid, LeaveBeginning?>();
|
||||||
foreach (var leaveType in leaveTypes)
|
foreach (var leaveType in leaveTypes)
|
||||||
{
|
{
|
||||||
var sendData = sendList.FirstOrDefault(x => x.KeycloakUserId == userId && x.LeaveTypeId == leaveType.Id);
|
|
||||||
var send = sendData == null ? 0 : sendData.SumLeaveDay;
|
|
||||||
|
|
||||||
var leaveData = await _leaveBeginningRepository.GetByYearAndTypeIdForUser(thisYear, leaveType.Id, pf);
|
var leaveData = await _leaveBeginningRepository.GetByYearAndTypeIdForUser(thisYear, leaveType.Id, pf);
|
||||||
var approve = leaveData == null ? 0 : leaveData.LeaveDaysUsed;
|
leaveBeginningDict[leaveType.Id] = leaveData;
|
||||||
|
}
|
||||||
|
|
||||||
var rejectData = rejectList.FirstOrDefault(x => x.KeycloakUserId == userId && x.LeaveTypeId == leaveType.Id);
|
var result = new List<dynamic>();
|
||||||
var reject = rejectData == null ? 0 : rejectData.SumLeaveDay;
|
|
||||||
|
|
||||||
var deleteData = deleteList.FirstOrDefault(x => x.KeycloakUserId == userId && x.LeaveTypeId == leaveType.Id);
|
foreach (var leaveType in leaveTypes)
|
||||||
var delete = deleteData == null ? 0 : deleteData.SumLeaveDay;
|
{
|
||||||
|
// Use dictionary lookups for better performance
|
||||||
|
var send = sendDict.GetValueOrDefault(leaveType.Id, 0);
|
||||||
|
var reject = rejectDict.GetValueOrDefault(leaveType.Id, 0);
|
||||||
|
var delete = deleteDict.GetValueOrDefault(leaveType.Id, 0);
|
||||||
|
|
||||||
|
leaveBeginningDict.TryGetValue(leaveType.Id, out var leaveData);
|
||||||
|
var approve = leaveData?.LeaveDaysUsed ?? 0;
|
||||||
|
|
||||||
// fix issue : SIT ระบบบันทึกการลา>> สิทธิ์การลา(โอนสิทธิ์การลา) #974
|
// fix issue : SIT ระบบบันทึกการลา>> สิทธิ์การลา(โอนสิทธิ์การลา) #974
|
||||||
|
|
||||||
var extendLeave = 0.0;
|
var extendLeave = 0.0;
|
||||||
var leaveLimit = (double)leaveType.Limit;
|
var leaveLimit = (double)leaveType.Limit;
|
||||||
|
|
||||||
if (leaveType.Code == "LV-005")
|
if (leaveType.Code == "LV-005")
|
||||||
{
|
{
|
||||||
leaveLimit = leaveData == null ? 0.0 : leaveData.LeaveDays;
|
leaveLimit = leaveData?.LeaveDays ?? 0.0;
|
||||||
extendLeave = leaveLimit - 10;
|
extendLeave = leaveLimit - 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue