From 8037ad7e1e24202b2cbf53435fe3451347570ef7 Mon Sep 17 00:00:00 2001 From: Suphonchai Phoonsawat Date: Tue, 28 Nov 2023 12:28:20 +0700 Subject: [PATCH] Add LeaveType Seeder --- .../ApplicationServicesRegistration.cs | 3 + .../LeaveRequests/LeaveTypeRepository.cs | 56 ++ .../Models/Leave/Commons/LeaveType.cs | 6 + ...50_Add Code to LeaveType Table.Designer.cs | 906 ++++++++++++++++++ ...31128051050_Add Code to LeaveType Table.cs | 52 + .../LeaveDb/LeaveDbContextModelSnapshot.cs | 8 +- .../Persistence/LeaveSeeder.cs | 47 + .../BMA.EHR.Leave.Service.csproj | 2 +- .../LeaveRequest/CreateLeaveRequestDto.cs | 30 + BMA.EHR.Leave.Service/Program.cs | 3 + BMA.EHR.Leave.Service/SeedLeaveData.xlsx | Bin 0 -> 11085 bytes 11 files changed, 1111 insertions(+), 2 deletions(-) create mode 100644 BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveTypeRepository.cs create mode 100644 BMA.EHR.Infrastructure/Migrations/LeaveDb/20231128051050_Add Code to LeaveType Table.Designer.cs create mode 100644 BMA.EHR.Infrastructure/Migrations/LeaveDb/20231128051050_Add Code to LeaveType Table.cs create mode 100644 BMA.EHR.Infrastructure/Persistence/LeaveSeeder.cs create mode 100644 BMA.EHR.Leave.Service/DTOs/LeaveRequest/CreateLeaveRequestDto.cs create mode 100644 BMA.EHR.Leave.Service/SeedLeaveData.xlsx diff --git a/BMA.EHR.Application/ApplicationServicesRegistration.cs b/BMA.EHR.Application/ApplicationServicesRegistration.cs index 6c6d052d..2dbc7e0a 100644 --- a/BMA.EHR.Application/ApplicationServicesRegistration.cs +++ b/BMA.EHR.Application/ApplicationServicesRegistration.cs @@ -1,6 +1,7 @@ using BMA.EHR.Application.Messaging; using BMA.EHR.Application.Repositories; using BMA.EHR.Application.Repositories.Commands; +using BMA.EHR.Application.Repositories.Leaves.LeaveRequests; using BMA.EHR.Application.Repositories.Leaves.TimeAttendants; using BMA.EHR.Application.Repositories.MessageQueue; using BMA.EHR.Application.Repositories.Reports; @@ -49,6 +50,8 @@ namespace BMA.EHR.Application services.AddTransient(); services.AddTransient(); + services.AddTransient(); + return services; } diff --git a/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveTypeRepository.cs b/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveTypeRepository.cs new file mode 100644 index 00000000..0fd361ac --- /dev/null +++ b/BMA.EHR.Application/Repositories/Leaves/LeaveRequests/LeaveTypeRepository.cs @@ -0,0 +1,56 @@ +using BMA.EHR.Application.Common.Interfaces; +using BMA.EHR.Application.Messaging; +using BMA.EHR.Domain.Models.Leave.Commons; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; + +namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests +{ + public class LeaveTypeRepository : 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 LeaveTypeRepository(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.Domain/Models/Leave/Commons/LeaveType.cs b/BMA.EHR.Domain/Models/Leave/Commons/LeaveType.cs index 06df5904..ce02ad3d 100644 --- a/BMA.EHR.Domain/Models/Leave/Commons/LeaveType.cs +++ b/BMA.EHR.Domain/Models/Leave/Commons/LeaveType.cs @@ -1,9 +1,15 @@ using BMA.EHR.Domain.Models.Base; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; namespace BMA.EHR.Domain.Models.Leave.Commons { public class LeaveType : EntityBase { + [Required, Comment("ชื่อประเภทการลา")] public string Name { get; set; } = string.Empty; + + [Required, Comment("รหัสประเภทการลา")] + public string Code { get; set; } = string.Empty; } } diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231128051050_Add Code to LeaveType Table.Designer.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231128051050_Add Code to LeaveType Table.Designer.cs new file mode 100644 index 00000000..ffb138c8 --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231128051050_Add Code to LeaveType Table.Designer.cs @@ -0,0 +1,906 @@ +// +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("20231128051050_Add Code to LeaveType Table")] + partial class AddCodetoLeaveTypeTable + { + /// + 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("Name") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อประเภทการลา"); + + b.HasKey("Id"); + + b.ToTable("LeaveTypes"); + }); + + 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("CoupleDayCountryHistory") + .IsRequired() + .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") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CoupleDayTotalHistory") + .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("HajjDayStatus") + .HasColumnType("tinyint(1)"); + + 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("LeaveComment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LeaveDetail") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รายละเอียดการลา"); + + b.Property("LeaveDocumentId") + .HasColumnType("char(36)"); + + b.Property("LeaveDraftDocumentId") + .HasColumnType("char(36)"); + + b.Property("LeaveEndDate") + .HasColumnType("datetime(6)") + .HasComment("วัน เดือน ปีสิ้นสุดลา"); + + b.Property("LeaveNumber") + .IsRequired() + .HasColumnType("longtext") + .HasComment("หมายเลขที่ติดต่อขณะลา"); + + b.Property("LeaveSalaryText") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LeaveStartDate") + .HasColumnType("datetime(6)") + .HasComment("วัน เดือน ปีเริ่มต้นลา"); + + b.Property("LeaveStatus") + .IsRequired() + .HasColumnType("longtext"); + + 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("RestDayCurrentTotal") + .HasColumnType("int"); + + b.Property("RestDayOldTotal") + .HasColumnType("int"); + + 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("LeaveDocumentId"); + + b.HasIndex("LeaveDraftDocumentId"); + + b.HasIndex("TypeId"); + + b.ToTable("LeaveRequests"); + }); + + 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("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.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("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("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.Requests.LeaveRequest", b => + { + b.HasOne("BMA.EHR.Domain.Models.Documents.Document", "LeaveDocument") + .WithMany() + .HasForeignKey("LeaveDocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BMA.EHR.Domain.Models.Documents.Document", "LeaveDraftDocument") + .WithMany() + .HasForeignKey("LeaveDraftDocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BMA.EHR.Domain.Models.Leave.Commons.LeaveType", "Type") + .WithMany() + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LeaveDocument"); + + b.Navigation("LeaveDraftDocument"); + + b.Navigation("Type"); + }); + + 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/20231128051050_Add Code to LeaveType Table.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231128051050_Add Code to LeaveType Table.cs new file mode 100644 index 00000000..661e386d --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231128051050_Add Code to LeaveType Table.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BMA.EHR.Infrastructure.Migrations.LeaveDb +{ + /// + public partial class AddCodetoLeaveTypeTable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Name", + table: "LeaveTypes", + type: "longtext", + nullable: false, + comment: "ชื่อประเภทการลา", + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "Code", + table: "LeaveTypes", + type: "longtext", + nullable: false, + comment: "รหัสประเภทการลา") + .Annotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Code", + table: "LeaveTypes"); + + migrationBuilder.AlterColumn( + name: "Name", + table: "LeaveTypes", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldComment: "ชื่อประเภทการลา") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs index 6392c853..7a6b4c96 100644 --- a/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs @@ -62,6 +62,11 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb .HasComment("PrimaryKey") .HasAnnotation("Relational:JsonPropertyName", "id"); + b.Property("Code") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รหัสประเภทการลา"); + b.Property("CreatedAt") .HasColumnType("datetime(6)") .HasColumnOrder(100) @@ -102,7 +107,8 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb b.Property("Name") .IsRequired() - .HasColumnType("longtext"); + .HasColumnType("longtext") + .HasComment("ชื่อประเภทการลา"); b.HasKey("Id"); diff --git a/BMA.EHR.Infrastructure/Persistence/LeaveSeeder.cs b/BMA.EHR.Infrastructure/Persistence/LeaveSeeder.cs new file mode 100644 index 00000000..d7357d0b --- /dev/null +++ b/BMA.EHR.Infrastructure/Persistence/LeaveSeeder.cs @@ -0,0 +1,47 @@ +using BMA.EHR.Application.Repositories.Leaves.LeaveRequests; +using BMA.EHR.Domain.Models.Leave.Commons; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using OfficeOpenXml; + +namespace BMA.EHR.Infrastructure.Persistence +{ + public static class LeaveSeeder + { + public static async Task SeedLeaveType(WebApplication app) + { + using var scope = app.Services.CreateScope(); + var service = scope.ServiceProvider.GetRequiredService(); + + if ((await service.GetAllAsync()).Count() == 0) + { + // read excels into object + var excelFile = "SeedLeaveData.xlsx"; + using (var excel = new ExcelPackage(new FileInfo(excelFile))) + { + var workSheet = excel.Workbook.Worksheets.FirstOrDefault(x => x.Name.ToLower() == "leavetype"); + var totalRows = workSheet?.Dimension.Rows; + + int row = 2; + + while (row <= totalRows) + { + var cell1 = workSheet?.Cells[row, 1]?.GetValue(); + if (cell1 == "" || cell1 == null) break; + + var inserted = new LeaveType + { + Id = Guid.Parse(workSheet?.Cells[row, 1]?.GetValue()!), + Name = workSheet?.Cells[row, 2]?.GetValue()!, + Code = workSheet?.Cells[row, 3]?.GetValue()!, + }; + + await service.AddAsync(inserted); + + row++; + } + } + } + } + } +} diff --git a/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj b/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj index 936fd555..24c08814 100644 --- a/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj +++ b/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj @@ -1,4 +1,4 @@ - + net7.0 diff --git a/BMA.EHR.Leave.Service/DTOs/LeaveRequest/CreateLeaveRequestDto.cs b/BMA.EHR.Leave.Service/DTOs/LeaveRequest/CreateLeaveRequestDto.cs new file mode 100644 index 00000000..9bdfbff6 --- /dev/null +++ b/BMA.EHR.Leave.Service/DTOs/LeaveRequest/CreateLeaveRequestDto.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations; + +namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest +{ + public class CreateLeaveRequestDto + { + [Required] + public Guid Type { get; set; } = Guid.Empty; + + [Required] + public DateTime LeaveStartDate { get; set; } = DateTime.Now; + + [Required] + public DateTime LeaveEndDate { get; set; } = DateTime.Now; + + public string? LeaveWrote { get; set; } + + public string? LeaveAddress { get; set; } + + public string? LeaveNumber { get; set; } + + public string? LeaveDetail { get; set; } + + public IFormFile? LeaveDocument { get; set; } + + public IFormFile? LeaveDraftDocument { get; set; } + + public string? LeaveSalaryText { get; set; } + } +} diff --git a/BMA.EHR.Leave.Service/Program.cs b/BMA.EHR.Leave.Service/Program.cs index 8965c224..48611dca 100644 --- a/BMA.EHR.Leave.Service/Program.cs +++ b/BMA.EHR.Leave.Service/Program.cs @@ -170,6 +170,9 @@ var app = builder.Build(); await using var db = scope.ServiceProvider.GetRequiredService(); await db.Database.MigrateAsync(); + // seed default data + await LeaveSeeder.SeedLeaveType(app); + app.Run(); } diff --git a/BMA.EHR.Leave.Service/SeedLeaveData.xlsx b/BMA.EHR.Leave.Service/SeedLeaveData.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..749bc60b202c34464974c62cb452adf6ec807e23 GIT binary patch literal 11085 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 literal 0 HcmV?d00001