From e76d994098aae8b8cbf847d701bb8d1a5913e1f6 Mon Sep 17 00:00:00 2001 From: Suphonchai Phoonsawat Date: Fri, 24 Nov 2023 11:23:18 +0700 Subject: [PATCH] =?UTF-8?q?cronjob=20+=20=E0=B8=A5=E0=B8=87=E0=B9=80?= =?UTF-8?q?=E0=B8=A7=E0=B8=A5=E0=B8=B2=E0=B8=81=E0=B8=A3=E0=B8=93=E0=B8=B5?= =?UTF-8?q?=E0=B8=9E=E0=B8=B4=E0=B9=80=E0=B8=94=E0=B8=A8=E0=B8=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApplicationServicesRegistration.cs | 1 + .../AdditionalCheckRequestRepository.cs | 56 ++ .../TimeAttendants/UserDutyTimeRepository.cs | 20 + .../Repositories/UserProfileRepository.cs | 27 +- .../TimeAttendants/AdditionalCheckRequest.cs | 30 + ...AdditionalCheckInRequest Table.Designer.cs | 539 +++++++++++++++++ ...5028_add AdditionalCheckInRequest Table.cs | 58 ++ ...AdditionalCheckInRequest Table.Designer.cs | 543 ++++++++++++++++++ ...oakid to AdditionalCheckInRequest Table.cs | 32 ++ .../LeaveDb/LeaveDbContextModelSnapshot.cs | 102 +++- .../Persistence/LeaveDbContext.cs | 2 + .../BMA.EHR.Leave.Service.csproj | 3 + .../Controllers/LeaveController.cs | 43 +- .../CreateAdditionalCheckRequestDto.cs | 13 + .../Filters/CustomAuthorizeFilter.cs | 15 + BMA.EHR.Leave.Service/Program.cs | 43 +- 16 files changed, 1518 insertions(+), 9 deletions(-) create mode 100644 BMA.EHR.Application/Repositories/Leaves/TimeAttendants/AdditionalCheckRequestRepository.cs create mode 100644 BMA.EHR.Domain/Models/Leave/TimeAttendants/AdditionalCheckRequest.cs create mode 100644 BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124035028_add AdditionalCheckInRequest Table.Designer.cs create mode 100644 BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124035028_add AdditionalCheckInRequest Table.cs create mode 100644 BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124040110_add keycloakid to AdditionalCheckInRequest Table.Designer.cs create mode 100644 BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124040110_add keycloakid to AdditionalCheckInRequest Table.cs create mode 100644 BMA.EHR.Leave.Service/DTOs/AdditionalCheck/CreateAdditionalCheckRequestDto.cs create mode 100644 BMA.EHR.Leave.Service/Filters/CustomAuthorizeFilter.cs diff --git a/BMA.EHR.Application/ApplicationServicesRegistration.cs b/BMA.EHR.Application/ApplicationServicesRegistration.cs index 5bcec7c9..6c6d052d 100644 --- a/BMA.EHR.Application/ApplicationServicesRegistration.cs +++ b/BMA.EHR.Application/ApplicationServicesRegistration.cs @@ -47,6 +47,7 @@ namespace BMA.EHR.Application services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); return services; } diff --git a/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/AdditionalCheckRequestRepository.cs b/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/AdditionalCheckRequestRepository.cs new file mode 100644 index 00000000..13127204 --- /dev/null +++ b/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/AdditionalCheckRequestRepository.cs @@ -0,0 +1,56 @@ +using BMA.EHR.Application.Common.Interfaces; +using BMA.EHR.Application.Messaging; +using BMA.EHR.Domain.Models.Leave.TimeAttendants; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; + +namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants +{ + public class AdditionalCheckRequestRepository : GenericLeaveRepository + { + #region " Fields " + + private readonly ILeaveDbContext _dbContext; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly OrganizationCommonRepository _organizationCommonRepository; + private readonly UserProfileRepository _userProfileRepository; + private readonly IConfiguration _configuration; + private readonly EmailSenderService _emailSenderService; + + #endregion + + #region " Constructor and Destuctor " + + public AdditionalCheckRequestRepository(ILeaveDbContext dbContext, + IHttpContextAccessor httpContextAccessor, + OrganizationCommonRepository organizationCommonRepository, + UserProfileRepository userProfileRepository, + IConfiguration configuration, + EmailSenderService emailSenderService) : base(dbContext, httpContextAccessor) + { + _dbContext = dbContext; + _httpContextAccessor = httpContextAccessor; + _organizationCommonRepository = organizationCommonRepository; + _userProfileRepository = userProfileRepository; + _configuration = configuration; + _emailSenderService = emailSenderService; + } + + #endregion + + #region " Properties " + + protected Guid UserOrganizationId + { + get + { + if (UserId != null || UserId != "") + return _userProfileRepository.GetUserOCId(Guid.Parse(UserId!)); + else + return Guid.Empty; + } + } + + #endregion + } +} diff --git a/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/UserDutyTimeRepository.cs b/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/UserDutyTimeRepository.cs index c6194545..327362e9 100644 --- a/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/UserDutyTimeRepository.cs +++ b/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/UserDutyTimeRepository.cs @@ -56,6 +56,26 @@ namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants #region " Methods " + public void UpdateUserDutyTime() + { + try + { + var data = _dbContext.Set() + .Where(u => !u.IsProcess) + .Where(u => u.EffectiveDate.Value.Date <= DateTime.Now.Date) + .ToList(); + + foreach (var d in data) + { + var result = _userProfileRepository.UpdateDutyTimeAsync(d.ProfileId, d.DutyTimeId, d.EffectiveDate.Value.Date).Result; + } + } + catch + { + throw; + } + } + public async Task> GetListByProfileIdAsync(Guid profileId) { var data = await _dbContext.Set().AsQueryable() diff --git a/BMA.EHR.Application/Repositories/UserProfileRepository.cs b/BMA.EHR.Application/Repositories/UserProfileRepository.cs index e97e8af1..b520a5a6 100644 --- a/BMA.EHR.Application/Repositories/UserProfileRepository.cs +++ b/BMA.EHR.Application/Repositories/UserProfileRepository.cs @@ -28,12 +28,37 @@ namespace BMA.EHR.Application.Repositories #region " Methods " + public async Task UpdateDutyTimeAsync(Guid profileId, Guid roundId, DateTime effectiveDate) + { + try + { + var profile = await _dbContext.Set().FirstOrDefaultAsync(x => x.Id == profileId); + if (profile == null) + { + throw new Exception(GlobalMessages.DataNotFound); + } + else + { + profile.DutyTimeId = roundId; + profile.DutyTimeEffectiveDate = effectiveDate; + + await UpdateAsync(profile); + + return true; + } + } + catch + { + throw; + } + } + public async Task> SearchProfile(string? citizenId, string? firstName, string? lastName) { try { var data = _dbContext.Set().AsQueryable(); - + if (citizenId != null) data = data.Where(x => x.CitizenId!.Contains(citizenId)); diff --git a/BMA.EHR.Domain/Models/Leave/TimeAttendants/AdditionalCheckRequest.cs b/BMA.EHR.Domain/Models/Leave/TimeAttendants/AdditionalCheckRequest.cs new file mode 100644 index 00000000..06d46074 --- /dev/null +++ b/BMA.EHR.Domain/Models/Leave/TimeAttendants/AdditionalCheckRequest.cs @@ -0,0 +1,30 @@ +using BMA.EHR.Domain.Models.Base; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; + +namespace BMA.EHR.Domain.Models.Leave.TimeAttendants +{ + public class AdditionalCheckRequest: EntityBase + { + [Required,Comment("*วันที่ลงเวลา")] + public DateTime CheckDate { get; set; } = DateTime.Now.Date; + + [Required, Comment("*ขอลงเวลาช่วงเช้า")] + public bool CheckInEdit { get; set; } = false; + + [Required, Comment("*ขอลงเวลาช่วงบ่าย")] + public bool CheckOutEdit { get; set; } = false; + + [Required, Comment("*หมายเหตุขอลงเวลาพิเศษ")] + public string Description { get; set; } = string.Empty; + + [Comment("สถานะการอนุมัติ")] + public bool IsApproved { get; set; } = false; + + [Comment("หมายเหตุในการการอนุมัติ/ไม่อนุมัติ")] + public string? Comment { get; set; } = string.Empty; + + [Required, Comment("รหัส User ของ Keycloak ที่ร้องขอ")] + public Guid KeycloakUserId { get; set; } = Guid.Empty; + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124035028_add AdditionalCheckInRequest Table.Designer.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124035028_add AdditionalCheckInRequest Table.Designer.cs new file mode 100644 index 00000000..948be34e --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124035028_add AdditionalCheckInRequest Table.Designer.cs @@ -0,0 +1,539 @@ +// +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("20231124035028_add AdditionalCheckInRequest Table")] + partial class addAdditionalCheckInRequestTable + { + /// + 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.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("IsApproved") + .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.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("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("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("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.HasKey("Id"); + + b.ToTable("ProcessUserTimeStamps"); + }); + + 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("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("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("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.HasKey("Id"); + + b.ToTable("UserTimeStamps"); + }); + + 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"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124035028_add AdditionalCheckInRequest Table.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124035028_add AdditionalCheckInRequest Table.cs new file mode 100644 index 00000000..61b1bd4c --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124035028_add AdditionalCheckInRequest Table.cs @@ -0,0 +1,58 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BMA.EHR.Infrastructure.Migrations.LeaveDb +{ + /// + public partial class addAdditionalCheckInRequestTable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AdditionalCheckRequests", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, comment: "PrimaryKey", collation: "ascii_general_ci"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false, comment: "สร้างข้อมูลเมื่อ"), + CreatedUserId = table.Column(type: "varchar(40)", maxLength: 40, nullable: false, comment: "User Id ที่สร้างข้อมูล") + .Annotation("MySql:CharSet", "utf8mb4"), + LastUpdatedAt = table.Column(type: "datetime(6)", nullable: true, comment: "แก้ไขข้อมูลล่าสุดเมื่อ"), + LastUpdateUserId = table.Column(type: "varchar(40)", maxLength: 40, nullable: false, comment: "User Id ที่แก้ไขข้อมูลล่าสุด") + .Annotation("MySql:CharSet", "utf8mb4"), + CreatedFullName = table.Column(type: "varchar(200)", maxLength: 200, nullable: false, comment: "ชื่อ User ที่สร้างข้อมูล") + .Annotation("MySql:CharSet", "utf8mb4"), + LastUpdateFullName = table.Column(type: "varchar(200)", maxLength: 200, nullable: false, comment: "ชื่อ User ที่แก้ไขข้อมูลล่าสุด") + .Annotation("MySql:CharSet", "utf8mb4"), + CheckDate = table.Column(type: "datetime(6)", nullable: false, comment: "*วันที่ลงเวลา"), + CheckInEdit = table.Column(type: "tinyint(1)", nullable: false, comment: "*ขอลงเวลาช่วงเช้า"), + CheckOutEdit = table.Column(type: "tinyint(1)", nullable: false, comment: "*ขอลงเวลาช่วงบ่าย"), + Description = table.Column(type: "longtext", nullable: false, comment: "*หมายเหตุขอลงเวลาพิเศษ") + .Annotation("MySql:CharSet", "utf8mb4"), + IsApproved = table.Column(type: "tinyint(1)", nullable: false, comment: "สถานะการอนุมัติ"), + Comment = table.Column(type: "longtext", nullable: true, comment: "หมายเหตุในการการอนุมัติ/ไม่อนุมัติ") + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AdditionalCheckRequests", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + + migrationBuilder.DropTable( + name: "AdditionalCheckRequests"); + + + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124040110_add keycloakid to AdditionalCheckInRequest Table.Designer.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124040110_add keycloakid to AdditionalCheckInRequest Table.Designer.cs new file mode 100644 index 00000000..ba7acbf1 --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124040110_add keycloakid to AdditionalCheckInRequest Table.Designer.cs @@ -0,0 +1,543 @@ +// +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("20231124040110_add keycloakid to AdditionalCheckInRequest Table")] + partial class addkeycloakidtoAdditionalCheckInRequestTable + { + /// + 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.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("IsApproved") + .HasColumnType("tinyint(1)") + .HasComment("สถานะการอนุมัติ"); + + b.Property("KeycloakUserId") + .HasColumnType("char(36)") + .HasComment("รหัส User ของ Keycloak ที่ร้องขอ"); + + 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.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("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("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("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.HasKey("Id"); + + b.ToTable("ProcessUserTimeStamps"); + }); + + 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("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("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("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.HasKey("Id"); + + b.ToTable("UserTimeStamps"); + }); + + 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"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124040110_add keycloakid to AdditionalCheckInRequest Table.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124040110_add keycloakid to AdditionalCheckInRequest Table.cs new file mode 100644 index 00000000..ebcc2166 --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231124040110_add keycloakid to AdditionalCheckInRequest Table.cs @@ -0,0 +1,32 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BMA.EHR.Infrastructure.Migrations.LeaveDb +{ + /// + public partial class addkeycloakidtoAdditionalCheckInRequestTable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "KeycloakUserId", + table: "AdditionalCheckRequests", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + comment: "รหัส User ของ Keycloak ที่ร้องขอ", + collation: "ascii_general_ci"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "KeycloakUserId", + table: "AdditionalCheckRequests"); + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs index c43e5323..d776afa5 100644 --- a/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs @@ -19,6 +19,87 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb .HasAnnotation("ProductVersion", "7.0.9") .HasAnnotation("Relational:MaxIdentifierLength", 64); + 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("IsApproved") + .HasColumnType("tinyint(1)") + .HasComment("สถานะการอนุมัติ"); + + b.Property("KeycloakUserId") + .HasColumnType("char(36)") + .HasComment("รหัส User ของ Keycloak ที่ร้องขอ"); + + 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.HasKey("Id"); + + b.ToTable("AdditionalCheckRequests"); + }); + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.DutyTime", b => { b.Property("Id") @@ -101,7 +182,7 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb b.HasKey("Id"); - b.ToTable("DutyTimes", (string)null); + b.ToTable("DutyTimes"); }); modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.ProcessUserTimeStamp", b => @@ -238,7 +319,7 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb b.HasKey("Id"); - b.ToTable("ProcessUserTimeStamps", (string)null); + b.ToTable("ProcessUserTimeStamps"); }); modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.UserDutyTime", b => @@ -310,7 +391,9 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb b.HasKey("Id"); - b.ToTable("UserDutyTimes", (string)null); + b.HasIndex("DutyTimeId"); + + b.ToTable("UserDutyTimes"); }); modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.UserTimeStamp", b => @@ -438,7 +521,18 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb b.HasKey("Id"); - b.ToTable("UserTimeStamps", (string)null); + b.ToTable("UserTimeStamps"); + }); + + 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"); }); #pragma warning restore 612, 618 } diff --git a/BMA.EHR.Infrastructure/Persistence/LeaveDbContext.cs b/BMA.EHR.Infrastructure/Persistence/LeaveDbContext.cs index 225918de..6b7e7b8f 100644 --- a/BMA.EHR.Infrastructure/Persistence/LeaveDbContext.cs +++ b/BMA.EHR.Infrastructure/Persistence/LeaveDbContext.cs @@ -16,6 +16,8 @@ namespace BMA.EHR.Infrastructure.Persistence public DbSet UserDutyTimes { get; set; } + public DbSet AdditionalCheckRequests { get; set; } + #endregion diff --git a/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj b/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj index 57b7f1cd..936fd555 100644 --- a/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj +++ b/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj @@ -23,6 +23,9 @@ + + + diff --git a/BMA.EHR.Leave.Service/Controllers/LeaveController.cs b/BMA.EHR.Leave.Service/Controllers/LeaveController.cs index f97dd8d4..74c681c8 100644 --- a/BMA.EHR.Leave.Service/Controllers/LeaveController.cs +++ b/BMA.EHR.Leave.Service/Controllers/LeaveController.cs @@ -5,6 +5,7 @@ using BMA.EHR.Domain.Common; using BMA.EHR.Domain.Models.Leave.TimeAttendants; using BMA.EHR.Domain.Shared; using BMA.EHR.Infrastructure.Persistence; +using BMA.EHR.Leave.Service.DTOs.AdditionalCheck; using BMA.EHR.Leave.Service.DTOs.ChangeRound; using BMA.EHR.Leave.Service.DTOs.CheckIn; using BMA.EHR.Leave.Service.DTOs.DutyTime; @@ -38,6 +39,7 @@ namespace BMA.EHR.Leave.Service.Controllers private readonly MinIOService _minIOService; private readonly ProcessUserTimeStampRepository _processUserTimeStampRepository; private readonly UserDutyTimeRepository _userDutyTimeRepository; + private readonly AdditionalCheckRequestRepository _additionalCheckRequestRepository; private readonly string _bucketName = "check-in"; @@ -54,7 +56,8 @@ namespace BMA.EHR.Leave.Service.Controllers UserTimeStampRepository userTimeStampRepository, MinIOService minIOService, ProcessUserTimeStampRepository processUserTimeStampRepository, - UserDutyTimeRepository userDutyTimeRepository) + UserDutyTimeRepository userDutyTimeRepository, + AdditionalCheckRequestRepository additionalCheckRequestRepository) { _dutyTimeRepository = dutyTimeRepository; _context = context; @@ -66,6 +69,7 @@ namespace BMA.EHR.Leave.Service.Controllers _minIOService = minIOService; _processUserTimeStampRepository = processUserTimeStampRepository; _userDutyTimeRepository = userDutyTimeRepository; + _additionalCheckRequestRepository = additionalCheckRequestRepository; } #endregion @@ -714,7 +718,6 @@ namespace BMA.EHR.Leave.Service.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] - [AllowAnonymous] public async Task> SearchProfileAsync([FromBody] SearchProfileDto req) { var profile = await _userProfileRepository.SearchProfile(req.CitizenId, req.FirstName, req.LastName); @@ -798,7 +801,6 @@ namespace BMA.EHR.Leave.Service.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] - [AllowAnonymous] public async Task> GetChangeRoundHistoryByProfileIdAsync(Guid id, int page = 1, int pageSize = 10, string keyword = "") { var data = await _userDutyTimeRepository.GetListByProfileIdAsync(id); @@ -829,6 +831,41 @@ namespace BMA.EHR.Leave.Service.Controllers } + #endregion + + #region " ขอลงเวลาเป็นกรณีพิเศษ " + + /// + /// LV1_017 - เพิ่มลงเวลากรณีพิเศษ (USER) + /// + /// + /// + /// เมื่อทำรายการสำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPost("user/edit")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> CreateAdditionalCheckRequestAsync([FromBody] CreateAdditionalCheckRequestDto req) + { + if (req.CheckDate.Date > DateTime.Now.Date) + { + return Error("ไม่สามารถขอลงเวลากรณีพิเศษในวันที่มากกว่าวันที่ปัจจุบันได้", (int)StatusCodes.Status400BadRequest); + } + + var request = new AdditionalCheckRequest + { + KeycloakUserId = UserId != null ? Guid.Parse(UserId) : Guid.Empty, + CheckDate = req.CheckDate, + CheckInEdit = req.CheckInEdit, + CheckOutEdit = req.CheckOutEdit, + Description = req.Description, + }; + await _additionalCheckRequestRepository.AddAsync(request); + return Success(); + } + #endregion #endregion diff --git a/BMA.EHR.Leave.Service/DTOs/AdditionalCheck/CreateAdditionalCheckRequestDto.cs b/BMA.EHR.Leave.Service/DTOs/AdditionalCheck/CreateAdditionalCheckRequestDto.cs new file mode 100644 index 00000000..a242cf81 --- /dev/null +++ b/BMA.EHR.Leave.Service/DTOs/AdditionalCheck/CreateAdditionalCheckRequestDto.cs @@ -0,0 +1,13 @@ +namespace BMA.EHR.Leave.Service.DTOs.AdditionalCheck +{ + public class CreateAdditionalCheckRequestDto + { + public DateTime CheckDate { get; set; } + + public bool CheckInEdit { get; set; } + + public bool CheckOutEdit { get; set;} + + public string Description { get; set; } + } +} diff --git a/BMA.EHR.Leave.Service/Filters/CustomAuthorizeFilter.cs b/BMA.EHR.Leave.Service/Filters/CustomAuthorizeFilter.cs new file mode 100644 index 00000000..52c8a0ff --- /dev/null +++ b/BMA.EHR.Leave.Service/Filters/CustomAuthorizeFilter.cs @@ -0,0 +1,15 @@ +using Hangfire.Dashboard; +using System.Diagnostics.CodeAnalysis; + +namespace BMA.EHR.Leave.Service.Filters +{ + public class CustomAuthorizeFilter : IDashboardAuthorizationFilter + { + public bool Authorize([NotNull] DashboardContext context) + { + //var httpcontext = context.GetHttpContext(); + //return httpcontext.User.Identity.IsAuthenticated; + return true; + } + } +} diff --git a/BMA.EHR.Leave.Service/Program.cs b/BMA.EHR.Leave.Service/Program.cs index 96e6174d..8965c224 100644 --- a/BMA.EHR.Leave.Service/Program.cs +++ b/BMA.EHR.Leave.Service/Program.cs @@ -1,4 +1,4 @@ -using BMA.EHR.Application; +using BMA.EHR.Application; using BMA.EHR.Leave.Service; using BMA.EHR.Domain.Middlewares; using BMA.EHR.Infrastructure; @@ -15,6 +15,12 @@ using Serilog.Exceptions; using Serilog.Sinks.Elasticsearch; using System.Reflection; using System.Text; +using Hangfire; +using Hangfire.MySql; +using System.Transactions; +using BMA.EHR.Leave.Service.Filters; +using Hangfire.Common; +using BMA.EHR.Application.Repositories.Leaves.TimeAttendants; var builder = WebApplication.CreateBuilder(args); { @@ -93,6 +99,29 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.ConfigureOptions(); builder.Services.AddHealthChecks(); + + // Add Hangfire services. + var defaultConnection = builder.Configuration.GetConnectionString("DefaultConnection"); + + builder.Services.AddHangfire(configuration => configuration + .SetDataCompatibilityLevel(CompatibilityLevel.Version_170) + .UseSimpleAssemblyNameTypeSerializer() + .UseRecommendedSerializerSettings() + .UseStorage( + new MySqlStorage( + defaultConnection, + new MySqlStorageOptions + { + TransactionIsolationLevel = IsolationLevel.ReadCommitted, + QueuePollInterval = TimeSpan.FromSeconds(15), + JobExpirationCheckInterval = TimeSpan.FromHours(1), + CountersAggregateInterval = TimeSpan.FromMinutes(5), + PrepareSchemaIfNecessary = true, + DashboardJobListLimit = 50000, + TransactionTimeout = TimeSpan.FromMinutes(1), + TablesPrefix = "Hangfire" + }))); + builder.Services.AddHangfireServer(); } var app = builder.Build(); @@ -124,6 +153,18 @@ var app = builder.Build(); app.MapControllers(); app.UseMiddleware(); + + app.UseHangfireDashboard("/hangfire", new DashboardOptions() + { + Authorization = new[] { new CustomAuthorizeFilter() } + }); + + var manager = new RecurringJobManager(); + if (manager != null) + { + manager.AddOrUpdate("ปรับปรุงรอบการลงเวลาทำงาน", Job.FromExpression(x => x.UpdateUserDutyTime()), Cron.Daily(6, 0), TimeZoneInfo.Local); + } + // apply migrations await using var scope = app.Services.CreateAsyncScope(); await using var db = scope.ServiceProvider.GetRequiredService();