Increase HttpClient timeout for long-running operations
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 1m21s

This commit is contained in:
Suphonchai Phoonsawat 2026-01-30 09:49:54 +07:00
parent 06b53ddeaa
commit 5c05f1123a
2 changed files with 259 additions and 246 deletions

View file

@ -948,93 +948,114 @@ namespace BMA.EHR.Leave.Service.Controllers
var fileName = $"{_bucketName}/{userId}/{currentDate.ToString("dd-MM-yyyy")}/{check_status}/{data.CheckInFileName}";
using (var ms = new MemoryStream(data.CheckInFileBytes ?? new byte[0]))
{
await _minIOService.UploadFileAsync(fileName, ms);
try
{
await _minIOService.UploadFileAsync(fileName, ms);
}
catch (Exception ex)
{
await _checkInJobStatusRepository.UpdateToFailedAsync(taskId, $"ไม่สามารถอัปโหลดรูปภาพได้: {ex.Message}");
return Error($"ไม่สามารถอัปโหลดรูปภาพได้: {ex.Message}", StatusCodes.Status500InternalServerError);
}
}
var defaultRound = await _dutyTimeRepository.GetDefaultAsync();
if (defaultRound == null)
{
return Error("ไม่พบรอบการลงเวลาทำงาน Default", StatusCodes.Status404NotFound);
}
var effectiveDate = await _userDutyTimeRepository.GetLastEffectRound(profile.Id, currentDate);
var roundId = effectiveDate != null ? effectiveDate.DutyTimeId : Guid.Empty;
var userRound = await _dutyTimeRepository.GetByIdAsync(roundId);
// TODO : รอดุึงรอบที่ผูกกับ user
var duty = userRound ?? defaultRound;
// create check in object
if (data.CheckInId == null)
{
// validate duplicate check in
var currentCheckIn = await _userTimeStampRepository.GetTimestampByDateAsync(userId, currentDate);
if (currentCheckIn != null)
var defaultRound = await _dutyTimeRepository.GetDefaultAsync();
if (defaultRound == null)
{
return Error(new Exception("ไม่สามารถลงเวลาได้ เนื่องจากมีการลงเวลาในวันนี้แล้ว!"), StatusCodes.Status400BadRequest);
await _checkInJobStatusRepository.UpdateToFailedAsync(taskId, "ไม่พบรอบการลงเวลาทำงาน Default");
return Error("ไม่พบรอบการลงเวลาทำงาน Default", StatusCodes.Status404NotFound);
}
var checkin = new UserTimeStamp
var effectiveDate = await _userDutyTimeRepository.GetLastEffectRound(profile.Id, currentDate);
var roundId = effectiveDate != null ? effectiveDate.DutyTimeId : Guid.Empty;
var userRound = await _dutyTimeRepository.GetByIdAsync(roundId);
// TODO : รอดุึงรอบที่ผูกกับ user
var duty = userRound ?? defaultRound;
// create check in object
if (data.CheckInId == null)
{
KeycloakUserId = userId,
CheckInLat = data.Lat,
CheckInLon = data.Lon,
IsLocationCheckIn = data.IsLocation,
CheckInLocationName = data.LocationName,
CheckInPOI = data.POI,
CheckInRemark = data.Remark,
CheckInImageUrl = fileName,
CheckIn = currentDate,
Prefix = profile.Prefix,
FirstName = profile.FirstName,
LastName = profile.LastName,
CitizenId = profile.CitizenId,
// validate duplicate check in
var currentCheckIn = await _userTimeStampRepository.GetTimestampByDateAsync(userId, currentDate);
Root = profile.Root,
Child1 = profile.Child1,
Child2 = profile.Child2,
Child3 = profile.Child3,
Child4 = profile.Child4,
if (currentCheckIn != null)
{
return Error(new Exception("ไม่สามารถลงเวลาได้ เนื่องจากมีการลงเวลาในวันนี้แล้ว!"), StatusCodes.Status400BadRequest);
}
RootId = profile.RootId,
Child1Id = profile.Child1Id,
Child2Id = profile.Child2Id,
Child3Id = profile.Child3Id,
Child4Id = profile.Child4Id,
Gender = profile.Gender,
var checkin = new UserTimeStamp
{
KeycloakUserId = userId,
CheckInLat = data.Lat,
CheckInLon = data.Lon,
IsLocationCheckIn = data.IsLocation,
CheckInLocationName = data.LocationName,
CheckInPOI = data.POI,
CheckInRemark = data.Remark,
CheckInImageUrl = fileName,
CheckIn = currentDate,
Prefix = profile.Prefix,
FirstName = profile.FirstName,
LastName = profile.LastName,
CitizenId = profile.CitizenId,
ProfileId = profile.Id,
ProfileType = profile.ProfileType,
Root = profile.Root,
Child1 = profile.Child1,
Child2 = profile.Child2,
Child3 = profile.Child3,
Child4 = profile.Child4,
RootDnaId = profile.RootDnaId,
Child1DnaId = profile.Child1DnaId,
Child2DnaId = profile.Child2DnaId,
Child3DnaId = profile.Child3DnaId,
Child4DnaId = profile.Child4DnaId,
};
RootId = profile.RootId,
Child1Id = profile.Child1Id,
Child2Id = profile.Child2Id,
Child3Id = profile.Child3Id,
Child4Id = profile.Child4Id,
Gender = profile.Gender,
var startTime = "";
var endTime = "";
if (!data.IsLocation && data.LocationName == "ไปประชุม / อบรม / สัมมนา")
{
//startTime = "09:30";
startTime = "10:30";
endTime = "12:00";
}
else
{
startTime = duty.StartTimeMorning;
endTime = duty.EndTimeMorning;
}
ProfileId = profile.Id,
ProfileType = profile.ProfileType,
string checkInStatus = "NORMAL";
var leaveReq = await _leaveRequestRepository.GetLeavePeriodAsync(userId, currentDate.Date);
if (leaveReq != null)
{
var leaveRange = leaveReq.LeaveRange == null ? "" : leaveReq.LeaveRange.ToUpper();
if (leaveRange == "MORNING" || leaveRange == "ALL")
checkInStatus = "NORMAL";
RootDnaId = profile.RootDnaId,
Child1DnaId = profile.Child1DnaId,
Child2DnaId = profile.Child2DnaId,
Child3DnaId = profile.Child3DnaId,
Child4DnaId = profile.Child4DnaId,
};
var startTime = "";
var endTime = "";
if (!data.IsLocation && data.LocationName == "ไปประชุม / อบรม / สัมมนา")
{
//startTime = "09:30";
startTime = "10:30";
endTime = "12:00";
}
else
{
startTime = duty.StartTimeMorning;
endTime = duty.EndTimeMorning;
}
string checkInStatus = "NORMAL";
var leaveReq = await _leaveRequestRepository.GetLeavePeriodAsync(userId, currentDate.Date);
if (leaveReq != null)
{
var leaveRange = leaveReq.LeaveRange == null ? "" : leaveReq.LeaveRange.ToUpper();
if (leaveRange == "MORNING" || leaveRange == "ALL")
checkInStatus = "NORMAL";
else
{
checkInStatus = DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) >
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {startTime}") ?
DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) >
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {duty.EndTimeMorning}") ?
"ABSENT" :
"LATE" :
"NORMAL";
}
}
else
{
checkInStatus = DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) >
@ -1045,123 +1066,127 @@ namespace BMA.EHR.Leave.Service.Controllers
"LATE" :
"NORMAL";
}
}
else
{
checkInStatus = DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) >
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {startTime}") ?
DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) >
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {duty.EndTimeMorning}") ?
"ABSENT" :
"LATE" :
"NORMAL";
}
// process - รอทำใน queue
var checkin_process = new ProcessUserTimeStamp
{
KeycloakUserId = userId,
CheckInLat = data.Lat,
CheckInLon = data.Lon,
IsLocationCheckIn = data.IsLocation,
CheckInLocationName = data.LocationName,
CheckInPOI = data.POI,
CheckInRemark = data.Remark,
CheckInImageUrl = fileName,
CheckIn = currentDate,
CheckInStatus = checkInStatus,
Prefix = profile.Prefix,
FirstName = profile.FirstName,
LastName = profile.LastName,
CitizenId = profile.CitizenId,
Root = profile.Root,
Child1 = profile.Child1,
Child2 = profile.Child2,
Child3 = profile.Child3,
Child4 = profile.Child4,
RootId = profile.RootId,
Child1Id = profile.Child1Id,
Child2Id = profile.Child2Id,
Child3Id = profile.Child3Id,
Child4Id = profile.Child4Id,
Gender = profile.Gender,
ProfileId = profile.Id,
ProfileType = profile.ProfileType,
RootDnaId = profile.RootDnaId,
Child1DnaId = profile.Child1DnaId,
Child2DnaId = profile.Child2DnaId,
Child3DnaId = profile.Child3DnaId,
Child4DnaId = profile.Child4DnaId,
};
await _userTimeStampRepository.AddAsync(checkin);
await _processUserTimeStampRepository.AddAsync(checkin_process);
}
else
{
var checkout = await _userTimeStampRepository.GetByIdAsync(data.CheckInId.Value);
var currentCheckInProcess = await _processUserTimeStampRepository.GetTimestampByDateAsync(userId, checkout.CheckIn.Date);
var checkout_process = await _processUserTimeStampRepository.GetByIdAsync(currentCheckInProcess.Id);
if (checkout != null)
{
checkout.CheckOutLat = data.Lat;
checkout.CheckOutLon = data.Lon;
checkout.IsLocationCheckOut = data.IsLocation;
checkout.CheckOutLocationName = data.LocationName;
checkout.CheckOutPOI = data.POI;
checkout.CheckOutRemark = data.Remark;
checkout.CheckOutImageUrl = fileName;
checkout.CheckOut = currentDate;
await _userTimeStampRepository.UpdateAsync(checkout);
}
else
{
return Error(new Exception(GlobalMessages.DataNotFound), StatusCodes.Status404NotFound);
}
var endTime = "";
var startTime = "";
var endTimeMorning = "";
if (!data.IsLocation && data.LocationName == "ไปประชุม / อบรม / สัมมนา")
{
startTime = "13:00";
endTime = "14:30";
endTimeMorning = "12:00";
}
else
{
endTime = duty.EndTimeAfternoon;
startTime = duty.StartTimeAfternoon;
endTimeMorning = duty.EndTimeMorning;
}
string checkOutStatus = "NORMAL";
var leaveReq = await _leaveRequestRepository.GetLeavePeriodAsync(userId, currentDate.Date);
if (leaveReq != null)
{
var leaveRange = leaveReq.LeaveRangeEnd == null ? "" : leaveReq.LeaveRangeEnd.ToUpper();
if (leaveRange == "AFTERNOON" || leaveRange == "ALL")
// process - รอทำใน queue
var checkin_process = new ProcessUserTimeStamp
{
if(DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) <
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {endTimeMorning}"))
checkOutStatus = "ABSENT";
else
checkOutStatus = "NORMAL";
KeycloakUserId = userId,
CheckInLat = data.Lat,
CheckInLon = data.Lon,
IsLocationCheckIn = data.IsLocation,
CheckInLocationName = data.LocationName,
CheckInPOI = data.POI,
CheckInRemark = data.Remark,
CheckInImageUrl = fileName,
CheckIn = currentDate,
CheckInStatus = checkInStatus,
Prefix = profile.Prefix,
FirstName = profile.FirstName,
LastName = profile.LastName,
CitizenId = profile.CitizenId,
Root = profile.Root,
Child1 = profile.Child1,
Child2 = profile.Child2,
Child3 = profile.Child3,
Child4 = profile.Child4,
RootId = profile.RootId,
Child1Id = profile.Child1Id,
Child2Id = profile.Child2Id,
Child3Id = profile.Child3Id,
Child4Id = profile.Child4Id,
Gender = profile.Gender,
ProfileId = profile.Id,
ProfileType = profile.ProfileType,
RootDnaId = profile.RootDnaId,
Child1DnaId = profile.Child1DnaId,
Child2DnaId = profile.Child2DnaId,
Child3DnaId = profile.Child3DnaId,
Child4DnaId = profile.Child4DnaId,
};
await _userTimeStampRepository.AddAsync(checkin);
await _processUserTimeStampRepository.AddAsync(checkin_process);
}
else
{
var checkout = await _userTimeStampRepository.GetByIdAsync(data.CheckInId.Value);
var currentCheckInProcess = await _processUserTimeStampRepository.GetTimestampByDateAsync(userId, checkout.CheckIn.Date);
var checkout_process = await _processUserTimeStampRepository.GetByIdAsync(currentCheckInProcess.Id);
if (checkout != null)
{
checkout.CheckOutLat = data.Lat;
checkout.CheckOutLon = data.Lon;
checkout.IsLocationCheckOut = data.IsLocation;
checkout.CheckOutLocationName = data.LocationName;
checkout.CheckOutPOI = data.POI;
checkout.CheckOutRemark = data.Remark;
checkout.CheckOutImageUrl = fileName;
checkout.CheckOut = currentDate;
await _userTimeStampRepository.UpdateAsync(checkout);
}
else
{
await _checkInJobStatusRepository.UpdateToFailedAsync(taskId, "ไม่พบข้อมูลการลงเวลาทำงาน");
return Error(new Exception(GlobalMessages.DataNotFound), StatusCodes.Status404NotFound);
}
var endTime = "";
var startTime = "";
var endTimeMorning = "";
if (!data.IsLocation && data.LocationName == "ไปประชุม / อบรม / สัมมนา")
{
startTime = "13:00";
endTime = "14:30";
endTimeMorning = "12:00";
}
else
{
endTime = duty.EndTimeAfternoon;
startTime = duty.StartTimeAfternoon;
endTimeMorning = duty.EndTimeMorning;
}
string checkOutStatus = "NORMAL";
var leaveReq = await _leaveRequestRepository.GetLeavePeriodAsync(userId, currentDate.Date);
if (leaveReq != null)
{
var leaveRange = leaveReq.LeaveRangeEnd == null ? "" : leaveReq.LeaveRangeEnd.ToUpper();
if (leaveRange == "AFTERNOON" || leaveRange == "ALL")
{
if(DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) <
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {endTimeMorning}"))
checkOutStatus = "ABSENT";
else
checkOutStatus = "NORMAL";
}
else
{
// fix issue : SIT ระบบบันทึกเวลาปฏิบัติงาน>>ลงเวลาเข้า-ออกงาน (กรณีลงเวลาออกอีกวัน) #921
checkOutStatus = DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) <
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {duty.EndTimeAfternoon}") ?
// "ABSENT" :
checkout.CheckIn.Date < currentDate.Date ? "NORMAL" :
DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) >=
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {endTime}") ?
"NORMAL" :
"ABSENT" :
DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) <
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {endTimeMorning}") ?
"ABSENT" :
"NORMAL";
}
}
else
{
// fix issue : SIT ระบบบันทึกเวลาปฏิบัติงาน>>ลงเวลาเข้า-ออกงาน (กรณีลงเวลาออกอีกวัน) #921
checkOutStatus = DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) <
@ -1176,71 +1201,55 @@ namespace BMA.EHR.Leave.Service.Controllers
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {endTimeMorning}") ?
"ABSENT" :
"NORMAL";
}
}
else
{
// fix issue : SIT ระบบบันทึกเวลาปฏิบัติงาน>>ลงเวลาเข้า-ออกงาน (กรณีลงเวลาออกอีกวัน) #921
checkOutStatus = DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) <
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {duty.EndTimeAfternoon}") ?
// "ABSENT" :
checkout.CheckIn.Date < currentDate.Date ? "NORMAL" :
DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) >=
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {endTime}") ?
"NORMAL" :
"ABSENT" :
DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) <
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {endTimeMorning}") ?
"ABSENT" :
"NORMAL";
}
}
if (checkout_process != null)
{
checkout_process.CheckOutLat = data.Lat;
checkout_process.CheckOutLon = data.Lon;
checkout_process.IsLocationCheckOut = data.IsLocation;
checkout_process.CheckOutLocationName = data.LocationName;
checkout_process.CheckOutPOI = data.POI;
checkout_process.CheckOutRemark = data.Remark;
checkout_process.CheckOutImageUrl = fileName;
checkout_process.CheckOut = currentDate;
checkout_process.CheckOutStatus = checkOutStatus;
if (checkout_process != null)
{
checkout_process.CheckOutLat = data.Lat;
checkout_process.CheckOutLon = data.Lon;
checkout_process.IsLocationCheckOut = data.IsLocation;
checkout_process.CheckOutLocationName = data.LocationName;
checkout_process.CheckOutPOI = data.POI;
checkout_process.CheckOutRemark = data.Remark;
checkout_process.CheckOutImageUrl = fileName;
checkout_process.CheckOut = currentDate;
checkout_process.CheckOutStatus = checkOutStatus;
await _processUserTimeStampRepository.UpdateAsync(checkout_process);
}
else
{
await _checkInJobStatusRepository.UpdateToFailedAsync(taskId, "ไม่พบข้อมูลการประมวลผลเวลาทำงาน");
return Error(new Exception(GlobalMessages.DataNotFound), StatusCodes.Status404NotFound);
}
await _processUserTimeStampRepository.UpdateAsync(checkout_process);
}
else
{
return Error(new Exception(GlobalMessages.DataNotFound), StatusCodes.Status404NotFound);
}
}
// อัปเดตสถานะเป็น COMPLETED
if (taskId != Guid.Empty)
{
var additionalData = JsonConvert.SerializeObject(new
// อัปเดตสถานะเป็น COMPLETED
if (taskId != Guid.Empty)
{
CheckInType = data.CheckInId == null ? "check-in" : "check-out",
FileName = fileName,
ProcessedDate = currentDate
});
await _checkInJobStatusRepository.UpdateToCompletedAsync(taskId, additionalData);
}
var additionalData = JsonConvert.SerializeObject(new
{
CheckInType = data.CheckInId == null ? "check-in" : "check-out",
FileName = fileName,
ProcessedDate = currentDate
});
await _checkInJobStatusRepository.UpdateToCompletedAsync(taskId, additionalData);
}
var checkInType = data.CheckInId == null ? "check-in" : "check-out";
return Success(new { user = $"{profile.FirstName} {profile.LastName}", date = currentDate, type = checkInType }); ;
}
catch (Exception ex)
{
// อัปเดตสถานะเป็น FAILED
if (taskId != Guid.Empty)
{
await _checkInJobStatusRepository.UpdateToFailedAsync(taskId, ex.Message);
var checkInType = data.CheckInId == null ? "check-in" : "check-out";
return Success(new { user = $"{profile.FirstName} {profile.LastName}", date = currentDate, type = checkInType }); ;
}
catch (Exception ex)
{
// อัปเดตสถานะเป็น FAILED
if (taskId != Guid.Empty)
{
await _checkInJobStatusRepository.UpdateToFailedAsync(taskId, ex.Message);
}
throw;
}
throw;
}
}
/// <summary>
/// LV1_005 - ลงเวลาเข้า-ออกงาน (USER)