diff --git a/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveRequestRepository.cs b/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveRequestRepository.cs index cb3820c4..8b828b00 100644 --- a/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveRequestRepository.cs +++ b/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveRequestRepository.cs @@ -74,6 +74,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests { var data = await _dbContext.Set().AsQueryable() //.AsNoTracking() + .Include(x => x.Approvers) .Include(x => x.LeaveDocument) .ThenInclude(x => x.Document) .Include(x => x.LeaveDraftDocument) @@ -88,6 +89,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests { var data = await _dbContext.Set().AsQueryable() .AsNoTracking() + .Include(x => x.Approvers) .Include(x => x.LeaveDocument) .ThenInclude(x => x.Document) .Include(x => x.LeaveDraftDocument) @@ -508,6 +510,10 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests public async Task CommanderApproveLeaveRequest(Guid id, string reason) { + // Get UserId from token + var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); + + var rawData = await GetByIdAsync(id); if (rawData == null) { @@ -516,18 +522,117 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests if (rawData.ApproveStep != "st2") { - throw new Exception("คำขอนี้ยังไม่ได้รับการอนุมัติจากเจ้าหน้าที่ ไม่สามารถทำรายการได้"); + throw new Exception("คำขอนี้ยังไม่ได้อยู่ในขั้นตอนที่สามารถอนุมัติได้ ไม่สามารถทำรายการได้"); } - rawData.LeaveStatus = "PENDING"; - rawData.LeaveComment = reason; - rawData.ApproveStep = "st3"; + // check commander approve + var approvers = rawData.Approvers.Where(x => x.ApproveType!.ToUpper() == "COMMANDER").OrderBy(x => x.Seq).ToList(); + var maxSeq = approvers.Max(x => x.Seq); + + var approver = approvers.FirstOrDefault(x => x.KeycloakId == userId); + if (approver == null) + { + throw new Exception("คุณไม่มีสิทธิ์อนุมัติการลาในขั้นตอนนี้"); + } + + approver.ApproveStatus = "APPROVE"; + approver.Comment = reason; + + if (approver.Seq != maxSeq) + { + + + var nextApprover = approvers.FirstOrDefault(x => x.Seq == approver.Seq + 1); + // Send Noti + var noti = new Notification + { + Body = $"การขอลาของคุณ {rawData.FirstName} {rawData.LastName} รอรับการอนุมัติจากคุณ", + ReceiverUserId = nextApprover!.ProfileId, + Type = "", + Payload = "", + }; + _appDbContext.Set().Add(noti); + await _appDbContext.SaveChangesAsync(); + + rawData.LeaveStatus = "PENDING"; + await UpdateAsync(rawData); + } + else + { + rawData.LeaveStatus = "PENDING"; + rawData.LeaveComment = reason; + rawData.ApproveStep = "st3"; + + await UpdateAsync(rawData); + } + + } + + public async Task CommanderRejectLeaveRequest(Guid id, string reason) + { + // Get UserId from token + var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); + + + var rawData = await GetByIdAsync(id); + if (rawData == null) + { + throw new Exception(GlobalMessages.DataNotFound); + } + + if (rawData.ApproveStep != "st2") + { + throw new Exception("คำขอนี้ยังไม่ได้อยู่ในขั้นตอนที่สามารถอนุมัติได้ ไม่สามารถทำรายการได้"); + } + + // check commander approve + var approvers = rawData.Approvers.Where(x => x.ApproveType!.ToUpper() == "COMMANDER").OrderBy(x => x.Seq).ToList(); + var maxSeq = approvers.Max(x => x.Seq); + + var approver = approvers.FirstOrDefault(x => x.KeycloakId == userId); + if (approver == null) + { + throw new Exception("คุณไม่มีสิทธิ์อนุมัติการลาในขั้นตอนนี้"); + } + + approver.ApproveStatus = "REJECT"; + approver.Comment = reason; + + if (approver.Seq != maxSeq) + { + + + var nextApprover = approvers.FirstOrDefault(x => x.Seq == approver.Seq + 1); + // Send Noti + var noti = new Notification + { + Body = $"การขอลาของคุณ {rawData.FirstName} {rawData.LastName} รอรับการอนุมัติจากคุณ", + ReceiverUserId = nextApprover!.ProfileId, + Type = "", + Payload = "", + }; + _appDbContext.Set().Add(noti); + await _appDbContext.SaveChangesAsync(); + + rawData.LeaveStatus = "PENDING"; + await UpdateAsync(rawData); + } + else + { + rawData.LeaveStatus = "PENDING"; + rawData.LeaveComment = reason; + rawData.ApproveStep = "st3"; + + await UpdateAsync(rawData); + } - await UpdateAsync(rawData); } public async Task ApproveLeaveRequest(Guid id, string reason) { + // Get UserId from token + var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); + var rawData = await GetByIdAsync(id); if (rawData == null) { @@ -536,107 +641,125 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests if (rawData.ApproveStep != "st3") { - throw new Exception("คำขอนี้ยังไม่ได้รับการอนุมัติจากผู้บังคับบัญชา ไม่สามารถทำรายการได้"); + throw new Exception("คำขอนี้ยังไม่ได้อยู่ในขั้นตอนที่สามารถอนุมัติได้ ไม่สามารถทำรายการได้"); } - var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken); - if (profile == null) + // check commander approve + var approvers = rawData.Approvers.Where(x => x.ApproveType!.ToUpper() == "APPROVER").OrderBy(x => x.Seq).ToList(); + var maxSeq = approvers.Max(x => x.Seq); + + var approver = approvers.FirstOrDefault(x => x.KeycloakId == userId); + if (approver == null) { - throw new Exception(GlobalMessages.DataNotFound); + throw new Exception("คุณไม่มีสิทธิ์อนุมัติการลาในขั้นตอนนี้"); } - rawData.LeaveStatus = "APPROVE"; - rawData.LeaveDirectorComment = reason; - rawData.ApproveStep = "st4"; + approver.ApproveStatus = "APPROVE"; + approver.Comment = reason; - await UpdateAsync(rawData); - - //var leaveType = await _appDbContext.Set() - // .FirstOrDefaultAsync(x => x.Name == rawData.Type.Name); - - - // insert to profile leave - // var profileLeave = new ProfileLeave - // { - // DateStartLeave = rawData.LeaveStartDate, - // DateEndLeave = rawData.LeaveEndDate, - - // TotalLeave = rawData.LeaveTotal, - // Status = "approve", - // Reason = rawData.LeaveDetail, - - // ProfileId = profile.Id, // change from profile object to id - // TypeLeave = leaveType - // }; - // _appDbContext.Set().Add(profileLeave); - var _baseAPI = _configuration["API"]; - var apiUrlSalary = string.Empty; - if (profile.ProfileType == "OFFICER") + if (approver.Seq != maxSeq) { - apiUrlSalary = $"{_baseAPI}/org/profile/leave"; - using (var client = new HttpClient()) + var nextApprover = approvers.FirstOrDefault(x => x.Seq == approver.Seq + 1); + // Send Noti + var noti1 = new Notification { - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", "")); - client.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]); - var _res = await client.PostAsJsonAsync(apiUrlSalary, new - { - profileId = profile.Id, - leaveTypeId = rawData?.Type?.Id ?? null, - dateLeaveStart = rawData.LeaveStartDate, - dateLeaveEnd = rawData.LeaveEndDate, - totalLeave = 0,//หน้า fe ไม่ได้ใช้ - leaveCount = 0,//หน้า fe ไม่ได้ใช้ - leaveDays = rawData.LeaveTotal, - status = "approve", - reason = rawData.LeaveDetail, - }); - // var _result = await _res.Content.ReadAsStringAsync(); - } - } - else if (profile.ProfileType == "EMPLOYEE") - { - apiUrlSalary = $"{_baseAPI}/org/profile-employee/leave"; - using (var client = new HttpClient()) - { - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", "")); - client.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]); - var _res = await client.PostAsJsonAsync(apiUrlSalary, new - { - profileEmployeeId = profile.Id, - leaveTypeId = rawData?.Type?.Id ?? null, - dateLeaveStart = rawData.LeaveStartDate, - dateLeaveEnd = rawData.LeaveEndDate, - totalLeave = 0, - leaveCount = 0, - leaveDays = rawData.LeaveTotal, - status = "approve", - reason = rawData.LeaveDetail, - }); - } + Body = $"การขอลาของคุณ {rawData.FirstName} {rawData.LastName} รอรับการอนุมัติจากคุณ", + ReceiverUserId = nextApprover!.ProfileId, + Type = "", + Payload = "", + }; + _appDbContext.Set().Add(noti1); + await _appDbContext.SaveChangesAsync(); + + await UpdateAsync(rawData); } else { - throw new Exception("ไม่สามารถทำรายการได้"); + var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken); + if (profile == null) + { + throw new Exception(GlobalMessages.DataNotFound); + } + + rawData.LeaveStatus = "APPROVE"; + rawData.LeaveDirectorComment = reason; + rawData.ApproveStep = "st4"; + + await UpdateAsync(rawData); + + var _baseAPI = _configuration["API"]; + var apiUrlSalary = string.Empty; + if (profile.ProfileType == "OFFICER") + { + apiUrlSalary = $"{_baseAPI}/org/profile/leave"; + using (var client = new HttpClient()) + { + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", "")); + client.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]); + var _res = await client.PostAsJsonAsync(apiUrlSalary, new + { + profileId = profile.Id, + leaveTypeId = rawData?.Type?.Id ?? null, + dateLeaveStart = rawData.LeaveStartDate, + dateLeaveEnd = rawData.LeaveEndDate, + totalLeave = 0,//หน้า fe ไม่ได้ใช้ + leaveCount = 0,//หน้า fe ไม่ได้ใช้ + leaveDays = rawData.LeaveTotal, + status = "approve", + reason = rawData.LeaveDetail, + }); + // var _result = await _res.Content.ReadAsStringAsync(); + } + } + else if (profile.ProfileType == "EMPLOYEE") + { + apiUrlSalary = $"{_baseAPI}/org/profile-employee/leave"; + using (var client = new HttpClient()) + { + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", "")); + client.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]); + var _res = await client.PostAsJsonAsync(apiUrlSalary, new + { + profileEmployeeId = profile.Id, + leaveTypeId = rawData?.Type?.Id ?? null, + dateLeaveStart = rawData.LeaveStartDate, + dateLeaveEnd = rawData.LeaveEndDate, + totalLeave = 0, + leaveCount = 0, + leaveDays = rawData.LeaveTotal, + status = "approve", + reason = rawData.LeaveDetail, + }); + } + } + else + { + throw new Exception("ไม่สามารถทำรายการได้"); + } + await _appDbContext.SaveChangesAsync(); + + // insert to process timestamp + + + // Send Noti + var noti = new Notification + { + Body = $"การขอลาของคุณได้รับการอนุมัติ", + ReceiverUserId = profile.Id, + Type = "", + Payload = "", + }; + _appDbContext.Set().Add(noti); + await _appDbContext.SaveChangesAsync(); } - await _appDbContext.SaveChangesAsync(); - // insert to process timestamp - - - // Send Noti - var noti = new Notification - { - Body = $"การขอลาของคุณได้รับการอนุมัติ", - ReceiverUserId = profile.Id, - Type = "", - Payload = "", - }; - _appDbContext.Set().Add(noti); - await _appDbContext.SaveChangesAsync(); } public async Task RejectLeaveRequest(Guid id, string reason) { + // Get UserId from token + var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); + var rawData = await GetByIdAsync(id); if (rawData == null) { @@ -645,31 +768,63 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests if (rawData.ApproveStep != "st3") { - throw new Exception("คำขอนี้ยังไม่ได้รับการอนุมัติจากผู้บังคับบัญชา ไม่สามารถทำรายการได้"); + throw new Exception("คำขอนี้ยังไม่ได้อยู่ในขั้นตอนที่สามารถอนุมัติได้ ไม่สามารถทำรายการได้"); } - var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken); - if (profile == null) + // check commander approve + var approvers = rawData.Approvers.Where(x => x.ApproveType!.ToUpper() == "APPROVER").OrderBy(x => x.Seq).ToList(); + var maxSeq = approvers.Max(x => x.Seq); + + var approver = approvers.FirstOrDefault(x => x.KeycloakId == userId); + if (approver == null) { - throw new Exception(GlobalMessages.DataNotFound); + throw new Exception("คุณไม่มีสิทธิ์อนุมัติการลาในขั้นตอนนี้"); } - rawData.LeaveStatus = "REJECT"; - rawData.LeaveDirectorComment = reason; - rawData.ApproveStep = "st5"; + approver.ApproveStatus = "REJECT"; + approver.Comment = reason; - await UpdateAsync(rawData); - - // Send Noti - var noti = new Notification + if (approver.Seq != maxSeq) { - Body = $"การขอลาของคุณไม่ได้รับการอนุมัติ \r\nเนื่องจาก{reason}", - ReceiverUserId = profile.Id, - Type = "", - Payload = "", - }; - _appDbContext.Set().Add(noti); - await _appDbContext.SaveChangesAsync(); + var nextApprover = approvers.FirstOrDefault(x => x.Seq == approver.Seq + 1); + // Send Noti + var noti1 = new Notification + { + Body = $"การขอลาของคุณ {rawData.FirstName} {rawData.LastName} รอรับการอนุมัติจากคุณ", + ReceiverUserId = nextApprover!.ProfileId, + Type = "", + Payload = "", + }; + _appDbContext.Set().Add(noti1); + await _appDbContext.SaveChangesAsync(); + + await UpdateAsync(rawData); + } + else + { + var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken); + if (profile == null) + { + throw new Exception(GlobalMessages.DataNotFound); + } + + rawData.LeaveStatus = "REJECT"; + rawData.LeaveDirectorComment = reason; + rawData.ApproveStep = "st5"; + + await UpdateAsync(rawData); + + // Send Noti + var noti = new Notification + { + Body = $"การขอลาของคุณไม่ได้รับการอนุมัติ \r\nเนื่องจาก{reason}", + ReceiverUserId = profile.Id, + Type = "", + Payload = "", + }; + _appDbContext.Set().Add(noti); + await _appDbContext.SaveChangesAsync(); + } } public async Task> GetSumSendLeaveAsync(int year) diff --git a/BMA.EHR.Domain/Models/Leave/Requests/LeaveRequestApprover.cs b/BMA.EHR.Domain/Models/Leave/Requests/LeaveRequestApprover.cs index 88e86dd7..11b1b719 100644 --- a/BMA.EHR.Domain/Models/Leave/Requests/LeaveRequestApprover.cs +++ b/BMA.EHR.Domain/Models/Leave/Requests/LeaveRequestApprover.cs @@ -23,5 +23,7 @@ namespace BMA.EHR.Domain.Models.Leave.Requests public string ApproveStatus { get; set; } = string.Empty; public string Comment { get; set; } = string.Empty; + + public string? ApproveType { get; set; } = string.Empty; // ผู้บังคับบัญชา = commander, ผู้มีอำนาจอนุมัติ = Approver } } diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20250422065634_Add Approver Type.Designer.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20250422065634_Add Approver Type.Designer.cs new file mode 100644 index 00000000..8e5e5319 --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20250422065634_Add Approver Type.Designer.cs @@ -0,0 +1,1481 @@ +// +using System; +using BMA.EHR.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace BMA.EHR.Infrastructure.Migrations.LeaveDb +{ + [DbContext(typeof(LeaveDbContext))] + [Migration("20250422065634_Add Approver Type")] + partial class AddApproverType + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Documents.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Detail") + .IsRequired() + .HasColumnType("text"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("FileSize") + .HasColumnType("int"); + + b.Property("FileType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ObjectRefId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("Document"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.Commons.LeaveType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รหัสประเภทการลา"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("Limit") + .HasColumnType("int") + .HasComment("จำนวนวันลาสูงสุดประจำปี"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อประเภทการลา"); + + b.HasKey("Id"); + + b.ToTable("LeaveTypes"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.Requests.LeaveBeginning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("LeaveDays") + .HasColumnType("double") + .HasComment("จำนวนวันลา"); + + b.Property("LeaveTypeId") + .HasColumnType("char(36)") + .HasComment("รหัสประเภทการลา"); + + b.Property("LeaveYear") + .HasColumnType("int") + .HasComment("ปีงบประมาณ"); + + b.Property("ProfileId") + .HasColumnType("char(36)") + .HasComment("รหัส Profile ในระบบทะเบียนประวัติ"); + + b.HasKey("Id"); + + b.HasIndex("LeaveTypeId"); + + b.ToTable("LeaveBeginnings"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.Requests.LeaveDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("DocumentId") + .HasColumnType("char(36)"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("LeaveRequestId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("LeaveRequestId"); + + b.ToTable("LeaveDocuments"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.Requests.LeaveRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("AbsentDayAt") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("AbsentDayGetIn") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("AbsentDayLocation") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("AbsentDayRegistorDate") + .HasColumnType("datetime(6)"); + + b.Property("AbsentDaySummon") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Amount") + .HasColumnType("double"); + + b.Property("ApproveStep") + .HasColumnType("longtext") + .HasComment("step การอนุมัติ st1 = จทน.อนุมัตื,st2 = ผู้บังคับบัญชา อนุมัติ "); + + b.Property("BirthDate") + .HasColumnType("datetime(6)"); + + b.Property("CancelLeaveWrote") + .HasColumnType("longtext") + .HasComment("เขียนที่ (ขอยกเลิก)"); + + b.Property("Child1") + .HasColumnType("longtext"); + + b.Property("Child1Id") + .HasColumnType("char(36)"); + + b.Property("Child2") + .HasColumnType("longtext"); + + b.Property("Child2Id") + .HasColumnType("char(36)"); + + b.Property("Child3") + .HasColumnType("longtext"); + + b.Property("Child3Id") + .HasColumnType("char(36)"); + + b.Property("Child4") + .HasColumnType("longtext"); + + b.Property("Child4Id") + .HasColumnType("char(36)"); + + b.Property("CitizenId") + .HasColumnType("longtext"); + + b.Property("CommanderPosition") + .HasColumnType("longtext"); + + b.Property("CoupleDayCountryHistory") + .HasColumnType("longtext"); + + b.Property("CoupleDayEndDateHistory") + .HasColumnType("datetime(6)"); + + b.Property("CoupleDayLevel") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CoupleDayLevelCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CoupleDayName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CoupleDayPosition") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CoupleDayStartDateHistory") + .HasColumnType("datetime(6)"); + + b.Property("CoupleDaySumTotalHistory") + .HasColumnType("longtext"); + + b.Property("CoupleDayTotalHistory") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("DateAppoint") + .HasColumnType("datetime(6)"); + + b.Property("Dear") + .HasColumnType("longtext") + .HasComment("เรียนใคร"); + + b.Property("FirstName") + .HasColumnType("longtext"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("HajjDayStatus") + .HasColumnType("tinyint(1)"); + + b.Property("KeycloakUserId") + .HasColumnType("char(36)"); + + b.Property("LastName") + .HasColumnType("longtext"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("LeaveAddress") + .IsRequired() + .HasColumnType("longtext") + .HasComment("สถานที่ติดต่อขณะลา"); + + b.Property("LeaveBirthDate") + .HasColumnType("datetime(6)"); + + b.Property("LeaveCancelComment") + .HasColumnType("longtext") + .HasComment("เหตุผลในการขอยกเลิก"); + + b.Property("LeaveCancelDocumentId") + .HasColumnType("char(36)"); + + b.Property("LeaveCancelStatus") + .HasColumnType("longtext") + .HasComment("สถานะของคำขอยกเลิก"); + + b.Property("LeaveComment") + .HasColumnType("longtext") + .HasComment("ความเห็นของผู้บังคับบัญชา"); + + b.Property("LeaveDetail") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รายละเอียดการลา"); + + b.Property("LeaveDirectorComment") + .HasColumnType("longtext") + .HasComment("ความเห็นของผู้อำนวยการสำนัก"); + + b.Property("LeaveDraftDocumentId") + .HasColumnType("char(36)"); + + b.Property("LeaveEndDate") + .HasColumnType("datetime(6)") + .HasComment("วัน เดือน ปีสิ้นสุดลา"); + + b.Property("LeaveGovernmentDate") + .HasColumnType("datetime(6)"); + + b.Property("LeaveLast") + .HasColumnType("datetime(6)"); + + b.Property("LeaveNumber") + .IsRequired() + .HasColumnType("longtext") + .HasComment("หมายเลขที่ติดต่อขณะลา"); + + b.Property("LeaveRange") + .HasColumnType("longtext") + .HasComment("ช่วงของการลาของวันเริ่ม เช่น ลาทั้งวัน ครึ่งวันเช้า ครึ่งวันบ่าย"); + + b.Property("LeaveRangeEnd") + .HasColumnType("longtext") + .HasComment("ช่วงของการลาของวันสิ้นสุด เช่น ลาทั้งวัน ครึ่งวันเช้า ครึ่งวันบ่าย"); + + b.Property("LeaveSalary") + .HasColumnType("int"); + + b.Property("LeaveSalaryText") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LeaveStartDate") + .HasColumnType("datetime(6)") + .HasComment("วัน เดือน ปีเริ่มต้นลา"); + + b.Property("LeaveStatus") + .IsRequired() + .HasColumnType("longtext") + .HasComment("สถานะของคำร้อง"); + + b.Property("LeaveSubTypeName") + .HasColumnType("longtext"); + + b.Property("LeaveTotal") + .HasColumnType("double"); + + b.Property("LeaveTypeCode") + .HasColumnType("longtext") + .HasComment("code ของประเภทการลา"); + + b.Property("LeaveWrote") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เขียนที่"); + + b.Property("OrdainDayBuddhistLentAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OrdainDayBuddhistLentName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OrdainDayLocationAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OrdainDayLocationName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OrdainDayLocationNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OrdainDayOrdination") + .HasColumnType("datetime(6)"); + + b.Property("OrdainDayStatus") + .HasColumnType("tinyint(1)"); + + b.Property("OrganizationName") + .HasColumnType("longtext") + .HasComment("สังกัดผู้ยื่นขอ"); + + b.Property("PositionLevelName") + .HasColumnType("longtext") + .HasComment("ระดับผู้ยื่นขอ"); + + b.Property("PositionName") + .HasColumnType("longtext") + .HasComment("ตำแหน่งผู้ยื่นขอ"); + + b.Property("Prefix") + .HasColumnType("longtext"); + + b.Property("ProfileId") + .HasColumnType("char(36)"); + + b.Property("ProfileType") + .HasColumnType("longtext"); + + b.Property("RestDayCurrentTotal") + .HasColumnType("double"); + + b.Property("RestDayOldTotal") + .HasColumnType("double"); + + b.Property("Root") + .HasColumnType("longtext"); + + b.Property("RootId") + .HasColumnType("char(36)"); + + b.Property("StudyDayCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StudyDayDegreeLevel") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StudyDayScholarship") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StudyDaySubject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StudyDayTrainingName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StudyDayTrainingSubject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StudyDayUniversityName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TypeId") + .HasColumnType("char(36)"); + + b.Property("WifeDayDateBorn") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("WifeDayName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("LeaveCancelDocumentId"); + + b.HasIndex("LeaveDraftDocumentId"); + + b.HasIndex("TypeId"); + + b.ToTable("LeaveRequests"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.Requests.LeaveRequestApprover", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("ApproveStatus") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ApproveType") + .HasColumnType("longtext"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("KeycloakId") + .HasColumnType("char(36)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("LeaveRequestId") + .HasColumnType("char(36)"); + + b.Property("PositionName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Prefix") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProfileId") + .HasColumnType("char(36)"); + + b.Property("Seq") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("LeaveRequestId"); + + b.ToTable("LeaveRequestApprovers"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.AdditionalCheckRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CheckDate") + .HasColumnType("datetime(6)") + .HasComment("*วันที่ลงเวลา"); + + b.Property("CheckInEdit") + .HasColumnType("tinyint(1)") + .HasComment("*ขอลงเวลาช่วงเช้า"); + + b.Property("CheckOutEdit") + .HasColumnType("tinyint(1)") + .HasComment("*ขอลงเวลาช่วงบ่าย"); + + b.Property("Comment") + .HasColumnType("longtext") + .HasComment("หมายเหตุในการการอนุมัติ/ไม่อนุมัติ"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext") + .HasComment("*หมายเหตุขอลงเวลาพิเศษ"); + + b.Property("FirstName") + .HasColumnType("longtext"); + + b.Property("KeycloakUserId") + .HasColumnType("char(36)") + .HasComment("รหัส User ของ Keycloak ที่ร้องขอ"); + + b.Property("LastName") + .HasColumnType("longtext"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("Prefix") + .HasColumnType("longtext"); + + b.Property("Status") + .IsRequired() + .HasColumnType("longtext") + .HasComment("สถานะการอนุมัติ"); + + b.HasKey("Id"); + + b.ToTable("AdditionalCheckRequests"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.DutyTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext") + .HasComment("คำอธิบาย"); + + b.Property("EndTimeAfternoon") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาออกงานช่วงบ่าย"); + + b.Property("EndTimeMorning") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาออกงานช่วงเช้า"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)") + .HasComment("สถานะการเปิดใช้งาน (เปิด/ปิด)"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)") + .HasComment("สถานะว่ารอบใดเป็นค่า Default ของข้าราชการ (สำหรับทุกคนที่ยังไม่ได้ทำการเลือกรอบ)"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("StartTimeAfternoon") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาเข้างานช่วงบ่าย"); + + b.Property("StartTimeMorning") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาเข้างานช่วงเช้า"); + + b.HasKey("Id"); + + b.ToTable("DutyTimes"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.ProcessUserTimeStamp", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CheckIn") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา เข้างาน"); + + b.Property("CheckInImageUrl") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รูปถ่ายสถานที่ Check-In"); + + b.Property("CheckInLat") + .HasColumnType("double") + .HasComment("พิกัดละติจูด Check-In"); + + b.Property("CheckInLocationName") + .HasColumnType("longtext") + .HasComment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-In"); + + b.Property("CheckInLon") + .HasColumnType("double") + .HasComment("พิกัดลองจิจูด Check-In"); + + b.Property("CheckInPOI") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-In"); + + b.Property("CheckInRemark") + .HasColumnType("longtext") + .HasComment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-In"); + + b.Property("CheckInStatus") + .IsRequired() + .HasColumnType("longtext") + .HasComment("สถานะ Check-In"); + + b.Property("CheckOut") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา ออกงาน"); + + b.Property("CheckOutImageUrl") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รูปถ่ายสถานที่ Check-Out"); + + b.Property("CheckOutLat") + .HasColumnType("double") + .HasComment("พิกัดละติจูด Check-Out"); + + b.Property("CheckOutLocationName") + .HasColumnType("longtext") + .HasComment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-Out"); + + b.Property("CheckOutLon") + .HasColumnType("double") + .HasComment("พิกัดลองจิจูด Check-Out"); + + b.Property("CheckOutPOI") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-Out"); + + b.Property("CheckOutRemark") + .HasColumnType("longtext") + .HasComment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-Out"); + + b.Property("CheckOutStatus") + .HasColumnType("longtext") + .HasComment("สถานะ Check-Out"); + + b.Property("Child1") + .HasColumnType("longtext"); + + b.Property("Child1Id") + .HasColumnType("char(36)"); + + b.Property("Child2") + .HasColumnType("longtext"); + + b.Property("Child2Id") + .HasColumnType("char(36)"); + + b.Property("Child3") + .HasColumnType("longtext"); + + b.Property("Child3Id") + .HasColumnType("char(36)"); + + b.Property("Child4") + .HasColumnType("longtext"); + + b.Property("Child4Id") + .HasColumnType("char(36)"); + + b.Property("CitizenId") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("EditReason") + .HasColumnType("longtext") + .HasComment("เหตุผลการอนุมัติ/ไม่อนุมัติขอลงเวลาพิเศษ"); + + b.Property("EditStatus") + .HasColumnType("longtext") + .HasComment("สถานะการของลงเวลาพิเศษ"); + + b.Property("FirstName") + .HasColumnType("longtext"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("IsLocationCheckIn") + .HasColumnType("tinyint(1)") + .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-In"); + + b.Property("IsLocationCheckOut") + .HasColumnType("tinyint(1)") + .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-Out"); + + b.Property("IsProcess") + .HasColumnType("tinyint(1)") + .HasComment("นำไปประมวลผลแล้วหรือยัง"); + + b.Property("KeycloakUserId") + .HasColumnType("char(36)") + .HasComment("รหัส User ของ Keycloak"); + + b.Property("LastName") + .HasColumnType("longtext"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("Prefix") + .HasColumnType("longtext"); + + b.Property("ProfileId") + .HasColumnType("char(36)"); + + b.Property("ProfileType") + .HasColumnType("longtext"); + + b.Property("Root") + .HasColumnType("longtext"); + + b.Property("RootId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("ProcessUserTimeStamps"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.UserCalendar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("Calendar") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ปฏิทินการทำงานของ ขรก ปกติ หรือ 6 วันต่อสัปดาห์"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("ProfileId") + .HasColumnType("char(36)") + .HasComment("รหัส Profile ในระบบทะเบียนประวัติ"); + + b.HasKey("Id"); + + b.ToTable("UserCalendars"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.UserDutyTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("DutyTimeId") + .HasColumnType("char(36)") + .HasComment("รหัสรอบการลงเวลา"); + + b.Property("EffectiveDate") + .HasColumnType("datetime(6)") + .HasComment("วันที่มีผล"); + + b.Property("IsProcess") + .HasColumnType("tinyint(1)") + .HasComment("ทำการประมวลผลแล้วหรือยัง"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("ProfileId") + .HasColumnType("char(36)") + .HasComment("รหัส Profile ในระบบทะเบียนประวัติ"); + + b.Property("Remark") + .HasColumnType("longtext") + .HasComment("หมายเหตุ"); + + b.HasKey("Id"); + + b.HasIndex("DutyTimeId"); + + b.ToTable("UserDutyTimes"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.UserTimeStamp", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CheckIn") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา เข้างาน"); + + b.Property("CheckInImageUrl") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รูปถ่ายสถานที่ Check-In"); + + b.Property("CheckInLat") + .HasColumnType("double") + .HasComment("พิกัดละติจูด Check-In"); + + b.Property("CheckInLocationName") + .HasColumnType("longtext") + .HasComment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-In"); + + b.Property("CheckInLon") + .HasColumnType("double") + .HasComment("พิกัดลองจิจูด Check-In"); + + b.Property("CheckInPOI") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-In"); + + b.Property("CheckInRemark") + .HasColumnType("longtext") + .HasComment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-In"); + + b.Property("CheckOut") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา ออกงาน"); + + b.Property("CheckOutImageUrl") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รูปถ่ายสถานที่ Check-Out"); + + b.Property("CheckOutLat") + .HasColumnType("double") + .HasComment("พิกัดละติจูด Check-Out"); + + b.Property("CheckOutLocationName") + .HasColumnType("longtext") + .HasComment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-Out"); + + b.Property("CheckOutLon") + .HasColumnType("double") + .HasComment("พิกัดลองจิจูด Check-Out"); + + b.Property("CheckOutPOI") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-Out"); + + b.Property("CheckOutRemark") + .HasColumnType("longtext") + .HasComment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-Out"); + + b.Property("Child1") + .HasColumnType("longtext"); + + b.Property("Child1Id") + .HasColumnType("char(36)"); + + b.Property("Child2") + .HasColumnType("longtext"); + + b.Property("Child2Id") + .HasColumnType("char(36)"); + + b.Property("Child3") + .HasColumnType("longtext"); + + b.Property("Child3Id") + .HasColumnType("char(36)"); + + b.Property("Child4") + .HasColumnType("longtext"); + + b.Property("Child4Id") + .HasColumnType("char(36)"); + + b.Property("CitizenId") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("FirstName") + .HasColumnType("longtext"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("IsLocationCheckIn") + .HasColumnType("tinyint(1)") + .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-In"); + + b.Property("IsLocationCheckOut") + .HasColumnType("tinyint(1)") + .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-Out"); + + b.Property("IsProcess") + .HasColumnType("tinyint(1)") + .HasComment("นำไปประมวลผลแล้วหรือยัง"); + + b.Property("KeycloakUserId") + .HasColumnType("char(36)") + .HasComment("รหัส User ของ Keycloak"); + + b.Property("LastName") + .HasColumnType("longtext"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("Prefix") + .HasColumnType("longtext"); + + b.Property("ProfileId") + .HasColumnType("char(36)"); + + b.Property("ProfileType") + .HasColumnType("longtext"); + + b.Property("Root") + .HasColumnType("longtext"); + + b.Property("RootId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("UserTimeStamps"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.Requests.LeaveBeginning", b => + { + b.HasOne("BMA.EHR.Domain.Models.Leave.Commons.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.Requests.LeaveDocument", b => + { + b.HasOne("BMA.EHR.Domain.Models.Documents.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BMA.EHR.Domain.Models.Leave.Requests.LeaveRequest", "LeaveRequest") + .WithMany("LeaveDocument") + .HasForeignKey("LeaveRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("LeaveRequest"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.Requests.LeaveRequest", b => + { + b.HasOne("BMA.EHR.Domain.Models.Documents.Document", "LeaveCancelDocument") + .WithMany() + .HasForeignKey("LeaveCancelDocumentId"); + + b.HasOne("BMA.EHR.Domain.Models.Documents.Document", "LeaveDraftDocument") + .WithMany() + .HasForeignKey("LeaveDraftDocumentId"); + + b.HasOne("BMA.EHR.Domain.Models.Leave.Commons.LeaveType", "Type") + .WithMany() + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LeaveCancelDocument"); + + b.Navigation("LeaveDraftDocument"); + + b.Navigation("Type"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.Requests.LeaveRequestApprover", b => + { + b.HasOne("BMA.EHR.Domain.Models.Leave.Requests.LeaveRequest", "LeaveRequest") + .WithMany("Approvers") + .HasForeignKey("LeaveRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LeaveRequest"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.UserDutyTime", b => + { + b.HasOne("BMA.EHR.Domain.Models.Leave.TimeAttendants.DutyTime", "DutyTime") + .WithMany() + .HasForeignKey("DutyTimeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DutyTime"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.Requests.LeaveRequest", b => + { + b.Navigation("Approvers"); + + b.Navigation("LeaveDocument"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20250422065634_Add Approver Type.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20250422065634_Add Approver Type.cs new file mode 100644 index 00000000..a3241003 --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20250422065634_Add Approver Type.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BMA.EHR.Infrastructure.Migrations.LeaveDb +{ + /// + public partial class AddApproverType : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ApproveType", + table: "LeaveRequestApprovers", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ApproveType", + table: "LeaveRequestApprovers"); + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs index c0baddfa..fc298018 100644 --- a/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs @@ -625,6 +625,9 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb .IsRequired() .HasColumnType("longtext"); + b.Property("ApproveType") + .HasColumnType("longtext"); + b.Property("Comment") .IsRequired() .HasColumnType("longtext"); diff --git a/BMA.EHR.Leave/Controllers/LeaveReportController.cs b/BMA.EHR.Leave/Controllers/LeaveReportController.cs index 8b387472..a8a2a0d0 100644 --- a/BMA.EHR.Leave/Controllers/LeaveReportController.cs +++ b/BMA.EHR.Leave/Controllers/LeaveReportController.cs @@ -3,6 +3,7 @@ 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.MetaData; +using BMA.EHR.Application.Responses.Profiles; using BMA.EHR.Domain.Common; using BMA.EHR.Domain.Extensions; using BMA.EHR.Domain.Models.Leave.Requests; @@ -10,13 +11,15 @@ using BMA.EHR.Domain.Shared; using BMA.EHR.Leave.Service.DTOs.Reports; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Newtonsoft.Json.Linq; +using Microsoft.OpenApi.Any; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Ocsp; +using Sentry; using Swashbuckle.AspNetCore.Annotations; using System.Globalization; using System.Security.Claims; -using BMA.EHR.Application.Responses.Profiles; -using Microsoft.OpenApi.Any; namespace BMA.EHR.Leave.Service.Controllers { @@ -228,12 +231,17 @@ namespace BMA.EHR.Leave.Service.Controllers private async Task GetReport03(LeaveRequest data) { + + + var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(data.KeycloakUserId, AccessToken); if (profile == null) { return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); } + + var fullName = $"{profile!.Prefix}{profile!.FirstName} {profile!.LastName}"; //var rootOc = _userProfileRepository.GetRootOcId(profile.OcId ?? Guid.Empty, AccessToken); @@ -247,6 +255,46 @@ namespace BMA.EHR.Leave.Service.Controllers var sumLeave = await _leaveRequestRepository.GetSumApproveLeaveByTypeForUserAsync(data.KeycloakUserId, data.Type.Id, data.LeaveStartDate.Year); + //var userCalendar = await _userCalendarRepository.GetExist(profile.Id); + //var category = userCalendar == null ? "NORMAL" : userCalendar.Calendar; + + //var sumWorkDay = await _holidayRepository.GetHolidayCountAsync(data.LeaveStartDate.Date, data.LeaveEndDate.Date, category); + + //var sumWeekend = _holidayRepository.GetWeekEndCount(data.LeaveStartDate.Date, data.LeaveEndDate.Date, category); + + + + var extendLeave = 0.0; + var leaveLimit = data.Type.Limit; + + var approvePrevYear = await _leaveRequestRepository.GetSumApproveLeaveAsync(data.LeaveStartDate.Year - 1); + + if (data.Type.Code == "LV-005") + { + var apprvPrevData = approvePrevYear.FirstOrDefault(x => x.KeycloakUserId == data.KeycloakUserId && x.LeaveTypeId == data.Type.Id); + var apprvPrev = apprvPrevData == null ? 0 : apprvPrevData.SumLeaveDay; + + //var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(data.KeycloakUserId, AccessToken); + var govAge = (profile?.DateStart?.Date ?? DateTime.Now.Date).DiffDay(DateTime.Now.Date); + + if (govAge >= 180) + { + if (govAge >= 3650) + { + // ถ้าอายุราชการเกิน 10 ปี ได้บวกเพิ่มอีก 10 วัน + extendLeave = 30 - apprvPrev; // หายอดวันลาที่เหลือของปีก่อน + if (extendLeave >= 20) extendLeave = 20; + } + else + { + extendLeave = 20 - apprvPrev; // หายอดวันลาที่เหลือของปีก่อน + if (extendLeave >= 10) extendLeave = 10; + } + } + else + leaveLimit = 0; + } + return new { template = "leave11", @@ -263,17 +311,21 @@ namespace BMA.EHR.Leave.Service.Controllers positionLeaveName = profile!.PositionLeaveName == null ? "-" : profile!.PositionLeaveName.ToThaiNumber(), organizationName = profile!.Oc!.ToThaiNumber() ?? "", - restDayOldTotal = data.RestDayOldTotal.ToString().ToThaiNumber(), - restDayCurrentTotal = data.RestDayCurrentTotal.ToString().ToThaiNumber(), + restDayOldTotal = extendLeave.ToString().ToThaiNumber(), + restDayCurrentTotal = leaveLimit.ToString().ToThaiNumber(), + + //restDayOldTotal = data.RestDayOldTotal.ToString().ToThaiNumber(), + //restDayCurrentTotal = data.RestDayCurrentTotal.ToString().ToThaiNumber(), leaveDateStart = data.LeaveStartDate.Date.ToThaiShortDate().ToThaiNumber(), leaveDateEnd = data.LeaveEndDate.Date.ToThaiShortDate().ToThaiNumber(), - LeaveTotal = data.LeaveStartDate.DiffDay(data.LeaveEndDate).ToString().ToThaiNumber(), + leaveTotal = data.LeaveTotal.ToString().ToThaiNumber(), + //LeaveTotal = data.LeaveStartDate.DiffDay(data.LeaveEndDate).ToString().ToThaiNumber(), leaveAddress = data.LeaveAddress.ToThaiNumber(), leaveNumber = data.LeaveNumber.ToThaiNumber(), LeaveSummary = sumLeave.ToString().ToThaiNumber(), - LeaveRemain = (data.Type.Limit - sumLeave).ToString().ToThaiNumber(), + LeaveRemain = (data.Type.Limit + extendLeave - sumLeave).ToString().ToThaiNumber(), } }; } @@ -1258,6 +1310,13 @@ namespace BMA.EHR.Leave.Service.Controllers remarkStr += "ครึ่งวันเช้า"; else if (leaveRange == "AFTERNOON") remarkStr += "ครึ่งวันบ่าย"; + + + var leaveRangeEnd = leaveReq.LeaveRangeEnd == null ? "" : leaveReq.LeaveRangeEnd.ToUpper(); + if (leaveRangeEnd == "MORNING") + remarkStr += "ครึ่งวันเช้า"; + else if (leaveRangeEnd == "AFTERNOON") + remarkStr += "ครึ่งวันบ่าย"; break; default: remarkStr += leaveReq.Type.Name; diff --git a/BMA.EHR.Leave/Controllers/LeaveRequestController.cs b/BMA.EHR.Leave/Controllers/LeaveRequestController.cs index 03cd8833..75264540 100644 --- a/BMA.EHR.Leave/Controllers/LeaveRequestController.cs +++ b/BMA.EHR.Leave/Controllers/LeaveRequestController.cs @@ -12,10 +12,12 @@ using BMA.EHR.Infrastructure.Persistence; using BMA.EHR.Leave.Service.DTOs.LeaveRequest; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Org.BouncyCastle.Asn1.Pkcs; +using Sentry; using Swashbuckle.AspNetCore.Annotations; using System.Net.Http.Headers; using System.Security.Claims; @@ -111,6 +113,57 @@ namespace BMA.EHR.Leave.Service.Controllers #region " Methods " + /// + /// เพิ่มรายชิื่อผู้อนุมัติ หรือ ผู้บังคับบัญชา + /// + /// + /// + /// เมื่อทำรายการสำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPost("officer/add-approver/{type}/{id:guid}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> AddApprover(string type, Guid id, [FromBody] List req) + { + try + { + var leaveReq = await _leaveRequestRepository.GetByIdAsync(id); + if (leaveReq == null) + { + return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); + } + + var delete = leaveReq.Approvers.RemoveAll(x => x.ApproveType == type.Trim().ToUpper()); + + foreach (var r in req) + { + leaveReq.Approvers.Add(new LeaveRequestApprover + { + Seq = r.Seq, + Prefix = r.Prefix, + FirstName = r.FirstName, + LastName = r.LastName, + PositionName = r.PositionName, + ProfileId = r.ProfileId, + KeycloakId = r.KeycloakId, + ApproveStatus = "PENDING", + ApproveType = type.Trim().ToUpper() + }); + } + + await _leaveRequestRepository.UpdateAsync(leaveReq); + + return Success(); + + } + catch (Exception ex) + { + return Error(ex); + } + } + /// /// LV2_001 - สร้างคำขอการลา (USER) /// @@ -174,6 +227,7 @@ namespace BMA.EHR.Leave.Service.Controllers LeaveSubTypeName = req.LeaveSubTypeName, LeaveRange = req.LeaveRange, + LeaveRangeEnd = req.LeaveRangeEnd, LeaveStartDate = req.LeaveStartDate, LeaveEndDate = req.LeaveEndDate, LeaveWrote = req.LeaveWrote ?? "", @@ -367,30 +421,30 @@ namespace BMA.EHR.Leave.Service.Controllers leaveRequest.PositionLevelName = profile.PosLevel == null ? "" : profile.PosLevel; leaveRequest.OrganizationName = userOc; - if (req.Approvers != null && req.Approvers != "") - { - //var jsonString = System.Text.Json.JsonSerializer.Deserialize(req.Approvers ?? ""); - //var fixedJson = req.Approvers.Replace("\\\"", "\""); - var approvers = JsonConvert.DeserializeObject>(req.Approvers); - if (approver != null) - { - foreach (var r in approvers!) - { - leaveRequest.Approvers.Add(new LeaveRequestApprover - { - Seq = r.Seq, - Prefix = r.Prefix, - FirstName = r.FirstName, - LastName = r.LastName, - PositionName = r.PositionName, - ProfileId = r.ProfileId, - KeycloakId = r.KeycloakId, - ApproveStatus = "PENDING", - }); - } - } + //if (req.Approvers != null && req.Approvers != "") + //{ + // //var jsonString = System.Text.Json.JsonSerializer.Deserialize(req.Approvers ?? ""); + // //var fixedJson = req.Approvers.Replace("\\\"", "\""); + // var approvers = JsonConvert.DeserializeObject>(req.Approvers); + // if (approver != null) + // { + // foreach (var r in approvers!) + // { + // leaveRequest.Approvers.Add(new LeaveRequestApprover + // { + // Seq = r.Seq, + // Prefix = r.Prefix, + // FirstName = r.FirstName, + // LastName = r.LastName, + // PositionName = r.PositionName, + // ProfileId = r.ProfileId, + // KeycloakId = r.KeycloakId, + // ApproveStatus = "PENDING", + // }); + // } + // } - } + //} // save to database @@ -493,6 +547,7 @@ namespace BMA.EHR.Leave.Service.Controllers // ลองใช้ oldData oldData.LeaveRange = req.LeaveRange; + oldData.LeaveRangeEnd = req.LeaveRangeEnd; oldData.LeaveStartDate = req.LeaveStartDate; oldData.LeaveEndDate = req.LeaveEndDate; oldData.LeaveWrote = req.LeaveWrote ?? ""; @@ -1328,7 +1383,8 @@ namespace BMA.EHR.Leave.Service.Controllers var result = new GetLeaveRequestByIdDto { Id = rawData.Id, - LeaveRange = rawData.LeaveRange ?? "", + LeaveRange = rawData.LeaveRange ?? "ALL", + LeaveRangeEnd = rawData.LeaveRangeEnd ?? "ALL", LeaveTypeName = rawData.Type.Name, LeaveSubTypeName = rawData.LeaveSubTypeName, LeaveTypeId = rawData.Type.Id, @@ -1493,6 +1549,7 @@ namespace BMA.EHR.Leave.Service.Controllers Agency = agency_name,//agency == null ? "" : agency.Name, Org = item.Root ?? "",//userOc == null ? "-" : userOc.Root, LeaveRange = item.LeaveRange ?? "ALL", + LeaveRangeEnd = item.LeaveRangeEnd ?? "ALL", HajjDayStatus = item.HajjDayStatus, }; @@ -1758,15 +1815,57 @@ namespace BMA.EHR.Leave.Service.Controllers public async Task> CommanderApproveLeaveRequestAsync(Guid id, [FromBody] LeaveRequestApproveDto req) { - var getPermission = await _permission.GetPermissionAPIAsync("UPDATE", "SYS_LEAVE_LIST"); - var jsonData = JsonConvert.DeserializeObject(getPermission); - if (jsonData["status"]?.ToString() != "200") + try { - return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); - } - await _leaveRequestRepository.CommanderApproveLeaveRequest(id, req.Reason ?? ""); + var getPermission = await _permission.GetPermissionAPIAsync("UPDATE", "SYS_LEAVE_LIST"); + var jsonData = JsonConvert.DeserializeObject(getPermission); + if (jsonData["status"]?.ToString() != "200") + { + return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); + } + await _leaveRequestRepository.CommanderApproveLeaveRequest(id, req.Reason ?? ""); + + return Success(); + } + catch(Exception ex) + { + return Error(ex); + } + + } + + /// + /// ผู้บังคับบัญชาไม่อนุมัติการลา(ADMIN) + /// + /// + /// + /// เมื่อทำรายการสำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPut("admin/reject/comander/{id:guid}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> CommanderRejectLeaveRequestAsync(Guid id, + [FromBody] LeaveRequestApproveDto req) + { + try + { + var getPermission = await _permission.GetPermissionAPIAsync("UPDATE", "SYS_LEAVE_LIST"); + var jsonData = JsonConvert.DeserializeObject(getPermission); + if (jsonData["status"]?.ToString() != "200") + { + return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); + } + await _leaveRequestRepository.CommanderRejectLeaveRequest(id, req.Reason ?? ""); + + return Success(); + } + catch (Exception ex) + { + return Error(ex); + } - return Success(); } /// @@ -1784,15 +1883,23 @@ namespace BMA.EHR.Leave.Service.Controllers public async Task> ApproveLeaveRequestAsync(Guid id, [FromBody] LeaveRequestApproveDto req) { - var getPermission = await _permission.GetPermissionAPIAsync("UPDATE", "SYS_LEAVE_LIST"); - var jsonData = JsonConvert.DeserializeObject(getPermission); - if (jsonData["status"]?.ToString() != "200") + try { - return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); - } - await _leaveRequestRepository.ApproveLeaveRequest(id, req.Reason ?? ""); + var getPermission = await _permission.GetPermissionAPIAsync("UPDATE", "SYS_LEAVE_LIST"); + var jsonData = JsonConvert.DeserializeObject(getPermission); + if (jsonData["status"]?.ToString() != "200") + { + return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); + } + await _leaveRequestRepository.ApproveLeaveRequest(id, req.Reason ?? ""); - return Success(); + return Success(); + } + catch (Exception ex) + { + return Error(ex); + } + } /// @@ -1810,49 +1917,56 @@ namespace BMA.EHR.Leave.Service.Controllers public async Task> SendLeaveRequestAsync(Guid id, [FromBody] LeaveRequestApproveDto req) { - await _leaveRequestRepository.SendToOfficerAsync(id); + try + { + await _leaveRequestRepository.SendToOfficerAsync(id); - var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); - var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); - if (profile == null) - { - return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); - } - var baseAPIOrg = _configuration["API"]; - var apiUrlOrg = $"{baseAPIOrg}/org/workflow/add-workflow"; - if (profile.ProfileType == "OFFICER") - { - using (var client = new HttpClient()) + var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); + var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); + if (profile == null) { - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", "")); - client.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]); - var _res = await client.PostAsJsonAsync(apiUrlOrg, new - { - refId = id, - sysName = "SYS_LEAVE_LIST", - posLevelName = profile.PosLevel ?? "", - posTypeName = profile.PosType ?? "", - fullName = $"{profile.Prefix}{profile.FirstName} {profile.LastName}" - }); + return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound); } - } - else - { - using (var client = new HttpClient()) + var baseAPIOrg = _configuration["API"]; + var apiUrlOrg = $"{baseAPIOrg}/org/workflow/add-workflow"; + if (profile.ProfileType == "OFFICER") { - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", "")); - client.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]); - var _res = await client.PostAsJsonAsync(apiUrlOrg, new + using (var client = new HttpClient()) { - refId = id, - sysName = "SYS_LEAVE_LIST_EMP", - posLevelName = "EMP", - posTypeName = "EMP", - }); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", "")); + client.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]); + var _res = await client.PostAsJsonAsync(apiUrlOrg, new + { + refId = id, + sysName = "SYS_LEAVE_LIST", + posLevelName = profile.PosLevel ?? "", + posTypeName = profile.PosType ?? "", + fullName = $"{profile.Prefix}{profile.FirstName} {profile.LastName}" + }); + } + } + else + { + using (var client = new HttpClient()) + { + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", "")); + client.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]); + var _res = await client.PostAsJsonAsync(apiUrlOrg, new + { + refId = id, + sysName = "SYS_LEAVE_LIST_EMP", + posLevelName = "EMP", + posTypeName = "EMP", + }); + } } - } - return Success(); + return Success(); + } + catch (Exception ex) + { + return Error(ex); + } } /// @@ -1870,15 +1984,23 @@ namespace BMA.EHR.Leave.Service.Controllers public async Task> RejectLeaveRequestAsync(Guid id, [FromBody] LeaveRequestApproveDto req) { - var getPermission = await _permission.GetPermissionAPIAsync("UPDATE", "SYS_LEAVE_LIST"); - var jsonData = JsonConvert.DeserializeObject(getPermission); - if (jsonData["status"]?.ToString() != "200") + try { - return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); - } - await _leaveRequestRepository.RejectLeaveRequest(id, req.Reason ?? ""); + var getPermission = await _permission.GetPermissionAPIAsync("UPDATE", "SYS_LEAVE_LIST"); + var jsonData = JsonConvert.DeserializeObject(getPermission); + if (jsonData["status"]?.ToString() != "200") + { + return Error(jsonData["message"]?.ToString(), StatusCodes.Status403Forbidden); + } + await _leaveRequestRepository.RejectLeaveRequest(id, req.Reason ?? ""); - return Success(); + return Success(); + } + catch (Exception ex) + { + return Error(ex); + } + } /// @@ -1974,6 +2096,38 @@ namespace BMA.EHR.Leave.Service.Controllers if (rawData.Root != null && rawData.Root != "") orgName += $" {rawData.Root}"; + // #1136 + var extendLeave = 0.0; + var leaveLimit = rawData.Type.Limit; + + var approvePrevYear = await _leaveRequestRepository.GetSumApproveLeaveAsync(thisYear - 1); + + if (rawData.Type.Code == "LV-005") + { + var apprvPrevData = approvePrevYear.FirstOrDefault(x => x.KeycloakUserId == rawData.KeycloakUserId && x.LeaveTypeId == rawData.Type.Id); + var apprvPrev = apprvPrevData == null ? 0 : apprvPrevData.SumLeaveDay; + + var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(rawData.KeycloakUserId, AccessToken); + var govAge = (profile?.DateStart?.Date ?? DateTime.Now.Date).DiffDay(DateTime.Now.Date); + + if (govAge >= 180) + { + if (govAge >= 3650) + { + // ถ้าอายุราชการเกิน 10 ปี ได้บวกเพิ่มอีก 10 วัน + extendLeave = 30 - apprvPrev; // หายอดวันลาที่เหลือของปีก่อน + if (extendLeave >= 20) extendLeave = 20; + } + else + { + extendLeave = 20 - apprvPrev; // หายอดวันลาที่เหลือของปีก่อน + if (extendLeave >= 10) extendLeave = 10; + } + } + else + leaveLimit = 0; + } + var result = new GetLeaveRequestForAdminByIdDto { Id = rawData.Id, @@ -1993,6 +2147,7 @@ namespace BMA.EHR.Leave.Service.Controllers LeaveNumber = rawData.LeaveNumber, LeaveDetail = rawData.LeaveDetail, LeaveRange = rawData.LeaveRange ?? "ALL", + LeaveRangeEnd = rawData.LeaveRangeEnd ?? "ALL", LeaveDocument = new(), //LeaveDocument = rawData.LeaveDocument == null ? "" : await _minIOService.ImagesPath(rawData.LeaveDocument.Id), LeaveDraftDocument = rawData.LeaveDraftDocument == null ? "" : await _minIOService.ImagesPath(rawData.LeaveDraftDocument.Id), @@ -2012,8 +2167,12 @@ namespace BMA.EHR.Leave.Service.Controllers WifeDayName = rawData.WifeDayName, WifeDayDateBorn = rawData.WifeDayDateBorn, - RestDayOldTotal = rawData.RestDayOldTotal, - RestDayCurrentTotal = rawData.RestDayCurrentTotal, + RestDayOldTotal = extendLeave, + RestDayCurrentTotal = rawData.Type.Limit, + // #1134 + //RestDayOldTotal = rawData.RestDayOldTotal, + //RestDayCurrentTotal = rawData.RestDayCurrentTotal, + OrdainDayStatus = rawData.OrdainDayStatus, OrdainDayLocationName = rawData.OrdainDayLocationName, OrdainDayLocationAddress = rawData.OrdainDayLocationAddress, @@ -2066,9 +2225,9 @@ namespace BMA.EHR.Leave.Service.Controllers ApproveStep = rawData.ApproveStep ?? "-", - LeaveLimit = rawData.Type.Limit, + LeaveLimit = rawData.Type.Limit + extendLeave, LeaveSummary = leaveSummary, - LeaveRemain = rawData.Type.Limit - leaveSummary + LeaveRemain = (rawData.Type.Limit + extendLeave) - leaveSummary }; if (rawData.LeaveDocument != null && rawData.LeaveDocument.Count > 0) @@ -2136,7 +2295,7 @@ namespace BMA.EHR.Leave.Service.Controllers if (leaveType.Code == "LV-005") { var apprvPrevData = approvePrevYear.FirstOrDefault(x => x.KeycloakUserId == userId && x.LeaveTypeId == leaveType.Id); - var apprvPrev = apprvPrevData == null ? 0 : approveData.SumLeaveDay; + var apprvPrev = apprvPrevData == null ? 0 : apprvPrevData.SumLeaveDay; var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId, AccessToken); var govAge = (profile?.DateStart?.Date ?? DateTime.Now.Date).DiffDay(DateTime.Now.Date); diff --git a/BMA.EHR.Leave/DTOs/LeaveRequest/CreateLeaveRequestDto.cs b/BMA.EHR.Leave/DTOs/LeaveRequest/CreateLeaveRequestDto.cs index c431388d..b8cc2c03 100644 --- a/BMA.EHR.Leave/DTOs/LeaveRequest/CreateLeaveRequestDto.cs +++ b/BMA.EHR.Leave/DTOs/LeaveRequest/CreateLeaveRequestDto.cs @@ -21,6 +21,8 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest public string? LeaveRange { get; set; } = "ALL"; + public string? LeaveRangeEnd { get; set; } = "ALL"; + public double LeaveTotal { get; set; } = 0.0; public string? LeaveAddress { get; set; } @@ -100,31 +102,7 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest public DateTime? CoupleDayEndDateHistory { get; set; } public string? CoupleDaySumTotalHistory { get; set; } - - public string? Approvers { get; set; } = string.Empty; } - public class LeaveRequestApproverDto - { - [JsonProperty("seq")] - public int Seq { get; set; } = 0; - - [JsonProperty("prefix")] - public string Prefix { get; set; } = string.Empty; - - [JsonProperty("firstName")] - public string FirstName { get; set; } = string.Empty; - - [JsonProperty("lastName")] - public string LastName { get; set; } = string.Empty; - - [JsonProperty("positionName")] - public string PositionName { get; set; } = string.Empty; - - [JsonProperty("profileId")] - public Guid ProfileId { get; set; } = Guid.Empty; - - [JsonProperty("keycloakId")] - public Guid KeycloakId { get; set; } = Guid.Empty; - } + } diff --git a/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestByIdDto.cs b/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestByIdDto.cs index 508c9173..449cecc3 100644 --- a/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestByIdDto.cs +++ b/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestByIdDto.cs @@ -27,6 +27,8 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest public string? LeaveRange { get; set; } = string.Empty; + public string? LeaveRangeEnd { get; set; } = string.Empty; + public string LeaveAddress { get; set; } = string.Empty; public string LeaveNumber { get; set; } = string.Empty; diff --git a/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestForAdminByIdDto.cs b/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestForAdminByIdDto.cs index 71c5d970..3693a941 100644 --- a/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestForAdminByIdDto.cs +++ b/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestForAdminByIdDto.cs @@ -135,6 +135,9 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest public double LeaveRemain { get; set; } = 0; public string LeaveRange { get; set; } = string.Empty; + + public string LeaveRangeEnd { get; set; } = string.Empty; + public string? ProfileType { get; set; } public string? CommanderPosition { get; set; } = string.Empty; diff --git a/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestForAdminResultDto.cs b/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestForAdminResultDto.cs index 19aa8b96..42a508ff 100644 --- a/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestForAdminResultDto.cs +++ b/BMA.EHR.Leave/DTOs/LeaveRequest/GetLeaveRequestForAdminResultDto.cs @@ -32,6 +32,8 @@ public string LeaveRange { get; set; } = string.Empty; + public string LeaveRangeEnd { get; set; } = string.Empty; + public bool? HajjDayStatus { get; set; } public string? ProfileType { get; set; } diff --git a/BMA.EHR.Leave/DTOs/LeaveRequest/LeaveRequestApproverDto.cs b/BMA.EHR.Leave/DTOs/LeaveRequest/LeaveRequestApproverDto.cs new file mode 100644 index 00000000..57a70e8d --- /dev/null +++ b/BMA.EHR.Leave/DTOs/LeaveRequest/LeaveRequestApproverDto.cs @@ -0,0 +1,28 @@ +using Newtonsoft.Json; + +namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest +{ + public class LeaveRequestApproverDto + { + [JsonProperty("seq")] + public int Seq { get; set; } = 0; + + [JsonProperty("prefix")] + public string Prefix { get; set; } = string.Empty; + + [JsonProperty("firstName")] + public string FirstName { get; set; } = string.Empty; + + [JsonProperty("lastName")] + public string LastName { get; set; } = string.Empty; + + [JsonProperty("positionName")] + public string PositionName { get; set; } = string.Empty; + + [JsonProperty("profileId")] + public Guid ProfileId { get; set; } = Guid.Empty; + + [JsonProperty("keycloakId")] + public Guid KeycloakId { get; set; } = Guid.Empty; + } +}