fix leave
This commit is contained in:
parent
f827ed558c
commit
f0fe68d851
9 changed files with 554 additions and 63 deletions
|
|
@ -1,4 +1,5 @@
|
|||
using BMA.EHR.Application.Repositories;
|
||||
using Amazon.S3.Model;
|
||||
using BMA.EHR.Application.Repositories;
|
||||
using BMA.EHR.Application.Repositories.Commands;
|
||||
using BMA.EHR.Application.Repositories.Leaves.LeaveRequests;
|
||||
using BMA.EHR.Application.Repositories.Leaves.TimeAttendants;
|
||||
|
|
@ -14,10 +15,16 @@ using BMA.EHR.Leave.Service.DTOs.CheckIn;
|
|||
using BMA.EHR.Leave.Service.DTOs.DutyTime;
|
||||
using BMA.EHR.Leave.Service.DTOs.LeaveRequest;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using Org.BouncyCastle.Ocsp;
|
||||
using RabbitMQ.Client;
|
||||
using Serilog;
|
||||
using Swashbuckle.AspNetCore.Annotations;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using SearchProfileResultDto = BMA.EHR.Leave.Service.DTOs.ChangeRound.SearchProfileResultDto;
|
||||
|
||||
namespace BMA.EHR.Leave.Service.Controllers
|
||||
|
|
@ -407,7 +414,6 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
return Success(ret);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// LV1_005 - ลงเวลาเข้า-ออกงาน (USER)
|
||||
/// </summary>
|
||||
|
|
@ -421,6 +427,239 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<ActionResult<ResponseObject>> CheckInAsync([FromForm] CheckTimeDto data)
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
var currentDate = DateTime.Now;
|
||||
var checkFileBytes = new byte[0];
|
||||
|
||||
if (data.Img != null && data.Img.Length == 0)
|
||||
{
|
||||
var formFile = data.Img;
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
await formFile.CopyToAsync(memoryStream);
|
||||
checkFileBytes = memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
var checkData = new CheckTimeDtoRB
|
||||
{
|
||||
UserId = userId,
|
||||
CurrentDate = currentDate,
|
||||
CheckInId = data.CheckInId,
|
||||
Lat = data.Lat,
|
||||
Lon = data.Lon,
|
||||
POI = data.POI,
|
||||
IsLocation = data.IsLocation,
|
||||
LocationName = data.LocationName,
|
||||
Remark = data.Remark,
|
||||
CheckInFileName = data.Img == null ? "no-file" : data.Img.FileName,
|
||||
CheckInFileBytes = checkFileBytes,
|
||||
Token = AccessToken ?? ""
|
||||
};
|
||||
|
||||
// create connection
|
||||
var factory = new ConnectionFactory()
|
||||
{
|
||||
HostName = _configuration["Rabbit:Host"],
|
||||
UserName = _configuration["Rabbit:User"],
|
||||
Password = _configuration["Rabbit:Password"],
|
||||
};
|
||||
|
||||
// create channel
|
||||
using var connection = factory.CreateConnection();
|
||||
using var channel = connection.CreateModel();
|
||||
channel.QueueDeclare(queue: "checkin-queue", durable: false, exclusive: false, autoDelete: false, arguments: null);
|
||||
|
||||
// แปลง Object เป็น JSON สตริง
|
||||
var serializedObject = JsonConvert.SerializeObject(checkData);
|
||||
|
||||
// แปลง JSON สตริงเป็น byte array
|
||||
var body = Encoding.UTF8.GetBytes(serializedObject);
|
||||
|
||||
channel.BasicPublish(exchange: "", routingKey: "checkin-queue", basicProperties: null, body: body);
|
||||
Console.WriteLine($"Send to Queue: {serializedObject}");
|
||||
|
||||
return Success(new { date = currentDate });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check in Processing
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// </returns>
|
||||
/// <response code="200">เมื่อทำรายการสำเร็จ</response>
|
||||
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
|
||||
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
|
||||
[HttpPost("process-check-in"), DisableRequestSizeLimit]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
[AllowAnonymous]
|
||||
public async Task<ActionResult<ResponseObject>> ProcessCheckInAsync([FromBody] CheckTimeDtoRB data)
|
||||
{
|
||||
var userId = data.UserId ?? Guid.Empty;
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, data.Token);
|
||||
|
||||
if (profile == null)
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
|
||||
if (data.CheckInFileName == "no-file") throw new Exception(GlobalMessages.NoFileToUpload);
|
||||
var currentDate = data.CurrentDate ?? DateTime.Now;
|
||||
|
||||
var fileName = $"{_bucketName}/{userId}/{currentDate.ToString("dd-MM-yyyy")}/{data.CheckInFileName}";
|
||||
using (var ms = new MemoryStream(data.CheckInFileBytes ?? new byte[0]))
|
||||
{
|
||||
await _minIOService.UploadFileAsync(fileName, ms);
|
||||
}
|
||||
|
||||
var defaultRound = await _dutyTimeRepository.GetDefaultAsync();
|
||||
if (defaultRound == null)
|
||||
{
|
||||
return Error("ไม่พบรอบการลงเวลาทำงาน Default", StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
var effectiveDate = await _userDutyTimeRepository.GetLastEffectRound(profile.Id);
|
||||
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)
|
||||
{
|
||||
return Error(new Exception("ไม่สามารถลงเวลาได้ เนื่องจากมีการลงเวลาในวันนี้แล้ว!"), StatusCodes.Status400BadRequest);
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
var checkInStatus = DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) >
|
||||
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {duty.StartTimeMorning}") ?
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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 checkOutStatus = DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) <
|
||||
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {duty.EndTimeAfternoon}") ?
|
||||
"ABSENT" :
|
||||
DateTime.Parse(currentDate.ToString("yyyy-MM-dd HH:mm")) <
|
||||
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {duty.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;
|
||||
|
||||
await _processUserTimeStampRepository.UpdateAsync(checkout_process);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Error(new Exception(GlobalMessages.DataNotFound), StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
}
|
||||
var checkInType = data.CheckInId == null ? "check-in" : "check-out";
|
||||
return Success(new { user = $"{profile.FirstName} {profile.LastName}", date = currentDate, type = checkInType }); ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LV1_005 - ลงเวลาเข้า-ออกงาน (USER)
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// </returns>
|
||||
/// <response code="200">เมื่อทำรายการสำเร็จ</response>
|
||||
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
|
||||
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
|
||||
[HttpPost("check-in-old"), DisableRequestSizeLimit]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<ActionResult<ResponseObject>> CheckInOldAsync([FromForm] CheckTimeDto data)
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken);
|
||||
|
|
@ -438,8 +677,6 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
await _minIOService.UploadFileAsync(fileName, ms);
|
||||
}
|
||||
|
||||
|
||||
|
||||
var defaultRound = await _dutyTimeRepository.GetDefaultAsync();
|
||||
if (defaultRound == null)
|
||||
{
|
||||
|
|
@ -490,7 +727,6 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
DateTime.Parse($"{currentDate.ToString("yyyy-MM-dd")} {duty.EndTimeMorning}") ?
|
||||
"ABSENT" :
|
||||
"LATE" :
|
||||
|
||||
"NORMAL";
|
||||
|
||||
// process - รอทำใน queue
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue