Enhance LeaveProcessJobStatusRepository with detailed processing logic and add new methods in UserProfileRepository for fetching officer and employee profiles by RootDnaId

This commit is contained in:
Suphonchai Phoonsawat 2026-03-30 15:53:33 +07:00
parent 3dee5f7166
commit 759a51ab58
3 changed files with 345 additions and 9 deletions

View file

@ -2,7 +2,13 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.Json;
using System.IO;
using BMA.EHR.Application.Common.Interfaces;
using BMA.EHR.Application.Repositories.Leaves.LeaveRequests;
using BMA.EHR.Application.Repositories.MetaData;
using BMA.EHR.Application.Responses.Profiles;
using BMA.EHR.Domain.Extensions;
using BMA.EHR.Domain.Models.Leave.TimeAttendants;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
@ -14,15 +20,35 @@ namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
#region " Fields "
private readonly ILeaveDbContext _dbContext;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly UserProfileRepository _userProfileRepository;
private readonly HolidayRepository _holidayRepository;
private readonly DutyTimeRepository _dutyTimeRepository;
private readonly UserDutyTimeRepository _userDutyTimeRepository;
private readonly ProcessUserTimeStampRepository _processUserTimeStampRepository;
private readonly LeaveRequestRepository _leaveRequestRepository;
#endregion
#region " Constructor and Destructor "
public LeaveProcessJobStatusRepository(ILeaveDbContext dbContext,
IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
IHttpContextAccessor httpContextAccessor,
UserProfileRepository userProfileRepository,
HolidayRepository holidayRepository,
DutyTimeRepository dutyTimeRepository,
UserDutyTimeRepository userDutyTimeRepository,
ProcessUserTimeStampRepository processUserTimeStampRepository,
LeaveRequestRepository leaveRequestRepository) : base(dbContext, httpContextAccessor)
{
_dbContext = dbContext;
_httpContextAccessor = httpContextAccessor;
_userProfileRepository = userProfileRepository;
_holidayRepository = holidayRepository;
_leaveRequestRepository = leaveRequestRepository;
_dutyTimeRepository = dutyTimeRepository;
_userDutyTimeRepository = userDutyTimeRepository;
_processUserTimeStampRepository = processUserTimeStampRepository;
}
#endregion
@ -123,9 +149,214 @@ namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
return job!;
}
public async Task ProcessTaskAsync(Guid id, CancellationToken cancellationToken = default)
public async Task ProcessTaskAsync(Guid rootDnaId, DateTime? startDate, DateTime? endDate)
{
Console.WriteLine($"กำลังประมวลผลงานที่มี RootDnaId: {id}");
var profiles = new List<GetProfileByKeycloakIdRootDto>();
var dateStart = startDate?.Date ?? DateTime.Now.Date;
var dateEnd = endDate?.Date ?? DateTime.Now.Date;
var holidays = await _holidayRepository.GetHolidayAsync(dateStart, dateEnd);
var weekend = _holidayRepository.GetWeekEnd(dateStart, dateEnd);
var excludeDates = holidays.Union(weekend).ToList();
var dateList = new List<LoopDate>();
for (DateTime i = dateStart; i <= dateEnd; i = i.AddDays(1))
{
if (holidays.Contains(i))
{
var d = await _holidayRepository.GetHolidayAsync(i);
dateList.Add(new LoopDate
{
date = i,
isHoliday = true,
isWeekEnd = false,
dateRemark = d
});
}
else if (weekend.Contains(i))
{
dateList.Add(new LoopDate
{
date = i,
isHoliday = true,
isWeekEnd = false,
dateRemark = "วันหยุด"
});
}
else
{
dateList.Add(new LoopDate
{
date = i,
isHoliday = false,
isWeekEnd = false,
dateRemark = ""
});
}
}
var defaultRound = await _dutyTimeRepository.GetDefaultAsync();
if (defaultRound == null)
{
throw new Exception("ไม่พบรอบการลงเวลา Default");
}
var employees = new List<DateResultReport>();
foreach (var dd in dateList.Where(x => !x.isHoliday && !x.isWeekEnd))
{
profiles = await _userProfileRepository.GetAllOfficerByRootDnaId(rootDnaId.ToString(),dd.date);
foreach (var p in profiles)
{
var count = 1;
var keycloakUserId = p.Keycloak ?? Guid.Empty;
var timeStamps = await _processUserTimeStampRepository.GetTimestampByDateAsync(keycloakUserId, dd.date);
var fullName = $"{p.Prefix}{p.FirstName} {p.LastName}";
var effectiveDate = await _userDutyTimeRepository.GetLastEffectRound(p.Id, dd.date);
var roundId = effectiveDate != null ? effectiveDate.DutyTimeId : Guid.Empty;
var userRound = await _dutyTimeRepository.GetByIdAsync(roundId);
var duty = userRound ?? defaultRound;
// check วันลาของแต่ละคน
var leaveReq = await _leaveRequestRepository.GetLeavePeriodAsync(keycloakUserId, dd.date);
var remarkStr = string.Empty;
if (leaveReq != null)
{
switch (leaveReq.Type.Code.ToUpper())
{
case "LV-001":
case "LV-002":
case "LV-005":
remarkStr += leaveReq.Type.Name;
var leaveRange = leaveReq.LeaveRange == null ? "" : leaveReq.LeaveRange.ToUpper();
if (leaveRange == "MORNING")
remarkStr += "ครึ่งวันเช้า";
else if (leaveRange == "AFTERNOON")
remarkStr += "ครึ่งวันบ่าย";
// var leaveRangeEnd = leaveReq.LeaveRangeEnd == null ? "" : leaveReq.LeaveRangeEnd.ToUpper();
// if (leaveRangeEnd == "MORNING")
// remarkStr += "ครึ่งวันเช้า";
// else if (leaveRangeEnd == "AFTERNOON")
// remarkStr += "ครึ่งวันบ่าย";
var leaveRangeEnd = leaveReq.LeaveRangeEnd == null ? "" : leaveReq.LeaveRangeEnd.ToUpper();
if (leaveRange != leaveRangeEnd)
{
if (leaveRangeEnd == "MORNING")
remarkStr += " - ครึ่งวันเช้า";
else if (leaveRangeEnd == "AFTERNOON")
remarkStr += " - ครึ่งวันบ่าย";
}
break;
default:
remarkStr += leaveReq.Type.Name;
break;
}
}
else
{
if (timeStamps == null)
{
if (dd.date <= DateTime.Now.Date)
{
remarkStr = "ขาดราชการ";
if (dd.isHoliday == true)
{
remarkStr = $"วันหยุด ({dd.dateRemark})";
}
else if (dd.isWeekEnd)
{
remarkStr = dd.dateRemark;
}
}
else remarkStr = "";
}
else
{
// check status ของการลงเวลา
if (timeStamps.CheckOut != null)
{
if (timeStamps.CheckOutStatus == "ABSENT")
remarkStr = "ขาดราชการ" + (!timeStamps.IsLocationCheckOut ? $" (นอกสถานที่:{timeStamps.CheckOutLocationName})".Trim() : "");
else if (timeStamps.CheckInStatus == "ABSENT")
remarkStr = "ขาดราชการ" + (!timeStamps.IsLocationCheckIn ? $" (นอกสถานที่:{timeStamps.CheckInLocationName})".Trim() : "");
else if (timeStamps.CheckInStatus == "LATE")
{
remarkStr = "สาย" + (!timeStamps.IsLocationCheckIn ? $" (นอกสถานที่:{timeStamps.CheckInLocationName})".Trim() : "");
//lateTotal += 1;
}
else
remarkStr = !timeStamps.IsLocationCheckIn ? $" นอกสถานที่:{timeStamps.CheckInLocationName}".Trim() : "";
}
else
{
if (timeStamps.CheckInStatus == "ABSENT")
remarkStr = "ขาดราชการ" + (!timeStamps.IsLocationCheckIn ? $" (นอกสถานที่:{timeStamps.CheckInLocationName})".Trim() : "");
else if (timeStamps.CheckInStatus == "LATE")
{
remarkStr = "สาย" + (!timeStamps.IsLocationCheckIn ? $" (นอกสถานที่:{timeStamps.CheckInLocationName})".Trim() : "");
//lateTotal += 1;
}
else
remarkStr = !timeStamps.IsLocationCheckIn ? $" นอกสถานที่:{timeStamps.CheckInLocationName}".Trim() : "";
}
}
}
var emp = new DateResultReport
{
no = count,
fullName = fullName,
dutyTimeName = $"{duty.StartTimeMorning} - {duty.EndTimeAfternoon} น.",
checkInLocation = timeStamps == null ? "" : timeStamps.CheckInPOI,
checkInTime = timeStamps == null ? "" : $"{timeStamps.CheckIn.ToString("HH:mm")} น.",
checkOutLocation = timeStamps == null ? "" : timeStamps.CheckOutPOI ?? "",
checkOutTime = timeStamps == null ? "" :
timeStamps.CheckOut != null ?
$"{timeStamps.CheckOut.Value.ToString("HH:mm")} น." :
"",
remark = remarkStr,
checkInDate = timeStamps == null ? dd.date.Date.ToThaiFullDate2() : timeStamps.CheckIn.Date.ToThaiFullDate2(),
checkedOutDate = timeStamps == null ? dd.date.Date.ToThaiFullDate2() :
timeStamps.CheckOut != null ?
timeStamps.CheckOut.Value.ToThaiFullDate2() :
"",
checkInTimeRaw = timeStamps == null ? dd.date.Date : timeStamps?.CheckIn,
checkOutTimeRaw = timeStamps == null ? dd.date.Date : timeStamps?.CheckOut != null ? timeStamps?.CheckOut : null,
};
employees.Add(emp);
count++;
}
// Write employees to JSON file
var fileName = $"employees_{DateTime.Now:yyyyMMdd_HHmmss}.txt";
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Exports", fileName);
// Ensure directory exists
var directory = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
var jsonOptions = new JsonSerializerOptions
{
WriteIndented = true,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
var jsonContent = JsonSerializer.Serialize(employees, jsonOptions);
await File.WriteAllTextAsync(filePath, jsonContent);
}
}
public async Task ProcessPendingJobsAsync()
@ -142,7 +373,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
await UpdateToProcessingAsync(job.Id);
// ทำงานที่ต้องการที่นี่ (เช่น เรียก API, ประมวลผลข้อมูล ฯลฯ)
await ProcessTaskAsync(job.RootDnaId);
await ProcessTaskAsync(job.RootDnaId,job.StartDate, job.EndDate);
// อัปเดตสถานะเป็น Completed
await UpdateToCompletedAsync(job.Id);
@ -157,4 +388,33 @@ namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
#endregion
}
class LoopDate
{
public DateTime date { get; set; }
public bool isHoliday { get; set; }
public bool isWeekEnd { get; set; }
public string dateRemark { get; set; }
}
class DateResultReport
{
public int no { get; set; }
public string fullName { get; set; }
public string dutyTimeName { get; set; }
public string checkInLocation { get; set; }
public string checkInTime { get; set; }
public string checkOutLocation { get; set; }
public string checkOutTime { get; set; }
public string remark { get; set; }
public string checkInDate { get; set; }
public string checkedOutDate { get; set; }
public DateTime? checkInTimeRaw { get; set; }
public DateTime? checkOutTimeRaw { get; set; }
}
}

View file

@ -764,6 +764,75 @@ namespace BMA.EHR.Application.Repositories
}
}
public async Task<List<GetProfileByKeycloakIdRootDto>> GetAllOfficerByRootDnaId(string? rootDnaId, DateTime date)
{
try
{
var apiPath = $"{_configuration["API"]}/org/unauthorize/officer-list";
var apiKey = _configuration["API_KEY"];
var body = new
{
reqNode = 0,
reqNodeId = rootDnaId,
date = date
};
//Console.WriteLine(body);
var profiles = new List<SearchProfileDto>();
var apiResult = await PostExternalAPIAsync(apiPath, "", body, apiKey);
if (apiResult != null)
{
var raw = JsonConvert.DeserializeObject<GetListProfileByKeycloakIdRootResultDto>(apiResult);
if (raw != null)
return raw.Result;
else
return new List<GetProfileByKeycloakIdRootDto>();
}
else
return new List<GetProfileByKeycloakIdRootDto>();
}
catch
{
throw;
}
}
public async Task<List<GetProfileByKeycloakIdRootDto>> GetAllEmployeeByRootDnaId(string? rootDnaId, DateTime date)
{
try
{
var apiPath = $"{_configuration["API"]}/org/unauthorize/employee-list";
var apiKey = _configuration["API_KEY"];
var body = new
{
reqNode = 0,
reqNodeId = rootDnaId,
startDate = date,
endDate = date
};
//Console.WriteLine(body);
var profiles = new List<SearchProfileDto>();
var apiResult = await PostExternalAPIAsync(apiPath, "", body, apiKey);
if (apiResult != null)
{
var raw = JsonConvert.DeserializeObject<GetListProfileByKeycloakIdRootResultDto>(apiResult);
if (raw != null)
return raw.Result;
else
return new List<GetProfileByKeycloakIdRootDto>();
}
else
return new List<GetProfileByKeycloakIdRootDto>();
}
catch
{
throw;
}
}
public async Task<List<GetProfileByKeycloakIdRootDto>> GetProfileByAdminRolev4(string? accessToken, int? node, string? nodeId, string role, string? revisionId, int? reqNode, string? reqNodeId, DateTime? startDate, DateTime? endDate)
{
try

View file

@ -31,10 +31,11 @@
//"DisciplineConnection": "server=hrms.chin.in.th;user=root;password=ey2qVVyyqGYw8CyA7h8X72559r2Ad84K;port=53636;database=hrms_discipline;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;"
},
"Jwt": {
//"Key": "j7C9RO_p4nRtuwCH4z9Db_A_6We42tkD_p4lZtDrezc",
//"Issuer": "https://hrms-id.chin.in.th/realms/hrms"
"Key": "HP-FnQMUj9msHMSD3T9HtdEnphAKoCJLEl85CIqROFI",
"Issuer": "https://id.frappet.synology.me/realms/hrms"
//"Key": "HP-FnQMUj9msHMSD3T9HtdEnphAKoCJLEl85CIqROFI",
"Key": "j7C9RO_p4nRtuwCH4z9Db_A_6We42tkD_p4lZtDrezc",
"Issuer": "https://hrmsbkk-id.case-collection.com/realms/hrms"
//"Key": "xY2VR-EFvvNPsMs39u8ooVBWQL6mPwrNJOh3koJFTgU",
//"Issuer": "https://hrms-id.bangkok.go.th/realms/hrms"
},
"EPPlus": {
"ExcelPackage": {
@ -55,11 +56,17 @@
"Node": {
"API": "https://bma-ehr.frappet.synology.me/api/v1/probation"
},
"API": "https://bma-ehr.frappet.synology.me/api/v1",
"RabbitMQ": {
"URL": "localhost",
"UserName": "frappet",
"Password": "FPTadmin2357"
},
"Domain": "https://hrmsbkk.case-collection.com",
"APIPROBATION": "https://hrmsbkk.case-collection.com/api/v1/probation",
"API": "https://hrmsbkk.case-collection.com/api/v1",
"APIV2": "https://hrmsbkk.case-collection.com/api/v2",
"VITE_URL_MGT": "https://hrmsbkk-mgt.case-collection.com",
//"API": "https://bma-ehr.frappet.synology.me/api/v1",
//"API": "https://bma-hrms.bangkok.go.th/api/v1",
"API_KEY": "fKRL16yyEgbyTEJdsMw2h64tGSCmkW685PRtM3CygzX1JOSdptT9UJtpgWwKM8FybRTJups3GTFwj27ZRvlPdIkv3XgCoVJaD5LmR06ozuEPvCCRSdp2WFthg08V5xHc56fTPfZLpr1VmXrhd6dvYhHIqKkQUJR02Rlkss11cLRWEQOssEFVA4xdu2J5DIRO1EM5m7wRRvEwcDB4mYRXD9HH52SMq6iYqUWEWsMwLdbk7QW9yYESUEuzMW5gWrb6vIeWZxJV5bTz1PcWUyR7eO9Fyw1F5DiQYc9JgzTC1mW7cv31fEtTtrfbJYKIb5EbWilqIEUKC6A0UKBDDek35ML0006cqRVm0pvdOH6jeq7VQyYrhdXe59dBEyhYGUIfozoVBvW7Up4QBuOMjyPjSqJPlMBKwaseptfrblxQV1AOOivSBpf1ZcQyOZ8JktRtKUDSuXsmG0lsXwFlI3JCeSHdpVdgZWFYcJPegqfrB6KotR02t9AVkpLs1ZWrixwz"
}